From c295e0f8f613136b4f10048c112792ecd1b18596 Mon Sep 17 00:00:00 2001 From: Ximin Luo Date: Sun, 6 Mar 2022 21:55:47 +0000 Subject: [PATCH] New upstream version 1.57.0+dfsg1 --- Cargo.lock | 322 +- Cargo.toml | 11 + RELEASES.md | 124 +- compiler/rustc/Cargo.toml | 2 +- compiler/rustc_apfloat/Cargo.toml | 2 +- compiler/rustc_apfloat/src/ieee.rs | 2 + compiler/rustc_arena/Cargo.toml | 2 +- compiler/rustc_ast/Cargo.toml | 2 +- compiler/rustc_ast/src/ast.rs | 2 + compiler/rustc_ast/src/attr/mod.rs | 2 +- compiler/rustc_ast/src/lib.rs | 12 - compiler/rustc_ast/src/token.rs | 8 + compiler/rustc_ast_lowering/Cargo.toml | 2 +- compiler/rustc_ast_lowering/src/asm.rs | 64 +- compiler/rustc_ast_lowering/src/block.rs | 2 +- compiler/rustc_ast_lowering/src/expr.rs | 59 +- compiler/rustc_ast_lowering/src/item.rs | 275 +- compiler/rustc_ast_lowering/src/lib.rs | 725 +-- compiler/rustc_ast_lowering/src/path.rs | 13 +- compiler/rustc_ast_passes/Cargo.toml | 2 +- .../rustc_ast_passes/src/ast_validation.rs | 69 +- compiler/rustc_ast_passes/src/feature_gate.rs | 7 + compiler/rustc_ast_passes/src/lib.rs | 1 - compiler/rustc_ast_pretty/Cargo.toml | 2 +- compiler/rustc_attr/Cargo.toml | 2 +- compiler/rustc_attr/src/builtin.rs | 8 +- .../{rustc_mir => rustc_borrowck}/Cargo.toml | 21 +- .../src}/borrow_set.rs | 10 +- .../src}/borrowck_errors.rs | 2 +- .../src}/constraint_generation.rs | 2 +- .../src}/constraints/graph.rs | 2 +- .../src}/constraints/mod.rs | 2 +- .../src}/consumers.rs | 8 +- .../src/dataflow.rs} | 119 +- .../src}/def_use.rs | 0 .../src}/diagnostics/bound_region_errors.rs | 121 +- .../src}/diagnostics/conflict_errors.rs | 151 +- .../src}/diagnostics/explain_borrow.rs | 20 +- .../src}/diagnostics/find_use.rs | 2 +- .../src}/diagnostics/mod.rs | 14 +- .../src}/diagnostics/move_errors.rs | 28 +- .../src}/diagnostics/mutability_errors.rs | 9 +- .../src}/diagnostics/outlives_suggestion.rs | 12 +- .../src}/diagnostics/region_errors.rs | 50 +- .../src}/diagnostics/region_name.rs | 2 +- .../src}/diagnostics/var_name.rs | 4 +- .../src}/facts.rs | 11 +- .../src}/invalidation.rs | 11 +- .../mod.rs => rustc_borrowck/src/lib.rs} | 98 +- .../src}/location.rs | 0 .../src}/member_constraints.rs | 2 +- .../src}/nll.rs | 35 +- .../src}/path_utils.rs | 10 +- .../src}/place_ext.rs | 2 +- .../src}/places_conflict.rs | 6 +- .../src}/prefixes.rs | 0 .../src}/region_infer/dump_mir.rs | 2 +- .../src}/region_infer/graphviz.rs | 2 +- .../src}/region_infer/mod.rs | 167 +- .../src}/region_infer/opaque_types.rs | 132 +- .../src}/region_infer/reverse_sccs.rs | 4 +- .../src}/region_infer/values.rs | 20 +- .../src}/renumber.rs | 22 +- .../src}/type_check/canonical.rs | 38 +- .../src}/type_check/constraint_conversion.rs | 5 +- .../src}/type_check/free_region_relations.rs | 13 +- .../src}/type_check/input_output.rs | 18 +- .../src}/type_check/liveness/local_use_map.rs | 4 +- .../src}/type_check/liveness/mod.rs | 8 +- .../src}/type_check/liveness/polonius.rs | 7 +- .../src}/type_check/liveness/trace.rs | 9 +- .../src}/type_check/mod.rs | 179 +- .../src/type_check/relate_tys.rs | 129 + .../src}/universal_regions.rs | 2 +- .../src}/used_muts.rs | 5 +- compiler/rustc_builtin_macros/Cargo.toml | 2 +- compiler/rustc_builtin_macros/src/asm.rs | 14 +- compiler/rustc_builtin_macros/src/cfg_eval.rs | 29 +- .../rustc_builtin_macros/src/concat_idents.rs | 6 +- compiler/rustc_builtin_macros/src/derive.rs | 40 +- .../src/deriving/debug.rs | 20 +- .../src/deriving/generic/mod.rs | 52 +- compiler/rustc_builtin_macros/src/format.rs | 105 +- .../src/format_foreign.rs | 65 +- .../src/format_foreign/printf/tests.rs | 4 +- .../src/format_foreign/shell/tests.rs | 4 +- compiler/rustc_builtin_macros/src/test.rs | 2 +- compiler/rustc_codegen_cranelift/Cargo.lock | 40 +- compiler/rustc_codegen_cranelift/Cargo.toml | 2 +- .../build_sysroot/Cargo.lock | 41 +- .../build_system/prepare.rs | 10 +- compiler/rustc_codegen_cranelift/clean_all.sh | 2 +- .../rustc_codegen_cranelift/docs/usage.md | 2 + .../example/alloc_example.rs | 4 +- .../example/mini_core_hello_world.rs | 2 +- ...able-simd-Disable-unsupported-tests.patch} | 51 +- ...027-sysroot-128bit-atomic-operations.patch | 41 +- .../rustc_codegen_cranelift/rust-toolchain | 2 +- .../scripts/filter_profile.rs | 6 +- .../scripts/test_rustc_tests.sh | 2 +- .../rustc_codegen_cranelift/scripts/tests.sh | 4 +- .../rustc_codegen_cranelift/src/abi/mod.rs | 29 +- .../src/abi/pass_mode.rs | 20 +- .../rustc_codegen_cranelift/src/archive.rs | 139 +- .../rustc_codegen_cranelift/src/backend.rs | 152 - compiler/rustc_codegen_cranelift/src/base.rs | 25 +- .../src/bin/cg_clif.rs | 3 + .../src/bin/cg_clif_build_sysroot.rs | 4 +- .../rustc_codegen_cranelift/src/common.rs | 85 +- .../rustc_codegen_cranelift/src/constant.rs | 4 +- .../src/debuginfo/emit.rs | 6 +- .../src/debuginfo/mod.rs | 1 + .../src/debuginfo/object.rs | 85 + .../src/debuginfo/unwind.rs | 5 +- .../rustc_codegen_cranelift/src/driver/aot.rs | 25 +- .../src/intrinsics/mod.rs | 10 +- compiler/rustc_codegen_cranelift/src/lib.rs | 11 +- .../rustc_codegen_cranelift/src/metadata.rs | 74 +- .../src/pretty_clif.rs | 8 +- .../src/value_and_place.rs | 24 +- .../.github/workflows/main.yml | 96 + compiler/rustc_codegen_gcc/Cargo.lock | 373 ++ compiler/rustc_codegen_gcc/Cargo.toml | 51 + compiler/rustc_codegen_gcc/LICENSE-APACHE | 176 + .../rustc_codegen_gcc}/LICENSE-MIT | 0 compiler/rustc_codegen_gcc/Readme.md | 135 + compiler/rustc_codegen_gcc/build.sh | 31 + .../build_sysroot/Cargo.toml | 19 + .../build_sysroot/build_sysroot.sh | 30 + .../build_sysroot/prepare_sysroot_src.sh | 39 + .../build_sysroot/src/lib.rs | 1 + compiler/rustc_codegen_gcc/cargo.sh | 23 + compiler/rustc_codegen_gcc/clean_all.sh | 5 + compiler/rustc_codegen_gcc/config.sh | 52 + .../example/alloc_example.rs | 41 + .../rustc_codegen_gcc/example/alloc_system.rs | 212 + ...itrary_self_types_pointers_and_wrappers.rs | 69 + .../example/dst-field-align.rs | 67 + compiler/rustc_codegen_gcc/example/example.rs | 208 + .../rustc_codegen_gcc/example/mini_core.rs | 585 ++ .../example/mini_core_hello_world.rs | 424 ++ .../rustc_codegen_gcc/example/mod_bench.rs | 37 + .../rustc_codegen_gcc/example/std_example.rs | 278 + .../example/subslice-patterns-const-eval.rs | 97 + .../example/track-caller-attribute.rs | 40 + ...022-core-Disable-not-compiling-tests.patch | 63 + .../0023-core-Ignore-failing-tests.patch | 49 + compiler/rustc_codegen_gcc/prepare.sh | 22 + compiler/rustc_codegen_gcc/prepare_build.sh | 5 + compiler/rustc_codegen_gcc/rust-toolchain | 1 + compiler/rustc_codegen_gcc/rustup.sh | 29 + compiler/rustc_codegen_gcc/src/abi.rs | 160 + compiler/rustc_codegen_gcc/src/allocator.rs | 116 + compiler/rustc_codegen_gcc/src/archive.rs | 217 + compiler/rustc_codegen_gcc/src/asm.rs | 785 +++ compiler/rustc_codegen_gcc/src/back/mod.rs | 1 + compiler/rustc_codegen_gcc/src/back/write.rs | 78 + compiler/rustc_codegen_gcc/src/base.rs | 165 + compiler/rustc_codegen_gcc/src/builder.rs | 1540 ++++++ compiler/rustc_codegen_gcc/src/callee.rs | 77 + compiler/rustc_codegen_gcc/src/common.rs | 450 ++ compiler/rustc_codegen_gcc/src/consts.rs | 390 ++ compiler/rustc_codegen_gcc/src/context.rs | 475 ++ .../rustc_codegen_gcc/src/coverageinfo.rs | 69 + compiler/rustc_codegen_gcc/src/debuginfo.rs | 62 + compiler/rustc_codegen_gcc/src/declare.rs | 144 + .../rustc_codegen_gcc/src/intrinsic/llvm.rs | 22 + .../rustc_codegen_gcc/src/intrinsic/mod.rs | 1067 ++++ .../rustc_codegen_gcc/src/intrinsic/simd.rs | 167 + compiler/rustc_codegen_gcc/src/lib.rs | 293 + compiler/rustc_codegen_gcc/src/mono_item.rs | 38 + compiler/rustc_codegen_gcc/src/type_.rs | 282 + compiler/rustc_codegen_gcc/src/type_of.rs | 359 ++ compiler/rustc_codegen_gcc/test.sh | 217 + compiler/rustc_codegen_gcc/tests/lib.rs | 50 + .../rustc_codegen_gcc/tests/run/abort1.rs | 51 + .../rustc_codegen_gcc/tests/run/abort2.rs | 53 + compiler/rustc_codegen_gcc/tests/run/array.rs | 229 + compiler/rustc_codegen_gcc/tests/run/asm.rs | 153 + .../rustc_codegen_gcc/tests/run/assign.rs | 153 + .../rustc_codegen_gcc/tests/run/closure.rs | 230 + .../rustc_codegen_gcc/tests/run/condition.rs | 320 ++ .../rustc_codegen_gcc/tests/run/empty_main.rs | 39 + compiler/rustc_codegen_gcc/tests/run/exit.rs | 49 + .../rustc_codegen_gcc/tests/run/exit_code.rs | 39 + .../rustc_codegen_gcc/tests/run/fun_ptr.rs | 223 + .../tests/run/int_overflow.rs | 129 + .../rustc_codegen_gcc/tests/run/mut_ref.rs | 165 + .../rustc_codegen_gcc/tests/run/operations.rs | 221 + .../rustc_codegen_gcc/tests/run/ptr_cast.rs | 222 + .../tests/run/return-tuple.rs | 72 + compiler/rustc_codegen_gcc/tests/run/slice.rs | 128 + .../rustc_codegen_gcc/tests/run/static.rs | 106 + .../rustc_codegen_gcc/tests/run/structs.rs | 70 + compiler/rustc_codegen_gcc/tests/run/tuple.rs | 51 + compiler/rustc_codegen_llvm/Cargo.toml | 4 +- compiler/rustc_codegen_llvm/src/abi.rs | 21 +- compiler/rustc_codegen_llvm/src/allocator.rs | 15 +- compiler/rustc_codegen_llvm/src/asm.rs | 18 +- compiler/rustc_codegen_llvm/src/attributes.rs | 11 +- .../rustc_codegen_llvm/src/back/archive.rs | 110 +- compiler/rustc_codegen_llvm/src/back/lto.rs | 45 +- compiler/rustc_codegen_llvm/src/back/write.rs | 52 +- compiler/rustc_codegen_llvm/src/base.rs | 4 +- compiler/rustc_codegen_llvm/src/builder.rs | 56 +- compiler/rustc_codegen_llvm/src/callee.rs | 12 +- compiler/rustc_codegen_llvm/src/common.rs | 7 +- compiler/rustc_codegen_llvm/src/consts.rs | 23 +- compiler/rustc_codegen_llvm/src/context.rs | 93 +- .../src/coverageinfo/mapgen.rs | 5 +- .../src/coverageinfo/mod.rs | 11 +- .../src/debuginfo/create_scope_map.rs | 9 +- .../rustc_codegen_llvm/src/debuginfo/gdb.rs | 6 +- .../src/debuginfo/metadata.rs | 196 +- .../rustc_codegen_llvm/src/debuginfo/mod.rs | 89 +- compiler/rustc_codegen_llvm/src/intrinsic.rs | 89 +- compiler/rustc_codegen_llvm/src/lib.rs | 22 +- compiler/rustc_codegen_llvm/src/llvm/ffi.rs | 51 +- compiler/rustc_codegen_llvm/src/llvm_util.rs | 92 +- compiler/rustc_codegen_llvm/src/mono_item.rs | 14 +- compiler/rustc_codegen_llvm/src/type_.rs | 2 +- compiler/rustc_codegen_llvm/src/type_of.rs | 35 +- compiler/rustc_codegen_llvm/src/va_arg.rs | 14 +- compiler/rustc_codegen_ssa/Cargo.toml | 4 +- .../rustc_codegen_ssa/src/back/archive.rs | 15 +- compiler/rustc_codegen_ssa/src/back/link.rs | 163 +- compiler/rustc_codegen_ssa/src/back/linker.rs | 6 +- .../rustc_codegen_ssa/src/back/metadata.rs | 2 +- compiler/rustc_codegen_ssa/src/back/write.rs | 6 +- compiler/rustc_codegen_ssa/src/base.rs | 18 +- .../src/debuginfo/type_names.rs | 57 +- compiler/rustc_codegen_ssa/src/lib.rs | 5 +- compiler/rustc_codegen_ssa/src/meth.rs | 2 +- compiler/rustc_codegen_ssa/src/mir/analyze.rs | 3 +- compiler/rustc_codegen_ssa/src/mir/block.rs | 87 +- .../rustc_codegen_ssa/src/mir/constant.rs | 2 +- .../rustc_codegen_ssa/src/mir/debuginfo.rs | 25 +- .../rustc_codegen_ssa/src/mir/intrinsic.rs | 1 - compiler/rustc_codegen_ssa/src/mir/mod.rs | 49 +- compiler/rustc_codegen_ssa/src/mir/operand.rs | 20 +- compiler/rustc_codegen_ssa/src/mir/place.rs | 8 +- compiler/rustc_codegen_ssa/src/mir/rvalue.rs | 57 +- compiler/rustc_codegen_ssa/src/mono_item.rs | 3 +- .../rustc_codegen_ssa/src/traits/backend.rs | 16 +- .../rustc_codegen_ssa/src/traits/builder.rs | 10 +- .../rustc_codegen_ssa/src/traits/consts.rs | 2 +- .../rustc_codegen_ssa/src/traits/debuginfo.rs | 9 +- compiler/rustc_const_eval/Cargo.toml | 26 + .../src/const_eval/error.rs | 0 .../src/const_eval/eval_queries.rs | 14 +- .../src/const_eval/fn_queries.rs | 51 +- .../src/const_eval/machine.rs | 68 +- .../src/const_eval/mod.rs | 0 .../src/interpret/cast.rs | 4 +- .../src/interpret/eval_context.rs | 35 +- .../src/interpret/intern.rs | 2 +- .../src/interpret/intrinsics.rs | 29 +- .../interpret/intrinsics/caller_location.rs | 2 +- .../src/interpret/intrinsics/type_name.rs | 0 .../src/interpret/machine.rs | 0 .../src/interpret/memory.rs | 4 +- .../src/interpret/mod.rs | 0 .../src/interpret/operand.rs | 17 +- .../src/interpret/operator.rs | 4 +- .../src/interpret/place.rs | 25 +- .../src/interpret/step.rs | 38 +- .../src/interpret/terminator.rs | 17 +- .../src/interpret/traits.rs | 0 .../src/interpret/util.rs | 3 +- .../src/interpret/validity.rs | 40 +- .../src/interpret/visitor.rs | 0 .../src/lib.rs | 36 +- .../src/transform/check_consts/check.rs | 62 +- .../src/transform/check_consts/mod.rs | 13 +- .../src/transform/check_consts/ops.rs | 75 +- .../check_consts/post_drop_elaboration.rs | 16 +- .../src/transform/check_consts/qualifs.rs | 59 +- .../src/transform/check_consts/resolver.rs | 5 +- .../rustc_const_eval/src/transform/mod.rs | 5 + .../src/transform/promote_consts.rs | 16 +- .../src/transform/validate.rs | 12 +- .../src/util/aggregate.rs | 0 .../src/util/alignment.rs | 0 .../src/util/collect_writes.rs | 2 +- .../src/util/find_self_call.rs | 0 compiler/rustc_const_eval/src/util/mod.rs | 8 + 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 | 56 +- .../src/graph/iterate/tests.rs | 16 + .../rustc_data_structures/src/graph/mod.rs | 2 +- .../src/graph/scc/mod.rs | 22 +- compiler/rustc_data_structures/src/lib.rs | 8 +- .../src/obligation_forest/mod.rs | 12 +- compiler/rustc_data_structures/src/sharded.rs | 20 +- .../rustc_data_structures/src/sorted_map.rs | 10 +- .../src/sorted_map/index_map.rs | 4 +- compiler/rustc_data_structures/src/sso/map.rs | 18 +- compiler/rustc_data_structures/src/sso/set.rs | 4 +- .../src/stable_hasher.rs | 10 +- compiler/rustc_data_structures/src/stack.rs | 1 + compiler/rustc_data_structures/src/steal.rs | 9 +- .../rustc_data_structures/src/thin_vec.rs | 2 +- .../rustc_data_structures/src/tiny_list.rs | 2 +- .../src/vec_linked_list.rs | 4 +- compiler/rustc_driver/Cargo.toml | 6 +- compiler/rustc_driver/src/lib.rs | 52 +- compiler/rustc_driver/src/pretty.rs | 13 +- compiler/rustc_error_codes/Cargo.toml | 2 +- compiler/rustc_error_codes/src/error_codes.rs | 6 +- .../src/error_codes/E0071.md | 18 +- .../src/error_codes/E0183.md | 39 + .../src/error_codes/E0222.md | 4 +- .../src/error_codes/E0439.md | 4 +- .../src/error_codes/E0464.md | 6 + .../src/error_codes/E0482.md | 73 + compiler/rustc_errors/Cargo.toml | 2 +- compiler/rustc_errors/src/diagnostic.rs | 76 +- .../rustc_errors/src/diagnostic_builder.rs | 15 + compiler/rustc_errors/src/emitter.rs | 22 +- compiler/rustc_errors/src/lib.rs | 13 +- compiler/rustc_expand/Cargo.toml | 2 +- compiler/rustc_expand/src/base.rs | 32 +- compiler/rustc_expand/src/config.rs | 2 +- compiler/rustc_expand/src/expand.rs | 95 +- compiler/rustc_expand/src/lib.rs | 2 - compiler/rustc_expand/src/mbe/quoted.rs | 2 +- compiler/rustc_expand/src/module.rs | 21 +- .../rustc_expand/src/proc_macro_server.rs | 10 +- compiler/rustc_feature/Cargo.toml | 2 +- compiler/rustc_feature/src/accepted.rs | 5 +- compiler/rustc_feature/src/active.rs | 22 +- compiler/rustc_feature/src/builtin_attrs.rs | 9 + compiler/rustc_feature/src/lib.rs | 1 - compiler/rustc_feature/src/removed.rs | 4 +- compiler/rustc_fs_util/Cargo.toml | 2 +- compiler/rustc_graphviz/Cargo.toml | 2 +- compiler/rustc_graphviz/src/lib.rs | 2 +- compiler/rustc_hir/Cargo.toml | 3 +- compiler/rustc_hir/src/arena.rs | 4 +- compiler/rustc_hir/src/def.rs | 5 + compiler/rustc_hir/src/def_path_hash_map.rs | 37 + compiler/rustc_hir/src/definitions.rs | 46 +- compiler/rustc_hir/src/diagnostic_items.rs | 17 + compiler/rustc_hir/src/hir.rs | 108 +- compiler/rustc_hir/src/intravisit.rs | 27 +- compiler/rustc_hir/src/lang_items.rs | 5 +- compiler/rustc_hir/src/lib.rs | 2 + compiler/rustc_hir/src/stable_hash_impls.rs | 19 + compiler/rustc_hir_pretty/Cargo.toml | 2 +- compiler/rustc_hir_pretty/src/lib.rs | 18 +- compiler/rustc_incremental/Cargo.toml | 2 +- .../rustc_incremental/src/assert_dep_graph.rs | 2 +- .../src/persist/dirty_clean.rs | 5 +- .../src/persist/file_format.rs | 78 +- .../rustc_incremental/src/persist/load.rs | 3 +- .../rustc_incremental/src/persist/save.rs | 67 +- compiler/rustc_index/Cargo.toml | 2 +- compiler/rustc_index/src/bit_set.rs | 17 +- compiler/rustc_index/src/lib.rs | 3 +- compiler/rustc_index/src/vec.rs | 101 +- compiler/rustc_infer/Cargo.toml | 2 +- compiler/rustc_infer/src/infer/at.rs | 8 +- .../src/infer/canonical/query_response.rs | 17 +- compiler/rustc_infer/src/infer/combine.rs | 20 +- .../src/infer/error_reporting/mod.rs | 145 +- .../mismatched_static_lifetime.rs | 10 +- .../error_reporting/nice_region_error/mod.rs | 2 + .../nice_region_error/static_impl_trait.rs | 211 +- .../trait_impl_difference.rs | 90 +- .../src/infer/error_reporting/note.rs | 18 + compiler/rustc_infer/src/infer/fudge.rs | 5 +- .../src/infer/higher_ranked/mod.rs | 3 +- compiler/rustc_infer/src/infer/mod.rs | 73 +- .../rustc_infer/src/infer/nll_relate/mod.rs | 38 +- .../src/infer/outlives/components.rs} | 24 +- .../rustc_infer/src/infer/outlives/mod.rs | 1 + .../src/infer/outlives/obligations.rs | 6 +- compiler/rustc_infer/src/infer/projection.rs | 39 + .../src/infer/region_constraints/mod.rs | 6 +- compiler/rustc_infer/src/infer/sub.rs | 4 +- .../rustc_infer/src/infer/type_variable.rs | 46 +- compiler/rustc_infer/src/traits/engine.rs | 5 +- .../src/traits/error_reporting/mod.rs | 12 +- compiler/rustc_infer/src/traits/mod.rs | 6 +- compiler/rustc_infer/src/traits/project.rs | 41 - compiler/rustc_infer/src/traits/util.rs | 5 +- compiler/rustc_interface/Cargo.toml | 7 +- compiler/rustc_interface/src/callbacks.rs | 13 +- compiler/rustc_interface/src/interface.rs | 8 +- compiler/rustc_interface/src/lib.rs | 1 + compiler/rustc_interface/src/passes.rs | 132 +- .../rustc_interface/src/proc_macro_decls.rs | 2 +- compiler/rustc_interface/src/queries.rs | 12 +- compiler/rustc_interface/src/tests.rs | 4 + compiler/rustc_interface/src/util.rs | 43 +- compiler/rustc_lexer/Cargo.toml | 2 +- compiler/rustc_lexer/src/unescape.rs | 11 +- compiler/rustc_lint/Cargo.toml | 2 +- compiler/rustc_lint/src/array_into_iter.rs | 4 +- compiler/rustc_lint/src/builtin.rs | 53 +- compiler/rustc_lint/src/context.rs | 71 +- compiler/rustc_lint/src/early.rs | 24 +- .../src/enum_intrinsics_non_enums.rs | 106 + .../src/hidden_unicode_codepoints.rs | 161 + compiler/rustc_lint/src/internal.rs | 31 +- compiler/rustc_lint/src/late.rs | 17 +- compiler/rustc_lint/src/levels.rs | 8 +- compiler/rustc_lint/src/lib.rs | 7 +- compiler/rustc_lint/src/methods.rs | 2 +- compiler/rustc_lint/src/non_ascii_idents.rs | 7 +- compiler/rustc_lint/src/non_fmt_panic.rs | 18 +- compiler/rustc_lint/src/nonstandard_style.rs | 13 +- compiler/rustc_lint/src/noop_method_call.rs | 7 +- compiler/rustc_lint/src/passes.rs | 4 +- compiler/rustc_lint/src/traits.rs | 5 + compiler/rustc_lint/src/types.rs | 31 +- compiler/rustc_lint/src/unused.rs | 137 +- compiler/rustc_lint_defs/Cargo.toml | 2 +- compiler/rustc_lint_defs/src/builtin.rs | 181 +- compiler/rustc_lint_defs/src/lib.rs | 1 + compiler/rustc_llvm/Cargo.toml | 2 +- compiler/rustc_llvm/build.rs | 1 + .../rustc_llvm/llvm-wrapper/PassWrapper.cpp | 58 +- .../rustc_llvm/llvm-wrapper/RustWrapper.cpp | 71 +- compiler/rustc_llvm/src/lib.rs | 12 + compiler/rustc_macros/Cargo.toml | 2 +- compiler/rustc_macros/src/hash_stable.rs | 12 +- compiler/rustc_macros/src/query.rs | 12 +- .../rustc_macros/src/session_diagnostic.rs | 16 +- compiler/rustc_macros/src/symbols.rs | 2 +- compiler/rustc_metadata/Cargo.toml | 3 +- compiler/rustc_metadata/src/creader.rs | 39 +- .../rustc_metadata/src/dependency_format.rs | 91 +- .../rustc_metadata/src/foreign_modules.rs | 4 +- compiler/rustc_metadata/src/lib.rs | 2 +- compiler/rustc_metadata/src/locator.rs | 197 +- compiler/rustc_metadata/src/native_libs.rs | 22 +- compiler/rustc_metadata/src/rmeta/decoder.rs | 200 +- .../src/rmeta/decoder/cstore_impl.rs | 106 +- .../src/rmeta/def_path_hash_map.rs | 58 + compiler/rustc_metadata/src/rmeta/encoder.rs | 74 +- compiler/rustc_metadata/src/rmeta/mod.rs | 13 +- compiler/rustc_metadata/src/rmeta/table.rs | 2 +- compiler/rustc_middle/Cargo.toml | 7 +- compiler/rustc_middle/src/arena.rs | 7 +- .../rustc_middle/src/dep_graph/dep_node.rs | 94 +- compiler/rustc_middle/src/dep_graph/mod.rs | 16 +- compiler/rustc_middle/src/hir/exports.rs | 13 +- .../rustc_middle/src/hir/map/collector.rs | 17 +- compiler/rustc_middle/src/hir/map/mod.rs | 245 +- compiler/rustc_middle/src/hir/mod.rs | 16 +- compiler/rustc_middle/src/lib.rs | 11 +- compiler/rustc_middle/src/lint.rs | 9 +- .../src/middle/codegen_fn_attrs.rs | 2 +- compiler/rustc_middle/src/middle/mod.rs | 1 - compiler/rustc_middle/src/middle/privacy.rs | 11 + compiler/rustc_middle/src/middle/region.rs | 5 +- compiler/rustc_middle/src/middle/stability.rs | 114 +- .../rustc_middle/src/mir/abstract_const.rs | 38 - .../src/mir}/generic_graph.rs | 0 .../src/mir}/generic_graphviz.rs | 0 .../util => rustc_middle/src/mir}/graphviz.rs | 0 .../src/mir/interpret/allocation.rs | 6 +- .../rustc_middle/src/mir/interpret/error.rs | 5 + .../rustc_middle/src/mir/interpret/pointer.rs | 14 +- compiler/rustc_middle/src/mir/mod.rs | 56 +- compiler/rustc_middle/src/mir/mono.rs | 10 +- .../util => rustc_middle/src/mir}/patch.rs | 0 .../util => rustc_middle/src/mir}/pretty.rs | 4 +- compiler/rustc_middle/src/mir/query.rs | 34 +- .../util => rustc_middle/src/mir}/spanview.rs | 0 compiler/rustc_middle/src/mir/tcx.rs | 7 +- .../rustc_middle/src/mir/type_foldable.rs | 5 + compiler/rustc_middle/src/mir/visit.rs | 7 +- compiler/rustc_middle/src/query/mod.rs | 75 +- compiler/rustc_middle/src/thir.rs | 3 + .../rustc_middle/src/thir/abstract_const.rs | 61 + .../src/thir/visit.rs | 6 +- compiler/rustc_middle/src/traits/mod.rs | 42 +- compiler/rustc_middle/src/traits/query.rs | 2 +- compiler/rustc_middle/src/traits/select.rs | 21 +- .../src/traits/specialization_graph.rs | 18 +- .../src/traits/structural_impls.rs | 3 + compiler/rustc_middle/src/ty/adt.rs | 7 +- compiler/rustc_middle/src/ty/codec.rs | 19 +- compiler/rustc_middle/src/ty/context.rs | 156 +- compiler/rustc_middle/src/ty/diagnostics.rs | 12 +- compiler/rustc_middle/src/ty/error.rs | 2 +- compiler/rustc_middle/src/ty/fast_reject.rs | 2 +- compiler/rustc_middle/src/ty/fold.rs | 36 +- .../rustc_middle/src/{ich => ty}/impls_ty.rs | 41 +- compiler/rustc_middle/src/ty/instance.rs | 76 +- compiler/rustc_middle/src/ty/layout.rs | 580 +- compiler/rustc_middle/src/ty/mod.rs | 117 +- compiler/rustc_middle/src/ty/print/mod.rs | 4 +- compiler/rustc_middle/src/ty/print/pretty.rs | 73 +- compiler/rustc_middle/src/ty/query.rs | 11 +- compiler/rustc_middle/src/ty/relate.rs | 9 + .../rustc_middle/src/ty/structural_impls.rs | 10 +- compiler/rustc_middle/src/ty/sty.rs | 19 +- compiler/rustc_middle/src/ty/trait_def.rs | 16 +- compiler/rustc_middle/src/ty/util.rs | 35 +- .../src/borrow_check/type_check/relate_tys.rs | 134 - compiler/rustc_mir/src/dataflow/mod.rs | 49 - compiler/rustc_mir/src/util/mod.rs | 21 - compiler/rustc_mir_build/Cargo.toml | 2 +- .../src/build/expr/as_operand.rs | 17 +- .../src/build/expr/as_rvalue.rs | 84 +- .../rustc_mir_build/src/build/expr/into.rs | 20 +- .../rustc_mir_build/src/build/matches/mod.rs | 5 +- .../src/build/matches/simplify.rs | 13 +- compiler/rustc_mir_build/src/build/mod.rs | 11 +- compiler/rustc_mir_build/src/build/scope.rs | 4 - .../rustc_mir_build/src/check_unsafety.rs | 2 +- compiler/rustc_mir_build/src/thir/cx/expr.rs | 19 +- compiler/rustc_mir_build/src/thir/cx/mod.rs | 10 + compiler/rustc_mir_build/src/thir/mod.rs | 1 - .../src/thir/pattern/check_match.rs | 264 +- .../src/thir/pattern/const_to_pat.rs | 14 +- .../src/thir/pattern/deconstruct_pat.rs | 1077 ++-- .../src/thir/pattern/usefulness.rs | 720 +-- compiler/rustc_mir_dataflow/Cargo.toml | 23 + .../src}/drop_flag_effects.rs | 14 +- .../src}/elaborate_drops.rs | 2 +- .../src}/framework/cursor.rs | 0 .../src}/framework/direction.rs | 0 .../src}/framework/engine.rs | 2 +- .../src}/framework/fmt.rs | 8 +- .../src}/framework/graphviz.rs | 2 +- .../src}/framework/lattice.rs | 0 .../src}/framework/mod.rs | 5 +- .../src}/framework/tests.rs | 0 .../src}/framework/visitor.rs | 93 - .../src}/impls/borrowed_locals.rs | 5 +- .../src}/impls/init_locals.rs | 6 +- .../src}/impls/liveness.rs | 33 +- .../src}/impls/mod.rs | 41 +- .../src}/impls/storage_liveness.rs | 12 +- compiler/rustc_mir_dataflow/src/lib.rs | 72 + .../src}/move_paths/abs_domain.rs | 0 .../src}/move_paths/builder.rs | 3 +- .../src}/move_paths/mod.rs | 21 +- .../src}/rustc_peek.rs | 18 +- .../src}/storage.rs | 0 compiler/rustc_mir_transform/Cargo.toml | 30 + .../src}/abort_unwinding_calls.rs | 12 +- .../src}/add_call_guards.rs | 2 +- .../src}/add_moves_for_packed_drops.rs | 4 +- .../src}/add_retag.rs | 2 +- .../src}/check_const_item_mutation.rs | 2 +- .../src}/check_packed_ref.rs | 2 +- .../src}/check_unsafety.rs | 0 .../src}/cleanup_post_borrowck.rs | 2 +- .../src}/const_debuginfo.rs | 2 +- .../src}/const_goto.rs | 2 +- .../src}/const_prop.rs | 21 +- .../src}/coverage/counters.rs | 0 .../src}/coverage/debug.rs | 26 +- .../src}/coverage/graph.rs | 0 .../src}/coverage/mod.rs | 10 +- .../src}/coverage/query.rs | 0 .../src}/coverage/spans.rs | 10 +- .../src}/coverage/test_macros/Cargo.toml | 2 +- .../src}/coverage/test_macros/src/lib.rs | 0 .../src}/coverage/tests.rs | 0 .../src}/deaggregator.rs | 2 +- .../src}/deduplicate_blocks.rs | 2 +- .../src}/dest_prop.rs | 11 +- .../src}/dump_mir.rs | 17 +- .../src}/early_otherwise_branch.rs | 4 +- .../src}/elaborate_drops.rs | 42 +- .../src}/function_item_references.rs | 4 +- .../src}/generator.rs | 33 +- .../src}/inline.rs | 4 +- .../src}/inline/cycle.rs | 0 .../src}/instcombine.rs | 2 +- .../mod.rs => rustc_mir_transform/src/lib.rs} | 150 +- .../src}/lower_intrinsics.rs | 11 +- .../src}/lower_slice_len.rs | 10 +- .../src}/match_branches.rs | 4 +- .../src}/multiple_return_terminators.rs | 2 +- .../src/normalize_array_len.rs | 286 + .../src}/nrvo.rs | 2 +- .../src}/remove_noop_landing_pads.rs | 4 +- .../src}/remove_storage_markers.rs | 2 +- .../src}/remove_unneeded_drops.rs | 2 +- .../src}/remove_zsts.rs | 2 +- .../src}/required_consts.rs | 0 .../src}/separate_const_switch.rs | 4 +- .../src/shim.rs | 12 +- .../src}/simplify.rs | 27 +- .../src}/simplify_branches.rs | 2 +- .../src}/simplify_comparison_integral.rs | 0 .../src}/simplify_try.rs | 2 +- .../src}/uninhabited_enum_branching.rs | 2 +- .../src}/unreachable_prop.rs | 4 +- compiler/rustc_monomorphize/Cargo.toml | 19 + .../src}/collector.rs | 32 +- .../mod.rs => rustc_monomorphize/src/lib.rs} | 31 +- .../src}/partitioning/default.rs | 31 +- .../src}/partitioning/merging.rs | 2 +- .../src}/partitioning/mod.rs | 4 +- .../src}/polymorphize.rs | 143 +- .../src}/util.rs | 0 compiler/rustc_parse/Cargo.toml | 3 +- compiler/rustc_parse/src/lexer/mod.rs | 40 +- .../src/lexer/unescape_error_reporting.rs | 81 +- compiler/rustc_parse/src/lib.rs | 7 +- compiler/rustc_parse/src/parser/attr.rs | 140 +- .../rustc_parse/src/parser/attr_wrapper.rs | 2 +- .../rustc_parse/src/parser/diagnostics.rs | 134 +- compiler/rustc_parse/src/parser/expr.rs | 245 +- compiler/rustc_parse/src/parser/item.rs | 29 +- compiler/rustc_parse/src/parser/mod.rs | 103 +- compiler/rustc_parse/src/parser/path.rs | 37 +- compiler/rustc_parse/src/parser/stmt.rs | 25 +- compiler/rustc_parse/src/validate_attr.rs | 133 +- compiler/rustc_parse_format/Cargo.toml | 2 +- compiler/rustc_passes/Cargo.toml | 2 +- compiler/rustc_passes/src/check_attr.rs | 62 +- compiler/rustc_passes/src/check_const.rs | 42 +- compiler/rustc_passes/src/dead.rs | 49 +- compiler/rustc_passes/src/diagnostic_items.rs | 36 +- compiler/rustc_passes/src/entry.rs | 6 +- compiler/rustc_passes/src/hir_id_validator.rs | 14 +- compiler/rustc_passes/src/hir_stats.rs | 10 +- compiler/rustc_passes/src/intrinsicck.rs | 136 +- compiler/rustc_passes/src/lang_items.rs | 7 +- compiler/rustc_passes/src/layout_test.rs | 21 +- compiler/rustc_passes/src/lib.rs | 3 +- compiler/rustc_passes/src/lib_features.rs | 6 +- compiler/rustc_passes/src/liveness.rs | 27 +- compiler/rustc_passes/src/reachable.rs | 2 +- compiler/rustc_passes/src/region.rs | 2 +- compiler/rustc_passes/src/stability.rs | 23 +- compiler/rustc_passes/src/weak_lang_items.rs | 6 +- compiler/rustc_plugin_impl/Cargo.toml | 2 +- compiler/rustc_plugin_impl/src/load.rs | 2 +- compiler/rustc_privacy/Cargo.toml | 2 +- compiler/rustc_privacy/src/lib.rs | 55 +- compiler/rustc_query_impl/Cargo.toml | 2 +- compiler/rustc_query_impl/src/keys.rs | 32 + compiler/rustc_query_impl/src/lib.rs | 2 +- .../rustc_query_impl/src/on_disk_cache.rs | 345 +- compiler/rustc_query_impl/src/plumbing.rs | 41 +- compiler/rustc_query_impl/src/stats.rs | 27 - compiler/rustc_query_system/Cargo.toml | 8 +- .../src/dep_graph/dep_node.rs | 28 +- .../rustc_query_system/src/dep_graph/graph.rs | 201 +- .../rustc_query_system/src/dep_graph/mod.rs | 36 +- .../src/dep_graph/serialized.rs | 4 +- .../src/ich/hcx.rs | 88 +- .../src/ich/impls_hir.rs | 46 +- .../src/ich/impls_syntax.rs | 0 .../src/ich/mod.rs | 6 +- compiler/rustc_query_system/src/lib.rs | 2 + .../rustc_query_system/src/query/config.rs | 11 +- compiler/rustc_query_system/src/query/job.rs | 2 + .../rustc_query_system/src/query/plumbing.rs | 508 +- compiler/rustc_resolve/Cargo.toml | 2 +- .../rustc_resolve/src/build_reduced_graph.rs | 243 +- compiler/rustc_resolve/src/def_collector.rs | 8 +- compiler/rustc_resolve/src/diagnostics.rs | 198 +- compiler/rustc_resolve/src/imports.rs | 28 +- compiler/rustc_resolve/src/late.rs | 41 +- .../rustc_resolve/src/late/diagnostics.rs | 66 +- compiler/rustc_resolve/src/late/lifetimes.rs | 35 +- compiler/rustc_resolve/src/lib.rs | 222 +- compiler/rustc_resolve/src/macros.rs | 54 +- compiler/rustc_save_analysis/Cargo.toml | 2 +- .../rustc_save_analysis/src/dump_visitor.rs | 15 +- compiler/rustc_save_analysis/src/lib.rs | 7 +- compiler/rustc_serialize/Cargo.toml | 2 +- compiler/rustc_serialize/src/serialize.rs | 16 +- compiler/rustc_session/Cargo.toml | 3 +- compiler/rustc_session/src/config.rs | 24 +- .../middle => rustc_session/src}/cstore.rs | 54 +- compiler/rustc_session/src/filesearch.rs | 22 +- compiler/rustc_session/src/lib.rs | 4 +- compiler/rustc_session/src/options.rs | 26 +- compiler/rustc_session/src/search_paths.rs | 22 +- compiler/rustc_session/src/session.rs | 73 +- compiler/rustc_span/Cargo.toml | 2 +- .../rustc_span/src/caching_source_map_view.rs | 14 +- compiler/rustc_span/src/hygiene.rs | 11 +- compiler/rustc_span/src/lib.rs | 127 +- compiler/rustc_span/src/source_map.rs | 45 +- compiler/rustc_span/src/span_encoding.rs | 30 +- compiler/rustc_span/src/symbol.rs | 87 +- compiler/rustc_span/src/symbol/tests.rs | 2 +- compiler/rustc_symbol_mangling/Cargo.toml | 3 +- compiler/rustc_symbol_mangling/src/legacy.rs | 2 +- compiler/rustc_symbol_mangling/src/test.rs | 2 +- compiler/rustc_target/Cargo.toml | 2 +- compiler/rustc_target/src/abi/call/m68k.rs | 30 + compiler/rustc_target/src/abi/call/mips64.rs | 6 +- compiler/rustc_target/src/abi/call/mod.rs | 60 +- compiler/rustc_target/src/abi/call/riscv.rs | 4 +- compiler/rustc_target/src/abi/call/s390x.rs | 2 +- compiler/rustc_target/src/abi/call/x86.rs | 2 +- compiler/rustc_target/src/abi/call/x86_64.rs | 2 +- compiler/rustc_target/src/abi/mod.rs | 204 +- compiler/rustc_target/src/lib.rs | 1 - .../src/spec/aarch64_apple_darwin.rs | 4 +- .../src/spec/aarch64_kmc_solid_asp3.rs | 19 + .../rustc_target/src/spec/android_base.rs | 2 +- .../src/spec/armv6k_nintendo_3ds.rs | 43 + .../spec/armv7_unknown_linux_uclibceabihf.rs | 24 + .../src/spec/armv7a_kmc_solid_asp3_eabi.rs | 19 + .../src/spec/armv7a_kmc_solid_asp3_eabihf.rs | 19 + .../src/spec/m68k_unknown_linux_gnu.rs | 15 + compiler/rustc_target/src/spec/mod.rs | 13 + compiler/rustc_target/src/spec/solid_base.rs | 12 + compiler/rustc_trait_selection/Cargo.toml | 4 +- .../rustc_trait_selection/src/autoderef.rs | 12 +- compiler/rustc_trait_selection/src/infer.rs | 50 +- .../rustc_trait_selection/src/opaque_types.rs | 84 +- .../src/traits/chalk_fulfill.rs | 18 +- .../src/traits/const_evaluatable.rs | 490 +- .../src/traits/error_reporting/mod.rs | 49 +- .../error_reporting/on_unimplemented.rs | 3 - .../src/traits/error_reporting/suggestions.rs | 262 +- .../src/traits/fulfill.rs | 18 +- .../rustc_trait_selection/src/traits/mod.rs | 68 +- .../src/traits/object_safety.rs | 31 +- .../src/traits/project.rs | 32 +- .../src/traits/query/evaluate_obligation.rs | 20 +- .../src/traits/query/mod.rs | 1 - .../query/type_op/implied_outlives_bounds.rs | 2 +- .../src/traits/relationships.rs | 69 + .../src/traits/select/candidate_assembly.rs | 220 +- .../src/traits/select/confirmation.rs | 19 +- .../src/traits/select/mod.rs | 138 +- .../traits/specialize/specialization_graph.rs | 36 +- .../rustc_trait_selection/src/traits/util.rs | 42 +- .../rustc_trait_selection/src/traits/wf.rs | 30 +- compiler/rustc_traits/Cargo.toml | 2 +- compiler/rustc_traits/src/chalk/lowering.rs | 2 +- .../src/implied_outlives_bounds.rs | 6 +- compiler/rustc_traits/src/lib.rs | 2 +- compiler/rustc_traits/src/type_op.rs | 16 +- compiler/rustc_ty_utils/Cargo.toml | 2 +- compiler/rustc_ty_utils/src/instance.rs | 3 +- compiler/rustc_ty_utils/src/lib.rs | 2 - compiler/rustc_ty_utils/src/needs_drop.rs | 101 +- compiler/rustc_ty_utils/src/ty.rs | 14 +- compiler/rustc_type_ir/Cargo.toml | 2 +- compiler/rustc_type_ir/src/lib.rs | 22 +- compiler/rustc_typeck/Cargo.toml | 2 +- compiler/rustc_typeck/src/astconv/errors.rs | 4 +- compiler/rustc_typeck/src/astconv/generics.rs | 27 +- compiler/rustc_typeck/src/astconv/mod.rs | 387 +- compiler/rustc_typeck/src/check/_match.rs | 15 +- compiler/rustc_typeck/src/check/callee.rs | 38 +- compiler/rustc_typeck/src/check/cast.rs | 55 +- compiler/rustc_typeck/src/check/check.rs | 45 +- compiler/rustc_typeck/src/check/closure.rs | 38 +- compiler/rustc_typeck/src/check/coercion.rs | 96 +- .../rustc_typeck/src/check/compare_method.rs | 20 +- compiler/rustc_typeck/src/check/demand.rs | 127 +- compiler/rustc_typeck/src/check/dropck.rs | 8 +- compiler/rustc_typeck/src/check/expr.rs | 120 +- compiler/rustc_typeck/src/check/fallback.rs | 372 +- .../rustc_typeck/src/check/fn_ctxt/_impl.rs | 96 +- .../rustc_typeck/src/check/fn_ctxt/checks.rs | 77 +- .../src/check/fn_ctxt/suggestions.rs | 102 +- .../src/check/generator_interior.rs | 226 +- compiler/rustc_typeck/src/check/inherited.rs | 7 + compiler/rustc_typeck/src/check/intrinsic.rs | 9 +- .../rustc_typeck/src/check/method/confirm.rs | 8 +- compiler/rustc_typeck/src/check/method/mod.rs | 79 +- .../rustc_typeck/src/check/method/probe.rs | 64 +- .../rustc_typeck/src/check/method/suggest.rs | 376 +- compiler/rustc_typeck/src/check/mod.rs | 36 +- compiler/rustc_typeck/src/check/op.rs | 139 +- compiler/rustc_typeck/src/check/pat.rs | 197 +- compiler/rustc_typeck/src/check/place_op.rs | 63 +- compiler/rustc_typeck/src/check/regionck.rs | 93 +- compiler/rustc_typeck/src/check/upvar.rs | 304 +- compiler/rustc_typeck/src/check/wfcheck.rs | 333 +- compiler/rustc_typeck/src/check/writeback.rs | 51 +- compiler/rustc_typeck/src/check_unused.rs | 8 +- .../src/coherence/inherent_impls.rs | 9 +- .../src/coherence/inherent_impls_overlap.rs | 107 +- compiler/rustc_typeck/src/coherence/mod.rs | 2 +- compiler/rustc_typeck/src/coherence/orphan.rs | 2 +- .../rustc_typeck/src/coherence/unsafety.rs | 2 +- compiler/rustc_typeck/src/collect.rs | 288 +- .../rustc_typeck/src/collect/item_bounds.rs | 30 +- compiler/rustc_typeck/src/collect/type_of.rs | 96 +- .../src/constrained_generic_params.rs | 2 +- compiler/rustc_typeck/src/errors.rs | 8 - compiler/rustc_typeck/src/expr_use_visitor.rs | 98 +- compiler/rustc_typeck/src/hir_wf_check.rs | 3 +- compiler/rustc_typeck/src/impl_wf_check.rs | 8 +- .../src/impl_wf_check/min_specialization.rs | 48 +- compiler/rustc_typeck/src/lib.rs | 43 +- .../rustc_typeck/src/mem_categorization.rs | 38 +- .../rustc_typeck/src/outlives/explicit.rs | 8 +- .../src/outlives/implicit_infer.rs | 2 +- compiler/rustc_typeck/src/outlives/mod.rs | 13 +- .../src/outlives}/outlives_bounds.rs | 8 +- compiler/rustc_typeck/src/outlives/test.rs | 2 +- compiler/rustc_typeck/src/outlives/utils.rs | 4 +- .../wrong_number_of_generic_args.rs | 41 +- .../rustc_typeck/src/variance/constraints.rs | 4 +- compiler/rustc_typeck/src/variance/terms.rs | 2 +- compiler/rustc_typeck/src/variance/test.rs | 2 +- config.toml.example | 26 +- git-commit-hash | 2 +- library/alloc/benches/btree/map.rs | 50 + library/alloc/benches/vec.rs | 15 + library/alloc/benches/vec_deque.rs | 15 + library/alloc/src/alloc.rs | 1 - library/alloc/src/borrow.rs | 6 +- library/alloc/src/boxed.rs | 55 + library/alloc/src/collections/binary_heap.rs | 26 +- .../collections/btree/dedup_sorted_iter.rs | 47 + library/alloc/src/collections/btree/map.rs | 53 +- .../alloc/src/collections/btree/map/entry.rs | 1 + .../alloc/src/collections/btree/map/tests.rs | 77 +- library/alloc/src/collections/btree/mod.rs | 1 + .../alloc/src/collections/btree/navigate.rs | 6 +- library/alloc/src/collections/btree/node.rs | 4 +- library/alloc/src/collections/btree/set.rs | 34 +- .../collections/btree/testing/crash_test.rs | 2 +- library/alloc/src/collections/linked_list.rs | 20 +- library/alloc/src/collections/mod.rs | 4 +- .../alloc/src/collections/vec_deque/drain.rs | 19 +- .../src/collections/vec_deque/into_iter.rs | 11 +- .../src/collections/vec_deque/iter_mut.rs | 19 +- .../alloc/src/collections/vec_deque/mod.rs | 98 +- .../src/collections/vec_deque/pair_slices.rs | 8 +- .../alloc/src/collections/vec_deque/tests.rs | 30 + library/alloc/src/fmt.rs | 28 +- library/alloc/src/lib.rs | 18 +- library/alloc/src/prelude/mod.rs | 15 - library/alloc/src/prelude/v1.rs | 14 - library/alloc/src/raw_vec.rs | 5 +- library/alloc/src/rc.rs | 26 +- library/alloc/src/slice.rs | 4 + library/alloc/src/str.rs | 7 + library/alloc/src/string.rs | 68 +- library/alloc/src/sync.rs | 41 +- library/alloc/src/vec/drain.rs | 1 + library/alloc/src/vec/into_iter.rs | 59 +- library/alloc/src/vec/mod.rs | 78 +- library/alloc/src/vec/source_iter_marker.rs | 16 +- library/alloc/tests/btree_set_hash.rs | 14 +- library/alloc/tests/lib.rs | 3 +- library/alloc/tests/vec.rs | 18 + library/backtrace/src/symbolize/gimli.rs | 1 + library/core/benches/lib.rs | 2 + library/core/benches/num/int_log/mod.rs | 58 + library/core/benches/num/mod.rs | 1 + library/core/benches/str.rs | 33 + library/core/primitive_docs/box_into_raw.md | 1 + library/core/primitive_docs/fs_file.md | 1 + library/core/primitive_docs/io_bufread.md | 1 + library/core/primitive_docs/io_read.md | 1 + library/core/primitive_docs/io_seek.md | 1 + library/core/primitive_docs/io_write.md | 1 + .../core/primitive_docs/net_tosocketaddrs.md | 1 + library/core/primitive_docs/process_exit.md | 1 + library/core/primitive_docs/string_string.md | 1 + library/core/src/alloc/layout.rs | 8 + library/core/src/array/iter.rs | 21 +- library/core/src/array/mod.rs | 128 +- library/core/src/ascii.rs | 10 +- library/core/src/bool.rs | 6 +- library/core/src/cell.rs | 15 +- library/core/src/char/convert.rs | 3 + library/core/src/char/methods.rs | 60 +- library/core/src/clone.rs | 1 + library/core/src/cmp.rs | 5 + library/core/src/convert/mod.rs | 12 +- library/core/src/fmt/mod.rs | 79 +- library/core/src/fmt/num.rs | 3 +- library/core/src/hash/mod.rs | 13 + library/core/src/hash/sip.rs | 2 + library/core/src/hint.rs | 18 +- library/core/src/intrinsics.rs | 74 +- library/core/src/iter/adapters/copied.rs | 10 + library/core/src/iter/adapters/cycle.rs | 21 + library/core/src/iter/adapters/enumerate.rs | 30 +- library/core/src/iter/adapters/filter.rs | 9 +- library/core/src/iter/adapters/filter_map.rs | 9 +- library/core/src/iter/adapters/flatten.rs | 70 + library/core/src/iter/adapters/inspect.rs | 9 +- library/core/src/iter/adapters/map.rs | 9 +- library/core/src/iter/adapters/map_while.rs | 15 +- library/core/src/iter/adapters/mod.rs | 13 +- library/core/src/iter/adapters/peekable.rs | 8 +- library/core/src/iter/adapters/scan.rs | 9 +- library/core/src/iter/adapters/skip.rs | 50 +- library/core/src/iter/adapters/skip_while.rs | 9 +- library/core/src/iter/adapters/take.rs | 42 +- library/core/src/iter/adapters/take_while.rs | 9 +- library/core/src/iter/adapters/zip.rs | 10 +- library/core/src/iter/mod.rs | 4 +- library/core/src/iter/range.rs | 89 + library/core/src/iter/traits/double_ended.rs | 8 +- library/core/src/iter/traits/iterator.rs | 31 +- library/core/src/lazy.rs | 12 +- library/core/src/lib.rs | 39 +- library/core/src/macros/mod.rs | 11 - library/core/src/marker.rs | 24 +- library/core/src/mem/manually_drop.rs | 6 +- library/core/src/mem/maybe_uninit.rs | 4 + library/core/src/mem/mod.rs | 1 + library/core/src/num/f32.rs | 25 + library/core/src/num/f64.rs | 27 + library/core/src/num/fmt.rs | 4 +- library/core/src/num/int_log10.rs | 123 +- library/core/src/num/int_macros.rs | 373 +- library/core/src/num/mod.rs | 57 +- library/core/src/num/nonzero.rs | 41 +- library/core/src/num/saturating.rs | 36 +- library/core/src/num/uint_macros.rs | 245 +- library/core/src/num/wrapping.rs | 40 +- library/core/src/ops/bit.rs | 1 + library/core/src/ops/deref.rs | 6 +- library/core/src/option.rs | 107 +- library/core/src/panic.rs | 9 + library/core/src/panicking.rs | 20 +- library/core/src/pin.rs | 11 +- library/core/src/primitive_docs.rs | 1307 +++++ library/core/src/ptr/non_null.rs | 13 + library/core/src/ptr/unique.rs | 4 + library/core/src/result.rs | 21 +- library/core/src/slice/ascii.rs | 2 + library/core/src/slice/iter.rs | 6 + library/core/src/slice/mod.rs | 74 +- library/core/src/slice/sort.rs | 25 +- library/core/src/str/converts.rs | 3 +- library/core/src/str/iter.rs | 4 + library/core/src/str/lossy.rs | 2 + library/core/src/str/mod.rs | 34 +- library/core/src/str/traits.rs | 2 +- library/core/src/str/validations.rs | 12 +- library/core/src/stream/stream/mod.rs | 4 +- library/core/src/sync/atomic.rs | 4 +- library/core/src/task/mod.rs | 2 + library/core/src/task/poll.rs | 38 +- library/core/src/task/ready.rs | 57 + library/core/src/task/wake.rs | 3 + library/core/src/time.rs | 132 +- library/core/src/unicode/printable.rs | 243 +- library/core/src/unicode/unicode_data.rs | 963 ++-- library/core/tests/array.rs | 84 +- library/core/tests/fmt/builders.rs | 1 + library/core/tests/fmt/num.rs | 1 + library/core/tests/iter/adapters/flatten.rs | 17 + library/core/tests/iter/range.rs | 23 + library/core/tests/lib.rs | 3 +- library/core/tests/num/int_log.rs | 25 +- library/core/tests/option.rs | 21 + library/core/tests/slice.rs | 39 + library/core/tests/time.rs | 28 + library/panic_abort/src/lib.rs | 1 + library/panic_unwind/src/lib.rs | 1 + library/proc_macro/src/bridge/mod.rs | 2 + library/proc_macro/src/lib.rs | 14 +- library/std/Cargo.toml | 3 +- library/std/build.rs | 1 + library/std/primitive_docs/box_into_raw.md | 1 + library/std/primitive_docs/fs_file.md | 1 + library/std/primitive_docs/io_bufread.md | 1 + library/std/primitive_docs/io_read.md | 1 + library/std/primitive_docs/io_seek.md | 1 + library/std/primitive_docs/io_write.md | 1 + .../std/primitive_docs/net_tosocketaddrs.md | 1 + library/std/primitive_docs/process_exit.md | 1 + library/std/primitive_docs/string_string.md | 1 + library/std/src/collections/hash/map.rs | 17 +- library/std/src/collections/hash/set.rs | 10 +- library/std/src/collections/mod.rs | 26 +- library/std/src/env.rs | 1 + library/std/src/error.rs | 9 +- library/std/src/ffi/c_str.rs | 93 +- library/std/src/ffi/mod.rs | 52 +- library/std/src/ffi/os_str.rs | 48 +- library/std/src/fs.rs | 75 +- library/std/src/io/buffered/bufreader.rs | 64 +- library/std/src/io/buffered/bufwriter.rs | 3 +- library/std/src/io/buffered/tests.rs | 26 +- library/std/src/io/cursor.rs | 15 +- library/std/src/io/error.rs | 2 + library/std/src/io/mod.rs | 146 +- library/std/src/io/stdio.rs | 4 + library/std/src/io/tests.rs | 20 +- library/std/src/io/util.rs | 2 +- library/std/src/keyword_docs.rs | 4 +- library/std/src/lazy.rs | 1 + library/std/src/lib.rs | 30 +- library/std/src/net/addr.rs | 22 +- library/std/src/net/ip.rs | 95 +- library/std/src/net/ip/tests.rs | 89 +- library/std/src/net/mod.rs | 6 +- library/std/src/net/tcp.rs | 52 + library/std/src/os/linux/fs.rs | 4 +- library/std/src/os/linux/process.rs | 4 +- library/std/src/os/linux/raw.rs | 1 + library/std/src/os/mod.rs | 215 +- library/std/src/os/raw/char.md | 2 +- library/std/src/os/raw/mod.rs | 6 + library/std/src/os/solid/ffi.rs | 41 + library/std/src/os/solid/io.rs | 113 + library/std/src/os/solid/mod.rs | 17 + library/std/src/os/unix/ffi/mod.rs | 4 +- library/std/src/os/unix/fs.rs | 74 +- library/std/src/os/unix/mod.rs | 7 +- library/std/src/os/unix/net/addr.rs | 90 +- library/std/src/os/unix/net/ancillary.rs | 1 + library/std/src/os/unix/net/datagram.rs | 108 +- library/std/src/os/unix/net/listener.rs | 38 + library/std/src/os/unix/net/mod.rs | 2 +- library/std/src/os/unix/net/stream.rs | 37 + library/std/src/os/unix/net/tests.rs | 149 +- library/std/src/os/unix/process.rs | 4 +- library/std/src/os/unix/thread.rs | 4 +- library/std/src/os/wasi/ffi.rs | 4 +- library/std/src/os/wasi/fs.rs | 4 +- library/std/src/os/wasi/mod.rs | 3 + library/std/src/os/windows/ffi.rs | 3 +- library/std/src/os/windows/fs.rs | 26 +- library/std/src/os/windows/io/handle.rs | 135 +- library/std/src/os/windows/mod.rs | 16 + library/std/src/os/windows/process.rs | 4 +- library/std/src/os/windows/raw.rs | 2 + library/std/src/os/windows/thread.rs | 4 +- library/std/src/panic.rs | 6 +- library/std/src/panicking.rs | 2 +- library/std/src/path.rs | 84 +- library/std/src/path/tests.rs | 10 + library/std/src/primitive_docs.rs | 70 +- library/std/src/process.rs | 22 +- library/std/src/rt.rs | 95 +- library/std/src/sync/barrier.rs | 2 + library/std/src/sync/condvar.rs | 1 + library/std/src/sync/mpsc/shared.rs | 6 +- library/std/src/sync/mutex.rs | 8 +- library/std/src/sync/once.rs | 1 + library/std/src/sync/rwlock.rs | 12 + library/std/src/sys/hermit/thread.rs | 2 +- library/std/src/sys/itron/abi.rs | 155 + library/std/src/sys/itron/condvar.rs | 294 + library/std/src/sys/itron/error.rs | 159 + library/std/src/sys/itron/mutex.rs | 183 + library/std/src/sys/itron/spin.rs | 164 + library/std/src/sys/itron/task.rs | 44 + library/std/src/sys/itron/thread.rs | 352 ++ library/std/src/sys/itron/time.rs | 123 + library/std/src/sys/itron/time/tests.rs | 33 + library/std/src/sys/mod.rs | 3 + library/std/src/sys/sgx/thread.rs | 2 +- library/std/src/sys/solid/abi/fs.rs | 53 + library/std/src/sys/solid/abi/mod.rs | 92 + library/std/src/sys/solid/abi/sockets.rs | 274 + library/std/src/sys/solid/alloc.rs | 32 + library/std/src/sys/solid/env.rs | 9 + library/std/src/sys/solid/error.rs | 55 + library/std/src/sys/solid/fs.rs | 529 ++ library/std/src/sys/solid/io.rs | 77 + library/std/src/sys/solid/memchr.rs | 21 + library/std/src/sys/solid/mod.rs | 96 + library/std/src/sys/solid/net.rs | 469 ++ library/std/src/sys/solid/os.rs | 200 + library/std/src/sys/solid/path.rs | 19 + library/std/src/sys/solid/rwlock.rs | 92 + library/std/src/sys/solid/stdio.rs | 80 + .../std/src/sys/solid/thread_local_dtor.rs | 50 + library/std/src/sys/solid/thread_local_key.rs | 26 + library/std/src/sys/solid/time.rs | 56 + library/std/src/sys/unix/fs.rs | 17 + library/std/src/sys/unix/mod.rs | 5 +- library/std/src/sys/unix/os.rs | 30 +- .../src/sys/unix/process/process_common.rs | 8 +- .../std/src/sys/unix/process/process_unix.rs | 46 +- library/std/src/sys/unix/process/zircon.rs | 11 +- library/std/src/sys/unix/stack_overflow.rs | 17 +- library/std/src/sys/unix/thread.rs | 20 +- library/std/src/sys/unix/time.rs | 1 + library/std/src/sys/unsupported/thread.rs | 2 +- library/std/src/sys/wasi/thread.rs | 2 +- library/std/src/sys/wasm/atomics/thread.rs | 2 +- library/std/src/sys/windows/c.rs | 29 +- library/std/src/sys/windows/fs.rs | 4 +- library/std/src/sys/windows/net.rs | 17 +- library/std/src/sys/windows/rand.rs | 12 - library/std/src/sys/windows/stack_overflow.rs | 8 +- library/std/src/sys/windows/stdio.rs | 28 +- library/std/src/sys/windows/thread.rs | 2 +- library/std/src/sys_common/backtrace.rs | 6 +- library/std/src/sys_common/mod.rs | 2 - library/std/src/sys_common/process.rs | 6 +- library/std/src/sys_common/rt.rs | 81 - library/std/src/sys_common/thread_info.rs | 27 +- library/std/src/thread/mod.rs | 98 +- library/std/src/time.rs | 23 +- library/std/src/time/monotonic.rs | 61 +- library/stdarch/.github/workflows/main.yml | 5 +- library/stdarch/Cargo.toml | 1 + .../aarch64-unknown-linux-gnu/Dockerfile | 6 +- library/stdarch/ci/run-docker.sh | 4 +- library/stdarch/ci/run.sh | 16 +- .../crates/assert-instr-macro/src/lib.rs | 68 +- .../crates/core_arch/src/aarch64/crc.rs | 2 +- .../core_arch/src/aarch64/neon/generated.rs | 776 ++- .../crates/core_arch/src/aarch64/neon/mod.rs | 512 +- .../crates/core_arch/src/aarch64/prefetch.rs | 2 +- .../crates/core_arch/src/aarch64/tme.rs | 2 +- .../stdarch/crates/core_arch/src/arm/dsp.rs | 2 +- .../stdarch/crates/core_arch/src/arm/ex.rs | 14 +- .../stdarch/crates/core_arch/src/arm/mod.rs | 2 +- .../stdarch/crates/core_arch/src/arm/neon.rs | 62 +- .../crates/core_arch/src/arm/simd32.rs | 2 +- .../core_arch/src/arm_shared/barrier/mod.rs | 2 +- .../crates/core_arch/src/arm_shared/crc.rs | 2 +- .../crates/core_arch/src/arm_shared/crypto.rs | 2 +- .../crates/core_arch/src/arm_shared/hints.rs | 2 +- .../src/arm_shared/neon/generated.rs | 4812 ++++++++++++++--- .../src/arm_shared/neon/load_tests.rs | 34 +- .../core_arch/src/arm_shared/neon/mod.rs | 512 +- .../crates/core_arch/src/powerpc/vsx.rs | 2 +- .../crates/core_arch/src/x86/avx512bw.rs | 23 +- .../crates/core_arch/src/x86_64/avx512f.rs | 4 +- .../stdarch/crates/intrinsic-test/Cargo.toml | 16 + .../stdarch/crates/intrinsic-test/README.md | 24 + .../crates/intrinsic-test/neon-intrinsics.csv | 4356 +++++++++++++++ .../crates/intrinsic-test/src/argument.rs | 137 + .../crates/intrinsic-test/src/intrinsic.rs | 112 + .../stdarch/crates/intrinsic-test/src/main.rs | 400 ++ .../crates/intrinsic-test/src/types.rs | 483 ++ .../crates/intrinsic-test/src/values.rs | 126 + .../std_detect/src/detect/os/linux/auxvec.rs | 6 +- library/stdarch/crates/stdarch-gen/neon.spec | 380 +- .../stdarch/crates/stdarch-gen/src/main.rs | 1651 +++--- .../crates/stdarch-test/src/disassembly.rs | 55 +- .../stdarch/crates/stdarch-test/src/lib.rs | 52 +- .../stdarch/crates/stdarch-verify/src/lib.rs | 69 +- .../crates/stdarch-verify/tests/arm.rs | 83 +- library/test/Cargo.toml | 1 + library/test/src/cli.rs | 74 + library/test/src/console.rs | 4 +- library/test/src/event.rs | 2 +- library/test/src/formatters/json.rs | 11 +- library/test/src/formatters/junit.rs | 13 +- library/test/src/formatters/mod.rs | 2 +- library/test/src/formatters/pretty.rs | 9 +- library/test/src/formatters/terse.rs | 9 +- library/test/src/helpers/concurrency.rs | 2 +- library/test/src/helpers/mod.rs | 1 + library/test/src/helpers/shuffle.rs | 67 + library/test/src/lib.rs | 13 +- library/test/src/term/terminfo/mod.rs | 1 + library/test/src/tests.rs | 119 +- library/unwind/src/lib.rs | 5 +- src/bootstrap/Cargo.toml | 2 +- src/bootstrap/bootstrap.py | 191 +- src/bootstrap/bootstrap_test.py | 29 +- src/bootstrap/builder.rs | 26 +- src/bootstrap/check.rs | 31 +- src/bootstrap/compile.rs | 14 +- src/bootstrap/config.rs | 17 +- src/bootstrap/configure.py | 2 + src/bootstrap/defaults/config.library.toml | 3 +- src/bootstrap/doc.rs | 98 +- src/bootstrap/lib.rs | 11 +- src/bootstrap/native.rs | 7 +- src/bootstrap/run.rs | 21 + src/bootstrap/sanity.rs | 12 +- src/bootstrap/setup.rs | 80 + src/bootstrap/test.rs | 18 +- src/bootstrap/tool.rs | 1 + src/build_helper/Cargo.toml | 2 +- .../disabled/dist-m68k-linux/Dockerfile | 26 + .../host-x86_64/dist-i686-linux/Dockerfile | 27 +- .../dist-various-2/build-wasi-toolchain.sh | 2 +- .../host-x86_64/dist-x86_64-linux/Dockerfile | 27 +- .../dist-x86_64-linux/build-curl.sh | 13 +- .../dist-x86_64-linux/build-openssl.sh | 13 +- .../download-openssl-curl.sh | 10 + .../host-x86_64/shared/ISRG_Root_X1.crt | 31 - src/ci/docker/run.sh | 3 +- src/ci/docker/scripts/freebsd-toolchain.sh | 2 +- src/ci/github-actions/ci.yml | 5 - src/ci/scripts/select-xcode.sh | 13 - src/doc/book/.github/workflows/main.yml | 8 +- .../listing-02-04/output.txt | 6 +- .../no-listing-02-without-expect/output.txt | 3 +- .../output.txt | 6 +- .../output.txt | 6 +- .../output.txt | 7 +- .../src/main.rs | 2 - .../output.txt | 6 +- .../output.txt | 6 +- .../output.txt | 6 +- .../output.txt | 6 +- .../listing-04-06/output.txt | 6 +- .../output.txt | 6 +- .../output.txt | 6 +- .../output.txt | 6 +- .../output.txt | 6 +- .../no-listing-19-slice-error/output.txt | 6 +- .../listing-05-11/output.txt | 7 +- .../output.txt | 22 +- .../output-only-01-debug/output.txt | 9 +- .../output.txt | 6 +- .../output.txt | 6 +- .../listing-07-03/output.txt | 6 +- .../listing-07-05/output.txt | 6 +- .../listing-08-07/output.txt | 6 +- .../listing-08-19/output.txt | 6 +- .../output.txt | 6 +- .../output.txt | 26 +- .../listing-10-05/output.txt | 6 +- .../listing-10-07/output.txt | 6 +- .../listing-10-17/output.txt | 6 +- .../listing-10-21/output.txt | 6 +- .../listing-10-24/output.txt | 6 +- .../output.txt | 6 +- .../output.txt | 6 +- .../no-listing-11-ignore-a-test/output.txt | 2 +- .../listing-12-12/output.txt | 3 +- .../output.txt | 6 +- .../listing-13-08/output.txt | 6 +- .../listing-13-17/output.txt | 3 +- .../output.txt | 6 +- .../no-listing-03-move-closures/output.txt | 6 +- .../listing-15-03/output.txt | 6 +- .../listing-15-09/output.txt | 6 +- .../listing-15-15/output.txt | 6 +- .../listing-15-17/output.txt | 6 +- .../listing-15-21/output.txt | 6 +- .../output.txt | 6 +- .../output.txt | 6 +- .../listing-16-03/output.txt | 6 +- .../listing-16-09/output.txt | 6 +- .../listing-16-13/output.txt | 6 +- .../listing-16-14/output.txt | 6 +- .../output-only-01-move-drop/output.txt | 6 +- .../ch17-oop/listing-17-10/output.txt | 6 +- .../output.txt | 10 +- .../listing-18-05/output.txt | 6 +- .../listing-18-08/output.txt | 6 +- .../listing-18-10/output.txt | 3 +- .../listing-18-25/output.txt | 6 +- .../listing-19-05/output.txt | 6 +- .../listing-19-20/output.txt | 14 +- .../output.txt | 6 +- .../no-listing-18-returns-closure/output.txt | 6 +- .../output-only-01-missing-unsafe/output.txt | 6 +- .../ch20-web-server/listing-20-12/output.txt | 6 +- .../ch20-web-server/listing-20-17/output.txt | 6 +- .../ch20-web-server/listing-20-22/output.txt | 6 +- .../output.txt | 6 +- .../output.txt | 6 +- .../output.txt | 6 +- src/doc/book/rust-toolchain | 2 +- src/doc/book/src/appendix-02-operators.md | 2 +- src/doc/book/src/ch17-01-what-is-oo.md | 2 +- src/doc/book/src/title-page.md | 2 +- src/doc/book/tools/update-rustc.sh | 3 + .../src/rust-2021/default-cargo-resolver.md | 8 + src/doc/embedded-book/src/intro/install.md | 2 + src/doc/embedded-book/src/start/qemu.md | 6 +- src/doc/nomicon/src/arc-mutex/arc-drop.md | 2 +- src/doc/nomicon/src/leaking.md | 6 + src/doc/nomicon/src/lifetimes.md | 4 +- src/doc/nomicon/src/other-reprs.md | 4 +- src/doc/nomicon/src/send-and-sync.md | 6 +- src/doc/nomicon/src/subtyping.md | 2 +- src/doc/reference/src/attributes/limits.md | 8 +- src/doc/reference/src/items/generics.md | 3 +- src/doc/reference/src/patterns.md | 38 +- src/doc/reference/src/tokens.md | 3 +- src/doc/reference/src/type-coercions.md | 2 +- src/doc/rust-by-example/src/cargo/test.md | 2 +- src/doc/rust-by-example/src/fn.md | 2 +- src/doc/rust-by-example/src/generics.md | 2 +- .../rust-by-example/src/hello/print/fmt.md | 2 +- src/doc/rust-by-example/src/std/arc.md | 27 +- .../rust-by-example/src/trait/impl_trait.md | 6 + src/doc/rustc-dev-guide/src/SUMMARY.md | 4 +- .../src/backend/backend-agnostic.md | 2 +- .../src/backend/updating-llvm.md | 2 +- .../region_inference/member_constraints.md | 2 +- .../src/borrow_check/two_phase_borrows.md | 6 +- src/doc/rustc-dev-guide/src/building/ctags.md | 26 - .../rustc-dev-guide/src/building/suggested.md | 5 +- src/doc/rustc-dev-guide/src/closure.md | 4 +- .../rustc-dev-guide/src/compiler-debugging.md | 135 +- src/doc/rustc-dev-guide/src/constants.md | 65 + src/doc/rustc-dev-guide/src/contributing.md | 6 +- src/doc/rustc-dev-guide/src/diagnostics.md | 10 +- .../src/diagnostics/diagnostic-items.md | 146 + .../rustc-dev-guide/src/getting-started.md | 6 +- src/doc/rustc-dev-guide/src/git.md | 6 +- .../src/llvm-coverage-instrumentation.md | 4 +- src/doc/rustc-dev-guide/src/overview.md | 27 +- src/doc/rustc-dev-guide/src/parallel-rustc.md | 73 +- .../query-evaluation-model-in-detail.md | 26 - .../rustc-dev-guide/src/rustdoc-internals.md | 18 +- src/doc/rustc-dev-guide/src/salsa.md | 4 +- src/doc/rustc-dev-guide/src/sanitizers.md | 72 +- src/doc/rustc-dev-guide/src/tests/adding.md | 7 +- src/doc/rustc-dev-guide/src/tracing.md | 204 + src/doc/rustc/src/SUMMARY.md | 1 + src/doc/rustc/src/codegen-options/index.md | 4 + src/doc/rustc/src/platform-support.md | 10 +- .../armv7-unknown-linux-uclibceabihf.md | 66 + .../rustc/src/platform-support/kmc-solid.md | 65 + .../m68k-unknown-linux-gnu.md | 97 + src/doc/rustc/src/tests/index.md | 40 +- src/doc/rustdoc/src/lints.md | 6 + src/doc/rustdoc/src/unstable-features.md | 24 +- .../debug_info_for_profiling.md | 35 + .../src/compiler-flags/profile_sample_use.md | 10 + .../src/compiler-flags/remap-cwd-prefix.md | 24 + .../language-features/closure-track-caller.md | 12 + .../unstable-book/src/library-features/asm.md | 14 +- src/etc/check_missing_items.py | 2 +- src/etc/test-float-parse/Cargo.toml | 2 +- src/librustdoc/Cargo.toml | 2 +- src/librustdoc/clean/auto_trait.rs | 346 +- src/librustdoc/clean/blanket_impl.rs | 30 +- src/librustdoc/clean/cfg.rs | 1 + src/librustdoc/clean/inline.rs | 123 +- src/librustdoc/clean/mod.rs | 260 +- src/librustdoc/clean/simplify.rs | 18 +- src/librustdoc/clean/types.rs | 452 +- src/librustdoc/clean/utils.rs | 119 +- src/librustdoc/config.rs | 8 +- src/librustdoc/core.rs | 55 +- src/librustdoc/docfs.rs | 12 +- src/librustdoc/doctest.rs | 46 +- src/librustdoc/doctest/tests.rs | 7 +- src/librustdoc/externalfiles.rs | 24 +- src/librustdoc/fold.rs | 8 +- src/librustdoc/formats/cache.rs | 48 +- src/librustdoc/formats/mod.rs | 10 +- src/librustdoc/html/format.rs | 156 +- src/librustdoc/html/highlight.rs | 101 +- .../html/highlight/fixtures/sample.html | 6 +- .../html/highlight/fixtures/sample.rs | 2 +- .../html/highlight/fixtures/union.html | 8 + .../html/highlight/fixtures/union.rs | 8 + src/librustdoc/html/highlight/tests.rs | 10 + src/librustdoc/html/markdown.rs | 144 +- src/librustdoc/html/markdown/tests.rs | 76 +- src/librustdoc/html/render/cache.rs | 17 +- src/librustdoc/html/render/context.rs | 28 +- src/librustdoc/html/render/mod.rs | 326 +- src/librustdoc/html/render/print_item.rs | 257 +- src/librustdoc/html/render/span_map.rs | 20 +- src/librustdoc/html/render/templates.rs | 20 + src/librustdoc/html/render/write_shared.rs | 89 +- src/librustdoc/html/sources.rs | 2 +- src/librustdoc/html/static/css/rustdoc.css | 71 +- src/librustdoc/html/static/css/themes/ayu.css | 8 +- .../html/static/css/themes/dark.css | 6 +- .../html/static/css/themes/light.css | 6 +- src/librustdoc/html/static/js/main.js | 9 + src/librustdoc/html/static_files.rs | 17 +- src/librustdoc/html/templates/print_item.html | 26 + src/librustdoc/json/conversions.rs | 53 +- src/librustdoc/json/mod.rs | 25 +- src/librustdoc/lib.rs | 17 +- src/librustdoc/markdown.rs | 19 +- src/librustdoc/passes/bare_urls.rs | 4 +- .../passes/calculate_doc_coverage.rs | 42 +- .../passes/check_code_block_syntax.rs | 4 +- ..._lints.rs => check_doc_test_visibility.rs} | 39 +- .../passes/collect_intra_doc_links.rs | 65 +- .../passes/collect_intra_doc_links/early.rs | 31 +- src/librustdoc/passes/collect_trait_impls.rs | 8 +- src/librustdoc/passes/html_tags.rs | 8 +- src/librustdoc/passes/mod.rs | 8 +- src/librustdoc/passes/stripper.rs | 4 +- src/librustdoc/visit_ast.rs | 32 +- src/librustdoc/visit_lib.rs | 2 +- src/rustdoc-json-types/Cargo.toml | 2 +- src/rustdoc-json-types/lib.rs | 9 +- src/stage0.json | 291 + src/stage0.txt | 42 - .../assembly/asm/aarch64-outline-atomics.rs | 17 + src/test/assembly/asm/bpf-types.rs | 2 +- src/test/assembly/niche-prefer-zero.rs | 25 + src/test/assembly/pic-relocation-model.rs | 35 + src/test/assembly/pie-relocation-model.rs | 38 + src/test/assembly/x86_64-sse_crc.rs | 12 + .../partitioning/extern-drop-glue.rs | 5 +- .../partitioning/extern-generic.rs | 5 +- .../partitioning/incremental-merging.rs | 5 +- .../inlining-from-extern-crate.rs | 5 +- .../partitioning/local-drop-glue.rs | 5 +- .../partitioning/local-generic.rs | 5 +- .../local-inlining-but-not-all.rs | 5 +- .../partitioning/local-inlining.rs | 5 +- .../partitioning/local-transitive-inlining.rs | 5 +- .../methods-are-with-self-type.rs | 5 +- .../partitioning/regular-modules.rs | 5 +- .../partitioning/shared-generics.rs | 3 +- .../codegen-units/partitioning/statics.rs | 5 +- .../partitioning/vtable-through-const.rs | 5 +- src/test/codegen/alloc-optimisation.rs | 1 + src/test/codegen/debug-vtable.rs | 57 + .../codegen/intrinsics/const_eval_select.rs | 17 + src/test/codegen/panic-in-drop-abort.rs | 59 + src/test/codegen/pic-relocation-model.rs | 16 + src/test/codegen/pie-relocation-model.rs | 22 + src/test/codegen/sse42-implies-crc32.rs | 16 + src/test/codegen/vtabletype.rs | 21 - src/test/debuginfo/basic-types.rs | 7 +- src/test/debuginfo/borrowed-struct.rs | 3 +- src/test/debuginfo/borrowed-tuple.rs | 3 +- src/test/debuginfo/borrowed-unique-basic.rs | 29 +- src/test/debuginfo/box.rs | 5 +- src/test/debuginfo/boxed-struct.rs | 15 +- .../debuginfo/closure-in-generic-function.rs | 1 - .../debuginfo/destructured-fn-argument.rs | 3 +- .../destructured-for-loop-variable.rs | 3 +- src/test/debuginfo/destructured-local.rs | 3 +- src/test/debuginfo/function-names.rs | 31 +- .../generic-method-on-generic-struct.rs | 3 +- src/test/debuginfo/method-on-enum.rs | 3 +- .../debuginfo/method-on-generic-struct.rs | 4 +- src/test/debuginfo/method-on-struct.rs | 4 +- src/test/debuginfo/method-on-trait.rs | 4 +- src/test/debuginfo/method-on-tuple-struct.rs | 4 +- src/test/debuginfo/msvc-pretty-enums.rs | 110 +- src/test/debuginfo/msvc-scalarpair-params.rs | 101 + src/test/debuginfo/mutex.rs | 12 +- src/test/debuginfo/pretty-std.rs | 16 +- src/test/debuginfo/recursive-struct.rs | 58 +- src/test/debuginfo/self-in-default-method.rs | 3 +- .../self-in-generic-default-method.rs | 3 +- src/test/debuginfo/trait-pointers.rs | 3 +- src/test/debuginfo/type-names.rs | 11 +- src/test/debuginfo/unique-enum.rs | 7 +- .../var-captured-in-nested-closure.rs | 3 +- .../var-captured-in-sendable-closure.rs | 3 +- .../var-captured-in-stack-closure.rs | 3 +- .../change_symbol_export_status.rs | 14 +- .../incremental/hashes/call_expressions.rs | 70 +- .../incremental/hashes/closure_expressions.rs | 54 +- src/test/incremental/hashes/consts.rs | 2 +- .../incremental/hashes/enum_constructors.rs | 128 +- src/test/incremental/hashes/enum_defs.rs | 236 +- .../incremental/hashes/exported_vs_not.rs | 28 +- src/test/incremental/hashes/extern_mods.rs | 100 +- src/test/incremental/hashes/for_loops.rs | 87 +- .../incremental/hashes/function_interfaces.rs | 208 +- src/test/incremental/hashes/if_expressions.rs | 67 +- .../hashes/indexing_expressions.rs | 60 +- src/test/incremental/hashes/inherent_impls.rs | 474 +- src/test/incremental/hashes/inline_asm.rs | 50 +- .../incremental/hashes/let_expressions.rs | 137 +- .../incremental/hashes/loop_expressions.rs | 69 +- .../incremental/hashes/match_expressions.rs | 145 +- src/test/incremental/hashes/statics.rs | 84 +- .../incremental/hashes/struct_constructors.rs | 75 +- src/test/incremental/hashes/struct_defs.rs | 133 +- src/test/incremental/hashes/trait_defs.rs | 659 ++- src/test/incremental/hashes/trait_impls.rs | 262 +- src/test/incremental/hashes/type_defs.rs | 2 +- .../hashes/unary_and_binary_exprs.rs | 190 +- .../incremental/hashes/while_let_loops.rs | 73 +- src/test/incremental/hashes/while_loops.rs | 75 +- src/test/incremental/mir-opt.rs | 11 + .../spans_significant_w_debuginfo.rs | 13 +- .../incremental/spans_significant_w_panic.rs | 22 +- src/test/incremental/string_constant.rs | 18 +- .../thinlto/cgu_keeps_identical_fn.rs | 61 +- .../box_expr.main.ElaborateDrops.before.mir | 66 +- ...d[0].SimplifyCfg-elaborate-drops.after.mir | 6 +- ...motion_extern_static.BAR.PromoteTemps.diff | 20 +- ...d[0].SimplifyCfg-elaborate-drops.after.mir | 6 +- ...motion_extern_static.FOO.PromoteTemps.diff | 20 +- .../const_prop/boxes.main.ConstProp.diff | 39 +- .../slice_len.main.ConstProp.32bit.diff | 7 +- .../slice_len.main.ConstProp.64bit.diff | 7 +- ...age_graphviz.main.InstrumentCoverage.0.dot | 14 +- ..._line_doc_comment_2.DeduplicateBlocks.diff | 6 +- ...float_to_exponential_common.ConstProp.diff | 12 +- .../inline/inline_diverging.h.Inline.diff | 2 +- ...line_into_box_place.main.Inline.32bit.diff | 60 +- ...line_into_box_place.main.Inline.64bit.diff | 60 +- .../inline/inline_shims.clone.Inline.diff | 6 +- .../inline_trait_method.test.Inline.after.mir | 6 +- ...67_inline_as_ref_as_mut.a.Inline.after.mir | 6 +- ...67_inline_as_ref_as_mut.b.Inline.after.mir | 6 +- ...67_inline_as_ref_as_mut.c.Inline.after.mir | 6 +- ...67_inline_as_ref_as_mut.d.Inline.after.mir | 6 +- ...ment_coverage.main.InstrumentCoverage.diff | 29 +- ...issue_62289.test.ElaborateDrops.before.mir | 128 +- ...76432.test.SimplifyComparisonIntegral.diff | 12 +- ...wer_array_len.array_bound.InstCombine.diff | 66 + ...ray_len.array_bound.NormalizeArrayLen.diff | 68 + ..._array_len.array_bound.SimplifyLocals.diff | 73 + ...array_len.array_bound_mut.InstCombine.diff | 79 + ...len.array_bound_mut.NormalizeArrayLen.diff | 81 + ...ay_len.array_bound_mut.SimplifyLocals.diff | 96 + ...lower_array_len.array_len.InstCombine.diff | 27 + ...array_len.array_len.NormalizeArrayLen.diff | 30 + ...er_array_len.array_len.SimplifyLocals.diff | 25 + ...ay_len.array_len_by_value.InstCombine.diff | 26 + ....array_len_by_value.NormalizeArrayLen.diff | 30 + ...len.array_len_by_value.SimplifyLocals.diff | 25 + src/test/mir-opt/lower_array_len.rs | 47 + ...r_intrinsics.align_of.LowerIntrinsics.diff | 24 + ...trinsics.discriminant.LowerIntrinsics.diff | 162 +- ...wer_intrinsics.f_u64.PreCodegen.before.mir | 36 +- ...er_intrinsics.f_unit.PreCodegen.before.mir | 26 +- ...wer_intrinsics.forget.LowerIntrinsics.diff | 26 +- ..._intrinsics.non_const.LowerIntrinsics.diff | 32 +- src/test/mir-opt/lower_intrinsics.rs | 5 + ...ntrinsics.unreachable.LowerIntrinsics.diff | 20 +- ...er_slice_len.bound.LowerSliceLenCalls.diff | 6 +- ..._after_call.main.ElaborateDrops.before.mir | 6 +- ...receiver_ptr_mutability.main.mir_map.0.mir | 18 +- src/test/mir-opt/remove-never-const.rs | 1 - ...ever_const.no_codegen.PreCodegen.after.mir | 4 +- ...age_markers.main.RemoveStorageMarkers.diff | 2 +- ...main.SimplifyCfg-elaborate-drops.after.mir | 16 +- ...mplify_cfg.main.SimplifyCfg-early-opt.diff | 34 +- ...simplify_cfg.main.SimplifyCfg-initial.diff | 29 +- ...ove_out.move_out_by_subslice.mir_map.0.mir | 108 +- ...y_move_out.move_out_from_end.mir_map.0.mir | 108 +- ...hable_asm.main.UnreachablePropagation.diff | 2 +- ...ble_asm_2.main.UnreachablePropagation.diff | 4 +- ...le_storage.while_loop.PreCodegen.after.mir | 34 +- src/test/pretty/dollar-crate.pp | 10 +- src/test/pretty/issue-4264.pp | 56 +- .../expected_show_coverage.issue-84561.txt | 6 +- .../hotplug_codegen_backend/the_backend.rs | 7 +- .../obtain-borrowck/driver.rs | 13 +- .../reproducible-build/Makefile | 65 +- .../sepcomp-cci-copies/Makefile | 2 +- .../sysroot-crates-are-unstable/test.py | 13 + .../run-make-fulldeps/target-specs/foo.rs | 2 +- src/test/run-make-fulldeps/tools.mk | 4 +- src/test/run-make/dep-graph/Makefile | 12 + src/test/run-make/dep-graph/foo.rs | 1 + src/test/run-make/issue-85441/Makefile | 9 + src/test/run-make/issue-85441/empty.rs | 1 + .../Makefile | 39 + .../c_static_lib_with_constructor.cpp | 11 + .../directly_linked.rs | 6 + .../indirectly_linked.rs | 5 + .../indirectly_linked_via_attr.rs | 5 + .../native_lib_in_src.rs | 15 + .../rlib_with_cmdline_native_lib.rs | 6 + .../run-make/raw-dylib-link-ordinal/Makefile | 18 + .../run-make/raw-dylib-link-ordinal/driver.rs | 5 + .../raw-dylib-link-ordinal/exporter.c | 5 + .../raw-dylib-link-ordinal/exporter.def | 3 + .../run-make/raw-dylib-link-ordinal/lib.rs | 13 + .../raw-dylib-link-ordinal/output.txt | 1 + src/test/rustdoc-gui/code-sidebar-toggle.goml | 1 + .../rustdoc-gui/docblock-big-code-mobile.goml | 9 + .../rustdoc-gui/docblock-table-overflow.goml | 8 + src/test/rustdoc-gui/header-size.goml | 99 + .../huge-collection-of-constants.goml | 5 + .../rustdoc-gui/jump-to-def-background.goml | 23 + src/test/rustdoc-gui/sidebar.goml | 14 +- src/test/rustdoc-gui/src/lib2/lib.rs | 9 + .../src/link_to_definition/Cargo.lock | 7 + .../src/link_to_definition/Cargo.toml | 7 + .../rustdoc-gui/src/link_to_definition/lib.rs | 6 + src/test/rustdoc-gui/src/test_docs/Cargo.toml | 2 + src/test/rustdoc-gui/src/test_docs/build.rs | 15 + src/test/rustdoc-gui/src/test_docs/lib.rs | 133 + src/test/rustdoc-js-std/multi-query.js | 7 +- src/test/rustdoc-json/primitive.rs | 14 + src/test/rustdoc-json/primitives.rs | 22 + .../rustdoc-json/structs/with_primitives.rs | 2 +- src/test/rustdoc-json/unions/impl.rs | 15 + .../rustdoc-ui/ambiguous-inherent-assoc-ty.rs | 1 - src/test/rustdoc-ui/bounded-hr-lifetime.rs | 9 + .../rustdoc-ui/bounded-hr-lifetime.stderr | 10 + .../coverage/enum-tuple-documented.rs | 37 + .../coverage/enum-tuple-documented.stdout | 7 + src/test/rustdoc-ui/coverage/enum-tuple.rs | 18 + .../rustdoc-ui/coverage/enum-tuple.stdout | 7 + src/test/rustdoc-ui/coverage/enums.stdout | 4 +- src/test/rustdoc-ui/display-output.rs | 9 + src/test/rustdoc-ui/display-output.stdout | 24 + src/test/rustdoc-ui/doc-cfg.rs | 9 + src/test/rustdoc-ui/doc-cfg.stderr | 26 + src/test/rustdoc-ui/doctest-edition.stderr | 2 +- .../rustdoc-ui/feature-gate-doc_cfg_hide.rs | 7 + .../feature-gate-doc_cfg_hide.stderr | 14 + src/test/rustdoc-ui/intra-doc/anchors.rs | 10 - src/test/rustdoc-ui/intra-doc/anchors.stderr | 35 +- .../rustdoc-ui/intra-doc/auxiliary/dep1.rs | 1 + .../rustdoc-ui/intra-doc/auxiliary/dep2.rs | 1 + .../rustdoc-ui/intra-doc/auxiliary/dep3.rs | 1 + .../rustdoc-ui/intra-doc/auxiliary/dep4.rs | 1 + .../rustdoc-ui/intra-doc/extern-crate-load.rs | 26 + src/test/rustdoc-ui/intra-doc/warning.stderr | 2 +- src/test/rustdoc-ui/invalid-syntax.stderr | 10 +- .../lint-missing-doc-code-example.rs | 16 + src/test/rustdoc/associated-consts.rs | 31 + src/test/rustdoc/auxiliary/issue-15318.rs | 11 +- src/test/rustdoc/auxiliary/primitive-doc.rs | 3 + .../check-source-code-urls-to-def-std.rs | 17 + .../rustdoc/check-source-code-urls-to-def.rs | 8 +- src/test/rustdoc/cross-crate-primitive-doc.rs | 6 +- src/test/rustdoc/doc-auto-cfg.rs | 8 + src/test/rustdoc/doc-cfg-hide.rs | 32 + src/test/rustdoc/doc-cfg-implicit-gate.rs | 7 + src/test/rustdoc/doc-cfg-implicit.rs | 31 + src/test/rustdoc/external-cross.rs | 2 +- src/test/rustdoc/external-doc.rs | 6 +- src/test/rustdoc/feature-gate-doc_auto_cfg.rs | 8 + ...rait-methods-with-document-hidden-items.rs | 31 + src/test/rustdoc/hidden-trait-methods.rs | 29 + src/test/rustdoc/intra-doc/anchors.rs | 12 + .../rustdoc/intra-doc/auxiliary/my-core.rs | 4 + .../intra-doc/prim-methods-external-core.rs | 6 +- .../rustdoc/intra-doc/prim-methods-local.rs | 9 +- src/test/rustdoc/intra-link-prim-self.rs | 4 +- src/test/rustdoc/issue-15318-2.rs | 1 + src/test/rustdoc/issue-42760.rs | 2 +- .../rustdoc/issue-89309-heading-levels.rs | 29 + .../macro-document-private-duplicate.rs | 2 + src/test/rustdoc/macro_rules-matchers.rs | 18 +- src/test/rustdoc/no_std-primitive.rs | 6 + src/test/rustdoc/primitive/no_std.rs | 16 + src/test/rustdoc/short-docblock.rs | 4 +- src/test/rustdoc/smart-punct.rs | 2 +- .../rustdoc/synthetic_auto/no-redundancy.rs | 2 +- src/test/rustdoc/table-in-docblock.rs | 16 + src/test/rustdoc/type-layout.rs | 18 + .../auxiliary/issue-40001-plugin.rs | 4 +- .../auxiliary/lint-for-crate-rpass.rs | 13 +- .../ui-fulldeps/auxiliary/lint-for-crate.rs | 16 +- .../auxiliary/lint-group-plugin-test.rs | 4 +- .../ui-fulldeps/auxiliary/lint-plugin-test.rs | 4 +- .../ui-fulldeps/auxiliary/lint-tool-test.rs | 4 +- .../auxiliary/outlive-expansion-phase.rs | 4 +- .../deriving-encodable-decodable-box.rs | 1 - .../ui-fulldeps/hash-stable-is-unstable.rs | 4 +- .../hash-stable-is-unstable.stderr | 6 +- .../lint_pass_impl_without_macro.stderr | 2 +- .../issue-76270-panic-in-libproc-macro.stderr | 2 +- src/test/ui/alignment-gep-tup-like-1.rs | 6 +- src/test/ui/annotate-snippet/multispan.stderr | 14 +- .../anon-params-denied-2018.stderr | 24 +- .../anon-params/anon-params-deprecated.stderr | 6 +- .../ui/array-slice-vec/slice_binary_search.rs | 1 + src/test/ui/array-slice-vec/vec-dst.rs | 6 +- .../vec-mut-iter-borrow.stderr | 2 +- .../ui/array-slice-vec/vector-no-ann-2.rs | 6 +- src/test/ui/asm/aarch64/bad-options.rs | 39 + src/test/ui/asm/aarch64/bad-options.stderr | 84 + src/test/ui/asm/aarch64/bad-reg.rs | 59 + src/test/ui/asm/aarch64/bad-reg.stderr | 152 + src/test/ui/asm/aarch64/const.rs | 42 + .../ui/asm/aarch64/duplicate-options.fixed | 26 + src/test/ui/asm/aarch64/duplicate-options.rs | 26 + .../ui/asm/aarch64/duplicate-options.stderr | 56 + .../ui/asm/aarch64/interpolated-idents.rs | 24 + .../ui/asm/aarch64/interpolated-idents.stderr | 51 + src/test/ui/asm/aarch64/parse-error.rs | 135 + src/test/ui/asm/aarch64/parse-error.stderr | 462 ++ src/test/ui/asm/aarch64/srcloc.rs | 121 + src/test/ui/asm/aarch64/srcloc.stderr | 278 + src/test/ui/asm/aarch64/sym.rs | 80 + src/test/ui/asm/aarch64/type-check-2.rs | 84 + src/test/ui/asm/aarch64/type-check-2.stderr | 103 + src/test/ui/asm/aarch64/type-check-3.rs | 115 + src/test/ui/asm/aarch64/type-check-3.stderr | 172 + src/test/ui/asm/bad-arch.mirunsafeck.stderr | 4 +- src/test/ui/asm/bad-arch.thirunsafeck.stderr | 4 +- .../bad-template.aarch64_mirunsafeck.stderr | 187 + .../bad-template.aarch64_thirunsafeck.stderr | 187 + src/test/ui/asm/bad-template.rs | 35 +- ...=> bad-template.x86_64_mirunsafeck.stderr} | 48 +- ...> bad-template.x86_64_thirunsafeck.stderr} | 48 +- src/test/ui/asm/issue-72570.rs | 2 +- src/test/ui/asm/issue-87802.rs | 5 +- src/test/ui/asm/issue-87802.stderr | 2 +- src/test/ui/asm/issue-89305.rs | 14 + src/test/ui/asm/issue-89305.stderr | 15 + src/test/ui/asm/naked-functions-ffi.rs | 2 +- .../asm/naked-functions-unused.aarch64.stderr | 69 + src/test/ui/asm/naked-functions-unused.rs | 28 +- src/test/ui/asm/naked-functions-unused.stderr | 69 - .../asm/naked-functions-unused.x86_64.stderr | 69 + src/test/ui/asm/naked-functions.rs | 6 +- src/test/ui/asm/naked-functions.stderr | 88 +- src/test/ui/asm/named-asm-labels.rs | 8 +- src/test/ui/asm/named-asm-labels.stderr | 52 +- src/test/ui/asm/noreturn.rs | 2 +- src/test/ui/asm/rustfix-asm.fixed | 2 +- src/test/ui/asm/rustfix-asm.rs | 2 +- src/test/ui/asm/rustfix-asm.stderr | 4 +- src/test/ui/asm/type-check-1.rs | 7 +- src/test/ui/asm/type-check-1.stderr | 38 +- src/test/ui/asm/type-check-4.rs | 5 +- src/test/ui/asm/type-check-4.stderr | 6 +- src/test/ui/asm/{ => x86_64}/bad-options.rs | 0 .../ui/asm/{ => x86_64}/bad-options.stderr | 0 src/test/ui/asm/{ => x86_64}/bad-reg.rs | 4 - src/test/ui/asm/{ => x86_64}/bad-reg.stderr | 48 +- src/test/ui/asm/{ => x86_64}/const.rs | 0 .../asm/{ => x86_64}/duplicate-options.fixed | 0 .../ui/asm/{ => x86_64}/duplicate-options.rs | 0 .../asm/{ => x86_64}/duplicate-options.stderr | 0 .../asm/{ => x86_64}/interpolated-idents.rs | 0 .../{ => x86_64}/interpolated-idents.stderr | 16 +- src/test/ui/asm/{ => x86_64}/issue-82869.rs | 0 .../ui/asm/{ => x86_64}/issue-82869.stderr | 0 src/test/ui/asm/{ => x86_64}/parse-error.rs | 6 + .../ui/asm/{ => x86_64}/parse-error.stderr | 72 +- src/test/ui/asm/{ => x86_64}/srcloc.rs | 0 src/test/ui/asm/{ => x86_64}/srcloc.stderr | 0 src/test/ui/asm/{ => x86_64}/sym.rs | 0 src/test/ui/asm/x86_64/target-feature-attr.rs | 40 + .../ui/asm/x86_64/target-feature-attr.stderr | 26 + src/test/ui/asm/{ => x86_64}/type-check-2.rs | 4 - .../ui/asm/{ => x86_64}/type-check-2.stderr | 22 +- src/test/ui/asm/{ => x86_64}/type-check-3.rs | 0 .../ui/asm/{ => x86_64}/type-check-3.stderr | 0 .../assignment-operator-unimplemented.stderr | 17 +- .../associated-const-ambiguity-report.stderr | 8 +- ...ssociated-const-impl-wrong-lifetime.stderr | 2 +- .../associated-const-in-trait.stderr | 2 +- .../defaults-not-assumed-fail.stderr | 2 +- .../ui/associated-item/issue-48027.stderr | 2 +- ...self.rs => supertrait-referencing-self.rs} | 0 ...ferencing.rs => supertrait-referencing.rs} | 0 ...s => supertrait-where-referencing-self.rs} | 0 .../traits-assoc-type-macros.rs | 2 +- ...mbig-between-bound-and-where-clause.stderr | 24 +- ...rojection-from-multiple-supertraits.stderr | 8 +- .../associated-types-bound-failure.stderr | 4 +- ...ciated-types-doubleendediterator-object.rs | 1 - .../associated-types-path-1.stderr | 4 +- .../associated-types-path-2.rs | 2 - .../associated-types-path-2.stderr | 32 +- ...iated-types-project-from-hrtb-in-fn.stderr | 7 +- ...s-project-from-hrtb-in-trait-method.stderr | 14 +- ...-fn-ret-contravariant.transmute.nll.stderr | 2 - ...ject-fn-ret-invariant.transmute.nll.stderr | 2 - .../higher-ranked-projection.bad.nll.stderr | 5 + .../hr-associated-type-bound-2.stderr | 4 +- .../associated-types/impl-wf-cycle-1.stderr | 6 +- .../issue-19883.rs | 0 .../issue-19883.stderr | 0 .../issue-21363.rs | 0 .../ui/associated-types/issue-22560.stderr | 2 +- .../issue-27675-unchecked-bounds.stderr | 4 +- .../ui/associated-types/issue-36499.stderr | 10 +- .../missing-associated-types.stderr | 8 +- .../auxiliary/issue-72470-lib.rs | 0 src/test/ui/async-await/issue-61452.stderr | 2 +- .../issue-64130-non-send-future-diags.rs | 2 + .../issue-64130-non-send-future-diags.stderr | 6 +- src/test/ui/async-await/issue-71137.rs | 2 + src/test/ui/async-await/issue-71137.stderr | 6 +- src/test/ui/async-await/issue-72442.rs | 2 +- src/test/ui/async-await/issue-72442.stderr | 4 +- .../issue-72470-llvm-dominate.rs | 0 src/test/ui/async-await/issue-73541-2.stderr | 2 +- .../ui/async-await/issue-76547.nll.stderr | 22 +- .../issues/issue-54752-async-block.stderr | 7 +- .../ui/async-await/issues/issue-61187.stderr | 2 +- .../async-await/issues/issue-62097.nll.stderr | 10 +- src/test/ui/async-await/issues/issue-64964.rs | 3 +- src/test/ui/async-await/issues/issue-65159.rs | 1 - .../ui/async-await/issues/issue-65159.stderr | 11 +- .../extented-attribute-macro-error.rs | 8 + .../extented-attribute-macro-error.stderr | 10 + .../ui/attributes/key-value-expansion.stderr | 20 +- .../attributes/nonterminal-expansion.stderr | 4 +- .../attributes/register-attr-tool-fail.stderr | 4 +- .../auto-traits/auto-trait-validation.fixed | 13 + .../ui/auto-traits/auto-trait-validation.rs | 8 +- .../auto-traits/auto-trait-validation.stderr | 31 +- src/test/ui/auto-traits/issue-23080-2.stderr | 6 +- src/test/ui/auto-traits/issue-23080.stderr | 13 +- src/test/ui/auto-traits/issue-84075.rs | 16 + src/test/ui/auto-traits/issue-84075.stderr | 11 + .../typeck-auto-trait-no-supertraits-2.rs | 1 + .../typeck-auto-trait-no-supertraits-2.stderr | 18 +- .../typeck-auto-trait-no-supertraits.stderr | 8 +- src/test/ui/autoderef-full-lval.rs | 12 +- .../autoderef-method-on-trait.rs | 3 +- .../autoderef-method-priority.rs | 3 +- .../autoderef-method-twice-but-not-thrice.rs | 3 +- .../autoderef-method-twice.rs | 3 +- .../ui/autoref-autoderef/autoderef-method.rs | 3 +- .../autoref-intermediate-types-issue-3585.rs | 3 +- .../ui/autoref-autoderef/issue-38940.stderr | 2 +- .../ui/binding/expr-match-generic-unique1.rs | 3 +- .../ui/binding/expr-match-generic-unique2.rs | 3 +- src/test/ui/binding/expr-match-unique.rs | 3 +- .../ui/binding/func-arg-incomplete-pattern.rs | 6 +- src/test/ui/binding/func-arg-ref-pattern.rs | 5 +- src/test/ui/binding/let-assignability.rs | 3 +- .../ui/binding/match-implicit-copy-unique.rs | 5 +- src/test/ui/binding/match-unique-bind.rs | 3 +- .../match-value-binding-in-guard-3291.rs | 6 +- src/test/ui/binop/binop-move-semantics.stderr | 2 +- src/test/ui/binop/issue-28837.stderr | 213 +- src/test/ui/binop/issue-77910-1.stderr | 4 +- .../consider-removing-last-semi.fixed | 7 + .../consider-removing-last-semi.rs | 7 + .../consider-removing-last-semi.stderr | 13 +- src/test/ui/block-result/issue-13428.stderr | 3 - src/test/ui/borrowck/borrow-tuple-fields.rs | 12 +- .../ui/borrowck/borrow-tuple-fields.stderr | 12 +- src/test/ui/borrowck/borrowck-argument.stderr | 8 +- .../borrowck-auto-mut-ref-to-immut-var.stderr | 2 +- .../borrowck-bad-nested-calls-free.rs | 8 +- .../borrowck-bad-nested-calls-move.rs | 8 +- .../borrowck-borrow-from-expr-block.rs | 3 +- ...rrowck-borrow-immut-deref-of-box-as-mut.rs | 6 +- ...ck-borrow-immut-deref-of-box-as-mut.stderr | 4 +- .../borrowck-borrow-mut-object-twice.stderr | 6 +- ...rrowck-borrow-overloaded-auto-deref.stderr | 14 +- .../borrowck/borrowck-borrowed-uniq-rvalue.rs | 10 +- .../borrowck-borrowed-uniq-rvalue.stderr | 2 +- .../ui/borrowck/borrowck-box-sensitivity.rs | 34 +- .../borrowck/borrowck-closures-mut-and-imm.rs | 10 +- .../borrowck-closures-two-mut-fail.rs | 4 +- .../ui/borrowck/borrowck-closures-two-mut.rs | 4 +- .../borrowck-closures-unique-imm.stderr | 2 +- .../borrowck-closures-use-after-free.rs | 8 +- .../borrowck-closures-use-after-free.stderr | 2 +- .../borrowck/borrowck-describe-lvalue.stderr | 12 +- .../borrowck-field-sensitivity-rpass.rs | 106 +- .../ui/borrowck/borrowck-field-sensitivity.rs | 28 +- .../borrowck-field-sensitivity.stderr | 2 +- ...rrowck-for-loop-correct-cmt-for-pattern.rs | 6 +- .../borrowck-for-loop-head-linkage.nll.stderr | 27 - .../ui/borrowck/borrowck-in-static.stderr | 5 +- .../borrowck-insert-during-each.stderr | 20 +- src/test/ui/borrowck/borrowck-issue-14498.rs | 20 +- src/test/ui/borrowck/borrowck-issue-2657-1.rs | 9 +- .../ui/borrowck/borrowck-issue-2657-1.stderr | 2 +- src/test/ui/borrowck/borrowck-issue-2657-2.rs | 6 +- src/test/ui/borrowck/borrowck-lend-flow-if.rs | 12 +- .../ui/borrowck/borrowck-lend-flow-if.stderr | 2 +- .../ui/borrowck/borrowck-lend-flow-loop.rs | 32 +- .../borrowck/borrowck-lend-flow-loop.stderr | 2 +- src/test/ui/borrowck/borrowck-lend-flow.rs | 8 +- .../ui/borrowck/borrowck-lend-flow.stderr | 2 +- .../borrowck/borrowck-loan-blocks-move-cc.rs | 8 +- .../borrowck-loan-blocks-move-cc.stderr | 4 +- .../ui/borrowck/borrowck-loan-blocks-move.rs | 10 +- .../borrowck/borrowck-loan-blocks-move.stderr | 2 +- .../borrowck/borrowck-loan-blocks-mut-uniq.rs | 8 +- .../borrowck-loan-blocks-mut-uniq.stderr | 2 +- .../borrowck-loan-in-overloaded-op.rs | 6 +- .../borrowck-loan-in-overloaded-op.stderr | 4 +- .../borrowck-loan-rcvr-overloaded-op.stderr | 2 +- .../ui/borrowck/borrowck-loan-rcvr.stderr | 18 +- .../borrowck-macro-interaction-issue-6304.rs | 4 +- .../borrowck/borrowck-move-by-capture-ok.rs | 3 +- .../ui/borrowck/borrowck-move-by-capture.rs | 4 +- .../borrowck/borrowck-move-by-capture.stderr | 21 +- .../borrowck/borrowck-move-error-with-note.rs | 12 +- ...owck-move-from-subpath-of-borrowed-path.rs | 4 +- ...-move-from-subpath-of-borrowed-path.stderr | 2 +- .../borrowck-move-moved-value-into-closure.rs | 6 +- ...rowck-move-moved-value-into-closure.stderr | 2 +- .../borrowck-move-mut-base-ptr.stderr | 2 +- ...k-move-out-of-overloaded-auto-deref.stderr | 2 +- .../ui/borrowck/borrowck-move-subcomponent.rs | 4 +- .../ui/borrowck/borrowck-multiple-captures.rs | 16 +- .../borrowck-multiple-captures.stderr | 6 +- .../borrowck-mut-borrow-linear-errors.stderr | 10 +- ...borrowck-mut-borrow-of-mut-base-ptr.stderr | 4 +- src/test/ui/borrowck/borrowck-mut-uniq.rs | 3 +- .../borrowck-no-cycle-in-exchange-heap.rs | 6 +- .../borrowck-object-lifetime.nll.stderr | 23 - .../borrowck/borrowck-object-lifetime.stderr | 8 +- ...borrowck-overloaded-index-autoderef.stderr | 16 +- ...borrowck-overloaded-index-move-from-vec.rs | 6 +- ...rowck-report-with-custom-diagnostic.stderr | 6 +- .../borrowck-swap-mut-base-ptr.stderr | 2 +- .../borrowck-union-borrow-nested.stderr | 2 +- .../ui/borrowck/borrowck-uniq-via-lend.rs | 26 +- .../ui/borrowck/borrowck-uniq-via-lend.stderr | 4 +- .../ui/borrowck/borrowck-unused-mut-locals.rs | 1 + .../borrowck/borrowck-use-mut-borrow-rpass.rs | 14 +- .../ui/borrowck/borrowck-use-mut-borrow.rs | 10 +- .../borrowck-vec-pattern-loan-from-mut.stderr | 5 +- .../borrowck/borrowck-vec-pattern-nesting.rs | 16 +- .../borrowck-vec-pattern-nesting.stderr | 8 +- src/test/ui/borrowck/fsu-moves-and-copies.rs | 10 +- .../borrowck/index-mut-help-with-impl.stderr | 2 +- src/test/ui/borrowck/index-mut-help.stderr | 2 +- src/test/ui/borrowck/issue-17263.rs | 6 +- src/test/ui/borrowck/issue-42344.stderr | 2 +- src/test/ui/borrowck/issue-51117.stderr | 2 +- src/test/ui/borrowck/issue-81365-10.stderr | 2 +- src/test/ui/borrowck/issue-81365-5.stderr | 2 +- src/test/ui/borrowck/issue-82032.stderr | 2 +- .../issue-82126-mismatched-subst-and-hir.rs | 1 - ...ssue-82126-mismatched-subst-and-hir.stderr | 18 +- src/test/ui/borrowck/issue-82462.rs | 21 + src/test/ui/borrowck/issue-82462.stderr | 22 + src/test/ui/borrowck/issue-85581.stderr | 2 +- src/test/ui/borrowck/issue-85765.stderr | 2 +- .../borrowck/issue-87456-point-to-closure.rs | 14 + .../issue-87456-point-to-closure.stderr | 22 + .../borrowck/issue-88434-minimal-example.rs | 13 + .../issue-88434-minimal-example.stderr | 17 + ...ssue-88434-removal-index-should-be-less.rs | 13 + ...-88434-removal-index-should-be-less.stderr | 17 + .../ui/borrowck/move-error-snippets.stderr | 2 +- .../ui/borrowck/mut-borrow-of-mut-ref.stderr | 2 +- .../borrowck/mut-borrow-outside-loop.stderr | 4 +- ...regions-bound-missing-bound-in-impl.stderr | 8 +- .../ui/borrowck/two-phase-across-loop.stderr | 2 +- ...wo-phase-cannot-nest-mut-self-calls.stderr | 19 +- .../ui/borrowck/two-phase-multi-mut.stderr | 5 +- ...-sharing-interference-2.migrate2015.stderr | 5 +- ...-sharing-interference-2.migrate2018.stderr | 5 +- ...tion-sharing-interference-2.nll2015.stderr | 10 +- ...tion-sharing-interference-2.nll2018.stderr | 10 +- ...interference-future-compat-lint.nll.stderr | 15 +- ...ing-interference-future-compat-lint.stderr | 10 +- src/test/ui/borrowck/two-phase-sneaky.stderr | 2 +- .../two-phase-surprise-no-conflict.stderr | 37 +- ...ove-upvar-from-non-once-ref-closure.stderr | 14 +- src/test/ui/box/into-boxed-slice-fail.stderr | 8 +- src/test/ui/box/leak-alloc.stderr | 2 +- src/test/ui/c-variadic/issue-86053-1.stderr | 4 +- src/test/ui/c-variadic/issue-86053-2.stderr | 2 +- .../cancel-clean-via-immediate-rvalue-ref.rs | 6 +- .../cannot-mutate-captured-non-mut-var.stderr | 2 +- src/test/ui/cast/issue-89497.fixed | 10 + src/test/ui/cast/issue-89497.rs | 10 + src/test/ui/cast/issue-89497.stderr | 15 + src/test/ui/chalkify/type_inference.stderr | 4 +- src/test/ui/class-cast-to-trait.rs | 6 +- src/test/ui/cleanup-arm-conditional.rs | 4 +- src/test/ui/cleanup-rvalue-scopes.rs | 5 +- ...nup-rvalue-temp-during-incomplete-alloc.rs | 4 +- src/test/ui/clone-with-exterior.rs | 4 +- src/test/ui/close-over-big-then-small-data.rs | 6 +- .../expect-fn-supply-fn.nll.stderr | 2 - .../expect-fn-supply-fn.stderr | 8 +- src/test/ui/closure-expected.stderr | 4 +- .../borrowck/borrowck-closures-mut-and-imm.rs | 4 +- .../diagnostics/liveness.rs | 1 + .../diagnostics/liveness.stderr | 14 +- .../liveness_unintentional_copy.rs | 1 + .../liveness_unintentional_copy.stderr | 6 +- .../2229_closure_analysis/issue-90465.fixed | 35 + .../2229_closure_analysis/issue-90465.rs | 34 + .../2229_closure_analysis/issue-90465.stderr | 26 + .../migrations/auto_traits.fixed | 13 +- .../migrations/auto_traits.rs | 13 +- .../migrations/auto_traits.stderr | 19 +- .../closure-body-macro-fragment.stderr | 2 +- .../issue-90024-adt-correct-subst.rs | 37 + .../migrations/mir_calls_to_shims.fixed | 5 +- .../migrations/mir_calls_to_shims.rs | 5 +- .../migrations/mir_calls_to_shims.stderr | 7 +- .../migrations/multi_diagnostics.fixed | 26 +- .../migrations/multi_diagnostics.rs | 26 +- .../migrations/multi_diagnostics.stderr | 35 +- .../struct-pattern-matching-with-methods.rs | 1 + .../run_pass/unsafe_ptr.rs | 2 + .../ui/closures/closure-bounds-subtype.stderr | 4 +- .../expect-region-supply-region-2.nll.stderr | 2 - .../expect-region-supply-region-2.stderr | 8 +- .../closures/coerce-unsafe-to-closure.stderr | 4 +- .../ui/{issues => closures}/issue-78720.rs | 0 .../{issues => closures}/issue-78720.stderr | 0 src/test/ui/closures/issue-87814-2.rs | 1 - .../wrong-abi-location-1.stderr | 2 +- .../wrong-abi-location-2.stderr | 2 +- .../ui/codemap_tests/bad-format-args.stderr | 2 +- src/test/ui/codemap_tests/issue-11715.stderr | 2 +- src/test/ui/codemap_tests/issue-28308.stderr | 2 +- src/test/ui/codemap_tests/one_line.stderr | 5 +- src/test/ui/coercion/coerce-expect-unsized.rs | 1 - ...ce-issue-49593-box-never.nofallback.stderr | 19 + .../coercion/coerce-issue-49593-box-never.rs | 10 +- src/test/ui/coercion/issue-88097.rs | 31 + ...ce-impl-trait-for-trait-object-safe.stderr | 2 +- .../coherence-unsafe-trait-object-impl.stderr | 4 +- .../ui/coherence/coherence_inherent.stderr | 6 +- .../ui/coherence/coherence_inherent_cc.stderr | 6 +- src/test/ui/command/command-pre-exec.rs | 25 +- src/test/ui/compile_error_macro.stderr | 2 +- .../cfg-attr-syntax-validation.stderr | 4 +- ...r-unknown-attribute-macro-expansion.stderr | 2 +- src/test/ui/const-generics/broken-mir-2.rs | 3 + .../expose-default-substs-param-env.rs | 9 + .../abstract-consts-as-cast-5.rs | 11 + .../abstract-consts-as-cast-5.stderr | 10 + ...y-size-in-generic-struct-param.full.stderr | 3 +- .../generic_const_exprs/closures.stderr | 3 +- .../const_eval_resolve_canonical.rs | 29 + .../generic_const_exprs/let-bindings.stderr | 10 +- .../object-safety-err-ret.stderr | 2 +- .../unify-op-with-fn-call.rs | 35 + .../unify-op-with-fn-call.stderr | 10 + .../generic_const_exprs/unused_expr.stderr | 15 +- .../issues/issue-67375.full.stderr | 6 +- .../issues/issue-67945-2.full.stderr | 4 +- .../ui/const-generics/issues/issue-82956.rs | 33 + .../const-generics/issues/issue-82956.stderr | 21 + .../ui/const-generics/issues/issue-84659.rs | 12 + .../const-generics/issues/issue-84659.stderr | 10 + .../ui/const-generics/issues/issue-86530.rs | 20 + .../const-generics/issues/issue-86530.stderr | 20 + .../ui/const-generics/issues/issue-86535-2.rs | 19 + .../ui/const-generics/issues/issue-86535.rs | 20 + .../ui/const-generics/issues/issue-87493.rs | 14 + .../const-generics/issues/issue-87493.stderr | 28 + .../ui/const-generics/issues/issue-89334.rs | 16 + .../issue-89013-no-assoc.rs | 16 + .../issue-89013-no-assoc.stderr | 14 + .../issue-89013-no-kw.rs | 17 + .../issue-89013-no-kw.stderr | 18 + .../parser-error-recovery/issue-89013-type.rs | 16 + .../issue-89013-type.stderr | 8 + .../parser-error-recovery/issue-89013.rs | 18 + .../parser-error-recovery/issue-89013.stderr | 30 + .../sneaky-array-repeat-expr.rs | 32 + .../sneaky-array-repeat-expr.stderr | 18 + .../type-dependent/type-mismatch.full.stderr | 2 +- .../type-dependent/type-mismatch.min.stderr | 2 +- .../ui/const-generics/unused_braces.stderr | 7 +- src/test/ui/consts/const-eval/const_panic.rs | 9 +- .../ui/consts/const-eval/const_panic.stderr | 58 +- .../ui/consts/const-eval/const_panic_2021.rs | 17 +- .../consts/const-eval/const_panic_2021.stderr | 58 +- .../const-eval/const_panic_libcore_bin.rs | 1 - .../const-eval/const_panic_libcore_bin.stderr | 12 +- .../const-eval/const_panic_track_caller.rs | 1 - .../const_panic_track_caller.stderr | 8 +- .../const-eval/const_raw_ptr_ops.stderr | 4 +- .../const-eval/feature-gate-const_panic.rs | 10 - .../feature-gate-const_panic.stderr | 33 - .../const-eval/match-test-ptr-null.stderr | 2 +- .../const-eval/panic-assoc-never-type.rs | 1 - .../const-eval/panic-assoc-never-type.stderr | 4 +- .../ui/consts/const-eval/panic-never-type.rs | 1 - .../consts/const-eval/panic-never-type.stderr | 4 +- src/test/ui/consts/const-eval/unwind-abort.rs | 2 +- .../const-extern-fn-min-const-fn.stderr | 2 +- .../const-external-macro-const-err.stderr | 2 +- src/test/ui/consts/const-float-bits-conv.rs | 1 - src/test/ui/consts/const-float-classify.rs | 1 - src/test/ui/consts/const-variant-count.rs | 2 +- src/test/ui/consts/const_fn_trait_bound.rs | 4 +- .../consts/const_fn_trait_bound.stock.stderr | 4 +- .../const_in_pattern/issue-73431.stderr | 1 + .../const_in_pattern/issue-78057.stderr | 5 +- src/test/ui/consts/const_let_assign3.stderr | 2 +- .../ui/consts/const_unsafe_unreachable.rs | 4 +- .../ui/consts/const_unsafe_unreachable_ub.rs | 3 +- .../consts/const_unsafe_unreachable_ub.stderr | 6 +- src/test/ui/consts/control-flow/assert.rs | 10 +- ...ssert.const_panic.stderr => assert.stderr} | 4 +- .../consts/control-flow/assert.stock.stderr | 23 - src/test/ui/consts/control-flow/basics.rs | 2 - .../consts/control-flow/short-circuit-let.rs | 2 - .../ui/consts/control-flow/short-circuit.rs | 2 - src/test/ui/consts/issue-17458.stderr | 2 +- src/test/ui/{issues => consts}/issue-23833.rs | 0 src/test/ui/consts/issue-25826.stderr | 2 +- src/test/ui/consts/issue-32829.rs | 2 +- src/test/ui/consts/issue-32829.stderr | 8 +- src/test/ui/{issues => consts}/issue-34784.rs | 0 ...issue-52023-array-size-pointer-cast.stderr | 2 +- .../consts/issue-66693-panic-in-array-len.rs | 2 - .../issue-66693-panic-in-array-len.stderr | 6 +- src/test/ui/consts/issue-66693.rs | 2 - src/test/ui/consts/issue-66693.stderr | 8 +- src/test/ui/consts/issue-76064.rs | 4 +- src/test/ui/consts/issue-76064.stderr | 10 +- src/test/ui/consts/issue-88071.rs | 21 + src/test/ui/consts/issue-89088.rs | 22 + .../min_const_fn/cmp_fn_pointers.stderr | 2 +- .../ui/consts/min_const_fn/min_const_fn.rs | 10 +- .../consts/min_const_fn/min_const_fn.stderr | 39 +- .../consts/min_const_fn/min_const_fn_dyn.rs | 4 +- .../min_const_fn/min_const_fn_dyn.stderr | 10 +- .../min_const_fn_libstd_stability.stderr | 6 +- ...in_const_unsafe_fn_libstd_stability.stderr | 6 +- ...n_const_unsafe_fn_libstd_stability2.stderr | 6 +- src/test/ui/consts/miri_unleashed/box.rs | 2 +- src/test/ui/consts/miri_unleashed/box.stderr | 2 +- ..._refers_to_static_cross_crate.32bit.stderr | 6 - ..._refers_to_static_cross_crate.64bit.stderr | 6 - .../consts/miri_unleashed/inline_asm.stderr | 8 +- .../ui/consts/not_const_clusure_in_const.rs | 9 + src/test/ui/consts/ptr_comparisons.rs | 1 - src/test/ui/consts/ptr_comparisons.stderr | 10 +- src/test/ui/consts/ptr_is_null.rs | 2 +- .../consts/refs_check_const_eq-issue-88384.rs | 25 + .../refs_check_const_eq-issue-88384.stderr | 11 + .../refs_check_const_value_eq-issue-88876.rs | 12 + src/test/ui/consts/unwind-abort.rs | 2 +- .../auxiliary/crateresolve2-1.rs | 5 + .../auxiliary/crateresolve2-2.rs | 5 + .../auxiliary/crateresolve2-3.rs | 5 + src/test/ui/crate-loading/crateresolve1.rs | 9 +- .../ui/crate-loading/crateresolve1.stderr | 14 + src/test/ui/crate-loading/crateresolve2.rs | 14 + .../ui/crate-loading/crateresolve2.stderr | 14 + src/test/ui/crate-method-reexport-grrrrrrr.rs | 4 +- .../cross-crate/auxiliary/cci_nested_lib.rs | 6 +- src/test/ui/cross-crate/cci_borrow.rs | 4 +- src/test/ui/cross/cross-borrow-trait.stderr | 6 +- .../cross-crate-macro-backtrace/main.stderr | 2 +- .../ui/cross/cross-file-errors/main.stderr | 4 +- .../dep-graph/dep-graph-assoc-type-codegen.rs | 3 +- .../dep-graph-assoc-type-codegen.stderr | 2 +- .../ui/dep-graph/dep-graph-caller-callee.rs | 3 +- .../dep-graph/dep-graph-caller-callee.stderr | 4 +- .../dep-graph/dep-graph-struct-signature.rs | 3 +- .../dep-graph-struct-signature.stderr | 70 +- ...graph-trait-impl-two-traits-same-method.rs | 3 +- ...h-trait-impl-two-traits-same-method.stderr | 4 +- .../dep-graph-trait-impl-two-traits.rs | 3 +- .../dep-graph-trait-impl-two-traits.stderr | 4 +- src/test/ui/dep-graph/dep-graph-trait-impl.rs | 3 +- .../ui/dep-graph/dep-graph-trait-impl.stderr | 10 +- src/test/ui/dep-graph/dep-graph-type-alias.rs | 3 +- .../ui/dep-graph/dep-graph-type-alias.stderr | 24 +- .../ui/dep-graph/dep-graph-variance-alias.rs | 3 +- .../dep-graph/dep-graph-variance-alias.stderr | 2 +- .../ui/deprecation/deprecation-lint-2.stderr | 2 +- src/test/ui/deref.rs | 4 +- src/test/ui/derives/clone-debug-dead-code.rs | 45 + .../ui/derives/clone-debug-dead-code.stderr | 38 + .../derives/derive-assoc-type-not-impl.stderr | 4 + ...-span-PartialEq-enum-struct-variant.stderr | 20 +- .../derives-span-PartialEq-enum.stderr | 20 +- .../derives-span-PartialEq-struct.stderr | 20 +- ...derives-span-PartialEq-tuple-struct.stderr | 20 +- src/test/ui/derives/deriving-copyclone.stderr | 33 +- ...eriving-no-inner-impl-error-message.stderr | 20 +- .../deriving/deriving-clone-generic-struct.rs | 2 + src/test/ui/deriving/deriving-clone-struct.rs | 2 + .../deriving/deriving-clone-tuple-struct.rs | 2 + src/test/ui/deriving/deriving-default-box.rs | 2 - src/test/ui/deriving/deriving-in-fn.rs | 3 + .../ui/{issues => deriving}/issue-3935.rs | 0 src/test/ui/deriving/issue-89188-gat-hrtb.rs | 39 + src/test/ui/destructure-trait-ref.rs | 6 +- src/test/ui/destructure-trait-ref.stderr | 6 +- .../note-unsupported.stderr | 17 +- .../ui/did_you_mean/bad-assoc-expr.stderr | 2 +- src/test/ui/did_you_mean/issue-34126.stderr | 5 +- src/test/ui/did_you_mean/issue-35937.stderr | 2 +- src/test/ui/did_you_mean/issue-38147-1.stderr | 2 +- src/test/ui/did_you_mean/issue-38147-2.stderr | 2 +- src/test/ui/did_you_mean/issue-38147-3.stderr | 2 +- src/test/ui/did_you_mean/issue-38147-4.stderr | 2 +- .../issue-39802-show-5-trait-impls.stderr | 12 +- src/test/ui/did_you_mean/issue-40823.stderr | 2 +- .../issue-87830-try-brackets-for-arrays.rs | 17 + ...issue-87830-try-brackets-for-arrays.stderr | 49 + .../ui/did_you_mean/recursion_limit.stderr | 2 +- .../did_you_mean/recursion_limit_deref.stderr | 2 +- .../did_you_mean/recursion_limit_macro.stderr | 4 +- .../macro-expanded-mod.stderr | 2 +- src/test/ui/discrim/discrim-ill-typed.stderr | 16 +- .../dollar-crate-is-keyword-2.stderr | 6 +- .../dollar-crate-is-keyword.stderr | 8 +- src/test/ui/drop/drop-on-empty-block-exit.rs | 4 +- src/test/ui/drop/drop-struct-as-object.rs | 4 +- src/test/ui/drop/drop-trait-enum.rs | 8 +- .../dropck/drop-with-active-borrows-1.stderr | 2 +- .../dropck/drop-with-active-borrows-2.stderr | 2 +- .../reject-specialized-drops-8142.stderr | 6 +- .../relate_lt_in_type_outlives_bound.rs | 13 + .../relate_lt_in_type_outlives_bound.stderr | 17 + src/test/ui/dst/dst-bad-coercions.stderr | 12 +- src/test/ui/duplicate_doc_alias.rs | 9 + src/test/ui/duplicate_doc_alias.stderr | 24 + .../dst-trait-tuple.rs | 1 - .../ui/dynamically-sized-types/dst-tuple.rs | 3 +- .../ui/editions/edition-imports-2015.stderr | 2 +- .../ui/editions/edition-imports-2018.stderr | 2 +- .../edition-imports-virtual-2015-gated.stderr | 2 +- src/test/ui/empty/empty-comment.stderr | 2 +- .../discriminant_value-wrapper.rs | 3 + src/test/ui/enum-discriminant/issue-90038.rs | 21 + .../ui/enum-discriminant/niche-prefer-zero.rs | 14 + src/test/ui/enum-discriminant/niche.rs | 2 - src/test/ui/error-codes/E0034.stderr | 8 +- src/test/ui/error-codes/E0038.stderr | 2 +- src/test/ui/error-codes/E0055.stderr | 2 +- src/test/ui/error-codes/E0161.edition.stderr | 2 +- src/test/ui/error-codes/E0161.migrate.stderr | 2 +- src/test/ui/error-codes/E0161.nll.stderr | 2 +- src/test/ui/error-codes/E0161.zflags.stderr | 2 +- src/test/ui/error-codes/E0221.stderr | 13 +- src/test/ui/error-codes/E0225.stderr | 4 +- src/test/ui/error-codes/E0275.stderr | 2 +- src/test/ui/error-codes/E0277.stderr | 4 +- src/test/ui/error-codes/E0308-2.stderr | 6 +- src/test/ui/error-codes/E0395.stderr | 2 +- src/test/ui/error-codes/E0407.stderr | 5 +- src/test/ui/error-codes/E0439.rs | 8 - src/test/ui/error-codes/E0439.stderr | 9 - src/test/ui/error-codes/E0464.rs | 15 + src/test/ui/error-codes/E0464.stderr | 14 + src/test/ui/error-codes/E0478.stderr | 4 +- src/test/ui/error-codes/E0490.stderr | 12 +- src/test/ui/error-codes/E0499.stderr | 2 +- src/test/ui/error-codes/E0502.nll.stderr | 2 +- src/test/ui/error-codes/E0502.stderr | 2 +- src/test/ui/error-codes/E0503.stderr | 2 +- src/test/ui/error-codes/E0505.stderr | 2 +- src/test/ui/error-codes/E0507.stderr | 2 +- src/test/ui/error-codes/E0605.stderr | 5 +- src/test/ui/error-codes/E0660.stderr | 4 +- .../error-codes/auxiliary/crateresolve1-1.rs | 5 + .../error-codes/auxiliary/crateresolve1-2.rs | 5 + .../error-codes/auxiliary/crateresolve1-3.rs | 5 + .../ui/error-codes/e0119/complex-impl.stderr | 2 +- src/test/ui/error-festival.stderr | 17 +- .../ui/error-should-say-copy-not-pod.stderr | 4 +- ...sue-89280-emitter-overflow-splice-lines.rs | 10 + ...89280-emitter-overflow-splice-lines.stderr | 23 + .../explicit-self-lifetime-mismatch.stderr | 8 +- src/test/ui/expr-block-generic-unique1.rs | 3 +- src/test/ui/expr-block-generic-unique2.rs | 3 +- src/test/ui/expr-block-unique.rs | 3 +- src/test/ui/expr-if-unique.rs | 4 +- src/test/ui/expr/if/if-let.stderr | 4 +- .../missing_braces_around_block.fixed | 19 + .../missing_braces_around_block.rs | 19 + .../missing_braces_around_block.stderr | 38 + .../malformed_closure/ruby_style_closure.rs | 16 + .../ruby_style_closure.stderr | 27 + src/test/ui/extenv/extenv-no-args.stderr | 2 +- .../extenv/extenv-not-defined-custom.stderr | 2 +- .../extenv/extenv-not-defined-default.stderr | 2 +- .../ui/extenv/extenv-too-many-args.stderr | 2 +- .../ui/extern/extern-wrong-value-type.stderr | 4 +- src/test/ui/extoption_env-no-args.stderr | 2 +- .../ui/extoption_env-too-many-args.stderr | 2 +- ...-allow-internal-unsafe-nested-macro.stderr | 2 +- ...llow-internal-unstable-nested-macro.stderr | 2 +- .../feature-gate-closure_track_caller.rs | 7 + .../feature-gate-closure_track_caller.stderr | 21 + .../feature-gate-concat_idents2.stderr | 2 +- ...te-non_exhaustive_omitted_patterns_lint.rs | 31 + ...on_exhaustive_omitted_patterns_lint.stderr | 93 + ...ature-gate-object_safe_for_dispatch.stderr | 4 +- .../feature-gates/feature-gate-try_reserve.rs | 4 - .../feature-gate-try_reserve.stderr | 12 - ...-gate-unboxed-closures-manual-impls.stderr | 4 +- .../feature-gate-unboxed-closures.stderr | 3 +- .../feature-gate-unsized_fn_params.stderr | 4 +- .../thread-local-const-init.stderr | 2 +- .../ui/feature-gates/trace_macros-gate.stderr | 4 +- ...loat-literal-inference-restrictions.stderr | 2 +- src/test/ui/fmt/ifmt-bad-format-args.stderr | 2 +- src/test/ui/fmt/issue-89173.rs | 14 + src/test/ui/fmt/issue-89173.stderr | 18 + src/test/ui/fn/fn-trait-formatting.rs | 10 +- src/test/ui/fn/fn-trait-formatting.stderr | 18 +- ...d-bounds-unnorm-associated-type.nll.stderr | 14 + .../implied-bounds-unnorm-associated-type.rs | 22 + ...plied-bounds-unnorm-associated-type.stderr | 13 + .../cleanup-rvalue-during-if-and-while.rs | 4 +- .../ui/future-incompatible-lint-group.stderr | 2 +- src/test/ui/gated-bad-feature.stderr | 4 +- src/test/ui/generator/dropck-resume.stderr | 2 +- src/test/ui/generator/dropck.stderr | 2 +- src/test/ui/generator/issue-88653.rs | 19 + src/test/ui/generator/issue-88653.stderr | 12 + .../resume-arg-late-bound.nll.stderr | 5 + .../ui/generator/resume-arg-late-bound.stderr | 4 +- src/test/ui/generator/static-not-unpin.stderr | 4 +- src/test/ui/generator/yield-in-box.rs | 10 +- src/test/ui/generator/yield-in-box.stderr | 2 +- .../gat-in-trait-path.stderr | 2 +- .../generic-associated-types/impl_bounds.rs | 4 +- .../impl_bounds.stderr | 40 +- .../issue-67510-pass.stderr | 2 +- .../issue-76535.stderr | 4 +- ...113-lifetime-mismatch-dyn-trait-box.stderr | 6 +- .../issue-78671.stderr | 2 +- .../issue-79422.stderr | 4 +- .../generic-associated-types/issue-86787.rs | 4 +- .../issue-86787.stderr | 17 +- .../generic-associated-types/issue-87748.rs | 30 - .../generic-associated-types/issue-87750.rs | 22 + .../issue-87750.stderr | 9 + .../generic-associated-types/issue-88287.rs | 39 + .../generic-associated-types/issue-88360.rs | 19 + .../issue-88360.stderr | 20 + .../generic-associated-types/issue-88405.rs | 16 + .../missing-where-clause-on-trait.rs | 13 + .../missing-where-clause-on-trait.stderr | 11 + .../trait-objects.stderr | 2 +- .../unsatified-item-lifetime-bound.stderr | 6 +- .../unsatisfied-outlives-bound.stderr | 2 +- src/test/ui/generics/generic-alias-unique.rs | 3 +- .../ui/generics/generic-exterior-unique.rs | 3 +- src/test/ui/generics/generic-fn-unique.rs | 6 +- src/test/ui/generics/generic-object.rs | 3 +- src/test/ui/generics/generic-recursive-tag.rs | 9 +- src/test/ui/generics/generic-tag.rs | 3 +- src/test/ui/generics/generic-unique.rs | 3 +- .../ui/{ => generics}/mid-path-type-params.rs | 0 .../ui/generics/wrong-number-of-args.stderr | 88 +- ...pats-inclusive-dotdotdot-bad-syntax.stderr | 2 +- ...lf-open-range-pats-inclusive-no-end.stderr | 4 +- .../hashmap-iter-value-lifetime.nll.stderr | 15 - .../hashmap-iter-value-lifetime.stderr | 2 +- .../ui/hashmap/hashmap-lifetimes.nll.stderr | 13 - src/test/ui/hashmap/hashmap-lifetimes.stderr | 2 +- .../issue-62529-1.stderr | 26 +- .../normalize-under-binder/issue-80706.rs | 70 + .../normalize-under-binder/issue-80956.rs | 21 + .../normalize-under-binder/issue-81809.rs | 21 + .../normalize-under-binder/issue-85455.rs | 18 + .../normalize-under-binder/issue-85455.stderr | 14 + .../normalize-under-binder/issue-89118.rs | 32 + .../normalize-under-binder/issue-89118.stderr | 63 + ...ound_a_b_ret_a_vs_bound_a_ret_a.nll.stderr | 4 +- .../hr-subtype.bound_a_vs_free_x.nll.stderr | 2 +- ...pe.bound_inv_a_b_vs_bound_inv_a.nll.stderr | 8 +- ...hr-subtype.free_inv_x_vs_free_inv_y.stderr | 8 +- .../hr-subtype.free_x_vs_free_y.stderr | 4 +- .../ui/hrtb/hrtb-debruijn-in-receiver.stderr | 4 +- ...igher-ranker-supertraits-transitive.stderr | 4 +- .../hrtb-higher-ranker-supertraits.stderr | 8 +- .../ui/hrtb/hrtb-just-for-static.nll.stderr | 2 - .../hrtb/hrtb-perfect-forwarding.nll.stderr | 2 - src/test/ui/hrtb/issue-88446.rs | 35 + src/test/ui/hygiene/assoc_item_ctxt.stderr | 9 +- .../ui/hygiene/duplicate_lifetimes.stderr | 4 +- .../extern-prelude-from-opaque-fail.stderr | 4 +- src/test/ui/hygiene/fields-definition.stderr | 2 +- .../ui/hygiene/fields-numeric-borrowck.stderr | 2 +- src/test/ui/hygiene/generate-mod.stderr | 8 +- src/test/ui/hygiene/globs.stderr | 10 +- src/test/ui/hygiene/hygienic-label-1.stderr | 2 +- src/test/ui/hygiene/hygienic-label-3.stderr | 2 +- .../ui/hygiene/hygienic-labels-in-let.stderr | 32 +- src/test/ui/hygiene/hygienic-labels.stderr | 32 +- src/test/ui/hygiene/impl_items.stderr | 2 +- src/test/ui/hygiene/missing-self-diag.stderr | 2 +- .../ui/hygiene/no_implicit_prelude.stderr | 10 +- src/test/ui/hygiene/privacy-early.stderr | 4 +- src/test/ui/hygiene/trait_items.stderr | 8 +- .../dyn-trait.nll.stderr | 11 +- src/test/ui/impl-trait/auto-trait-leak.stderr | 4 +- .../ui/impl-trait/hidden-lifetimes.stderr | 22 +- .../multiple-lifetimes/error-handling-2.rs | 3 - .../error-handling-2.stderr | 12 +- .../multiple-lifetimes/error-handling.rs | 2 - .../multiple-lifetimes/error-handling.stderr | 2 +- .../ordinary-bounds-unrelated.nll.stderr | 9 +- .../ordinary-bounds-unsuited.nll.stderr | 9 +- ...t_outlive_least_region_or_bound.nll.stderr | 3 - .../impl-trait/region-escape-via-bound.stderr | 12 +- .../static-return-lifetime-infered.nll.stderr | 1 - .../type-arg-mismatch-due-to-impl-trait.rs | 0 ...type-arg-mismatch-due-to-impl-trait.stderr | 0 .../extern-prelude-extern-crate-fail.stderr | 2 +- ...e-extern-crate-restricted-shadowing.stderr | 4 +- src/test/ui/imports/glob-resolve1.stderr | 60 +- src/test/ui/imports/import-crate-var.stderr | 2 +- src/test/ui/imports/issue-30560.stderr | 2 +- src/test/ui/imports/issue-4366-2.stderr | 7 +- .../local-modularized-tricky-fail-1.stderr | 8 +- .../local-modularized-tricky-fail-2.stderr | 4 +- .../ui/imports/shadow_builtin_macros.stderr | 2 +- .../in-band-lifetimes/elided-lifetimes.stderr | 2 +- src/test/ui/indexing-requires-a-uint.stderr | 2 +- src/test/ui/inference/deref-suggestion.stderr | 2 +- src/test/ui/inference/issue-71309.rs | 7 + src/test/ui/inference/issue-71309.stderr | 15 + src/test/ui/infinite/infinite-autoderef.rs | 4 +- .../ui/infinite/infinite-autoderef.stderr | 17 +- .../infinite/infinite-macro-expansion.stderr | 2 +- .../no-overlap.rs | 19 + src/test/ui/init-res-into-things.rs | 7 +- .../integer-literal-suffix-inference.stderr | 280 +- .../internal/internal-unstable-noallow.stderr | 4 +- src/test/ui/internal/internal-unstable.stderr | 2 +- .../ui/intrinsics/const-eval-select-bad.rs | 36 + .../intrinsics/const-eval-select-bad.stderr | 65 + .../intrinsics/const-eval-select-stability.rs | 20 + .../const-eval-select-stability.stderr | 10 + .../ui/intrinsics/const-eval-select-x86_64.rs | 39 + src/test/ui/intrinsics/const-eval-select.rs | 26 + src/test/ui/intrinsics/intrinsic-atomics.rs | 3 +- .../intrinsics/panic-uninitialized-zeroed.rs | 11 +- .../ui/invalid/invalid-crate-type-macro.rs | 7 + .../invalid/invalid-crate-type-macro.stderr | 8 + src/test/ui/invalid_crate_type_syntax.stderr | 2 +- src/test/ui/issues/issue-10291.nll.stderr | 2 - src/test/ui/issues/issue-10291.stderr | 4 +- src/test/ui/issues/issue-10465.stderr | 6 +- src/test/ui/issues/issue-13359.stderr | 4 +- src/test/ui/issues/issue-13497-2.stderr | 15 +- src/test/ui/issues/issue-1362.stderr | 2 +- src/test/ui/issues/issue-14091-2.stderr | 19 +- src/test/ui/issues/issue-14091.stderr | 2 +- src/test/ui/issues/issue-1448-2.stderr | 2 +- src/test/ui/issues/issue-16098.stderr | 2 +- src/test/ui/issues/issue-16683.nll.stderr | 13 +- src/test/ui/issues/issue-16683.stderr | 4 +- src/test/ui/issues/issue-16966.stderr | 2 +- src/test/ui/issues/issue-17651.rs | 1 - src/test/ui/issues/issue-17651.stderr | 16 +- src/test/ui/issues/issue-17740.stderr | 8 +- src/test/ui/issues/issue-17758.nll.stderr | 13 +- src/test/ui/issues/issue-17758.stderr | 4 +- src/test/ui/issues/issue-17905-2.stderr | 8 +- src/test/ui/issues/issue-18294.stderr | 2 +- src/test/ui/issues/issue-18400.stderr | 2 +- src/test/ui/issues/issue-18959.stderr | 2 +- src/test/ui/issues/issue-19163.stderr | 6 +- src/test/ui/issues/issue-19358.rs | 3 + src/test/ui/issues/issue-19538.stderr | 4 +- src/test/ui/issues/issue-20413.stderr | 12 +- src/test/ui/issues/issue-20605.stderr | 8 +- .../ui/issues/issue-20831-debruijn.stderr | 8 +- src/test/ui/issues/issue-2150.stderr | 2 +- src/test/ui/issues/issue-21600.stderr | 2 +- src/test/ui/issues/issue-23122-2.stderr | 2 +- src/test/ui/issues/issue-23966.stderr | 4 +- src/test/ui/issues/issue-25076.stderr | 4 +- src/test/ui/issues/issue-25385.stderr | 2 +- src/test/ui/issues/issue-26093.stderr | 4 +- src/test/ui/issues/issue-26217.nll.stderr | 2 - src/test/ui/issues/issue-27942.stderr | 8 +- src/test/ui/issues/issue-28098.stderr | 16 +- src/test/ui/issues/issue-29084.stderr | 2 +- src/test/ui/issues/issue-2995.stderr | 5 +- src/test/ui/issues/issue-30355.stderr | 4 +- src/test/ui/issues/issue-31011.stderr | 2 +- src/test/ui/issues/issue-31076.rs | 2 +- src/test/ui/issues/issue-31076.stderr | 4 +- src/test/ui/issues/issue-32655.stderr | 2 +- src/test/ui/issues/issue-32782.stderr | 2 +- src/test/ui/issues/issue-32963.stderr | 4 +- src/test/ui/issues/issue-34255-1.rs | 2 +- src/test/ui/issues/issue-34255-1.stderr | 19 +- src/test/ui/issues/issue-37884.stderr | 4 +- src/test/ui/issues/issue-3794.rs | 1 + src/test/ui/issues/issue-3820.stderr | 17 +- src/test/ui/issues/issue-39848.stderr | 2 +- src/test/ui/issues/issue-41726.stderr | 2 +- src/test/ui/issues/issue-42106.stderr | 4 +- src/test/ui/issues/issue-42954.stderr | 2 +- src/test/ui/issues/issue-4335.stderr | 5 +- src/test/ui/issues/issue-44405.stderr | 2 +- src/test/ui/issues/issue-4736.stderr | 9 +- src/test/ui/issues/issue-47646.stderr | 2 +- src/test/ui/issues/issue-47706-trait.stderr | 4 +- src/test/ui/issues/issue-47706.stderr | 8 +- .../option-as_deref.stderr | 1 - .../option-as_deref_mut.stderr | 2 +- .../result-as_deref.stderr | 1 - .../result-as_deref_mut.stderr | 2 +- src/test/ui/issues/issue-50403.stderr | 2 +- src/test/ui/issues/issue-51102.stderr | 5 +- ...ue-51632-try-desugar-incompatible-types.rs | 2 +- ...1632-try-desugar-incompatible-types.stderr | 3 +- src/test/ui/issues/issue-51848.stderr | 2 +- .../issue-52126-assign-op-invariance.stderr | 2 +- src/test/ui/issues/issue-52213.stderr | 4 +- src/test/ui/issues/issue-52533-1.stderr | 4 +- src/test/ui/issues/issue-52533.stderr | 4 +- src/test/ui/issues/issue-53251.stderr | 4 +- src/test/ui/issues/issue-54943.nll.stderr | 2 - src/test/ui/issues/issue-55796.nll.stderr | 4 - src/test/ui/issues/issue-55796.stderr | 8 +- src/test/ui/issues/issue-56031.stderr | 10 + src/test/ui/issues/issue-5791.rs | 14 - src/test/ui/issues/issue-5791.stderr | 21 - src/test/ui/issues/issue-59488.stderr | 4 +- src/test/ui/issues/issue-59494.stderr | 4 +- src/test/ui/issues/issue-60218.stderr | 6 +- src/test/ui/issues/issue-60283.stderr | 13 +- src/test/ui/issues/issue-61108.stderr | 2 +- src/test/ui/issues/issue-61882-2.stderr | 2 +- src/test/ui/issues/issue-62375.stderr | 10 +- src/test/ui/issues/issue-65230.rs | 11 + src/test/ui/issues/issue-65230.stderr | 18 + src/test/ui/issues/issue-6596-1.stderr | 2 +- src/test/ui/issues/issue-6596-2.stderr | 2 +- src/test/ui/issues/issue-66353.stderr | 4 +- .../issue-68091-unicode-ident-after-if.stderr | 2 +- ...70724-add_type_neq_err_label-unwrap.stderr | 6 +- src/test/ui/issues/issue-75777.nll.stderr | 2 - src/test/ui/issues/issue-75777.stderr | 4 +- src/test/ui/issues/issue-7970a.stderr | 2 +- src/test/ui/issues/issue-80607.stderr | 9 +- src/test/ui/issues/issue-81584.stderr | 2 +- src/test/ui/issues/issue-86865.rs | 11 + src/test/ui/issues/issue-86865.stderr | 18 + src/test/ui/issues/issue-87199.stderr | 4 +- src/test/ui/issues/issue-8761.stderr | 4 +- .../iterators/into-iter-on-arrays-2018.stderr | 10 +- .../iterators/into-iter-on-arrays-lint.stderr | 24 +- .../ui/kindck/kindck-impl-type-params-2.rs | 6 +- .../kindck/kindck-impl-type-params-2.stderr | 4 +- src/test/ui/kindck/kindck-impl-type-params.rs | 6 +- .../kindck-inherited-copy-bound.curr.stderr | 4 +- ...copy-bound.object_safe_for_dispatch.stderr | 4 +- .../ui/kindck/kindck-inherited-copy-bound.rs | 6 +- .../lang-items/fn-fn_mut-call-ill-formed.rs | 27 + .../fn-fn_mut-call-ill-formed.stderr | 14 + src/test/ui/lang-items/issue-83471.rs | 23 + src/test/ui/lang-items/issue-83471.stderr | 51 + .../lang-item-generic-requirements.rs | 16 +- .../lang-item-generic-requirements.stderr | 23 +- src/test/ui/last-use-is-capture.rs | 4 +- src/test/ui/leak-unique-as-tydesc.rs | 7 +- .../lifetimes/borrowck-let-suggestion.stderr | 2 +- src/test/ui/lifetimes/issue-77175.rs | 19 + .../ui/lifetimes/issue-79187-2.nll.stderr | 15 + src/test/ui/lifetimes/issue-79187-2.stderr | 4 +- src/test/ui/lifetimes/issue-79187.nll.stderr | 5 + ...etime-bound-will-change-warning.nll.stderr | 22 +- .../lifetime-bound-will-change-warning.stderr | 4 +- ...oth-anon-regions-using-fn-items.nll.stderr | 16 +- ...non-regions-using-trait-objects.nll.stderr | 16 +- .../lifetime-errors/issue_74400.nll.stderr | 35 + .../lifetimes/lifetime-errors/issue_74400.rs | 13 + .../lifetime-errors/issue_74400.stderr | 11 + ...ime-used-in-debug-macro-issue-70152.stderr | 22 +- .../{ => lint}/enable-unstable-lib-feature.rs | 0 .../enable-unstable-lib-feature.stderr | 0 src/test/ui/{issues => lint}/issue-57410.rs | 0 ...0819-dont-override-forbid-in-same-scope.rs | 2 - ...-dont-override-forbid-in-same-scope.stderr | 13 +- src/test/ui/lint/issue-79546-fuel-ice.rs | 8 + src/test/ui/{issues => lint}/issue-79744.rs | 0 .../ui/{issues => lint}/issue-79744.stderr | 0 src/test/ui/lint/issue-87308.rs | 12 + src/test/ui/lint/issue-87308.stdout | 14 + src/test/ui/lint/issue-89469.rs | 20 + ...ext-direction-codepoint-in-comment-lint.rs | 9 + .../ui/lint/known-tool-in-submodule/root.rs | 10 + .../lint/known-tool-in-submodule/submodule.rs | 4 + src/test/ui/lint/lint-ctypes-fn.rs | 4 + src/test/ui/lint/lint-ctypes-fn.stderr | 40 +- src/test/ui/lint/lint-ctypes.rs | 2 + src/test/ui/lint/lint-ctypes.stderr | 59 +- .../ui/lint/lint-enum-intrinsics-non-enums.rs | 67 + .../lint-enum-intrinsics-non-enums.stderr | 95 + src/test/ui/lint/lint-malformed.stderr | 2 +- src/test/ui/lint/lint-owned-heap-memory.rs | 4 +- .../ui/lint/lint-owned-heap-memory.stderr | 4 +- src/test/ui/lint/lint-stability2.stderr | 2 +- .../ui/lint/lint-unnecessary-parens.stderr | 135 +- .../ui/lint/lints-in-foreign-macros.stderr | 2 +- src/test/ui/lint/must_not_suspend/boxed.rs | 25 + .../ui/lint/must_not_suspend/boxed.stderr | 26 + src/test/ui/lint/must_not_suspend/dedup.rs | 20 + .../ui/lint/must_not_suspend/dedup.stderr | 19 + .../feature-gate-must_not_suspend.rs | 9 + .../feature-gate-must_not_suspend.stderr | 12 + src/test/ui/lint/must_not_suspend/gated.rs | 14 + .../ui/lint/must_not_suspend/gated.stderr | 54 + src/test/ui/lint/must_not_suspend/generic.rs | 20 + src/test/ui/lint/must_not_suspend/handled.rs | 28 + .../ui/lint/must_not_suspend/issue-89562.rs | 19 + src/test/ui/lint/must_not_suspend/mutex.rs | 13 + .../ui/lint/must_not_suspend/mutex.stderr | 26 + .../ui/lint/must_not_suspend/other_items.rs | 8 + .../lint/must_not_suspend/other_items.stderr | 10 + src/test/ui/lint/must_not_suspend/ref.rs | 29 + src/test/ui/lint/must_not_suspend/ref.stderr | 27 + src/test/ui/lint/must_not_suspend/return.rs | 9 + .../ui/lint/must_not_suspend/return.stderr | 12 + src/test/ui/lint/must_not_suspend/trait.rs | 28 + .../ui/lint/must_not_suspend/trait.stderr | 37 + src/test/ui/lint/must_not_suspend/unit.rs | 25 + src/test/ui/lint/must_not_suspend/unit.stderr | 26 + src/test/ui/lint/must_not_suspend/warn.rs | 26 + src/test/ui/lint/must_not_suspend/warn.stderr | 26 + src/test/ui/lint/outer-forbid.rs | 3 +- src/test/ui/lint/outer-forbid.stderr | 18 +- .../lint-mixed-script-confusables.rs | 6 +- .../lint-mixed-script-confusables.stderr | 18 +- src/test/ui/lint/suggestions.stderr | 7 +- src/test/ui/lint/unaligned_references.stderr | 2 +- .../ui/lint/unreachable_pub-pub_crate.stderr | 2 +- src/test/ui/lint/unreachable_pub.stderr | 2 +- .../auxiliary/forge_unsafe_block.rs | 16 + .../ui/lint/unsafe_code/forge_unsafe_block.rs | 16 + ...47390-unused-variable-in-struct-pattern.rs | 4 +- .../issue-54538-unused-parens-lint.stderr | 191 +- ...ssue-74883-unused-paren-baren-yield.stderr | 46 +- .../lint/unused/issue-88519-unused-paren.rs | 94 + .../ui/lint/unused/unused-macro-rules.stderr | 2 +- src/test/ui/lint/unused_braces.stderr | 38 +- src/test/ui/lint/unused_braces_borrow.stderr | 7 +- .../lint/unused_parens_json_suggestion.stderr | 9 +- ...nused_parens_remove_json_suggestion.stderr | 89 +- src/test/ui/list.rs | 6 +- .../ui/liveness/liveness-move-call-arg.rs | 6 +- .../ui/liveness/liveness-move-call-arg.stderr | 4 +- src/test/ui/liveness/liveness-move-in-loop.rs | 6 +- .../ui/liveness/liveness-move-in-loop.stderr | 2 +- .../ui/liveness/liveness-move-in-while.rs | 6 +- .../ui/liveness/liveness-move-in-while.stderr | 2 +- .../liveness-return-last-stmt-semi.stderr | 7 +- .../ui/liveness/liveness-use-after-move.rs | 6 +- .../liveness/liveness-use-after-move.stderr | 3 +- .../llvm-asm/inline-asm-bad-constraint.stderr | 2 +- .../ui/{issues => llvm-asm}/issue-37433.rs | 0 .../{issues => llvm-asm}/issue-37433.stderr | 0 src/test/ui/llvm-asm/issue-62046.stderr | 2 +- .../ui/llvm-asm/llvm-asm-parse-errors.stderr | 2 +- .../loops/loops-reject-duplicate-labels-2.rs | 6 +- .../loops-reject-duplicate-labels-2.stderr | 10 +- .../ui/loops/loops-reject-duplicate-labels.rs | 11 +- .../loops-reject-duplicate-labels.stderr | 26 +- .../loops-reject-lifetime-shadowing-label.rs | 13 +- ...ops-reject-lifetime-shadowing-label.stderr | 10 +- .../lub-glb/old-lub-glb-hr-noteq1.nll.stderr | 4 +- .../ui/lub-glb/old-lub-glb-object.nll.stderr | 8 +- src/test/ui/lub-if.nll.stderr | 4 - src/test/ui/lub-if.stderr | 4 +- src/test/ui/lub-match.nll.stderr | 4 - src/test/ui/lub-match.stderr | 4 +- .../main.-Zmacro-backtrace.stderr | 16 +- .../ui/macro_backtrace/main.default.stderr | 6 +- .../ui/macros/assert-trailing-junk.stderr | 2 +- src/test/ui/macros/assert.stderr | 4 +- .../ui/{ => macros}/auxiliary/define-macro.rs | 0 .../macros/auxiliary/macro-def-site-super.rs | 13 + src/test/ui/macros/bang-after-name.fixed | 8 + src/test/ui/macros/bang-after-name.rs | 8 + src/test/ui/macros/bang-after-name.stderr | 8 + src/test/ui/macros/cfg.stderr | 2 +- src/test/ui/macros/format-parse-errors.stderr | 2 +- src/test/ui/macros/global-asm.stderr | 2 +- src/test/ui/macros/issue-54441.stderr | 2 +- ...issue-78325-inconsistent-resolution.stderr | 2 +- ...e-84632-eager-expansion-recursion-limit.rs | 2 +- ...632-eager-expansion-recursion-limit.stderr | 4 +- .../macros/macro-at-most-once-rep-2015.stderr | 4 +- .../macros/macro-at-most-once-rep-2018.stderr | 4 +- .../macro-backtrace-invalid-internals.stderr | 8 +- .../ui/macros/macro-backtrace-nested.stderr | 2 +- .../ui/macros/macro-backtrace-println.stderr | 2 +- src/test/ui/macros/macro-comma-support.stderr | 4 +- src/test/ui/macros/macro-context.stderr | 2 +- src/test/ui/macros/macro-def-site-super.rs | 10 + .../ui/macros/macro-inner-attributes.stderr | 5 + .../macro-lifetime-used-with-labels.stderr | 2 +- .../macros/macro-local-data-key-priv.stderr | 2 +- src/test/ui/macros/macro-shadowing.stderr | 4 +- .../ui/macros/macros-nonfatal-errors.stderr | 12 +- .../ui/macros/must-use-in-macro-55516.stderr | 2 +- .../ui/macros/nonterminal-matching.stderr | 2 +- .../ui/{ => macros}/out-of-order-shadowing.rs | 0 .../out-of-order-shadowing.stderr | 2 +- .../macros/restricted-shadowing-legacy.stderr | 48 +- .../macros/restricted-shadowing-modern.stderr | 36 +- src/test/ui/macros/same-sequence-span.stderr | 4 +- .../ui/macros/span-covering-argument-1.stderr | 2 +- src/test/ui/macros/trace-macro.stderr | 2 +- src/test/ui/macros/trace_faulty_macros.stderr | 12 +- .../ui/malformed/malformed-plugin-1.stderr | 2 +- .../ui/malformed/malformed-plugin-2.stderr | 2 +- src/test/ui/map-types.rs | 6 +- src/test/ui/{ => match}/guards.rs | 0 src/test/ui/{issues => match}/issue-33498.rs | 0 src/test/ui/{issues => match}/issue-41255.rs | 0 .../ui/{issues => match}/issue-41255.stderr | 0 src/test/ui/{issues => match}/issue-56685.rs | 0 .../ui/{issues => match}/issue-56685.stderr | 0 src/test/ui/match/issue-74050-end-span.stderr | 2 +- .../ui/match/match-ref-mut-invariance.stderr | 4 +- .../match/match-ref-mut-let-invariance.stderr | 4 +- src/test/ui/maybe-bounds-where.rs | 1 + src/test/ui/maybe-bounds-where.stderr | 32 +- .../meta/expected-error-correct-rev.a.stderr | 2 +- .../meta-expected-error-wrong-rev.a.stderr | 2 +- .../ui/methods/auxiliary/method_self_arg1.rs | 6 +- .../ui/methods/auxiliary/method_self_arg2.rs | 6 +- ...od-ambig-one-trait-unknown-int-type.stderr | 2 +- ...method-ambig-two-traits-from-impls2.stderr | 8 +- .../ui/methods/method-call-err-msg.stderr | 11 + src/test/ui/methods/method-self-arg-2.stderr | 4 +- src/test/ui/methods/method-self-arg-aux1.rs | 4 +- src/test/ui/methods/method-self-arg-aux2.rs | 6 +- src/test/ui/methods/method-self-arg-trait.rs | 10 +- src/test/ui/methods/method-self-arg.rs | 8 +- .../method-two-trait-defer-resolution-2.rs | 4 +- src/test/ui/mir-dataflow/liveness-enum.rs | 22 + src/test/ui/mir-dataflow/liveness-enum.stderr | 10 + src/test/ui/mismatched_types/E0631.stderr | 8 +- .../ui/mismatched_types/cast-rfc0401.stderr | 5 +- .../mismatched_types/closure-arg-count.stderr | 20 +- .../closure-arg-type-mismatch.stderr | 4 +- .../closure-mismatch.nll.stderr | 5 + .../ui/mismatched_types/fn-variance-1.stderr | 8 +- .../ui/mismatched_types/issue-26480.stderr | 6 +- .../method-help-unsatisfied-bound.stderr | 4 + .../numeric-literal-cast.stderr | 6 +- .../unboxed-closures-vtable-mismatch.rs | 1 + .../unboxed-closures-vtable-mismatch.stderr | 4 +- .../missing-alloc_error_handler.stderr | 4 +- src/test/ui/missing/missing-allocator.stderr | 2 +- src/test/ui/modules/issue-56411.stderr | 4 +- src/test/ui/modules/path-invalid-form.rs | 4 + src/test/ui/modules/path-invalid-form.stderr | 8 + src/test/ui/modules/path-macro.rs | 8 + src/test/ui/modules/path-macro.stderr | 8 + src/test/ui/monomorphize-abi-alignment.rs | 1 + .../ui/moves/issue-72649-uninit-in-loop.rs | 74 + .../moves/issue-72649-uninit-in-loop.stderr | 58 + src/test/ui/moves/move-1-unique.rs | 6 +- src/test/ui/moves/move-2-unique.rs | 3 +- src/test/ui/moves/move-2.rs | 3 +- src/test/ui/moves/move-3-unique.rs | 6 +- src/test/ui/moves/move-4-unique.rs | 3 +- src/test/ui/moves/move-4.rs | 3 +- src/test/ui/moves/move-arg-2-unique.rs | 5 +- src/test/ui/moves/move-arg-2.rs | 5 +- .../ui/moves/move-fn-self-receiver.stderr | 2 +- src/test/ui/moves/move-guard-same-consts.rs | 6 +- .../ui/moves/move-guard-same-consts.stderr | 2 +- src/test/ui/moves/move-in-guard-1.rs | 6 +- src/test/ui/moves/move-in-guard-1.stderr | 2 +- src/test/ui/moves/move-in-guard-2.rs | 4 +- src/test/ui/moves/move-in-guard-2.stderr | 4 +- src/test/ui/moves/move-out-of-tuple-field.rs | 8 +- .../ui/moves/moves-based-on-type-block-bad.rs | 4 +- ...type-move-out-of-closure-env-issue-1965.rs | 4 +- ...-move-out-of-closure-env-issue-1965.stderr | 7 +- .../ui/moves/moves-based-on-type-tuple.rs | 8 +- .../ui/moves/moves-based-on-type-tuple.stderr | 11 +- src/test/ui/moves/moves-sru-moved-field.rs | 8 +- src/test/ui/mut-function-arguments.rs | 6 +- src/test/ui/mut/mut-cant-alias.stderr | 2 +- src/test/ui/mut/mut-cross-borrowing.rs | 6 +- src/test/ui/mut/mut-suggestion.stderr | 4 +- src/test/ui/mutexguard-sync.stderr | 4 +- src/test/ui/namespace/namespace-mix.stderr | 176 +- .../mix-bundle-and-whole-archive-link-attr.rs | 12 + ...-bundle-and-whole-archive-link-attr.stderr | 6 + .../mix-bundle-and-whole-archive.rs | 7 + .../mix-bundle-and-whole-archive.stderr | 6 + ...r => defaulted-never-note.fallback.stderr} | 8 +- .../ui/never_type/defaulted-never-note.rs | 20 +- .../diverging-fallback-control-flow.rs | 38 +- ...diverging-fallback-no-leak.fallback.stderr | 18 + .../never_type/diverging-fallback-no-leak.rs | 19 + ...diverging-fallback-unconstrained-return.rs | 37 + .../ui/{ => never_type}/expr-empty-ret.rs | 0 .../ui/never_type/fallback-closure-ret.rs | 23 + .../fallback-closure-wrap.fallback.stderr | 17 + .../ui/never_type/fallback-closure-wrap.rs | 30 + ...lue-fallback-issue-66757.nofallback.stderr | 17 + .../never-value-fallback-issue-66757.rs | 10 +- src/test/ui/new-box-syntax.rs | 11 +- src/test/ui/new-box.rs | 6 +- src/test/ui/nll/closure-access-spans.stderr | 10 +- src/test/ui/nll/closure-borrow-spans.stderr | 28 +- ...oximated-shorter-to-static-no-bound.stderr | 11 +- ...mated-shorter-to-static-wrong-bound.stderr | 11 +- ...n-lbr-named-does-not-outlive-static.stderr | 2 - src/test/ui/nll/get_default.nll.stderr | 48 - src/test/ui/nll/get_default.stderr | 6 +- src/test/ui/nll/issue-46036.stderr | 2 +- src/test/ui/nll/issue-46589.stderr | 4 +- src/test/ui/nll/issue-50716.nll.stderr | 2 - src/test/ui/nll/issue-50716.stderr | 6 +- src/test/ui/nll/issue-51191.stderr | 2 +- ...e-52663-span-decl-captured-variable.stderr | 5 +- src/test/ui/nll/issue-52663-trait-object.rs | 6 +- .../ui/nll/issue-52663-trait-object.stderr | 4 +- src/test/ui/nll/issue-52669.stderr | 2 +- src/test/ui/nll/issue-52742.stderr | 4 +- src/test/ui/nll/issue-53773.stderr | 2 +- src/test/ui/nll/issue-54556-niconii.stderr | 2 +- src/test/ui/nll/issue-55394.stderr | 6 +- src/test/ui/nll/issue-55401.nll.stderr | 2 - src/test/ui/nll/issue-55401.stderr | 2 +- src/test/ui/nll/issue-55825-const-fn.rs | 8 + src/test/ui/nll/issue-55825-const-fn.stderr | 12 + src/test/ui/nll/issue-58299.stderr | 4 - .../nll/issue-62007-assign-const-index.stderr | 2 +- ...issue-62007-assign-differing-fields.stderr | 2 +- src/test/ui/nll/issue-67007-escaping-data.rs | 26 + .../ui/nll/issue-67007-escaping-data.stderr | 21 + src/test/ui/nll/issue-73159-rpit-static.rs | 14 + .../ui/nll/issue-73159-rpit-static.stderr | 10 + .../ui/nll/loan_ends_mid_block_vec.stderr | 6 +- src/test/ui/nll/mir_check_cast_reify.stderr | 2 - .../ui/nll/mir_check_cast_unsafe_fn.stderr | 2 - src/test/ui/nll/mir_check_cast_unsize.stderr | 2 - .../ui/nll/normalization-bounds-error.stderr | 4 +- .../ui/nll/outlives-suggestion-more.stderr | 4 - .../ui/nll/outlives-suggestion-simple.stderr | 13 +- .../assignment-to-differing-field.stderr | 4 +- .../region-ends-after-if-condition.nll.stderr | 15 - src/test/ui/nll/relate_tys/fn-subtype.stderr | 2 +- .../ui/nll/relate_tys/hr-fn-aaa-as-aba.stderr | 4 +- src/test/ui/nll/relate_tys/trait-hrtb.stderr | 2 +- src/test/ui/nll/return_from_loop.stderr | 4 +- .../ui/nll/trait-associated-constant.stderr | 4 +- .../ui/nll/ty-outlives/wf-unreachable.stderr | 16 - .../ui/nll/type-alias-free-regions.stderr | 12 +- .../user-annotations/adt-brace-enums.stderr | 6 +- .../user-annotations/adt-brace-structs.stderr | 6 +- .../user-annotations/adt-tuple-enums.stderr | 6 +- .../user-annotations/adt-tuple-struct.stderr | 6 +- .../user-annotations/closure-substs.stderr | 13 +- .../constant-in-expr-inherent-1.nll.stderr | 2 - .../constant-in-expr-normalize.nll.stderr | 2 - .../constant-in-expr-normalize.stderr | 2 +- .../constant-in-expr-trait-item-1.nll.stderr | 2 - .../constant-in-expr-trait-item-1.stderr | 2 +- .../constant-in-expr-trait-item-2.nll.stderr | 2 - .../constant-in-expr-trait-item-2.stderr | 2 +- .../constant-in-expr-trait-item-3.nll.stderr | 2 - .../constant-in-expr-trait-item-3.stderr | 2 +- .../inherent-associated-constants.stderr | 2 - .../nll/user-annotations/issue-54124.stderr | 2 - ...-55748-pat-types-constrain-bindings.stderr | 6 - .../issue-57731-ascibed-coupled-types.stderr | 8 - .../ui/nll/user-annotations/patterns.stderr | 8 - .../ui/nll/where_clauses_in_structs.stderr | 2 +- src/test/ui/no_crate_type.stderr | 2 +- src/test/ui/no_send-rc.stderr | 4 +- src/test/ui/no_send-struct.stderr | 4 +- src/test/ui/no_share-struct.stderr | 4 +- src/test/ui/non-fmt-panic.stderr | 2 +- src/test/ui/nullable-pointer-iotareduction.rs | 4 +- src/test/ui/numeric/const-scope.stderr | 8 +- src/test/ui/numeric/len.stderr | 2 +- src/test/ui/numeric/numeric-cast-2.stderr | 24 +- src/test/ui/numeric/numeric-cast-binop.stderr | 544 +- .../ui/numeric/numeric-cast-no-fix.stderr | 22 +- src/test/ui/numeric/numeric-cast.stderr | 434 +- src/test/ui/numeric/numeric-fields.stderr | 14 +- src/test/ui/numeric/numeric-suffix.stderr | 284 +- src/test/ui/object-does-not-impl-trait.stderr | 4 +- .../object-lifetime-default-elision.stderr | 12 +- ...ime-default-from-rptr-box-error.nll.stderr | 2 - ...ifetime-default-from-rptr-box-error.stderr | 2 +- ...-default-from-rptr-struct-error.nll.stderr | 2 - ...time-default-from-rptr-struct-error.stderr | 2 +- .../object-lifetime-default-mybox.nll.stderr | 11 +- .../object-lifetime-default-mybox.stderr | 2 +- ...bject-safety-associated-consts.curr.stderr | 2 +- ...ted-consts.object_safe_for_dispatch.stderr | 2 +- .../object-safety-by-value-self-use.stderr | 2 +- .../object-safety-generics.curr.stderr | 4 +- ...y-generics.object_safe_for_dispatch.stderr | 4 +- .../object-safety-mentions-Self.curr.stderr | 4 +- ...tions-Self.object_safe_for_dispatch.stderr | 4 +- ...owned-object-borrowed-method-headerless.rs | 9 +- .../ui/objects-owned-object-owned-method.rs | 4 +- src/test/ui/occurs-check-2.rs | 6 +- src/test/ui/occurs-check-2.stderr | 11 +- src/test/ui/occurs-check.rs | 6 +- src/test/ui/occurs-check.stderr | 11 +- .../on-unimplemented/enclosing-scope.stderr | 16 +- .../ui/on-unimplemented/multiple-impls.stderr | 12 +- src/test/ui/on-unimplemented/on-impl.stderr | 4 +- .../or-patterns-syntactic-fail.stderr | 17 +- src/test/ui/output-slot-variants.rs | 9 +- .../overloaded/overloaded-autoderef-order.rs | 2 + .../ui/overloaded/overloaded-autoderef.rs | 4 +- .../overloaded/overloaded-index-autoderef.rs | 6 +- src/test/ui/panics/args-panic.rs | 4 +- src/test/ui/panics/panic-macro-any.rs | 3 +- .../ui/parser/attr-stmt-expr-attr-bad.stderr | 96 +- src/test/ui/parser/attr.stderr | 10 +- .../ui/parser/bad-interpolated-block.stderr | 6 +- .../parser/doc-comment-in-if-statement.stderr | 5 + src/test/ui/parser/expr-as-stmt.fixed | 7 +- src/test/ui/parser/expr-as-stmt.rs | 7 +- src/test/ui/parser/expr-as-stmt.stderr | 30 +- .../ui/parser/float-field-interpolated.stderr | 8 +- .../inner-attr-after-doc-comment.stderr | 10 +- src/test/ui/parser/inner-attr.stderr | 9 +- src/test/ui/parser/inverted-parameters.stderr | 6 +- src/test/ui/parser/issue-30318.fixed | 27 + src/test/ui/parser/issue-30318.rs | 22 +- src/test/ui/parser/issue-30318.stderr | 74 +- src/test/ui/parser/issue-44406.rs | 4 +- src/test/ui/parser/issue-44406.stderr | 20 +- src/test/ui/parser/issue-45296.rs | 1 + src/test/ui/parser/issue-45296.stderr | 9 +- ...interpolate-impl-items-bad-variants.stderr | 6 +- .../issue-73568-lifetime-after-mut.stderr | 2 +- src/test/ui/parser/issue-87812-path.stderr | 2 +- .../ui/parser/issue-88276-unary-plus.fixed | 8 + src/test/ui/parser/issue-88276-unary-plus.rs | 8 + .../ui/parser/issue-88276-unary-plus.stderr | 50 + src/test/ui/parser/issue-88770.rs | 11 + src/test/ui/parser/issue-88770.stderr | 66 + src/test/ui/parser/issue-88818.rs | 10 + src/test/ui/parser/issue-88818.stderr | 18 + src/test/ui/parser/issue-89388.rs | 7 + src/test/ui/parser/issue-89388.stderr | 8 + src/test/ui/parser/issue-89396.fixed | 16 + src/test/ui/parser/issue-89396.rs | 16 + src/test/ui/parser/issue-89396.stderr | 20 + .../ui/parser/labeled-no-colon-expr.stderr | 2 +- src/test/ui/parser/lifetime-in-pattern.stderr | 8 +- .../ui/parser/macro-braces-dot-question.rs | 11 + src/test/ui/parser/macro/issue-37113.stderr | 2 +- src/test/ui/parser/macro/issue-37234.stderr | 2 +- .../macro/macro-incomplete-parse.stderr | 4 +- .../ui/parser/macro/pub-item-macro.stderr | 4 +- .../parser/macro/trait-non-item-macros.stderr | 2 +- src/test/ui/parser/missing-semicolon.stderr | 2 +- src/test/ui/parser/mut-patterns.stderr | 2 +- .../ui/parser/omitted-arg-in-item-fn.stderr | 6 +- src/test/ui/parser/pat-lt-bracket-2.stderr | 4 +- .../recover-for-loop-parens-around-head.rs | 2 +- ...recover-for-loop-parens-around-head.stderr | 15 +- .../ui/parser/recover-from-bad-variant.rs | 2 +- .../ui/parser/recover-from-bad-variant.stderr | 19 +- src/test/ui/parser/recover-range-pats.stderr | 8 +- .../parser/stmt_expr_attrs_placement.stderr | 21 +- src/test/ui/parser/trailing-plus-in-bounds.rs | 3 +- .../ui/parser/trait-object-delimiters.stderr | 4 +- .../parser/trait-object-trait-parens.stderr | 6 +- .../ui/parser/unicode-character-literal.fixed | 21 + .../ui/parser/unicode-character-literal.rs | 21 + .../parser/unicode-character-literal.stderr | 48 + .../ui/parser/unicode-control-codepoints.rs | 39 + .../parser/unicode-control-codepoints.stderr | 192 + src/test/ui/path-lookahead.stderr | 7 +- ...d-type-ascription-syntactically-invalid.rs | 2 +- ...ssue-88074-pat-range-type-inference-err.rs | 28 + ...-88074-pat-range-type-inference-err.stderr | 21 + .../issue-88074-pat-range-type-inference.rs | 16 + .../ui/pattern/patkind-litrange-no-expr.rs | 1 - .../pattern/patkind-litrange-no-expr.stderr | 12 +- .../ui/pattern/usefulness/auxiliary/hidden.rs | 6 + .../pattern/usefulness/auxiliary/unstable.rs | 12 + .../usefulness/const-private-fields.rs | 30 + .../pattern/usefulness/consts-opaque.stderr | 58 +- .../usefulness/doc-hidden-non-exhaustive.rs | 30 + .../doc-hidden-non-exhaustive.stderr | 54 + .../integer-ranges/reachability.stderr | 4 +- src/test/ui/pattern/usefulness/issue-12116.rs | 8 +- .../ui/pattern/usefulness/issue-12116.stderr | 4 +- src/test/ui/pattern/usefulness/issue-3601.rs | 6 +- .../ui/pattern/usefulness/issue-3601.stderr | 4 +- .../issue-72476-and-89393-associated-type.rs | 56 + .../usefulness/issue-72476-associated-type.rs | 22 - .../issue-82772-match-box-as-struct.rs | 6 + .../issue-82772-match-box-as-struct.stderr | 9 + .../usefulness/stable-gated-patterns.rs | 18 + .../usefulness/stable-gated-patterns.stderr | 26 + .../usefulness/unstable-gated-patterns.rs | 22 + .../usefulness/unstable-gated-patterns.stderr | 17 + src/test/ui/phantom-auto-trait.stderr | 8 +- .../issue-74614.rs | 0 src/test/ui/polymorphization/predicates.rs | 5 + .../ui/polymorphization/predicates.stderr | 39 +- src/test/ui/pptypedef.stderr | 4 +- src/test/ui/print_type_sizes/uninhabited.rs | 2 +- .../ui/print_type_sizes/uninhabited.stdout | 1 + .../associated-item-privacy-inherent.stderr | 42 +- .../associated-item-privacy-trait.stderr | 60 +- ...ssociated-item-privacy-type-binding.stderr | 32 +- .../ui/{issues => privacy}/issue-79593.rs | 0 .../ui/{issues => privacy}/issue-79593.stderr | 0 src/test/ui/privacy/privacy2.stderr | 8 +- src/test/ui/privacy/privacy3.stderr | 8 +- .../ui/privacy/private-inferred-type-3.stderr | 14 +- .../ui/privacy/private-inferred-type.stderr | 12 +- .../attribute-after-derive-feature-gate.rs | 37 - ...attribute-after-derive-feature-gate.stderr | 30 - .../ui/proc-macro/attribute-after-derive.rs | 2 - .../proc-macro/attribute-after-derive.stdout | 106 +- .../ui/proc-macro/auxiliary/is-available.rs | 1 - .../proc-macro/derive-helper-shadowing.stderr | 2 +- .../proc-macro/gen-macro-rules-hygiene.stderr | 8 +- src/test/ui/proc-macro/generate-mod.stderr | 76 +- .../group-compat-hack.stderr | 20 +- .../proc-macro/invalid-punct-ident-1.stderr | 2 +- .../proc-macro/invalid-punct-ident-2.stderr | 2 +- .../proc-macro/invalid-punct-ident-3.stderr | 2 +- .../proc-macro/invalid-punct-ident-4.stderr | 4 +- src/test/ui/proc-macro/is-available.rs | 2 - src/test/ui/proc-macro/issue-83510.stderr | 8 +- .../issue-86781-bad-inner-doc.fixed | 12 + .../proc-macro/issue-86781-bad-inner-doc.rs | 3 +- .../issue-86781-bad-inner-doc.stderr | 10 +- .../ui/proc-macro/lints_in_proc_macros.stderr | 2 +- .../ui/proc-macro/macro-rules-derive.stderr | 2 +- src/test/ui/proc-macro/meta-macro-hygiene.rs | 1 + .../ui/proc-macro/meta-macro-hygiene.stdout | 4 +- src/test/ui/proc-macro/mixed-site-span.stderr | 6 +- src/test/ui/proc-macro/multispan.stderr | 14 +- .../proc-macro/nonterminal-token-hygiene.rs | 1 + .../nonterminal-token-hygiene.stdout | 10 +- .../ui/proc-macro/parent-source-spans.stderr | 44 +- src/test/ui/proc-macro/raw-ident.stderr | 2 +- src/test/ui/proc-macro/span-api-tests.rs | 2 +- .../ui/proc-macro/span-from-proc-macro.stderr | 4 +- .../ui/proc-macro/span-preservation.stderr | 2 +- src/test/ui/proc-macro/subspan.stderr | 16 +- src/test/ui/proc-macro/three-equals.stderr | 2 +- src/test/ui/proc-macro/weird-hygiene.stderr | 4 +- .../ui/process/process-panic-after-fork.rs | 17 +- src/test/ui/pure-sum.rs | 6 +- src/test/ui/rcvr-borrowed-to-region.rs | 3 +- src/test/ui/reachable/expr_again.rs | 2 +- src/test/ui/reachable/expr_again.stderr | 2 +- src/test/ui/reachable/expr_block.stderr | 2 +- src/test/ui/reachable/expr_if.stderr | 2 +- src/test/ui/reachable/expr_loop.stderr | 6 +- src/test/ui/reachable/expr_match.stderr | 4 +- src/test/ui/reachable/unreachable-arm.rs | 2 +- .../ui/reachable/unreachable-code-ret.stderr | 2 +- .../issue-26548-recursion-via-normalize.rs | 6 +- ...issue-26548-recursion-via-normalize.stderr | 6 +- src/test/ui/recursion/issue-83150.stderr | 2 +- .../ui/recursion_limit/invalid_digit_type.rs | 3 + .../recursion_limit/invalid_digit_type.stderr | 8 + src/test/ui/recursion_limit/invalid_macro.rs | 7 + .../ui/recursion_limit/invalid_macro.stderr | 8 + src/test/ui/recursion_limit/no-value.rs | 6 + src/test/ui/recursion_limit/no-value.stderr | 8 + src/test/ui/recursion_limit/zero-overflow.rs | 7 + .../ui/recursion_limit/zero-overflow.stderr | 7 + src/test/ui/recursion_limit/zero.rs | 2 +- src/test/ui/recursion_limit/zero.stderr | 4 +- src/test/ui/regions/issue-12470.rs | 6 +- src/test/ui/regions/issue-28848.stderr | 4 +- .../ui/regions/issue-78262.default.stderr | 2 +- src/test/ui/regions/issue-78262.nll.stderr | 7 +- .../ui/regions/issue-78262.polonius.stderr | 7 +- ...unds-on-objects-and-type-parameters.stderr | 4 +- ...nvariant-static-error-reporting.nll.stderr | 11 +- ...on-invariant-static-error-reporting.stderr | 2 +- .../regions/region-object-lifetime-2.stderr | 4 +- .../regions/region-object-lifetime-4.stderr | 4 +- .../ui/regions/region-object-lifetime-5.rs | 2 +- .../regions/region-object-lifetime-5.stderr | 7 +- .../region-object-lifetime-in-coercion.stderr | 6 +- .../regions/regions-addr-of-upvar-self.stderr | 2 +- ...pertrait-outlives-container.migrate.stderr | 4 +- ...-type-region-bound-in-trait-not-met.stderr | 2 +- src/test/ui/regions/regions-borrow-at.rs | 3 +- src/test/ui/regions/regions-borrow-uniq.rs | 3 +- ...unded-by-trait-requiring-static.nll.stderr | 12 - ...hod-type-parameters-trait-bound.nll.stderr | 13 +- ...-bounded-method-type-parameters.nll.stderr | 2 - src/test/ui/regions/regions-bounds.stderr | 8 +- ...gions-close-associated-type-into-object.rs | 8 +- .../regions-close-object-into-object-1.rs | 4 +- .../regions-close-object-into-object-1.stderr | 8 +- ...ions-close-object-into-object-2.nll.stderr | 18 +- .../regions-close-object-into-object-2.rs | 5 +- .../regions-close-object-into-object-2.stderr | 6 +- .../regions-close-object-into-object-3.rs | 4 +- .../regions-close-object-into-object-3.stderr | 8 +- ...ions-close-object-into-object-4.nll.stderr | 48 +- .../regions-close-object-into-object-4.rs | 5 +- .../regions-close-object-into-object-4.stderr | 6 +- ...ions-close-object-into-object-5.nll.stderr | 36 +- .../regions-close-object-into-object-5.rs | 5 +- .../regions-close-object-into-object-5.stderr | 75 +- ...ons-close-over-type-parameter-1.nll.stderr | 8 +- .../regions-close-over-type-parameter-1.rs | 10 +- ...regions-close-over-type-parameter-1.stderr | 8 +- ...se-over-type-parameter-multiple.nll.stderr | 4 +- ...ions-close-over-type-parameter-multiple.rs | 10 +- ...-close-over-type-parameter-multiple.stderr | 18 +- ...-close-over-type-parameter-successfully.rs | 4 +- .../ui/regions/regions-creating-enums4.stderr | 6 +- .../ui/regions/regions-dependent-addr-of.rs | 3 +- .../regions-early-bound-error-method.stderr | 4 +- .../regions/regions-early-bound-error.stderr | 4 +- .../regions-early-bound-trait-param.rs | 4 +- .../regions/regions-escape-into-other-fn.rs | 4 +- ...gions-free-region-ordering-callee-4.stderr | 4 +- ...free-region-ordering-caller.migrate.stderr | 12 +- ...ions-free-region-ordering-incorrect.stderr | 4 +- ...gions-infer-borrow-scope-within-loop-ok.rs | 3 +- .../ui/regions/regions-infer-borrow-scope.rs | 3 +- ...ns-infer-invariance-due-to-decl.nll.stderr | 2 - ...egions-infer-invariance-due-to-decl.stderr | 2 +- ...-invariance-due-to-mutability-3.nll.stderr | 2 - ...nfer-invariance-due-to-mutability-3.stderr | 2 +- ...-invariance-due-to-mutability-4.nll.stderr | 2 - ...nfer-invariance-due-to-mutability-4.stderr | 2 +- .../ui/regions/regions-infer-not-param.stderr | 12 +- .../regions-infer-paramd-indirect.stderr | 4 +- .../regions-lifetime-nonfree-late-bound.rs | 6 +- .../ui/regions/regions-nested-fns.nll.stderr | 2 - src/test/ui/regions/regions-nested-fns.stderr | 8 +- ...ions-normalize-in-where-clause-list.stderr | 8 +- ...s-projection-container-hrtb.migrate.stderr | 8 +- ...ves-projection-container-wc.migrate.stderr | 4 +- ...gions-outlives-projection-container.stderr | 16 +- src/test/ui/regions/regions-ref-in-fn-arg.rs | 4 +- ...ions-on-closures-to-inference-variables.rs | 2 - .../ui/regions/regions-ret-borrowed-1.stderr | 6 +- .../ui/regions/regions-ret-borrowed.stderr | 6 +- .../regions-static-bound.migrate.nll.stderr | 2 - .../regions-static-bound.migrate.stderr | 2 +- .../regions/regions-static-bound.nll.stderr | 2 - .../regions-trait-object-subtyping.stderr | 14 +- src/test/ui/regions/regions-trait-variance.rs | 8 +- .../regions-var-type-out-of-scope.stderr | 2 +- ...ariance-invariant-use-covariant.nll.stderr | 2 - ...ns-variance-invariant-use-covariant.stderr | 2 +- .../ui/regions/regions-wf-trait-object.stderr | 4 +- src/test/ui/repeat_count.stderr | 2 +- .../ui/repr/repr-transparent-issue-87496.rs | 12 + .../repr/repr-transparent-issue-87496.stderr | 16 + .../ui/{issues => resolve}/issue-42944.rs | 0 .../ui/{issues => resolve}/issue-42944.stderr | 7 +- src/test/ui/resolve/issue-82865.stderr | 2 +- src/test/ui/resolve/issue-85671.rs | 37 + src/test/ui/resolve/issue-88472.rs | 38 + src/test/ui/resolve/issue-88472.stderr | 42 + src/test/ui/resolve/privacy-enum-ctor.stderr | 52 +- .../ui/resolve/privacy-struct-ctor.stderr | 7 +- .../resolve/suggest-path-for-tuple-struct.rs | 26 + .../suggest-path-for-tuple-struct.stderr | 19 + .../ui/{ => resolve}/use-self-in-inner-fn.rs | 0 .../{ => resolve}/use-self-in-inner-fn.stderr | 0 .../missing-link-attr.stderr | 2 +- .../multiple-renames.stderr | 2 +- .../borrowck-issue-49631.nll.stderr | 14 - .../borrowck-issue-49631.stderr | 2 +- .../auxiliary/enums.rs | 23 +- .../auxiliary/structs.rs | 18 +- .../auxiliary/unstable.rs | 29 + .../omitted-patterns.rs | 170 + .../omitted-patterns.stderr | 160 + .../stable-omitted-patterns.rs | 33 + .../stable-omitted-patterns.stderr | 16 + .../ui/rfc-2008-non-exhaustive/struct.stderr | 6 +- .../rfc-2091-track-caller/tracked-closure.rs | 154 + ...ns-outlives-nominal-type-region-rev.stderr | 4 +- ...egions-outlives-nominal-type-region.stderr | 4 +- ...ions-outlives-nominal-type-type-rev.stderr | 4 +- .../regions-outlives-nominal-type-type.stderr | 4 +- .../regions-struct-not-wf.stderr | 4 +- .../extern_block_nonascii_forbidden.stderr | 6 +- .../param-attrs-2018.stderr | 6 +- .../link-ordinal-missing-argument.rs | 11 + .../link-ordinal-missing-argument.stderr | 19 + .../link-ordinal-multiple.rs | 13 + .../link-ordinal-multiple.stderr | 17 + .../link-ordinal-too-large.rs | 4 +- .../link-ordinal-too-large.stderr | 8 +- .../link-ordinal-too-many-arguments.rs | 11 + .../link-ordinal-too-many-arguments.stderr | 19 + .../call-generic-method-dup-bound.rs | 13 +- .../call-generic-method-nonconst.stderr | 4 +- .../const-closures.rs | 31 + .../const-drop-fail.precise.stderr | 68 + .../const-drop-fail.rs | 54 + .../const-drop-fail.stock.stderr | 68 + .../rfc-2632-const-trait-impl/const-drop.rs | 80 + ...ult-fn.rs => impl-with-default-fn-fail.rs} | 6 +- ...tderr => impl-with-default-fn-fail.stderr} | 6 +- .../impl-with-default-fn-pass.rs | 34 + .../inherent-impl-const-bounds.rs | 21 + .../stability.stderr | 2 +- src/test/ui/rfc1623.nll.stderr | 8 +- .../rfcs/rfc-2005-default-binding-mode/box.rs | 4 +- .../fn-traits.stderr | 24 +- .../rust-2018/trait-import-suggestions.stderr | 6 +- .../ambiguity-macros-nested.stderr | 2 +- .../uniform-paths/ambiguity-macros.stderr | 2 +- .../future-prelude-collision-shadow.stderr | 9 +- .../reserved-prefixes-via-macro-2.stderr | 6 +- src/test/ui/sanitize/crt-static.stderr | 2 +- src/test/ui/self/explicit-self-generic.rs | 3 +- .../ui/self/explicit-self-objects-uniq.rs | 3 +- src/test/ui/self/explicit-self.rs | 4 +- src/test/ui/self/self-impl-2.rs | 12 +- .../self/self-in-mut-slot-default-method.rs | 3 +- src/test/ui/self/self-re-assign.rs | 3 +- src/test/ui/self/self_type_keyword.stderr | 7 +- src/test/ui/self/ufcs-explicit-self.rs | 10 +- src/test/ui/self/uniq-self-in-mut-slot.rs | 3 +- .../ui/shadowed/shadowed-type-parameter.rs | 2 +- src/test/ui/shift-various-bad-types.stderr | 2 +- .../simd-intrinsic-generic-bitmask.rs | 92 - .../{simd-array-trait.rs => array-trait.rs} | 0 ...-array-trait.stderr => array-trait.stderr} | 2 +- .../{simd-array-type.rs => array-type.rs} | 0 .../ui/simd/{simd-generics.rs => generics.rs} | 0 .../float-math-pass.rs} | 0 .../float-minmax-pass.rs} | 0 .../intrinsic/generic-arithmetic-2.rs} | 0 .../intrinsic/generic-arithmetic-2.stderr} | 30 +- .../generic-arithmetic-pass.rs} | 0 .../generic-arithmetic-saturating-2.rs} | 0 .../generic-arithmetic-saturating-2.stderr} | 4 +- .../generic-arithmetic-saturating-pass.rs} | 0 .../generic-bitmask-pass.rs} | 0 src/test/ui/simd/intrinsic/generic-bitmask.rs | 69 + .../intrinsic/generic-bitmask.stderr} | 10 +- .../generic-cast-pass.rs} | 0 .../intrinsic/generic-cast.rs} | 0 .../intrinsic/generic-cast.stderr} | 8 +- .../generic-comparison-pass.rs} | 0 .../intrinsic/generic-comparison.rs} | 0 .../intrinsic/generic-comparison.stderr} | 36 +- .../generic-elements-pass.rs} | 0 .../intrinsic/generic-elements.rs} | 0 .../intrinsic/generic-elements.stderr} | 24 +- .../generic-gather-pass.rs} | 0 .../generic-reduction-pass.rs} | 9 - .../intrinsic/generic-reduction.rs} | 0 .../intrinsic/generic-reduction.stderr} | 20 +- .../generic-select-pass.rs} | 0 .../intrinsic/generic-select.rs} | 0 .../intrinsic/generic-select.stderr} | 16 +- src/test/ui/simd/intrinsic/generic-shuffle.rs | 33 + .../ui/simd/intrinsic/generic-shuffle.stderr | 21 + .../intrinsic/inlining-issue67557-ice.rs} | 0 .../intrinsic/inlining-issue67557.rs} | 0 .../intrinsic}/issue-85855.rs | 0 .../intrinsic}/issue-85855.stderr | 0 src/test/ui/simd/issue-89193.rs | 51 + .../ui/simd/monomorphize-shuffle-index.rs | 40 + src/test/ui/simd/shuffle-not-out-of-bounds.rs | 176 +- .../ui/simd/shuffle-not-out-of-bounds.stderr | 63 +- src/test/ui/simd/shuffle.rs | 24 + .../{simd-size-align.rs => size-align.rs} | 0 ...ature-mixup.rs => target-feature-mixup.rs} | 0 ...=> type-generic-monomorphisation-empty.rs} | 0 ...ype-generic-monomorphisation-empty.stderr} | 0 ...ic-monomorphisation-extern-nonnull-ptr.rs} | 0 ...generic-monomorphisation-non-primitive.rs} | 0 ...ric-monomorphisation-non-primitive.stderr} | 0 ...ype-generic-monomorphisation-oversized.rs} | 0 ...generic-monomorphisation-oversized.stderr} | 0 ...-generic-monomorphisation-power-of-two.rs} | 0 ...type-generic-monomorphisation-wide-ptr.rs} | 0 ...-generic-monomorphisation-wide-ptr.stderr} | 0 ...on.rs => type-generic-monomorphisation.rs} | 0 ...r => type-generic-monomorphisation.stderr} | 0 .../ui/simd/{simd-type.rs => type-len.rs} | 0 .../{simd-type.stderr => type-len.stderr} | 12 +- ...simd-type-wide-ptr.rs => type-wide-ptr.rs} | 0 ...e-wide-ptr.stderr => type-wide-ptr.stderr} | 0 ...ck-borrow-overloaded-auto-deref-mut.stderr | 8 +- ...borrowck-call-is-borrow-issue-12224.stderr | 16 +- ...owck-call-method-from-mut-aliasable.stderr | 2 +- .../ui/span/borrowck-fn-in-const-b.stderr | 2 +- .../borrowck-let-suggestion-suffixes.stderr | 2 +- .../ui/span/borrowck-object-mutability.stderr | 4 +- src/test/ui/span/coerce-suggestions.rs | 6 +- src/test/ui/span/coerce-suggestions.stderr | 11 +- .../ui/span/destructor-restrictions.stderr | 2 +- src/test/ui/span/issue-11925.rs | 4 +- ...338-locals-die-before-temps-of-body.stderr | 4 +- src/test/ui/span/issue-34264.stderr | 14 +- src/test/ui/span/issue-36537.stderr | 2 +- src/test/ui/span/issue-39018.stderr | 17 +- src/test/ui/span/issue-40157.stderr | 2 +- src/test/ui/span/issue-7575.stderr | 14 +- .../ui/span/macro-span-replacement.stderr | 2 +- src/test/ui/span/mut-arg-hint.stderr | 6 +- .../ui/span/mut-ptr-cant-outlive-ref.stderr | 2 +- .../regionck-unboxed-closure-lifetimes.stderr | 2 +- .../regions-close-over-borrowed-ref-in-obj.rs | 6 +- .../regions-close-over-type-parameter-2.rs | 8 +- .../span/regions-escape-loop-via-vec.stderr | 11 +- .../span/send-is-not-static-std-sync.stderr | 10 +- src/test/ui/span/slice-borrow.stderr | 2 +- src/test/ui/span/transitive-dep-span.stderr | 2 +- src/test/ui/specialization/README-rpass.md | 2 +- ...pecialization-trait-not-implemented.stderr | 8 + .../{issues => specialization}/issue-35376.rs | 0 .../issue-35376.stderr | 0 .../spec-marker-supertraits.rs | 29 + .../spec-marker-supertraits.stderr | 13 + ...raits.rs => specialization-supertraits.rs} | 0 ...derr => specialization-supertraits.stderr} | 2 +- src/test/ui/{issues => static}/issue-34194.rs | 0 src/test/ui/static/static-lifetime.stderr | 2 +- src/test/ui/static/static-region-bound.rs | 6 +- src/test/ui/str/str-idx.stderr | 8 +- src/test/ui/str/str-mut-idx.stderr | 8 +- .../class-cast-to-trait-cross-crate-2.rs | 4 +- .../class-cast-to-trait-multiple-types.rs | 1 + .../structs-enums/class-implement-traits.rs | 1 + .../ui/structs-enums/class-separate-impl.rs | 4 +- .../enum-nullable-simplifycfg-misopt.rs | 3 +- .../ui/structs-enums/functional-struct-upd.rs | 3 + .../{issues => structs-enums}/issue-38002.rs | 0 src/test/ui/structs-enums/tag-align-shape.rs | 1 + ...rg-where-it-should-have-been-called.stderr | 8 +- .../ui/suggestions/box-future-wrong-output.rs | 22 + .../box-future-wrong-output.stderr | 14 + .../core-std-import-order-issue-83564.rs | 10 + .../core-std-import-order-issue-83564.stderr | 16 + .../ui/suggestions/crate-or-module-typo.rs | 17 + .../suggestions/crate-or-module-typo.stderr | 43 + .../derive-trait-for-method-call.rs | 44 + .../derive-trait-for-method-call.stderr | 95 + ...gest-deref-inside-macro-issue-58298.stderr | 2 +- .../dont-suggest-ref/move-into-closure.stderr | 554 +- .../dont-suggest-try_into-in-macros.stderr | 2 +- .../expected-boxed-future-isnt-pinned.rs | 3 - .../expected-boxed-future-isnt-pinned.stderr | 19 +- ...rg-where-it-should-have-been-called.stderr | 8 +- .../ignore-nested-field-binding.fixed | 20 + .../ignore-nested-field-binding.rs | 20 + .../ignore-nested-field-binding.stderr | 20 + .../imm-ref-trait-object-literal.stderr | 15 +- ...-bound-needing-more-suggestions.nll.stderr | 16 +- ...atic-bound-needing-more-suggestions.stderr | 16 +- ...rait-with-implicit-static-bound.nll.stderr | 44 +- .../impl-trait-with-missing-bounds.stderr | 24 +- src/test/ui/suggestions/invalid-bin-op.stderr | 9 + src/test/ui/suggestions/issue-62843.stderr | 11 +- .../suggestions/issue-64252-self-type.stderr | 8 +- src/test/ui/suggestions/issue-72766.rs | 2 +- ...ait-with-missing-bounds-on-async-fn.stderr | 8 +- src/test/ui/suggestions/issue-84973-2.stderr | 11 +- .../ui/suggestions/issue-84973-blacklist.rs | 1 - .../suggestions/issue-84973-blacklist.stderr | 30 +- .../suggestions/issue-84973-negative.stderr | 15 +- src/test/ui/suggestions/issue-84973.stderr | 11 +- src/test/ui/suggestions/issue-88730.rs | 16 + src/test/ui/suggestions/issue-88730.stderr | 21 + src/test/ui/suggestions/issue-89333.rs | 11 + src/test/ui/suggestions/issue-89333.stderr | 15 + ...issue-90213-expected-boxfuture-self-ice.rs | 13 + ...e-90213-expected-boxfuture-self-ice.stderr | 17 + ...issing-lifetimes-in-signature-2.nll.stderr | 2 +- .../missing-lifetimes-in-signature-2.stderr | 2 +- ...ait-object-nested-in-impl-trait.nll.stderr | 3 - .../missing-type-param-used-in-param.fixed | 8 + .../missing-type-param-used-in-param.rs | 8 + .../missing-type-param-used-in-param.stderr | 21 + .../mut-borrow-needed-by-trait.stderr | 4 +- .../suggestions/negative-literal-index.fixed | 22 + .../ui/suggestions/negative-literal-index.rs | 22 + .../suggestions/negative-literal-index.stderr | 35 + .../nested-non-tuple-tuple-struct.rs | 18 + .../nested-non-tuple-tuple-struct.stderr | 116 + ...object-unsafe-trait-references-self.stderr | 4 +- .../suggestions/option-content-move2.stderr | 27 +- .../suggestions/restrict-type-argument.stderr | 24 +- src/test/ui/suggestions/slice-issue-87994.rs | 16 + .../ui/suggestions/slice-issue-87994.stderr | 83 + .../ui/suggestions/suggest-change-mut.stderr | 4 +- .../suggest-imm-mut-trait-implementations.rs | 23 + ...ggest-imm-mut-trait-implementations.stderr | 59 + .../ui/suggestions/suggest-ref-macro.stderr | 2 +- .../ui/suggestions/suggest-trait-items.rs | 48 + .../ui/suggestions/suggest-trait-items.stderr | 74 + ...e-mismatch-struct-field-shorthand-2.stderr | 20 +- ...ype-mismatch-struct-field-shorthand.stderr | 30 +- ...onst-generics-structural-demangling.stderr | 6 +- .../{issues => symbol-names}/issue-53912.rs | 0 src/test/ui/tail-typeck.stderr | 2 +- .../ui/{issues => test-attrs}/issue-36768.rs | 0 .../test-attrs/test-should-panic-attr.stderr | 8 +- src/test/ui/{ => thread-local}/tls.rs | 0 .../sendfn-spawn-with-fn-arg.rs | 4 +- .../task-spawn-move-and-copy.rs | 4 +- src/test/ui/trace_macros-format.stderr | 12 +- src/test/ui/traits/alias/no-duplicates.stderr | 54 +- .../ui/traits/alias/no-extra-traits.stderr | 56 +- .../issue_89119_intercrate_caching.rs | 60 + src/test/ui/traits/bad-sized.stderr | 2 +- src/test/ui/traits/bound/in-arc.rs | 11 +- .../ui/traits/bound/same-crate-name.stderr | 16 +- src/test/ui/{ => traits}/bug-7183-generics.rs | 0 src/test/ui/traits/coercion.rs | 1 - src/test/ui/traits/conditional-dispatch.rs | 3 +- ...trait-has-wrong-lifetime-parameters.stderr | 4 +- .../supertrait-auto-trait.stderr | 12 +- src/test/ui/{issues => traits}/issue-20692.rs | 0 .../ui/{issues => traits}/issue-20692.stderr | 0 src/test/ui/{issues => traits}/issue-23825.rs | 0 src/test/ui/traits/issue-52893.rs | 57 + src/test/ui/traits/issue-52893.stderr | 15 + src/test/ui/traits/issue-6128.rs | 4 +- src/test/ui/traits/issue-68295.rs | 47 + src/test/ui/traits/issue-68295.stderr | 17 + src/test/ui/traits/issue-89119.rs | 11 + src/test/ui/traits/item-privacy.stderr | 6 +- src/test/ui/traits/kindck-owned-contains-1.rs | 6 +- src/test/ui/traits/matching-lifetimes.stderr | 8 +- src/test/ui/traits/multidispatch-bad.stderr | 2 +- .../mutual-recursion-issue-75860.stderr | 2 +- .../negated-auto-traits-error.stderr | 44 +- ...super-trait.rs => normalize-supertrait.rs} | 0 .../ui/traits/object-one-type-two-traits.rs | 4 +- src/test/ui/traits/object/generics.rs | 4 +- .../ui/traits/reservation-impl/no-use.stderr | 4 +- .../suggest-deferences/issue-39029.stderr | 9 +- .../suggest-deferences/issue-62530.stderr | 9 +- .../suggest-deferences/multiple-0.stderr | 9 +- .../suggest-deferences/multiple-1.stderr | 4 +- src/test/ui/traits/test-2.rs | 7 +- src/test/ui/traits/test-2.stderr | 37 +- .../issue-11515-upcast-fn_mut-fn.rs | 4 +- .../trait-upcasting/migrate-lint-deny.rs | 25 + .../trait-upcasting/migrate-lint-deny.stderr | 16 + .../type-checking-test-3.stderr | 4 +- .../type-checking-test-4.stderr | 4 +- src/test/ui/traits/vtable/vtable-diamond.rs | 4 +- .../ui/traits/vtable/vtable-diamond.stderr | 4 +- .../ui/traits/vtable/vtable-multi-level.rs | 24 +- .../traits/vtable/vtable-multi-level.stderr | 24 +- src/test/ui/traits/vtable/vtable-multiple.rs | 4 +- .../ui/traits/vtable/vtable-multiple.stderr | 4 +- .../traits/vtable/vtable-non-object-safe.rs | 18 + .../vtable/vtable-non-object-safe.stderr | 16 + src/test/ui/traits/vtable/vtable-vacant.rs | 9 +- .../ui/traits/vtable/vtable-vacant.stderr | 6 +- .../ui/traits/wf-object/no-duplicates.stderr | 10 +- .../trivial-bounds-inconsistent-copy.stderr | 8 +- ...ounds-inconsistent-projection-error.stderr | 2 +- ...vial-bounds-inconsistent-projection.stderr | 14 +- .../trivial-bounds-inconsistent-sized.stderr | 6 +- ...ial-bounds-inconsistent-well-formed.stderr | 4 +- .../trivial-bounds-inconsistent.stderr | 26 +- .../trivial-bounds/trivial-bounds-leak.stderr | 8 +- .../trivial-bounds/trivial-bounds-lint.stderr | 14 +- .../ui/try-block/try-block-opt-init.stderr | 2 +- .../try-block/try-block-unused-delims.stderr | 38 +- .../ui/tutorial-suffix-inference-test.stderr | 14 +- .../auto-trait-leakage3.stderr | 2 +- .../type-alias-impl-trait/bound_reduction2.rs | 5 + .../bound_reduction2.stderr | 62 +- .../bounds-are-checked.stderr | 2 +- .../generic_duplicate_lifetime_param.rs | 1 + .../generic_duplicate_lifetime_param.stderr | 10 +- .../generic_duplicate_param_use.rs | 3 + .../generic_duplicate_param_use.stderr | 30 +- .../generic_duplicate_param_use2.rs | 1 + .../generic_duplicate_param_use2.stderr | 16 +- .../generic_duplicate_param_use3.rs | 2 + .../generic_duplicate_param_use3.stderr | 28 +- .../generic_duplicate_param_use4.rs | 1 + .../generic_duplicate_param_use4.stderr | 16 +- .../generic_nondefining_use.rs | 3 + .../generic_nondefining_use.stderr | 28 +- .../incomplete-inference.rs | 1 - .../incomplete-inference.stderr | 14 +- .../inference-cycle.stderr | 2 +- .../ui/type-alias-impl-trait/issue-60371.rs | 1 + .../type-alias-impl-trait/issue-60371.stderr | 11 +- .../ui/type-alias-impl-trait/issue-60564.rs | 1 + .../type-alias-impl-trait/issue-60564.stderr | 10 +- .../issue-68368-non-defining-use-2.rs | 14 + .../issue-68368-non-defining-use-2.stderr | 20 + .../issue-68368-non-defining-use.rs | 1 + .../issue-68368-non-defining-use.stderr | 10 +- .../ui/type-alias-impl-trait/issue-74761-2.rs | 1 - .../issue-74761-2.stderr | 4 +- .../multiple-def-uses-in-one-fn3.rs | 1 - .../multiple-def-uses-in-one-fn3.stderr | 17 +- .../not_a_defining_use.rs | 2 + .../not_a_defining_use.stderr | 29 +- src/test/ui/type-param-constraints.rs | 10 +- .../ui/type/type-ascription-precedence.stderr | 17 +- ...check-fn-with-more-than-65535-arguments.rs | 12 + ...k-fn-with-more-than-65535-arguments.stderr | 13 + ...ter-defaults-referencing-Self-ppaux.stderr | 2 +- src/test/ui/typeck/call-block.rs | 3 + src/test/ui/typeck/call-block.stderr | 11 + .../issue-87771-ice-assign-assign-to-bool.rs | 4 + ...sue-87771-ice-assign-assign-to-bool.stderr | 9 + src/test/ui/typeck/issue-88609.rs | 19 + .../typeck/issue-88803-call-expr-method.fixed | 9 + .../ui/typeck/issue-88803-call-expr-method.rs | 9 + .../issue-88803-call-expr-method.stderr | 15 + src/test/ui/typeck/issue-88844.rs | 14 + src/test/ui/typeck/issue-88844.stderr | 12 + .../issue-89044-wrapped-expr-method.fixed | 9 + .../typeck/issue-89044-wrapped-expr-method.rs | 9 + .../issue-89044-wrapped-expr-method.stderr | 14 + src/test/ui/typeck/issue-89275.rs | 29 + src/test/ui/typeck/issue-89275.stderr | 14 + src/test/ui/typeck/issue-89935.rs | 18 + ...sue-90483-inaccessible-field-adjustment.rs | 14 + ...90483-inaccessible-field-adjustment.stderr | 14 + .../typeck/typeck-unsafe-always-share.stderr | 12 +- src/test/ui/typeclasses-eq-example-static.rs | 9 +- src/test/ui/typeclasses-eq-example.rs | 9 +- src/test/ui/typeof/type_mismatch.stderr | 2 +- src/test/ui/ufcs/ufcs-explicit-self-bad.rs | 12 +- .../ui/ufcs/ufcs-explicit-self-bad.stderr | 16 +- .../ui/ufcs/ufcs-qpath-self-mismatch.stderr | 4 +- .../unboxed-closure-illegal-move.stderr | 20 +- .../unboxed-closures-boxed.rs | 3 +- .../unboxed-closures-fnmut-as-fn.stderr | 4 +- ...-argument-types-two-region-pointers.stderr | 4 +- .../unboxed-closures-type-mismatch.stderr | 2 +- .../unboxed-closures-unsafe-extern-fn.stderr | 12 +- .../unboxed-closures-wrong-abi.stderr | 12 +- ...d-closures-wrong-arg-type-extern-fn.stderr | 12 +- src/test/ui/underscore-imports/shadow.stderr | 6 +- .../ui/uninhabited/uninhabited-patterns.rs | 2 +- .../union-derive-clone.mirunsafeck.stderr | 4 + .../union-derive-clone.thirunsafeck.stderr | 4 + src/test/ui/unique-object-noncopyable.rs | 6 +- src/test/ui/unique-pinned-nocopy.stderr | 4 + src/test/ui/unique/unique-assign-copy.rs | 3 +- src/test/ui/unique/unique-assign-drop.rs | 6 +- src/test/ui/unique/unique-assign-generic.rs | 5 +- src/test/ui/unique/unique-assign.rs | 3 +- src/test/ui/unique/unique-autoderef-field.rs | 5 +- src/test/ui/unique/unique-autoderef-index.rs | 3 +- src/test/ui/unique/unique-cmp.rs | 13 +- src/test/ui/unique/unique-containing-tag.rs | 8 +- src/test/ui/unique/unique-create.rs | 4 +- src/test/ui/unique/unique-decl-init-copy.rs | 3 +- src/test/ui/unique/unique-decl-init.rs | 3 +- src/test/ui/unique/unique-decl-move.rs | 3 +- src/test/ui/unique/unique-deref.rs | 3 +- src/test/ui/unique/unique-destructure.rs | 3 +- src/test/ui/unique/unique-drop-complex.rs | 4 +- src/test/ui/unique/unique-fn-arg-move.rs | 3 +- src/test/ui/unique/unique-fn-arg-mut.rs | 5 +- src/test/ui/unique/unique-fn-arg.rs | 5 +- src/test/ui/unique/unique-fn-ret.rs | 5 +- src/test/ui/unique/unique-in-tag.rs | 4 +- src/test/ui/unique/unique-in-vec-copy.rs | 3 +- src/test/ui/unique/unique-in-vec.rs | 5 +- src/test/ui/unique/unique-init.rs | 4 +- src/test/ui/unique/unique-kinds.rs | 25 +- src/test/ui/unique/unique-log.rs | 3 +- src/test/ui/unique/unique-move-drop.rs | 5 +- src/test/ui/unique/unique-move-temp.rs | 3 +- src/test/ui/unique/unique-move.rs | 3 +- src/test/ui/unique/unique-mutable.rs | 3 +- src/test/ui/unique/unique-object-move.rs | 4 +- src/test/ui/unique/unique-pat-2.rs | 10 +- src/test/ui/unique/unique-pat-3.rs | 17 +- src/test/ui/unique/unique-pat.rs | 3 +- src/test/ui/unique/unique-rec.rs | 3 +- src/test/ui/unique/unique-send-2.rs | 4 +- src/test/ui/unique/unique-send.rs | 5 +- src/test/ui/unique/unique-swap.rs | 9 +- src/test/ui/unop-move-semantics.stderr | 2 +- src/test/ui/unsafe/inline_asm.mir.stderr | 4 +- src/test/ui/unsafe/inline_asm.thir.stderr | 4 +- ...7-unnecessary-unsafe-in-closure.mir.stderr | 0 ...sue-45107-unnecessary-unsafe-in-closure.rs | 0 ...-unnecessary-unsafe-in-closure.thir.stderr | 0 .../ui/unsized-locals/unsized-exprs.stderr | 6 +- src/test/ui/unsized/unsized2.rs | 5 +- src/test/ui/unsized/unsized3-rpass.rs | 10 +- src/test/ui/unsized/unsized3.rs | 4 +- src/test/ui/unsized/unsized3.stderr | 53 +- src/test/ui/unused-move-capture.rs | 4 +- src/test/ui/unused-move.rs | 6 +- src/test/ui/unwind-unique.rs | 4 +- ...use-after-move-implicity-coerced-object.rs | 8 +- ...after-move-implicity-coerced-object.stderr | 7 +- src/test/ui/use/use-after-move-self.rs | 6 +- src/test/ui/use/use-from-trait-xc.stderr | 2 +- .../variance-associated-types2.nll.stderr | 2 - .../variance-associated-types2.stderr | 2 +- .../variance-btree-invariant-types.nll.stderr | 32 - .../variance-btree-invariant-types.stderr | 32 +- .../variance-contravariant-arg-object.stderr | 8 +- ...iance-contravariant-arg-trait-match.stderr | 8 +- ...ance-contravariant-self-trait-match.stderr | 16 +- .../variance-covariant-arg-object.stderr | 8 +- .../variance-covariant-arg-trait-match.stderr | 8 +- ...variance-covariant-self-trait-match.stderr | 16 +- .../variance-invariant-arg-object.stderr | 8 +- .../variance-invariant-arg-trait-match.stderr | 8 +- ...variance-invariant-self-trait-match.stderr | 16 +- ...variance-use-contravariant-struct-1.stderr | 4 +- .../variance-use-covariant-struct-1.stderr | 4 +- .../variance-use-invariant-struct-1.stderr | 8 +- src/test/ui/vtable-res-trait-param.stderr | 4 +- src/test/ui/wasm/simd-to-array-80108.rs | 15 + .../ui/weak-new-uninhabited-issue-48493.rs | 4 +- src/test/ui/wf/hir-wf-check-erase-regions.rs | 2 +- src/test/ui/wf/issue-87495.stderr | 2 +- .../wf-in-foreign-fn-decls-issue-80468.stderr | 2 +- src/test/ui/wf/wf-object-safe.stderr | 2 +- src/test/ui/wf/wf-static-method.stderr | 24 +- ...traints-are-local-for-inherent-impl.stderr | 4 +- ...onstraints-are-local-for-trait-impl.stderr | 4 +- .../where-clauses-method-unsatisfied.stderr | 4 +- src/test/ui/while-let.stderr | 4 +- src/test/ui/wrong-ret-type.stderr | 2 +- src/tools/build-manifest/Cargo.toml | 2 +- src/tools/build-manifest/src/main.rs | 1 + src/tools/bump-stage0/Cargo.toml | 14 + src/tools/bump-stage0/src/main.rs | 204 + src/tools/cargotest/Cargo.toml | 2 +- src/tools/clippy/.cargo/config | 8 +- .../.github/ISSUE_TEMPLATE/blank_issue.md | 14 + .../.github/ISSUE_TEMPLATE/bug_report.md | 40 +- .../.github/ISSUE_TEMPLATE/false_negative.md | 22 +- .../.github/ISSUE_TEMPLATE/false_positive.md | 31 +- .../clippy/.github/ISSUE_TEMPLATE/ice.md | 21 +- .../clippy/.github/workflows/clippy_dev.yml | 3 - src/tools/clippy/CHANGELOG.md | 118 +- src/tools/clippy/Cargo.toml | 33 +- src/tools/clippy/README.md | 10 +- src/tools/clippy/clippy_dev/Cargo.toml | 8 +- src/tools/clippy/clippy_dev/src/bless.rs | 20 +- src/tools/clippy/clippy_dev/src/lib.rs | 524 +- src/tools/clippy/clippy_dev/src/main.rs | 9 +- .../clippy_dev/src/stderr_length_check.rs | 51 - .../clippy/clippy_dev/src/update_lints.rs | 675 ++- src/tools/clippy/clippy_dummy/Cargo.toml | 2 +- src/tools/clippy/clippy_lints/Cargo.toml | 20 +- .../clippy/clippy_lints/src/approx_const.rs | 128 +- .../src/assertions_on_constants.rs | 2 +- src/tools/clippy/clippy_lints/src/attrs.rs | 6 +- .../clippy_lints/src/await_holding_invalid.rs | 2 +- .../src/blocks_in_if_conditions.rs | 4 +- .../src/bool_assert_comparison.rs | 90 +- src/tools/clippy/clippy_lints/src/booleans.rs | 4 +- .../clippy/clippy_lints/src/bytecount.rs | 4 +- .../clippy_lints/src/cargo_common_metadata.rs | 18 +- ...se_sensitive_file_extension_comparisons.rs | 2 +- .../src/casts/cast_precision_loss.rs | 2 +- .../src/casts/cast_ptr_alignment.rs | 6 +- .../clippy_lints/src/cognitive_complexity.rs | 4 +- .../clippy_lints/src/collapsible_match.rs | 39 +- src/tools/clippy/clippy_lints/src/copies.rs | 22 +- .../clippy/clippy_lints/src/dereference.rs | 2 +- .../clippy_lints/src/derivable_impls.rs | 118 + src/tools/clippy/clippy_lints/src/derive.rs | 7 +- .../clippy_lints/src/disallowed_method.rs | 86 +- .../clippy_lints/src/disallowed_type.rs | 6 +- src/tools/clippy/clippy_lints/src/doc.rs | 37 +- src/tools/clippy/clippy_lints/src/entry.rs | 44 +- .../clippy_lints/src/equatable_if_let.rs | 100 + .../clippy/clippy_lints/src/erasing_op.rs | 2 +- src/tools/clippy/clippy_lints/src/escape.rs | 14 +- .../clippy/clippy_lints/src/eta_reduction.rs | 247 +- .../clippy_lints/src/eval_order_dependence.rs | 6 +- .../clippy_lints/src/fallible_impl_from.rs | 8 +- .../clippy/clippy_lints/src/feature_name.rs | 164 + .../clippy/clippy_lints/src/float_literal.rs | 2 +- .../src/floating_point_arithmetic.rs | 32 +- src/tools/clippy/clippy_lints/src/format.rs | 15 +- .../clippy/clippy_lints/src/formatting.rs | 57 +- .../clippy/clippy_lints/src/from_over_into.rs | 2 +- .../clippy_lints/src/from_str_radix_10.rs | 2 +- .../clippy_lints/src/functions/must_use.rs | 1 - .../src/functions/result_unit_err.rs | 2 +- .../clippy_lints/src/future_not_send.rs | 2 +- .../clippy_lints/src/get_last_with_len.rs | 2 +- .../clippy/clippy_lints/src/identity_op.rs | 14 +- .../clippy/clippy_lints/src/if_let_mutex.rs | 9 +- .../clippy_lints/src/implicit_hasher.rs | 32 +- .../clippy/clippy_lints/src/infinite_iter.rs | 8 +- .../clippy/clippy_lints/src/inherent_impl.rs | 4 +- .../clippy_lints/src/inherent_to_string.rs | 2 +- .../clippy/clippy_lints/src/int_plus_one.rs | 4 +- .../clippy_lints/src/integer_division.rs | 2 +- .../src/invalid_upcast_comparisons.rs | 2 +- .../src/iter_not_returning_iterator.rs | 64 + .../clippy_lints/src/large_const_arrays.rs | 3 +- .../clippy_lints/src/large_enum_variant.rs | 163 +- .../clippy_lints/src/large_stack_arrays.rs | 3 +- src/tools/clippy/clippy_lints/src/len_zero.rs | 16 +- .../clippy/clippy_lints/src/let_if_seq.rs | 21 +- .../clippy/clippy_lints/src/lib.deprecated.rs | 70 + .../clippy_lints/src/lib.register_all.rs | 302 ++ .../clippy_lints/src/lib.register_cargo.rs | 11 + .../src/lib.register_complexity.rs | 94 + .../src/lib.register_correctness.rs | 72 + .../clippy_lints/src/lib.register_internal.rs | 18 + .../clippy_lints/src/lib.register_lints.rs | 509 ++ .../clippy_lints/src/lib.register_nursery.rs | 30 + .../clippy_lints/src/lib.register_pedantic.rs | 101 + .../clippy_lints/src/lib.register_perf.rs | 27 + .../src/lib.register_restriction.rs | 65 + .../clippy_lints/src/lib.register_style.rs | 113 + .../src/lib.register_suspicious.rs | 20 + src/tools/clippy/clippy_lints/src/lib.rs | 1432 +---- .../src/loops/explicit_iter_loop.rs | 8 +- .../clippy_lints/src/loops/for_kv_map.rs | 18 +- .../src/loops/for_loops_over_fallibles.rs | 4 +- .../clippy_lints/src/loops/iter_next_loop.rs | 4 +- .../clippy_lints/src/loops/manual_flatten.rs | 6 +- .../clippy_lints/src/loops/manual_memcpy.rs | 2 +- .../clippy/clippy_lints/src/loops/mod.rs | 27 +- .../clippy_lints/src/loops/mut_range_bound.rs | 100 +- .../src/loops/needless_collect.rs | 14 +- .../src/loops/needless_range_loop.rs | 35 +- .../clippy_lints/src/loops/never_loop.rs | 6 +- .../clippy_lints/src/loops/same_item_push.rs | 2 +- .../clippy/clippy_lints/src/loops/utils.rs | 2 +- .../clippy_lints/src/loops/while_let_loop.rs | 8 +- .../src/loops/while_let_on_iterator.rs | 24 +- .../clippy/clippy_lints/src/macro_use.rs | 51 +- .../clippy/clippy_lints/src/main_recursion.rs | 4 +- .../clippy/clippy_lints/src/manual_assert.rs | 99 + .../clippy_lints/src/manual_async_fn.rs | 4 +- .../clippy/clippy_lints/src/manual_map.rs | 340 +- .../clippy/clippy_lints/src/manual_ok_or.rs | 2 +- .../clippy_lints/src/manual_unwrap_or.rs | 4 +- .../clippy/clippy_lints/src/map_clone.rs | 2 +- .../clippy/clippy_lints/src/map_unit_fn.rs | 15 +- .../clippy_lints/src/match_on_vec_items.rs | 2 +- ..._let_some_result.rs => match_result_ok.rs} | 61 +- src/tools/clippy/clippy_lints/src/matches.rs | 31 +- .../clippy_lints/src/mem_discriminant.rs | 82 - .../clippy/clippy_lints/src/mem_forget.rs | 4 +- .../clippy/clippy_lints/src/mem_replace.rs | 85 +- .../clippy_lints/src/methods/bytes_nth.rs | 2 +- .../clippy_lints/src/methods/clone_on_copy.rs | 4 +- .../src/methods/cloned_instead_of_copied.rs | 2 +- .../src/methods/expect_fun_call.rs | 8 +- .../clippy_lints/src/methods/expect_used.rs | 4 +- .../src/methods/extend_with_drain.rs | 4 +- .../clippy_lints/src/methods/filter_map.rs | 6 +- .../clippy_lints/src/methods/filter_next.rs | 7 +- .../src/methods/flat_map_option.rs | 2 +- .../clippy_lints/src/methods/get_unwrap.rs | 6 +- .../src/methods/inefficient_to_string.rs | 2 +- .../src/methods/iter_cloned_collect.rs | 2 +- .../clippy_lints/src/methods/iter_count.rs | 8 +- .../src/methods/iter_next_slice.rs | 2 +- .../clippy_lints/src/methods/iter_nth.rs | 4 +- .../methods/manual_saturating_arithmetic.rs | 2 +- .../src/methods/manual_split_once.rs | 211 + .../src/methods/manual_str_repeat.rs | 6 +- .../src/methods/map_collect_result_unit.rs | 2 +- .../clippy_lints/src/methods/map_flatten.rs | 6 +- .../clippy_lints/src/methods/map_identity.rs | 4 +- .../clippy_lints/src/methods/map_unwrap_or.rs | 4 +- .../clippy/clippy_lints/src/methods/mod.rs | 55 +- .../clippy_lints/src/methods/ok_expect.rs | 6 +- .../src/methods/option_as_ref_deref.rs | 2 +- .../src/methods/option_map_or_none.rs | 4 +- .../src/methods/option_map_unwrap_or.rs | 2 +- .../clippy_lints/src/methods/or_fun_call.rs | 18 +- .../src/methods/search_is_some.rs | 2 +- .../src/methods/string_extend_chars.rs | 4 +- .../src/methods/suspicious_map.rs | 2 +- .../src/methods/suspicious_splitn.rs | 14 +- .../src/methods/unnecessary_filter_map.rs | 3 +- .../src/methods/unnecessary_lazy_eval.rs | 4 +- .../src/methods/unwrap_or_else_default.rs | 4 +- .../clippy_lints/src/methods/unwrap_used.rs | 4 +- .../clippy/clippy_lints/src/methods/utils.rs | 8 +- src/tools/clippy/clippy_lints/src/misc.rs | 6 +- .../clippy/clippy_lints/src/missing_doc.rs | 9 +- .../src/missing_enforced_import_rename.rs | 4 +- .../clippy/clippy_lints/src/module_style.rs | 178 + .../clippy_lints/src/modulo_arithmetic.rs | 2 +- .../src/multiple_crate_versions.rs | 4 +- src/tools/clippy/clippy_lints/src/mut_key.rs | 81 +- .../clippy/clippy_lints/src/mut_mutex_lock.rs | 7 +- .../clippy/clippy_lints/src/mutex_atomic.rs | 3 +- .../clippy/clippy_lints/src/needless_bool.rs | 2 +- .../clippy_lints/src/needless_borrow.rs | 32 +- .../clippy_lints/src/needless_continue.rs | 13 +- .../src/needless_option_as_deref.rs | 66 + .../src/needless_pass_by_value.rs | 4 +- .../clippy/clippy_lints/src/neg_multiply.rs | 2 +- .../clippy_lints/src/new_without_default.rs | 2 +- .../clippy/clippy_lints/src/no_effect.rs | 71 +- .../clippy_lints/src/non_expressive_names.rs | 2 +- .../src/non_send_fields_in_send_ty.rs | 238 + .../clippy/clippy_lints/src/open_options.rs | 6 +- .../clippy_lints/src/option_if_let_else.rs | 48 +- .../src/overflow_check_conditional.rs | 31 +- .../clippy_lints/src/panic_in_result_fn.rs | 2 +- .../clippy_lints/src/pass_by_ref_or_value.rs | 2 +- .../clippy_lints/src/pattern_type_mismatch.rs | 2 +- src/tools/clippy/clippy_lints/src/ptr.rs | 6 +- .../clippy_lints/src/ptr_offset_with_cast.rs | 8 +- .../clippy/clippy_lints/src/question_mark.rs | 7 +- .../clippy_lints/src/redundant_clone.rs | 9 +- .../src/redundant_closure_call.rs | 4 +- .../clippy_lints/src/redundant_pub_crate.rs | 36 +- .../clippy/clippy_lints/src/ref_option_ref.rs | 2 +- src/tools/clippy/clippy_lints/src/regex.rs | 15 +- .../clippy/clippy_lints/src/repeat_once.rs | 4 +- src/tools/clippy/clippy_lints/src/returns.rs | 16 +- .../clippy_lints/src/same_name_method.rs | 160 + src/tools/clippy/clippy_lints/src/shadow.rs | 441 +- .../src/slow_vector_initialization.rs | 2 +- src/tools/clippy/clippy_lints/src/strings.rs | 12 +- src/tools/clippy/clippy_lints/src/swap.rs | 6 +- .../clippy_lints/src/tabs_in_doc_comments.rs | 1 + .../clippy_lints/src/to_string_in_display.rs | 4 +- .../transmute/unsound_collection_transmute.rs | 8 +- .../clippy_lints/src/transmuting_null.rs | 4 +- src/tools/clippy/clippy_lints/src/try_err.rs | 8 +- .../clippy_lints/src/types/box_collection.rs | 50 + .../clippy/clippy_lints/src/types/box_vec.rs | 25 - .../clippy/clippy_lints/src/types/mod.rs | 91 +- .../clippy_lints/src/types/option_option.rs | 4 +- .../clippy_lints/src/types/rc_buffer.rs | 6 +- .../clippy/clippy_lints/src/types/rc_mutex.rs | 13 +- .../src/types/redundant_allocation.rs | 8 +- .../clippy/clippy_lints/src/types/vec_box.rs | 4 +- .../src/undropped_manually_drops.rs | 4 +- .../clippy_lints/src/unnecessary_sort_by.rs | 7 +- .../clippy_lints/src/unnecessary_wraps.rs | 4 +- .../clippy/clippy_lints/src/unused_async.rs | 7 +- .../clippy_lints/src/unused_io_amount.rs | 8 +- .../clippy/clippy_lints/src/unused_self.rs | 5 +- src/tools/clippy/clippy_lints/src/unwrap.rs | 137 +- .../clippy_lints/src/unwrap_in_result.rs | 12 +- .../clippy_lints/src/useless_conversion.rs | 8 +- .../clippy/clippy_lints/src/utils/conf.rs | 22 +- .../clippy_lints/src/utils/inspector.rs | 2 +- .../clippy_lints/src/utils/internal_lints.rs | 51 +- .../internal_lints/metadata_collector.rs | 5 +- src/tools/clippy/clippy_lints/src/vec.rs | 4 +- .../clippy_lints/src/vec_init_then_push.rs | 8 +- .../clippy_lints/src/wildcard_dependencies.rs | 4 +- .../clippy/clippy_lints/src/zero_div_zero.rs | 2 +- .../clippy_lints/src/zero_sized_map_values.rs | 4 +- src/tools/clippy/clippy_utils/Cargo.toml | 12 +- .../clippy/clippy_utils/src/ast_utils.rs | 85 +- .../clippy/clippy_utils/src/diagnostics.rs | 2 +- .../clippy/clippy_utils/src/eager_or_lazy.rs | 9 +- src/tools/clippy/clippy_utils/src/higher.rs | 233 +- .../clippy/clippy_utils/src/hir_utils.rs | 8 +- src/tools/clippy/clippy_utils/src/lib.rs | 403 +- src/tools/clippy/clippy_utils/src/msrvs.rs | 3 + .../clippy_utils/src/numeric_literal.rs | 15 +- src/tools/clippy/clippy_utils/src/paths.rs | 14 +- .../clippy_utils/src/qualify_min_const_fn.rs | 8 +- src/tools/clippy/clippy_utils/src/sugg.rs | 4 +- src/tools/clippy/clippy_utils/src/ty.rs | 25 +- src/tools/clippy/clippy_utils/src/usage.rs | 13 +- src/tools/clippy/clippy_utils/src/visitors.rs | 117 +- src/tools/clippy/doc/adding_lints.md | 9 +- .../clippy/doc/common_tools_writing_lints.md | 27 +- src/tools/clippy/lintcheck/Cargo.toml | 17 +- src/tools/clippy/lintcheck/src/main.rs | 64 +- src/tools/clippy/rust-toolchain | 2 +- src/tools/clippy/src/main.rs | 20 +- src/tools/clippy/tests/cargo/mod.rs | 22 - src/tools/clippy/tests/compile-test.rs | 188 +- src/tools/clippy/tests/dogfood.rs | 14 +- src/tools/clippy/tests/fmt.rs | 3 + src/tools/clippy/tests/integration.rs | 9 +- .../clippy/tests/lint_message_convention.rs | 3 + src/tools/clippy/tests/missing-test-files.rs | 2 + .../ui-cargo/feature_name/fail/Cargo.toml | 21 + .../ui-cargo/feature_name/fail/src/main.rs | 7 + .../feature_name/fail/src/main.stderr | 44 + .../ui-cargo/feature_name/pass/Cargo.toml | 9 + .../ui-cargo/feature_name/pass/src/main.rs | 7 + .../ui-cargo/module_style/fail_mod/Cargo.toml | 8 + .../module_style/fail_mod/src/bad/inner.rs | 1 + .../fail_mod/src/bad/inner/stuff.rs | 3 + .../fail_mod/src/bad/inner/stuff/most.rs | 1 + .../module_style/fail_mod/src/bad/mod.rs | 3 + .../module_style/fail_mod/src/main.rs | 9 + .../module_style/fail_mod/src/main.stderr | 19 + .../module_style/fail_no_mod/Cargo.toml | 8 + .../module_style/fail_no_mod/src/bad/mod.rs | 1 + .../module_style/fail_no_mod/src/main.rs | 7 + .../module_style/fail_no_mod/src/main.stderr | 11 + .../ui-cargo/module_style/pass_mod/Cargo.toml | 8 + .../module_style/pass_mod/src/bad/mod.rs | 1 + .../module_style/pass_mod/src/main.rs | 10 + .../module_style/pass_mod/src/more/foo.rs | 1 + .../pass_mod/src/more/inner/mod.rs | 1 + .../module_style/pass_mod/src/more/mod.rs | 2 + .../module_style/pass_no_mod/Cargo.toml | 8 + .../module_style/pass_no_mod/src/good.rs | 1 + .../module_style/pass_no_mod/src/main.rs | 7 + .../tests/ui-internal/invalid_paths.stderr | 2 +- .../match_type_on_diag_item.stderr | 4 +- .../conf_nonstandard_macro_braces.stderr | 6 +- .../clippy.toml | 1 + .../strict_non_send_fields_in_send_ty/test.rs | 43 + .../test.stderr | 91 + .../toml_disallowed_method/clippy.toml | 7 +- .../conf_disallowed_method.stderr | 8 +- .../tests/ui-toml/toml_trivially_copy/test.rs | 1 - .../ui-toml/toml_trivially_copy/test.stderr | 4 +- .../toml_unknown_key/conf_unknown_key.stderr | 2 +- src/tools/clippy/tests/ui/approx_const.rs | 6 +- src/tools/clippy/tests/ui/approx_const.stderr | 101 +- src/tools/clippy/tests/ui/asm_syntax.stderr | 10 +- .../tests/ui/assertions_on_constants.stderr | 18 +- .../tests/ui/auxiliary/option_helpers.rs | 9 + .../proc_macro_suspicious_else_formatting.rs | 75 + .../clippy/tests/ui/bool_assert_comparison.rs | 63 + .../tests/ui/bool_assert_comparison.stderr | 98 +- src/tools/clippy/tests/ui/box_collection.rs | 44 + .../clippy/tests/ui/box_collection.stderr | 27 + src/tools/clippy/tests/ui/box_vec.rs | 32 - src/tools/clippy/tests/ui/box_vec.stderr | 11 - .../branches_sharing_code/shared_at_bottom.rs | 2 +- .../clippy/tests/ui/cast_lossless_float.fixed | 22 +- .../clippy/tests/ui/cast_lossless_float.rs | 22 +- .../tests/ui/cast_lossless_float.stderr | 66 +- .../tests/ui/cast_lossless_integer.fixed | 38 +- .../clippy/tests/ui/cast_lossless_integer.rs | 38 +- .../tests/ui/cast_lossless_integer.stderr | 114 +- .../complex_conditionals.stderr | 39 +- .../complex_conditionals_nested.stderr | 4 +- .../ui/checked_unwrap/simple_conditionals.rs | 4 + .../checked_unwrap/simple_conditionals.stderr | 128 +- .../clippy/tests/ui/collapsible_else_if.fixed | 2 +- .../clippy/tests/ui/collapsible_else_if.rs | 2 +- .../clippy/tests/ui/collapsible_if.fixed | 2 +- src/tools/clippy/tests/ui/collapsible_if.rs | 2 +- .../clippy/tests/ui/collapsible_match.rs | 7 +- .../clippy/tests/ui/collapsible_match.stderr | 40 +- .../clippy/tests/ui/collapsible_match2.stderr | 2 +- src/tools/clippy/tests/ui/crashes/ice-3462.rs | 2 +- .../clippy/tests/ui/crashes/ice-6255.stderr | 2 +- .../clippy/tests/ui/crashes/ice-6256.stderr | 2 +- .../tests/ui/crashes/issues_loop_mut_cond.rs | 1 - .../others.stderr | 2 +- .../traits.stderr | 2 +- src/tools/clippy/tests/ui/def_id_nocore.rs | 6 +- .../clippy/tests/ui/def_id_nocore.stderr | 2 +- .../ui/default_numeric_fallback_f64.stderr | 2 +- .../ui/default_numeric_fallback_i32.stderr | 2 +- .../tests/ui/default_trait_access.fixed | 2 +- .../clippy/tests/ui/default_trait_access.rs | 2 +- src/tools/clippy/tests/ui/deref_addrof.fixed | 2 +- src/tools/clippy/tests/ui/deref_addrof.rs | 2 +- src/tools/clippy/tests/ui/derivable_impls.rs | 243 + .../clippy/tests/ui/derivable_impls.stderr | 89 + src/tools/clippy/tests/ui/doc/doc.rs | 5 + src/tools/clippy/tests/ui/doc_unsafe.rs | 21 +- src/tools/clippy/tests/ui/doc_unsafe.stderr | 16 +- src/tools/clippy/tests/ui/entry.fixed | 15 +- src/tools/clippy/tests/ui/entry.rs | 9 +- src/tools/clippy/tests/ui/entry.stderr | 16 +- src/tools/clippy/tests/ui/entry_btree.fixed | 18 + src/tools/clippy/tests/ui/entry_btree.rs | 18 + src/tools/clippy/tests/ui/entry_btree.stderr | 20 + src/tools/clippy/tests/ui/eq_op.rs | 2 +- src/tools/clippy/tests/ui/eq_op_macros.stderr | 8 +- .../clippy/tests/ui/equatable_if_let.fixed | 69 + src/tools/clippy/tests/ui/equatable_if_let.rs | 69 + .../clippy/tests/ui/equatable_if_let.stderr | 64 + src/tools/clippy/tests/ui/eta.fixed | 64 +- src/tools/clippy/tests/ui/eta.rs | 56 +- src/tools/clippy/tests/ui/eta.stderr | 70 +- .../clippy/tests/ui/eval_order_dependence.rs | 1 - .../tests/ui/eval_order_dependence.stderr | 16 +- .../clippy/tests/ui/excessive_precision.fixed | 16 +- .../clippy/tests/ui/excessive_precision.rs | 6 + .../tests/ui/excessive_precision.stderr | 44 +- .../tests/ui/explicit_deref_methods.fixed | 2 +- .../clippy/tests/ui/explicit_deref_methods.rs | 2 +- .../clippy/tests/ui/fallible_impl_from.stderr | 8 +- src/tools/clippy/tests/ui/float_cmp.rs | 3 +- src/tools/clippy/tests/ui/float_cmp.stderr | 12 +- .../clippy/tests/ui/for_loop_fixable.fixed | 9 +- src/tools/clippy/tests/ui/for_loop_fixable.rs | 9 +- .../clippy/tests/ui/for_loop_fixable.stderr | 30 +- .../clippy/tests/ui/for_loop_unfixable.rs | 9 +- .../clippy/tests/ui/for_loop_unfixable.stderr | 2 +- src/tools/clippy/tests/ui/format.stderr | 26 +- .../clippy/tests/ui/if_let_some_result.fixed | 28 - .../clippy/tests/ui/if_let_some_result.rs | 28 - .../clippy/tests/ui/if_same_then_else2.rs | 1 + .../clippy/tests/ui/if_same_then_else2.stderr | 24 +- src/tools/clippy/tests/ui/implicit_hasher.rs | 4 + .../clippy/tests/ui/implicit_hasher.stderr | 41 +- src/tools/clippy/tests/ui/infinite_loop.rs | 3 - .../clippy/tests/ui/infinite_loop.stderr | 22 +- .../clippy/tests/ui/inherent_to_string.rs | 1 - .../clippy/tests/ui/inherent_to_string.stderr | 4 +- .../clippy/tests/ui/integer_arithmetic.rs | 9 +- .../clippy/tests/ui/integer_arithmetic.stderr | 54 +- .../tests/ui/item_after_statement.stderr | 2 +- .../tests/ui/iter_not_returning_iterator.rs | 47 + .../ui/iter_not_returning_iterator.stderr | 16 + .../clippy/tests/ui/large_enum_variant.rs | 18 + .../clippy/tests/ui/large_enum_variant.stderr | 63 +- src/tools/clippy/tests/ui/linkedlist.rs | 31 +- src/tools/clippy/tests/ui/linkedlist.stderr | 24 +- src/tools/clippy/tests/ui/logic_bug.rs | 2 +- src/tools/clippy/tests/ui/manual_assert.fixed | 40 + src/tools/clippy/tests/ui/manual_assert.rs | 54 + .../clippy/tests/ui/manual_assert.stderr | 60 + src/tools/clippy/tests/ui/manual_flatten.rs | 13 + .../clippy/tests/ui/manual_map_option_2.fixed | 50 + .../clippy/tests/ui/manual_map_option_2.rs | 56 + .../tests/ui/manual_map_option_2.stderr | 43 + .../clippy/tests/ui/manual_split_once.fixed | 56 + .../clippy/tests/ui/manual_split_once.rs | 56 + .../clippy/tests/ui/manual_split_once.stderr | 106 + .../clippy/tests/ui/many_single_char_names.rs | 2 +- src/tools/clippy/tests/ui/map_clone.fixed | 14 +- src/tools/clippy/tests/ui/map_clone.rs | 14 +- src/tools/clippy/tests/ui/map_flatten.fixed | 1 + src/tools/clippy/tests/ui/map_flatten.rs | 1 + src/tools/clippy/tests/ui/map_flatten.stderr | 14 +- .../ui/match_expr_like_matches_macro.fixed | 2 +- .../tests/ui/match_expr_like_matches_macro.rs | 2 +- .../clippy/tests/ui/match_overlapping_arm.rs | 2 +- src/tools/clippy/tests/ui/match_ref_pats.rs | 1 + .../clippy/tests/ui/match_ref_pats.stderr | 16 +- .../clippy/tests/ui/match_result_ok.fixed | 63 + src/tools/clippy/tests/ui/match_result_ok.rs | 63 + ...e_result.stderr => match_result_ok.stderr} | 19 +- .../clippy/tests/ui/match_same_arms.stderr | 20 +- .../tests/ui/match_single_binding.fixed | 2 +- .../clippy/tests/ui/match_single_binding.rs | 2 +- .../clippy/tests/ui/mem_discriminant.fixed | 45 - src/tools/clippy/tests/ui/mem_discriminant.rs | 45 - .../clippy/tests/ui/mem_discriminant.stderr | 94 - .../tests/ui/mem_discriminant_unfixable.rs | 16 - .../ui/mem_discriminant_unfixable.stderr | 20 - src/tools/clippy/tests/ui/mem_replace.fixed | 20 + src/tools/clippy/tests/ui/mem_replace.rs | 20 + src/tools/clippy/tests/ui/mem_replace.stderr | 20 +- .../clippy/tests/ui/mem_replace_macro.stderr | 2 +- src/tools/clippy/tests/ui/methods.rs | 5 +- .../clippy/tests/ui/min_rust_version_attr.rs | 5 + .../tests/ui/min_rust_version_attr.stderr | 8 +- .../clippy/tests/ui/missing-doc-crate.stderr | 0 .../missing_const_for_fn/cant_be_const.stderr | 0 .../clippy/tests/ui/missing_panics_doc.stderr | 4 +- .../tests/ui/modulo_arithmetic_float.rs | 9 +- .../tests/ui/modulo_arithmetic_float.stderr | 20 +- .../tests/ui/modulo_arithmetic_integral.rs | 9 +- .../ui/modulo_arithmetic_integral.stderr | 34 +- .../ui/modulo_arithmetic_integral_const.rs | 9 +- .../modulo_arithmetic_integral_const.stderr | 34 +- src/tools/clippy/tests/ui/modulo_one.stderr | 8 +- src/tools/clippy/tests/ui/mut_key.rs | 34 +- src/tools/clippy/tests/ui/mut_key.stderr | 88 +- src/tools/clippy/tests/ui/mut_range_bound.rs | 39 +- .../clippy/tests/ui/mut_range_bound.stderr | 47 +- .../tests/ui/needless_bool/fixable.fixed | 1 + .../clippy/tests/ui/needless_bool/fixable.rs | 1 + .../tests/ui/needless_bool/fixable.stderr | 24 +- .../clippy/tests/ui/needless_borrow.fixed | 24 +- src/tools/clippy/tests/ui/needless_borrow.rs | 24 +- .../clippy/tests/ui/needless_borrow.stderr | 14 +- .../tests/ui/needless_option_as_deref.fixed | 13 + .../tests/ui/needless_option_as_deref.rs | 13 + .../tests/ui/needless_option_as_deref.stderr | 16 + .../clippy/tests/ui/needless_pass_by_value.rs | 1 - .../tests/ui/needless_pass_by_value.stderr | 52 +- .../clippy/tests/ui/needless_return.fixed | 9 +- src/tools/clippy/tests/ui/needless_return.rs | 9 +- .../clippy/tests/ui/needless_return.stderr | 64 +- .../tests/ui/non_send_fields_in_send_ty.rs | 127 + .../ui/non_send_fields_in_send_ty.stderr | 171 + src/tools/clippy/tests/ui/nonminimal_bool.rs | 2 +- .../tests/ui/nonminimal_bool_methods.rs | 2 +- src/tools/clippy/tests/ui/op_ref.rs | 1 - src/tools/clippy/tests/ui/op_ref.stderr | 4 +- .../clippy/tests/ui/option_if_let_else.fixed | 64 +- .../clippy/tests/ui/option_if_let_else.rs | 70 +- .../clippy/tests/ui/option_if_let_else.stderr | 72 +- .../tests/ui/overflow_check_conditional.rs | 1 - .../ui/overflow_check_conditional.stderr | 16 +- .../clippy/tests/ui/panic_in_result_fn.stderr | 12 +- .../ui/panic_in_result_fn_assertions.stderr | 6 +- .../clippy/tests/ui/panicking_macros.stderr | 32 +- .../ui/pattern_type_mismatch/syntax.stderr | 2 +- src/tools/clippy/tests/ui/proc_macro.stderr | 3 +- .../ui/rc_buffer_redefined_string.stderr | 0 src/tools/clippy/tests/ui/rc_mutex.rs | 32 +- src/tools/clippy/tests/ui/rc_mutex.stderr | 33 +- .../clippy/tests/ui/redundant_allocation.rs | 20 + .../tests/ui/redundant_allocation.stderr | 11 +- ...edundant_pattern_matching_drop_order.fixed | 2 +- .../redundant_pattern_matching_drop_order.rs | 2 +- .../redundant_pattern_matching_option.fixed | 1 + .../ui/redundant_pattern_matching_option.rs | 1 + .../redundant_pattern_matching_option.stderr | 38 +- .../ui/redundant_pattern_matching_poll.fixed | 1 + .../ui/redundant_pattern_matching_poll.rs | 1 + .../ui/redundant_pattern_matching_poll.stderr | 36 +- src/tools/clippy/tests/ui/rename.fixed | 1 + src/tools/clippy/tests/ui/rename.rs | 1 + src/tools/clippy/tests/ui/rename.stderr | 14 +- src/tools/clippy/tests/ui/repeat_once.fixed | 2 +- src/tools/clippy/tests/ui/repeat_once.rs | 2 +- src/tools/clippy/tests/ui/same_name_method.rs | 111 + .../clippy/tests/ui/same_name_method.stderr | 64 + .../tests/ui/semicolon_if_nothing_returned.rs | 5 +- .../ui/semicolon_if_nothing_returned.stderr | 12 +- src/tools/clippy/tests/ui/shadow.rs | 125 +- src/tools/clippy/tests/ui/shadow.stderr | 265 +- .../tests/ui/suspicious_else_formatting.rs | 9 + .../ui/suspicious_else_formatting.stderr | 18 +- .../clippy/tests/ui/suspicious_map.stderr | 4 +- .../ui/suspicious_operation_groupings.stderr | 8 +- .../clippy/tests/ui/toplevel_ref_arg.stderr | 2 +- .../ui/toplevel_ref_arg_non_rustfix.stderr | 2 +- .../tests/ui/trivially_copy_pass_by_ref.rs | 6 +- .../ui/trivially_copy_pass_by_ref.stderr | 34 +- src/tools/clippy/tests/ui/try_err.stderr | 4 +- src/tools/clippy/tests/ui/unit_cmp.stderr | 8 +- .../tests/ui/unnecessary_operation.fixed | 4 +- .../tests/ui/unnecessary_operation.stderr | 80 +- .../tests/ui/while_let_on_iterator.fixed | 26 +- .../clippy/tests/ui/while_let_on_iterator.rs | 8 +- .../tests/ui/while_let_on_iterator.stderr | 60 +- .../clippy/tests/ui/wrong_self_convention2.rs | 37 + src/tools/clippy/tests/versioncheck.rs | 3 + src/tools/clippy/util/etc/pre-commit.sh | 1 + src/tools/compiletest/Cargo.toml | 2 +- src/tools/compiletest/src/common.rs | 6 + src/tools/compiletest/src/compute_diff.rs | 157 + src/tools/compiletest/src/header.rs | 28 + src/tools/compiletest/src/main.rs | 3 + src/tools/compiletest/src/read2.rs | 71 + src/tools/compiletest/src/runtest.rs | 441 +- src/tools/compiletest/src/runtest/debugger.rs | 115 + src/tools/compiletest/src/util.rs | 4 +- src/tools/error_index_generator/Cargo.toml | 2 +- src/tools/error_index_generator/main.rs | 74 +- src/tools/expand-yaml-anchors/Cargo.toml | 2 +- src/tools/html-checker/Cargo.toml | 2 +- src/tools/jsondocck/Cargo.toml | 2 +- src/tools/linkchecker/Cargo.toml | 2 +- src/tools/linkchecker/main.rs | 26 + src/tools/lint-docs/Cargo.toml | 2 +- src/tools/lint-docs/src/lib.rs | 4 + src/tools/lld-wrapper/Cargo.toml | 4 +- src/tools/rust-demangler/Cargo.toml | 2 +- src/tools/rustbook/Cargo.toml | 2 +- src/tools/rustc-workspace-hack/Cargo.toml | 4 +- src/tools/rustdoc-gui/tester.js | 2 +- src/tools/rustdoc-themes/Cargo.toml | 2 +- src/tools/rustdoc/Cargo.toml | 2 +- src/tools/rustfmt/Cargo.toml | 2 +- src/tools/rustfmt/src/macros.rs | 42 +- src/tools/rustfmt/src/modules.rs | 2 - src/tools/rustfmt/src/syntux/session.rs | 1 + src/tools/rustfmt/src/utils.rs | 4 +- src/tools/tidy/Cargo.toml | 2 +- src/tools/tidy/src/deps.rs | 2 + src/tools/tidy/src/edition.rs | 44 +- src/tools/tidy/src/error_codes_check.rs | 6 +- src/tools/tidy/src/features.rs | 1 + src/tools/tidy/src/lib.rs | 2 + src/tools/tidy/src/main.rs | 1 + src/tools/tidy/src/primitive_docs.rs | 17 + src/tools/tidy/src/ui_tests.rs | 4 +- src/tools/tier-check/Cargo.toml | 2 +- src/tools/unicode-table-generator/Cargo.toml | 2 +- .../src/case_mapping.rs | 22 +- .../src/raw_emitter.rs | 10 +- src/tools/unstable-book-gen/Cargo.toml | 2 +- src/tools/x/Cargo.toml | 2 +- src/version | 2 +- vendor/aho-corasick/.cargo-checksum.json | 2 +- vendor/aho-corasick/Cargo.toml | 11 +- vendor/aho-corasick/README.md | 8 +- vendor/aho-corasick/src/ahocorasick.rs | 74 +- vendor/aho-corasick/src/automaton.rs | 8 +- vendor/aho-corasick/src/buffer.rs | 4 +- vendor/aho-corasick/src/classes.rs | 4 +- vendor/aho-corasick/src/dfa.rs | 20 +- vendor/aho-corasick/src/error.rs | 2 +- vendor/aho-corasick/src/lib.rs | 7 +- vendor/aho-corasick/src/nfa.rs | 46 +- vendor/aho-corasick/src/packed/api.rs | 8 +- vendor/aho-corasick/src/packed/mod.rs | 2 +- vendor/aho-corasick/src/packed/pattern.rs | 10 +- vendor/aho-corasick/src/packed/rabinkarp.rs | 4 +- .../aho-corasick/src/packed/teddy/compile.rs | 10 +- vendor/aho-corasick/src/packed/teddy/mod.rs | 12 +- .../aho-corasick/src/packed/teddy/runtime.rs | 8 +- vendor/aho-corasick/src/packed/tests.rs | 4 +- vendor/aho-corasick/src/prefilter.rs | 72 +- vendor/aho-corasick/src/state_id.rs | 2 +- vendor/aho-corasick/src/tests.rs | 148 +- vendor/anyhow/.cargo-checksum.json | 2 +- vendor/anyhow/Cargo.toml | 11 +- vendor/anyhow/README.md | 8 +- vendor/anyhow/build.rs | 31 +- vendor/anyhow/src/chain.rs | 1 + vendor/anyhow/src/error.rs | 13 + vendor/anyhow/src/kind.rs | 3 + vendor/anyhow/src/lib.rs | 12 +- vendor/bitflags/.cargo-checksum.json | 2 +- vendor/bitflags/CHANGELOG.md | 406 +- vendor/bitflags/CODE_OF_CONDUCT.md | 144 +- vendor/bitflags/Cargo.toml | 2 +- vendor/bitflags/LICENSE-APACHE | 402 +- vendor/bitflags/LICENSE-MIT | 50 +- vendor/bitflags/README.md | 64 +- vendor/bitflags/src/example_generated.rs | 28 +- vendor/bitflags/src/lib.rs | 3456 ++++++------ vendor/bitflags/tests/basic.rs | 40 +- .../compile-fail/{derive => impls}/copy.rs | 20 +- .../{derive => impls}/copy.stderr.beta | 54 +- .../compile-fail/{derive => impls}/eq.rs | 20 +- .../{derive => impls}/eq.stderr.beta | 110 +- .../non_integer_base/all_defined.rs | 246 +- .../non_integer_base/all_defined.stderr.beta | 27 + .../{missing_copy.rs => all_missing.rs} | 26 +- .../non_integer_base/all_missing.stderr.beta | 13 + .../non_integer_base/missing_bitops.rs | 14 - .../compile-fail/visibility/private_field.rs | 13 + .../visibility/private_field.stderr.beta | 10 + .../{ => visibility}/private_flags.rs | 36 +- .../private_flags.stderr.beta | 36 +- .../compile-fail/visibility/pub_const.rs | 9 + .../visibility/pub_const.stderr.beta | 5 + .../tests/compile-pass/impls/convert.rs | 17 + .../compile-pass/{derive => impls}/default.rs | 20 +- .../compile-pass/impls/inherent_methods.rs | 15 + .../tests/compile-pass/redefinition/core.rs | 28 +- .../compile-pass/redefinition/stringify.rs | 38 +- vendor/bitflags/tests/compile-pass/repr/c.rs | 20 +- .../tests/compile-pass/repr/transparent.rs | 20 +- .../compile-pass/visibility/bits_field.rs | 11 + .../tests/compile-pass/visibility/pub_in.rs | 19 + vendor/bitflags/tests/compile.rs | 126 +- vendor/cc/.cargo-checksum.json | 2 +- vendor/cc/Cargo.lock | 2 +- vendor/cc/Cargo.toml | 2 +- vendor/cc/README.md | 1 + vendor/cc/src/lib.rs | 133 +- vendor/compiletest_rs/.cargo-checksum.json | 2 +- vendor/compiletest_rs/Cargo.toml | 2 +- vendor/compiletest_rs/README.md | 4 +- vendor/compiletest_rs/src/common.rs | 13 +- vendor/compiletest_rs/src/runtest.rs | 33 +- vendor/dissimilar/.cargo-checksum.json | 1 - vendor/dissimilar/README.md | 58 - vendor/dissimilar/benches/bench.rs | 15 - vendor/dissimilar/benches/document1.txt | 230 - vendor/dissimilar/benches/document2.txt | 188 - vendor/dissimilar/src/find.rs | 232 - vendor/dissimilar/src/lib.rs | 887 --- vendor/dissimilar/src/range.rs | 148 - vendor/dissimilar/src/tests.rs | 580 -- vendor/dissimilar/tests/test.rs | 19 - vendor/expect-test-1.0.1/.cargo-checksum.json | 1 + .../Cargo.toml | 6 +- .../LICENSE-APACHE | 0 .../LICENSE-MIT | 0 vendor/expect-test-1.0.1/README.md | 3 + .../src/lib.rs | 36 +- vendor/expect-test/.cargo-checksum.json | 1 - vendor/expect-test/README.md | 11 - vendor/flate2/.cargo-checksum.json | 2 +- vendor/flate2/Cargo.lock | 12 +- vendor/flate2/Cargo.toml | 13 +- vendor/flate2/examples/deflateencoder-read.rs | 6 +- vendor/flate2/examples/gzencoder-read.rs | 6 +- vendor/flate2/examples/zlibencoder-read.rs | 6 +- vendor/flate2/src/ffi/c.rs | 174 +- vendor/flate2/src/ffi/mod.rs | 6 + vendor/flate2/src/ffi/rust.rs | 16 +- vendor/flate2/src/gz/bufread.rs | 453 +- vendor/flate2/src/gz/mod.rs | 29 + vendor/flate2/src/mem.rs | 99 +- .../{corrupt-file.gz => corrupt-gz-file.bin} | Bin vendor/flate2/tests/gunzip.rs | 2 +- vendor/instant/.cargo-checksum.json | 2 +- vendor/instant/AUTHORS | 2 +- vendor/instant/Cargo.toml | 11 +- vendor/instant/LICENSE | 54 +- vendor/instant/README.md | 288 +- vendor/instant/src/lib.rs | 44 +- vendor/instant/src/native.rs | 14 +- vendor/instant/src/wasm.rs | 306 +- vendor/instant/tests/wasm.rs | 98 +- vendor/itertools/.cargo-checksum.json | 1 + vendor/itertools/CHANGELOG.md | 362 ++ vendor/itertools/Cargo.lock | 724 +++ vendor/itertools/Cargo.toml | 87 + .../{expect-test => itertools}/LICENSE-APACHE | 0 vendor/itertools/LICENSE-MIT | 25 + vendor/itertools/README.rst | 55 + vendor/itertools/benches/bench1.rs | 877 +++ vendor/itertools/benches/combinations.rs | 125 + .../benches/combinations_with_replacement.rs | 40 + vendor/itertools/benches/extra/mod.rs | 2 + vendor/itertools/benches/extra/zipslices.rs | 188 + .../itertools/benches/fold_specialization.rs | 73 + vendor/itertools/benches/powerset.rs | 44 + vendor/itertools/benches/tree_fold1.rs | 144 + .../itertools/benches/tuple_combinations.rs | 113 + vendor/itertools/benches/tuples.rs | 213 + vendor/itertools/examples/iris.data | 150 + vendor/itertools/examples/iris.rs | 137 + vendor/itertools/src/adaptors/coalesce.rs | 233 + vendor/itertools/src/adaptors/map.rs | 120 + vendor/itertools/src/adaptors/mod.rs | 1131 ++++ .../itertools/src/adaptors/multi_product.rs | 222 + vendor/itertools/src/combinations.rs | 128 + .../src/combinations_with_replacement.rs | 109 + vendor/itertools/src/concat_impl.rs | 22 + vendor/itertools/src/cons_tuples_impl.rs | 64 + vendor/itertools/src/diff.rs | 61 + vendor/itertools/src/duplicates_impl.rs | 206 + vendor/itertools/src/either_or_both.rs | 205 + vendor/itertools/src/exactly_one_err.rs | 110 + vendor/itertools/src/flatten_ok.rs | 166 + vendor/itertools/src/format.rs | 113 + vendor/itertools/src/free.rs | 241 + vendor/itertools/src/group_map.rs | 32 + vendor/itertools/src/groupbylazy.rs | 571 ++ vendor/itertools/src/grouping_map.rs | 536 ++ vendor/itertools/src/impl_macros.rs | 28 + vendor/itertools/src/intersperse.rs | 119 + vendor/itertools/src/k_smallest.rs | 20 + vendor/itertools/src/kmerge_impl.rs | 227 + vendor/itertools/src/lazy_buffer.rs | 67 + vendor/itertools/src/lib.rs | 3539 ++++++++++++ vendor/itertools/src/merge_join.rs | 167 + vendor/itertools/src/minmax.rs | 115 + vendor/itertools/src/multipeek_impl.rs | 98 + vendor/itertools/src/pad_tail.rs | 89 + vendor/itertools/src/peek_nth.rs | 102 + vendor/itertools/src/peeking_take_while.rs | 147 + vendor/itertools/src/permutations.rs | 280 + vendor/itertools/src/powerset.rs | 90 + vendor/itertools/src/process_results_impl.rs | 80 + vendor/itertools/src/put_back_n_impl.rs | 61 + vendor/itertools/src/rciter_impl.rs | 100 + vendor/itertools/src/repeatn.rs | 59 + vendor/itertools/src/size_hint.rs | 119 + vendor/itertools/src/sources.rs | 183 + vendor/itertools/src/tee.rs | 78 + vendor/itertools/src/tuple_impl.rs | 331 ++ vendor/itertools/src/unique_impl.rs | 178 + vendor/itertools/src/with_position.rs | 100 + vendor/itertools/src/zip_eq_impl.rs | 60 + vendor/itertools/src/zip_longest.rs | 83 + vendor/itertools/src/ziptuple.rs | 137 + vendor/itertools/tests/adaptors_no_collect.rs | 47 + vendor/itertools/tests/flatten_ok.rs | 76 + vendor/itertools/tests/fold_specialization.rs | 13 + vendor/itertools/tests/macros_hygiene.rs | 13 + vendor/itertools/tests/merge_join.rs | 108 + vendor/itertools/tests/peeking_take_while.rs | 50 + vendor/itertools/tests/quick.rs | 1695 ++++++ vendor/itertools/tests/specializations.rs | 100 + vendor/itertools/tests/test_core.rs | 303 ++ vendor/itertools/tests/test_std.rs | 1082 ++++ vendor/itertools/tests/tuples.rs | 86 + vendor/itertools/tests/zip.rs | 77 + vendor/itoa/.cargo-checksum.json | 2 +- vendor/itoa/Cargo.toml | 11 +- vendor/itoa/src/lib.rs | 9 +- vendor/itoa/src/udiv128.rs | 90 +- vendor/libc/.cargo-checksum.json | 2 +- vendor/libc/Cargo.toml | 2 +- vendor/libc/src/fuchsia/mod.rs | 6 +- vendor/libc/src/unix/bsd/apple/mod.rs | 868 ++- .../src/unix/bsd/freebsdlike/dragonfly/mod.rs | 140 +- .../unix/bsd/freebsdlike/freebsd/aarch64.rs | 125 + .../bsd/freebsdlike/freebsd/freebsd12/mod.rs | 12 + .../freebsdlike/freebsd/freebsd12/x86_64.rs | 5 + .../bsd/freebsdlike/freebsd/freebsd13/mod.rs | 13 + .../freebsdlike/freebsd/freebsd13/x86_64.rs | 5 + .../src/unix/bsd/freebsdlike/freebsd/mod.rs | 212 +- .../bsd/freebsdlike/freebsd/x86_64/mod.rs | 63 + vendor/libc/src/unix/bsd/freebsdlike/mod.rs | 28 +- vendor/libc/src/unix/bsd/mod.rs | 3 + vendor/libc/src/unix/bsd/netbsdlike/mod.rs | 2 + .../src/unix/bsd/netbsdlike/netbsd/aarch64.rs | 81 + .../src/unix/bsd/netbsdlike/netbsd/mod.rs | 80 + .../unix/bsd/netbsdlike/openbsd/aarch64.rs | 14 + .../src/unix/bsd/netbsdlike/openbsd/mod.rs | 6 + .../src/unix/bsd/netbsdlike/openbsd/x86_64.rs | 106 + vendor/libc/src/unix/haiku/mod.rs | 44 + vendor/libc/src/unix/haiku/native.rs | 113 +- vendor/libc/src/unix/haiku/x86_64.rs | 264 + .../src/unix/linux_like/android/b64/mod.rs | 6 + .../libc/src/unix/linux_like/android/mod.rs | 42 + .../linux_like/linux/gnu/b32/riscv32/mod.rs | 1 + .../linux_like/linux/gnu/b64/riscv64/mod.rs | 1 + .../unix/linux_like/linux/gnu/b64/s390x.rs | 1 + .../libc/src/unix/linux_like/linux/gnu/mod.rs | 41 +- vendor/libc/src/unix/linux_like/linux/mod.rs | 48 + .../src/unix/linux_like/linux/musl/mod.rs | 126 +- .../unix/linux_like/linux/uclibc/arm/mod.rs | 34 +- .../linux/uclibc/mips/mips32/mod.rs | 1 + .../unix/linux_like/linux/uclibc/mips/mod.rs | 45 - .../src/unix/linux_like/linux/uclibc/mod.rs | 145 + .../linux_like/linux/uclibc/x86_64/l4re.rs | 5 + vendor/libc/src/unix/linux_like/mod.rs | 24 +- vendor/libc/src/unix/mod.rs | 1 + vendor/libc/src/unix/newlib/mod.rs | 3 + vendor/libc/src/unix/redox/mod.rs | 2 + vendor/libc/src/unix/solarish/illumos.rs | 4 + vendor/libc/src/unix/solarish/mod.rs | 110 +- vendor/libc/src/unix/solarish/x86_64.rs | 129 + vendor/libc/src/vxworks/mod.rs | 1 + vendor/libc/src/wasi.rs | 1 + vendor/libc/src/windows/mod.rs | 7 + .../libc/src/windows/{msvc.rs => msvc/mod.rs} | 16 + vendor/libc/src/windows/msvc/x86_64.rs | 140 + vendor/lock_api/.cargo-checksum.json | 2 +- vendor/lock_api/Cargo.toml | 14 +- vendor/lock_api/src/lib.rs | 7 +- vendor/lock_api/src/mutex.rs | 189 + vendor/lock_api/src/remutex.rs | 185 + vendor/lock_api/src/rwlock.rs | 797 +++ vendor/odht/.cargo-checksum.json | 1 + vendor/odht/CODE_OF_CONDUCT.md | 3 + vendor/odht/Cargo.toml | 33 + vendor/odht/LICENSE-APACHE | 176 + vendor/odht/LICENSE-MIT | 23 + vendor/odht/README.md | 17 + vendor/odht/benches/bench.rs | 228 + vendor/odht/src/error.rs | 9 + vendor/odht/src/fxhash.rs | 58 + vendor/odht/src/lib.rs | 963 ++++ vendor/odht/src/memory_layout.rs | 369 ++ vendor/odht/src/raw_table.rs | 659 +++ vendor/odht/src/swisstable_group_query/mod.rs | 117 + .../src/swisstable_group_query/no_simd.rs | 70 + .../odht/src/swisstable_group_query/sse2.rs | 54 + vendor/odht/src/unhash.rs | 15 + vendor/parking_lot/.cargo-checksum.json | 2 +- vendor/parking_lot/CHANGELOG.md | 28 + vendor/parking_lot/Cargo.toml | 22 +- vendor/parking_lot/src/raw_rwlock.rs | 4 +- vendor/parking_lot_core/.cargo-checksum.json | 2 +- vendor/parking_lot_core/Cargo.toml | 23 +- vendor/parking_lot_core/build.rs | 10 + vendor/parking_lot_core/src/word_lock.rs | 17 +- vendor/proc-macro2/.cargo-checksum.json | 2 +- vendor/proc-macro2/Cargo.toml | 2 +- vendor/proc-macro2/build.rs | 4 + vendor/proc-macro2/src/lib.rs | 2 +- vendor/proc-macro2/src/wrapper.rs | 27 +- vendor/rand/.cargo-checksum.json | 2 +- vendor/rand/CHANGELOG.md | 14 + vendor/rand/Cargo.toml | 7 +- vendor/rand/README.md | 8 + vendor/rand/src/distributions/bernoulli.rs | 5 +- vendor/rand/src/distributions/distribution.rs | 272 + vendor/rand/src/distributions/mod.rs | 226 +- vendor/rand/src/distributions/other.rs | 60 +- vendor/rand/src/distributions/slice.rs | 117 + vendor/rand/src/distributions/uniform.rs | 58 +- vendor/rand/src/distributions/utils.rs | 2 + .../rand/src/distributions/weighted_index.rs | 14 +- vendor/rand/src/lib.rs | 2 +- vendor/rand/src/rng.rs | 38 +- vendor/rand/src/rngs/adapter/mod.rs | 1 + vendor/rand/src/rngs/adapter/read.rs | 15 +- vendor/rand/src/rngs/adapter/reseeding.rs | 2 + vendor/rand/src/rngs/xoshiro256plusplus.rs | 4 +- vendor/rand/src/seq/index.rs | 6 +- vendor/rand/src/seq/mod.rs | 4 +- vendor/rand_xoshiro/.cargo-checksum.json | 1 + vendor/rand_xoshiro/CHANGELOG.md | 42 + vendor/rand_xoshiro/COPYRIGHT | 12 + .../{dissimilar => rand_xoshiro}/Cargo.toml | 31 +- .../LICENSE-APACHE | 0 vendor/rand_xoshiro/LICENSE-MIT | 25 + vendor/rand_xoshiro/README.md | 34 + vendor/rand_xoshiro/src/common.rs | 265 + vendor/rand_xoshiro/src/lib.rs | 114 + vendor/rand_xoshiro/src/splitmix64.rs | 149 + vendor/rand_xoshiro/src/xoroshiro128plus.rs | 129 + .../rand_xoshiro/src/xoroshiro128plusplus.rs | 126 + .../rand_xoshiro/src/xoroshiro128starstar.rs | 126 + vendor/rand_xoshiro/src/xoroshiro64star.rs | 101 + .../rand_xoshiro/src/xoroshiro64starstar.rs | 100 + vendor/rand_xoshiro/src/xoshiro128plus.rs | 112 + vendor/rand_xoshiro/src/xoshiro128plusplus.rs | 120 + vendor/rand_xoshiro/src/xoshiro128starstar.rs | 120 + vendor/rand_xoshiro/src/xoshiro256plus.rs | 131 + vendor/rand_xoshiro/src/xoshiro256plusplus.rs | 130 + vendor/rand_xoshiro/src/xoshiro256starstar.rs | 130 + vendor/rand_xoshiro/src/xoshiro512plus.rs | 137 + vendor/rand_xoshiro/src/xoshiro512plusplus.rs | 137 + vendor/rand_xoshiro/src/xoshiro512starstar.rs | 137 + vendor/rand_xoshiro/tests/serde.rs | 83 + vendor/regex-1.4.6/.cargo-checksum.json | 1 - vendor/regex-1.4.6/src/literal/imp.rs | 1122 ---- vendor/regex/.cargo-checksum.json | 1 + vendor/{regex-1.4.6 => regex}/CHANGELOG.md | 52 + vendor/{regex-1.4.6 => regex}/Cargo.lock | 14 +- vendor/{regex-1.4.6 => regex}/Cargo.toml | 9 +- vendor/{regex-1.4.6 => regex}/HACKING.md | 0 vendor/regex/LICENSE-APACHE | 201 + vendor/{regex-1.4.6 => regex}/LICENSE-MIT | 0 vendor/{regex-1.4.6 => regex}/PERFORMANCE.md | 10 +- vendor/{regex-1.4.6 => regex}/README.md | 12 +- vendor/{regex-1.4.6 => regex}/UNICODE.md | 0 .../examples/regexdna-input.txt | 0 .../examples/regexdna-output.txt | 0 .../examples/shootout-regex-dna-bytes.rs | 2 - .../examples/shootout-regex-dna-cheat.rs | 2 - .../examples/shootout-regex-dna-replace.rs | 2 - .../shootout-regex-dna-single-cheat.rs | 2 - .../examples/shootout-regex-dna-single.rs | 2 - .../examples/shootout-regex-dna.rs | 2 - vendor/{regex-1.4.6 => regex}/rustfmt.toml | 0 .../{regex-1.4.6 => regex}/src/backtrack.rs | 10 +- vendor/{regex-1.4.6 => regex}/src/compile.rs | 25 +- vendor/{regex-1.4.6 => regex}/src/dfa.rs | 27 +- vendor/{regex-1.4.6 => regex}/src/error.rs | 4 +- vendor/{regex-1.4.6 => regex}/src/exec.rs | 59 +- vendor/{regex-1.4.6 => regex}/src/expand.rs | 14 +- .../{regex-1.4.6 => regex}/src/find_byte.rs | 0 vendor/{regex-1.4.6 => regex}/src/freqs.rs | 0 vendor/{regex-1.4.6 => regex}/src/input.rs | 18 +- vendor/{regex-1.4.6 => regex}/src/lib.rs | 70 +- vendor/regex/src/literal/imp.rs | 402 ++ .../{regex-1.4.6 => regex}/src/literal/mod.rs | 2 +- vendor/{regex-1.4.6 => regex}/src/pattern.rs | 3 +- vendor/{regex-1.4.6 => regex}/src/pikevm.rs | 14 +- vendor/{regex-1.4.6 => regex}/src/pool.rs | 10 +- vendor/{regex-1.4.6 => regex}/src/prog.rs | 6 +- .../{regex-1.4.6 => regex}/src/re_builder.rs | 12 +- vendor/{regex-1.4.6 => regex}/src/re_bytes.rs | 90 +- vendor/{regex-1.4.6 => regex}/src/re_set.rs | 12 +- vendor/{regex-1.4.6 => regex}/src/re_trait.rs | 6 +- .../{regex-1.4.6 => regex}/src/re_unicode.rs | 95 +- vendor/{regex-1.4.6 => regex}/src/sparse.rs | 2 +- .../src/testdata/LICENSE | 0 .../src/testdata/README | 0 .../src/testdata/basic.dat | 0 .../src/testdata/nullsubexpr.dat | 0 .../src/testdata/repetition.dat | 0 vendor/{regex-1.4.6 => regex}/src/utf8.rs | 0 vendor/{regex-1.4.6 => regex}/test | 2 + vendor/{regex-1.4.6 => regex}/tests/api.rs | 0 .../{regex-1.4.6 => regex}/tests/api_str.rs | 0 vendor/{regex-1.4.6 => regex}/tests/bytes.rs | 0 .../tests/consistent.rs | 0 .../tests/crates_regex.rs | 0 vendor/{regex-1.4.6 => regex}/tests/crazy.rs | 0 vendor/{regex-1.4.6 => regex}/tests/flags.rs | 0 vendor/{regex-1.4.6 => regex}/tests/fowler.rs | 0 vendor/{regex-1.4.6 => regex}/tests/macros.rs | 0 .../tests/macros_bytes.rs | 0 .../tests/macros_str.rs | 0 vendor/{regex-1.4.6 => regex}/tests/misc.rs | 0 .../{regex-1.4.6 => regex}/tests/multiline.rs | 0 .../{regex-1.4.6 => regex}/tests/noparse.rs | 0 .../tests/regression.rs | 0 .../tests/regression_fuzz.rs | 0 .../{regex-1.4.6 => regex}/tests/replace.rs | 4 +- .../{regex-1.4.6 => regex}/tests/searcher.rs | 0 vendor/{regex-1.4.6 => regex}/tests/set.rs | 0 .../tests/shortest_match.rs | 0 .../tests/suffix_reverse.rs | 0 .../tests/test_backtrack.rs | 3 - .../tests/test_backtrack_bytes.rs | 3 - .../tests/test_backtrack_utf8bytes.rs | 3 - .../tests/test_crates_regex.rs | 3 - .../tests/test_default.rs | 3 +- .../tests/test_default_bytes.rs | 3 - .../{regex-1.4.6 => regex}/tests/test_nfa.rs | 3 - .../tests/test_nfa_bytes.rs | 3 - .../tests/test_nfa_utf8bytes.rs | 3 - .../{regex-1.4.6 => regex}/tests/unicode.rs | 0 .../tests/word_boundary.rs | 0 .../tests/word_boundary_ascii.rs | 0 .../tests/word_boundary_unicode.rs | 0 vendor/serde/.cargo-checksum.json | 2 +- vendor/serde/Cargo.toml | 4 +- vendor/serde/build.rs | 10 +- vendor/serde/src/de/mod.rs | 4 +- vendor/serde/src/lib.rs | 4 +- vendor/serde/src/private/mod.rs | 1 + vendor/serde/src/ser/mod.rs | 30 +- vendor/serde_derive/.cargo-checksum.json | 2 +- vendor/serde_derive/Cargo.toml | 2 +- vendor/serde_derive/build.rs | 6 + vendor/serde_derive/src/de.rs | 56 +- vendor/serde_derive/src/lib.rs | 4 +- vendor/serde_derive/src/pretend.rs | 143 +- vendor/serde_derive/src/ser.rs | 2 +- vendor/serde_json/.cargo-checksum.json | 2 +- vendor/serde_json/Cargo.toml | 2 +- vendor/serde_json/src/de.rs | 4 +- vendor/serde_json/src/lib.rs | 2 +- vendor/serde_json/src/map.rs | 1 + vendor/serde_json/src/value/de.rs | 120 +- vendor/smallvec/.cargo-checksum.json | 2 +- vendor/smallvec/Cargo.toml | 15 +- vendor/smallvec/src/lib.rs | 135 +- vendor/smallvec/src/tests.rs | 58 + vendor/syn/.cargo-checksum.json | 2 +- vendor/syn/Cargo.toml | 4 +- vendor/syn/src/attr.rs | 12 +- vendor/syn/src/data.rs | 6 +- vendor/syn/src/expr.rs | 13 +- vendor/syn/src/generics.rs | 6 +- vendor/syn/src/item.rs | 54 +- vendor/syn/src/lib.rs | 6 +- vendor/syn/src/pat.rs | 28 +- vendor/syn/src/stmt.rs | 90 +- vendor/syn/tests/common/eq.rs | 40 +- vendor/syn/tests/repo/mod.rs | 34 +- vendor/syn/tests/test_precedence.rs | 49 +- vendor/syn/tests/test_round_trip.rs | 7 + vendor/tinyvec/.cargo-checksum.json | 2 +- vendor/tinyvec/CHANGELOG.md | 11 + vendor/tinyvec/Cargo.toml | 20 +- vendor/tinyvec/src/array.rs | 6 +- vendor/tinyvec/src/lib.rs | 6 +- vendor/tinyvec/src/tinyvec.rs | 15 + vendor/tinyvec/tests/tinyvec.rs | 15 + .../tracing-attributes/.cargo-checksum.json | 2 +- vendor/tracing-attributes/CHANGELOG.md | 35 + vendor/tracing-attributes/Cargo.toml | 11 +- vendor/tracing-attributes/README.md | 4 +- vendor/tracing-attributes/src/lib.rs | 234 +- vendor/tracing-attributes/tests/async_fn.rs | 2 +- .../tracing-attributes/tests/destructuring.rs | 2 +- vendor/tracing-attributes/tests/err.rs | 2 +- vendor/tracing-attributes/tests/fields.rs | 14 +- vendor/tracing-attributes/tests/instrument.rs | 30 +- vendor/tracing-core/.cargo-checksum.json | 2 +- vendor/tracing-core/CHANGELOG.md | 62 +- vendor/tracing-core/Cargo.toml | 11 +- vendor/tracing-core/README.md | 26 +- vendor/tracing-core/src/dispatcher.rs | 107 +- vendor/tracing-core/src/event.rs | 4 +- vendor/tracing-core/src/field.rs | 58 +- vendor/tracing-core/src/lib.rs | 6 +- vendor/tracing-core/src/metadata.rs | 182 +- vendor/tracing-core/src/span.rs | 11 +- vendor/tracing-core/src/spin/once.rs | 54 +- vendor/tracing-core/src/subscriber.rs | 42 +- .../tracing-subscriber/.cargo-checksum.json | 2 +- vendor/tracing-subscriber/CHANGELOG.md | 142 +- vendor/tracing-subscriber/Cargo.toml | 4 +- vendor/tracing-subscriber/README.md | 2 +- vendor/tracing-subscriber/src/field/debug.rs | 5 + .../tracing-subscriber/src/field/display.rs | 5 + vendor/tracing-subscriber/src/field/mod.rs | 6 +- .../src/filter/directive.rs | 413 ++ .../src/filter/env/directive.rs | 320 +- .../src/filter/env/field.rs | 91 +- .../tracing-subscriber/src/filter/env/mod.rs | 65 +- .../src/filter/filter_fn.rs | 748 +++ .../src/filter/layer_filters.rs | 830 +++ vendor/tracing-subscriber/src/filter/mod.rs | 49 +- .../tracing-subscriber/src/filter/targets.rs | 665 +++ .../tracing-subscriber/src/fmt/format/json.rs | 35 +- .../tracing-subscriber/src/fmt/format/mod.rs | 51 +- .../src/fmt/format/pretty.rs | 8 +- vendor/tracing-subscriber/src/fmt/mod.rs | 12 +- vendor/tracing-subscriber/src/fmt/writer.rs | 72 +- vendor/tracing-subscriber/src/layer.rs | 1454 ----- .../tracing-subscriber/src/layer/context.rs | 493 ++ .../tracing-subscriber/src/layer/layered.rs | 471 ++ vendor/tracing-subscriber/src/layer/mod.rs | 1232 +++++ vendor/tracing-subscriber/src/layer/tests.rs | 306 ++ vendor/tracing-subscriber/src/lib.rs | 37 +- .../src/registry/extensions.rs | 8 +- vendor/tracing-subscriber/src/registry/mod.rs | 163 +- .../src/registry/sharded.rs | 127 +- .../tracing-subscriber/src/registry/stack.rs | 14 +- vendor/tracing-subscriber/src/reload.rs | 4 + vendor/tracing-subscriber/src/sync.rs | 6 +- ...d_layer_filters_dont_break_other_layers.rs | 123 + .../tests/duplicate_spans.rs | 1 + .../tracing-subscriber/tests/field_filter.rs | 1 + vendor/tracing-subscriber/tests/filter.rs | 2 + vendor/tracing-subscriber/tests/filter_log.rs | 1 + .../tests/fmt_max_level_hint.rs | 1 + ...d_layer_filters_dont_break_other_layers.rs | 131 + .../layer_filter_interests_are_cached.rs | 69 + .../tests/layer_filters/boxed.rs | 73 + .../tests/layer_filters/filter_scopes.rs | 131 + .../tests/layer_filters/main.rs | 187 + .../tests/layer_filters/targets.rs | 59 + .../tests/layer_filters/trees.rs | 146 + .../multiple_layer_filter_interests_cached.rs | 131 + .../tests/registry_max_level_hint.rs | 1 + .../tests/registry_with_subscriber.rs | 1 + vendor/tracing-subscriber/tests/reload.rs | 1 + .../tests/same_len_filters.rs | 2 +- vendor/tracing-subscriber/tests/support.rs | 412 +- ...d_layer_filters_dont_break_other_layers.rs | 123 + vendor/tracing-subscriber/tests/utils.rs | 2 + vendor/tracing-tree/.cargo-checksum.json | 2 +- vendor/tracing-tree/Cargo.lock | 221 +- vendor/tracing-tree/Cargo.toml | 7 +- vendor/tracing-tree/src/format.rs | 4 +- vendor/tracing-tree/src/lib.rs | 29 +- vendor/tracing/.cargo-checksum.json | 2 +- vendor/tracing/CHANGELOG.md | 62 + vendor/tracing/Cargo.toml | 6 +- vendor/tracing/README.md | 8 +- vendor/tracing/src/dispatcher.rs | 9 +- vendor/tracing/src/field.rs | 4 - vendor/tracing/src/instrument.rs | 43 +- vendor/tracing/src/lib.rs | 71 +- vendor/tracing/src/span.rs | 226 +- vendor/tracing/tests/event.rs | 24 +- vendor/tracing/tests/span.rs | 22 + vendor/tracing/tests/support/event.rs | 81 +- vendor/tracing/tests/support/field.rs | 90 +- vendor/tracing/tests/support/metadata.rs | 16 +- vendor/tracing/tests/support/mod.rs | 70 + vendor/tracing/tests/support/span.rs | 87 +- vendor/tracing/tests/support/subscriber.rs | 197 +- version | 2 +- 4720 files changed, 138136 insertions(+), 44466 deletions(-) rename compiler/{rustc_mir => rustc_borrowck}/Cargo.toml (72%) rename compiler/{rustc_mir/src/borrow_check => rustc_borrowck/src}/borrow_set.rs (98%) rename compiler/{rustc_mir/src/util => rustc_borrowck/src}/borrowck_errors.rs (99%) rename compiler/{rustc_mir/src/borrow_check => rustc_borrowck/src}/constraint_generation.rs (99%) rename compiler/{rustc_mir/src/borrow_check => rustc_borrowck/src}/constraints/graph.rs (99%) rename compiler/{rustc_mir/src/borrow_check => rustc_borrowck/src}/constraints/mod.rs (98%) rename compiler/{rustc_mir/src/borrow_check => rustc_borrowck/src}/consumers.rs (87%) rename compiler/{rustc_mir/src/dataflow/impls/borrows.rs => rustc_borrowck/src/dataflow.rs} (78%) rename compiler/{rustc_mir/src/borrow_check => rustc_borrowck/src}/def_use.rs (100%) rename compiler/{rustc_mir/src/borrow_check => rustc_borrowck/src}/diagnostics/bound_region_errors.rs (77%) rename compiler/{rustc_mir/src/borrow_check => rustc_borrowck/src}/diagnostics/conflict_errors.rs (95%) rename compiler/{rustc_mir/src/borrow_check => rustc_borrowck/src}/diagnostics/explain_borrow.rs (98%) rename compiler/{rustc_mir/src/borrow_check => rustc_borrowck/src}/diagnostics/find_use.rs (99%) rename compiler/{rustc_mir/src/borrow_check => rustc_borrowck/src}/diagnostics/mod.rs (99%) rename compiler/{rustc_mir/src/borrow_check => rustc_borrowck/src}/diagnostics/move_errors.rs (96%) rename compiler/{rustc_mir/src/borrow_check => rustc_borrowck/src}/diagnostics/mutability_errors.rs (99%) rename compiler/{rustc_mir/src/borrow_check => rustc_borrowck/src}/diagnostics/outlives_suggestion.rs (97%) rename compiler/{rustc_mir/src/borrow_check => rustc_borrowck/src}/diagnostics/region_errors.rs (94%) rename compiler/{rustc_mir/src/borrow_check => rustc_borrowck/src}/diagnostics/region_name.rs (99%) rename compiler/{rustc_mir/src/borrow_check => rustc_borrowck/src}/diagnostics/var_name.rs (97%) rename compiler/{rustc_mir/src/borrow_check => rustc_borrowck/src}/facts.rs (95%) rename compiler/{rustc_mir/src/borrow_check => rustc_borrowck/src}/invalidation.rs (98%) rename compiler/{rustc_mir/src/borrow_check/mod.rs => rustc_borrowck/src/lib.rs} (97%) rename compiler/{rustc_mir/src/borrow_check => rustc_borrowck/src}/location.rs (100%) rename compiler/{rustc_mir/src/borrow_check => rustc_borrowck/src}/member_constraints.rs (99%) rename compiler/{rustc_mir/src/borrow_check => rustc_borrowck/src}/nll.rs (93%) rename compiler/{rustc_mir/src/borrow_check => rustc_borrowck/src}/path_utils.rs (96%) rename compiler/{rustc_mir/src/borrow_check => rustc_borrowck/src}/place_ext.rs (98%) rename compiler/{rustc_mir/src/borrow_check => rustc_borrowck/src}/places_conflict.rs (99%) rename compiler/{rustc_mir/src/borrow_check => rustc_borrowck/src}/prefixes.rs (100%) rename compiler/{rustc_mir/src/borrow_check => rustc_borrowck/src}/region_infer/dump_mir.rs (98%) rename compiler/{rustc_mir/src/borrow_check => rustc_borrowck/src}/region_infer/graphviz.rs (98%) rename compiler/{rustc_mir/src/borrow_check => rustc_borrowck/src}/region_infer/mod.rs (95%) rename compiler/{rustc_mir/src/borrow_check => rustc_borrowck/src}/region_infer/opaque_types.rs (51%) rename compiler/{rustc_mir/src/borrow_check => rustc_borrowck/src}/region_infer/reverse_sccs.rs (95%) rename compiler/{rustc_mir/src/borrow_check => rustc_borrowck/src}/region_infer/values.rs (97%) rename compiler/{rustc_mir/src/borrow_check => rustc_borrowck/src}/renumber.rs (82%) rename compiler/{rustc_mir/src/borrow_check => rustc_borrowck/src}/type_check/canonical.rs (81%) rename compiler/{rustc_mir/src/borrow_check => rustc_borrowck/src}/type_check/constraint_conversion.rs (98%) rename compiler/{rustc_mir/src/borrow_check => rustc_borrowck/src}/type_check/free_region_relations.rs (97%) rename compiler/{rustc_mir/src/borrow_check => rustc_borrowck/src}/type_check/input_output.rs (95%) rename compiler/{rustc_mir/src/borrow_check => rustc_borrowck/src}/type_check/liveness/local_use_map.rs (97%) rename compiler/{rustc_mir/src/borrow_check => rustc_borrowck/src}/type_check/liveness/mod.rs (96%) rename compiler/{rustc_mir/src/borrow_check => rustc_borrowck/src}/type_check/liveness/polonius.rs (96%) rename compiler/{rustc_mir/src/borrow_check => rustc_borrowck/src}/type_check/liveness/trace.rs (98%) rename compiler/{rustc_mir/src/borrow_check => rustc_borrowck/src}/type_check/mod.rs (96%) create mode 100644 compiler/rustc_borrowck/src/type_check/relate_tys.rs rename compiler/{rustc_mir/src/borrow_check => rustc_borrowck/src}/universal_regions.rs (99%) rename compiler/{rustc_mir/src/borrow_check => rustc_borrowck/src}/used_muts.rs (99%) rename compiler/rustc_codegen_cranelift/patches/{0001-stdsimd-Disable-unsupported-tests.patch => 0001-portable-simd-Disable-unsupported-tests.patch} (77%) delete mode 100644 compiler/rustc_codegen_cranelift/src/backend.rs create mode 100644 compiler/rustc_codegen_cranelift/src/debuginfo/object.rs create mode 100644 compiler/rustc_codegen_gcc/.github/workflows/main.yml create mode 100644 compiler/rustc_codegen_gcc/Cargo.lock create mode 100644 compiler/rustc_codegen_gcc/Cargo.toml create mode 100644 compiler/rustc_codegen_gcc/LICENSE-APACHE rename {vendor/dissimilar => compiler/rustc_codegen_gcc}/LICENSE-MIT (100%) create mode 100644 compiler/rustc_codegen_gcc/Readme.md create mode 100755 compiler/rustc_codegen_gcc/build.sh create mode 100644 compiler/rustc_codegen_gcc/build_sysroot/Cargo.toml create mode 100755 compiler/rustc_codegen_gcc/build_sysroot/build_sysroot.sh create mode 100755 compiler/rustc_codegen_gcc/build_sysroot/prepare_sysroot_src.sh create mode 100644 compiler/rustc_codegen_gcc/build_sysroot/src/lib.rs create mode 100755 compiler/rustc_codegen_gcc/cargo.sh create mode 100755 compiler/rustc_codegen_gcc/clean_all.sh create mode 100644 compiler/rustc_codegen_gcc/config.sh create mode 100644 compiler/rustc_codegen_gcc/example/alloc_example.rs create mode 100644 compiler/rustc_codegen_gcc/example/alloc_system.rs create mode 100644 compiler/rustc_codegen_gcc/example/arbitrary_self_types_pointers_and_wrappers.rs create mode 100644 compiler/rustc_codegen_gcc/example/dst-field-align.rs create mode 100644 compiler/rustc_codegen_gcc/example/example.rs create mode 100644 compiler/rustc_codegen_gcc/example/mini_core.rs create mode 100644 compiler/rustc_codegen_gcc/example/mini_core_hello_world.rs create mode 100644 compiler/rustc_codegen_gcc/example/mod_bench.rs create mode 100644 compiler/rustc_codegen_gcc/example/std_example.rs create mode 100644 compiler/rustc_codegen_gcc/example/subslice-patterns-const-eval.rs create mode 100644 compiler/rustc_codegen_gcc/example/track-caller-attribute.rs create mode 100644 compiler/rustc_codegen_gcc/patches/0022-core-Disable-not-compiling-tests.patch create mode 100644 compiler/rustc_codegen_gcc/patches/0023-core-Ignore-failing-tests.patch create mode 100755 compiler/rustc_codegen_gcc/prepare.sh create mode 100755 compiler/rustc_codegen_gcc/prepare_build.sh create mode 100644 compiler/rustc_codegen_gcc/rust-toolchain create mode 100755 compiler/rustc_codegen_gcc/rustup.sh create mode 100644 compiler/rustc_codegen_gcc/src/abi.rs create mode 100644 compiler/rustc_codegen_gcc/src/allocator.rs create mode 100644 compiler/rustc_codegen_gcc/src/archive.rs create mode 100644 compiler/rustc_codegen_gcc/src/asm.rs create mode 100644 compiler/rustc_codegen_gcc/src/back/mod.rs create mode 100644 compiler/rustc_codegen_gcc/src/back/write.rs create mode 100644 compiler/rustc_codegen_gcc/src/base.rs create mode 100644 compiler/rustc_codegen_gcc/src/builder.rs create mode 100644 compiler/rustc_codegen_gcc/src/callee.rs create mode 100644 compiler/rustc_codegen_gcc/src/common.rs create mode 100644 compiler/rustc_codegen_gcc/src/consts.rs create mode 100644 compiler/rustc_codegen_gcc/src/context.rs create mode 100644 compiler/rustc_codegen_gcc/src/coverageinfo.rs create mode 100644 compiler/rustc_codegen_gcc/src/debuginfo.rs create mode 100644 compiler/rustc_codegen_gcc/src/declare.rs create mode 100644 compiler/rustc_codegen_gcc/src/intrinsic/llvm.rs create mode 100644 compiler/rustc_codegen_gcc/src/intrinsic/mod.rs create mode 100644 compiler/rustc_codegen_gcc/src/intrinsic/simd.rs create mode 100644 compiler/rustc_codegen_gcc/src/lib.rs create mode 100644 compiler/rustc_codegen_gcc/src/mono_item.rs create mode 100644 compiler/rustc_codegen_gcc/src/type_.rs create mode 100644 compiler/rustc_codegen_gcc/src/type_of.rs create mode 100755 compiler/rustc_codegen_gcc/test.sh create mode 100644 compiler/rustc_codegen_gcc/tests/lib.rs create mode 100644 compiler/rustc_codegen_gcc/tests/run/abort1.rs create mode 100644 compiler/rustc_codegen_gcc/tests/run/abort2.rs create mode 100644 compiler/rustc_codegen_gcc/tests/run/array.rs create mode 100644 compiler/rustc_codegen_gcc/tests/run/asm.rs create mode 100644 compiler/rustc_codegen_gcc/tests/run/assign.rs create mode 100644 compiler/rustc_codegen_gcc/tests/run/closure.rs create mode 100644 compiler/rustc_codegen_gcc/tests/run/condition.rs create mode 100644 compiler/rustc_codegen_gcc/tests/run/empty_main.rs create mode 100644 compiler/rustc_codegen_gcc/tests/run/exit.rs create mode 100644 compiler/rustc_codegen_gcc/tests/run/exit_code.rs create mode 100644 compiler/rustc_codegen_gcc/tests/run/fun_ptr.rs create mode 100644 compiler/rustc_codegen_gcc/tests/run/int_overflow.rs create mode 100644 compiler/rustc_codegen_gcc/tests/run/mut_ref.rs create mode 100644 compiler/rustc_codegen_gcc/tests/run/operations.rs create mode 100644 compiler/rustc_codegen_gcc/tests/run/ptr_cast.rs create mode 100644 compiler/rustc_codegen_gcc/tests/run/return-tuple.rs create mode 100644 compiler/rustc_codegen_gcc/tests/run/slice.rs create mode 100644 compiler/rustc_codegen_gcc/tests/run/static.rs create mode 100644 compiler/rustc_codegen_gcc/tests/run/structs.rs create mode 100644 compiler/rustc_codegen_gcc/tests/run/tuple.rs create mode 100644 compiler/rustc_const_eval/Cargo.toml rename compiler/{rustc_mir => rustc_const_eval}/src/const_eval/error.rs (100%) rename compiler/{rustc_mir => rustc_const_eval}/src/const_eval/eval_queries.rs (98%) rename compiler/{rustc_mir => rustc_const_eval}/src/const_eval/fn_queries.rs (66%) rename compiler/{rustc_mir => rustc_const_eval}/src/const_eval/machine.rs (89%) rename compiler/{rustc_mir => rustc_const_eval}/src/const_eval/mod.rs (100%) rename compiler/{rustc_mir => rustc_const_eval}/src/interpret/cast.rs (99%) rename compiler/{rustc_mir => rustc_const_eval}/src/interpret/eval_context.rs (97%) rename compiler/{rustc_mir => rustc_const_eval}/src/interpret/intern.rs (99%) rename compiler/{rustc_mir => rustc_const_eval}/src/interpret/intrinsics.rs (96%) rename compiler/{rustc_mir => rustc_const_eval}/src/interpret/intrinsics/caller_location.rs (99%) rename compiler/{rustc_mir => rustc_const_eval}/src/interpret/intrinsics/type_name.rs (100%) rename compiler/{rustc_mir => rustc_const_eval}/src/interpret/machine.rs (100%) rename compiler/{rustc_mir => rustc_const_eval}/src/interpret/memory.rs (99%) rename compiler/{rustc_mir => rustc_const_eval}/src/interpret/mod.rs (100%) rename compiler/{rustc_mir => rustc_const_eval}/src/interpret/operand.rs (98%) rename compiler/{rustc_mir => rustc_const_eval}/src/interpret/operator.rs (99%) rename compiler/{rustc_mir => rustc_const_eval}/src/interpret/place.rs (97%) rename compiler/{rustc_mir => rustc_const_eval}/src/interpret/step.rs (90%) rename compiler/{rustc_mir => rustc_const_eval}/src/interpret/terminator.rs (97%) rename compiler/{rustc_mir => rustc_const_eval}/src/interpret/traits.rs (100%) rename compiler/{rustc_mir => rustc_const_eval}/src/interpret/util.rs (96%) rename compiler/{rustc_mir => rustc_const_eval}/src/interpret/validity.rs (97%) rename compiler/{rustc_mir => rustc_const_eval}/src/interpret/visitor.rs (100%) rename compiler/{rustc_mir => rustc_const_eval}/src/lib.rs (66%) rename compiler/{rustc_mir => rustc_const_eval}/src/transform/check_consts/check.rs (95%) rename compiler/{rustc_mir => rustc_const_eval}/src/transform/check_consts/mod.rs (92%) rename compiler/{rustc_mir => rustc_const_eval}/src/transform/check_consts/ops.rs (92%) rename compiler/{rustc_mir => rustc_const_eval}/src/transform/check_consts/post_drop_elaboration.rs (90%) rename compiler/{rustc_mir => rustc_const_eval}/src/transform/check_consts/qualifs.rs (82%) rename compiler/{rustc_mir => rustc_const_eval}/src/transform/check_consts/resolver.rs (97%) create mode 100644 compiler/rustc_const_eval/src/transform/mod.rs rename compiler/{rustc_mir => rustc_const_eval}/src/transform/promote_consts.rs (98%) rename compiler/{rustc_mir => rustc_const_eval}/src/transform/validate.rs (98%) rename compiler/{rustc_mir => rustc_const_eval}/src/util/aggregate.rs (100%) rename compiler/{rustc_mir => rustc_const_eval}/src/util/alignment.rs (100%) rename compiler/{rustc_mir => rustc_const_eval}/src/util/collect_writes.rs (97%) rename compiler/{rustc_mir => rustc_const_eval}/src/util/find_self_call.rs (100%) create mode 100644 compiler/rustc_const_eval/src/util/mod.rs create mode 100644 compiler/rustc_error_codes/src/error_codes/E0183.md create mode 100644 compiler/rustc_error_codes/src/error_codes/E0464.md create mode 100644 compiler/rustc_error_codes/src/error_codes/E0482.md create mode 100644 compiler/rustc_hir/src/def_path_hash_map.rs create mode 100644 compiler/rustc_hir/src/diagnostic_items.rs rename compiler/{rustc_middle/src/ty/outlives.rs => rustc_infer/src/infer/outlives/components.rs} (94%) create mode 100644 compiler/rustc_infer/src/infer/projection.rs create mode 100644 compiler/rustc_lint/src/enum_intrinsics_non_enums.rs create mode 100644 compiler/rustc_lint/src/hidden_unicode_codepoints.rs create mode 100644 compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs delete mode 100644 compiler/rustc_middle/src/mir/abstract_const.rs rename compiler/{rustc_mir/src/util => rustc_middle/src/mir}/generic_graph.rs (100%) rename compiler/{rustc_mir/src/util => rustc_middle/src/mir}/generic_graphviz.rs (100%) rename compiler/{rustc_mir/src/util => rustc_middle/src/mir}/graphviz.rs (100%) rename compiler/{rustc_mir/src/util => rustc_middle/src/mir}/patch.rs (100%) rename compiler/{rustc_mir/src/util => rustc_middle/src/mir}/pretty.rs (99%) rename compiler/{rustc_mir/src/util => rustc_middle/src/mir}/spanview.rs (100%) create mode 100644 compiler/rustc_middle/src/thir/abstract_const.rs rename compiler/{rustc_mir_build => rustc_middle}/src/thir/visit.rs (98%) rename compiler/rustc_middle/src/{ich => ty}/impls_ty.rs (78%) delete mode 100644 compiler/rustc_mir/src/borrow_check/type_check/relate_tys.rs delete mode 100644 compiler/rustc_mir/src/dataflow/mod.rs delete mode 100644 compiler/rustc_mir/src/util/mod.rs create mode 100644 compiler/rustc_mir_dataflow/Cargo.toml rename compiler/{rustc_mir/src/dataflow => rustc_mir_dataflow/src}/drop_flag_effects.rs (96%) rename compiler/{rustc_mir/src/util => rustc_mir_dataflow/src}/elaborate_drops.rs (99%) rename compiler/{rustc_mir/src/dataflow => rustc_mir_dataflow/src}/framework/cursor.rs (100%) rename compiler/{rustc_mir/src/dataflow => rustc_mir_dataflow/src}/framework/direction.rs (100%) rename compiler/{rustc_mir/src/dataflow => rustc_mir_dataflow/src}/framework/engine.rs (99%) rename compiler/{rustc_mir/src/dataflow => rustc_mir_dataflow/src}/framework/fmt.rs (94%) rename compiler/{rustc_mir/src/dataflow => rustc_mir_dataflow/src}/framework/graphviz.rs (99%) rename compiler/{rustc_mir/src/dataflow => rustc_mir_dataflow/src}/framework/lattice.rs (100%) rename compiler/{rustc_mir/src/dataflow => rustc_mir_dataflow/src}/framework/mod.rs (99%) rename compiler/{rustc_mir/src/dataflow => rustc_mir_dataflow/src}/framework/tests.rs (100%) rename compiler/{rustc_mir/src/dataflow => rustc_mir_dataflow/src}/framework/visitor.rs (63%) rename compiler/{rustc_mir/src/dataflow => rustc_mir_dataflow/src}/impls/borrowed_locals.rs (98%) rename compiler/{rustc_mir/src/dataflow => rustc_mir_dataflow/src}/impls/init_locals.rs (95%) rename compiler/{rustc_mir/src/dataflow => rustc_mir_dataflow/src}/impls/liveness.rs (81%) rename compiler/{rustc_mir/src/dataflow => rustc_mir_dataflow/src}/impls/mod.rs (95%) rename compiler/{rustc_mir/src/dataflow => rustc_mir_dataflow/src}/impls/storage_liveness.rs (96%) create mode 100644 compiler/rustc_mir_dataflow/src/lib.rs rename compiler/{rustc_mir/src/dataflow => rustc_mir_dataflow/src}/move_paths/abs_domain.rs (100%) rename compiler/{rustc_mir/src/dataflow => rustc_mir_dataflow/src}/move_paths/builder.rs (99%) rename compiler/{rustc_mir/src/dataflow => rustc_mir_dataflow/src}/move_paths/mod.rs (96%) rename compiler/{rustc_mir/src/transform => rustc_mir_dataflow/src}/rustc_peek.rs (96%) rename compiler/{rustc_mir/src/util => rustc_mir_dataflow/src}/storage.rs (100%) create mode 100644 compiler/rustc_mir_transform/Cargo.toml rename compiler/{rustc_mir/src/transform => rustc_mir_transform/src}/abort_unwinding_calls.rs (93%) rename compiler/{rustc_mir/src/transform => rustc_mir_transform/src}/add_call_guards.rs (98%) rename compiler/{rustc_mir/src/transform => rustc_mir_transform/src}/add_moves_for_packed_drops.rs (98%) rename compiler/{rustc_mir/src/transform => rustc_mir_transform/src}/add_retag.rs (99%) rename compiler/{rustc_mir/src/transform => rustc_mir_transform/src}/check_const_item_mutation.rs (99%) rename compiler/{rustc_mir/src/transform => rustc_mir_transform/src}/check_packed_ref.rs (99%) rename compiler/{rustc_mir/src/transform => rustc_mir_transform/src}/check_unsafety.rs (100%) rename compiler/{rustc_mir/src/transform => rustc_mir_transform/src}/cleanup_post_borrowck.rs (98%) rename compiler/{rustc_mir/src/transform => rustc_mir_transform/src}/const_debuginfo.rs (99%) rename compiler/{rustc_mir/src/transform => rustc_mir_transform/src}/const_goto.rs (99%) rename compiler/{rustc_mir/src/transform => rustc_mir_transform/src}/const_prop.rs (99%) rename compiler/{rustc_mir/src/transform => rustc_mir_transform/src}/coverage/counters.rs (100%) rename compiler/{rustc_mir/src/transform => rustc_mir_transform/src}/coverage/debug.rs (97%) rename compiler/{rustc_mir/src/transform => rustc_mir_transform/src}/coverage/graph.rs (100%) rename compiler/{rustc_mir/src/transform => rustc_mir_transform/src}/coverage/mod.rs (99%) rename compiler/{rustc_mir/src/transform => rustc_mir_transform/src}/coverage/query.rs (100%) rename compiler/{rustc_mir/src/transform => rustc_mir_transform/src}/coverage/spans.rs (99%) rename compiler/{rustc_mir/src/transform => rustc_mir_transform/src}/coverage/test_macros/Cargo.toml (85%) rename compiler/{rustc_mir/src/transform => rustc_mir_transform/src}/coverage/test_macros/src/lib.rs (100%) rename compiler/{rustc_mir/src/transform => rustc_mir_transform/src}/coverage/tests.rs (100%) rename compiler/{rustc_mir/src/transform => rustc_mir_transform/src}/deaggregator.rs (98%) rename compiler/{rustc_mir/src/transform => rustc_mir_transform/src}/deduplicate_blocks.rs (99%) rename compiler/{rustc_mir/src/transform => rustc_mir_transform/src}/dest_prop.rs (99%) rename compiler/{rustc_mir/src/transform => rustc_mir_transform/src}/dump_mir.rs (74%) rename compiler/{rustc_mir/src/transform => rustc_mir_transform/src}/early_otherwise_branch.rs (98%) rename compiler/{rustc_mir/src/transform => rustc_mir_transform/src}/elaborate_drops.rs (94%) rename compiler/{rustc_mir/src/transform => rustc_mir_transform/src}/function_item_references.rs (98%) rename compiler/{rustc_mir/src/transform => rustc_mir_transform/src}/generator.rs (98%) rename compiler/{rustc_mir/src/transform => rustc_mir_transform/src}/inline.rs (99%) rename compiler/{rustc_mir/src/transform => rustc_mir_transform/src}/inline/cycle.rs (100%) rename compiler/{rustc_mir/src/transform => rustc_mir_transform/src}/instcombine.rs (99%) rename compiler/{rustc_mir/src/transform/mod.rs => rustc_mir_transform/src/lib.rs} (90%) rename compiler/{rustc_mir/src/transform => rustc_mir_transform/src}/lower_intrinsics.rs (94%) rename compiler/{rustc_mir/src/transform => rustc_mir_transform/src}/lower_slice_len.rs (92%) rename compiler/{rustc_mir/src/transform => rustc_mir_transform/src}/match_branches.rs (98%) rename compiler/{rustc_mir/src/transform => rustc_mir_transform/src}/multiple_return_terminators.rs (96%) create mode 100644 compiler/rustc_mir_transform/src/normalize_array_len.rs rename compiler/{rustc_mir/src/transform => rustc_mir_transform/src}/nrvo.rs (99%) rename compiler/{rustc_mir/src/transform => rustc_mir_transform/src}/remove_noop_landing_pads.rs (98%) rename compiler/{rustc_mir/src/transform => rustc_mir_transform/src}/remove_storage_markers.rs (96%) rename compiler/{rustc_mir/src/transform => rustc_mir_transform/src}/remove_unneeded_drops.rs (97%) rename compiler/{rustc_mir/src/transform => rustc_mir_transform/src}/remove_zsts.rs (98%) rename compiler/{rustc_mir/src/transform => rustc_mir_transform/src}/required_consts.rs (100%) rename compiler/{rustc_mir/src/transform => rustc_mir_transform/src}/separate_const_switch.rs (99%) rename compiler/{rustc_mir => rustc_mir_transform}/src/shim.rs (99%) rename compiler/{rustc_mir/src/transform => rustc_mir_transform/src}/simplify.rs (95%) rename compiler/{rustc_mir/src/transform => rustc_mir_transform/src}/simplify_branches.rs (98%) rename compiler/{rustc_mir/src/transform => rustc_mir_transform/src}/simplify_comparison_integral.rs (100%) rename compiler/{rustc_mir/src/transform => rustc_mir_transform/src}/simplify_try.rs (99%) rename compiler/{rustc_mir/src/transform => rustc_mir_transform/src}/uninhabited_enum_branching.rs (99%) rename compiler/{rustc_mir/src/transform => rustc_mir_transform/src}/unreachable_prop.rs (98%) create mode 100644 compiler/rustc_monomorphize/Cargo.toml rename compiler/{rustc_mir/src/monomorphize => rustc_monomorphize/src}/collector.rs (98%) rename compiler/{rustc_mir/src/monomorphize/mod.rs => rustc_monomorphize/src/lib.rs} (65%) rename compiler/{rustc_mir/src/monomorphize => rustc_monomorphize/src}/partitioning/default.rs (95%) rename compiler/{rustc_mir/src/monomorphize => rustc_monomorphize/src}/partitioning/merging.rs (98%) rename compiler/{rustc_mir/src/monomorphize => rustc_monomorphize/src}/partitioning/mod.rs (99%) rename compiler/{rustc_mir/src/monomorphize => rustc_monomorphize/src}/polymorphize.rs (82%) rename compiler/{rustc_mir/src/monomorphize => rustc_monomorphize/src}/util.rs (100%) rename compiler/{rustc_middle => rustc_query_system}/src/ich/hcx.rs (72%) rename compiler/{rustc_middle => rustc_query_system}/src/ich/impls_hir.rs (80%) rename compiler/{rustc_middle => rustc_query_system}/src/ich/impls_syntax.rs (100%) rename compiler/{rustc_middle => rustc_query_system}/src/ich/mod.rs (74%) rename compiler/{rustc_middle/src/middle => rustc_session/src}/cstore.rs (86%) create mode 100644 compiler/rustc_target/src/abi/call/m68k.rs create mode 100644 compiler/rustc_target/src/spec/aarch64_kmc_solid_asp3.rs create mode 100644 compiler/rustc_target/src/spec/armv6k_nintendo_3ds.rs create mode 100644 compiler/rustc_target/src/spec/armv7_unknown_linux_uclibceabihf.rs create mode 100644 compiler/rustc_target/src/spec/armv7a_kmc_solid_asp3_eabi.rs create mode 100644 compiler/rustc_target/src/spec/armv7a_kmc_solid_asp3_eabihf.rs create mode 100644 compiler/rustc_target/src/spec/m68k_unknown_linux_gnu.rs create mode 100644 compiler/rustc_target/src/spec/solid_base.rs create mode 100644 compiler/rustc_trait_selection/src/traits/relationships.rs rename compiler/{rustc_trait_selection/src/traits/query => rustc_typeck/src/outlives}/outlives_bounds.rs (93%) create mode 100644 library/alloc/src/collections/btree/dedup_sorted_iter.rs delete mode 100644 library/alloc/src/prelude/mod.rs delete mode 100644 library/alloc/src/prelude/v1.rs create mode 100644 library/core/benches/num/int_log/mod.rs create mode 100644 library/core/benches/str.rs create mode 100644 library/core/primitive_docs/box_into_raw.md create mode 100644 library/core/primitive_docs/fs_file.md create mode 100644 library/core/primitive_docs/io_bufread.md create mode 100644 library/core/primitive_docs/io_read.md create mode 100644 library/core/primitive_docs/io_seek.md create mode 100644 library/core/primitive_docs/io_write.md create mode 100644 library/core/primitive_docs/net_tosocketaddrs.md create mode 100644 library/core/primitive_docs/process_exit.md create mode 100644 library/core/primitive_docs/string_string.md create mode 100644 library/core/src/primitive_docs.rs create mode 100644 library/std/primitive_docs/box_into_raw.md create mode 100644 library/std/primitive_docs/fs_file.md create mode 100644 library/std/primitive_docs/io_bufread.md create mode 100644 library/std/primitive_docs/io_read.md create mode 100644 library/std/primitive_docs/io_seek.md create mode 100644 library/std/primitive_docs/io_write.md create mode 100644 library/std/primitive_docs/net_tosocketaddrs.md create mode 100644 library/std/primitive_docs/process_exit.md create mode 100644 library/std/primitive_docs/string_string.md create mode 100644 library/std/src/os/solid/ffi.rs create mode 100644 library/std/src/os/solid/io.rs create mode 100644 library/std/src/os/solid/mod.rs create mode 100644 library/std/src/sys/itron/abi.rs create mode 100644 library/std/src/sys/itron/condvar.rs create mode 100644 library/std/src/sys/itron/error.rs create mode 100644 library/std/src/sys/itron/mutex.rs create mode 100644 library/std/src/sys/itron/spin.rs create mode 100644 library/std/src/sys/itron/task.rs create mode 100644 library/std/src/sys/itron/thread.rs create mode 100644 library/std/src/sys/itron/time.rs create mode 100644 library/std/src/sys/itron/time/tests.rs create mode 100644 library/std/src/sys/solid/abi/fs.rs create mode 100644 library/std/src/sys/solid/abi/mod.rs create mode 100644 library/std/src/sys/solid/abi/sockets.rs create mode 100644 library/std/src/sys/solid/alloc.rs create mode 100644 library/std/src/sys/solid/env.rs create mode 100644 library/std/src/sys/solid/error.rs create mode 100644 library/std/src/sys/solid/fs.rs create mode 100644 library/std/src/sys/solid/io.rs create mode 100644 library/std/src/sys/solid/memchr.rs create mode 100644 library/std/src/sys/solid/mod.rs create mode 100644 library/std/src/sys/solid/net.rs create mode 100644 library/std/src/sys/solid/os.rs create mode 100644 library/std/src/sys/solid/path.rs create mode 100644 library/std/src/sys/solid/rwlock.rs create mode 100644 library/std/src/sys/solid/stdio.rs create mode 100644 library/std/src/sys/solid/thread_local_dtor.rs create mode 100644 library/std/src/sys/solid/thread_local_key.rs create mode 100644 library/std/src/sys/solid/time.rs delete mode 100644 library/std/src/sys_common/rt.rs create mode 100644 library/stdarch/crates/intrinsic-test/Cargo.toml create mode 100644 library/stdarch/crates/intrinsic-test/README.md create mode 100644 library/stdarch/crates/intrinsic-test/neon-intrinsics.csv create mode 100644 library/stdarch/crates/intrinsic-test/src/argument.rs create mode 100644 library/stdarch/crates/intrinsic-test/src/intrinsic.rs create mode 100644 library/stdarch/crates/intrinsic-test/src/main.rs create mode 100644 library/stdarch/crates/intrinsic-test/src/types.rs create mode 100644 library/stdarch/crates/intrinsic-test/src/values.rs create mode 100644 library/test/src/helpers/shuffle.rs create mode 100644 src/ci/docker/host-x86_64/disabled/dist-m68k-linux/Dockerfile create mode 100755 src/ci/docker/host-x86_64/dist-x86_64-linux/download-openssl-curl.sh delete mode 100644 src/ci/docker/host-x86_64/shared/ISRG_Root_X1.crt delete mode 100755 src/ci/scripts/select-xcode.sh delete mode 100644 src/doc/rustc-dev-guide/src/building/ctags.md create mode 100644 src/doc/rustc-dev-guide/src/constants.md create mode 100644 src/doc/rustc-dev-guide/src/diagnostics/diagnostic-items.md create mode 100644 src/doc/rustc-dev-guide/src/tracing.md create mode 100644 src/doc/rustc/src/platform-support/armv7-unknown-linux-uclibceabihf.md create mode 100644 src/doc/rustc/src/platform-support/kmc-solid.md create mode 100644 src/doc/rustc/src/platform-support/m68k-unknown-linux-gnu.md create mode 100644 src/doc/unstable-book/src/compiler-flags/debug_info_for_profiling.md create mode 100644 src/doc/unstable-book/src/compiler-flags/profile_sample_use.md create mode 100644 src/doc/unstable-book/src/compiler-flags/remap-cwd-prefix.md create mode 100644 src/doc/unstable-book/src/language-features/closure-track-caller.md create mode 100644 src/librustdoc/html/highlight/fixtures/union.html create mode 100644 src/librustdoc/html/highlight/fixtures/union.rs create mode 100644 src/librustdoc/html/render/templates.rs create mode 100644 src/librustdoc/html/templates/print_item.html rename src/librustdoc/passes/{doc_test_lints.rs => check_doc_test_visibility.rs} (76%) create mode 100644 src/stage0.json delete mode 100644 src/stage0.txt create mode 100644 src/test/assembly/asm/aarch64-outline-atomics.rs create mode 100644 src/test/assembly/niche-prefer-zero.rs create mode 100644 src/test/assembly/pic-relocation-model.rs create mode 100644 src/test/assembly/pie-relocation-model.rs create mode 100644 src/test/assembly/x86_64-sse_crc.rs create mode 100644 src/test/codegen/debug-vtable.rs create mode 100644 src/test/codegen/intrinsics/const_eval_select.rs create mode 100644 src/test/codegen/panic-in-drop-abort.rs create mode 100644 src/test/codegen/pic-relocation-model.rs create mode 100644 src/test/codegen/pie-relocation-model.rs create mode 100644 src/test/codegen/sse42-implies-crc32.rs delete mode 100644 src/test/codegen/vtabletype.rs create mode 100644 src/test/debuginfo/msvc-scalarpair-params.rs create mode 100644 src/test/incremental/mir-opt.rs create mode 100644 src/test/mir-opt/lower_array_len.array_bound.InstCombine.diff create mode 100644 src/test/mir-opt/lower_array_len.array_bound.NormalizeArrayLen.diff create mode 100644 src/test/mir-opt/lower_array_len.array_bound.SimplifyLocals.diff create mode 100644 src/test/mir-opt/lower_array_len.array_bound_mut.InstCombine.diff create mode 100644 src/test/mir-opt/lower_array_len.array_bound_mut.NormalizeArrayLen.diff create mode 100644 src/test/mir-opt/lower_array_len.array_bound_mut.SimplifyLocals.diff create mode 100644 src/test/mir-opt/lower_array_len.array_len.InstCombine.diff create mode 100644 src/test/mir-opt/lower_array_len.array_len.NormalizeArrayLen.diff create mode 100644 src/test/mir-opt/lower_array_len.array_len.SimplifyLocals.diff create mode 100644 src/test/mir-opt/lower_array_len.array_len_by_value.InstCombine.diff create mode 100644 src/test/mir-opt/lower_array_len.array_len_by_value.NormalizeArrayLen.diff create mode 100644 src/test/mir-opt/lower_array_len.array_len_by_value.SimplifyLocals.diff create mode 100644 src/test/mir-opt/lower_array_len.rs create mode 100644 src/test/mir-opt/lower_intrinsics.align_of.LowerIntrinsics.diff create mode 100644 src/test/run-make/dep-graph/Makefile create mode 100644 src/test/run-make/dep-graph/foo.rs create mode 100644 src/test/run-make/issue-85441/Makefile create mode 100644 src/test/run-make/issue-85441/empty.rs create mode 100644 src/test/run-make/native-link-modifier-whole-archive/Makefile create mode 100644 src/test/run-make/native-link-modifier-whole-archive/c_static_lib_with_constructor.cpp create mode 100644 src/test/run-make/native-link-modifier-whole-archive/directly_linked.rs create mode 100644 src/test/run-make/native-link-modifier-whole-archive/indirectly_linked.rs create mode 100644 src/test/run-make/native-link-modifier-whole-archive/indirectly_linked_via_attr.rs create mode 100644 src/test/run-make/native-link-modifier-whole-archive/native_lib_in_src.rs create mode 100644 src/test/run-make/native-link-modifier-whole-archive/rlib_with_cmdline_native_lib.rs create mode 100644 src/test/run-make/raw-dylib-link-ordinal/Makefile create mode 100644 src/test/run-make/raw-dylib-link-ordinal/driver.rs create mode 100644 src/test/run-make/raw-dylib-link-ordinal/exporter.c create mode 100644 src/test/run-make/raw-dylib-link-ordinal/exporter.def create mode 100644 src/test/run-make/raw-dylib-link-ordinal/lib.rs create mode 100644 src/test/run-make/raw-dylib-link-ordinal/output.txt create mode 100644 src/test/rustdoc-gui/docblock-big-code-mobile.goml create mode 100644 src/test/rustdoc-gui/header-size.goml create mode 100644 src/test/rustdoc-gui/huge-collection-of-constants.goml create mode 100644 src/test/rustdoc-gui/jump-to-def-background.goml create mode 100644 src/test/rustdoc-gui/src/link_to_definition/Cargo.lock create mode 100644 src/test/rustdoc-gui/src/link_to_definition/Cargo.toml create mode 100644 src/test/rustdoc-gui/src/link_to_definition/lib.rs create mode 100644 src/test/rustdoc-gui/src/test_docs/build.rs create mode 100644 src/test/rustdoc-json/primitive.rs create mode 100644 src/test/rustdoc-json/primitives.rs create mode 100644 src/test/rustdoc-json/unions/impl.rs create mode 100644 src/test/rustdoc-ui/bounded-hr-lifetime.rs create mode 100644 src/test/rustdoc-ui/bounded-hr-lifetime.stderr create mode 100644 src/test/rustdoc-ui/coverage/enum-tuple-documented.rs create mode 100644 src/test/rustdoc-ui/coverage/enum-tuple-documented.stdout create mode 100644 src/test/rustdoc-ui/coverage/enum-tuple.rs create mode 100644 src/test/rustdoc-ui/coverage/enum-tuple.stdout create mode 100644 src/test/rustdoc-ui/display-output.rs create mode 100644 src/test/rustdoc-ui/display-output.stdout create mode 100644 src/test/rustdoc-ui/doc-cfg.rs create mode 100644 src/test/rustdoc-ui/doc-cfg.stderr create mode 100644 src/test/rustdoc-ui/feature-gate-doc_cfg_hide.rs create mode 100644 src/test/rustdoc-ui/feature-gate-doc_cfg_hide.stderr create mode 100644 src/test/rustdoc-ui/intra-doc/auxiliary/dep1.rs create mode 100644 src/test/rustdoc-ui/intra-doc/auxiliary/dep2.rs create mode 100644 src/test/rustdoc-ui/intra-doc/auxiliary/dep3.rs create mode 100644 src/test/rustdoc-ui/intra-doc/auxiliary/dep4.rs create mode 100644 src/test/rustdoc-ui/intra-doc/extern-crate-load.rs create mode 100644 src/test/rustdoc/associated-consts.rs create mode 100644 src/test/rustdoc/check-source-code-urls-to-def-std.rs create mode 100644 src/test/rustdoc/doc-auto-cfg.rs create mode 100644 src/test/rustdoc/doc-cfg-hide.rs create mode 100644 src/test/rustdoc/doc-cfg-implicit-gate.rs create mode 100644 src/test/rustdoc/doc-cfg-implicit.rs create mode 100644 src/test/rustdoc/feature-gate-doc_auto_cfg.rs create mode 100644 src/test/rustdoc/hidden-trait-methods-with-document-hidden-items.rs create mode 100644 src/test/rustdoc/hidden-trait-methods.rs create mode 100644 src/test/rustdoc/issue-89309-heading-levels.rs create mode 100644 src/test/rustdoc/no_std-primitive.rs create mode 100644 src/test/rustdoc/primitive/no_std.rs create mode 100644 src/test/rustdoc/table-in-docblock.rs create mode 100644 src/test/ui/asm/aarch64/bad-options.rs create mode 100644 src/test/ui/asm/aarch64/bad-options.stderr create mode 100644 src/test/ui/asm/aarch64/bad-reg.rs create mode 100644 src/test/ui/asm/aarch64/bad-reg.stderr create mode 100644 src/test/ui/asm/aarch64/const.rs create mode 100644 src/test/ui/asm/aarch64/duplicate-options.fixed create mode 100644 src/test/ui/asm/aarch64/duplicate-options.rs create mode 100644 src/test/ui/asm/aarch64/duplicate-options.stderr create mode 100644 src/test/ui/asm/aarch64/interpolated-idents.rs create mode 100644 src/test/ui/asm/aarch64/interpolated-idents.stderr create mode 100644 src/test/ui/asm/aarch64/parse-error.rs create mode 100644 src/test/ui/asm/aarch64/parse-error.stderr create mode 100644 src/test/ui/asm/aarch64/srcloc.rs create mode 100644 src/test/ui/asm/aarch64/srcloc.stderr create mode 100644 src/test/ui/asm/aarch64/sym.rs create mode 100644 src/test/ui/asm/aarch64/type-check-2.rs create mode 100644 src/test/ui/asm/aarch64/type-check-2.stderr create mode 100644 src/test/ui/asm/aarch64/type-check-3.rs create mode 100644 src/test/ui/asm/aarch64/type-check-3.stderr create mode 100644 src/test/ui/asm/bad-template.aarch64_mirunsafeck.stderr create mode 100644 src/test/ui/asm/bad-template.aarch64_thirunsafeck.stderr rename src/test/ui/asm/{bad-template.thirunsafeck.stderr => bad-template.x86_64_mirunsafeck.stderr} (85%) rename src/test/ui/asm/{bad-template.mirunsafeck.stderr => bad-template.x86_64_thirunsafeck.stderr} (85%) create mode 100644 src/test/ui/asm/issue-89305.rs create mode 100644 src/test/ui/asm/issue-89305.stderr create mode 100644 src/test/ui/asm/naked-functions-unused.aarch64.stderr delete mode 100644 src/test/ui/asm/naked-functions-unused.stderr create mode 100644 src/test/ui/asm/naked-functions-unused.x86_64.stderr rename src/test/ui/asm/{ => x86_64}/bad-options.rs (100%) rename src/test/ui/asm/{ => x86_64}/bad-options.stderr (100%) rename src/test/ui/asm/{ => x86_64}/bad-reg.rs (92%) rename src/test/ui/asm/{ => x86_64}/bad-reg.stderr (87%) rename src/test/ui/asm/{ => x86_64}/const.rs (100%) rename src/test/ui/asm/{ => x86_64}/duplicate-options.fixed (100%) rename src/test/ui/asm/{ => x86_64}/duplicate-options.rs (100%) rename src/test/ui/asm/{ => x86_64}/duplicate-options.stderr (100%) rename src/test/ui/asm/{ => x86_64}/interpolated-idents.rs (100%) rename src/test/ui/asm/{ => x86_64}/interpolated-idents.stderr (77%) rename src/test/ui/asm/{ => x86_64}/issue-82869.rs (100%) rename src/test/ui/asm/{ => x86_64}/issue-82869.stderr (100%) rename src/test/ui/asm/{ => x86_64}/parse-error.rs (95%) rename src/test/ui/asm/{ => x86_64}/parse-error.stderr (91%) rename src/test/ui/asm/{ => x86_64}/srcloc.rs (100%) rename src/test/ui/asm/{ => x86_64}/srcloc.stderr (100%) rename src/test/ui/asm/{ => x86_64}/sym.rs (100%) create mode 100644 src/test/ui/asm/x86_64/target-feature-attr.rs create mode 100644 src/test/ui/asm/x86_64/target-feature-attr.stderr rename src/test/ui/asm/{ => x86_64}/type-check-2.rs (93%) rename src/test/ui/asm/{ => x86_64}/type-check-2.stderr (91%) rename src/test/ui/asm/{ => x86_64}/type-check-3.rs (100%) rename src/test/ui/asm/{ => x86_64}/type-check-3.stderr (100%) rename src/test/ui/associated-type-bounds/{super-trait-referencing-self.rs => supertrait-referencing-self.rs} (100%) rename src/test/ui/associated-type-bounds/{super-trait-referencing.rs => supertrait-referencing.rs} (100%) rename src/test/ui/associated-type-bounds/{super-trait-where-referencing-self.rs => supertrait-where-referencing-self.rs} (100%) rename src/test/ui/{issues => associated-types}/issue-19883.rs (100%) rename src/test/ui/{issues => associated-types}/issue-19883.stderr (100%) rename src/test/ui/{issues => associated-types}/issue-21363.rs (100%) rename src/test/ui/{ => async-await}/auxiliary/issue-72470-lib.rs (100%) rename src/test/ui/{ => async-await}/issue-72470-llvm-dominate.rs (100%) create mode 100644 src/test/ui/attributes/extented-attribute-macro-error.rs create mode 100644 src/test/ui/attributes/extented-attribute-macro-error.stderr create mode 100644 src/test/ui/auto-traits/auto-trait-validation.fixed create mode 100644 src/test/ui/auto-traits/issue-84075.rs create mode 100644 src/test/ui/auto-traits/issue-84075.stderr delete mode 100644 src/test/ui/borrowck/borrowck-for-loop-head-linkage.nll.stderr delete mode 100644 src/test/ui/borrowck/borrowck-object-lifetime.nll.stderr create mode 100644 src/test/ui/borrowck/issue-82462.rs create mode 100644 src/test/ui/borrowck/issue-82462.stderr create mode 100644 src/test/ui/borrowck/issue-87456-point-to-closure.rs create mode 100644 src/test/ui/borrowck/issue-87456-point-to-closure.stderr create mode 100644 src/test/ui/borrowck/issue-88434-minimal-example.rs create mode 100644 src/test/ui/borrowck/issue-88434-minimal-example.stderr create mode 100644 src/test/ui/borrowck/issue-88434-removal-index-should-be-less.rs create mode 100644 src/test/ui/borrowck/issue-88434-removal-index-should-be-less.stderr create mode 100644 src/test/ui/cast/issue-89497.fixed create mode 100644 src/test/ui/cast/issue-89497.rs create mode 100644 src/test/ui/cast/issue-89497.stderr create mode 100644 src/test/ui/closures/2229_closure_analysis/issue-90465.fixed create mode 100644 src/test/ui/closures/2229_closure_analysis/issue-90465.rs create mode 100644 src/test/ui/closures/2229_closure_analysis/issue-90465.stderr create mode 100644 src/test/ui/closures/2229_closure_analysis/migrations/issue-90024-adt-correct-subst.rs rename src/test/ui/{issues => closures}/issue-78720.rs (100%) rename src/test/ui/{issues => closures}/issue-78720.stderr (100%) create mode 100644 src/test/ui/coercion/coerce-issue-49593-box-never.nofallback.stderr create mode 100644 src/test/ui/coercion/issue-88097.rs create mode 100644 src/test/ui/const-generics/expose-default-substs-param-env.rs create mode 100644 src/test/ui/const-generics/generic_const_exprs/abstract-consts-as-cast-5.rs create mode 100644 src/test/ui/const-generics/generic_const_exprs/abstract-consts-as-cast-5.stderr create mode 100644 src/test/ui/const-generics/generic_const_exprs/const_eval_resolve_canonical.rs create mode 100644 src/test/ui/const-generics/generic_const_exprs/unify-op-with-fn-call.rs create mode 100644 src/test/ui/const-generics/generic_const_exprs/unify-op-with-fn-call.stderr create mode 100644 src/test/ui/const-generics/issues/issue-82956.rs create mode 100644 src/test/ui/const-generics/issues/issue-82956.stderr create mode 100644 src/test/ui/const-generics/issues/issue-84659.rs create mode 100644 src/test/ui/const-generics/issues/issue-84659.stderr create mode 100644 src/test/ui/const-generics/issues/issue-86530.rs create mode 100644 src/test/ui/const-generics/issues/issue-86530.stderr create mode 100644 src/test/ui/const-generics/issues/issue-86535-2.rs create mode 100644 src/test/ui/const-generics/issues/issue-86535.rs create mode 100644 src/test/ui/const-generics/issues/issue-87493.rs create mode 100644 src/test/ui/const-generics/issues/issue-87493.stderr create mode 100644 src/test/ui/const-generics/issues/issue-89334.rs create mode 100644 src/test/ui/const-generics/parser-error-recovery/issue-89013-no-assoc.rs create mode 100644 src/test/ui/const-generics/parser-error-recovery/issue-89013-no-assoc.stderr create mode 100644 src/test/ui/const-generics/parser-error-recovery/issue-89013-no-kw.rs create mode 100644 src/test/ui/const-generics/parser-error-recovery/issue-89013-no-kw.stderr create mode 100644 src/test/ui/const-generics/parser-error-recovery/issue-89013-type.rs create mode 100644 src/test/ui/const-generics/parser-error-recovery/issue-89013-type.stderr create mode 100644 src/test/ui/const-generics/parser-error-recovery/issue-89013.rs create mode 100644 src/test/ui/const-generics/parser-error-recovery/issue-89013.stderr create mode 100644 src/test/ui/const-generics/sneaky-array-repeat-expr.rs create mode 100644 src/test/ui/const-generics/sneaky-array-repeat-expr.stderr delete mode 100644 src/test/ui/consts/const-eval/feature-gate-const_panic.rs delete mode 100644 src/test/ui/consts/const-eval/feature-gate-const_panic.stderr create mode 100644 src/test/ui/consts/const_in_pattern/issue-73431.stderr rename src/test/ui/consts/control-flow/{assert.const_panic.stderr => assert.stderr} (82%) delete mode 100644 src/test/ui/consts/control-flow/assert.stock.stderr rename src/test/ui/{issues => consts}/issue-23833.rs (100%) rename src/test/ui/{issues => consts}/issue-34784.rs (100%) create mode 100644 src/test/ui/consts/issue-88071.rs create mode 100644 src/test/ui/consts/issue-89088.rs create mode 100644 src/test/ui/consts/not_const_clusure_in_const.rs create mode 100644 src/test/ui/consts/refs_check_const_eq-issue-88384.rs create mode 100644 src/test/ui/consts/refs_check_const_eq-issue-88384.stderr create mode 100644 src/test/ui/consts/refs_check_const_value_eq-issue-88876.rs create mode 100644 src/test/ui/crate-loading/auxiliary/crateresolve2-1.rs create mode 100644 src/test/ui/crate-loading/auxiliary/crateresolve2-2.rs create mode 100644 src/test/ui/crate-loading/auxiliary/crateresolve2-3.rs create mode 100644 src/test/ui/crate-loading/crateresolve1.stderr create mode 100644 src/test/ui/crate-loading/crateresolve2.rs create mode 100644 src/test/ui/crate-loading/crateresolve2.stderr create mode 100644 src/test/ui/derives/clone-debug-dead-code.rs create mode 100644 src/test/ui/derives/clone-debug-dead-code.stderr rename src/test/ui/{issues => deriving}/issue-3935.rs (100%) create mode 100644 src/test/ui/deriving/issue-89188-gat-hrtb.rs create mode 100644 src/test/ui/did_you_mean/issue-87830-try-brackets-for-arrays.rs create mode 100644 src/test/ui/did_you_mean/issue-87830-try-brackets-for-arrays.stderr create mode 100644 src/test/ui/dropck/relate_lt_in_type_outlives_bound.rs create mode 100644 src/test/ui/dropck/relate_lt_in_type_outlives_bound.stderr create mode 100644 src/test/ui/duplicate_doc_alias.rs create mode 100644 src/test/ui/duplicate_doc_alias.stderr create mode 100644 src/test/ui/enum-discriminant/issue-90038.rs create mode 100644 src/test/ui/enum-discriminant/niche-prefer-zero.rs delete mode 100644 src/test/ui/error-codes/E0439.rs delete mode 100644 src/test/ui/error-codes/E0439.stderr create mode 100644 src/test/ui/error-codes/E0464.rs create mode 100644 src/test/ui/error-codes/E0464.stderr create mode 100644 src/test/ui/error-codes/auxiliary/crateresolve1-1.rs create mode 100644 src/test/ui/error-codes/auxiliary/crateresolve1-2.rs create mode 100644 src/test/ui/error-codes/auxiliary/crateresolve1-3.rs create mode 100644 src/test/ui/errors/issue-89280-emitter-overflow-splice-lines.rs create mode 100644 src/test/ui/errors/issue-89280-emitter-overflow-splice-lines.stderr create mode 100644 src/test/ui/expr/malformed_closure/missing_braces_around_block.fixed create mode 100644 src/test/ui/expr/malformed_closure/missing_braces_around_block.rs create mode 100644 src/test/ui/expr/malformed_closure/missing_braces_around_block.stderr create mode 100644 src/test/ui/expr/malformed_closure/ruby_style_closure.rs create mode 100644 src/test/ui/expr/malformed_closure/ruby_style_closure.stderr create mode 100644 src/test/ui/feature-gates/feature-gate-closure_track_caller.rs create mode 100644 src/test/ui/feature-gates/feature-gate-closure_track_caller.stderr create mode 100644 src/test/ui/feature-gates/feature-gate-non_exhaustive_omitted_patterns_lint.rs create mode 100644 src/test/ui/feature-gates/feature-gate-non_exhaustive_omitted_patterns_lint.stderr delete mode 100644 src/test/ui/feature-gates/feature-gate-try_reserve.rs delete mode 100644 src/test/ui/feature-gates/feature-gate-try_reserve.stderr create mode 100644 src/test/ui/fmt/issue-89173.rs create mode 100644 src/test/ui/fmt/issue-89173.stderr create mode 100644 src/test/ui/fn/implied-bounds-unnorm-associated-type.nll.stderr create mode 100644 src/test/ui/fn/implied-bounds-unnorm-associated-type.rs create mode 100644 src/test/ui/fn/implied-bounds-unnorm-associated-type.stderr create mode 100644 src/test/ui/generator/issue-88653.rs create mode 100644 src/test/ui/generator/issue-88653.stderr delete mode 100644 src/test/ui/generic-associated-types/issue-87748.rs create mode 100644 src/test/ui/generic-associated-types/issue-87750.rs create mode 100644 src/test/ui/generic-associated-types/issue-87750.stderr create mode 100644 src/test/ui/generic-associated-types/issue-88287.rs create mode 100644 src/test/ui/generic-associated-types/issue-88360.rs create mode 100644 src/test/ui/generic-associated-types/issue-88360.stderr create mode 100644 src/test/ui/generic-associated-types/issue-88405.rs create mode 100644 src/test/ui/generic-associated-types/missing-where-clause-on-trait.rs create mode 100644 src/test/ui/generic-associated-types/missing-where-clause-on-trait.stderr rename src/test/ui/{ => generics}/mid-path-type-params.rs (100%) delete mode 100644 src/test/ui/hashmap/hashmap-iter-value-lifetime.nll.stderr delete mode 100644 src/test/ui/hashmap/hashmap-lifetimes.nll.stderr create mode 100644 src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-80706.rs create mode 100644 src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-80956.rs create mode 100644 src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-81809.rs create mode 100644 src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-85455.rs create mode 100644 src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-85455.stderr create mode 100644 src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-89118.rs create mode 100644 src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-89118.stderr create mode 100644 src/test/ui/hrtb/issue-88446.rs rename src/test/ui/{issues => impl-trait}/type-arg-mismatch-due-to-impl-trait.rs (100%) rename src/test/ui/{issues => impl-trait}/type-arg-mismatch-due-to-impl-trait.stderr (100%) create mode 100644 src/test/ui/inference/issue-71309.rs create mode 100644 src/test/ui/inference/issue-71309.stderr create mode 100644 src/test/ui/intrinsics/const-eval-select-bad.rs create mode 100644 src/test/ui/intrinsics/const-eval-select-bad.stderr create mode 100644 src/test/ui/intrinsics/const-eval-select-stability.rs create mode 100644 src/test/ui/intrinsics/const-eval-select-stability.stderr create mode 100644 src/test/ui/intrinsics/const-eval-select-x86_64.rs create mode 100644 src/test/ui/intrinsics/const-eval-select.rs create mode 100644 src/test/ui/invalid/invalid-crate-type-macro.rs create mode 100644 src/test/ui/invalid/invalid-crate-type-macro.stderr delete mode 100644 src/test/ui/issues/issue-5791.rs delete mode 100644 src/test/ui/issues/issue-5791.stderr create mode 100644 src/test/ui/issues/issue-65230.rs create mode 100644 src/test/ui/issues/issue-65230.stderr create mode 100644 src/test/ui/issues/issue-86865.rs create mode 100644 src/test/ui/issues/issue-86865.stderr create mode 100644 src/test/ui/lang-items/fn-fn_mut-call-ill-formed.rs create mode 100644 src/test/ui/lang-items/fn-fn_mut-call-ill-formed.stderr create mode 100644 src/test/ui/lang-items/issue-83471.rs create mode 100644 src/test/ui/lang-items/issue-83471.stderr create mode 100644 src/test/ui/lifetimes/issue-77175.rs create mode 100644 src/test/ui/lifetimes/lifetime-errors/issue_74400.nll.stderr create mode 100644 src/test/ui/lifetimes/lifetime-errors/issue_74400.rs create mode 100644 src/test/ui/lifetimes/lifetime-errors/issue_74400.stderr rename src/test/ui/{ => lint}/enable-unstable-lib-feature.rs (100%) rename src/test/ui/{ => lint}/enable-unstable-lib-feature.stderr (100%) rename src/test/ui/{issues => lint}/issue-57410.rs (100%) create mode 100644 src/test/ui/lint/issue-79546-fuel-ice.rs rename src/test/ui/{issues => lint}/issue-79744.rs (100%) rename src/test/ui/{issues => lint}/issue-79744.stderr (100%) create mode 100644 src/test/ui/lint/issue-87308.rs create mode 100644 src/test/ui/lint/issue-87308.stdout create mode 100644 src/test/ui/lint/issue-89469.rs create mode 100644 src/test/ui/lint/issue-90614-accept-allow-text-direction-codepoint-in-comment-lint.rs create mode 100644 src/test/ui/lint/known-tool-in-submodule/root.rs create mode 100644 src/test/ui/lint/known-tool-in-submodule/submodule.rs create mode 100644 src/test/ui/lint/lint-enum-intrinsics-non-enums.rs create mode 100644 src/test/ui/lint/lint-enum-intrinsics-non-enums.stderr create mode 100644 src/test/ui/lint/must_not_suspend/boxed.rs create mode 100644 src/test/ui/lint/must_not_suspend/boxed.stderr create mode 100644 src/test/ui/lint/must_not_suspend/dedup.rs create mode 100644 src/test/ui/lint/must_not_suspend/dedup.stderr create mode 100644 src/test/ui/lint/must_not_suspend/feature-gate-must_not_suspend.rs create mode 100644 src/test/ui/lint/must_not_suspend/feature-gate-must_not_suspend.stderr create mode 100644 src/test/ui/lint/must_not_suspend/gated.rs create mode 100644 src/test/ui/lint/must_not_suspend/gated.stderr create mode 100644 src/test/ui/lint/must_not_suspend/generic.rs create mode 100644 src/test/ui/lint/must_not_suspend/handled.rs create mode 100644 src/test/ui/lint/must_not_suspend/issue-89562.rs create mode 100644 src/test/ui/lint/must_not_suspend/mutex.rs create mode 100644 src/test/ui/lint/must_not_suspend/mutex.stderr create mode 100644 src/test/ui/lint/must_not_suspend/other_items.rs create mode 100644 src/test/ui/lint/must_not_suspend/other_items.stderr create mode 100644 src/test/ui/lint/must_not_suspend/ref.rs create mode 100644 src/test/ui/lint/must_not_suspend/ref.stderr create mode 100644 src/test/ui/lint/must_not_suspend/return.rs create mode 100644 src/test/ui/lint/must_not_suspend/return.stderr create mode 100644 src/test/ui/lint/must_not_suspend/trait.rs create mode 100644 src/test/ui/lint/must_not_suspend/trait.stderr create mode 100644 src/test/ui/lint/must_not_suspend/unit.rs create mode 100644 src/test/ui/lint/must_not_suspend/unit.stderr create mode 100644 src/test/ui/lint/must_not_suspend/warn.rs create mode 100644 src/test/ui/lint/must_not_suspend/warn.stderr create mode 100644 src/test/ui/lint/unsafe_code/auxiliary/forge_unsafe_block.rs create mode 100644 src/test/ui/lint/unsafe_code/forge_unsafe_block.rs create mode 100644 src/test/ui/lint/unused/issue-88519-unused-paren.rs rename src/test/ui/{issues => llvm-asm}/issue-37433.rs (100%) rename src/test/ui/{issues => llvm-asm}/issue-37433.stderr (100%) rename src/test/ui/{ => macros}/auxiliary/define-macro.rs (100%) create mode 100644 src/test/ui/macros/auxiliary/macro-def-site-super.rs create mode 100644 src/test/ui/macros/bang-after-name.fixed create mode 100644 src/test/ui/macros/bang-after-name.rs create mode 100644 src/test/ui/macros/bang-after-name.stderr create mode 100644 src/test/ui/macros/macro-def-site-super.rs rename src/test/ui/{ => macros}/out-of-order-shadowing.rs (100%) rename src/test/ui/{ => macros}/out-of-order-shadowing.stderr (96%) rename src/test/ui/{ => match}/guards.rs (100%) rename src/test/ui/{issues => match}/issue-33498.rs (100%) rename src/test/ui/{issues => match}/issue-41255.rs (100%) rename src/test/ui/{issues => match}/issue-41255.stderr (100%) rename src/test/ui/{issues => match}/issue-56685.rs (100%) rename src/test/ui/{issues => match}/issue-56685.stderr (100%) create mode 100644 src/test/ui/mir-dataflow/liveness-enum.rs create mode 100644 src/test/ui/mir-dataflow/liveness-enum.stderr create mode 100644 src/test/ui/modules/path-invalid-form.rs create mode 100644 src/test/ui/modules/path-invalid-form.stderr create mode 100644 src/test/ui/modules/path-macro.rs create mode 100644 src/test/ui/modules/path-macro.stderr create mode 100644 src/test/ui/moves/issue-72649-uninit-in-loop.rs create mode 100644 src/test/ui/moves/issue-72649-uninit-in-loop.stderr create mode 100644 src/test/ui/native-library-link-flags/mix-bundle-and-whole-archive-link-attr.rs create mode 100644 src/test/ui/native-library-link-flags/mix-bundle-and-whole-archive-link-attr.stderr create mode 100644 src/test/ui/native-library-link-flags/mix-bundle-and-whole-archive.rs create mode 100644 src/test/ui/native-library-link-flags/mix-bundle-and-whole-archive.stderr rename src/test/ui/never_type/{defaulted-never-note.stderr => defaulted-never-note.fallback.stderr} (78%) create mode 100644 src/test/ui/never_type/diverging-fallback-no-leak.fallback.stderr create mode 100644 src/test/ui/never_type/diverging-fallback-no-leak.rs create mode 100644 src/test/ui/never_type/diverging-fallback-unconstrained-return.rs rename src/test/ui/{ => never_type}/expr-empty-ret.rs (100%) create mode 100644 src/test/ui/never_type/fallback-closure-ret.rs create mode 100644 src/test/ui/never_type/fallback-closure-wrap.fallback.stderr create mode 100644 src/test/ui/never_type/fallback-closure-wrap.rs create mode 100644 src/test/ui/never_type/never-value-fallback-issue-66757.nofallback.stderr delete mode 100644 src/test/ui/nll/get_default.nll.stderr create mode 100644 src/test/ui/nll/issue-55825-const-fn.rs create mode 100644 src/test/ui/nll/issue-55825-const-fn.stderr create mode 100644 src/test/ui/nll/issue-67007-escaping-data.rs create mode 100644 src/test/ui/nll/issue-67007-escaping-data.stderr create mode 100644 src/test/ui/nll/issue-73159-rpit-static.rs create mode 100644 src/test/ui/nll/issue-73159-rpit-static.stderr delete mode 100644 src/test/ui/nll/region-ends-after-if-condition.nll.stderr create mode 100644 src/test/ui/parser/issue-30318.fixed create mode 100644 src/test/ui/parser/issue-88276-unary-plus.fixed create mode 100644 src/test/ui/parser/issue-88276-unary-plus.rs create mode 100644 src/test/ui/parser/issue-88276-unary-plus.stderr create mode 100644 src/test/ui/parser/issue-88770.rs create mode 100644 src/test/ui/parser/issue-88770.stderr create mode 100644 src/test/ui/parser/issue-88818.rs create mode 100644 src/test/ui/parser/issue-88818.stderr create mode 100644 src/test/ui/parser/issue-89388.rs create mode 100644 src/test/ui/parser/issue-89388.stderr create mode 100644 src/test/ui/parser/issue-89396.fixed create mode 100644 src/test/ui/parser/issue-89396.rs create mode 100644 src/test/ui/parser/issue-89396.stderr create mode 100644 src/test/ui/parser/macro-braces-dot-question.rs create mode 100644 src/test/ui/parser/unicode-character-literal.fixed create mode 100644 src/test/ui/parser/unicode-character-literal.rs create mode 100644 src/test/ui/parser/unicode-character-literal.stderr create mode 100644 src/test/ui/parser/unicode-control-codepoints.rs create mode 100644 src/test/ui/parser/unicode-control-codepoints.stderr create mode 100644 src/test/ui/pattern/issue-88074-pat-range-type-inference-err.rs create mode 100644 src/test/ui/pattern/issue-88074-pat-range-type-inference-err.stderr create mode 100644 src/test/ui/pattern/issue-88074-pat-range-type-inference.rs create mode 100644 src/test/ui/pattern/usefulness/auxiliary/hidden.rs create mode 100644 src/test/ui/pattern/usefulness/auxiliary/unstable.rs create mode 100644 src/test/ui/pattern/usefulness/const-private-fields.rs create mode 100644 src/test/ui/pattern/usefulness/doc-hidden-non-exhaustive.rs create mode 100644 src/test/ui/pattern/usefulness/doc-hidden-non-exhaustive.stderr create mode 100644 src/test/ui/pattern/usefulness/issue-72476-and-89393-associated-type.rs delete mode 100644 src/test/ui/pattern/usefulness/issue-72476-associated-type.rs create mode 100644 src/test/ui/pattern/usefulness/issue-82772-match-box-as-struct.rs create mode 100644 src/test/ui/pattern/usefulness/issue-82772-match-box-as-struct.stderr create mode 100644 src/test/ui/pattern/usefulness/stable-gated-patterns.rs create mode 100644 src/test/ui/pattern/usefulness/stable-gated-patterns.stderr create mode 100644 src/test/ui/pattern/usefulness/unstable-gated-patterns.rs create mode 100644 src/test/ui/pattern/usefulness/unstable-gated-patterns.stderr rename src/test/ui/{issues => polymorphization}/issue-74614.rs (100%) rename src/test/ui/{issues => privacy}/issue-79593.rs (100%) rename src/test/ui/{issues => privacy}/issue-79593.stderr (100%) delete mode 100644 src/test/ui/proc-macro/attribute-after-derive-feature-gate.rs delete mode 100644 src/test/ui/proc-macro/attribute-after-derive-feature-gate.stderr create mode 100644 src/test/ui/proc-macro/issue-86781-bad-inner-doc.fixed create mode 100644 src/test/ui/recursion_limit/invalid_digit_type.rs create mode 100644 src/test/ui/recursion_limit/invalid_digit_type.stderr create mode 100644 src/test/ui/recursion_limit/invalid_macro.rs create mode 100644 src/test/ui/recursion_limit/invalid_macro.stderr create mode 100644 src/test/ui/recursion_limit/no-value.rs create mode 100644 src/test/ui/recursion_limit/no-value.stderr create mode 100644 src/test/ui/recursion_limit/zero-overflow.rs create mode 100644 src/test/ui/recursion_limit/zero-overflow.stderr create mode 100644 src/test/ui/repr/repr-transparent-issue-87496.rs create mode 100644 src/test/ui/repr/repr-transparent-issue-87496.stderr rename src/test/ui/{issues => resolve}/issue-42944.rs (100%) rename src/test/ui/{issues => resolve}/issue-42944.stderr (81%) create mode 100644 src/test/ui/resolve/issue-85671.rs create mode 100644 src/test/ui/resolve/issue-88472.rs create mode 100644 src/test/ui/resolve/issue-88472.stderr create mode 100644 src/test/ui/resolve/suggest-path-for-tuple-struct.rs create mode 100644 src/test/ui/resolve/suggest-path-for-tuple-struct.stderr rename src/test/ui/{ => resolve}/use-self-in-inner-fn.rs (100%) rename src/test/ui/{ => resolve}/use-self-in-inner-fn.stderr (100%) delete mode 100644 src/test/ui/rfc-2005-default-binding-mode/borrowck-issue-49631.nll.stderr create mode 100644 src/test/ui/rfc-2008-non-exhaustive/auxiliary/unstable.rs create mode 100644 src/test/ui/rfc-2008-non-exhaustive/omitted-patterns.rs create mode 100644 src/test/ui/rfc-2008-non-exhaustive/omitted-patterns.stderr create mode 100644 src/test/ui/rfc-2008-non-exhaustive/stable-omitted-patterns.rs create mode 100644 src/test/ui/rfc-2008-non-exhaustive/stable-omitted-patterns.stderr create mode 100644 src/test/ui/rfc-2091-track-caller/tracked-closure.rs create mode 100644 src/test/ui/rfc-2627-raw-dylib/link-ordinal-missing-argument.rs create mode 100644 src/test/ui/rfc-2627-raw-dylib/link-ordinal-missing-argument.stderr create mode 100644 src/test/ui/rfc-2627-raw-dylib/link-ordinal-multiple.rs create mode 100644 src/test/ui/rfc-2627-raw-dylib/link-ordinal-multiple.stderr create mode 100644 src/test/ui/rfc-2627-raw-dylib/link-ordinal-too-many-arguments.rs create mode 100644 src/test/ui/rfc-2627-raw-dylib/link-ordinal-too-many-arguments.stderr create mode 100644 src/test/ui/rfc-2632-const-trait-impl/const-closures.rs create mode 100644 src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.precise.stderr create mode 100644 src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.rs create mode 100644 src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.stock.stderr create mode 100644 src/test/ui/rfc-2632-const-trait-impl/const-drop.rs rename src/test/ui/rfc-2632-const-trait-impl/{impl-with-default-fn.rs => impl-with-default-fn-fail.rs} (89%) rename src/test/ui/rfc-2632-const-trait-impl/{impl-with-default-fn.stderr => impl-with-default-fn-fail.stderr} (84%) create mode 100644 src/test/ui/rfc-2632-const-trait-impl/impl-with-default-fn-pass.rs create mode 100644 src/test/ui/rfc-2632-const-trait-impl/inherent-impl-const-bounds.rs delete mode 100644 src/test/ui/simd-intrinsic/simd-intrinsic-generic-bitmask.rs rename src/test/ui/simd/{simd-array-trait.rs => array-trait.rs} (100%) rename src/test/ui/simd/{simd-array-trait.stderr => array-trait.stderr} (87%) rename src/test/ui/simd/{simd-array-type.rs => array-type.rs} (100%) rename src/test/ui/simd/{simd-generics.rs => generics.rs} (100%) rename src/test/ui/simd/{simd-intrinsic-float-math.rs => intrinsic/float-math-pass.rs} (100%) rename src/test/ui/simd/{simd-intrinsic-float-minmax.rs => intrinsic/float-minmax-pass.rs} (100%) rename src/test/ui/{simd-intrinsic/simd-intrinsic-generic-arithmetic.rs => simd/intrinsic/generic-arithmetic-2.rs} (100%) rename src/test/ui/{simd-intrinsic/simd-intrinsic-generic-arithmetic.stderr => simd/intrinsic/generic-arithmetic-2.stderr} (77%) rename src/test/ui/simd/{simd-intrinsic-generic-arithmetic.rs => intrinsic/generic-arithmetic-pass.rs} (100%) rename src/test/ui/{simd-intrinsic/simd-intrinsic-generic-arithmetic-saturating.rs => simd/intrinsic/generic-arithmetic-saturating-2.rs} (100%) rename src/test/ui/{simd-intrinsic/simd-intrinsic-generic-arithmetic-saturating.stderr => simd/intrinsic/generic-arithmetic-saturating-2.stderr} (82%) rename src/test/ui/simd/{simd-intrinsic-generic-arithmetic-saturating.rs => intrinsic/generic-arithmetic-saturating-pass.rs} (100%) rename src/test/ui/simd/{simd-intrinsic-generic-bitmask.rs => intrinsic/generic-bitmask-pass.rs} (100%) create mode 100644 src/test/ui/simd/intrinsic/generic-bitmask.rs rename src/test/ui/{simd-intrinsic/simd-intrinsic-generic-bitmask.stderr => simd/intrinsic/generic-bitmask.stderr} (80%) rename src/test/ui/simd/{simd-intrinsic-generic-cast.rs => intrinsic/generic-cast-pass.rs} (100%) rename src/test/ui/{simd-intrinsic/simd-intrinsic-generic-cast.rs => simd/intrinsic/generic-cast.rs} (100%) rename src/test/ui/{simd-intrinsic/simd-intrinsic-generic-cast.stderr => simd/intrinsic/generic-cast.stderr} (83%) rename src/test/ui/simd/{simd-intrinsic-generic-comparison.rs => intrinsic/generic-comparison-pass.rs} (100%) rename src/test/ui/{simd-intrinsic/simd-intrinsic-generic-comparison.rs => simd/intrinsic/generic-comparison.rs} (100%) rename src/test/ui/{simd-intrinsic/simd-intrinsic-generic-comparison.stderr => simd/intrinsic/generic-comparison.stderr} (80%) rename src/test/ui/simd/{simd-intrinsic-generic-elements.rs => intrinsic/generic-elements-pass.rs} (100%) rename src/test/ui/{simd-intrinsic/simd-intrinsic-generic-elements.rs => simd/intrinsic/generic-elements.rs} (100%) rename src/test/ui/{simd-intrinsic/simd-intrinsic-generic-elements.stderr => simd/intrinsic/generic-elements.stderr} (82%) rename src/test/ui/simd/{simd-intrinsic-generic-gather.rs => intrinsic/generic-gather-pass.rs} (100%) rename src/test/ui/simd/{simd-intrinsic-generic-reduction.rs => intrinsic/generic-reduction-pass.rs} (95%) rename src/test/ui/{simd-intrinsic/simd-intrinsic-generic-reduction.rs => simd/intrinsic/generic-reduction.rs} (100%) rename src/test/ui/{simd-intrinsic/simd-intrinsic-generic-reduction.stderr => simd/intrinsic/generic-reduction.stderr} (82%) rename src/test/ui/simd/{simd-intrinsic-generic-select.rs => intrinsic/generic-select-pass.rs} (100%) rename src/test/ui/{simd-intrinsic/simd-intrinsic-generic-select.rs => simd/intrinsic/generic-select.rs} (100%) rename src/test/ui/{simd-intrinsic/simd-intrinsic-generic-select.stderr => simd/intrinsic/generic-select.stderr} (81%) create mode 100644 src/test/ui/simd/intrinsic/generic-shuffle.rs create mode 100644 src/test/ui/simd/intrinsic/generic-shuffle.stderr rename src/test/ui/{simd-intrinsic/simd-intrinsic-inlining-issue67557-ice.rs => simd/intrinsic/inlining-issue67557-ice.rs} (100%) rename src/test/ui/{simd-intrinsic/simd-intrinsic-inlining-issue67557.rs => simd/intrinsic/inlining-issue67557.rs} (100%) rename src/test/ui/{simd-intrinsic => simd/intrinsic}/issue-85855.rs (100%) rename src/test/ui/{simd-intrinsic => simd/intrinsic}/issue-85855.stderr (100%) create mode 100644 src/test/ui/simd/issue-89193.rs create mode 100644 src/test/ui/simd/monomorphize-shuffle-index.rs create mode 100644 src/test/ui/simd/shuffle.rs rename src/test/ui/simd/{simd-size-align.rs => size-align.rs} (100%) rename src/test/ui/simd/{simd-target-feature-mixup.rs => target-feature-mixup.rs} (100%) rename src/test/ui/simd/{simd-type-generic-monomorphisation-empty.rs => type-generic-monomorphisation-empty.rs} (100%) rename src/test/ui/simd/{simd-type-generic-monomorphisation-empty.stderr => type-generic-monomorphisation-empty.stderr} (100%) rename src/test/ui/simd/{simd-type-generic-monomorphisation-extern-nonnull-ptr.rs => type-generic-monomorphisation-extern-nonnull-ptr.rs} (100%) rename src/test/ui/simd/{simd-type-generic-monomorphisation-non-primitive.rs => type-generic-monomorphisation-non-primitive.rs} (100%) rename src/test/ui/simd/{simd-type-generic-monomorphisation-non-primitive.stderr => type-generic-monomorphisation-non-primitive.stderr} (100%) rename src/test/ui/simd/{simd-type-generic-monomorphisation-oversized.rs => type-generic-monomorphisation-oversized.rs} (100%) rename src/test/ui/simd/{simd-type-generic-monomorphisation-oversized.stderr => type-generic-monomorphisation-oversized.stderr} (100%) rename src/test/ui/simd/{simd-type-generic-monomorphisation-power-of-two.rs => type-generic-monomorphisation-power-of-two.rs} (100%) rename src/test/ui/simd/{simd-type-generic-monomorphisation-wide-ptr.rs => type-generic-monomorphisation-wide-ptr.rs} (100%) rename src/test/ui/simd/{simd-type-generic-monomorphisation-wide-ptr.stderr => type-generic-monomorphisation-wide-ptr.stderr} (100%) rename src/test/ui/simd/{simd-type-generic-monomorphisation.rs => type-generic-monomorphisation.rs} (100%) rename src/test/ui/simd/{simd-type-generic-monomorphisation.stderr => type-generic-monomorphisation.stderr} (100%) rename src/test/ui/simd/{simd-type.rs => type-len.rs} (100%) rename src/test/ui/simd/{simd-type.stderr => type-len.stderr} (84%) rename src/test/ui/simd/{simd-type-wide-ptr.rs => type-wide-ptr.rs} (100%) rename src/test/ui/simd/{simd-type-wide-ptr.stderr => type-wide-ptr.stderr} (100%) rename src/test/ui/{issues => specialization}/issue-35376.rs (100%) rename src/test/ui/{issues => specialization}/issue-35376.stderr (100%) create mode 100644 src/test/ui/specialization/min_specialization/spec-marker-supertraits.rs create mode 100644 src/test/ui/specialization/min_specialization/spec-marker-supertraits.stderr rename src/test/ui/specialization/{specialization-super-traits.rs => specialization-supertraits.rs} (100%) rename src/test/ui/specialization/{specialization-super-traits.stderr => specialization-supertraits.stderr} (90%) rename src/test/ui/{issues => static}/issue-34194.rs (100%) rename src/test/ui/{issues => structs-enums}/issue-38002.rs (100%) create mode 100644 src/test/ui/suggestions/box-future-wrong-output.rs create mode 100644 src/test/ui/suggestions/box-future-wrong-output.stderr create mode 100644 src/test/ui/suggestions/core-std-import-order-issue-83564.rs create mode 100644 src/test/ui/suggestions/core-std-import-order-issue-83564.stderr create mode 100644 src/test/ui/suggestions/crate-or-module-typo.rs create mode 100644 src/test/ui/suggestions/crate-or-module-typo.stderr create mode 100644 src/test/ui/suggestions/derive-trait-for-method-call.rs create mode 100644 src/test/ui/suggestions/derive-trait-for-method-call.stderr create mode 100644 src/test/ui/suggestions/ignore-nested-field-binding.fixed create mode 100644 src/test/ui/suggestions/ignore-nested-field-binding.rs create mode 100644 src/test/ui/suggestions/ignore-nested-field-binding.stderr create mode 100644 src/test/ui/suggestions/issue-88730.rs create mode 100644 src/test/ui/suggestions/issue-88730.stderr create mode 100644 src/test/ui/suggestions/issue-89333.rs create mode 100644 src/test/ui/suggestions/issue-89333.stderr create mode 100644 src/test/ui/suggestions/issue-90213-expected-boxfuture-self-ice.rs create mode 100644 src/test/ui/suggestions/issue-90213-expected-boxfuture-self-ice.stderr create mode 100644 src/test/ui/suggestions/missing-type-param-used-in-param.fixed create mode 100644 src/test/ui/suggestions/missing-type-param-used-in-param.rs create mode 100644 src/test/ui/suggestions/missing-type-param-used-in-param.stderr create mode 100644 src/test/ui/suggestions/negative-literal-index.fixed create mode 100644 src/test/ui/suggestions/negative-literal-index.rs create mode 100644 src/test/ui/suggestions/negative-literal-index.stderr create mode 100644 src/test/ui/suggestions/nested-non-tuple-tuple-struct.rs create mode 100644 src/test/ui/suggestions/nested-non-tuple-tuple-struct.stderr create mode 100644 src/test/ui/suggestions/slice-issue-87994.rs create mode 100644 src/test/ui/suggestions/slice-issue-87994.stderr create mode 100644 src/test/ui/suggestions/suggest-imm-mut-trait-implementations.rs create mode 100644 src/test/ui/suggestions/suggest-imm-mut-trait-implementations.stderr create mode 100644 src/test/ui/suggestions/suggest-trait-items.rs create mode 100644 src/test/ui/suggestions/suggest-trait-items.stderr rename src/test/ui/{issues => symbol-names}/issue-53912.rs (100%) rename src/test/ui/{issues => test-attrs}/issue-36768.rs (100%) rename src/test/ui/{ => thread-local}/tls.rs (100%) create mode 100644 src/test/ui/traits/auxiliary/issue_89119_intercrate_caching.rs rename src/test/ui/{ => traits}/bug-7183-generics.rs (100%) rename src/test/ui/{issues => traits}/issue-20692.rs (100%) rename src/test/ui/{issues => traits}/issue-20692.stderr (100%) rename src/test/ui/{issues => traits}/issue-23825.rs (100%) create mode 100644 src/test/ui/traits/issue-52893.rs create mode 100644 src/test/ui/traits/issue-52893.stderr create mode 100644 src/test/ui/traits/issue-68295.rs create mode 100644 src/test/ui/traits/issue-68295.stderr create mode 100644 src/test/ui/traits/issue-89119.rs rename src/test/ui/traits/{normalize-super-trait.rs => normalize-supertrait.rs} (100%) create mode 100644 src/test/ui/traits/trait-upcasting/migrate-lint-deny.rs create mode 100644 src/test/ui/traits/trait-upcasting/migrate-lint-deny.stderr create mode 100644 src/test/ui/traits/vtable/vtable-non-object-safe.rs create mode 100644 src/test/ui/traits/vtable/vtable-non-object-safe.stderr create mode 100644 src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.rs create mode 100644 src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.stderr create mode 100644 src/test/ui/type/type-check/issue-88577-check-fn-with-more-than-65535-arguments.rs create mode 100644 src/test/ui/type/type-check/issue-88577-check-fn-with-more-than-65535-arguments.stderr create mode 100644 src/test/ui/typeck/call-block.rs create mode 100644 src/test/ui/typeck/call-block.stderr create mode 100644 src/test/ui/typeck/issue-87771-ice-assign-assign-to-bool.rs create mode 100644 src/test/ui/typeck/issue-87771-ice-assign-assign-to-bool.stderr create mode 100644 src/test/ui/typeck/issue-88609.rs create mode 100644 src/test/ui/typeck/issue-88803-call-expr-method.fixed create mode 100644 src/test/ui/typeck/issue-88803-call-expr-method.rs create mode 100644 src/test/ui/typeck/issue-88803-call-expr-method.stderr create mode 100644 src/test/ui/typeck/issue-88844.rs create mode 100644 src/test/ui/typeck/issue-88844.stderr create mode 100644 src/test/ui/typeck/issue-89044-wrapped-expr-method.fixed create mode 100644 src/test/ui/typeck/issue-89044-wrapped-expr-method.rs create mode 100644 src/test/ui/typeck/issue-89044-wrapped-expr-method.stderr create mode 100644 src/test/ui/typeck/issue-89275.rs create mode 100644 src/test/ui/typeck/issue-89275.stderr create mode 100644 src/test/ui/typeck/issue-89935.rs create mode 100644 src/test/ui/typeck/issue-90483-inaccessible-field-adjustment.rs create mode 100644 src/test/ui/typeck/issue-90483-inaccessible-field-adjustment.stderr rename src/test/ui/{issues => unsafe}/issue-45107-unnecessary-unsafe-in-closure.mir.stderr (100%) rename src/test/ui/{issues => unsafe}/issue-45107-unnecessary-unsafe-in-closure.rs (100%) rename src/test/ui/{issues => unsafe}/issue-45107-unnecessary-unsafe-in-closure.thir.stderr (100%) create mode 100644 src/test/ui/wasm/simd-to-array-80108.rs create mode 100644 src/tools/bump-stage0/Cargo.toml create mode 100644 src/tools/bump-stage0/src/main.rs delete mode 100644 src/tools/clippy/clippy_dev/src/stderr_length_check.rs create mode 100644 src/tools/clippy/clippy_lints/src/derivable_impls.rs create mode 100644 src/tools/clippy/clippy_lints/src/equatable_if_let.rs create mode 100644 src/tools/clippy/clippy_lints/src/feature_name.rs create mode 100644 src/tools/clippy/clippy_lints/src/iter_not_returning_iterator.rs create mode 100644 src/tools/clippy/clippy_lints/src/lib.deprecated.rs create mode 100644 src/tools/clippy/clippy_lints/src/lib.register_all.rs create mode 100644 src/tools/clippy/clippy_lints/src/lib.register_cargo.rs create mode 100644 src/tools/clippy/clippy_lints/src/lib.register_complexity.rs create mode 100644 src/tools/clippy/clippy_lints/src/lib.register_correctness.rs create mode 100644 src/tools/clippy/clippy_lints/src/lib.register_internal.rs create mode 100644 src/tools/clippy/clippy_lints/src/lib.register_lints.rs create mode 100644 src/tools/clippy/clippy_lints/src/lib.register_nursery.rs create mode 100644 src/tools/clippy/clippy_lints/src/lib.register_pedantic.rs create mode 100644 src/tools/clippy/clippy_lints/src/lib.register_perf.rs create mode 100644 src/tools/clippy/clippy_lints/src/lib.register_restriction.rs create mode 100644 src/tools/clippy/clippy_lints/src/lib.register_style.rs create mode 100644 src/tools/clippy/clippy_lints/src/lib.register_suspicious.rs create mode 100644 src/tools/clippy/clippy_lints/src/manual_assert.rs rename src/tools/clippy/clippy_lints/src/{if_let_some_result.rs => match_result_ok.rs} (58%) delete mode 100644 src/tools/clippy/clippy_lints/src/mem_discriminant.rs create mode 100644 src/tools/clippy/clippy_lints/src/methods/manual_split_once.rs create mode 100644 src/tools/clippy/clippy_lints/src/module_style.rs create mode 100644 src/tools/clippy/clippy_lints/src/needless_option_as_deref.rs create mode 100644 src/tools/clippy/clippy_lints/src/non_send_fields_in_send_ty.rs create mode 100644 src/tools/clippy/clippy_lints/src/same_name_method.rs create mode 100644 src/tools/clippy/clippy_lints/src/types/box_collection.rs delete mode 100644 src/tools/clippy/clippy_lints/src/types/box_vec.rs create mode 100644 src/tools/clippy/tests/ui-cargo/feature_name/fail/Cargo.toml create mode 100644 src/tools/clippy/tests/ui-cargo/feature_name/fail/src/main.rs create mode 100644 src/tools/clippy/tests/ui-cargo/feature_name/fail/src/main.stderr create mode 100644 src/tools/clippy/tests/ui-cargo/feature_name/pass/Cargo.toml create mode 100644 src/tools/clippy/tests/ui-cargo/feature_name/pass/src/main.rs create mode 100644 src/tools/clippy/tests/ui-cargo/module_style/fail_mod/Cargo.toml create mode 100644 src/tools/clippy/tests/ui-cargo/module_style/fail_mod/src/bad/inner.rs create mode 100644 src/tools/clippy/tests/ui-cargo/module_style/fail_mod/src/bad/inner/stuff.rs create mode 100644 src/tools/clippy/tests/ui-cargo/module_style/fail_mod/src/bad/inner/stuff/most.rs create mode 100644 src/tools/clippy/tests/ui-cargo/module_style/fail_mod/src/bad/mod.rs create mode 100644 src/tools/clippy/tests/ui-cargo/module_style/fail_mod/src/main.rs create mode 100644 src/tools/clippy/tests/ui-cargo/module_style/fail_mod/src/main.stderr create mode 100644 src/tools/clippy/tests/ui-cargo/module_style/fail_no_mod/Cargo.toml create mode 100644 src/tools/clippy/tests/ui-cargo/module_style/fail_no_mod/src/bad/mod.rs create mode 100644 src/tools/clippy/tests/ui-cargo/module_style/fail_no_mod/src/main.rs create mode 100644 src/tools/clippy/tests/ui-cargo/module_style/fail_no_mod/src/main.stderr create mode 100644 src/tools/clippy/tests/ui-cargo/module_style/pass_mod/Cargo.toml create mode 100644 src/tools/clippy/tests/ui-cargo/module_style/pass_mod/src/bad/mod.rs create mode 100644 src/tools/clippy/tests/ui-cargo/module_style/pass_mod/src/main.rs create mode 100644 src/tools/clippy/tests/ui-cargo/module_style/pass_mod/src/more/foo.rs create mode 100644 src/tools/clippy/tests/ui-cargo/module_style/pass_mod/src/more/inner/mod.rs create mode 100644 src/tools/clippy/tests/ui-cargo/module_style/pass_mod/src/more/mod.rs create mode 100644 src/tools/clippy/tests/ui-cargo/module_style/pass_no_mod/Cargo.toml create mode 100644 src/tools/clippy/tests/ui-cargo/module_style/pass_no_mod/src/good.rs create mode 100644 src/tools/clippy/tests/ui-cargo/module_style/pass_no_mod/src/main.rs create mode 100644 src/tools/clippy/tests/ui-toml/strict_non_send_fields_in_send_ty/clippy.toml create mode 100644 src/tools/clippy/tests/ui-toml/strict_non_send_fields_in_send_ty/test.rs create mode 100644 src/tools/clippy/tests/ui-toml/strict_non_send_fields_in_send_ty/test.stderr create mode 100644 src/tools/clippy/tests/ui/auxiliary/proc_macro_suspicious_else_formatting.rs create mode 100644 src/tools/clippy/tests/ui/box_collection.rs create mode 100644 src/tools/clippy/tests/ui/box_collection.stderr delete mode 100644 src/tools/clippy/tests/ui/box_vec.rs delete mode 100644 src/tools/clippy/tests/ui/box_vec.stderr create mode 100644 src/tools/clippy/tests/ui/derivable_impls.rs create mode 100644 src/tools/clippy/tests/ui/derivable_impls.stderr create mode 100644 src/tools/clippy/tests/ui/entry_btree.fixed create mode 100644 src/tools/clippy/tests/ui/entry_btree.rs create mode 100644 src/tools/clippy/tests/ui/entry_btree.stderr create mode 100644 src/tools/clippy/tests/ui/equatable_if_let.fixed create mode 100644 src/tools/clippy/tests/ui/equatable_if_let.rs create mode 100644 src/tools/clippy/tests/ui/equatable_if_let.stderr delete mode 100644 src/tools/clippy/tests/ui/if_let_some_result.fixed delete mode 100644 src/tools/clippy/tests/ui/if_let_some_result.rs create mode 100644 src/tools/clippy/tests/ui/iter_not_returning_iterator.rs create mode 100644 src/tools/clippy/tests/ui/iter_not_returning_iterator.stderr create mode 100644 src/tools/clippy/tests/ui/manual_assert.fixed create mode 100644 src/tools/clippy/tests/ui/manual_assert.rs create mode 100644 src/tools/clippy/tests/ui/manual_assert.stderr create mode 100644 src/tools/clippy/tests/ui/manual_map_option_2.fixed create mode 100644 src/tools/clippy/tests/ui/manual_map_option_2.rs create mode 100644 src/tools/clippy/tests/ui/manual_map_option_2.stderr create mode 100644 src/tools/clippy/tests/ui/manual_split_once.fixed create mode 100644 src/tools/clippy/tests/ui/manual_split_once.rs create mode 100644 src/tools/clippy/tests/ui/manual_split_once.stderr create mode 100644 src/tools/clippy/tests/ui/match_result_ok.fixed create mode 100644 src/tools/clippy/tests/ui/match_result_ok.rs rename src/tools/clippy/tests/ui/{if_let_some_result.stderr => match_result_ok.stderr} (56%) delete mode 100644 src/tools/clippy/tests/ui/mem_discriminant.fixed delete mode 100644 src/tools/clippy/tests/ui/mem_discriminant.rs delete mode 100644 src/tools/clippy/tests/ui/mem_discriminant.stderr delete mode 100644 src/tools/clippy/tests/ui/mem_discriminant_unfixable.rs delete mode 100644 src/tools/clippy/tests/ui/mem_discriminant_unfixable.stderr delete mode 100644 src/tools/clippy/tests/ui/missing-doc-crate.stderr delete mode 100644 src/tools/clippy/tests/ui/missing_const_for_fn/cant_be_const.stderr create mode 100644 src/tools/clippy/tests/ui/needless_option_as_deref.fixed create mode 100644 src/tools/clippy/tests/ui/needless_option_as_deref.rs create mode 100644 src/tools/clippy/tests/ui/needless_option_as_deref.stderr create mode 100644 src/tools/clippy/tests/ui/non_send_fields_in_send_ty.rs create mode 100644 src/tools/clippy/tests/ui/non_send_fields_in_send_ty.stderr delete mode 100644 src/tools/clippy/tests/ui/rc_buffer_redefined_string.stderr create mode 100644 src/tools/clippy/tests/ui/same_name_method.rs create mode 100644 src/tools/clippy/tests/ui/same_name_method.stderr create mode 100644 src/tools/compiletest/src/compute_diff.rs create mode 100644 src/tools/compiletest/src/runtest/debugger.rs create mode 100644 src/tools/tidy/src/primitive_docs.rs rename vendor/bitflags/tests/compile-fail/{derive => impls}/copy.rs (93%) rename vendor/bitflags/tests/compile-fail/{derive => impls}/copy.stderr.beta (97%) rename vendor/bitflags/tests/compile-fail/{derive => impls}/eq.rs (93%) rename vendor/bitflags/tests/compile-fail/{derive => impls}/eq.stderr.beta (97%) create mode 100644 vendor/bitflags/tests/compile-fail/non_integer_base/all_defined.stderr.beta rename vendor/bitflags/tests/compile-fail/non_integer_base/{missing_copy.rs => all_missing.rs} (94%) create mode 100644 vendor/bitflags/tests/compile-fail/non_integer_base/all_missing.stderr.beta delete mode 100644 vendor/bitflags/tests/compile-fail/non_integer_base/missing_bitops.rs create mode 100644 vendor/bitflags/tests/compile-fail/visibility/private_field.rs create mode 100644 vendor/bitflags/tests/compile-fail/visibility/private_field.stderr.beta rename vendor/bitflags/tests/compile-fail/{ => visibility}/private_flags.rs (94%) rename vendor/bitflags/tests/compile-fail/{ => visibility}/private_flags.stderr.beta (96%) create mode 100644 vendor/bitflags/tests/compile-fail/visibility/pub_const.rs create mode 100644 vendor/bitflags/tests/compile-fail/visibility/pub_const.stderr.beta create mode 100644 vendor/bitflags/tests/compile-pass/impls/convert.rs rename vendor/bitflags/tests/compile-pass/{derive => impls}/default.rs (93%) create mode 100644 vendor/bitflags/tests/compile-pass/impls/inherent_methods.rs create mode 100644 vendor/bitflags/tests/compile-pass/visibility/bits_field.rs create mode 100644 vendor/bitflags/tests/compile-pass/visibility/pub_in.rs delete mode 100644 vendor/dissimilar/.cargo-checksum.json delete mode 100644 vendor/dissimilar/README.md delete mode 100644 vendor/dissimilar/benches/bench.rs delete mode 100644 vendor/dissimilar/benches/document1.txt delete mode 100644 vendor/dissimilar/benches/document2.txt delete mode 100644 vendor/dissimilar/src/find.rs delete mode 100644 vendor/dissimilar/src/lib.rs delete mode 100644 vendor/dissimilar/src/range.rs delete mode 100644 vendor/dissimilar/src/tests.rs delete mode 100644 vendor/dissimilar/tests/test.rs create mode 100644 vendor/expect-test-1.0.1/.cargo-checksum.json rename vendor/{expect-test => expect-test-1.0.1}/Cargo.toml (94%) rename vendor/{dissimilar => expect-test-1.0.1}/LICENSE-APACHE (100%) rename vendor/{expect-test => expect-test-1.0.1}/LICENSE-MIT (100%) create mode 100644 vendor/expect-test-1.0.1/README.md rename vendor/{expect-test => expect-test-1.0.1}/src/lib.rs (92%) delete mode 100644 vendor/expect-test/.cargo-checksum.json delete mode 100644 vendor/expect-test/README.md rename vendor/flate2/tests/{corrupt-file.gz => corrupt-gz-file.bin} (100%) create mode 100644 vendor/itertools/.cargo-checksum.json create mode 100644 vendor/itertools/CHANGELOG.md create mode 100644 vendor/itertools/Cargo.lock create mode 100644 vendor/itertools/Cargo.toml rename vendor/{expect-test => itertools}/LICENSE-APACHE (100%) create mode 100644 vendor/itertools/LICENSE-MIT create mode 100644 vendor/itertools/README.rst create mode 100644 vendor/itertools/benches/bench1.rs create mode 100644 vendor/itertools/benches/combinations.rs create mode 100644 vendor/itertools/benches/combinations_with_replacement.rs create mode 100644 vendor/itertools/benches/extra/mod.rs create mode 100644 vendor/itertools/benches/extra/zipslices.rs create mode 100644 vendor/itertools/benches/fold_specialization.rs create mode 100644 vendor/itertools/benches/powerset.rs create mode 100644 vendor/itertools/benches/tree_fold1.rs create mode 100644 vendor/itertools/benches/tuple_combinations.rs create mode 100644 vendor/itertools/benches/tuples.rs create mode 100644 vendor/itertools/examples/iris.data create mode 100644 vendor/itertools/examples/iris.rs create mode 100644 vendor/itertools/src/adaptors/coalesce.rs create mode 100644 vendor/itertools/src/adaptors/map.rs create mode 100644 vendor/itertools/src/adaptors/mod.rs create mode 100644 vendor/itertools/src/adaptors/multi_product.rs create mode 100644 vendor/itertools/src/combinations.rs create mode 100644 vendor/itertools/src/combinations_with_replacement.rs create mode 100644 vendor/itertools/src/concat_impl.rs create mode 100644 vendor/itertools/src/cons_tuples_impl.rs create mode 100644 vendor/itertools/src/diff.rs create mode 100644 vendor/itertools/src/duplicates_impl.rs create mode 100644 vendor/itertools/src/either_or_both.rs create mode 100644 vendor/itertools/src/exactly_one_err.rs create mode 100644 vendor/itertools/src/flatten_ok.rs create mode 100644 vendor/itertools/src/format.rs create mode 100644 vendor/itertools/src/free.rs create mode 100644 vendor/itertools/src/group_map.rs create mode 100644 vendor/itertools/src/groupbylazy.rs create mode 100644 vendor/itertools/src/grouping_map.rs create mode 100644 vendor/itertools/src/impl_macros.rs create mode 100644 vendor/itertools/src/intersperse.rs create mode 100644 vendor/itertools/src/k_smallest.rs create mode 100644 vendor/itertools/src/kmerge_impl.rs create mode 100644 vendor/itertools/src/lazy_buffer.rs create mode 100644 vendor/itertools/src/lib.rs create mode 100644 vendor/itertools/src/merge_join.rs create mode 100644 vendor/itertools/src/minmax.rs create mode 100644 vendor/itertools/src/multipeek_impl.rs create mode 100644 vendor/itertools/src/pad_tail.rs create mode 100644 vendor/itertools/src/peek_nth.rs create mode 100644 vendor/itertools/src/peeking_take_while.rs create mode 100644 vendor/itertools/src/permutations.rs create mode 100644 vendor/itertools/src/powerset.rs create mode 100644 vendor/itertools/src/process_results_impl.rs create mode 100644 vendor/itertools/src/put_back_n_impl.rs create mode 100644 vendor/itertools/src/rciter_impl.rs create mode 100644 vendor/itertools/src/repeatn.rs create mode 100644 vendor/itertools/src/size_hint.rs create mode 100644 vendor/itertools/src/sources.rs create mode 100644 vendor/itertools/src/tee.rs create mode 100644 vendor/itertools/src/tuple_impl.rs create mode 100644 vendor/itertools/src/unique_impl.rs create mode 100644 vendor/itertools/src/with_position.rs create mode 100644 vendor/itertools/src/zip_eq_impl.rs create mode 100644 vendor/itertools/src/zip_longest.rs create mode 100644 vendor/itertools/src/ziptuple.rs create mode 100644 vendor/itertools/tests/adaptors_no_collect.rs create mode 100644 vendor/itertools/tests/flatten_ok.rs create mode 100644 vendor/itertools/tests/fold_specialization.rs create mode 100644 vendor/itertools/tests/macros_hygiene.rs create mode 100644 vendor/itertools/tests/merge_join.rs create mode 100644 vendor/itertools/tests/peeking_take_while.rs create mode 100644 vendor/itertools/tests/quick.rs create mode 100644 vendor/itertools/tests/specializations.rs create mode 100644 vendor/itertools/tests/test_core.rs create mode 100644 vendor/itertools/tests/test_std.rs create mode 100644 vendor/itertools/tests/tuples.rs create mode 100644 vendor/itertools/tests/zip.rs create mode 100644 vendor/libc/src/unix/bsd/freebsdlike/freebsd/freebsd12/x86_64.rs create mode 100644 vendor/libc/src/unix/bsd/freebsdlike/freebsd/freebsd13/x86_64.rs create mode 100644 vendor/libc/src/unix/haiku/x86_64.rs create mode 100644 vendor/libc/src/unix/solarish/x86_64.rs rename vendor/libc/src/windows/{msvc.rs => msvc/mod.rs} (57%) create mode 100644 vendor/libc/src/windows/msvc/x86_64.rs create mode 100644 vendor/odht/.cargo-checksum.json create mode 100644 vendor/odht/CODE_OF_CONDUCT.md create mode 100644 vendor/odht/Cargo.toml create mode 100644 vendor/odht/LICENSE-APACHE create mode 100644 vendor/odht/LICENSE-MIT create mode 100644 vendor/odht/README.md create mode 100644 vendor/odht/benches/bench.rs create mode 100644 vendor/odht/src/error.rs create mode 100644 vendor/odht/src/fxhash.rs create mode 100644 vendor/odht/src/lib.rs create mode 100644 vendor/odht/src/memory_layout.rs create mode 100644 vendor/odht/src/raw_table.rs create mode 100644 vendor/odht/src/swisstable_group_query/mod.rs create mode 100644 vendor/odht/src/swisstable_group_query/no_simd.rs create mode 100644 vendor/odht/src/swisstable_group_query/sse2.rs create mode 100644 vendor/odht/src/unhash.rs create mode 100644 vendor/parking_lot_core/build.rs create mode 100644 vendor/rand/src/distributions/distribution.rs create mode 100644 vendor/rand/src/distributions/slice.rs create mode 100644 vendor/rand_xoshiro/.cargo-checksum.json create mode 100644 vendor/rand_xoshiro/CHANGELOG.md create mode 100644 vendor/rand_xoshiro/COPYRIGHT rename vendor/{dissimilar => rand_xoshiro}/Cargo.toml (52%) rename vendor/{regex-1.4.6 => rand_xoshiro}/LICENSE-APACHE (100%) create mode 100644 vendor/rand_xoshiro/LICENSE-MIT create mode 100644 vendor/rand_xoshiro/README.md create mode 100644 vendor/rand_xoshiro/src/common.rs create mode 100644 vendor/rand_xoshiro/src/lib.rs create mode 100644 vendor/rand_xoshiro/src/splitmix64.rs create mode 100644 vendor/rand_xoshiro/src/xoroshiro128plus.rs create mode 100644 vendor/rand_xoshiro/src/xoroshiro128plusplus.rs create mode 100644 vendor/rand_xoshiro/src/xoroshiro128starstar.rs create mode 100644 vendor/rand_xoshiro/src/xoroshiro64star.rs create mode 100644 vendor/rand_xoshiro/src/xoroshiro64starstar.rs create mode 100644 vendor/rand_xoshiro/src/xoshiro128plus.rs create mode 100644 vendor/rand_xoshiro/src/xoshiro128plusplus.rs create mode 100644 vendor/rand_xoshiro/src/xoshiro128starstar.rs create mode 100644 vendor/rand_xoshiro/src/xoshiro256plus.rs create mode 100644 vendor/rand_xoshiro/src/xoshiro256plusplus.rs create mode 100644 vendor/rand_xoshiro/src/xoshiro256starstar.rs create mode 100644 vendor/rand_xoshiro/src/xoshiro512plus.rs create mode 100644 vendor/rand_xoshiro/src/xoshiro512plusplus.rs create mode 100644 vendor/rand_xoshiro/src/xoshiro512starstar.rs create mode 100644 vendor/rand_xoshiro/tests/serde.rs delete mode 100644 vendor/regex-1.4.6/.cargo-checksum.json delete mode 100644 vendor/regex-1.4.6/src/literal/imp.rs create mode 100644 vendor/regex/.cargo-checksum.json rename vendor/{regex-1.4.6 => regex}/CHANGELOG.md (94%) rename vendor/{regex-1.4.6 => regex}/Cargo.lock (87%) rename vendor/{regex-1.4.6 => regex}/Cargo.toml (96%) rename vendor/{regex-1.4.6 => regex}/HACKING.md (100%) create mode 100644 vendor/regex/LICENSE-APACHE rename vendor/{regex-1.4.6 => regex}/LICENSE-MIT (100%) rename vendor/{regex-1.4.6 => regex}/PERFORMANCE.md (98%) rename vendor/{regex-1.4.6 => regex}/README.md (97%) rename vendor/{regex-1.4.6 => regex}/UNICODE.md (100%) rename vendor/{regex-1.4.6 => regex}/examples/regexdna-input.txt (100%) rename vendor/{regex-1.4.6 => regex}/examples/regexdna-output.txt (100%) rename vendor/{regex-1.4.6 => regex}/examples/shootout-regex-dna-bytes.rs (99%) rename vendor/{regex-1.4.6 => regex}/examples/shootout-regex-dna-cheat.rs (99%) rename vendor/{regex-1.4.6 => regex}/examples/shootout-regex-dna-replace.rs (95%) rename vendor/{regex-1.4.6 => regex}/examples/shootout-regex-dna-single-cheat.rs (99%) rename vendor/{regex-1.4.6 => regex}/examples/shootout-regex-dna-single.rs (98%) rename vendor/{regex-1.4.6 => regex}/examples/shootout-regex-dna.rs (98%) rename vendor/{regex-1.4.6 => regex}/rustfmt.toml (100%) rename vendor/{regex-1.4.6 => regex}/src/backtrack.rs (98%) rename vendor/{regex-1.4.6 => regex}/src/compile.rs (97%) rename vendor/{regex-1.4.6 => regex}/src/dfa.rs (99%) rename vendor/{regex-1.4.6 => regex}/src/error.rs (94%) rename vendor/{regex-1.4.6 => regex}/src/exec.rs (98%) rename vendor/{regex-1.4.6 => regex}/src/expand.rs (96%) rename vendor/{regex-1.4.6 => regex}/src/find_byte.rs (100%) rename vendor/{regex-1.4.6 => regex}/src/freqs.rs (100%) rename vendor/{regex-1.4.6 => regex}/src/input.rs (96%) rename vendor/{regex-1.4.6 => regex}/src/lib.rs (95%) create mode 100644 vendor/regex/src/literal/imp.rs rename vendor/{regex-1.4.6 => regex}/src/literal/mod.rs (95%) rename vendor/{regex-1.4.6 => regex}/src/pattern.rs (96%) rename vendor/{regex-1.4.6 => regex}/src/pikevm.rs (98%) rename vendor/{regex-1.4.6 => regex}/src/pool.rs (98%) rename vendor/{regex-1.4.6 => regex}/src/prog.rs (99%) rename vendor/{regex-1.4.6 => regex}/src/re_builder.rs (98%) rename vendor/{regex-1.4.6 => regex}/src/re_bytes.rs (94%) rename vendor/{regex-1.4.6 => regex}/src/re_set.rs (98%) rename vendor/{regex-1.4.6 => regex}/src/re_trait.rs (98%) rename vendor/{regex-1.4.6 => regex}/src/re_unicode.rs (94%) rename vendor/{regex-1.4.6 => regex}/src/sparse.rs (97%) rename vendor/{regex-1.4.6 => regex}/src/testdata/LICENSE (100%) rename vendor/{regex-1.4.6 => regex}/src/testdata/README (100%) rename vendor/{regex-1.4.6 => regex}/src/testdata/basic.dat (100%) rename vendor/{regex-1.4.6 => regex}/src/testdata/nullsubexpr.dat (100%) rename vendor/{regex-1.4.6 => regex}/src/testdata/repetition.dat (100%) rename vendor/{regex-1.4.6 => regex}/src/utf8.rs (100%) rename vendor/{regex-1.4.6 => regex}/test (99%) rename vendor/{regex-1.4.6 => regex}/tests/api.rs (100%) rename vendor/{regex-1.4.6 => regex}/tests/api_str.rs (100%) rename vendor/{regex-1.4.6 => regex}/tests/bytes.rs (100%) rename vendor/{regex-1.4.6 => regex}/tests/consistent.rs (100%) rename vendor/{regex-1.4.6 => regex}/tests/crates_regex.rs (100%) rename vendor/{regex-1.4.6 => regex}/tests/crazy.rs (100%) rename vendor/{regex-1.4.6 => regex}/tests/flags.rs (100%) rename vendor/{regex-1.4.6 => regex}/tests/fowler.rs (100%) rename vendor/{regex-1.4.6 => regex}/tests/macros.rs (100%) rename vendor/{regex-1.4.6 => regex}/tests/macros_bytes.rs (100%) rename vendor/{regex-1.4.6 => regex}/tests/macros_str.rs (100%) rename vendor/{regex-1.4.6 => regex}/tests/misc.rs (100%) rename vendor/{regex-1.4.6 => regex}/tests/multiline.rs (100%) rename vendor/{regex-1.4.6 => regex}/tests/noparse.rs (100%) rename vendor/{regex-1.4.6 => regex}/tests/regression.rs (100%) rename vendor/{regex-1.4.6 => regex}/tests/regression_fuzz.rs (100%) rename vendor/{regex-1.4.6 => regex}/tests/replace.rs (98%) rename vendor/{regex-1.4.6 => regex}/tests/searcher.rs (100%) rename vendor/{regex-1.4.6 => regex}/tests/set.rs (100%) rename vendor/{regex-1.4.6 => regex}/tests/shortest_match.rs (100%) rename vendor/{regex-1.4.6 => regex}/tests/suffix_reverse.rs (100%) rename vendor/{regex-1.4.6 => regex}/tests/test_backtrack.rs (96%) rename vendor/{regex-1.4.6 => regex}/tests/test_backtrack_bytes.rs (96%) rename vendor/{regex-1.4.6 => regex}/tests/test_backtrack_utf8bytes.rs (96%) rename vendor/{regex-1.4.6 => regex}/tests/test_crates_regex.rs (96%) rename vendor/{regex-1.4.6 => regex}/tests/test_default.rs (99%) rename vendor/{regex-1.4.6 => regex}/tests/test_default_bytes.rs (97%) rename vendor/{regex-1.4.6 => regex}/tests/test_nfa.rs (96%) rename vendor/{regex-1.4.6 => regex}/tests/test_nfa_bytes.rs (96%) rename vendor/{regex-1.4.6 => regex}/tests/test_nfa_utf8bytes.rs (96%) rename vendor/{regex-1.4.6 => regex}/tests/unicode.rs (100%) rename vendor/{regex-1.4.6 => regex}/tests/word_boundary.rs (100%) rename vendor/{regex-1.4.6 => regex}/tests/word_boundary_ascii.rs (100%) rename vendor/{regex-1.4.6 => regex}/tests/word_boundary_unicode.rs (100%) create mode 100644 vendor/tracing-subscriber/src/filter/directive.rs create mode 100644 vendor/tracing-subscriber/src/filter/filter_fn.rs create mode 100644 vendor/tracing-subscriber/src/filter/layer_filters.rs create mode 100644 vendor/tracing-subscriber/src/filter/targets.rs delete mode 100644 vendor/tracing-subscriber/src/layer.rs create mode 100644 vendor/tracing-subscriber/src/layer/context.rs create mode 100644 vendor/tracing-subscriber/src/layer/layered.rs create mode 100644 vendor/tracing-subscriber/src/layer/mod.rs create mode 100644 vendor/tracing-subscriber/src/layer/tests.rs create mode 100644 vendor/tracing-subscriber/tests/cached_layer_filters_dont_break_other_layers.rs create mode 100644 vendor/tracing-subscriber/tests/hinted_layer_filters_dont_break_other_layers.rs create mode 100644 vendor/tracing-subscriber/tests/layer_filter_interests_are_cached.rs create mode 100644 vendor/tracing-subscriber/tests/layer_filters/boxed.rs create mode 100644 vendor/tracing-subscriber/tests/layer_filters/filter_scopes.rs create mode 100644 vendor/tracing-subscriber/tests/layer_filters/main.rs create mode 100644 vendor/tracing-subscriber/tests/layer_filters/targets.rs create mode 100644 vendor/tracing-subscriber/tests/layer_filters/trees.rs create mode 100644 vendor/tracing-subscriber/tests/multiple_layer_filter_interests_cached.rs create mode 100644 vendor/tracing-subscriber/tests/unhinted_layer_filters_dont_break_other_layers.rs diff --git a/Cargo.lock b/Cargo.lock index 4f1a5ca35f..dce7745076 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -26,9 +26,9 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "0.7.13" +version = "0.7.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "043164d8ba5c4c3035fec9bbee8647c0261d788f3474306f93bb65901cae0e86" +checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" dependencies = [ "memchr", ] @@ -220,6 +220,18 @@ dependencies = [ name = "build_helper" version = "0.1.0" +[[package]] +name = "bump-stage0" +version = "0.1.0" +dependencies = [ + "anyhow", + "curl", + "indexmap", + "serde", + "serde_json", + "toml", +] + [[package]] name = "byte-tools" version = "0.3.1" @@ -255,7 +267,7 @@ checksum = "81a18687293a1546b67c246452202bbbf143d239cb43494cc163da14979082da" [[package]] name = "cargo" -version = "0.57.0" +version = "0.58.0" dependencies = [ "anyhow", "atty", @@ -281,7 +293,7 @@ dependencies = [ "humantime 2.0.1", "ignore", "im-rc", - "itertools 0.10.0", + "itertools 0.10.1", "jobserver", "lazy_static", "lazycell", @@ -292,6 +304,7 @@ dependencies = [ "num_cpus", "opener", "openssl", + "os_info", "percent-encoding 2.1.0", "pretty_env_logger", "rustc-workspace-hack", @@ -348,7 +361,7 @@ version = "0.1.0" dependencies = [ "directories", "rustc-workspace-hack", - "rustc_version", + "rustc_version 0.3.3", "serde", "serde_json", "vergen", @@ -376,7 +389,7 @@ dependencies = [ "flate2", "git2", "glob", - "itertools 0.10.0", + "itertools 0.10.1", "lazy_static", "remove_dir_all", "serde_json", @@ -542,13 +555,16 @@ dependencies = [ [[package]] name = "clippy" -version = "0.1.56" +version = "0.1.57" dependencies = [ "cargo_metadata 0.12.0", "clippy_lints", + "clippy_utils", "compiletest_rs", "derive-new", "filetime", + "if_chain", + "itertools 0.10.1", "quote", "regex", "rustc-workspace-hack", @@ -566,7 +582,7 @@ version = "0.0.1" dependencies = [ "bytecount", "clap", - "itertools 0.9.0", + "itertools 0.10.1", "opener", "regex", "shell-escape", @@ -575,12 +591,12 @@ dependencies = [ [[package]] name = "clippy_lints" -version = "0.1.56" +version = "0.1.57" dependencies = [ "cargo_metadata 0.12.0", "clippy_utils", "if_chain", - "itertools 0.9.0", + "itertools 0.10.1", "pulldown-cmark 0.8.0", "quine-mc_cluskey", "regex-syntax", @@ -596,14 +612,10 @@ dependencies = [ [[package]] name = "clippy_utils" -version = "0.1.56" +version = "0.1.57" dependencies = [ "if_chain", - "itertools 0.9.0", - "regex-syntax", "rustc-semver", - "serde", - "unicode-normalization", ] [[package]] @@ -678,9 +690,9 @@ dependencies = [ [[package]] name = "compiletest_rs" -version = "0.6.0" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0086d6ad78cf409c3061618cd98e2789d5c9ce598fc9651611cf62eae0a599cb" +checksum = "64698e5e2435db061a85e6320af12c30c5fd88eb84b35d2c1e03ce4f143255ca" dependencies = [ "diff", "filetime", @@ -856,9 +868,9 @@ dependencies = [ [[package]] name = "curl" -version = "0.4.38" +version = "0.4.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "003cb79c1c6d1c93344c7e1201bb51c2148f24ec2bd9c253709d6b2efb796515" +checksum = "aaa3b8db7f3341ddef15786d250106334d4a6c4b0ae4a46cd77082777d9849b9" dependencies = [ "curl-sys", "libc", @@ -1081,19 +1093,6 @@ dependencies = [ "termcolor", ] -[[package]] -name = "env_logger" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54532e3223c5af90a6a757c90b5c5521564b07e5e7a958681bcd2afad421cdcd" -dependencies = [ - "atty", - "humantime 2.0.1", - "log", - "regex", - "termcolor", -] - [[package]] name = "env_logger" version = "0.9.0" @@ -1429,9 +1428,9 @@ dependencies = [ [[package]] name = "git2" -version = "0.13.17" +version = "0.13.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d250f5f82326884bd39c2853577e70a121775db76818ffa452ed1e80de12986" +checksum = "2a8057932925d3a9d9e4434ea016570d37420ddb1ceed45a174d577f24ed6700" dependencies = [ "bitflags", "libc", @@ -1649,7 +1648,7 @@ checksum = "3ca8957e71f04a205cb162508f9326aea04676c8dfd0711220190d6b83664f3f" dependencies = [ "bitmaps", "rand_core 0.5.1", - "rand_xoshiro", + "rand_xoshiro 0.4.0", "sized-chunks", "typenum", "version_check", @@ -1663,6 +1662,7 @@ checksum = "bc633605454125dec4b66843673f01c7df2b89479b32e0ed634e43a91cff62a5" dependencies = [ "autocfg", "hashbrown", + "serde", ] [[package]] @@ -1708,9 +1708,9 @@ dependencies = [ [[package]] name = "itertools" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37d572918e350e82412fe766d24b15e6682fb2ed2bbe018280caa810397cb319" +checksum = "69ddb889f9d0d08a67338271fa9b62996bc788c7796a5c18cf057420aaed5eaf" dependencies = [ "either", ] @@ -1880,18 +1880,18 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.99" +version = "0.2.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7f823d141fe0a24df1e23b4af4e3c7ba9e5966ec514ea068c93024aa7deb765" +checksum = "dd8f7255a17a627354f321ef0055d63b898c6fb27eff628af4d1b66b7331edf6" dependencies = [ "rustc-std-workspace-core", ] [[package]] name = "libgit2-sys" -version = "0.12.18+1.1.0" +version = "0.12.24+1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3da6a42da88fc37ee1ecda212ffa254c25713532980005d5f7c0b0fbe7e6e885" +checksum = "ddbd6021eef06fb289a8f54b3c2acfdd85ff2a585dfbb24b8576325373d2152c" dependencies = [ "cc", "libc", @@ -2242,15 +2242,15 @@ version = "0.1.0" dependencies = [ "colored", "compiletest_rs", - "env_logger 0.8.1", + "env_logger 0.9.0", "getrandom 0.2.0", "hex 0.4.2", "libc", "log", "measureme", - "rand 0.8.3", + "rand 0.8.4", "rustc-workspace-hack", - "rustc_version", + "rustc_version 0.4.0", "shell-escape", "smallvec", ] @@ -2313,6 +2313,15 @@ dependencies = [ "rustc-std-workspace-core", ] +[[package]] +name = "odht" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a518809ac14b25b569624d0268eba1e88498f71615893dca57982bed7621abb" +dependencies = [ + "cfg-if 1.0.0", +] + [[package]] name = "once_cell" version = "1.7.2" @@ -2399,6 +2408,17 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd20eec3dbe4376829cb7d80ae6ac45e0a766831dca50202ff2d40db46a8a024" +[[package]] +name = "os_info" +version = "3.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ac91020bfed8cc3f8aa450d4c3b5fa1d3373fc091c8a92009f3b27749d5a227" +dependencies = [ + "log", + "serde", + "winapi", +] + [[package]] name = "output_vt100" version = "0.1.2" @@ -2835,9 +2855,9 @@ dependencies = [ [[package]] name = "rand" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e" +checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8" dependencies = [ "libc", "rand_chacha 0.3.0", @@ -2928,6 +2948,15 @@ dependencies = [ "rand_core 0.5.1", ] +[[package]] +name = "rand_xoshiro" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f97cdb2a36ed4183de61b2f824cc45c9f1037f28afe0a322e9fff4c108b5aaa" +dependencies = [ + "rand_core 0.6.2", +] + [[package]] name = "rayon" version = "1.3.1" @@ -2974,9 +3003,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.4.6" +version = "1.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a26af418b574bd56588335b3a3659a65725d4e636eb1016c2f9e3b38c7cc759" +checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461" dependencies = [ "aho-corasick", "memchr", @@ -3589,6 +3618,33 @@ dependencies = [ "rustc_span", ] +[[package]] +name = "rustc_borrowck" +version = "0.0.0" +dependencies = [ + "either", + "itertools 0.9.0", + "polonius-engine", + "rustc_const_eval", + "rustc_data_structures", + "rustc_errors", + "rustc_graphviz", + "rustc_hir", + "rustc_index", + "rustc_infer", + "rustc_lexer", + "rustc_middle", + "rustc_mir_dataflow", + "rustc_serialize", + "rustc_session", + "rustc_span", + "rustc_target", + "rustc_trait_selection", + "rustc_traits", + "smallvec", + "tracing", +] + [[package]] name = "rustc_builtin_macros" version = "0.0.0" @@ -3619,6 +3675,7 @@ dependencies = [ "libc", "measureme", "rustc-demangle", + "rustc_arena", "rustc_ast", "rustc_attr", "rustc_codegen_ssa", @@ -3630,6 +3687,7 @@ dependencies = [ "rustc_llvm", "rustc_metadata", "rustc_middle", + "rustc_query_system", "rustc_serialize", "rustc_session", "rustc_span", @@ -3661,7 +3719,9 @@ dependencies = [ "rustc_incremental", "rustc_index", "rustc_macros", + "rustc_metadata", "rustc_middle", + "rustc_query_system", "rustc_serialize", "rustc_session", "rustc_span", @@ -3672,6 +3732,29 @@ dependencies = [ "tracing", ] +[[package]] +name = "rustc_const_eval" +version = "0.0.0" +dependencies = [ + "rustc_apfloat", + "rustc_ast", + "rustc_attr", + "rustc_data_structures", + "rustc_errors", + "rustc_hir", + "rustc_index", + "rustc_infer", + "rustc_macros", + "rustc_middle", + "rustc_mir_dataflow", + "rustc_query_system", + "rustc_session", + "rustc_span", + "rustc_target", + "rustc_trait_selection", + "tracing", +] + [[package]] name = "rustc_data_structures" version = "0.0.0" @@ -3710,6 +3793,7 @@ dependencies = [ "rustc_ast", "rustc_ast_pretty", "rustc_codegen_ssa", + "rustc_const_eval", "rustc_data_structures", "rustc_error_codes", "rustc_errors", @@ -3720,7 +3804,6 @@ dependencies = [ "rustc_lint", "rustc_metadata", "rustc_middle", - "rustc_mir", "rustc_parse", "rustc_plugin_impl", "rustc_save_analysis", @@ -3799,6 +3882,7 @@ version = "0.0.0" name = "rustc_hir" version = "0.0.0" dependencies = [ + "odht", "rustc_ast", "rustc_data_structures", "rustc_feature", @@ -3879,9 +3963,11 @@ dependencies = [ "rustc_ast_lowering", "rustc_ast_passes", "rustc_attr", + "rustc_borrowck", "rustc_builtin_macros", "rustc_codegen_llvm", "rustc_codegen_ssa", + "rustc_const_eval", "rustc_data_structures", "rustc_errors", "rustc_expand", @@ -3890,8 +3976,9 @@ dependencies = [ "rustc_lint", "rustc_metadata", "rustc_middle", - "rustc_mir", "rustc_mir_build", + "rustc_mir_transform", + "rustc_monomorphize", "rustc_parse", "rustc_passes", "rustc_plugin_impl", @@ -3982,6 +4069,7 @@ name = "rustc_metadata" version = "0.0.0" dependencies = [ "libc", + "odht", "rustc_ast", "rustc_attr", "rustc_data_structures", @@ -4009,7 +4097,11 @@ version = "0.0.0" dependencies = [ "bitflags", "chalk-ir", + "either", + "gsgdt", "polonius-engine", + "rand 0.8.4", + "rand_xoshiro 0.6.0", "rustc-rayon-core", "rustc_apfloat", "rustc_arena", @@ -4018,6 +4110,7 @@ dependencies = [ "rustc_data_structures", "rustc_errors", "rustc_feature", + "rustc_graphviz", "rustc_hir", "rustc_index", "rustc_macros", @@ -4031,38 +4124,6 @@ dependencies = [ "tracing", ] -[[package]] -name = "rustc_mir" -version = "0.0.0" -dependencies = [ - "coverage_test_macros", - "either", - "gsgdt", - "itertools 0.9.0", - "polonius-engine", - "regex", - "rustc_apfloat", - "rustc_ast", - "rustc_attr", - "rustc_data_structures", - "rustc_errors", - "rustc_graphviz", - "rustc_hir", - "rustc_index", - "rustc_infer", - "rustc_lexer", - "rustc_macros", - "rustc_middle", - "rustc_serialize", - "rustc_session", - "rustc_span", - "rustc_target", - "rustc_trait_selection", - "rustc_traits", - "smallvec", - "tracing", -] - [[package]] name = "rustc_mir_build" version = "0.0.0" @@ -4086,6 +4147,67 @@ dependencies = [ "tracing", ] +[[package]] +name = "rustc_mir_dataflow" +version = "0.0.0" +dependencies = [ + "polonius-engine", + "regex", + "rustc_ast", + "rustc_data_structures", + "rustc_graphviz", + "rustc_hir", + "rustc_index", + "rustc_middle", + "rustc_serialize", + "rustc_session", + "rustc_span", + "rustc_target", + "smallvec", + "tracing", +] + +[[package]] +name = "rustc_mir_transform" +version = "0.0.0" +dependencies = [ + "coverage_test_macros", + "itertools 0.9.0", + "rustc_ast", + "rustc_attr", + "rustc_const_eval", + "rustc_data_structures", + "rustc_errors", + "rustc_hir", + "rustc_index", + "rustc_middle", + "rustc_mir_dataflow", + "rustc_query_system", + "rustc_serialize", + "rustc_session", + "rustc_span", + "rustc_target", + "rustc_trait_selection", + "smallvec", + "tracing", +] + +[[package]] +name = "rustc_monomorphize" +version = "0.0.0" +dependencies = [ + "rustc_data_structures", + "rustc_errors", + "rustc_hir", + "rustc_index", + "rustc_middle", + "rustc_session", + "rustc_span", + "rustc_target", + "smallvec", + "tracing", +] + [[package]] name = "rustc_parse" version = "0.0.0" @@ -4101,6 +4223,7 @@ dependencies = [ "rustc_span", "tracing", "unicode-normalization", + "unicode-width", ] [[package]] @@ -4191,13 +4314,17 @@ dependencies = [ "parking_lot", "rustc-rayon-core", "rustc_arena", + "rustc_ast", "rustc_data_structures", "rustc_errors", + "rustc_feature", + "rustc_hir", "rustc_index", "rustc_macros", "rustc_serialize", "rustc_session", "rustc_span", + "rustc_target", "smallvec", "tracing", ] @@ -4265,6 +4392,7 @@ dependencies = [ "rustc_errors", "rustc_feature", "rustc_fs_util", + "rustc_hir", "rustc_lint_defs", "rustc_macros", "rustc_serialize", @@ -4300,6 +4428,7 @@ dependencies = [ "rustc_data_structures", "rustc_hir", "rustc_middle", + "rustc_query_system", "rustc_session", "rustc_span", "rustc_target", @@ -4340,9 +4469,11 @@ dependencies = [ "rustc_hir", "rustc_index", "rustc_infer", + "rustc_lint_defs", "rustc_macros", "rustc_middle", "rustc_parse_format", + "rustc_query_system", "rustc_session", "rustc_span", "rustc_target", @@ -4431,6 +4562,15 @@ dependencies = [ "semver 0.11.0", ] +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver 1.0.3", +] + [[package]] name = "rustdoc" version = "0.0.0" @@ -4791,9 +4931,9 @@ checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" [[package]] name = "smallvec" -version = "1.6.1" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e" +checksum = "1ecab6c735a6bb4139c0caafd0cc3635748bbb3acf4550e8138122099251f309" [[package]] name = "snap" @@ -4991,7 +5131,7 @@ checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22" dependencies = [ "cfg-if 1.0.0", "libc", - "rand 0.8.3", + "rand 0.8.4", "redox_syscall", "remove_dir_all", "winapi", @@ -5240,9 +5380,9 @@ checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6" [[package]] name = "tracing" -version = "0.1.25" +version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01ebdc2bb4498ab1ab5f5b73c5803825e60199229ccba0698170e3be0e7f959f" +checksum = "84f96e095c0c82419687c20ddf5cb3eadb61f4e1405923c9dc8e53a1adacbda8" dependencies = [ "cfg-if 1.0.0", "pin-project-lite", @@ -5252,9 +5392,9 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.13" +version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8a9bd1db7706f2373a190b0d067146caa39350c486f3d455b0e33b431f94c07" +checksum = "c4f915eb6abf914599c200260efced9203504c4c37380af10cdf3b7d36970650" dependencies = [ "proc-macro2", "quote", @@ -5263,9 +5403,9 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.17" +version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f50de3927f93d202783f4513cda820ab47ef17f624b03c096e86ef00c67e6b5f" +checksum = "1f4ed65637b8390770814083d20756f87bfa2c21bf2f110babdc5438351746e4" dependencies = [ "lazy_static", ] diff --git a/Cargo.toml b/Cargo.toml index 626f9ae9bd..8d6afd2b44 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -35,12 +35,14 @@ members = [ "src/tools/expand-yaml-anchors", "src/tools/jsondocck", "src/tools/html-checker", + "src/tools/bump-stage0", "src/tools/lld-wrapper", ] exclude = [ "build", "compiler/rustc_codegen_cranelift", + "compiler/rustc_codegen_gcc", "src/test/rustdoc-gui", # HACK(eddyb) This hardcodes the fact that our CI uses `/checkout/obj`. "obj", @@ -87,6 +89,15 @@ gimli.debug = 0 miniz_oxide.debug = 0 object.debug = 0 +# The only package that ever uses debug builds is bootstrap. +# We care a lot about bootstrap's compile times, so don't include debug info for +# dependencies, only bootstrap itself. +[profile.dev] +debug = 0 +[profile.dev.package] +# Only use debuginfo=1 to further reduce compile times. +bootstrap.debug = 1 + # We want the RLS to use the version of Cargo that we've got vendored in this # repository to ensure that the same exact version of Cargo is used by both the # RLS and the Cargo binary itself. The RLS depends on Cargo as a git repository diff --git a/RELEASES.md b/RELEASES.md index 52d823d8ac..4b9b20f4cb 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,3 +1,125 @@ +Version 1.57.0 (2021-12-02) +========================== + +Language +-------- + +- [Macro attributes may follow `#[derive]` and will see the original (pre-`cfg`) input.][87220] +- [Accept curly-brace macros in expressions, like `m!{ .. }.method()` and `m!{ .. }?`.][88690] +- [Allow panicking in constant evaluation.][89508] + +Compiler +-------- + +- [Create more accurate debuginfo for vtables.][89597] +- [Add `armv6k-nintendo-3ds` at Tier 3\*.][88529] +- [Add `armv7-unknown-linux-uclibceabihf` at Tier 3\*.][88952] +- [Add `m68k-unknown-linux-gnu` at Tier 3\*.][88321] +- [Add SOLID targets at Tier 3\*:][86191] `aarch64-kmc-solid_asp3`, `armv7a-kmc-solid_asp3-eabi`, `armv7a-kmc-solid_asp3-eabihf` + +\* Refer to Rust's [platform support page][platform-support-doc] for more + information on Rust's tiered platform support. + +Libraries +--------- + +- [Avoid allocations and copying in `Vec::leak`][89337] +- [Add `#[repr(i8)]` to `Ordering`][89507] +- [Optimize `File::read_to_end` and `read_to_string`][89582] +- [Update to Unicode 14.0][89614] +- [Many more functions are marked `#[must_use]`][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. + +Stabilised APIs +--------------- + +- [`[T; N]::as_mut_slice`][`array::as_mut_slice`] +- [`[T; N]::as_slice`][`array::as_slice`] +- [`collections::TryReserveError`] +- [`HashMap::try_reserve`] +- [`HashSet::try_reserve`] +- [`String::try_reserve`] +- [`String::try_reserve_exact`] +- [`Vec::try_reserve`] +- [`Vec::try_reserve_exact`] +- [`VecDeque::try_reserve`] +- [`VecDeque::try_reserve_exact`] +- [`Iterator::map_while`] +- [`iter::MapWhile`] +- [`proc_macro::is_available`] +- [`Command::get_program`] +- [`Command::get_args`] +- [`Command::get_envs`] +- [`Command::get_current_dir`] +- [`CommandArgs`] +- [`CommandEnvs`] + +These APIs are now usable in const contexts: + +- [`hint::unreachable_unchecked`] + +Cargo +----- + +- [Stabilize custom profiles][cargo/9943] + +Compatibility notes +------------------- + +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. + +- [Added an experimental backend for codegen with `libgccjit`.][87260] + +[86191]: https://github.com/rust-lang/rust/pull/86191/ +[87220]: https://github.com/rust-lang/rust/pull/87220/ +[87260]: https://github.com/rust-lang/rust/pull/87260/ +[88243]: https://github.com/rust-lang/rust/pull/88243/ +[88321]: https://github.com/rust-lang/rust/pull/88321/ +[88529]: https://github.com/rust-lang/rust/pull/88529/ +[88690]: https://github.com/rust-lang/rust/pull/88690/ +[88952]: https://github.com/rust-lang/rust/pull/88952/ +[89337]: https://github.com/rust-lang/rust/pull/89337/ +[89507]: https://github.com/rust-lang/rust/pull/89507/ +[89508]: https://github.com/rust-lang/rust/pull/89508/ +[89582]: https://github.com/rust-lang/rust/pull/89582/ +[89597]: https://github.com/rust-lang/rust/pull/89597/ +[89614]: https://github.com/rust-lang/rust/pull/89614/ +[89692]: https://github.com/rust-lang/rust/issues/89692/ +[cargo/9943]: https://github.com/rust-lang/cargo/pull/9943/ +[`array::as_mut_slice`]: https://doc.rust-lang.org/std/primitive.array.html#method.as_mut_slice +[`array::as_slice`]: https://doc.rust-lang.org/std/primitive.array.html#method.as_slice +[`collections::TryReserveError`]: https://doc.rust-lang.org/std/collections/struct.TryReserveError.html +[`HashMap::try_reserve`]: https://doc.rust-lang.org/std/collections/hash_map/struct.HashMap.html#method.try_reserve +[`HashSet::try_reserve`]: https://doc.rust-lang.org/std/collections/hash_set/struct.HashSet.html#method.try_reserve +[`String::try_reserve`]: https://doc.rust-lang.org/alloc/string/struct.String.html#method.try_reserve +[`String::try_reserve_exact`]: https://doc.rust-lang.org/alloc/string/struct.String.html#method.try_reserve_exact +[`Vec::try_reserve`]: https://doc.rust-lang.org/std/vec/struct.Vec.html#method.try_reserve +[`Vec::try_reserve_exact`]: https://doc.rust-lang.org/std/vec/struct.Vec.html#method.try_reserve_exact +[`VecDeque::try_reserve`]: https://doc.rust-lang.org/std/collections/struct.VecDeque.html#method.try_reserve +[`VecDeque::try_reserve_exact`]: https://doc.rust-lang.org/std/collections/struct.VecDeque.html#method.try_reserve_exact +[`Iterator::map_while`]: https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.map_while +[`iter::MapWhile`]: https://doc.rust-lang.org/std/iter/struct.MapWhile.html +[`proc_macro::is_available`]: https://doc.rust-lang.org/proc_macro/fn.is_available.html +[`Command::get_program`]: https://doc.rust-lang.org/std/process/struct.Command.html#method.get_program +[`Command::get_args`]: https://doc.rust-lang.org/std/process/struct.Command.html#method.get_args +[`Command::get_envs`]: https://doc.rust-lang.org/std/process/struct.Command.html#method.get_envs +[`Command::get_current_dir`]: https://doc.rust-lang.org/std/process/struct.Command.html#method.get_current_dir +[`CommandArgs`]: https://doc.rust-lang.org/std/process/struct.CommandArgs.html +[`CommandEnvs`]: https://doc.rust-lang.org/std/process/struct.CommandEnvs.html + +Version 1.56.1 (2021-11-01) +=========================== + +- New lints to detect the presence of bidirectional-override Unicode + codepoints in the compiled source code ([CVE-2021-42574]) + +[CVE-2021-42574]: https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-42574 + Version 1.56.0 (2021-10-21) ======================== @@ -77,7 +199,7 @@ Cargo - [Cargo supports specifying a minimum supported Rust version in Cargo.toml.][`rust-version`] This has no effect at present on dependency version selection. We encourage crates to specify their minimum supported Rust version, and we encourage CI systems - that support Rust code to include a crate's specified minimum version in the text matrix for that + that support Rust code to include a crate's specified minimum version in the test matrix for that crate by default. Compatibility notes diff --git a/compiler/rustc/Cargo.toml b/compiler/rustc/Cargo.toml index 37f90bf3c1..277cf0f51d 100644 --- a/compiler/rustc/Cargo.toml +++ b/compiler/rustc/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustc-main" version = "0.0.0" -edition = '2018' +edition = "2021" [dependencies] rustc_driver = { path = "../rustc_driver" } diff --git a/compiler/rustc_apfloat/Cargo.toml b/compiler/rustc_apfloat/Cargo.toml index 9f266b1fb9..bb01d4f51b 100644 --- a/compiler/rustc_apfloat/Cargo.toml +++ b/compiler/rustc_apfloat/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustc_apfloat" version = "0.0.0" -edition = "2018" +edition = "2021" [dependencies] bitflags = "1.2.1" diff --git a/compiler/rustc_apfloat/src/ieee.rs b/compiler/rustc_apfloat/src/ieee.rs index 96277950cf..739c6fd0a4 100644 --- a/compiler/rustc_apfloat/src/ieee.rs +++ b/compiler/rustc_apfloat/src/ieee.rs @@ -389,6 +389,7 @@ 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 { @@ -2526,6 +2527,7 @@ 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/Cargo.toml b/compiler/rustc_arena/Cargo.toml index eba8a2a082..33ccd04450 100644 --- a/compiler/rustc_arena/Cargo.toml +++ b/compiler/rustc_arena/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustc_arena" version = "0.0.0" -edition = "2018" +edition = "2021" [dependencies] rustc_data_structures = { path = "../rustc_data_structures" } diff --git a/compiler/rustc_ast/Cargo.toml b/compiler/rustc_ast/Cargo.toml index 67cf5d92b0..58b967a370 100644 --- a/compiler/rustc_ast/Cargo.toml +++ b/compiler/rustc_ast/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustc_ast" version = "0.0.0" -edition = "2018" +edition = "2021" [lib] doctest = false diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index c27ab810a4..e2424e7d7a 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -1211,6 +1211,8 @@ impl Expr { } } + ExprKind::Underscore => TyKind::Infer, + // This expression doesn't look like a type syntactically. _ => return None, }; diff --git a/compiler/rustc_ast/src/attr/mod.rs b/compiler/rustc_ast/src/attr/mod.rs index 81195f7fb5..5f17008bdc 100644 --- a/compiler/rustc_ast/src/attr/mod.rs +++ b/compiler/rustc_ast/src/attr/mod.rs @@ -367,7 +367,7 @@ impl MetaItem { let is_first = i == 0; if !is_first { let mod_sep_span = - Span::new(last_pos, segment.ident.span.lo(), segment.ident.span.ctxt()); + Span::new(last_pos, segment.ident.span.lo(), segment.ident.span.ctxt(), None); idents.push(TokenTree::token(token::ModSep, mod_sep_span).into()); } idents.push(TokenTree::Token(Token::from_ast_ident(segment.ident)).into()); diff --git a/compiler/rustc_ast/src/lib.rs b/compiler/rustc_ast/src/lib.rs index ef3f603508..e3c610585d 100644 --- a/compiler/rustc_ast/src/lib.rs +++ b/compiler/rustc_ast/src/lib.rs @@ -9,29 +9,17 @@ test(attr(deny(warnings))) )] #![feature(box_patterns)] -#![cfg_attr(bootstrap, feature(const_fn_transmute))] #![feature(crate_visibility_modifier)] #![feature(if_let_guard)] #![feature(iter_zip)] #![feature(label_break_value)] #![feature(nll)] #![feature(min_specialization)] -#![cfg_attr(bootstrap, allow(incomplete_features))] // if_let_guard #![recursion_limit = "256"] #[macro_use] extern crate rustc_macros; -#[macro_export] -macro_rules! unwrap_or { - ($opt:expr, $default:expr) => { - match $opt { - Some(x) => x, - None => $default, - } - }; -} - pub mod util { pub mod classify; pub mod comments; diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs index 710a592e25..db066d7c6a 100644 --- a/compiler/rustc_ast/src/token.rs +++ b/compiler/rustc_ast/src/token.rs @@ -295,6 +295,7 @@ impl TokenKind { match *self { Comma => Some(vec![Dot, Lt, Semi]), Semi => Some(vec![Colon, Comma]), + FatArrow => Some(vec![Eq, RArrow]), _ => None, } } @@ -586,6 +587,13 @@ impl Token { self.is_non_raw_ident_where(|id| id.name.is_bool_lit()) } + pub fn is_numeric_lit(&self) -> bool { + matches!( + self.kind, + Literal(Lit { kind: LitKind::Integer, .. }) | Literal(Lit { kind: LitKind::Float, .. }) + ) + } + /// Returns `true` if the token is a non-raw identifier for which `pred` holds. pub fn is_non_raw_ident_where(&self, pred: impl FnOnce(Ident) -> bool) -> bool { match self.ident() { diff --git a/compiler/rustc_ast_lowering/Cargo.toml b/compiler/rustc_ast_lowering/Cargo.toml index 4e848a6a2b..f4859ee4ae 100644 --- a/compiler/rustc_ast_lowering/Cargo.toml +++ b/compiler/rustc_ast_lowering/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustc_ast_lowering" version = "0.0.0" -edition = "2018" +edition = "2021" [lib] doctest = false diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs index 7165b3bcb9..957b14f348 100644 --- a/compiler/rustc_ast_lowering/src/asm.rs +++ b/compiler/rustc_ast_lowering/src/asm.rs @@ -202,39 +202,20 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let mut used_input_regs = FxHashMap::default(); let mut used_output_regs = FxHashMap::default(); - let mut required_features: Vec<&str> = vec![]; + for (idx, &(ref op, op_sp)) in operands.iter().enumerate() { if let Some(reg) = op.reg() { - // Make sure we don't accidentally carry features from the - // previous iteration. - required_features.clear(); - let reg_class = reg.reg_class(); if reg_class == asm::InlineAsmRegClass::Err { continue; } - // We ignore target feature requirements for clobbers: if the - // feature is disabled then the compiler doesn't care what we - // do with the registers. - // - // Note that this is only possible for explicit register - // operands, which cannot be used in the asm string. - let is_clobber = matches!( - op, - hir::InlineAsmOperand::Out { - reg: asm::InlineAsmRegOrRegClass::Reg(_), - late: _, - expr: None - } - ); - // Some register classes can only be used as clobbers. This // means that we disallow passing a value in/out of the asm and // require that the operand name an explicit register, not a // register class. if reg_class.is_clobber_only(asm_arch.unwrap()) - && !(is_clobber && matches!(reg, asm::InlineAsmRegOrRegClass::Reg(_))) + && !(op.is_clobber() && matches!(reg, asm::InlineAsmRegOrRegClass::Reg(_))) { let msg = format!( "register class `{}` can only be used as a clobber, \ @@ -245,47 +226,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { continue; } - if !is_clobber { - // Validate register classes against currently enabled target - // features. We check that at least one type is available for - // the current target. - for &(_, feature) in reg_class.supported_types(asm_arch.unwrap()) { - if let Some(feature) = feature { - if self.sess.target_features.contains(&Symbol::intern(feature)) { - required_features.clear(); - break; - } else { - required_features.push(feature); - } - } else { - required_features.clear(); - break; - } - } - // We are sorting primitive strs here and can use unstable sort here - required_features.sort_unstable(); - required_features.dedup(); - match &required_features[..] { - [] => {} - [feature] => { - let msg = format!( - "register class `{}` requires the `{}` target feature", - reg_class.name(), - feature - ); - sess.struct_span_err(op_sp, &msg).emit(); - } - features => { - let msg = format!( - "register class `{}` requires at least one target feature: {}", - reg_class.name(), - features.join(", ") - ); - sess.struct_span_err(op_sp, &msg).emit(); - } - } - } - // Check for conflicts between explicit register operands. if let asm::InlineAsmRegOrRegClass::Reg(reg) = reg { let (input, output) = match op { diff --git a/compiler/rustc_ast_lowering/src/block.rs b/compiler/rustc_ast_lowering/src/block.rs index ca804ec675..14a894d61f 100644 --- a/compiler/rustc_ast_lowering/src/block.rs +++ b/compiler/rustc_ast_lowering/src/block.rs @@ -55,7 +55,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } } StmtKind::Item(ref it) => { - stmts.extend(self.lower_item_id(it).into_iter().enumerate().map( + stmts.extend(self.lower_item_ref(it).into_iter().enumerate().map( |(i, item_id)| { let hir_id = match i { 0 => self.lower_node_id(s.id), diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 80633e141f..6027027428 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -55,7 +55,6 @@ impl<'hir> LoweringContext<'_, 'hir> { 0, ParenthesizedGenericArgs::Err, ImplTraitContext::disallowed(), - None, )); let args = self.lower_exprs(args); hir::ExprKind::MethodCall( @@ -101,10 +100,13 @@ impl<'hir> LoweringContext<'_, 'hir> { ExprKind::If(ref cond, ref then, ref else_opt) => { self.lower_expr_if(cond, then, else_opt.as_deref()) } - ExprKind::While(ref cond, ref body, opt_label) => self - .with_loop_scope(e.id, |this| { - this.lower_expr_while_in_loop_scope(e.span, cond, body, opt_label) - }), + ExprKind::While(ref cond, ref body, opt_label) => { + self.with_loop_scope(e.id, |this| { + let span = + this.mark_span_with_reason(DesugaringKind::WhileLoop, e.span, None); + this.lower_expr_while_in_loop_scope(span, cond, body, opt_label) + }) + } ExprKind::Loop(ref body, opt_label) => self.with_loop_scope(e.id, |this| { hir::ExprKind::Loop( this.lower_block(body, false), @@ -328,7 +330,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let mut generic_args = vec![]; for (idx, arg) in args.into_iter().enumerate() { if legacy_args_idx.contains(&idx) { - let parent_def_id = self.current_hir_id_owner.0; + let parent_def_id = self.current_hir_id_owner; let node_id = self.resolver.next_node_id(); // Add a definition for the in-band const def. @@ -422,7 +424,9 @@ impl<'hir> LoweringContext<'_, 'hir> { let if_kind = hir::ExprKind::If(new_cond, self.arena.alloc(then), Some(else_expr)); let if_expr = self.expr(span, if_kind, ThinVec::new()); let block = self.block_expr(self.arena.alloc(if_expr)); - hir::ExprKind::Loop(block, opt_label, hir::LoopSource::While, span.with_hi(cond.span.hi())) + let span = self.lower_span(span.with_hi(cond.span.hi())); + let opt_label = self.lower_label(opt_label); + hir::ExprKind::Loop(block, opt_label, hir::LoopSource::While, span) } /// Desugar `try { ; }` into `{ ; ::std::ops::Try::from_output() }`, @@ -1186,9 +1190,7 @@ impl<'hir> LoweringContext<'_, 'hir> { } } None => self - .loop_scopes - .last() - .cloned() + .loop_scope .map(|id| Ok(self.lower_node_id(id))) .unwrap_or(Err(hir::LoopIdError::OutsideLoopScope)), }; @@ -1208,18 +1210,9 @@ impl<'hir> LoweringContext<'_, 'hir> { } fn with_catch_scope(&mut self, catch_id: NodeId, f: impl FnOnce(&mut Self) -> T) -> T { - let len = self.catch_scopes.len(); - self.catch_scopes.push(catch_id); - + let old_scope = self.catch_scope.replace(catch_id); let result = f(self); - assert_eq!( - len + 1, - self.catch_scopes.len(), - "catch scopes should be added and removed in stack order" - ); - - self.catch_scopes.pop().unwrap(); - + self.catch_scope = old_scope; result } @@ -1228,17 +1221,9 @@ impl<'hir> LoweringContext<'_, 'hir> { let was_in_loop_condition = self.is_in_loop_condition; self.is_in_loop_condition = false; - let len = self.loop_scopes.len(); - self.loop_scopes.push(loop_id); - + let old_scope = self.loop_scope.replace(loop_id); let result = f(self); - assert_eq!( - len + 1, - self.loop_scopes.len(), - "loop scopes should be added and removed in stack order" - ); - - self.loop_scopes.pop().unwrap(); + self.loop_scope = old_scope; self.is_in_loop_condition = was_in_loop_condition; @@ -1469,8 +1454,13 @@ impl<'hir> LoweringContext<'_, 'hir> { ) }; + // #82462: to correctly diagnose borrow errors, the block that contains + // the iter expr needs to have a span that covers the loop body. + let desugared_full_span = + self.mark_span_with_reason(DesugaringKind::ForLoop(ForLoopLoc::Head), e.span, None); + let match_expr = self.arena.alloc(self.expr_match( - desugared_span, + desugared_full_span, into_iter_expr, arena_vec![self; iter_arm], hir::MatchSource::ForLoopDesugar, @@ -1484,7 +1474,7 @@ impl<'hir> LoweringContext<'_, 'hir> { // surrounding scope of the `match` since the `match` is not a terminating scope. // // Also, add the attributes to the outer returned expr node. - self.expr_drop_temps_mut(desugared_span, match_expr, attrs.into()) + self.expr_drop_temps_mut(desugared_full_span, match_expr, attrs.into()) } /// Desugar `ExprKind::Try` from: `?` into: @@ -1565,8 +1555,7 @@ impl<'hir> LoweringContext<'_, 'hir> { unstable_span, ); let thin_attrs = ThinVec::from(attrs); - let catch_scope = self.catch_scopes.last().copied(); - let ret_expr = if let Some(catch_node) = catch_scope { + let ret_expr = if let Some(catch_node) = self.catch_scope { let target_id = Ok(self.lower_node_id(catch_node)); self.arena.alloc(self.expr( try_span, diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index f8aedfd146..a5a4de81f1 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -2,7 +2,6 @@ use super::{AnonymousLifetimeMode, LoweringContext, ParamMode}; use super::{ImplTraitContext, ImplTraitPosition}; use crate::Arena; -use rustc_ast::node_id::NodeMap; use rustc_ast::ptr::P; use rustc_ast::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor}; use rustc_ast::*; @@ -42,21 +41,13 @@ impl ItemLowerer<'_, '_, '_> { impl<'a> Visitor<'a> for ItemLowerer<'a, '_, '_> { fn visit_item(&mut self, item: &'a Item) { let hir_id = self.lctx.with_hir_id_owner(item.id, |lctx| { - lctx.without_in_scope_lifetime_defs(|lctx| { - let hir_item = lctx.lower_item(item); - lctx.insert_item(hir_item) - }) + let node = lctx.without_in_scope_lifetime_defs(|lctx| lctx.lower_item(item)); + hir::OwnerNode::Item(node) }); self.lctx.with_parent_item_lifetime_defs(hir_id, |this| { let this = &mut ItemLowerer { lctx: this }; match item.kind { - ItemKind::Mod(..) => { - let def_id = this.lctx.lower_node_id(item.id).expect_owner(); - let old_current_module = mem::replace(&mut this.lctx.current_module, def_id); - visit::walk_item(this, item); - this.lctx.current_module = old_current_module; - } ItemKind::Impl(box ImplKind { ref of_trait, .. }) => { this.with_trait_impl_ref(of_trait, |this| visit::walk_item(this, item)); } @@ -79,24 +70,16 @@ impl<'a> Visitor<'a> for ItemLowerer<'a, '_, '_> { fn visit_assoc_item(&mut self, item: &'a AssocItem, ctxt: AssocCtxt) { self.lctx.with_hir_id_owner(item.id, |lctx| match ctxt { - AssocCtxt::Trait => { - let hir_item = lctx.lower_trait_item(item); - lctx.insert_trait_item(hir_item); - } - AssocCtxt::Impl => { - let hir_item = lctx.lower_impl_item(item); - lctx.insert_impl_item(hir_item); - } + AssocCtxt::Trait => hir::OwnerNode::TraitItem(lctx.lower_trait_item(item)), + AssocCtxt::Impl => hir::OwnerNode::ImplItem(lctx.lower_impl_item(item)), }); visit::walk_assoc_item(self, item, ctxt); } fn visit_foreign_item(&mut self, item: &'a ForeignItem) { - self.lctx.allocate_hir_id_counter(item.id); self.lctx.with_hir_id_owner(item.id, |lctx| { - let hir_item = lctx.lower_foreign_item(item); - lctx.insert_foreign_item(hir_item); + hir::OwnerNode::ForeignItem(lctx.lower_foreign_item(item)) }); visit::walk_foreign_item(self, item); @@ -111,12 +94,12 @@ impl<'hir> LoweringContext<'_, 'hir> { // only used when lowering a child item of a trait or impl. fn with_parent_item_lifetime_defs( &mut self, - parent_hir_id: hir::ItemId, + parent_hir_id: LocalDefId, f: impl FnOnce(&mut Self) -> T, ) -> T { let old_len = self.in_scope_lifetimes.len(); - let parent_generics = match self.owners[parent_hir_id.def_id].unwrap().expect_item().kind { + let parent_generics = match self.owners[parent_hir_id].unwrap().expect_item().kind { hir::ItemKind::Impl(hir::Impl { ref generics, .. }) | hir::ItemKind::Trait(_, _, ref generics, ..) => generics.params, _ => &[], @@ -155,41 +138,28 @@ impl<'hir> LoweringContext<'_, 'hir> { pub(super) fn lower_mod(&mut self, items: &[P], inner: Span) -> hir::Mod<'hir> { hir::Mod { inner: self.lower_span(inner), - item_ids: self.arena.alloc_from_iter(items.iter().flat_map(|x| self.lower_item_id(x))), + item_ids: self.arena.alloc_from_iter(items.iter().flat_map(|x| self.lower_item_ref(x))), } } - pub(super) fn lower_item_id(&mut self, i: &Item) -> SmallVec<[hir::ItemId; 1]> { - let node_ids = match i.kind { - ItemKind::Use(ref use_tree) => { - let mut vec = smallvec![i.id]; - self.lower_item_id_use_tree(use_tree, i.id, &mut vec); - vec - } - ItemKind::Fn(..) | ItemKind::Impl(box ImplKind { of_trait: None, .. }) => { - smallvec![i.id] - } - _ => smallvec![i.id], - }; - + pub(super) fn lower_item_ref(&mut self, i: &Item) -> SmallVec<[hir::ItemId; 1]> { + let mut node_ids = smallvec![hir::ItemId { def_id: self.resolver.local_def_id(i.id) }]; + if let ItemKind::Use(ref use_tree) = &i.kind { + self.lower_item_id_use_tree(use_tree, i.id, &mut node_ids); + } node_ids - .into_iter() - .map(|node_id| hir::ItemId { - def_id: self.allocate_hir_id_counter(node_id).expect_owner(), - }) - .collect() } fn lower_item_id_use_tree( &mut self, tree: &UseTree, base_id: NodeId, - vec: &mut SmallVec<[NodeId; 1]>, + vec: &mut SmallVec<[hir::ItemId; 1]>, ) { match tree.kind { UseTreeKind::Nested(ref nested_vec) => { for &(ref nested, id) in nested_vec { - vec.push(id); + vec.push(hir::ItemId { def_id: self.resolver.local_def_id(id) }); self.lower_item_id_use_tree(nested, id, vec); } } @@ -198,25 +168,26 @@ impl<'hir> LoweringContext<'_, 'hir> { for (_, &id) in iter::zip(self.expect_full_res_from_use(base_id).skip(1), &[id1, id2]) { - vec.push(id); + vec.push(hir::ItemId { def_id: self.resolver.local_def_id(id) }); } } } } - pub fn lower_item(&mut self, i: &Item) -> hir::Item<'hir> { + fn lower_item(&mut self, i: &Item) -> &'hir hir::Item<'hir> { let mut ident = i.ident; - let mut vis = self.lower_visibility(&i.vis, None); + let mut vis = self.lower_visibility(&i.vis); let hir_id = self.lower_node_id(i.id); let attrs = self.lower_attrs(hir_id, &i.attrs); let kind = self.lower_item_kind(i.span, i.id, hir_id, &mut ident, attrs, &mut vis, &i.kind); - hir::Item { + let item = hir::Item { def_id: hir_id.expect_owner(), ident: self.lower_ident(ident), kind, vis, span: self.lower_span(i.span), - } + }; + self.arena.alloc(item) } fn lower_item_kind( @@ -487,7 +458,7 @@ impl<'hir> LoweringContext<'_, 'hir> { } } - let mut resolutions = self.expect_full_res_from_use(id); + let mut resolutions = self.expect_full_res_from_use(id).fuse(); // We want to return *something* from this function, so hold onto the first item // for later. let ret_res = self.lower_res(resolutions.next().unwrap_or(Res::Err)); @@ -497,7 +468,18 @@ impl<'hir> LoweringContext<'_, 'hir> { // won't be dealing with macros in the rest of the compiler. // Essentially a single `use` which imports two names is desugared into // two imports. - for (res, &new_node_id) in iter::zip(resolutions, &[id1, id2]) { + for new_node_id in [id1, id2] { + let new_id = self.resolver.local_def_id(new_node_id); + let res = if let Some(res) = resolutions.next() { + res + } else { + // Associate an HirId to both ids even if there is no resolution. + let _old = self + .node_id_to_hir_id + .insert(new_node_id, hir::HirId::make_owner(new_id)); + debug_assert!(_old.is_none()); + continue; + }; let ident = *ident; let mut path = path.clone(); for seg in &mut path.segments { @@ -506,26 +488,26 @@ impl<'hir> LoweringContext<'_, 'hir> { let span = path.span; self.with_hir_id_owner(new_node_id, |this| { - let new_id = this.lower_node_id(new_node_id); let res = this.lower_res(res); - let path = this.lower_path_extra(res, &path, ParamMode::Explicit, None); + let path = this.lower_path_extra(res, &path, ParamMode::Explicit); let kind = hir::ItemKind::Use(path, hir::UseKind::Single); let vis = this.rebuild_vis(&vis); if let Some(attrs) = attrs { - this.attrs.insert(new_id, attrs); + this.attrs.insert(hir::HirId::make_owner(new_id), attrs); } - this.insert_item(hir::Item { - def_id: new_id.expect_owner(), + let item = hir::Item { + def_id: new_id, ident: this.lower_ident(ident), kind, vis, span: this.lower_span(span), - }); + }; + hir::OwnerNode::Item(this.arena.alloc(item)) }); } - let path = self.lower_path_extra(ret_res, &path, ParamMode::Explicit, None); + let path = self.lower_path_extra(ret_res, &path, ParamMode::Explicit); hir::ItemKind::Use(path, hir::UseKind::Single) } UseTreeKind::Glob => { @@ -565,7 +547,7 @@ impl<'hir> LoweringContext<'_, 'hir> { // Add all the nested `PathListItem`s to the HIR. for &(ref use_tree, id) in trees { - let new_hir_id = self.lower_node_id(id); + let new_hir_id = self.resolver.local_def_id(id); let mut prefix = prefix.clone(); @@ -586,16 +568,17 @@ impl<'hir> LoweringContext<'_, 'hir> { let kind = this.lower_use_tree(use_tree, &prefix, id, &mut vis, &mut ident, attrs); if let Some(attrs) = attrs { - this.attrs.insert(new_hir_id, attrs); + this.attrs.insert(hir::HirId::make_owner(new_hir_id), attrs); } - this.insert_item(hir::Item { - def_id: new_hir_id.expect_owner(), + let item = hir::Item { + def_id: new_hir_id, ident: this.lower_ident(ident), kind, vis, span: this.lower_span(use_tree.span), - }); + }; + hir::OwnerNode::Item(this.arena.alloc(item)) }); } @@ -625,7 +608,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let res = self.expect_full_res_from_use(id).next().unwrap_or(Res::Err); let res = self.lower_res(res); - let path = self.lower_path_extra(res, &prefix, ParamMode::Explicit, None); + let path = self.lower_path_extra(res, &prefix, ParamMode::Explicit); hir::ItemKind::Use(path, hir::UseKind::ListStem) } } @@ -662,11 +645,11 @@ impl<'hir> LoweringContext<'_, 'hir> { respan(self.lower_span(vis.span), vis_kind) } - fn lower_foreign_item(&mut self, i: &ForeignItem) -> hir::ForeignItem<'hir> { + fn lower_foreign_item(&mut self, i: &ForeignItem) -> &'hir hir::ForeignItem<'hir> { let hir_id = self.lower_node_id(i.id); let def_id = hir_id.expect_owner(); self.lower_attrs(hir_id, &i.attrs); - hir::ForeignItem { + let item = hir::ForeignItem { def_id, ident: self.lower_ident(i.ident), kind: match i.kind { @@ -694,17 +677,17 @@ impl<'hir> LoweringContext<'_, 'hir> { ForeignItemKind::TyAlias(..) => hir::ForeignItemKind::Type, ForeignItemKind::MacCall(_) => panic!("macro shouldn't exist here"), }, - vis: self.lower_visibility(&i.vis, None), + vis: self.lower_visibility(&i.vis), span: self.lower_span(i.span), - } + }; + self.arena.alloc(item) } - fn lower_foreign_item_ref(&mut self, i: &ForeignItem) -> hir::ForeignItemRef<'hir> { + fn lower_foreign_item_ref(&mut self, i: &ForeignItem) -> hir::ForeignItemRef { hir::ForeignItemRef { - id: hir::ForeignItemId { def_id: self.lower_node_id(i.id).expect_owner() }, + id: hir::ForeignItemId { def_id: self.resolver.local_def_id(i.id) }, ident: self.lower_ident(i.ident), span: self.lower_span(i.span), - vis: self.lower_visibility(&i.vis, Some(i.id)), } } @@ -772,12 +755,12 @@ impl<'hir> LoweringContext<'_, 'hir> { // FIXME(jseyfried): positional field hygiene. None => Ident::new(sym::integer(index), self.lower_span(f.span)), }, - vis: self.lower_visibility(&f.vis, None), + vis: self.lower_visibility(&f.vis), ty, } } - fn lower_trait_item(&mut self, i: &AssocItem) -> hir::TraitItem<'hir> { + fn lower_trait_item(&mut self, i: &AssocItem) -> &'hir hir::TraitItem<'hir> { let hir_id = self.lower_node_id(i.id); let trait_item_def_id = hir_id.expect_owner(); @@ -820,13 +803,14 @@ impl<'hir> LoweringContext<'_, 'hir> { }; self.lower_attrs(hir_id, &i.attrs); - hir::TraitItem { + let item = hir::TraitItem { def_id: trait_item_def_id, ident: self.lower_ident(i.ident), generics, kind, span: self.lower_span(i.span), - } + }; + self.arena.alloc(item) } fn lower_trait_item_ref(&mut self, i: &AssocItem) -> hir::TraitItemRef { @@ -840,7 +824,7 @@ impl<'hir> LoweringContext<'_, 'hir> { } AssocItemKind::MacCall(..) => unimplemented!(), }; - let id = hir::TraitItemId { def_id: self.lower_node_id(i.id).expect_owner() }; + let id = hir::TraitItemId { def_id: self.resolver.local_def_id(i.id) }; let defaultness = hir::Defaultness::Default { has_value: has_default }; hir::TraitItemRef { id, @@ -856,7 +840,7 @@ impl<'hir> LoweringContext<'_, 'hir> { self.expr(span, hir::ExprKind::Err, AttrVec::new()) } - fn lower_impl_item(&mut self, i: &AssocItem) -> hir::ImplItem<'hir> { + fn lower_impl_item(&mut self, i: &AssocItem) -> &'hir hir::ImplItem<'hir> { let impl_item_def_id = self.resolver.local_def_id(i.id); let (generics, kind) = match &i.kind { @@ -910,26 +894,26 @@ impl<'hir> LoweringContext<'_, 'hir> { let (defaultness, _) = self.lower_defaultness(i.kind.defaultness(), has_value); let hir_id = self.lower_node_id(i.id); self.lower_attrs(hir_id, &i.attrs); - hir::ImplItem { + let item = hir::ImplItem { def_id: hir_id.expect_owner(), ident: self.lower_ident(i.ident), generics, - vis: self.lower_visibility(&i.vis, None), + vis: self.lower_visibility(&i.vis), defaultness, kind, span: self.lower_span(i.span), - } + }; + self.arena.alloc(item) } - fn lower_impl_item_ref(&mut self, i: &AssocItem) -> hir::ImplItemRef<'hir> { + fn lower_impl_item_ref(&mut self, i: &AssocItem) -> hir::ImplItemRef { // Since `default impl` is not yet implemented, this is always true in impls. let has_value = true; let (defaultness, _) = self.lower_defaultness(i.kind.defaultness(), has_value); hir::ImplItemRef { - id: hir::ImplItemId { def_id: self.lower_node_id(i.id).expect_owner() }, + id: hir::ImplItemId { def_id: self.resolver.local_def_id(i.id) }, ident: self.lower_ident(i.ident), span: self.lower_span(i.span), - vis: self.lower_visibility(&i.vis, Some(i.id)), defaultness, kind: match &i.kind { AssocItemKind::Const(..) => hir::AssocItemKind::Const, @@ -947,25 +931,15 @@ impl<'hir> LoweringContext<'_, 'hir> { /// lowered. This can happen during `lower_impl_item_ref()` where we need to /// lower a `Visibility` value although we haven't lowered the owning /// `ImplItem` in question yet. - fn lower_visibility( - &mut self, - v: &Visibility, - explicit_owner: Option, - ) -> hir::Visibility<'hir> { + fn lower_visibility(&mut self, v: &Visibility) -> hir::Visibility<'hir> { let node = match v.kind { VisibilityKind::Public => hir::VisibilityKind::Public, VisibilityKind::Crate(sugar) => hir::VisibilityKind::Crate(sugar), VisibilityKind::Restricted { ref path, id } => { debug!("lower_visibility: restricted path id = {:?}", id); - let lowered_id = if let Some(owner) = explicit_owner { - self.lower_node_id_with_owner(id, owner) - } else { - self.lower_node_id(id) - }; - let res = self.expect_full_res(id); - let res = self.lower_res(res); + let lowered_id = self.lower_node_id(id); hir::VisibilityKind::Restricted { - path: self.lower_path_extra(res, path, ParamMode::Explicit, explicit_owner), + path: self.lower_path(id, path, ParamMode::Explicit), hir_id: lowered_id, } } @@ -1348,42 +1322,56 @@ impl<'hir> LoweringContext<'_, 'hir> { generics: &Generics, itctx: ImplTraitContext<'_, 'hir>, ) -> GenericsCtor<'hir> { - // Collect `?Trait` bounds in where clause and move them to parameter definitions. - let mut add_bounds: NodeMap> = Default::default(); + // Error if `?Trait` bounds in where clauses don't refer directly to type paramters. + // Note: we used to clone these bounds directly onto the type parameter (and avoid lowering + // these into hir when we lower thee where clauses), but this makes it quite difficult to + // keep track of the Span info. Now, `add_implicitly_sized` in `AstConv` checks both param bounds and + // where clauses for `?Sized`. for pred in &generics.where_clause.predicates { - if let WherePredicate::BoundPredicate(ref bound_pred) = *pred { - 'next_bound: for bound in &bound_pred.bounds { - if let GenericBound::Trait(_, TraitBoundModifier::Maybe) = *bound { - // Check if the where clause type is a plain type parameter. - match self - .resolver - .get_partial_res(bound_pred.bounded_ty.id) - .map(|d| (d.base_res(), d.unresolved_segments())) - { - Some((Res::Def(DefKind::TyParam, def_id), 0)) - if bound_pred.bound_generic_params.is_empty() => - { - for param in &generics.params { - if def_id == self.resolver.local_def_id(param.id).to_def_id() { - add_bounds.entry(param.id).or_default().push(bound.clone()); - continue 'next_bound; - } - } - } - _ => {} - } - self.diagnostic().span_err( - bound_pred.bounded_ty.span, - "`?Trait` bounds are only permitted at the \ - point where a type parameter is declared", - ); + let bound_pred = match *pred { + WherePredicate::BoundPredicate(ref bound_pred) => bound_pred, + _ => continue, + }; + let compute_is_param = || { + // Check if the where clause type is a plain type parameter. + match self + .resolver + .get_partial_res(bound_pred.bounded_ty.id) + .map(|d| (d.base_res(), d.unresolved_segments())) + { + Some((Res::Def(DefKind::TyParam, def_id), 0)) + if bound_pred.bound_generic_params.is_empty() => + { + generics + .params + .iter() + .any(|p| def_id == self.resolver.local_def_id(p.id).to_def_id()) } + // Either the `bounded_ty` is not a plain type parameter, or + // it's not found in the generic type parameters list. + _ => false, + } + }; + // We only need to compute this once per `WherePredicate`, but don't + // need to compute this at all unless there is a Maybe bound. + let mut is_param: Option = None; + for bound in &bound_pred.bounds { + if !matches!(*bound, GenericBound::Trait(_, TraitBoundModifier::Maybe)) { + continue; + } + let is_param = *is_param.get_or_insert_with(compute_is_param); + if !is_param { + self.diagnostic().span_err( + bound.span(), + "`?Trait` bounds are only permitted at the \ + point where a type parameter is declared", + ); } } } GenericsCtor { - params: self.lower_generic_params_mut(&generics.params, &add_bounds, itctx).collect(), + params: self.lower_generic_params_mut(&generics.params, itctx).collect(), where_clause: self.lower_where_clause(&generics.where_clause), span: self.lower_span(generics.span), } @@ -1416,32 +1404,17 @@ impl<'hir> LoweringContext<'_, 'hir> { ref bounded_ty, ref bounds, span, - }) => { - self.with_in_scope_lifetime_defs(&bound_generic_params, |this| { - hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate { - bound_generic_params: this.lower_generic_params( - bound_generic_params, - &NodeMap::default(), - ImplTraitContext::disallowed(), - ), - bounded_ty: this.lower_ty(bounded_ty, ImplTraitContext::disallowed()), - bounds: this.arena.alloc_from_iter(bounds.iter().map( - |bound| match bound { - // We used to ignore `?Trait` bounds, as they were copied into type - // parameters already, but we need to keep them around only for - // diagnostics when we suggest removal of `?Sized` bounds. See - // `suggest_constraining_type_param`. This will need to change if - // we ever allow something *other* than `?Sized`. - GenericBound::Trait(p, TraitBoundModifier::Maybe) => { - hir::GenericBound::Unsized(this.lower_span(p.span)) - } - _ => this.lower_param_bound(bound, ImplTraitContext::disallowed()), - }, - )), - span: this.lower_span(span), - }) + }) => self.with_in_scope_lifetime_defs(&bound_generic_params, |this| { + hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate { + bound_generic_params: this + .lower_generic_params(bound_generic_params, ImplTraitContext::disallowed()), + bounded_ty: this.lower_ty(bounded_ty, ImplTraitContext::disallowed()), + bounds: this.arena.alloc_from_iter(bounds.iter().map(|bound| { + this.lower_param_bound(bound, ImplTraitContext::disallowed()) + })), + span: this.lower_span(span), }) - } + }), WherePredicate::RegionPredicate(WhereRegionPredicate { ref lifetime, ref bounds, diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 41ae115a4d..245199e375 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -38,7 +38,7 @@ use rustc_ast::node_id::NodeMap; use rustc_ast::token::{self, Token}; use rustc_ast::tokenstream::{CanSynthesizeMissingTokens, TokenStream, TokenTree}; -use rustc_ast::visit::{self, AssocCtxt, Visitor}; +use rustc_ast::visit; use rustc_ast::{self as ast, *}; use rustc_ast_pretty::pprust; use rustc_data_structures::captures::Captures; @@ -64,7 +64,6 @@ use rustc_span::{Span, DUMMY_SP}; use smallvec::SmallVec; use std::collections::BTreeMap; -use std::mem; use tracing::{debug, trace}; macro_rules! arena_vec { @@ -81,8 +80,6 @@ mod item; mod pat; mod path; -const HIR_ID_COUNTER_LOCKED: u32 = 0xFFFFFFFF; - rustc_hir::arena_types!(rustc_arena::declare_arena, 'tcx); struct LoweringContext<'a, 'hir: 'a> { @@ -103,8 +100,6 @@ struct LoweringContext<'a, 'hir: 'a> { owners: IndexVec>>, bodies: BTreeMap>, - modules: BTreeMap, - generator_kind: Option, attrs: BTreeMap, @@ -117,8 +112,8 @@ struct LoweringContext<'a, 'hir: 'a> { /// outside of an `async fn`. current_item: Option, - catch_scopes: Vec, - loop_scopes: Vec, + catch_scope: Option, + loop_scope: Option, is_in_loop_condition: bool, is_in_trait_impl: bool, is_in_dyn_type: bool, @@ -153,10 +148,8 @@ struct LoweringContext<'a, 'hir: 'a> { /// vector. in_scope_lifetimes: Vec, - current_module: LocalDefId, - - current_hir_id_owner: (LocalDefId, u32), - item_local_id_counters: NodeMap, + current_hir_id_owner: LocalDefId, + item_local_id_counter: hir::ItemLocalId, node_id_to_hir_id: IndexVec>, allow_try_trait: Option>, @@ -166,12 +159,14 @@ struct LoweringContext<'a, 'hir: 'a> { pub trait ResolverAstLowering { fn def_key(&mut self, id: DefId) -> DefKey; + fn def_span(&self, id: LocalDefId) -> Span; + fn item_generics_num_lifetimes(&self, def: DefId) -> usize; fn legacy_const_generic_args(&mut self, expr: &Expr) -> Option>; /// Obtains resolution for a `NodeId` with a single resolution. - fn get_partial_res(&mut self, id: NodeId) -> Option; + fn get_partial_res(&self, id: NodeId) -> Option; /// Obtains per-namespace resolutions for `use` statement with the given `NodeId`. fn get_import_res(&mut self, id: NodeId) -> PerNS>>; @@ -216,6 +211,11 @@ impl<'a> rustc_span::HashStableContext for LoweringHasher<'a> { 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) @@ -321,17 +321,15 @@ pub fn lower_crate<'a, 'hir>( arena, owners: IndexVec::default(), bodies: BTreeMap::new(), - modules: BTreeMap::new(), attrs: BTreeMap::default(), - catch_scopes: Vec::new(), - loop_scopes: Vec::new(), + catch_scope: None, + loop_scope: None, is_in_loop_condition: false, is_in_trait_impl: false, is_in_dyn_type: false, anonymous_lifetime_mode: AnonymousLifetimeMode::PassThrough, - current_module: CRATE_DEF_ID, - current_hir_id_owner: (CRATE_DEF_ID, 0), - item_local_id_counters: Default::default(), + current_hir_id_owner: CRATE_DEF_ID, + item_local_id_counter: hir::ItemLocalId::new(0), node_id_to_hir_id: IndexVec::new(), generator_kind: None, task_context: None, @@ -412,66 +410,15 @@ enum AnonymousLifetimeMode { impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_crate(mut self, c: &Crate) -> &'hir hir::Crate<'hir> { - /// Full-crate AST visitor that inserts into a fresh - /// `LoweringContext` any information that may be - /// needed from arbitrary locations in the crate, - /// e.g., the number of lifetime generic parameters - /// declared for every type and trait definition. - struct MiscCollector<'tcx, 'lowering, 'hir> { - lctx: &'tcx mut LoweringContext<'lowering, 'hir>, - } + debug_assert_eq!(self.resolver.local_def_id(CRATE_NODE_ID), CRATE_DEF_ID); - impl MiscCollector<'_, '_, '_> { - fn allocate_use_tree_hir_id_counters(&mut self, tree: &UseTree) { - match tree.kind { - UseTreeKind::Simple(_, id1, id2) => { - for id in [id1, id2] { - self.lctx.allocate_hir_id_counter(id); - } - } - UseTreeKind::Glob => (), - UseTreeKind::Nested(ref trees) => { - for &(ref use_tree, id) in trees { - self.lctx.allocate_hir_id_counter(id); - self.allocate_use_tree_hir_id_counters(use_tree); - } - } - } - } - } - - impl<'tcx> Visitor<'tcx> for MiscCollector<'tcx, '_, '_> { - fn visit_item(&mut self, item: &'tcx Item) { - self.lctx.allocate_hir_id_counter(item.id); - - if let ItemKind::Use(ref use_tree) = item.kind { - self.allocate_use_tree_hir_id_counters(use_tree); - } - - visit::walk_item(self, item); - } - - fn visit_assoc_item(&mut self, item: &'tcx AssocItem, ctxt: AssocCtxt) { - self.lctx.allocate_hir_id_counter(item.id); - visit::walk_assoc_item(self, item, ctxt); - } - - fn visit_foreign_item(&mut self, item: &'tcx ForeignItem) { - self.lctx.allocate_hir_id_counter(item.id); - visit::walk_foreign_item(self, item); - } - } - - self.lower_node_id(CRATE_NODE_ID); - debug_assert!(self.node_id_to_hir_id[CRATE_NODE_ID] == Some(hir::CRATE_HIR_ID)); - - visit::walk_crate(&mut MiscCollector { lctx: &mut self }, c); visit::walk_crate(&mut item::ItemLowerer { lctx: &mut self }, c); - let module = self.arena.alloc(self.lower_mod(&c.items, c.span)); - self.lower_attrs(hir::CRATE_HIR_ID, &c.attrs); - self.owners.ensure_contains_elem(CRATE_DEF_ID, || None); - self.owners[CRATE_DEF_ID] = Some(hir::OwnerNode::Crate(module)); + self.with_hir_id_owner(CRATE_NODE_ID, |lctx| { + let module = lctx.lower_mod(&c.items, c.span); + lctx.lower_attrs(hir::CRATE_HIR_ID, &c.attrs); + hir::OwnerNode::Crate(lctx.arena.alloc(module)) + }); let mut trait_map: FxHashMap<_, FxHashMap<_, _>> = FxHashMap::default(); for (k, v) in self.resolver.take_trait_map().into_iter() { @@ -502,61 +449,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } } - let krate = hir::Crate { - owners: self.owners, - bodies: self.bodies, - modules: self.modules, - trait_map, - attrs: self.attrs, - }; + let krate = + hir::Crate { owners: self.owners, bodies: self.bodies, trait_map, attrs: self.attrs }; self.arena.alloc(krate) } - fn insert_item(&mut self, item: hir::Item<'hir>) -> hir::ItemId { - let id = item.item_id(); - let item = self.arena.alloc(item); - self.owners.ensure_contains_elem(id.def_id, || None); - self.owners[id.def_id] = Some(hir::OwnerNode::Item(item)); - self.modules.entry(self.current_module).or_default().items.insert(id); - id - } - - fn insert_foreign_item(&mut self, item: hir::ForeignItem<'hir>) -> hir::ForeignItemId { - let id = item.foreign_item_id(); - let item = self.arena.alloc(item); - self.owners.ensure_contains_elem(id.def_id, || None); - self.owners[id.def_id] = Some(hir::OwnerNode::ForeignItem(item)); - self.modules.entry(self.current_module).or_default().foreign_items.insert(id); - id - } - - fn insert_impl_item(&mut self, item: hir::ImplItem<'hir>) -> hir::ImplItemId { - let id = item.impl_item_id(); - let item = self.arena.alloc(item); - self.owners.ensure_contains_elem(id.def_id, || None); - self.owners[id.def_id] = Some(hir::OwnerNode::ImplItem(item)); - self.modules.entry(self.current_module).or_default().impl_items.insert(id); - id - } - - fn insert_trait_item(&mut self, item: hir::TraitItem<'hir>) -> hir::TraitItemId { - let id = item.trait_item_id(); - let item = self.arena.alloc(item); - self.owners.ensure_contains_elem(id.def_id, || None); - self.owners[id.def_id] = Some(hir::OwnerNode::TraitItem(item)); - self.modules.entry(self.current_module).or_default().trait_items.insert(id); - id - } - - fn allocate_hir_id_counter(&mut self, owner: NodeId) -> hir::HirId { - // Set up the counter if needed. - self.item_local_id_counters.entry(owner).or_insert(0); - // Always allocate the first `HirId` for the owner itself. - let lowered = self.lower_node_id_with_owner(owner, owner); - debug_assert_eq!(lowered.local_id.as_u32(), 0); - lowered - } - fn create_stable_hashing_context(&self) -> LoweringHasher<'_> { LoweringHasher { source_map: CachingSourceMapView::new(self.sess.source_map()), @@ -564,47 +461,30 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } } - fn lower_node_id_generic( + fn with_hir_id_owner( &mut self, - ast_node_id: NodeId, - alloc_hir_id: impl FnOnce(&mut Self) -> hir::HirId, - ) -> hir::HirId { - assert_ne!(ast_node_id, DUMMY_NODE_ID); - - let min_size = ast_node_id.as_usize() + 1; - - if min_size > self.node_id_to_hir_id.len() { - self.node_id_to_hir_id.resize(min_size, None); - } - - if let Some(existing_hir_id) = self.node_id_to_hir_id[ast_node_id] { - existing_hir_id - } else { - // Generate a new `HirId`. - let hir_id = alloc_hir_id(self); - self.node_id_to_hir_id[ast_node_id] = Some(hir_id); - - hir_id - } - } - - fn with_hir_id_owner(&mut self, owner: NodeId, f: impl FnOnce(&mut Self) -> T) -> T { - let counter = self - .item_local_id_counters - .insert(owner, HIR_ID_COUNTER_LOCKED) - .unwrap_or_else(|| panic!("no `item_local_id_counters` entry for {:?}", owner)); + owner: NodeId, + f: impl FnOnce(&mut Self) -> hir::OwnerNode<'hir>, + ) -> LocalDefId { let def_id = self.resolver.local_def_id(owner); - let old_owner = std::mem::replace(&mut self.current_hir_id_owner, (def_id, counter)); - let ret = f(self); - let (new_def_id, new_counter) = - std::mem::replace(&mut self.current_hir_id_owner, old_owner); - debug_assert!(def_id == new_def_id); - debug_assert!(new_counter >= counter); + // Always allocate the first `HirId` for the owner itself. + let _old = self.node_id_to_hir_id.insert(owner, hir::HirId::make_owner(def_id)); + debug_assert_eq!(_old, None); - let prev = self.item_local_id_counters.insert(owner, new_counter).unwrap(); - debug_assert!(prev == HIR_ID_COUNTER_LOCKED); - ret + let current_owner = std::mem::replace(&mut self.current_hir_id_owner, def_id); + let current_local_counter = + std::mem::replace(&mut self.item_local_id_counter, hir::ItemLocalId::new(1)); + + let item = f(self); + + self.current_hir_id_owner = current_owner; + self.item_local_id_counter = current_local_counter; + + let _old = self.owners.insert(def_id, item); + debug_assert!(_old.is_none()); + + def_id } /// This method allocates a new `HirId` for the given `NodeId` and stores it in @@ -614,34 +494,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { /// `HirIdValidator` later on, which makes sure that all `NodeId`s got mapped /// properly. Calling the method twice with the same `NodeId` is fine though. fn lower_node_id(&mut self, ast_node_id: NodeId) -> hir::HirId { - self.lower_node_id_generic(ast_node_id, |this| { - let &mut (owner, ref mut local_id_counter) = &mut this.current_hir_id_owner; - let local_id = *local_id_counter; - *local_id_counter += 1; - hir::HirId { owner, local_id: hir::ItemLocalId::from_u32(local_id) } - }) - } + assert_ne!(ast_node_id, DUMMY_NODE_ID); - fn lower_node_id_with_owner(&mut self, ast_node_id: NodeId, owner: NodeId) -> hir::HirId { - self.lower_node_id_generic(ast_node_id, |this| { - let local_id_counter = this - .item_local_id_counters - .get_mut(&owner) - .expect("called `lower_node_id_with_owner` before `allocate_hir_id_counter`"); - let local_id = *local_id_counter; - - // We want to be sure not to modify the counter in the map while it - // is also on the stack. Otherwise we'll get lost updates when writing - // back from the stack to the map. - debug_assert!(local_id != HIR_ID_COUNTER_LOCKED); - - *local_id_counter += 1; - let owner = this.resolver.opt_local_def_id(owner).expect( - "you forgot to call `create_def` or are lowering node-IDs \ - that do not belong to the current owner", - ); - - hir::HirId { owner, local_id: hir::ItemLocalId::from_u32(local_id) } + *self.node_id_to_hir_id.get_or_insert_with(ast_node_id, || { + // Generate a new `HirId`. + let owner = self.current_hir_id_owner; + let local_id = self.item_local_id_counter; + self.item_local_id_counter.increment_by(1); + hir::HirId { owner, local_id } }) } @@ -652,7 +512,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_res(&mut self, res: Res) -> Res { res.map_id(|id| { - self.lower_node_id_generic(id, |_| { + self.node_id_to_hir_id.get(id).copied().flatten().unwrap_or_else(|| { panic!("expected `NodeId` to be lowered already for res {:#?}", res); }) }) @@ -712,9 +572,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } /// Intercept all spans entering HIR. - /// For now we are not doing anything with the intercepted spans. + /// Mark a span as relative to the current owning item. fn lower_span(&self, span: Span) -> Span { - span + if self.sess.opts.debugging_opts.incremental_relative_spans { + span.with_parent(Some(self.current_hir_id_owner)) + } else { + // Do not make spans relative when not using incremental compilation. + span + } } fn lower_ident(&self, ident: Ident) -> Ident { @@ -782,7 +647,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { node_id, DefPathData::LifetimeNs(str_name), ExpnId::root(), - span, + span.with_parent(None), ); hir::GenericParam { @@ -883,7 +748,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // wouldn't have been added yet. let generics = this.lower_generics_mut( generics, - ImplTraitContext::Universal(&mut params, this.current_hir_id_owner.0), + ImplTraitContext::Universal(&mut params, this.current_hir_id_owner), ); let res = f(this, &mut params); (params, (generics, res)) @@ -911,11 +776,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let was_in_loop_condition = self.is_in_loop_condition; self.is_in_loop_condition = false; - let catch_scopes = mem::take(&mut self.catch_scopes); - let loop_scopes = mem::take(&mut self.loop_scopes); + let catch_scope = self.catch_scope.take(); + let loop_scope = self.loop_scope.take(); let ret = f(self); - self.catch_scopes = catch_scopes; - self.loop_scopes = loop_scopes; + self.catch_scope = catch_scope; + self.loop_scope = loop_scope; self.is_in_loop_condition = was_in_loop_condition; @@ -1089,7 +954,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } AssocTyConstraintKind::Bound { ref bounds } => { let mut capturable_lifetimes; - let mut parent_def_id = self.current_hir_id_owner.0; + let mut parent_def_id = self.current_hir_id_owner; // Piggy-back on the `impl Trait` context to figure out the correct behavior. let (desugar_to_impl_trait, itctx) = match itctx { // We are in the return position: @@ -1217,7 +1082,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // Construct an AnonConst where the expr is the "ty"'s path. - let parent_def_id = self.current_hir_id_owner.0; + let parent_def_id = self.current_hir_id_owner; let node_id = self.resolver.next_node_id(); // Add a definition for the in-band const def. @@ -1305,7 +1170,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { hir::TyKind::BareFn(this.arena.alloc(hir::BareFnTy { generic_params: this.lower_generic_params( &f.generic_params, - &NodeMap::default(), ImplTraitContext::disallowed(), ), unsafety: this.lower_unsafety(f.unsafety), @@ -1486,198 +1350,26 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let opaque_ty_def_id = self.resolver.local_def_id(opaque_ty_node_id); - self.allocate_hir_id_counter(opaque_ty_node_id); + let mut collected_lifetimes = Vec::new(); + self.with_hir_id_owner(opaque_ty_node_id, |lctx| { + let hir_bounds = lower_bounds(lctx); - let hir_bounds = self.with_hir_id_owner(opaque_ty_node_id, lower_bounds); + collected_lifetimes = lifetimes_from_impl_trait_bounds( + opaque_ty_node_id, + &hir_bounds, + capturable_lifetimes, + ); - let (lifetimes, lifetime_defs) = self.lifetimes_from_impl_trait_bounds( - opaque_ty_node_id, - opaque_ty_def_id, - &hir_bounds, - capturable_lifetimes, - ); - - debug!("lower_opaque_impl_trait: lifetimes={:#?}", lifetimes); - - debug!("lower_opaque_impl_trait: lifetime_defs={:#?}", lifetime_defs); - - self.with_hir_id_owner(opaque_ty_node_id, move |lctx| { - let opaque_ty_item = hir::OpaqueTy { - generics: hir::Generics { - params: lifetime_defs, - where_clause: hir::WhereClause { predicates: &[], span: lctx.lower_span(span) }, - span: lctx.lower_span(span), - }, - bounds: hir_bounds, - impl_trait_fn: fn_def_id, - origin, - }; - - trace!("lower_opaque_impl_trait: {:#?}", opaque_ty_def_id); - lctx.generate_opaque_type(opaque_ty_def_id, opaque_ty_item, span, opaque_ty_span); - - // `impl Trait` now just becomes `Foo<'a, 'b, ..>`. - hir::TyKind::OpaqueDef(hir::ItemId { def_id: opaque_ty_def_id }, lifetimes) - }) - } - - /// Registers a new opaque type with the proper `NodeId`s and - /// returns the lowered node-ID for the opaque type. - fn generate_opaque_type( - &mut self, - opaque_ty_id: LocalDefId, - opaque_ty_item: hir::OpaqueTy<'hir>, - span: Span, - opaque_ty_span: Span, - ) { - let opaque_ty_item_kind = hir::ItemKind::OpaqueTy(opaque_ty_item); - // Generate an `type Foo = impl Trait;` declaration. - trace!("registering opaque type with id {:#?}", opaque_ty_id); - let opaque_ty_item = hir::Item { - def_id: opaque_ty_id, - ident: Ident::invalid(), - kind: opaque_ty_item_kind, - vis: respan(self.lower_span(span.shrink_to_lo()), hir::VisibilityKind::Inherited), - span: self.lower_span(opaque_ty_span), - }; - - // Insert the item into the global item list. This usually happens - // automatically for all AST items. But this opaque type item - // does not actually exist in the AST. - self.insert_item(opaque_ty_item); - } - - fn lifetimes_from_impl_trait_bounds( - &mut self, - opaque_ty_id: NodeId, - parent_def_id: LocalDefId, - bounds: hir::GenericBounds<'hir>, - lifetimes_to_include: Option<&FxHashSet>, - ) -> (&'hir [hir::GenericArg<'hir>], &'hir [hir::GenericParam<'hir>]) { - debug!( - "lifetimes_from_impl_trait_bounds(opaque_ty_id={:?}, \ - parent_def_id={:?}, \ - bounds={:#?})", - opaque_ty_id, parent_def_id, bounds, - ); - - // This visitor walks over `impl Trait` bounds and creates defs for all lifetimes that - // appear in the bounds, excluding lifetimes that are created within the bounds. - // E.g., `'a`, `'b`, but not `'c` in `impl for<'c> SomeTrait<'a, 'b, 'c>`. - struct ImplTraitLifetimeCollector<'r, 'a, 'hir> { - context: &'r mut LoweringContext<'a, 'hir>, - parent: LocalDefId, - opaque_ty_id: NodeId, - collect_elided_lifetimes: bool, - currently_bound_lifetimes: Vec, - already_defined_lifetimes: FxHashSet, - output_lifetimes: Vec>, - output_lifetime_params: Vec>, - lifetimes_to_include: Option<&'r FxHashSet>, - } - - impl<'r, 'a, 'v, 'hir> intravisit::Visitor<'v> for ImplTraitLifetimeCollector<'r, 'a, 'hir> { - type Map = intravisit::ErasedMap<'v>; - - fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap { - intravisit::NestedVisitorMap::None - } - - fn visit_generic_args(&mut self, span: Span, parameters: &'v hir::GenericArgs<'v>) { - // Don't collect elided lifetimes used inside of `Fn()` syntax. - if parameters.parenthesized { - let old_collect_elided_lifetimes = self.collect_elided_lifetimes; - self.collect_elided_lifetimes = false; - intravisit::walk_generic_args(self, span, parameters); - self.collect_elided_lifetimes = old_collect_elided_lifetimes; - } else { - intravisit::walk_generic_args(self, span, parameters); - } - } - - fn visit_ty(&mut self, t: &'v hir::Ty<'v>) { - // Don't collect elided lifetimes used inside of `fn()` syntax. - if let hir::TyKind::BareFn(_) = t.kind { - let old_collect_elided_lifetimes = self.collect_elided_lifetimes; - self.collect_elided_lifetimes = false; - - // Record the "stack height" of `for<'a>` lifetime bindings - // to be able to later fully undo their introduction. - let old_len = self.currently_bound_lifetimes.len(); - intravisit::walk_ty(self, t); - self.currently_bound_lifetimes.truncate(old_len); - - self.collect_elided_lifetimes = old_collect_elided_lifetimes; - } else { - intravisit::walk_ty(self, t) - } - } - - fn visit_poly_trait_ref( - &mut self, - trait_ref: &'v hir::PolyTraitRef<'v>, - modifier: hir::TraitBoundModifier, - ) { - // Record the "stack height" of `for<'a>` lifetime bindings - // to be able to later fully undo their introduction. - let old_len = self.currently_bound_lifetimes.len(); - intravisit::walk_poly_trait_ref(self, trait_ref, modifier); - self.currently_bound_lifetimes.truncate(old_len); - } - - fn visit_generic_param(&mut self, param: &'v hir::GenericParam<'v>) { - // Record the introduction of 'a in `for<'a> ...`. - if let hir::GenericParamKind::Lifetime { .. } = param.kind { - // Introduce lifetimes one at a time so that we can handle - // cases like `fn foo<'d>() -> impl for<'a, 'b: 'a, 'c: 'b + 'd>`. - let lt_name = hir::LifetimeName::Param(param.name); - self.currently_bound_lifetimes.push(lt_name); - } - - intravisit::walk_generic_param(self, param); - } - - fn visit_lifetime(&mut self, lifetime: &'v hir::Lifetime) { - let name = match lifetime.name { - hir::LifetimeName::Implicit | hir::LifetimeName::Underscore => { - if self.collect_elided_lifetimes { - // Use `'_` for both implicit and underscore lifetimes in - // `type Foo<'_> = impl SomeTrait<'_>;`. - hir::LifetimeName::Underscore - } else { - return; - } - } - hir::LifetimeName::Param(_) => lifetime.name, - - // Refers to some other lifetime that is "in - // scope" within the type. - hir::LifetimeName::ImplicitObjectLifetimeDefault => return, - - hir::LifetimeName::Error | hir::LifetimeName::Static => return, - }; - - if !self.currently_bound_lifetimes.contains(&name) - && !self.already_defined_lifetimes.contains(&name) - && self.lifetimes_to_include.map_or(true, |lifetimes| lifetimes.contains(&name)) - { - self.already_defined_lifetimes.insert(name); - - self.output_lifetimes.push(hir::GenericArg::Lifetime(hir::Lifetime { - hir_id: self.context.next_id(), - span: self.context.lower_span(lifetime.span), - name, - })); - - let def_node_id = self.context.resolver.next_node_id(); - let hir_id = - self.context.lower_node_id_with_owner(def_node_id, self.opaque_ty_id); - self.context.resolver.create_def( - self.parent, + let lifetime_defs = + lctx.arena.alloc_from_iter(collected_lifetimes.iter().map(|&(name, span)| { + let def_node_id = lctx.resolver.next_node_id(); + let hir_id = lctx.lower_node_id(def_node_id); + lctx.resolver.create_def( + opaque_ty_def_id, def_node_id, DefPathData::LifetimeNs(name.ident().name), ExpnId::root(), - lifetime.span, + span.with_parent(None), ); let (name, kind) = match name { @@ -1690,48 +1382,65 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } _ => panic!("expected `LifetimeName::Param` or `ParamName::Plain`"), }; - let name = match name { - hir::ParamName::Plain(ident) => { - hir::ParamName::Plain(self.context.lower_ident(ident)) - } - name => name, - }; - self.output_lifetime_params.push(hir::GenericParam { + hir::GenericParam { hir_id, name, - span: self.context.lower_span(lifetime.span), + span, pure_wrt_drop: false, bounds: &[], kind: hir::GenericParamKind::Lifetime { kind }, - }); - } - } - } + } + })); - let mut lifetime_collector = ImplTraitLifetimeCollector { - context: self, - parent: parent_def_id, - opaque_ty_id, - collect_elided_lifetimes: true, - currently_bound_lifetimes: Vec::new(), - already_defined_lifetimes: FxHashSet::default(), - output_lifetimes: Vec::new(), - output_lifetime_params: Vec::new(), - lifetimes_to_include, + debug!("lower_opaque_impl_trait: lifetime_defs={:#?}", lifetime_defs); + + let opaque_ty_item = hir::OpaqueTy { + generics: hir::Generics { + params: lifetime_defs, + where_clause: hir::WhereClause { predicates: &[], span: lctx.lower_span(span) }, + span: lctx.lower_span(span), + }, + bounds: hir_bounds, + impl_trait_fn: fn_def_id, + origin, + }; + + trace!("lower_opaque_impl_trait: {:#?}", opaque_ty_def_id); + lctx.generate_opaque_type(opaque_ty_def_id, opaque_ty_item, span, opaque_ty_span) + }); + + let lifetimes = + self.arena.alloc_from_iter(collected_lifetimes.into_iter().map(|(name, span)| { + hir::GenericArg::Lifetime(hir::Lifetime { hir_id: self.next_id(), span, name }) + })); + + debug!("lower_opaque_impl_trait: lifetimes={:#?}", lifetimes); + + // `impl Trait` now just becomes `Foo<'a, 'b, ..>`. + hir::TyKind::OpaqueDef(hir::ItemId { def_id: opaque_ty_def_id }, lifetimes) + } + + /// Registers a new opaque type with the proper `NodeId`s and + /// returns the lowered node-ID for the opaque type. + fn generate_opaque_type( + &mut self, + opaque_ty_id: LocalDefId, + opaque_ty_item: hir::OpaqueTy<'hir>, + span: Span, + opaque_ty_span: Span, + ) -> hir::OwnerNode<'hir> { + let opaque_ty_item_kind = hir::ItemKind::OpaqueTy(opaque_ty_item); + // Generate an `type Foo = impl Trait;` declaration. + trace!("registering opaque type with id {:#?}", opaque_ty_id); + let opaque_ty_item = hir::Item { + def_id: opaque_ty_id, + ident: Ident::invalid(), + kind: opaque_ty_item_kind, + vis: respan(self.lower_span(span.shrink_to_lo()), hir::VisibilityKind::Inherited), + span: self.lower_span(opaque_ty_span), }; - - for bound in bounds { - intravisit::walk_param_bound(&mut lifetime_collector, &bound); - } - - let ImplTraitLifetimeCollector { output_lifetimes, output_lifetime_params, .. } = - lifetime_collector; - - ( - self.arena.alloc_from_iter(output_lifetimes), - self.arena.alloc_from_iter(output_lifetime_params), - ) + hir::OwnerNode::Item(self.arena.alloc(opaque_ty_item)) } fn lower_fn_params_to_names(&mut self, decl: &FnDecl) -> &'hir [Ident] { @@ -1800,7 +1509,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { if let Some((_, ibty)) = &mut in_band_ty_params { this.lower_ty_direct( ¶m.ty, - ImplTraitContext::Universal(ibty, this.current_hir_id_owner.0), + ImplTraitContext::Universal(ibty, this.current_hir_id_owner), ) } else { this.lower_ty_direct(¶m.ty, ImplTraitContext::disallowed()) @@ -1893,8 +1602,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let opaque_ty_def_id = self.resolver.local_def_id(opaque_ty_node_id); - self.allocate_hir_id_counter(opaque_ty_node_id); - // When we create the opaque type for this async fn, it is going to have // to capture all the lifetimes involved in the signature (including in the // return type). This is done by introducing lifetime parameters for: @@ -1943,7 +1650,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // grow. let input_lifetimes_count = self.in_scope_lifetimes.len() + self.lifetimes_to_define.len(); - let lifetime_params = self.with_hir_id_owner(opaque_ty_node_id, |this| { + let mut lifetime_params = Vec::new(); + self.with_hir_id_owner(opaque_ty_node_id, |this| { // We have to be careful to get elision right here. The // idea is that we create a lifetime parameter for each // lifetime in the return type. So, given a return type @@ -1965,7 +1673,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // // Note: this must be done after lowering the output type, // as the output type may introduce new in-band lifetimes. - let lifetime_params: Vec<(Span, ParamName)> = this + lifetime_params = this .in_scope_lifetimes .iter() .cloned() @@ -1994,9 +1702,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { }; trace!("exist ty from async fn def id: {:#?}", opaque_ty_def_id); - this.generate_opaque_type(opaque_ty_def_id, opaque_ty_item, span, opaque_ty_span); - - lifetime_params + this.generate_opaque_type(opaque_ty_def_id, opaque_ty_item, span, opaque_ty_span) }); // As documented above on the variable @@ -2138,30 +1844,25 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_generic_params_mut<'s>( &'s mut self, params: &'s [GenericParam], - add_bounds: &'s NodeMap>, mut itctx: ImplTraitContext<'s, 'hir>, ) -> impl Iterator> + Captures<'a> + Captures<'s> { - params - .iter() - .map(move |param| self.lower_generic_param(param, add_bounds, itctx.reborrow())) + params.iter().map(move |param| self.lower_generic_param(param, itctx.reborrow())) } fn lower_generic_params( &mut self, params: &[GenericParam], - add_bounds: &NodeMap>, itctx: ImplTraitContext<'_, 'hir>, ) -> &'hir [hir::GenericParam<'hir>] { - self.arena.alloc_from_iter(self.lower_generic_params_mut(params, add_bounds, itctx)) + self.arena.alloc_from_iter(self.lower_generic_params_mut(params, itctx)) } fn lower_generic_param( &mut self, param: &GenericParam, - add_bounds: &NodeMap>, mut itctx: ImplTraitContext<'_, 'hir>, ) -> hir::GenericParam<'hir> { - let mut bounds: Vec<_> = self + let bounds: Vec<_> = self .with_anonymous_lifetime_mode(AnonymousLifetimeMode::ReportError, |this| { this.lower_param_bounds_mut(¶m.bounds, itctx.reborrow()).collect() }); @@ -2197,12 +1898,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { (param_name, kind) } GenericParamKind::Type { ref default, .. } => { - let add_bounds = add_bounds.get(¶m.id).map_or(&[][..], |x| &x); - if !add_bounds.is_empty() { - let params = self.lower_param_bounds_mut(add_bounds, itctx.reborrow()); - bounds.extend(params); - } - let kind = hir::GenericParamKind::Type { default: default.as_ref().map(|x| { self.lower_ty(x, ImplTraitContext::Disallowed(ImplTraitPosition::Other)) @@ -2263,11 +1958,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { p: &PolyTraitRef, mut itctx: ImplTraitContext<'_, 'hir>, ) -> hir::PolyTraitRef<'hir> { - let bound_generic_params = self.lower_generic_params( - &p.bound_generic_params, - &NodeMap::default(), - itctx.reborrow(), - ); + let bound_generic_params = + self.lower_generic_params(&p.bound_generic_params, itctx.reborrow()); let trait_ref = self.with_in_scope_lifetime_defs(&p.bound_generic_params, |this| { // Any impl Trait types defined within this scope can capture @@ -2714,3 +2406,132 @@ impl<'hir> GenericArgsCtor<'hir> { this.arena.alloc(ga) } } + +fn lifetimes_from_impl_trait_bounds( + opaque_ty_id: NodeId, + bounds: hir::GenericBounds<'_>, + lifetimes_to_include: Option<&FxHashSet>, +) -> Vec<(hir::LifetimeName, Span)> { + debug!( + "lifetimes_from_impl_trait_bounds(opaque_ty_id={:?}, \ + bounds={:#?})", + opaque_ty_id, bounds, + ); + + // This visitor walks over `impl Trait` bounds and creates defs for all lifetimes that + // appear in the bounds, excluding lifetimes that are created within the bounds. + // E.g., `'a`, `'b`, but not `'c` in `impl for<'c> SomeTrait<'a, 'b, 'c>`. + struct ImplTraitLifetimeCollector<'r> { + collect_elided_lifetimes: bool, + currently_bound_lifetimes: Vec, + already_defined_lifetimes: FxHashSet, + lifetimes: Vec<(hir::LifetimeName, Span)>, + lifetimes_to_include: Option<&'r FxHashSet>, + } + + impl<'r, 'v> intravisit::Visitor<'v> for ImplTraitLifetimeCollector<'r> { + type Map = intravisit::ErasedMap<'v>; + + fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap { + intravisit::NestedVisitorMap::None + } + + fn visit_generic_args(&mut self, span: Span, parameters: &'v hir::GenericArgs<'v>) { + // Don't collect elided lifetimes used inside of `Fn()` syntax. + if parameters.parenthesized { + let old_collect_elided_lifetimes = self.collect_elided_lifetimes; + self.collect_elided_lifetimes = false; + intravisit::walk_generic_args(self, span, parameters); + self.collect_elided_lifetimes = old_collect_elided_lifetimes; + } else { + intravisit::walk_generic_args(self, span, parameters); + } + } + + fn visit_ty(&mut self, t: &'v hir::Ty<'v>) { + // Don't collect elided lifetimes used inside of `fn()` syntax. + if let hir::TyKind::BareFn(_) = t.kind { + let old_collect_elided_lifetimes = self.collect_elided_lifetimes; + self.collect_elided_lifetimes = false; + + // Record the "stack height" of `for<'a>` lifetime bindings + // to be able to later fully undo their introduction. + let old_len = self.currently_bound_lifetimes.len(); + intravisit::walk_ty(self, t); + self.currently_bound_lifetimes.truncate(old_len); + + self.collect_elided_lifetimes = old_collect_elided_lifetimes; + } else { + intravisit::walk_ty(self, t) + } + } + + fn visit_poly_trait_ref( + &mut self, + trait_ref: &'v hir::PolyTraitRef<'v>, + modifier: hir::TraitBoundModifier, + ) { + // Record the "stack height" of `for<'a>` lifetime bindings + // to be able to later fully undo their introduction. + let old_len = self.currently_bound_lifetimes.len(); + intravisit::walk_poly_trait_ref(self, trait_ref, modifier); + self.currently_bound_lifetimes.truncate(old_len); + } + + fn visit_generic_param(&mut self, param: &'v hir::GenericParam<'v>) { + // Record the introduction of 'a in `for<'a> ...`. + if let hir::GenericParamKind::Lifetime { .. } = param.kind { + // Introduce lifetimes one at a time so that we can handle + // cases like `fn foo<'d>() -> impl for<'a, 'b: 'a, 'c: 'b + 'd>`. + let lt_name = hir::LifetimeName::Param(param.name); + self.currently_bound_lifetimes.push(lt_name); + } + + intravisit::walk_generic_param(self, param); + } + + fn visit_lifetime(&mut self, lifetime: &'v hir::Lifetime) { + let name = match lifetime.name { + hir::LifetimeName::Implicit | hir::LifetimeName::Underscore => { + if self.collect_elided_lifetimes { + // Use `'_` for both implicit and underscore lifetimes in + // `type Foo<'_> = impl SomeTrait<'_>;`. + hir::LifetimeName::Underscore + } else { + return; + } + } + hir::LifetimeName::Param(_) => lifetime.name, + + // Refers to some other lifetime that is "in + // scope" within the type. + hir::LifetimeName::ImplicitObjectLifetimeDefault => return, + + hir::LifetimeName::Error | hir::LifetimeName::Static => return, + }; + + if !self.currently_bound_lifetimes.contains(&name) + && !self.already_defined_lifetimes.contains(&name) + && self.lifetimes_to_include.map_or(true, |lifetimes| lifetimes.contains(&name)) + { + self.already_defined_lifetimes.insert(name); + + self.lifetimes.push((name, lifetime.span)); + } + } + } + + let mut lifetime_collector = ImplTraitLifetimeCollector { + collect_elided_lifetimes: true, + currently_bound_lifetimes: Vec::new(), + already_defined_lifetimes: FxHashSet::default(), + lifetimes: Vec::new(), + lifetimes_to_include, + }; + + for bound in bounds { + intravisit::walk_param_bound(&mut lifetime_collector, &bound); + } + + lifetime_collector.lifetimes +} diff --git a/compiler/rustc_ast_lowering/src/path.rs b/compiler/rustc_ast_lowering/src/path.rs index 90a22b5c20..929f427484 100644 --- a/compiler/rustc_ast_lowering/src/path.rs +++ b/compiler/rustc_ast_lowering/src/path.rs @@ -99,7 +99,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { num_lifetimes, parenthesized_generic_args, itctx.reborrow(), - None, ) }, )), @@ -147,7 +146,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { 0, ParenthesizedGenericArgs::Err, itctx.reborrow(), - None, )); let qpath = hir::QPath::TypeRelative(ty, hir_segment); @@ -178,7 +176,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { res: Res, p: &Path, param_mode: ParamMode, - explicit_owner: Option, ) -> &'hir hir::Path<'hir> { self.arena.alloc(hir::Path { res, @@ -190,7 +187,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { 0, ParenthesizedGenericArgs::Err, ImplTraitContext::disallowed(), - explicit_owner, ) })), span: self.lower_span(p.span), @@ -205,7 +201,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ) -> &'hir hir::Path<'hir> { let res = self.expect_full_res(id); let res = self.lower_res(res); - self.lower_path_extra(res, p, param_mode, None) + self.lower_path_extra(res, p, param_mode) } crate fn lower_path_segment( @@ -216,7 +212,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { expected_lifetimes: usize, parenthesized_generic_args: ParenthesizedGenericArgs, itctx: ImplTraitContext<'_, 'hir>, - explicit_owner: Option, ) -> hir::PathSegment<'hir> { debug!( "path_span: {:?}, lower_path_segment(segment: {:?}, expected_lifetimes: {:?})", @@ -354,11 +349,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } let res = self.expect_full_res(segment.id); - let id = if let Some(owner) = explicit_owner { - self.lower_node_id_with_owner(segment.id, owner) - } else { - self.lower_node_id(segment.id) - }; + let id = self.lower_node_id(segment.id); debug!( "lower_path_segment: ident={:?} original-id={:?} new-id={:?}", segment.ident, segment.id, id, diff --git a/compiler/rustc_ast_passes/Cargo.toml b/compiler/rustc_ast_passes/Cargo.toml index 4a6eb80fb3..9312a68bc6 100644 --- a/compiler/rustc_ast_passes/Cargo.toml +++ b/compiler/rustc_ast_passes/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustc_ast_passes" version = "0.0.0" -edition = "2018" +edition = "2021" [dependencies] itertools = "0.9" diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 07f721d2d8..968e9fa3e2 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -356,11 +356,25 @@ impl<'a> AstValidator<'a> { } fn check_fn_decl(&self, fn_decl: &FnDecl, self_semantic: SelfSemantic) { + self.check_decl_num_args(fn_decl); self.check_decl_cvaradic_pos(fn_decl); self.check_decl_attrs(fn_decl); self.check_decl_self_param(fn_decl, self_semantic); } + /// Emits fatal error if function declaration has more than `u16::MAX` arguments + /// Error is fatal to prevent errors during typechecking + fn check_decl_num_args(&self, fn_decl: &FnDecl) { + let max_num_args: usize = u16::MAX.into(); + if fn_decl.inputs.len() > max_num_args { + let Param { span, .. } = fn_decl.inputs[0]; + self.err_handler().span_fatal( + span, + &format!("function can not have more than {} arguments", max_num_args), + ); + } + } + fn check_decl_cvaradic_pos(&self, fn_decl: &FnDecl) { match &*fn_decl.inputs { [Param { ty, span, .. }] => { @@ -576,7 +590,7 @@ impl<'a> AstValidator<'a> { ) .span_label(self.current_extern_span(), "in this `extern` block") .note(&format!( - "This limitation may be lifted in the future; see issue #{} for more information", + "this limitation may be lifted in the future; see issue #{} for more information", n, n, )) .emit(); @@ -669,31 +683,53 @@ impl<'a> AstValidator<'a> { } } + fn emit_e0568(&self, span: Span, ident_span: Span) { + struct_span_err!( + self.session, + span, + E0568, + "auto traits cannot have super traits or lifetime bounds" + ) + .span_label(ident_span, "auto trait cannot have super traits or lifetime bounds") + .span_suggestion( + span, + "remove the super traits or lifetime bounds", + String::new(), + Applicability::MachineApplicable, + ) + .emit(); + } + fn deny_super_traits(&self, bounds: &GenericBounds, ident_span: Span) { - if let [first @ last] | [first, .., last] = &bounds[..] { - let span = first.span().to(last.span()); - struct_span_err!(self.session, span, E0568, "auto traits cannot have super traits") - .span_label(ident_span, "auto trait cannot have super traits") - .span_suggestion( - span, - "remove the super traits", - String::new(), - Applicability::MachineApplicable, - ) - .emit(); + if let [.., last] = &bounds[..] { + let span = ident_span.shrink_to_hi().to(last.span()); + self.emit_e0568(span, ident_span); + } + } + + fn deny_where_clause(&self, where_clause: &WhereClause, ident_span: Span) { + if !where_clause.predicates.is_empty() { + self.emit_e0568(where_clause.span, ident_span); } } fn deny_items(&self, trait_items: &[P], ident_span: Span) { if !trait_items.is_empty() { let spans: Vec<_> = trait_items.iter().map(|i| i.ident.span).collect(); + let total_span = trait_items.first().unwrap().span.to(trait_items.last().unwrap().span); struct_span_err!( self.session, spans, E0380, - "auto traits cannot have methods or associated items" + "auto traits cannot have associated items" ) - .span_label(ident_span, "auto trait cannot have items") + .span_suggestion( + total_span, + "remove these associated items", + String::new(), + Applicability::MachineApplicable, + ) + .span_label(ident_span, "auto trait cannot have associated items") .emit(); } } @@ -1170,6 +1206,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { // Auto traits cannot have generics, super traits nor contain items. self.deny_generic_params(generics, item.ident.span); self.deny_super_traits(bounds, item.ident.span); + self.deny_where_clause(&generics.where_clause, item.ident.span); self.deny_items(trait_items, item.ident.span); } self.no_questions_in_bounds(bounds, "supertraits", true); @@ -1587,7 +1624,9 @@ impl<'a> Visitor<'a> for AstValidator<'a> { walk_list!(self, visit_ty, ty); } AssocItemKind::Fn(box FnKind(_, ref sig, ref generics, ref body)) - if self.in_const_trait_impl || ctxt == AssocCtxt::Trait => + if self.in_const_trait_impl + || ctxt == AssocCtxt::Trait + || matches!(sig.header.constness, Const::Yes(_)) => { self.visit_vis(&item.vis); self.visit_ident(item.ident); diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 038d31e7c9..91b4597a9b 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -319,6 +319,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { gate_doc!( cfg => doc_cfg + cfg_hide => doc_cfg_hide masked => doc_masked notable_trait => doc_notable_trait keyword => doc_keyword @@ -762,10 +763,16 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session) { } fn maybe_stage_features(sess: &Session, krate: &ast::Crate) { + // checks if `#![feature]` has been used to enable any lang feature + // does not check the same for lib features unless there's at least one + // declared lang feature use rustc_errors::Applicability; if !sess.opts.unstable_features.is_nightly_build() { let lang_features = &sess.features_untracked().declared_lang_features; + if lang_features.len() == 0 { + return; + } for attr in krate.attrs.iter().filter(|attr| attr.has_name(sym::feature)) { let mut err = struct_span_err!( sess.parse_sess.span_diagnostic, diff --git a/compiler/rustc_ast_passes/src/lib.rs b/compiler/rustc_ast_passes/src/lib.rs index 6cde7d2bbd..47666670b2 100644 --- a/compiler/rustc_ast_passes/src/lib.rs +++ b/compiler/rustc_ast_passes/src/lib.rs @@ -4,7 +4,6 @@ //! //! The crate also contains other misc AST visitors, e.g. `node_count` and `show_span`. -#![cfg_attr(bootstrap, feature(bindings_after_at))] #![feature(iter_is_partitioned)] #![feature(box_patterns)] #![recursion_limit = "256"] diff --git a/compiler/rustc_ast_pretty/Cargo.toml b/compiler/rustc_ast_pretty/Cargo.toml index fa88740103..29f2be4cf4 100644 --- a/compiler/rustc_ast_pretty/Cargo.toml +++ b/compiler/rustc_ast_pretty/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustc_ast_pretty" version = "0.0.0" -edition = "2018" +edition = "2021" [lib] doctest = false diff --git a/compiler/rustc_attr/Cargo.toml b/compiler/rustc_attr/Cargo.toml index 0566379e1f..ba310a6860 100644 --- a/compiler/rustc_attr/Cargo.toml +++ b/compiler/rustc_attr/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustc_attr" version = "0.0.0" -edition = "2018" +edition = "2021" [lib] doctest = false diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs index 0ab452fb42..719caaabbb 100644 --- a/compiler/rustc_attr/src/builtin.rs +++ b/compiler/rustc_attr/src/builtin.rs @@ -66,7 +66,7 @@ fn handle_errors(sess: &ParseSess, span: Span, error: AttrError) { } } -#[derive(Copy, Clone, PartialEq, Encodable, Decodable, Debug)] +#[derive(Copy, Clone, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)] pub enum InlineAttr { None, Hint, @@ -74,13 +74,13 @@ pub enum InlineAttr { Never, } -#[derive(Clone, Encodable, Decodable, Debug, PartialEq, Eq)] +#[derive(Clone, Encodable, Decodable, Debug, PartialEq, Eq, HashStable_Generic)] pub enum InstructionSetAttr { ArmA32, ArmT32, } -#[derive(Clone, Encodable, Decodable, Debug)] +#[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)] pub enum OptimizeAttr { None, Speed, @@ -802,7 +802,7 @@ impl IntType { /// Valid repr contents: any of the primitive integral type names (see /// `int_type_of_word`, below) to specify enum discriminant type; `C`, to use /// the same discriminant size that the corresponding C enum would or C -/// structure layout, `packed` to remove padding, and `transparent` to elegate representation +/// structure layout, `packed` to remove padding, and `transparent` to delegate representation /// concerns to the only non-ZST field. pub fn find_repr_attrs(sess: &Session, attr: &Attribute) -> Vec { use ReprAttr::*; diff --git a/compiler/rustc_mir/Cargo.toml b/compiler/rustc_borrowck/Cargo.toml similarity index 72% rename from compiler/rustc_mir/Cargo.toml rename to compiler/rustc_borrowck/Cargo.toml index 3049fb3b38..75e9c69af4 100644 --- a/compiler/rustc_mir/Cargo.toml +++ b/compiler/rustc_borrowck/Cargo.toml @@ -1,37 +1,30 @@ [package] -name = "rustc_mir" +name = "rustc_borrowck" version = "0.0.0" -edition = "2018" +edition = "2021" [lib] doctest = false [dependencies] either = "1.5.0" -rustc_graphviz = { path = "../rustc_graphviz" } -gsgdt = "0.1.2" itertools = "0.9" tracing = "0.1" polonius-engine = "0.13.0" -regex = "1" -rustc_middle = { path = "../rustc_middle" } -rustc_attr = { path = "../rustc_attr" } +smallvec = { version = "1.6.1", features = ["union", "may_dangle"] } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } +rustc_graphviz = { path = "../rustc_graphviz" } rustc_hir = { path = "../rustc_hir" } rustc_index = { path = "../rustc_index" } rustc_infer = { path = "../rustc_infer" } rustc_lexer = { path = "../rustc_lexer" } -rustc_macros = { path = "../rustc_macros" } +rustc_middle = { path = "../rustc_middle" } +rustc_const_eval = { path = "../rustc_const_eval" } +rustc_mir_dataflow = { path = "../rustc_mir_dataflow" } rustc_serialize = { path = "../rustc_serialize" } rustc_session = { path = "../rustc_session" } rustc_target = { path = "../rustc_target" } rustc_trait_selection = { path = "../rustc_trait_selection" } rustc_traits = { path = "../rustc_traits" } -rustc_ast = { path = "../rustc_ast" } rustc_span = { path = "../rustc_span" } -rustc_apfloat = { path = "../rustc_apfloat" } -smallvec = { version = "1.6.1", features = ["union", "may_dangle"] } - -[dev-dependencies] -coverage_test_macros = { path = "src/transform/coverage/test_macros" } diff --git a/compiler/rustc_mir/src/borrow_check/borrow_set.rs b/compiler/rustc_borrowck/src/borrow_set.rs similarity index 98% rename from compiler/rustc_mir/src/borrow_check/borrow_set.rs rename to compiler/rustc_borrowck/src/borrow_set.rs index 288eda32e4..ee2ce1d3f7 100644 --- a/compiler/rustc_mir/src/borrow_check/borrow_set.rs +++ b/compiler/rustc_borrowck/src/borrow_set.rs @@ -1,14 +1,14 @@ -use crate::borrow_check::nll::ToRegionVid; -use crate::borrow_check::path_utils::allow_two_phase_borrow; -use crate::borrow_check::place_ext::PlaceExt; -use crate::dataflow::indexes::BorrowIndex; -use crate::dataflow::move_paths::MoveData; +use crate::nll::ToRegionVid; +use crate::path_utils::allow_two_phase_borrow; +use crate::place_ext::PlaceExt; +use crate::BorrowIndex; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap}; use rustc_index::bit_set::BitSet; use rustc_middle::mir::traversal; use rustc_middle::mir::visit::{MutatingUseContext, NonUseContext, PlaceContext, Visitor}; use rustc_middle::mir::{self, Body, Local, Location}; use rustc_middle::ty::{RegionVid, TyCtxt}; +use rustc_mir_dataflow::move_paths::MoveData; use std::fmt; use std::ops::Index; diff --git a/compiler/rustc_mir/src/util/borrowck_errors.rs b/compiler/rustc_borrowck/src/borrowck_errors.rs similarity index 99% rename from compiler/rustc_mir/src/util/borrowck_errors.rs rename to compiler/rustc_borrowck/src/borrowck_errors.rs index 56d8045813..5702203d7c 100644 --- a/compiler/rustc_mir/src/util/borrowck_errors.rs +++ b/compiler/rustc_borrowck/src/borrowck_errors.rs @@ -2,7 +2,7 @@ use rustc_errors::{struct_span_err, DiagnosticBuilder, DiagnosticId}; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_span::{MultiSpan, Span}; -impl<'cx, 'tcx> crate::borrow_check::MirBorrowckCtxt<'cx, 'tcx> { +impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { crate fn cannot_move_when_borrowed(&self, span: Span, desc: &str) -> DiagnosticBuilder<'cx> { struct_span_err!(self, span, E0505, "cannot move out of {} because it is borrowed", desc,) } diff --git a/compiler/rustc_mir/src/borrow_check/constraint_generation.rs b/compiler/rustc_borrowck/src/constraint_generation.rs similarity index 99% rename from compiler/rustc_mir/src/borrow_check/constraint_generation.rs rename to compiler/rustc_borrowck/src/constraint_generation.rs index c84928523d..a40f148cdf 100644 --- a/compiler/rustc_mir/src/borrow_check/constraint_generation.rs +++ b/compiler/rustc_borrowck/src/constraint_generation.rs @@ -9,7 +9,7 @@ use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::subst::SubstsRef; use rustc_middle::ty::{self, RegionVid, Ty}; -use crate::borrow_check::{ +use crate::{ borrow_set::BorrowSet, facts::AllFacts, location::LocationTable, nll::ToRegionVid, places_conflict, region_infer::values::LivenessValues, }; diff --git a/compiler/rustc_mir/src/borrow_check/constraints/graph.rs b/compiler/rustc_borrowck/src/constraints/graph.rs similarity index 99% rename from compiler/rustc_mir/src/borrow_check/constraints/graph.rs rename to compiler/rustc_borrowck/src/constraints/graph.rs index 9e4cfb2cc0..cb9e0234c4 100644 --- a/compiler/rustc_mir/src/borrow_check/constraints/graph.rs +++ b/compiler/rustc_borrowck/src/constraints/graph.rs @@ -4,7 +4,7 @@ use rustc_middle::mir::ConstraintCategory; use rustc_middle::ty::{RegionVid, VarianceDiagInfo}; use rustc_span::DUMMY_SP; -use crate::borrow_check::{ +use crate::{ constraints::OutlivesConstraintIndex, constraints::{OutlivesConstraint, OutlivesConstraintSet}, type_check::Locations, diff --git a/compiler/rustc_mir/src/borrow_check/constraints/mod.rs b/compiler/rustc_borrowck/src/constraints/mod.rs similarity index 98% rename from compiler/rustc_mir/src/borrow_check/constraints/mod.rs rename to compiler/rustc_borrowck/src/constraints/mod.rs index b944479ca4..98378a9868 100644 --- a/compiler/rustc_mir/src/borrow_check/constraints/mod.rs +++ b/compiler/rustc_borrowck/src/constraints/mod.rs @@ -5,7 +5,7 @@ use rustc_middle::ty::{RegionVid, VarianceDiagInfo}; use std::fmt; use std::ops::Index; -use crate::borrow_check::type_check::Locations; +use crate::type_check::Locations; crate mod graph; diff --git a/compiler/rustc_mir/src/borrow_check/consumers.rs b/compiler/rustc_borrowck/src/consumers.rs similarity index 87% rename from compiler/rustc_mir/src/borrow_check/consumers.rs rename to compiler/rustc_borrowck/src/consumers.rs index f6e4e38884..97daad201d 100644 --- a/compiler/rustc_mir/src/borrow_check/consumers.rs +++ b/compiler/rustc_borrowck/src/consumers.rs @@ -14,7 +14,9 @@ pub use super::{ }; /// This function computes Polonius facts for the given body. It makes a copy of -/// the body because it needs to regenerate the region identifiers. +/// the body because it needs to regenerate the region identifiers. This function +/// should never be invoked during a typical compilation session due to performance +/// issues with Polonius. /// /// Note: /// * This function will panic if the required body was already stolen. This @@ -22,8 +24,6 @@ pub use super::{ /// because they are evaluated during typechecking. The panic can be avoided /// by overriding the `mir_borrowck` query. You can find a complete example /// that shows how to do this at `src/test/run-make/obtain-borrowck/`. -/// * This function will also panic if computation of Polonius facts -/// (`-Zpolonius` flag) is not enabled. /// /// * Polonius is highly unstable, so expect regular changes in its signature or other details. pub fn get_body_with_borrowck_facts<'tcx>( @@ -31,7 +31,7 @@ pub fn get_body_with_borrowck_facts<'tcx>( def: ty::WithOptConstParam, ) -> BodyWithBorrowckFacts<'tcx> { let (input_body, promoted) = tcx.mir_promoted(def); - tcx.infer_ctxt().enter(|infcx| { + tcx.infer_ctxt().with_opaque_type_inference(def.did).enter(|infcx| { let input_body: &Body<'_> = &input_body.borrow(); let promoted: &IndexVec<_, _> = &promoted.borrow(); *super::do_mir_borrowck(&infcx, input_body, promoted, true).1.unwrap() diff --git a/compiler/rustc_mir/src/dataflow/impls/borrows.rs b/compiler/rustc_borrowck/src/dataflow.rs similarity index 78% rename from compiler/rustc_mir/src/dataflow/impls/borrows.rs rename to compiler/rustc_borrowck/src/dataflow.rs index c92cff1433..7db8d4520d 100644 --- a/compiler/rustc_mir/src/dataflow/impls/borrows.rs +++ b/compiler/rustc_borrowck/src/dataflow.rs @@ -1,18 +1,111 @@ -use rustc_middle::mir::{self, Body, Location, Place}; -use rustc_middle::ty::RegionVid; -use rustc_middle::ty::TyCtxt; - use rustc_data_structures::fx::FxHashMap; use rustc_index::bit_set::BitSet; - -use crate::borrow_check::{ - places_conflict, BorrowSet, PlaceConflictBias, PlaceExt, RegionInferenceContext, ToRegionVid, -}; -use crate::dataflow::{self, fmt::DebugWithContext, GenKill}; - +use rustc_middle::mir::{self, BasicBlock, Body, Location, Place}; +use rustc_middle::ty::RegionVid; +use rustc_middle::ty::TyCtxt; +use rustc_mir_dataflow::impls::{EverInitializedPlaces, MaybeUninitializedPlaces}; +use rustc_mir_dataflow::ResultsVisitable; +use rustc_mir_dataflow::{self, fmt::DebugWithContext, GenKill}; +use rustc_mir_dataflow::{Analysis, Direction, Results}; use std::fmt; use std::iter; +use crate::{ + places_conflict, BorrowSet, PlaceConflictBias, PlaceExt, RegionInferenceContext, ToRegionVid, +}; + +/// A tuple with named fields that can hold either the results or the transient state of the +/// dataflow analyses used by the borrow checker. +#[derive(Debug)] +pub struct BorrowckAnalyses { + pub borrows: B, + pub uninits: U, + pub ever_inits: E, +} + +/// The results of the dataflow analyses used by the borrow checker. +pub type BorrowckResults<'mir, 'tcx> = BorrowckAnalyses< + Results<'tcx, Borrows<'mir, 'tcx>>, + Results<'tcx, MaybeUninitializedPlaces<'mir, 'tcx>>, + Results<'tcx, EverInitializedPlaces<'mir, 'tcx>>, +>; + +/// The transient state of the dataflow analyses used by the borrow checker. +pub type BorrowckFlowState<'mir, 'tcx> = + as ResultsVisitable<'tcx>>::FlowState; + +macro_rules! impl_visitable { + ( $( + $T:ident { $( $field:ident : $A:ident ),* $(,)? } + )* ) => { $( + impl<'tcx, $($A),*, D: Direction> ResultsVisitable<'tcx> for $T<$( Results<'tcx, $A> ),*> + where + $( $A: Analysis<'tcx, Direction = D>, )* + { + type Direction = D; + type FlowState = $T<$( $A::Domain ),*>; + + fn new_flow_state(&self, body: &mir::Body<'tcx>) -> Self::FlowState { + $T { + $( $field: self.$field.analysis.bottom_value(body) ),* + } + } + + fn reset_to_block_entry( + &self, + state: &mut Self::FlowState, + block: BasicBlock, + ) { + $( state.$field.clone_from(&self.$field.entry_set_for_block(block)); )* + } + + fn reconstruct_before_statement_effect( + &self, + state: &mut Self::FlowState, + stmt: &mir::Statement<'tcx>, + loc: Location, + ) { + $( self.$field.analysis + .apply_before_statement_effect(&mut state.$field, stmt, loc); )* + } + + fn reconstruct_statement_effect( + &self, + state: &mut Self::FlowState, + stmt: &mir::Statement<'tcx>, + loc: Location, + ) { + $( self.$field.analysis + .apply_statement_effect(&mut state.$field, stmt, loc); )* + } + + fn reconstruct_before_terminator_effect( + &self, + state: &mut Self::FlowState, + term: &mir::Terminator<'tcx>, + loc: Location, + ) { + $( self.$field.analysis + .apply_before_terminator_effect(&mut state.$field, term, loc); )* + } + + fn reconstruct_terminator_effect( + &self, + state: &mut Self::FlowState, + term: &mir::Terminator<'tcx>, + loc: Location, + ) { + $( self.$field.analysis + .apply_terminator_effect(&mut state.$field, term, loc); )* + } + } + )* } +} + +impl_visitable! { + BorrowckAnalyses { borrows: B, uninits: U, ever_inits: E } +} + rustc_index::newtype_index! { pub struct BorrowIndex { DEBUG_FORMAT = "bw{}" @@ -108,7 +201,7 @@ impl<'tcx> OutOfScopePrecomputer<'_, 'tcx> { let bb_data = &self.body[bb]; debug_assert!(hi == bb_data.statements.len()); for &succ_bb in bb_data.terminator().successors() { - if self.visited.insert(succ_bb) == false { + if !self.visited.insert(succ_bb) { if succ_bb == location.block && first_lo > 0 { // `succ_bb` has been seen before. If it wasn't // fully processed, add its first part to `stack` @@ -230,7 +323,7 @@ impl<'a, 'tcx> Borrows<'a, 'tcx> { } } -impl<'tcx> dataflow::AnalysisDomain<'tcx> for Borrows<'_, 'tcx> { +impl<'tcx> rustc_mir_dataflow::AnalysisDomain<'tcx> for Borrows<'_, 'tcx> { type Domain = BitSet; const NAME: &'static str = "borrows"; @@ -246,7 +339,7 @@ impl<'tcx> dataflow::AnalysisDomain<'tcx> for Borrows<'_, 'tcx> { } } -impl<'tcx> dataflow::GenKillAnalysis<'tcx> for Borrows<'_, 'tcx> { +impl<'tcx> rustc_mir_dataflow::GenKillAnalysis<'tcx> for Borrows<'_, 'tcx> { type Idx = BorrowIndex; fn before_statement_effect( diff --git a/compiler/rustc_mir/src/borrow_check/def_use.rs b/compiler/rustc_borrowck/src/def_use.rs similarity index 100% rename from compiler/rustc_mir/src/borrow_check/def_use.rs rename to compiler/rustc_borrowck/src/def_use.rs diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/bound_region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs similarity index 77% rename from compiler/rustc_mir/src/borrow_check/diagnostics/bound_region_errors.rs rename to compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs index ac30093ba8..15309ccd8d 100644 --- a/compiler/rustc_mir/src/borrow_check/diagnostics/bound_region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs @@ -9,13 +9,13 @@ use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable}; use rustc_span::Span; use rustc_trait_selection::traits::query::type_op; use rustc_trait_selection::traits::{SelectionContext, TraitEngineExt as _}; -use rustc_traits::{type_op_ascribe_user_type_with_span, type_op_prove_predicate_with_span}; +use rustc_traits::{type_op_ascribe_user_type_with_span, type_op_prove_predicate_with_cause}; use std::fmt; use std::rc::Rc; -use crate::borrow_check::region_infer::values::RegionElement; -use crate::borrow_check::MirBorrowckCtxt; +use crate::region_infer::values::RegionElement; +use crate::MirBorrowckCtxt; #[derive(Clone)] crate struct UniverseInfo<'tcx>(UniverseInfoInner<'tcx>); @@ -45,13 +45,12 @@ impl UniverseInfo<'tcx> { mbcx: &mut MirBorrowckCtxt<'_, 'tcx>, placeholder: ty::PlaceholderRegion, error_element: RegionElement, - span: Span, + cause: ObligationCause<'tcx>, ) { match self.0 { UniverseInfoInner::RelateTys { expected, found } => { - let body_id = mbcx.infcx.tcx.hir().local_def_id_to_hir_id(mbcx.mir_def_id()); let err = mbcx.infcx.report_mismatched_types( - &ObligationCause::misc(span, body_id), + &cause, expected, found, TypeError::RegionsPlaceholderMismatch, @@ -59,7 +58,7 @@ impl UniverseInfo<'tcx> { err.buffer(&mut mbcx.errors_buffer); } UniverseInfoInner::TypeOp(ref type_op_info) => { - type_op_info.report_error(mbcx, placeholder, error_element, span); + type_op_info.report_error(mbcx, placeholder, error_element, cause); } UniverseInfoInner::Other => { // FIXME: This error message isn't great, but it doesn't show @@ -68,7 +67,7 @@ impl UniverseInfo<'tcx> { mbcx.infcx .tcx .sess - .struct_span_err(span, "higher-ranked subtype error") + .struct_span_err(cause.span, "higher-ranked subtype error") .buffer(&mut mbcx.errors_buffer); } } @@ -130,7 +129,7 @@ trait TypeOpInfo<'tcx> { fn nice_error( &self, tcx: TyCtxt<'tcx>, - span: Span, + cause: ObligationCause<'tcx>, placeholder_region: ty::Region<'tcx>, error_region: Option>, ) -> Option>; @@ -140,7 +139,7 @@ trait TypeOpInfo<'tcx> { mbcx: &mut MirBorrowckCtxt<'_, 'tcx>, placeholder: ty::PlaceholderRegion, error_element: RegionElement, - span: Span, + cause: ObligationCause<'tcx>, ) { let tcx = mbcx.infcx.tcx; let base_universe = self.base_universe(); @@ -150,7 +149,7 @@ trait TypeOpInfo<'tcx> { { adjusted } else { - self.fallback_error(tcx, span).buffer(&mut mbcx.errors_buffer); + self.fallback_error(tcx, cause.span).buffer(&mut mbcx.errors_buffer); return; }; @@ -175,7 +174,8 @@ trait TypeOpInfo<'tcx> { debug!(?placeholder_region); - let nice_error = self.nice_error(tcx, span, placeholder_region, error_region); + let span = cause.span; + let nice_error = self.nice_error(tcx, cause, placeholder_region, error_region); if let Some(nice_error) = nice_error { nice_error.buffer(&mut mbcx.errors_buffer); @@ -205,15 +205,24 @@ impl TypeOpInfo<'tcx> for PredicateQuery<'tcx> { fn nice_error( &self, tcx: TyCtxt<'tcx>, - span: Span, + cause: ObligationCause<'tcx>, placeholder_region: ty::Region<'tcx>, error_region: Option>, ) -> Option> { - tcx.infer_ctxt().enter_with_canonical(span, &self.canonical_query, |ref infcx, key, _| { - let mut fulfill_cx = >::new(tcx); - type_op_prove_predicate_with_span(infcx, &mut *fulfill_cx, key, Some(span)); - try_extract_error_from_fulfill_cx(fulfill_cx, infcx, placeholder_region, error_region) - }) + tcx.infer_ctxt().enter_with_canonical( + cause.span, + &self.canonical_query, + |ref infcx, key, _| { + let mut fulfill_cx = >::new(tcx); + type_op_prove_predicate_with_cause(infcx, &mut *fulfill_cx, key, cause); + try_extract_error_from_fulfill_cx( + fulfill_cx, + infcx, + placeholder_region, + error_region, + ) + }, + ) } } @@ -239,32 +248,41 @@ where fn nice_error( &self, tcx: TyCtxt<'tcx>, - span: Span, + cause: ObligationCause<'tcx>, placeholder_region: ty::Region<'tcx>, error_region: Option>, ) -> Option> { - tcx.infer_ctxt().enter_with_canonical(span, &self.canonical_query, |ref infcx, key, _| { - let mut fulfill_cx = >::new(tcx); + tcx.infer_ctxt().enter_with_canonical( + cause.span, + &self.canonical_query, + |ref infcx, key, _| { + let mut fulfill_cx = >::new(tcx); - let mut selcx = SelectionContext::new(infcx); + let mut selcx = SelectionContext::new(infcx); - // FIXME(lqd): Unify and de-duplicate the following with the actual - // `rustc_traits::type_op::type_op_normalize` query to allow the span we need in the - // `ObligationCause`. The normalization results are currently different between - // `AtExt::normalize` used in the query and `normalize` called below: the former fails - // to normalize the `nll/relate_tys/impl-fn-ignore-binder-via-bottom.rs` test. Check - // after #85499 lands to see if its fixes have erased this difference. - let (param_env, value) = key.into_parts(); - let Normalized { value: _, obligations } = rustc_trait_selection::traits::normalize( - &mut selcx, - param_env, - ObligationCause::dummy_with_span(span), - value.value, - ); - fulfill_cx.register_predicate_obligations(infcx, obligations); + // FIXME(lqd): Unify and de-duplicate the following with the actual + // `rustc_traits::type_op::type_op_normalize` query to allow the span we need in the + // `ObligationCause`. The normalization results are currently different between + // `AtExt::normalize` used in the query and `normalize` called below: the former fails + // to normalize the `nll/relate_tys/impl-fn-ignore-binder-via-bottom.rs` test. Check + // after #85499 lands to see if its fixes have erased this difference. + let (param_env, value) = key.into_parts(); + let Normalized { value: _, obligations } = rustc_trait_selection::traits::normalize( + &mut selcx, + param_env, + cause, + value.value, + ); + fulfill_cx.register_predicate_obligations(infcx, obligations); - try_extract_error_from_fulfill_cx(fulfill_cx, infcx, placeholder_region, error_region) - }) + try_extract_error_from_fulfill_cx( + fulfill_cx, + infcx, + placeholder_region, + error_region, + ) + }, + ) } } @@ -287,18 +305,29 @@ impl TypeOpInfo<'tcx> for AscribeUserTypeQuery<'tcx> { fn nice_error( &self, tcx: TyCtxt<'tcx>, - span: Span, + cause: ObligationCause<'tcx>, placeholder_region: ty::Region<'tcx>, error_region: Option>, ) -> Option> { - tcx.infer_ctxt().enter_with_canonical(span, &self.canonical_query, |ref infcx, key, _| { - let mut fulfill_cx = >::new(tcx); - type_op_ascribe_user_type_with_span(infcx, &mut *fulfill_cx, key, Some(span)).ok()?; - try_extract_error_from_fulfill_cx(fulfill_cx, infcx, placeholder_region, error_region) - }) + tcx.infer_ctxt().enter_with_canonical( + cause.span, + &self.canonical_query, + |ref infcx, key, _| { + let mut fulfill_cx = >::new(tcx); + type_op_ascribe_user_type_with_span(infcx, &mut *fulfill_cx, key, Some(cause.span)) + .ok()?; + try_extract_error_from_fulfill_cx( + fulfill_cx, + infcx, + placeholder_region, + error_region, + ) + }, + ) } } +#[instrument(skip(fulfill_cx, infcx), level = "debug")] fn try_extract_error_from_fulfill_cx<'tcx>( mut fulfill_cx: Box + 'tcx>, infcx: &InferCtxt<'_, 'tcx>, @@ -313,7 +342,7 @@ fn try_extract_error_from_fulfill_cx<'tcx>( let _errors = fulfill_cx.select_all_or_error(infcx).err().unwrap_or_else(Vec::new); let (sub_region, cause) = infcx.with_region_constraints(|region_constraints| { - debug!(?region_constraints); + debug!("{:#?}", region_constraints); region_constraints.constraints.iter().find_map(|(constraint, cause)| { match *constraint { Constraint::RegSubReg(sub, sup) if sup == placeholder_region && sup != sub => { @@ -328,7 +357,7 @@ fn try_extract_error_from_fulfill_cx<'tcx>( }) })?; - debug!(?sub_region, ?cause); + debug!(?sub_region, "cause = {:#?}", cause); let nice_error = match (error_region, sub_region) { (Some(error_region), &ty::ReVar(vid)) => NiceRegionError::new( infcx, diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs similarity index 95% rename from compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs rename to compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 6561fe37c1..37398894a2 100644 --- a/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -10,16 +10,15 @@ use rustc_middle::mir::{ ProjectionElem, Rvalue, Statement, StatementKind, Terminator, TerminatorKind, VarBindingForm, }; use rustc_middle::ty::{self, suggest_constraining_type_param, Ty}; +use rustc_mir_dataflow::move_paths::{InitKind, MoveOutIndex, MovePathIndex}; use rustc_span::source_map::DesugaringKind; use rustc_span::symbol::sym; use rustc_span::{BytePos, MultiSpan, Span, DUMMY_SP}; use rustc_trait_selection::infer::InferCtxtExt; -use crate::dataflow::drop_flag_effects; -use crate::dataflow::indexes::{MoveOutIndex, MovePathIndex}; -use crate::util::borrowck_errors; +use crate::borrowck_errors; -use crate::borrow_check::{ +use crate::{ borrow_set::BorrowData, diagnostics::Instance, prefixes::IsPrefixOf, InitializationRequiringAction, MirBorrowckCtxt, PrefixSet, WriteKind, }; @@ -49,7 +48,7 @@ enum StorageDeadOrDrop<'tcx> { } impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { - pub(in crate::borrow_check) fn report_use_of_moved_or_uninitialized( + pub(crate) fn report_use_of_moved_or_uninitialized( &mut self, location: Location, desired_action: InitializationRequiringAction, @@ -218,7 +217,19 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ); if self.fn_self_span_reported.insert(fn_span) { err.span_note( - self_arg.span, + // Check whether the source is accessible + if self + .infcx + .tcx + .sess + .source_map() + .span_to_snippet(self_arg.span) + .is_ok() + { + self_arg.span + } else { + fn_call_span + }, "calling this operator moves the left-hand side", ); } @@ -429,7 +440,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { deref_target_ty )); - err.span_note(deref_target, "deref defined here"); + // Check first whether the source is accessible (issue #87060) + if self.infcx.tcx.sess.source_map().span_to_snippet(deref_target).is_ok() { + err.span_note(deref_target, "deref defined here"); + } } if let Some((_, mut old_err)) = @@ -441,7 +455,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } } - pub(in crate::borrow_check) fn report_move_out_while_borrowed( + pub(crate) fn report_move_out_while_borrowed( &mut self, location: Location, (place, span): (Place<'tcx>, Span), @@ -489,7 +503,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { err.buffer(&mut self.errors_buffer); } - pub(in crate::borrow_check) fn report_use_while_mutably_borrowed( + pub(crate) fn report_use_while_mutably_borrowed( &mut self, location: Location, (place, _span): (Place<'tcx>, Span), @@ -535,7 +549,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { err } - pub(in crate::borrow_check) fn report_conflicting_borrow( + pub(crate) fn report_conflicting_borrow( &mut self, location: Location, (place, span): (Place<'tcx>, Span), @@ -798,7 +812,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { /// cannot borrow `a.u` (via `a.u.z.c`) as immutable because it is also borrowed as /// mutable (via `a.u.s.b`) [E0502] /// ``` - pub(in crate::borrow_check) fn describe_place_for_conflicting_borrow( + pub(crate) fn describe_place_for_conflicting_borrow( &self, first_borrowed_place: Place<'tcx>, second_borrowed_place: Place<'tcx>, @@ -875,7 +889,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { /// short a lifetime. (But sometimes it is more useful to report /// it as a more direct conflict between the execution of a /// `Drop::drop` with an aliasing borrow.) - pub(in crate::borrow_check) fn report_borrowed_value_does_not_live_long_enough( + pub(crate) fn report_borrowed_value_does_not_live_long_enough( &mut self, location: Location, borrow: &BorrowData<'tcx>, @@ -1516,25 +1530,45 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } } + let mut mpis = vec![mpi]; + let move_paths = &self.move_data.move_paths; + mpis.extend(move_paths[mpi].parents(move_paths).map(|(mpi, _)| mpi)); + let mut stack = Vec::new(); - stack.extend(predecessor_locations(self.body, location).map(|predecessor| { - let is_back_edge = location.dominates(predecessor, &self.dominators); - (predecessor, is_back_edge) - })); + let mut back_edge_stack = Vec::new(); + + predecessor_locations(self.body, location).for_each(|predecessor| { + if location.dominates(predecessor, &self.dominators) { + back_edge_stack.push(predecessor) + } else { + stack.push(predecessor); + } + }); + + let mut reached_start = false; + + /* Check if the mpi is initialized as an argument */ + let mut is_argument = false; + for arg in self.body.args_iter() { + let path = self.move_data.rev_lookup.find_local(arg); + if mpis.contains(&path) { + is_argument = true; + } + } let mut visited = FxHashSet::default(); let mut move_locations = FxHashSet::default(); let mut reinits = vec![]; let mut result = vec![]; - 'dfs: while let Some((location, is_back_edge)) = stack.pop() { + let mut dfs_iter = |result: &mut Vec, location: Location, is_back_edge: bool| { debug!( "report_use_of_moved_or_uninitialized: (current_location={:?}, back_edge={})", location, is_back_edge ); if !visited.insert(location) { - continue; + return true; } // check for moves @@ -1553,10 +1587,6 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // worry about the other case: that is, if there is a move of a.b.c, it is already // marked as a move of a.b and a as well, so we will generate the correct errors // there. - let mut mpis = vec![mpi]; - let move_paths = &self.move_data.move_paths; - mpis.extend(move_paths[mpi].parents(move_paths).map(|(mpi, _)| mpi)); - for moi in &self.move_data.loc_map[location] { debug!("report_use_of_moved_or_uninitialized: moi={:?}", moi); let path = self.move_data.moves[*moi].path; @@ -1584,33 +1614,70 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // Because we stop the DFS here, we only highlight `let c = a`, // and not `let b = a`. We will of course also report an error at // `let c = a` which highlights `let b = a` as the move. - continue 'dfs; + return true; } } } // check for inits let mut any_match = false; - drop_flag_effects::for_location_inits( - self.infcx.tcx, - &self.body, - self.move_data, - location, - |m| { - if m == mpi { - any_match = true; + for ii in &self.move_data.init_loc_map[location] { + let init = self.move_data.inits[*ii]; + match init.kind { + InitKind::Deep | InitKind::NonPanicPathOnly => { + if mpis.contains(&init.path) { + any_match = true; + } } - }, - ); + InitKind::Shallow => { + if mpi == init.path { + any_match = true; + } + } + } + } if any_match { reinits.push(location); - continue 'dfs; + return true; + } + return false; + }; + + while let Some(location) = stack.pop() { + if dfs_iter(&mut result, location, false) { + continue; } - stack.extend(predecessor_locations(self.body, location).map(|predecessor| { - let back_edge = location.dominates(predecessor, &self.dominators); - (predecessor, is_back_edge || back_edge) - })); + let mut has_predecessor = false; + predecessor_locations(self.body, location).for_each(|predecessor| { + if location.dominates(predecessor, &self.dominators) { + back_edge_stack.push(predecessor) + } else { + stack.push(predecessor); + } + has_predecessor = true; + }); + + if !has_predecessor { + reached_start = true; + } + } + if (is_argument || !reached_start) && result.is_empty() { + /* Process back edges (moves in future loop iterations) only if + the move path is definitely initialized upon loop entry, + to avoid spurious "in previous iteration" errors. + During DFS, if there's a path from the error back to the start + of the function with no intervening init or move, then the + move path may be uninitialized at loop entry. + */ + while let Some(location) = back_edge_stack.pop() { + if dfs_iter(&mut result, location, true) { + continue; + } + + predecessor_locations(self.body, location) + .for_each(|predecessor| back_edge_stack.push(predecessor)); + } } // Check if we can reach these reinits from a move location. @@ -1634,7 +1701,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { (result, reinits_reachable) } - pub(in crate::borrow_check) fn report_illegal_mutation_of_borrowed( + pub(crate) fn report_illegal_mutation_of_borrowed( &mut self, location: Location, (place, span): (Place<'tcx>, Span), @@ -1695,7 +1762,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { Some((method_did, method_substs)), ) = ( &self.body[loan.reserve_location.block].terminator, - crate::util::find_self_call( + rustc_const_eval::util::find_self_call( tcx, self.body, loan.assigned_place.local, @@ -1726,7 +1793,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { /// assigned; `err_place` is a place providing a reason why /// `place` is not mutable (e.g., the non-`mut` local `x` in an /// assignment to `x.f`). - pub(in crate::borrow_check) fn report_illegal_reassignment( + pub(crate) fn report_illegal_reassignment( &mut self, _location: Location, (place, span): (Place<'tcx>, Span), @@ -2226,7 +2293,7 @@ enum AnnotatedBorrowFnSignature<'tcx> { impl<'tcx> AnnotatedBorrowFnSignature<'tcx> { /// Annotate the provided diagnostic with information about borrow from the fn signature that /// helps explain. - pub(in crate::borrow_check) fn emit( + pub(crate) fn emit( &self, cx: &mut MirBorrowckCtxt<'_, 'tcx>, diag: &mut DiagnosticBuilder<'_>, diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs similarity index 98% rename from compiler/rustc_mir/src/borrow_check/diagnostics/explain_borrow.rs rename to compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs index f40a2db330..d5de0801ac 100644 --- a/compiler/rustc_mir/src/borrow_check/diagnostics/explain_borrow.rs +++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs @@ -15,8 +15,8 @@ use rustc_middle::ty::{self, RegionVid, TyCtxt}; use rustc_span::symbol::Symbol; use rustc_span::Span; -use crate::borrow_check::region_infer::BlameConstraint; -use crate::borrow_check::{ +use crate::region_infer::BlameConstraint; +use crate::{ borrow_set::BorrowData, nll::ConstraintDescription, region_infer::Cause, MirBorrowckCtxt, WriteKind, }; @@ -24,7 +24,7 @@ use crate::borrow_check::{ use super::{find_use, RegionName, UseSpans}; #[derive(Debug)] -pub(in crate::borrow_check) enum BorrowExplanation { +pub(crate) enum BorrowExplanation { UsedLater(LaterUseKind, Span, Option), UsedLaterInLoop(LaterUseKind, Span, Option), UsedLaterWhenDropped { @@ -43,7 +43,7 @@ pub(in crate::borrow_check) enum BorrowExplanation { } #[derive(Clone, Copy, Debug)] -pub(in crate::borrow_check) enum LaterUseKind { +pub(crate) enum LaterUseKind { TraitCapture, ClosureCapture, Call, @@ -52,13 +52,13 @@ pub(in crate::borrow_check) enum LaterUseKind { } impl BorrowExplanation { - pub(in crate::borrow_check) fn is_explained(&self) -> bool { + pub(crate) fn is_explained(&self) -> bool { match self { BorrowExplanation::Unexplained => false, _ => true, } } - pub(in crate::borrow_check) fn add_explanation_to_diagnostic<'tcx>( + pub(crate) fn add_explanation_to_diagnostic<'tcx>( &self, tcx: TyCtxt<'tcx>, body: &Body<'tcx>, @@ -267,7 +267,7 @@ impl BorrowExplanation { _ => {} } } - pub(in crate::borrow_check) fn add_lifetime_bound_suggestion_to_diagnostic( + pub(crate) fn add_lifetime_bound_suggestion_to_diagnostic( &self, err: &mut DiagnosticBuilder<'_>, category: &ConstraintCategory, @@ -300,7 +300,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { borrow_region: RegionVid, outlived_region: RegionVid, ) -> (ConstraintCategory, bool, Span, Option) { - let BlameConstraint { category, from_closure, span, variance_info: _ } = + let BlameConstraint { category, from_closure, cause, variance_info: _ } = self.regioncx.best_blame_constraint( &self.body, borrow_region, @@ -310,7 +310,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let outlived_fr_name = self.give_region_a_name(outlived_region); - (category, from_closure, span, outlived_fr_name) + (category, from_closure, cause.span, outlived_fr_name) } /// Returns structured explanation for *why* the borrow contains the @@ -326,7 +326,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { /// - second half is the place being accessed /// /// [d]: https://rust-lang.github.io/rfcs/2094-nll.html#leveraging-intuition-framing-errors-in-terms-of-points - pub(in crate::borrow_check) fn explain_why_borrow_contains_point( + pub(crate) fn explain_why_borrow_contains_point( &self, location: Location, borrow: &BorrowData<'tcx>, diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/find_use.rs b/compiler/rustc_borrowck/src/diagnostics/find_use.rs similarity index 99% rename from compiler/rustc_mir/src/borrow_check/diagnostics/find_use.rs rename to compiler/rustc_borrowck/src/diagnostics/find_use.rs index 8d8cdfb529..ab4536f00f 100644 --- a/compiler/rustc_mir/src/borrow_check/diagnostics/find_use.rs +++ b/compiler/rustc_borrowck/src/diagnostics/find_use.rs @@ -1,7 +1,7 @@ use std::collections::VecDeque; use std::rc::Rc; -use crate::borrow_check::{ +use crate::{ def_use::{self, DefUse}, nll::ToRegionVid, region_infer::{Cause, RegionInferenceContext}, diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs similarity index 99% rename from compiler/rustc_mir/src/borrow_check/diagnostics/mod.rs rename to compiler/rustc_borrowck/src/diagnostics/mod.rs index 55c6410ed3..a4df277a7b 100644 --- a/compiler/rustc_mir/src/borrow_check/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -12,6 +12,7 @@ use rustc_middle::mir::{ }; use rustc_middle::ty::print::Print; use rustc_middle::ty::{self, DefIdTree, Instance, Ty, TyCtxt}; +use rustc_mir_dataflow::move_paths::{InitLocation, LookupResult}; use rustc_span::{ hygiene::{DesugaringKind, ForLoopLoc}, symbol::sym, @@ -21,7 +22,6 @@ use rustc_target::abi::VariantIdx; use super::borrow_set::BorrowData; use super::MirBorrowckCtxt; -use crate::dataflow::move_paths::{InitLocation, LookupResult}; mod find_use; mod outlives_suggestion; @@ -900,8 +900,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { }) = &self.body[location.block].terminator { let (method_did, method_substs) = if let Some(info) = - crate::util::find_self_call(self.infcx.tcx, &self.body, target_temp, location.block) - { + rustc_const_eval::util::find_self_call( + self.infcx.tcx, + &self.body, + target_temp, + location.block, + ) { info } else { return normal_ret; @@ -962,8 +966,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { _ => None, }); let is_option_or_result = parent_self_ty.map_or(false, |def_id| { - tcx.is_diagnostic_item(sym::option_type, def_id) - || tcx.is_diagnostic_item(sym::result_type, def_id) + tcx.is_diagnostic_item(sym::Option, def_id) + || tcx.is_diagnostic_item(sym::Result, def_id) }); FnSelfUseKind::Normal { self_arg, implicit_into_iter, is_option_or_result } }); diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/move_errors.rs b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs similarity index 96% rename from compiler/rustc_mir/src/borrow_check/diagnostics/move_errors.rs rename to compiler/rustc_borrowck/src/diagnostics/move_errors.rs index 66e06325fa..855e6850b2 100644 --- a/compiler/rustc_mir/src/borrow_check/diagnostics/move_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs @@ -2,16 +2,16 @@ use rustc_errors::{Applicability, DiagnosticBuilder}; use rustc_infer::infer::TyCtxtInferExt; use rustc_middle::mir::*; use rustc_middle::ty; +use rustc_mir_dataflow::move_paths::{ + IllegalMoveOrigin, IllegalMoveOriginKind, LookupResult, MoveError, MovePathIndex, +}; use rustc_span::source_map::DesugaringKind; use rustc_span::{sym, Span, DUMMY_SP}; use rustc_trait_selection::traits::type_known_to_meet_bound_modulo_regions; -use crate::borrow_check::diagnostics::UseSpans; -use crate::borrow_check::prefixes::PrefixSet; -use crate::borrow_check::MirBorrowckCtxt; -use crate::dataflow::move_paths::{ - IllegalMoveOrigin, IllegalMoveOriginKind, LookupResult, MoveError, MovePathIndex, -}; +use crate::diagnostics::UseSpans; +use crate::prefixes::PrefixSet; +use crate::MirBorrowckCtxt; // Often when desugaring a pattern match we may have many individual moves in // MIR that are all part of one operation from the user's point-of-view. For @@ -336,15 +336,15 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { if def_id.as_local() == Some(self.mir_def_id()) && upvar_field.is_some() => { let closure_kind_ty = closure_substs.as_closure().kind_ty(); - let closure_kind = closure_kind_ty.to_opt_closure_kind(); - let capture_description = match closure_kind { - Some(ty::ClosureKind::Fn) => "captured variable in an `Fn` closure", - Some(ty::ClosureKind::FnMut) => "captured variable in an `FnMut` closure", + let closure_kind = match closure_kind_ty.to_opt_closure_kind() { + Some(kind @ (ty::ClosureKind::Fn | ty::ClosureKind::FnMut)) => kind, Some(ty::ClosureKind::FnOnce) => { bug!("closure kind does not match first argument type") } None => bug!("closure kind not inferred by borrowck"), }; + let capture_description = + format!("captured variable in an `{}` closure", closure_kind); let upvar = &self.upvars[upvar_field.unwrap().index()]; let upvar_hir_id = upvar.place.get_root_variable(); @@ -368,6 +368,10 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { let mut diag = self.cannot_move_out_of(span, &place_description); diag.span_label(upvar_span, "captured outer variable"); + diag.span_label( + self.body.span, + format!("captured by this `{}` closure", closure_kind), + ); diag } @@ -396,8 +400,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { | ty::Opaque(def_id, _) => def_id, _ => return err, }; - let is_option = self.infcx.tcx.is_diagnostic_item(sym::option_type, def_id); - let is_result = self.infcx.tcx.is_diagnostic_item(sym::result_type, def_id); + let is_option = self.infcx.tcx.is_diagnostic_item(sym::Option, def_id); + let is_result = self.infcx.tcx.is_diagnostic_item(sym::Result, def_id); if (is_option || is_result) && use_spans.map_or(true, |v| !v.for_closure()) { err.span_suggestion_verbose( span.shrink_to_hi(), diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs similarity index 99% rename from compiler/rustc_mir/src/borrow_check/diagnostics/mutability_errors.rs rename to compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index 4e079ed865..246d2e3208 100644 --- a/compiler/rustc_mir/src/borrow_check/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -14,9 +14,9 @@ use rustc_span::source_map::DesugaringKind; use rustc_span::symbol::{kw, Symbol}; use rustc_span::{BytePos, Span}; -use crate::borrow_check::diagnostics::BorrowedContentSource; -use crate::borrow_check::MirBorrowckCtxt; -use crate::util::collect_writes::FindAssignments; +use crate::diagnostics::BorrowedContentSource; +use crate::MirBorrowckCtxt; +use rustc_const_eval::util::collect_writes::FindAssignments; use rustc_errors::{Applicability, DiagnosticBuilder}; #[derive(Copy, Clone, Debug, Eq, PartialEq)] @@ -972,8 +972,7 @@ fn suggest_ampmut<'tcx>( if let Some(assignment_rhs_span) = opt_assignment_rhs_span { if let Ok(src) = tcx.sess.source_map().span_to_snippet(assignment_rhs_span) { let is_mutbl = |ty: &str| -> bool { - if ty.starts_with("mut") { - let rest = &ty[3..]; + if let Some(rest) = ty.strip_prefix("mut") { match rest.chars().next() { // e.g. `&mut x` Some(c) if c.is_whitespace() => true, diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/outlives_suggestion.rs b/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs similarity index 97% rename from compiler/rustc_mir/src/borrow_check/diagnostics/outlives_suggestion.rs rename to compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs index 7dc3434bf3..b15e55cd66 100644 --- a/compiler/rustc_mir/src/borrow_check/diagnostics/outlives_suggestion.rs +++ b/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs @@ -1,16 +1,14 @@ //! Contains utilities for generating suggestions for borrowck errors related to unsatisfied //! outlives constraints. -use std::collections::BTreeMap; - use rustc_data_structures::fx::FxHashSet; use rustc_errors::DiagnosticBuilder; use rustc_middle::ty::RegionVid; +use smallvec::SmallVec; +use std::collections::BTreeMap; use tracing::debug; -use smallvec::SmallVec; - -use crate::borrow_check::MirBorrowckCtxt; +use crate::MirBorrowckCtxt; use super::{ErrorConstraintInfo, RegionName, RegionNameSource}; @@ -173,9 +171,7 @@ impl OutlivesSuggestionBuilder { let outlived_fr_name = self.region_vid_to_name(mbcx, errci.outlived_fr); if let (Some(fr_name), Some(outlived_fr_name)) = (fr_name, outlived_fr_name) { - if let RegionNameSource::Static = outlived_fr_name.source { - diag.help(&format!("consider replacing `{}` with `'static`", fr_name)); - } else { + if !matches!(outlived_fr_name.source, RegionNameSource::Static) { diag.help(&format!( "consider adding the following bound: `{}: {}`", fr_name, outlived_fr_name diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs similarity index 94% rename from compiler/rustc_mir/src/borrow_check/diagnostics/region_errors.rs rename to compiler/rustc_borrowck/src/diagnostics/region_errors.rs index cbb8f064bb..11cdbe84ac 100644 --- a/compiler/rustc_mir/src/borrow_check/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -11,18 +11,17 @@ use rustc_middle::ty::{self, RegionVid, Ty}; use rustc_span::symbol::{kw, sym}; use rustc_span::{BytePos, Span}; -use crate::util::borrowck_errors; +use crate::borrowck_errors; -use crate::borrow_check::region_infer::BlameConstraint; -use crate::borrow_check::{ +use super::{OutlivesSuggestionBuilder, RegionName}; +use crate::region_infer::BlameConstraint; +use crate::{ nll::ConstraintDescription, region_infer::{values::RegionElement, TypeTest}, universal_regions::DefiningTy, MirBorrowckCtxt, }; -use super::{OutlivesSuggestionBuilder, RegionName}; - impl ConstraintDescription for ConstraintCategory { fn description(&self) -> &'static str { // Must end with a space. Allows for empty names to be provided. @@ -40,7 +39,9 @@ impl ConstraintDescription for ConstraintCategory { ConstraintCategory::CopyBound => "copying this value ", ConstraintCategory::OpaqueType => "opaque type ", ConstraintCategory::ClosureUpvar(_) => "closure capture ", - ConstraintCategory::Boring + ConstraintCategory::Usage => "this usage ", + ConstraintCategory::Predicate(_) + | ConstraintCategory::Boring | ConstraintCategory::BoringNoLocation | ConstraintCategory::Internal => "", } @@ -152,7 +153,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { } /// Produces nice borrowck error diagnostics for all the errors collected in `nll_errors`. - pub(in crate::borrow_check) fn report_region_errors(&mut self, nll_errors: RegionErrors<'tcx>) { + pub(crate) fn report_region_errors(&mut self, nll_errors: RegionErrors<'tcx>) { // Iterate through all the errors, producing a diagnostic for each one. The diagnostics are // buffered in the `MirBorrowckCtxt`. @@ -216,7 +217,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { let error_vid = self.regioncx.region_from_element(longer_fr, &error_element); // Find the code to blame for the fact that `longer_fr` outlives `error_fr`. - let (_, span) = self.regioncx.find_outlives_blame_span( + let (_, cause) = self.regioncx.find_outlives_blame_span( &self.body, longer_fr, NllRegionVariableOrigin::Placeholder(placeholder), @@ -226,7 +227,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { let universe = placeholder.universe; let universe_info = self.regioncx.universe_info(universe); - universe_info.report_error(self, placeholder, error_element, span); + universe_info.report_error(self, placeholder, error_element, cause); } RegionErrorKind::RegionError { fr_origin, longer_fr, shorter_fr, is_reported } => { @@ -265,7 +266,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { /// ``` /// /// Here we would be invoked with `fr = 'a` and `outlived_fr = `'b`. - pub(in crate::borrow_check) fn report_region_error( + pub(crate) fn report_region_error( &mut self, fr: RegionVid, fr_origin: NllRegionVariableOrigin, @@ -274,15 +275,15 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { ) { debug!("report_region_error(fr={:?}, outlived_fr={:?})", fr, outlived_fr); - let BlameConstraint { category, span, variance_info, from_closure: _ } = + let BlameConstraint { category, cause, variance_info, from_closure: _ } = self.regioncx.best_blame_constraint(&self.body, fr, fr_origin, |r| { self.regioncx.provides_universal_region(r, fr, outlived_fr) }); - debug!("report_region_error: category={:?} {:?} {:?}", category, span, variance_info); + debug!("report_region_error: category={:?} {:?} {:?}", category, cause, variance_info); // Check if we can use one of the "nice region errors". if let (Some(f), Some(o)) = (self.to_error_region(fr), self.to_error_region(outlived_fr)) { - let nice = NiceRegionError::new_from_span(self.infcx, span, o, f); + let nice = NiceRegionError::new_from_span(self.infcx, cause.span, o, f); if let Some(diag) = nice.try_report_from_nll() { diag.buffer(&mut self.errors_buffer); return; @@ -305,7 +306,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { fr_is_local, outlived_fr_is_local, category, - span, + span: cause.span, }; let mut diag = match (category, fr_is_local, outlived_fr_is_local) { @@ -497,6 +498,27 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { diag.span_label(*span, format!("`{}` escapes the {} body here", fr_name, escapes_from)); } + // Only show an extra note if we can find an 'error region' for both of the region + // variables. This avoids showing a noisy note that just mentions 'synthetic' regions + // that don't help the user understand the error. + if self.to_error_region(errci.fr).is_some() + && self.to_error_region(errci.outlived_fr).is_some() + { + let fr_region_name = self.give_region_a_name(errci.fr).unwrap(); + fr_region_name.highlight_region_name(&mut diag); + let outlived_fr_region_name = self.give_region_a_name(errci.outlived_fr).unwrap(); + outlived_fr_region_name.highlight_region_name(&mut diag); + + diag.span_label( + *span, + format!( + "{}requires that `{}` must outlive `{}`", + category.description(), + fr_region_name, + outlived_fr_region_name, + ), + ); + } diag } diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs similarity index 99% rename from compiler/rustc_mir/src/borrow_check/diagnostics/region_name.rs rename to compiler/rustc_borrowck/src/diagnostics/region_name.rs index 1f168c612f..5edb52b0b6 100644 --- a/compiler/rustc_mir/src/borrow_check/diagnostics/region_name.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs @@ -10,7 +10,7 @@ use rustc_middle::ty::{self, RegionVid, Ty}; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{Span, DUMMY_SP}; -use crate::borrow_check::{nll::ToRegionVid, universal_regions::DefiningTy, MirBorrowckCtxt}; +use crate::{nll::ToRegionVid, universal_regions::DefiningTy, MirBorrowckCtxt}; /// A name for a particular region used in emitting diagnostics. This name could be a generated /// name like `'1`, a name used by the user like `'a`, or a name like `'static`. diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/var_name.rs b/compiler/rustc_borrowck/src/diagnostics/var_name.rs similarity index 97% rename from compiler/rustc_mir/src/borrow_check/diagnostics/var_name.rs rename to compiler/rustc_borrowck/src/diagnostics/var_name.rs index 4abc623fc5..00f6280675 100644 --- a/compiler/rustc_mir/src/borrow_check/diagnostics/var_name.rs +++ b/compiler/rustc_borrowck/src/diagnostics/var_name.rs @@ -1,5 +1,5 @@ -use crate::borrow_check::Upvar; -use crate::borrow_check::{nll::ToRegionVid, region_infer::RegionInferenceContext}; +use crate::Upvar; +use crate::{nll::ToRegionVid, region_infer::RegionInferenceContext}; use rustc_index::vec::{Idx, IndexVec}; use rustc_middle::mir::{Body, Local}; use rustc_middle::ty::{RegionVid, TyCtxt}; diff --git a/compiler/rustc_mir/src/borrow_check/facts.rs b/compiler/rustc_borrowck/src/facts.rs similarity index 95% rename from compiler/rustc_mir/src/borrow_check/facts.rs rename to compiler/rustc_borrowck/src/facts.rs index 215dead5bd..86b719bdfa 100644 --- a/compiler/rustc_mir/src/borrow_check/facts.rs +++ b/compiler/rustc_borrowck/src/facts.rs @@ -1,10 +1,11 @@ -use crate::borrow_check::location::{LocationIndex, LocationTable}; -use crate::dataflow::indexes::{BorrowIndex, MovePathIndex}; +use crate::location::{LocationIndex, LocationTable}; +use crate::BorrowIndex; use polonius_engine::AllFacts as PoloniusFacts; use polonius_engine::Atom; use rustc_index::vec::Idx; use rustc_middle::mir::Local; use rustc_middle::ty::{RegionVid, TyCtxt}; +use rustc_mir_dataflow::move_paths::MovePathIndex; use std::error::Error; use std::fmt::Debug; use std::fs::{self, File}; @@ -100,12 +101,6 @@ impl Atom for LocationIndex { } } -impl Atom for MovePathIndex { - fn index(self) -> usize { - Idx::index(self) - } -} - struct FactWriter<'w> { location_table: &'w LocationTable, dir: &'w Path, diff --git a/compiler/rustc_mir/src/borrow_check/invalidation.rs b/compiler/rustc_borrowck/src/invalidation.rs similarity index 98% rename from compiler/rustc_mir/src/borrow_check/invalidation.rs rename to compiler/rustc_borrowck/src/invalidation.rs index b83a427f47..efd34f4e0a 100644 --- a/compiler/rustc_mir/src/borrow_check/invalidation.rs +++ b/compiler/rustc_borrowck/src/invalidation.rs @@ -7,12 +7,10 @@ use rustc_middle::mir::{Statement, StatementKind}; use rustc_middle::ty::TyCtxt; use std::iter; -use crate::dataflow::indexes::BorrowIndex; - -use crate::borrow_check::{ +use crate::{ borrow_set::BorrowSet, facts::AllFacts, location::LocationTable, path_utils::*, AccessDepth, - Activation, ArtificialField, Deep, JustWrite, LocalMutationIsAllowed, MutateMode, Read, - ReadKind, ReadOrWrite, Reservation, Shallow, Write, WriteAndRead, WriteKind, + Activation, ArtificialField, BorrowIndex, Deep, JustWrite, LocalMutationIsAllowed, MutateMode, + Read, ReadKind, ReadOrWrite, Reservation, Shallow, Write, WriteAndRead, WriteKind, }; pub(super) fn generate_invalidates<'tcx>( @@ -318,7 +316,8 @@ impl<'cx, 'tcx> InvalidationGenerator<'cx, 'tcx> { Rvalue::Use(ref operand) | Rvalue::Repeat(ref operand, _) | Rvalue::UnaryOp(_ /*un_op*/, ref operand) - | Rvalue::Cast(_ /*cast_kind*/, ref operand, _ /*ty*/) => { + | Rvalue::Cast(_ /*cast_kind*/, ref operand, _ /*ty*/) + | Rvalue::ShallowInitBox(ref operand, _ /*ty*/) => { self.consume_operand(location, operand) } diff --git a/compiler/rustc_mir/src/borrow_check/mod.rs b/compiler/rustc_borrowck/src/lib.rs similarity index 97% rename from compiler/rustc_mir/src/borrow_check/mod.rs rename to compiler/rustc_borrowck/src/lib.rs index 1dcb067656..e6260157d1 100644 --- a/compiler/rustc_mir/src/borrow_check/mod.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -1,5 +1,23 @@ //! This query borrow-checks the MIR to (further) ensure it is not broken. +#![feature(bool_to_option)] +#![feature(box_patterns)] +#![cfg_attr(bootstrap, feature(const_panic))] +#![feature(crate_visibility_modifier)] +#![feature(format_args_capture)] +#![feature(in_band_lifetimes)] +#![feature(iter_zip)] +#![feature(min_specialization)] +#![feature(stmt_expr_attributes)] +#![feature(trusted_step)] +#![feature(try_blocks)] +#![recursion_limit = "256"] + +#[macro_use] +extern crate rustc_middle; +#[macro_use] +extern crate tracing; + use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::graph::dominators::Dominators; use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorReported}; @@ -29,14 +47,13 @@ use std::iter; use std::mem; use std::rc::Rc; -use crate::dataflow; -use crate::dataflow::impls::{ - Borrows, EverInitializedPlaces, MaybeInitializedPlaces, MaybeUninitializedPlaces, +use rustc_mir_dataflow::impls::{ + EverInitializedPlaces, MaybeInitializedPlaces, MaybeUninitializedPlaces, }; -use crate::dataflow::indexes::{BorrowIndex, InitIndex, MoveOutIndex, MovePathIndex}; -use crate::dataflow::move_paths::{InitLocation, LookupResult, MoveData, MoveError}; -use crate::dataflow::MoveDataParamEnv; -use crate::dataflow::{Analysis, BorrowckFlowState as Flows, BorrowckResults}; +use rustc_mir_dataflow::move_paths::{InitIndex, MoveOutIndex, MovePathIndex}; +use rustc_mir_dataflow::move_paths::{InitLocation, LookupResult, MoveData, MoveError}; +use rustc_mir_dataflow::Analysis; +use rustc_mir_dataflow::MoveDataParamEnv; use self::diagnostics::{AccessKind, RegionName}; use self::location::LocationTable; @@ -47,9 +64,10 @@ use facts::AllFacts; use self::path_utils::*; mod borrow_set; +mod borrowck_errors; mod constraint_generation; mod constraints; -pub mod consumers; +mod dataflow; mod def_use; mod diagnostics; mod facts; @@ -67,15 +85,19 @@ mod type_check; mod universal_regions; mod used_muts; -crate use borrow_set::{BorrowData, BorrowSet}; -crate use nll::{PoloniusOutput, ToRegionVid}; -crate use place_ext::PlaceExt; -crate use places_conflict::{places_conflict, PlaceConflictBias}; -crate use region_infer::RegionInferenceContext; +// A public API provided for the Rust compiler consumers. +pub mod consumers; + +use borrow_set::{BorrowData, BorrowSet}; +use dataflow::{BorrowIndex, BorrowckFlowState as Flows, BorrowckResults, Borrows}; +use nll::{PoloniusOutput, ToRegionVid}; +use place_ext::PlaceExt; +use places_conflict::{places_conflict, PlaceConflictBias}; +use region_infer::RegionInferenceContext; // FIXME(eddyb) perhaps move this somewhere more centrally. #[derive(Debug)] -crate struct Upvar<'tcx> { +struct Upvar<'tcx> { place: CapturedPlace<'tcx>, /// If true, the capture is behind a reference. @@ -122,6 +144,7 @@ fn mir_borrowck<'tcx>( /// If `return_body_with_facts` is true, then return the body with non-erased /// region ids on which the borrow checking was performed together with Polonius /// facts. +#[instrument(skip(infcx, input_body, input_promoted), level = "debug")] fn do_mir_borrowck<'a, 'tcx>( infcx: &InferCtxt<'a, 'tcx>, input_body: &Body<'tcx>, @@ -130,12 +153,7 @@ fn do_mir_borrowck<'a, 'tcx>( ) -> (BorrowCheckResult<'tcx>, Option>>) { let def = input_body.source.with_opt_param().as_local().unwrap(); - debug!("do_mir_borrowck(def = {:?})", def); - - assert!( - !return_body_with_facts || infcx.tcx.sess.opts.debugging_opts.polonius, - "borrowck facts can be requested only when Polonius is enabled" - ); + debug!(?def); let tcx = infcx.tcx; let param_env = tcx.param_env(def.did); @@ -213,6 +231,8 @@ fn do_mir_borrowck<'a, 'tcx>( let borrow_set = Rc::new(BorrowSet::build(tcx, body, locals_are_invalidated_at_exit, &mdpe.move_data)); + let use_polonius = return_body_with_facts || infcx.tcx.sess.opts.debugging_opts.polonius; + // Compute non-lexical lifetimes. let nll::NllOutput { regioncx, @@ -232,6 +252,7 @@ fn do_mir_borrowck<'a, 'tcx>( &mdpe.move_data, &borrow_set, &upvars, + use_polonius, ); // Dump MIR results into a file, if that is enabled. This let us @@ -256,26 +277,26 @@ fn do_mir_borrowck<'a, 'tcx>( let regioncx = Rc::new(regioncx); - let flow_borrows = Borrows::new(tcx, &body, ®ioncx, &borrow_set) - .into_engine(tcx, &body) + let flow_borrows = Borrows::new(tcx, body, ®ioncx, &borrow_set) + .into_engine(tcx, body) .pass_name("borrowck") .iterate_to_fixpoint(); - let flow_uninits = MaybeUninitializedPlaces::new(tcx, &body, &mdpe) - .into_engine(tcx, &body) + let flow_uninits = MaybeUninitializedPlaces::new(tcx, body, &mdpe) + .into_engine(tcx, body) .pass_name("borrowck") .iterate_to_fixpoint(); - let flow_ever_inits = EverInitializedPlaces::new(tcx, &body, &mdpe) - .into_engine(tcx, &body) + let flow_ever_inits = EverInitializedPlaces::new(tcx, body, &mdpe) + .into_engine(tcx, body) .pass_name("borrowck") .iterate_to_fixpoint(); - let movable_generator = match tcx.hir().get(id) { + let movable_generator = !matches!( + tcx.hir().get(id), Node::Expr(&hir::Expr { kind: hir::ExprKind::Closure(.., Some(hir::Movability::Static)), .. - }) => false, - _ => true, - }; + }) + ); for (idx, move_data_results) in promoted_errors { let promoted_body = &promoted[idx]; @@ -352,9 +373,9 @@ fn do_mir_borrowck<'a, 'tcx>( mbcx.report_move_errors(move_errors); - dataflow::visit_results( - &body, - traversal::reverse_postorder(&body).map(|(bb, _)| bb), + rustc_mir_dataflow::visit_results( + body, + traversal::reverse_postorder(body).map(|(bb, _)| bb), &results, &mut mbcx, ); @@ -495,8 +516,8 @@ pub struct BodyWithBorrowckFacts<'tcx> { pub location_table: LocationTable, } -crate struct MirBorrowckCtxt<'cx, 'tcx> { - crate infcx: &'cx InferCtxt<'cx, 'tcx>, +struct MirBorrowckCtxt<'cx, 'tcx> { + infcx: &'cx InferCtxt<'cx, 'tcx>, param_env: ParamEnv<'tcx>, body: &'cx Body<'tcx>, move_data: &'cx MoveData<'tcx>, @@ -594,7 +615,7 @@ crate struct MirBorrowckCtxt<'cx, 'tcx> { // 2. loans made in overlapping scopes do not conflict // 3. assignments do not affect things loaned out as immutable // 4. moves do not affect things loaned out in any way -impl<'cx, 'tcx> dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtxt<'cx, 'tcx> { +impl<'cx, 'tcx> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtxt<'cx, 'tcx> { type FlowState = Flows<'cx, 'tcx>; fn visit_statement_before_primary_effect( @@ -1341,7 +1362,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { Rvalue::Use(ref operand) | Rvalue::Repeat(ref operand, _) | Rvalue::UnaryOp(_ /*un_op*/, ref operand) - | Rvalue::Cast(_ /*cast_kind*/, ref operand, _ /*ty*/) => { + | Rvalue::Cast(_ /*cast_kind*/, ref operand, _ /*ty*/) + | Rvalue::ShallowInitBox(ref operand, _ /*ty*/) => { self.consume_operand(location, (operand, span), flow_state) } @@ -2344,7 +2366,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { /// then returns the index of the field being projected. Note that this closure will always /// be `self` in the current MIR, because that is the only time we directly access the fields /// of a closure type. - pub fn is_upvar_field_projection(&self, place_ref: PlaceRef<'tcx>) -> Option { + fn is_upvar_field_projection(&self, place_ref: PlaceRef<'tcx>) -> Option { path_utils::is_upvar_field_projection(self.infcx.tcx, &self.upvars, place_ref, self.body()) } } diff --git a/compiler/rustc_mir/src/borrow_check/location.rs b/compiler/rustc_borrowck/src/location.rs similarity index 100% rename from compiler/rustc_mir/src/borrow_check/location.rs rename to compiler/rustc_borrowck/src/location.rs diff --git a/compiler/rustc_mir/src/borrow_check/member_constraints.rs b/compiler/rustc_borrowck/src/member_constraints.rs similarity index 99% rename from compiler/rustc_mir/src/borrow_check/member_constraints.rs rename to compiler/rustc_borrowck/src/member_constraints.rs index 2e2578df01..f22d355e61 100644 --- a/compiler/rustc_mir/src/borrow_check/member_constraints.rs +++ b/compiler/rustc_borrowck/src/member_constraints.rs @@ -144,7 +144,7 @@ impl MemberConstraintSet<'tcx, R> where R: Copy + Hash + Eq, { - crate fn all_indices(&self) -> impl Iterator { + crate fn all_indices(&self) -> impl Iterator + '_ { self.constraints.indices() } diff --git a/compiler/rustc_mir/src/borrow_check/nll.rs b/compiler/rustc_borrowck/src/nll.rs similarity index 93% rename from compiler/rustc_mir/src/borrow_check/nll.rs rename to compiler/rustc_borrowck/src/nll.rs index 66ca94d3b4..e5924f9d08 100644 --- a/compiler/rustc_mir/src/borrow_check/nll.rs +++ b/compiler/rustc_borrowck/src/nll.rs @@ -4,6 +4,7 @@ use rustc_data_structures::vec_map::VecMap; use rustc_errors::Diagnostic; use rustc_index::vec::IndexVec; use rustc_infer::infer::InferCtxt; +use rustc_middle::mir::{create_dump_file, dump_enabled, dump_mir, PassWhere}; use rustc_middle::mir::{ BasicBlock, Body, ClosureOutlivesSubject, ClosureRegionRequirements, LocalKind, Location, Promoted, @@ -17,16 +18,13 @@ use std::path::PathBuf; use std::rc::Rc; use std::str::FromStr; -use self::mir_util::PassWhere; use polonius_engine::{Algorithm, Output}; -use crate::dataflow::impls::MaybeInitializedPlaces; -use crate::dataflow::move_paths::{InitKind, InitLocation, MoveData}; -use crate::dataflow::ResultsCursor; -use crate::util as mir_util; -use crate::util::pretty; +use rustc_mir_dataflow::impls::MaybeInitializedPlaces; +use rustc_mir_dataflow::move_paths::{InitKind, InitLocation, MoveData}; +use rustc_mir_dataflow::ResultsCursor; -use crate::borrow_check::{ +use crate::{ borrow_set::BorrowSet, constraint_generation, diagnostics::RegionErrors, @@ -56,7 +54,8 @@ crate struct NllOutput<'tcx> { /// Rewrites the regions in the MIR to use NLL variables, also scraping out the set of universal /// regions (e.g., region parameters) declared on the function. That set will need to be given to /// `compute_regions`. -pub(in crate::borrow_check) fn replace_regions_in_mir<'cx, 'tcx>( +#[instrument(skip(infcx, param_env, body, promoted), level = "debug")] +pub(crate) fn replace_regions_in_mir<'cx, 'tcx>( infcx: &InferCtxt<'cx, 'tcx>, param_env: ty::ParamEnv<'tcx>, body: &mut Body<'tcx>, @@ -64,7 +63,7 @@ pub(in crate::borrow_check) fn replace_regions_in_mir<'cx, 'tcx>( ) -> UniversalRegions<'tcx> { let def = body.source.with_opt_param().as_local().unwrap(); - debug!("replace_regions_in_mir(def={:?})", def); + debug!(?def); // Compute named region information. This also renumbers the inputs/outputs. let universal_regions = UniversalRegions::new(infcx, def, param_env); @@ -72,7 +71,7 @@ pub(in crate::borrow_check) fn replace_regions_in_mir<'cx, 'tcx>( // Replace all remaining regions with fresh inference variables. renumber::renumber_mir(infcx, body, promoted); - mir_util::dump_mir(infcx.tcx, None, "renumber", &0, body, |_, _| Ok(())); + dump_mir(infcx.tcx, None, "renumber", &0, body, |_, _| Ok(())); universal_regions } @@ -155,7 +154,7 @@ fn populate_polonius_move_facts( /// Computes the (non-lexical) regions from the input MIR. /// /// This may result in errors being reported. -pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>( +pub(crate) fn compute_regions<'cx, 'tcx>( infcx: &InferCtxt<'cx, 'tcx>, universal_regions: UniversalRegions<'tcx>, body: &Body<'tcx>, @@ -166,8 +165,10 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>( move_data: &MoveData<'tcx>, borrow_set: &BorrowSet<'tcx>, upvars: &[Upvar<'tcx>], + use_polonius: bool, ) -> NllOutput<'tcx> { - let mut all_facts = AllFacts::enabled(infcx.tcx).then_some(AllFacts::default()); + let mut all_facts = + (use_polonius || AllFacts::enabled(infcx.tcx)).then_some(AllFacts::default()); let universal_regions = Rc::new(universal_regions); @@ -283,7 +284,7 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>( all_facts.write_to_dir(dir_path, location_table).unwrap(); } - if infcx.tcx.sess.opts.debugging_opts.polonius { + if use_polonius { let algorithm = env::var("POLONIUS_ALGORITHM").unwrap_or_else(|_| String::from("Hybrid")); let algorithm = Algorithm::from_str(&algorithm).unwrap(); @@ -322,11 +323,11 @@ pub(super) fn dump_mir_results<'a, 'tcx>( regioncx: &RegionInferenceContext<'tcx>, closure_region_requirements: &Option>, ) { - if !mir_util::dump_enabled(infcx.tcx, "nll", body.source.def_id()) { + if !dump_enabled(infcx.tcx, "nll", body.source.def_id()) { return; } - mir_util::dump_mir(infcx.tcx, None, "nll", &0, body, |pass_where, out| { + dump_mir(infcx.tcx, None, "nll", &0, body, |pass_where, out| { match pass_where { // Before the CFG, dump out the values for each region variable. PassWhere::BeforeCFG => { @@ -354,14 +355,14 @@ pub(super) fn dump_mir_results<'a, 'tcx>( // Also dump the inference graph constraints as a graphviz file. let _: io::Result<()> = try { let mut file = - pretty::create_dump_file(infcx.tcx, "regioncx.all.dot", None, "nll", &0, body.source)?; + create_dump_file(infcx.tcx, "regioncx.all.dot", None, "nll", &0, body.source)?; regioncx.dump_graphviz_raw_constraints(&mut file)?; }; // Also dump the inference graph constraints as a graphviz file. let _: io::Result<()> = try { let mut file = - pretty::create_dump_file(infcx.tcx, "regioncx.scc.dot", None, "nll", &0, body.source)?; + create_dump_file(infcx.tcx, "regioncx.scc.dot", None, "nll", &0, body.source)?; regioncx.dump_graphviz_scc_constraints(&mut file)?; }; } diff --git a/compiler/rustc_mir/src/borrow_check/path_utils.rs b/compiler/rustc_borrowck/src/path_utils.rs similarity index 96% rename from compiler/rustc_mir/src/borrow_check/path_utils.rs rename to compiler/rustc_borrowck/src/path_utils.rs index 80de3b4e36..d5d00b467e 100644 --- a/compiler/rustc_mir/src/borrow_check/path_utils.rs +++ b/compiler/rustc_borrowck/src/path_utils.rs @@ -1,8 +1,8 @@ -use crate::borrow_check::borrow_set::{BorrowData, BorrowSet, TwoPhaseActivation}; -use crate::borrow_check::places_conflict; -use crate::borrow_check::AccessDepth; -use crate::borrow_check::Upvar; -use crate::dataflow::indexes::BorrowIndex; +use crate::borrow_set::{BorrowData, BorrowSet, TwoPhaseActivation}; +use crate::places_conflict; +use crate::AccessDepth; +use crate::BorrowIndex; +use crate::Upvar; use rustc_data_structures::graph::dominators::Dominators; use rustc_middle::mir::BorrowKind; use rustc_middle::mir::{BasicBlock, Body, Field, Location, Place, PlaceRef, ProjectionElem}; diff --git a/compiler/rustc_mir/src/borrow_check/place_ext.rs b/compiler/rustc_borrowck/src/place_ext.rs similarity index 98% rename from compiler/rustc_mir/src/borrow_check/place_ext.rs rename to compiler/rustc_borrowck/src/place_ext.rs index 52fac3e53e..83ff1595b0 100644 --- a/compiler/rustc_mir/src/borrow_check/place_ext.rs +++ b/compiler/rustc_borrowck/src/place_ext.rs @@ -1,4 +1,4 @@ -use crate::borrow_check::borrow_set::LocalsStateAtExit; +use crate::borrow_set::LocalsStateAtExit; use rustc_hir as hir; use rustc_middle::mir::ProjectionElem; use rustc_middle::mir::{Body, Mutability, Place}; diff --git a/compiler/rustc_mir/src/borrow_check/places_conflict.rs b/compiler/rustc_borrowck/src/places_conflict.rs similarity index 99% rename from compiler/rustc_mir/src/borrow_check/places_conflict.rs rename to compiler/rustc_borrowck/src/places_conflict.rs index d21550a8e1..773e9e90b0 100644 --- a/compiler/rustc_mir/src/borrow_check/places_conflict.rs +++ b/compiler/rustc_borrowck/src/places_conflict.rs @@ -1,6 +1,6 @@ -use crate::borrow_check::ArtificialField; -use crate::borrow_check::Overlap; -use crate::borrow_check::{AccessDepth, Deep, Shallow}; +use crate::ArtificialField; +use crate::Overlap; +use crate::{AccessDepth, Deep, Shallow}; use rustc_hir as hir; use rustc_middle::mir::{Body, BorrowKind, Local, Place, PlaceElem, PlaceRef, ProjectionElem}; use rustc_middle::ty::{self, TyCtxt}; diff --git a/compiler/rustc_mir/src/borrow_check/prefixes.rs b/compiler/rustc_borrowck/src/prefixes.rs similarity index 100% rename from compiler/rustc_mir/src/borrow_check/prefixes.rs rename to compiler/rustc_borrowck/src/prefixes.rs diff --git a/compiler/rustc_mir/src/borrow_check/region_infer/dump_mir.rs b/compiler/rustc_borrowck/src/region_infer/dump_mir.rs similarity index 98% rename from compiler/rustc_mir/src/borrow_check/region_infer/dump_mir.rs rename to compiler/rustc_borrowck/src/region_infer/dump_mir.rs index 213ebff12a..cfd3acb6bd 100644 --- a/compiler/rustc_mir/src/borrow_check/region_infer/dump_mir.rs +++ b/compiler/rustc_borrowck/src/region_infer/dump_mir.rs @@ -4,7 +4,7 @@ //! context internal state. use super::{OutlivesConstraint, RegionInferenceContext}; -use crate::borrow_check::type_check::Locations; +use crate::type_check::Locations; use rustc_infer::infer::NllRegionVariableOrigin; use rustc_middle::ty::TyCtxt; use std::io::{self, Write}; diff --git a/compiler/rustc_mir/src/borrow_check/region_infer/graphviz.rs b/compiler/rustc_borrowck/src/region_infer/graphviz.rs similarity index 98% rename from compiler/rustc_mir/src/borrow_check/region_infer/graphviz.rs rename to compiler/rustc_borrowck/src/region_infer/graphviz.rs index b944d74e6f..95048d50f1 100644 --- a/compiler/rustc_mir/src/borrow_check/region_infer/graphviz.rs +++ b/compiler/rustc_borrowck/src/region_infer/graphviz.rs @@ -6,7 +6,7 @@ use std::borrow::Cow; use std::io::{self, Write}; use super::*; -use crate::borrow_check::constraints::OutlivesConstraint; +use crate::constraints::OutlivesConstraint; use rustc_graphviz as dot; impl<'tcx> RegionInferenceContext<'tcx> { diff --git a/compiler/rustc_mir/src/borrow_check/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs similarity index 95% rename from compiler/rustc_mir/src/borrow_check/region_infer/mod.rs rename to compiler/rustc_borrowck/src/region_infer/mod.rs index a96cdbc13f..21c26af817 100644 --- a/compiler/rustc_mir/src/borrow_check/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -5,7 +5,8 @@ use rustc_data_structures::binary_search_util; use rustc_data_structures::frozen::Frozen; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::graph::scc::Sccs; -use rustc_hir::def_id::DefId; +use rustc_hir::def_id::{DefId, CRATE_DEF_ID}; +use rustc_hir::CRATE_HIR_ID; use rustc_index::vec::IndexVec; use rustc_infer::infer::canonical::QueryOutlivesConstraint; use rustc_infer::infer::region_constraints::{GenericKind, VarInfos, VerifyBound}; @@ -14,10 +15,12 @@ use rustc_middle::mir::{ Body, ClosureOutlivesRequirement, ClosureOutlivesSubject, ClosureRegionRequirements, ConstraintCategory, Local, Location, ReturnConstraint, }; +use rustc_middle::traits::ObligationCause; +use rustc_middle::traits::ObligationCauseCode; use rustc_middle::ty::{self, subst::SubstsRef, RegionVid, Ty, TyCtxt, TypeFoldable}; use rustc_span::Span; -use crate::borrow_check::{ +use crate::{ constraints::{ graph::NormalConstraintGraph, ConstraintSccIndex, OutlivesConstraint, OutlivesConstraintSet, }, @@ -85,7 +88,7 @@ pub struct RegionInferenceContext<'tcx> { FxHashMap>, /// Map universe indexes to information on why we created it. - universe_causes: IndexVec>, + universe_causes: FxHashMap>, /// Contains the minimum universe of any variable within the same /// SCC. We will ensure that no SCC contains values that are not @@ -132,33 +135,33 @@ pub(crate) struct AppliedMemberConstraint { /// /// The vector if `AppliedMemberConstraint` elements is kept sorted /// by this field. - pub(in crate::borrow_check) member_region_scc: ConstraintSccIndex, + pub(crate) member_region_scc: ConstraintSccIndex, /// The "best option" that `apply_member_constraint` found -- this was /// added as an "ad-hoc" lower-bound to `member_region_scc`. - pub(in crate::borrow_check) min_choice: ty::RegionVid, + pub(crate) min_choice: ty::RegionVid, /// The "member constraint index" -- we can find out details about /// the constraint from /// `set.member_constraints[member_constraint_index]`. - pub(in crate::borrow_check) member_constraint_index: NllMemberConstraintIndex, + pub(crate) member_constraint_index: NllMemberConstraintIndex, } pub(crate) struct RegionDefinition<'tcx> { /// What kind of variable is this -- a free region? existential /// variable? etc. (See the `NllRegionVariableOrigin` for more /// info.) - pub(in crate::borrow_check) origin: NllRegionVariableOrigin, + pub(crate) origin: NllRegionVariableOrigin, /// Which universe is this region variable defined in? This is /// most often `ty::UniverseIndex::ROOT`, but when we encounter /// forall-quantifiers like `for<'a> { 'a = 'b }`, we would create /// the variable for `'a` in a fresh universe that extends ROOT. - pub(in crate::borrow_check) universe: ty::UniverseIndex, + pub(crate) universe: ty::UniverseIndex, /// If this is 'static or an early-bound region, then this is /// `Some(X)` where `X` is the name of the region. - pub(in crate::borrow_check) external_name: Option>, + pub(crate) external_name: Option>, } /// N.B., the variants in `Cause` are intentionally ordered. Lower @@ -245,7 +248,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { /// /// The `outlives_constraints` and `type_tests` are an initial set /// of constraints produced by the MIR type check. - pub(in crate::borrow_check) fn new( + pub(crate) fn new( var_infos: VarInfos, universal_regions: Rc>, placeholder_indices: Rc, @@ -256,7 +259,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { Location, FxHashMap<(RegionVid, RegionVid), (ConstraintCategory, Span)>, >, - universe_causes: IndexVec>, + universe_causes: FxHashMap>, type_tests: Vec>, liveness_constraints: LivenessValues, elements: &Rc, @@ -494,7 +497,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { } /// Returns an iterator over all the region indices. - pub fn regions(&self) -> impl Iterator { + pub fn regions(&self) -> impl Iterator + '_ { self.definitions.indices() } @@ -534,7 +537,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { /// Once region solving has completed, this function will return /// the member constraints that were applied to the value of a given /// region `r`. See `AppliedMemberConstraint`. - pub(in crate::borrow_check) fn applied_member_constraints( + pub(crate) fn applied_member_constraints( &self, r: impl ToRegionVid, ) -> &[AppliedMemberConstraint] { @@ -549,6 +552,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { /// Performs region inference and report errors if we see any /// unsatisfiable constraints. If this is a closure, returns the /// region requirements to propagate to our creator, if any. + #[instrument(skip(self, infcx, body, polonius_output), level = "debug")] pub(super) fn solve( &mut self, infcx: &InferCtxt<'_, 'tcx>, @@ -604,10 +608,9 @@ impl<'tcx> RegionInferenceContext<'tcx> { /// for each region variable until all the constraints are /// satisfied. Note that some values may grow **too** large to be /// feasible, but we check this later. + #[instrument(skip(self, _body), level = "debug")] fn propagate_constraints(&mut self, _body: &Body<'tcx>) { - debug!("propagate_constraints()"); - - debug!("propagate_constraints: constraints={:#?}", { + debug!("constraints={:#?}", { let mut constraints: Vec<_> = self.constraints.outlives().iter().collect(); constraints.sort(); constraints @@ -634,12 +637,13 @@ impl<'tcx> RegionInferenceContext<'tcx> { /// computed, by unioning the values of its successors. /// Assumes that all successors have been computed already /// (which is assured by iterating over SCCs in dependency order). + #[instrument(skip(self), level = "debug")] fn compute_value_for_scc(&mut self, scc_a: ConstraintSccIndex) { let constraint_sccs = self.constraint_sccs.clone(); // Walk each SCC `B` such that `A: B`... for &scc_b in constraint_sccs.successors(scc_a) { - debug!("propagate_constraint_sccs: scc_a = {:?} scc_b = {:?}", scc_a, scc_b); + debug!(?scc_b); // ...and add elements from `B` into `A`. One complication // arises because of universes: If `B` contains something @@ -660,11 +664,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { self.apply_member_constraint(scc_a, m_c_i, member_constraints.choice_regions(m_c_i)); } - debug!( - "propagate_constraint_sccs: scc_a = {:?} has value {:?}", - scc_a, - self.scc_values.region_value_str(scc_a), - ); + debug!(value = ?self.scc_values.region_value_str(scc_a)); } /// Invoked for each `R0 member of [R1..Rn]` constraint. @@ -678,14 +678,13 @@ impl<'tcx> RegionInferenceContext<'tcx> { /// is considered a *lower bound*. If possible, we will modify /// the constraint to set it equal to one of the option regions. /// If we make any changes, returns true, else false. + #[instrument(skip(self, member_constraint_index), level = "debug")] fn apply_member_constraint( &mut self, scc: ConstraintSccIndex, member_constraint_index: NllMemberConstraintIndex, choice_regions: &[ty::RegionVid], ) -> bool { - debug!("apply_member_constraint(scc={:?}, choice_regions={:#?})", scc, choice_regions,); - // Create a mutable vector of the options. We'll try to winnow // them down. let mut choice_regions: Vec = choice_regions.to_vec(); @@ -711,7 +710,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { .universal_regions_outlived_by(scc) .all(|lb| self.universal_region_relations.outlives(o_r, lb)) }); - debug!("apply_member_constraint: after lb, choice_regions={:?}", choice_regions); + debug!(?choice_regions, "after lb"); // Now find all the *upper bounds* -- that is, each UB is a // free region that must outlive the member region `R0` (`UB: @@ -720,10 +719,10 @@ impl<'tcx> RegionInferenceContext<'tcx> { let rev_scc_graph = self.reverse_scc_graph(); let universal_region_relations = &self.universal_region_relations; for ub in rev_scc_graph.upper_bounds(scc) { - debug!("apply_member_constraint: ub={:?}", ub); + debug!(?ub); choice_regions.retain(|&o_r| universal_region_relations.outlives(ub, o_r)); } - debug!("apply_member_constraint: after ub, choice_regions={:?}", choice_regions); + debug!(?choice_regions, "after ub"); // If we ruled everything out, we're done. if choice_regions.is_empty() { @@ -732,7 +731,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { // Otherwise, we need to find the minimum remaining choice, if // any, and take that. - debug!("apply_member_constraint: choice_regions remaining are {:#?}", choice_regions); + debug!("choice_regions remaining are {:#?}", choice_regions); let min = |r1: ty::RegionVid, r2: ty::RegionVid| -> Option { let r1_outlives_r2 = self.universal_region_relations.outlives(r1, r2); let r2_outlives_r1 = self.universal_region_relations.outlives(r2, r1); @@ -745,27 +744,18 @@ impl<'tcx> RegionInferenceContext<'tcx> { }; let mut min_choice = choice_regions[0]; for &other_option in &choice_regions[1..] { - debug!( - "apply_member_constraint: min_choice={:?} other_option={:?}", - min_choice, other_option, - ); + debug!(?min_choice, ?other_option,); match min(min_choice, other_option) { Some(m) => min_choice = m, None => { - debug!( - "apply_member_constraint: {:?} and {:?} are incomparable; no min choice", - min_choice, other_option, - ); + debug!(?min_choice, ?other_option, "incomparable; no min choice",); return false; } } } let min_choice_scc = self.constraint_sccs.scc(min_choice); - debug!( - "apply_member_constraint: min_choice={:?} best_choice_scc={:?}", - min_choice, min_choice_scc, - ); + debug!(?min_choice, ?min_choice_scc); if self.scc_values.add_region(scc, min_choice_scc) { self.member_constraints_applied.push(AppliedMemberConstraint { member_region_scc: scc, @@ -1088,8 +1078,9 @@ impl<'tcx> RegionInferenceContext<'tcx> { /// include the CFG anyhow. /// - For each `end('x)` element in `'r`, compute the mutual LUB, yielding /// a result `'y`. - pub(in crate::borrow_check) fn universal_upper_bound(&self, r: RegionVid) -> RegionVid { - debug!("universal_upper_bound(r={:?}={})", r, self.region_value_str(r)); + #[instrument(skip(self), level = "debug")] + pub(crate) fn universal_upper_bound(&self, r: RegionVid) -> RegionVid { + debug!(r = %self.region_value_str(r)); // Find the smallest universal region that contains all other // universal regions within `region`. @@ -1099,7 +1090,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { lub = self.universal_region_relations.postdom_upper_bound(lub, ur); } - debug!("universal_upper_bound: r={:?} lub={:?}", r, lub); + debug!(?lub); lub } @@ -1115,7 +1106,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { /// Therefore, this method should only be used in diagnostic code, /// where displaying *some* named universal region is better than /// falling back to 'static. - pub(in crate::borrow_check) fn approx_universal_upper_bound(&self, r: RegionVid) -> RegionVid { + pub(crate) fn approx_universal_upper_bound(&self, r: RegionVid) -> RegionVid { debug!("approx_universal_upper_bound(r={:?}={})", r, self.region_value_str(r)); // Find the smallest universal region that contains all other @@ -1259,9 +1250,8 @@ impl<'tcx> RegionInferenceContext<'tcx> { } // Evaluate whether `sup_region: sub_region`. + #[instrument(skip(self), level = "debug")] fn eval_outlives(&self, sup_region: RegionVid, sub_region: RegionVid) -> bool { - debug!("eval_outlives({:?}: {:?})", sup_region, sub_region); - debug!( "eval_outlives: sup_region's value = {:?} universal={:?}", self.region_value_str(sup_region), @@ -1464,6 +1454,10 @@ impl<'tcx> RegionInferenceContext<'tcx> { /// /// Things that are to be propagated are accumulated into the /// `outlives_requirements` vector. + #[instrument( + skip(self, body, propagated_outlives_requirements, errors_buffer), + level = "debug" + )] fn check_universal_region( &self, body: &Body<'tcx>, @@ -1471,8 +1465,6 @@ impl<'tcx> RegionInferenceContext<'tcx> { propagated_outlives_requirements: &mut Option<&mut Vec>>, errors_buffer: &mut RegionErrors<'tcx>, ) { - debug!("check_universal_region(fr={:?})", longer_fr); - let longer_fr_scc = self.constraint_sccs.scc(longer_fr); // Because this free region must be in the ROOT universe, we @@ -1596,7 +1588,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { propagated_outlives_requirements.push(ClosureOutlivesRequirement { subject: ClosureOutlivesSubject::Region(fr_minus), outlived_free_region: fr, - blame_span: blame_span_category.1, + blame_span: blame_span_category.1.span, category: blame_span_category.0, }); } @@ -1738,8 +1730,8 @@ impl<'tcx> RegionInferenceContext<'tcx> { return BlameConstraint { category: constraint.category, from_closure: false, - span, - variance_info: constraint.variance_info.clone(), + cause: ObligationCause::dummy_with_span(span), + variance_info: constraint.variance_info, }; } Locations::Single(loc) => loc, @@ -1751,30 +1743,30 @@ impl<'tcx> RegionInferenceContext<'tcx> { .map(|&(category, span)| BlameConstraint { category, from_closure: true, - span: span, - variance_info: constraint.variance_info.clone(), + cause: ObligationCause::dummy_with_span(span), + variance_info: constraint.variance_info, }) .unwrap_or(BlameConstraint { category: constraint.category, from_closure: false, - span: body.source_info(loc).span, - variance_info: constraint.variance_info.clone(), + cause: ObligationCause::dummy_with_span(body.source_info(loc).span), + variance_info: constraint.variance_info, }) } - /// Finds a good span to blame for the fact that `fr1` outlives `fr2`. + /// Finds a good `ObligationCause` to blame for the fact that `fr1` outlives `fr2`. crate fn find_outlives_blame_span( &self, body: &Body<'tcx>, fr1: RegionVid, fr1_origin: NllRegionVariableOrigin, fr2: RegionVid, - ) -> (ConstraintCategory, Span) { - let BlameConstraint { category, span, .. } = + ) -> (ConstraintCategory, ObligationCause<'tcx>) { + let BlameConstraint { category, cause, .. } = self.best_blame_constraint(body, fr1, fr1_origin, |r| { self.provides_universal_region(r, fr1, fr2) }); - (category, span) + (category, cause) } /// Walks the graph of constraints (where `'a: 'b` is considered @@ -1877,21 +1869,13 @@ impl<'tcx> RegionInferenceContext<'tcx> { } /// Finds some region R such that `fr1: R` and `R` is live at `elem`. + #[instrument(skip(self), level = "trace")] crate fn find_sub_region_live_at(&self, fr1: RegionVid, elem: Location) -> RegionVid { - debug!("find_sub_region_live_at(fr1={:?}, elem={:?})", fr1, elem); - debug!("find_sub_region_live_at: {:?} is in scc {:?}", fr1, self.constraint_sccs.scc(fr1)); - debug!( - "find_sub_region_live_at: {:?} is in universe {:?}", - fr1, - self.scc_universes[self.constraint_sccs.scc(fr1)] - ); + trace!(scc = ?self.constraint_sccs.scc(fr1)); + trace!(universe = ?self.scc_universes[self.constraint_sccs.scc(fr1)]); self.find_constraint_paths_between_regions(fr1, |r| { // First look for some `r` such that `fr1: r` and `r` is live at `elem` - debug!( - "find_sub_region_live_at: liveness_constraints for {:?} are {:?}", - r, - self.liveness_constraints.region_value_str(r), - ); + trace!(?r, liveness_constraints=?self.liveness_constraints.region_value_str(r)); self.liveness_constraints.contains(r, elem) }) .or_else(|| { @@ -1990,6 +1974,27 @@ impl<'tcx> RegionInferenceContext<'tcx> { .collect::>() ); + // We try to avoid reporting a `ConstraintCategory::Predicate` as our best constraint. + // Instead, we use it to produce an improved `ObligationCauseCode`. + // FIXME - determine what we should do if we encounter multiple `ConstraintCategory::Predicate` + // constraints. Currently, we just pick the first one. + let cause_code = path + .iter() + .find_map(|constraint| { + if let ConstraintCategory::Predicate(predicate_span) = constraint.category { + // We currentl'y doesn't store the `DefId` in the `ConstraintCategory` + // for perforamnce reasons. The error reporting code used by NLL only + // uses the span, so this doesn't cause any problems at the moment. + Some(ObligationCauseCode::BindingObligation( + CRATE_DEF_ID.to_def_id(), + predicate_span, + )) + } else { + None + } + }) + .unwrap_or_else(|| ObligationCauseCode::MiscObligation); + // Classify each of the constraints along the path. let mut categorized_path: Vec> = path .iter() @@ -2000,8 +2005,12 @@ impl<'tcx> RegionInferenceContext<'tcx> { BlameConstraint { category: constraint.category, from_closure: false, - span: constraint.locations.span(body), - variance_info: constraint.variance_info.clone(), + cause: ObligationCause::new( + constraint.locations.span(body), + CRATE_HIR_ID, + cause_code.clone(), + ), + variance_info: constraint.variance_info, } } }) @@ -2083,7 +2092,8 @@ impl<'tcx> RegionInferenceContext<'tcx> { ConstraintCategory::OpaqueType | ConstraintCategory::Boring | ConstraintCategory::BoringNoLocation - | ConstraintCategory::Internal => false, + | ConstraintCategory::Internal + | ConstraintCategory::Predicate(_) => false, ConstraintCategory::TypeAnnotation | ConstraintCategory::Return(_) | ConstraintCategory::Yield => true, @@ -2094,7 +2104,8 @@ impl<'tcx> RegionInferenceContext<'tcx> { ConstraintCategory::OpaqueType | ConstraintCategory::Boring | ConstraintCategory::BoringNoLocation - | ConstraintCategory::Internal => false, + | ConstraintCategory::Internal + | ConstraintCategory::Predicate(_) => false, _ => true, } } @@ -2143,13 +2154,13 @@ impl<'tcx> RegionInferenceContext<'tcx> { // appears to be the most interesting point to report to the // user via an even more ad-hoc guess. categorized_path.sort_by(|p0, p1| p0.category.cmp(&p1.category)); - debug!("`: sorted_path={:#?}", categorized_path); + debug!("best_blame_constraint: sorted_path={:#?}", categorized_path); categorized_path.remove(0) } crate fn universe_info(&self, universe: ty::UniverseIndex) -> UniverseInfo<'tcx> { - self.universe_causes[universe].clone() + self.universe_causes[&universe].clone() } } @@ -2249,6 +2260,6 @@ impl<'tcx> ClosureRegionRequirementsExt<'tcx> for ClosureRegionRequirements<'tcx pub struct BlameConstraint<'tcx> { pub category: ConstraintCategory, pub from_closure: bool, - pub span: Span, + pub cause: ObligationCause<'tcx>, pub variance_info: ty::VarianceDiagInfo<'tcx>, } diff --git a/compiler/rustc_mir/src/borrow_check/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs similarity index 51% rename from compiler/rustc_mir/src/borrow_check/region_infer/opaque_types.rs rename to compiler/rustc_borrowck/src/region_infer/opaque_types.rs index 12fceeff08..4eb7be542e 100644 --- a/compiler/rustc_mir/src/borrow_check/region_infer/opaque_types.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs @@ -1,5 +1,9 @@ +use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::vec_map::VecMap; +use rustc_hir::OpaqueTyOrigin; +use rustc_infer::infer::opaque_types::OpaqueTypeDecl; use rustc_infer::infer::InferCtxt; +use rustc_middle::ty::subst::GenericArgKind; use rustc_middle::ty::{self, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable}; use rustc_span::Span; use rustc_trait_selection::opaque_types::InferCtxtExt; @@ -46,17 +50,18 @@ impl<'tcx> RegionInferenceContext<'tcx> { /// Calling `universal_upper_bound` for such a region gives `fr_fn_body`, /// which has no `external_name` in which case we use `'empty` as the /// region to pass to `infer_opaque_definition_from_instantiation`. - #[instrument(skip(self, infcx))] - pub(in crate::borrow_check) fn infer_opaque_types( + #[instrument(level = "debug", skip(self, infcx))] + pub(crate) fn infer_opaque_types( &self, infcx: &InferCtxt<'_, 'tcx>, - opaque_ty_decls: VecMap, Ty<'tcx>>, + opaque_ty_decls: VecMap, OpaqueTypeDecl<'tcx>>, span: Span, ) -> VecMap, Ty<'tcx>> { opaque_ty_decls .into_iter() - .map(|(opaque_type_key, concrete_type)| { + .filter_map(|(opaque_type_key, decl)| { let substs = opaque_type_key.substs; + let concrete_type = decl.concrete_ty; debug!(?concrete_type, ?substs); let mut subst_regions = vec![self.universal_regions.fr_static]; @@ -94,7 +99,13 @@ impl<'tcx> RegionInferenceContext<'tcx> { universal_concrete_type, span, ); - (opaque_type_key, remapped_type) + + check_opaque_type_parameter_valid( + infcx.tcx, + opaque_type_key, + OpaqueTypeDecl { concrete_ty: remapped_type, ..decl }, + ) + .then_some((opaque_type_key, remapped_type)) }) .collect() } @@ -105,7 +116,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { /// that the regions produced are in fact equal to the named region they are /// replaced with. This is fine because this function is only to improve the /// region names in error messages. - pub(in crate::borrow_check) fn name_regions(&self, tcx: TyCtxt<'tcx>, ty: T) -> T + pub(crate) fn name_regions(&self, tcx: TyCtxt<'tcx>, ty: T) -> T where T: TypeFoldable<'tcx>, { @@ -113,9 +124,116 @@ impl<'tcx> RegionInferenceContext<'tcx> { ty::ReVar(vid) => { // Find something that we can name let upper_bound = self.approx_universal_upper_bound(vid); - self.definitions[upper_bound].external_name.unwrap_or(region) + let upper_bound = &self.definitions[upper_bound]; + match upper_bound.external_name { + Some(reg) => reg, + None => { + // Nothing exact found, so we pick the first one that we find. + let scc = self.constraint_sccs.scc(vid); + for vid in self.rev_scc_graph.as_ref().unwrap().upper_bounds(scc) { + match self.definitions[vid].external_name { + None => {} + Some(&ty::ReStatic) => {} + Some(region) => return region, + } + } + region + } + } } _ => region, }) } } + +fn check_opaque_type_parameter_valid( + tcx: TyCtxt<'_>, + opaque_type_key: OpaqueTypeKey<'_>, + decl: OpaqueTypeDecl<'_>, +) -> bool { + match decl.origin { + // No need to check return position impl trait (RPIT) + // because for type and const parameters they are correct + // by construction: we convert + // + // fn foo() -> impl Trait + // + // into + // + // type Foo + // fn foo() -> Foo. + // + // For lifetime parameters we convert + // + // fn foo<'l0..'ln>() -> impl Trait<'l0..'lm> + // + // into + // + // type foo::<'p0..'pn>::Foo<'q0..'qm> + // fn foo() -> foo::<'static..'static>::Foo<'l0..'lm>. + // + // which would error here on all of the `'static` args. + OpaqueTyOrigin::FnReturn | OpaqueTyOrigin::AsyncFn => return true, + // Check these + OpaqueTyOrigin::TyAlias => {} + } + let span = decl.definition_span; + let opaque_generics = tcx.generics_of(opaque_type_key.def_id); + let mut seen_params: FxHashMap<_, Vec<_>> = FxHashMap::default(); + for (i, arg) in opaque_type_key.substs.iter().enumerate() { + let arg_is_param = match arg.unpack() { + GenericArgKind::Type(ty) => matches!(ty.kind(), ty::Param(_)), + GenericArgKind::Lifetime(ty::ReStatic) => { + tcx.sess + .struct_span_err(span, "non-defining opaque type use in defining scope") + .span_label( + tcx.def_span(opaque_generics.param_at(i, tcx).def_id), + "cannot use static lifetime; use a bound lifetime \ + instead or remove the lifetime parameter from the \ + opaque type", + ) + .emit(); + return false; + } + GenericArgKind::Lifetime(lt) => { + matches!(lt, ty::ReEarlyBound(_) | ty::ReFree(_)) + } + GenericArgKind::Const(ct) => matches!(ct.val, ty::ConstKind::Param(_)), + }; + + if arg_is_param { + seen_params.entry(arg).or_default().push(i); + } else { + // Prevent `fn foo() -> Foo` from being defining. + let opaque_param = opaque_generics.param_at(i, tcx); + tcx.sess + .struct_span_err(span, "non-defining opaque type use in defining scope") + .span_note( + tcx.def_span(opaque_param.def_id), + &format!( + "used non-generic {} `{}` for generic parameter", + opaque_param.kind.descr(), + arg, + ), + ) + .emit(); + return false; + } + } + + for (_, indices) in seen_params { + if indices.len() > 1 { + let descr = opaque_generics.param_at(indices[0], tcx).kind.descr(); + let spans: Vec<_> = indices + .into_iter() + .map(|i| tcx.def_span(opaque_generics.param_at(i, tcx).def_id)) + .collect(); + tcx.sess + .struct_span_err(span, "non-defining opaque type use in defining scope") + .span_note(spans, &format!("{} used multiple times", descr)) + .emit(); + return false; + } + } + true +} diff --git a/compiler/rustc_mir/src/borrow_check/region_infer/reverse_sccs.rs b/compiler/rustc_borrowck/src/region_infer/reverse_sccs.rs similarity index 95% rename from compiler/rustc_mir/src/borrow_check/region_infer/reverse_sccs.rs rename to compiler/rustc_borrowck/src/region_infer/reverse_sccs.rs index 5d345a6e63..056907dcb1 100644 --- a/compiler/rustc_mir/src/borrow_check/region_infer/reverse_sccs.rs +++ b/compiler/rustc_borrowck/src/region_infer/reverse_sccs.rs @@ -1,5 +1,5 @@ -use crate::borrow_check::constraints::ConstraintSccIndex; -use crate::borrow_check::RegionInferenceContext; +use crate::constraints::ConstraintSccIndex; +use crate::RegionInferenceContext; use itertools::Itertools; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::graph::vec_graph::VecGraph; diff --git a/compiler/rustc_mir/src/borrow_check/region_infer/values.rs b/compiler/rustc_borrowck/src/region_infer/values.rs similarity index 97% rename from compiler/rustc_mir/src/borrow_check/region_infer/values.rs rename to compiler/rustc_borrowck/src/region_infer/values.rs index 2864abde00..8819039c75 100644 --- a/compiler/rustc_mir/src/borrow_check/region_infer/values.rs +++ b/compiler/rustc_borrowck/src/region_infer/values.rs @@ -174,17 +174,19 @@ impl LivenessValues { self.points.contains(row, index) } + /// Returns an iterator of all the elements contained by the region `r` + crate fn get_elements(&self, row: N) -> impl Iterator + '_ { + self.points + .row(row) + .into_iter() + .flat_map(|set| set.iter()) + .take_while(move |&p| self.elements.point_in_range(p)) + .map(move |p| self.elements.to_location(p)) + } + /// Returns a "pretty" string value of the region. Meant for debugging. crate fn region_value_str(&self, r: N) -> String { - region_value_str( - self.points - .row(r) - .into_iter() - .flat_map(|set| set.iter()) - .take_while(|&p| self.elements.point_in_range(p)) - .map(|p| self.elements.to_location(p)) - .map(RegionElement::Location), - ) + region_value_str(self.get_elements(r).map(RegionElement::Location)) } } diff --git a/compiler/rustc_mir/src/borrow_check/renumber.rs b/compiler/rustc_borrowck/src/renumber.rs similarity index 82% rename from compiler/rustc_mir/src/borrow_check/renumber.rs rename to compiler/rustc_borrowck/src/renumber.rs index 9377473bef..20567610f6 100644 --- a/compiler/rustc_mir/src/borrow_check/renumber.rs +++ b/compiler/rustc_borrowck/src/renumber.rs @@ -7,13 +7,13 @@ use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable}; /// Replaces all free regions appearing in the MIR with fresh /// inference variables, returning the number of variables created. +#[instrument(skip(infcx, body, promoted), level = "debug")] pub fn renumber_mir<'tcx>( infcx: &InferCtxt<'_, 'tcx>, body: &mut Body<'tcx>, promoted: &mut IndexVec>, ) { - debug!("renumber_mir()"); - debug!("renumber_mir: body.arg_count={:?}", body.arg_count); + debug!(?body.arg_count); let mut visitor = NllVisitor { infcx }; @@ -26,12 +26,11 @@ pub fn renumber_mir<'tcx>( /// Replaces all regions appearing in `value` with fresh inference /// variables. +#[instrument(skip(infcx), level = "debug")] pub fn renumber_regions<'tcx, T>(infcx: &InferCtxt<'_, 'tcx>, value: T) -> T where T: TypeFoldable<'tcx>, { - debug!("renumber_regions(value={:?})", value); - infcx.tcx.fold_regions(value, &mut false, |_region, _depth| { let origin = NllRegionVariableOrigin::Existential { from_forall: false }; infcx.next_nll_region_var(origin) @@ -56,12 +55,11 @@ impl<'a, 'tcx> MutVisitor<'tcx> for NllVisitor<'a, 'tcx> { self.infcx.tcx } + #[instrument(skip(self), level = "debug")] fn visit_ty(&mut self, ty: &mut Ty<'tcx>, ty_context: TyContext) { - debug!("visit_ty(ty={:?}, ty_context={:?})", ty, ty_context); - *ty = self.renumber_regions(ty); - debug!("visit_ty: ty={:?}", ty); + debug!(?ty); } fn process_projection_elem( @@ -80,21 +78,19 @@ impl<'a, 'tcx> MutVisitor<'tcx> for NllVisitor<'a, 'tcx> { None } + #[instrument(skip(self), level = "debug")] fn visit_substs(&mut self, substs: &mut SubstsRef<'tcx>, location: Location) { - debug!("visit_substs(substs={:?}, location={:?})", substs, location); - *substs = self.renumber_regions(*substs); - debug!("visit_substs: substs={:?}", substs); + debug!(?substs); } + #[instrument(skip(self), level = "debug")] fn visit_region(&mut self, region: &mut ty::Region<'tcx>, location: Location) { - debug!("visit_region(region={:?}, location={:?})", region, location); - let old_region = *region; *region = self.renumber_regions(&old_region); - debug!("visit_region: region={:?}", region); + debug!(?region); } fn visit_const(&mut self, constant: &mut &'tcx ty::Const<'tcx>, _location: Location) { diff --git a/compiler/rustc_mir/src/borrow_check/type_check/canonical.rs b/compiler/rustc_borrowck/src/type_check/canonical.rs similarity index 81% rename from compiler/rustc_mir/src/borrow_check/type_check/canonical.rs rename to compiler/rustc_borrowck/src/type_check/canonical.rs index b501716a89..7d4df59902 100644 --- a/compiler/rustc_mir/src/borrow_check/type_check/canonical.rs +++ b/compiler/rustc_borrowck/src/type_check/canonical.rs @@ -4,11 +4,12 @@ use rustc_infer::infer::canonical::Canonical; use rustc_infer::traits::query::NoSolution; use rustc_middle::mir::ConstraintCategory; use rustc_middle::ty::{self, ToPredicate, TypeFoldable}; +use rustc_span::def_id::DefId; use rustc_span::Span; use rustc_trait_selection::traits::query::type_op::{self, TypeOpOutput}; use rustc_trait_selection::traits::query::Fallible; -use crate::borrow_check::diagnostics::{ToUniverseInfo, UniverseInfo}; +use crate::diagnostics::{ToUniverseInfo, UniverseInfo}; use super::{Locations, NormalizeLocation, TypeChecker}; @@ -23,6 +24,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { /// **Any `rustc_infer::infer` operations that might generate region /// constraints should occur within this method so that those /// constraints can be properly localized!** + #[instrument(skip(self, category, op), level = "trace")] pub(super) fn fully_perform_op( &mut self, locations: Locations, @@ -50,9 +52,10 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { None => UniverseInfo::other(), }; for u in old_universe..universe { - let info_universe = - self.borrowck_context.constraints.universe_causes.push(universe_info.clone()); - assert_eq!(u.as_u32() + 1, info_universe.as_u32()); + self.borrowck_context + .constraints + .universe_causes + .insert(u + 1, universe_info.clone()); } } @@ -70,9 +73,12 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { let (instantiated, _) = self.infcx.instantiate_canonical_with_fresh_inference_vars(span, canonical); - for _ in 0..canonical.max_universe.as_u32() { + for u in 0..canonical.max_universe.as_u32() { let info = UniverseInfo::other(); - self.borrowck_context.constraints.universe_causes.push(info); + self.borrowck_context + .constraints + .universe_causes + .insert(ty::UniverseIndex::from_u32(u), info); } instantiated @@ -85,10 +91,10 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { category: ConstraintCategory, ) { self.prove_predicates( - Some(ty::PredicateKind::Trait(ty::TraitPredicate { + Some(ty::Binder::dummy(ty::PredicateKind::Trait(ty::TraitPredicate { trait_ref, constness: ty::BoundConstness::NotConst, - })), + }))), locations, category, ); @@ -96,12 +102,19 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { pub(super) fn normalize_and_prove_instantiated_predicates( &mut self, + // Keep this parameter for now, in case we start using + // it in `ConstraintCategory` at some point. + _def_id: DefId, instantiated_predicates: ty::InstantiatedPredicates<'tcx>, locations: Locations, ) { - for predicate in instantiated_predicates.predicates { + for (predicate, span) in instantiated_predicates + .predicates + .into_iter() + .zip(instantiated_predicates.spans.into_iter()) + { let predicate = self.normalize(predicate, locations); - self.prove_predicate(predicate, locations, ConstraintCategory::Boring); + self.prove_predicate(predicate, locations, ConstraintCategory::Predicate(span)); } } @@ -119,14 +132,13 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } } + #[instrument(skip(self), level = "debug")] pub(super) fn prove_predicate( &mut self, predicate: ty::Predicate<'tcx>, locations: Locations, category: ConstraintCategory, ) { - debug!("prove_predicate(predicate={:?}, location={:?})", predicate, locations,); - let param_env = self.param_env; self.fully_perform_op( locations, @@ -138,11 +150,11 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { }) } + #[instrument(skip(self), level = "debug")] pub(super) fn normalize(&mut self, value: T, location: impl NormalizeLocation) -> T where T: type_op::normalize::Normalizable<'tcx> + fmt::Display + Copy + 'tcx, { - debug!("normalize(value={:?}, location={:?})", value, location); let param_env = self.param_env; self.fully_perform_op( location.to_locations(), diff --git a/compiler/rustc_mir/src/borrow_check/type_check/constraint_conversion.rs b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs similarity index 98% rename from compiler/rustc_mir/src/borrow_check/type_check/constraint_conversion.rs rename to compiler/rustc_borrowck/src/type_check/constraint_conversion.rs index 446a0f8e72..ab1a7461b4 100644 --- a/compiler/rustc_mir/src/borrow_check/type_check/constraint_conversion.rs +++ b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs @@ -9,7 +9,7 @@ use rustc_middle::ty::subst::GenericArgKind; use rustc_middle::ty::{self, TyCtxt}; use rustc_span::DUMMY_SP; -use crate::borrow_check::{ +use crate::{ constraints::OutlivesConstraint, nll::ToRegionVid, region_infer::TypeTest, @@ -53,9 +53,8 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> { } } + #[instrument(skip(self), level = "debug")] pub(super) fn convert_all(&mut self, query_constraints: &QueryRegionConstraints<'tcx>) { - debug!("convert_all(query_constraints={:#?})", query_constraints); - let QueryRegionConstraints { outlives, member_constraints } = query_constraints; // Annoying: to invoke `self.to_region_vid`, we need access to diff --git a/compiler/rustc_mir/src/borrow_check/type_check/free_region_relations.rs b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs similarity index 97% rename from compiler/rustc_mir/src/borrow_check/type_check/free_region_relations.rs rename to compiler/rustc_borrowck/src/type_check/free_region_relations.rs index 6426098d84..84fa9bbca8 100644 --- a/compiler/rustc_mir/src/borrow_check/type_check/free_region_relations.rs +++ b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs @@ -13,7 +13,7 @@ use rustc_trait_selection::traits::query::type_op::{self, TypeOp}; use std::rc::Rc; use type_op::TypeOpOutput; -use crate::borrow_check::{ +use crate::{ nll::ToRegionVid, type_check::constraint_conversion, type_check::{Locations, MirTypeckRegionConstraints}, @@ -55,7 +55,7 @@ type RegionBoundPairs<'tcx> = Vec<(ty::Region<'tcx>, GenericKind<'tcx>)>; type NormalizedInputsAndOutput<'tcx> = Vec>; crate struct CreateResult<'tcx> { - pub(in crate::borrow_check) universal_region_relations: Frozen>, + crate universal_region_relations: Frozen>, crate region_bound_pairs: RegionBoundPairs<'tcx>, crate normalized_inputs_and_output: NormalizedInputsAndOutput<'tcx>, } @@ -258,8 +258,7 @@ impl UniversalRegionRelationsBuilder<'cx, 'tcx> { debug!("build: input_or_output={:?}", ty); // We add implied bounds from both the unnormalized and normalized ty // See issue #87748 - let constraints_implied_1 = self.add_implied_bounds(ty); - let TypeOpOutput { output: ty, constraints: constraints1, .. } = self + let TypeOpOutput { output: norm_ty, constraints: constraints1, .. } = self .param_env .and(type_op::normalize::Normalize::new(ty)) .fully_perform(self.infcx) @@ -286,9 +285,9 @@ impl UniversalRegionRelationsBuilder<'cx, 'tcx> { // } // ``` // Both &Self::Bar and &() are WF - let constraints_implied_2 = self.add_implied_bounds(ty); - normalized_inputs_and_output.push(ty); - constraints1.into_iter().chain(constraints_implied_1).chain(constraints_implied_2) + let constraints_implied = self.add_implied_bounds(norm_ty); + normalized_inputs_and_output.push(norm_ty); + constraints1.into_iter().chain(constraints_implied) }) .collect(); diff --git a/compiler/rustc_mir/src/borrow_check/type_check/input_output.rs b/compiler/rustc_borrowck/src/type_check/input_output.rs similarity index 95% rename from compiler/rustc_mir/src/borrow_check/type_check/input_output.rs rename to compiler/rustc_borrowck/src/type_check/input_output.rs index ba9b692652..24332690be 100644 --- a/compiler/rustc_mir/src/borrow_check/type_check/input_output.rs +++ b/compiler/rustc_borrowck/src/type_check/input_output.rs @@ -7,20 +7,20 @@ //! `RETURN_PLACE` the MIR arguments) are always fully normalized (and //! contain revealed `impl Trait` values). +use rustc_index::vec::Idx; use rustc_infer::infer::LateBoundRegionConversionTime; use rustc_middle::mir::*; use rustc_middle::traits::ObligationCause; use rustc_middle::ty::{self, Ty}; +use rustc_span::Span; use rustc_trait_selection::traits::query::normalize::AtExt; -use rustc_index::vec::Idx; -use rustc_span::Span; - -use crate::borrow_check::universal_regions::UniversalRegions; +use crate::universal_regions::UniversalRegions; use super::{Locations, TypeChecker}; impl<'a, 'tcx> TypeChecker<'a, 'tcx> { + #[instrument(skip(self, body, universal_regions), level = "debug")] pub(super) fn equate_inputs_and_outputs( &mut self, body: &Body<'tcx>, @@ -65,10 +65,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { ); } - debug!( - "equate_inputs_and_outputs: normalized_input_tys = {:?}, local_decls = {:?}", - normalized_input_tys, body.local_decls - ); + debug!(?normalized_input_tys, ?body.local_decls); // Equate expected input tys with those in the MIR. for (argument_index, &normalized_input_ty) in normalized_input_tys.iter().enumerate() { @@ -161,9 +158,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } } + #[instrument(skip(self, span), level = "debug")] fn equate_normalized_input_or_output(&mut self, a: Ty<'tcx>, b: Ty<'tcx>, span: Span) { - debug!("equate_normalized_input_or_output(a={:?}, b={:?})", a, b); - if let Err(_) = self.eq_types(a, b, Locations::All(span), ConstraintCategory::BoringNoLocation) { @@ -195,6 +191,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { b } }; + // Note: if we have to introduce new placeholders during normalization above, then we won't have + // added those universes to the universe info, which we would want in `relate_tys`. if let Err(terr) = self.eq_types(a, b, Locations::All(span), ConstraintCategory::BoringNoLocation) { diff --git a/compiler/rustc_mir/src/borrow_check/type_check/liveness/local_use_map.rs b/compiler/rustc_borrowck/src/type_check/liveness/local_use_map.rs similarity index 97% rename from compiler/rustc_mir/src/borrow_check/type_check/liveness/local_use_map.rs rename to compiler/rustc_borrowck/src/type_check/liveness/local_use_map.rs index 7e8a33efe1..8b74abd94c 100644 --- a/compiler/rustc_mir/src/borrow_check/type_check/liveness/local_use_map.rs +++ b/compiler/rustc_borrowck/src/type_check/liveness/local_use_map.rs @@ -3,8 +3,8 @@ use rustc_index::vec::IndexVec; use rustc_middle::mir::visit::{PlaceContext, Visitor}; use rustc_middle::mir::{Body, Local, Location}; -use crate::borrow_check::def_use::{self, DefUse}; -use crate::borrow_check::region_infer::values::{PointIndex, RegionValueElements}; +use crate::def_use::{self, DefUse}; +use crate::region_infer::values::{PointIndex, RegionValueElements}; /// A map that cross references each local with the locations where it /// is defined (assigned), used, or dropped. Used during liveness diff --git a/compiler/rustc_mir/src/borrow_check/type_check/liveness/mod.rs b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs similarity index 96% rename from compiler/rustc_mir/src/borrow_check/type_check/liveness/mod.rs rename to compiler/rustc_borrowck/src/type_check/liveness/mod.rs index a34ae281b7..1e712354d6 100644 --- a/compiler/rustc_mir/src/borrow_check/type_check/liveness/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs @@ -3,11 +3,11 @@ use rustc_middle::mir::{Body, Local}; use rustc_middle::ty::{RegionVid, TyCtxt}; use std::rc::Rc; -use crate::dataflow::impls::MaybeInitializedPlaces; -use crate::dataflow::move_paths::MoveData; -use crate::dataflow::ResultsCursor; +use rustc_mir_dataflow::impls::MaybeInitializedPlaces; +use rustc_mir_dataflow::move_paths::MoveData; +use rustc_mir_dataflow::ResultsCursor; -use crate::borrow_check::{ +use crate::{ constraints::OutlivesConstraintSet, facts::{AllFacts, AllFactsExt}, location::LocationTable, diff --git a/compiler/rustc_mir/src/borrow_check/type_check/liveness/polonius.rs b/compiler/rustc_borrowck/src/type_check/liveness/polonius.rs similarity index 96% rename from compiler/rustc_mir/src/borrow_check/type_check/liveness/polonius.rs rename to compiler/rustc_borrowck/src/type_check/liveness/polonius.rs index d285098c52..79ab8b713f 100644 --- a/compiler/rustc_mir/src/borrow_check/type_check/liveness/polonius.rs +++ b/compiler/rustc_borrowck/src/type_check/liveness/polonius.rs @@ -1,10 +1,9 @@ -use crate::borrow_check::def_use::{self, DefUse}; -use crate::borrow_check::location::{LocationIndex, LocationTable}; -use crate::dataflow::indexes::MovePathIndex; -use crate::dataflow::move_paths::{LookupResult, MoveData}; +use crate::def_use::{self, DefUse}; +use crate::location::{LocationIndex, LocationTable}; use rustc_middle::mir::visit::{MutatingUseContext, PlaceContext, Visitor}; use rustc_middle::mir::{Body, Local, Location, Place}; use rustc_middle::ty::subst::GenericArg; +use rustc_mir_dataflow::move_paths::{LookupResult, MoveData, MovePathIndex}; use super::TypeChecker; diff --git a/compiler/rustc_mir/src/borrow_check/type_check/liveness/trace.rs b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs similarity index 98% rename from compiler/rustc_mir/src/borrow_check/type_check/liveness/trace.rs rename to compiler/rustc_borrowck/src/type_check/liveness/trace.rs index 566c11811e..1671c7c627 100644 --- a/compiler/rustc_mir/src/borrow_check/type_check/liveness/trace.rs +++ b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs @@ -8,12 +8,11 @@ use rustc_trait_selection::traits::query::type_op::outlives::DropckOutlives; use rustc_trait_selection::traits::query::type_op::{TypeOp, TypeOpOutput}; use std::rc::Rc; -use crate::dataflow::impls::MaybeInitializedPlaces; -use crate::dataflow::indexes::MovePathIndex; -use crate::dataflow::move_paths::{HasMoveData, MoveData}; -use crate::dataflow::ResultsCursor; +use rustc_mir_dataflow::impls::MaybeInitializedPlaces; +use rustc_mir_dataflow::move_paths::{HasMoveData, MoveData, MovePathIndex}; +use rustc_mir_dataflow::ResultsCursor; -use crate::borrow_check::{ +use crate::{ region_infer::values::{self, PointIndex, RegionValueElements}, type_check::liveness::local_use_map::LocalUseMap, type_check::liveness::polonius, diff --git a/compiler/rustc_mir/src/borrow_check/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs similarity index 96% rename from compiler/rustc_mir/src/borrow_check/type_check/mod.rs rename to compiler/rustc_borrowck/src/type_check/mod.rs index 639bcb8fa9..7bf119863f 100644 --- a/compiler/rustc_mir/src/borrow_check/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -14,6 +14,7 @@ use rustc_hir::def_id::LocalDefId; use rustc_hir::lang_items::LangItem; use rustc_index::vec::{Idx, IndexVec}; use rustc_infer::infer::canonical::QueryRegionConstraints; +use rustc_infer::infer::opaque_types::OpaqueTypeDecl; use rustc_infer::infer::outlives::env::RegionBoundPairs; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::infer::{ @@ -31,6 +32,7 @@ use rustc_middle::ty::{ self, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, OpaqueTypeKey, RegionVid, ToPredicate, Ty, TyCtxt, UserType, UserTypeAnnotationIndex, WithConstness, }; +use rustc_span::def_id::CRATE_DEF_ID; use rustc_span::{Span, DUMMY_SP}; use rustc_target::abi::VariantIdx; use rustc_trait_selection::infer::InferCtxtExt as _; @@ -41,14 +43,14 @@ use rustc_trait_selection::traits::query::type_op::custom::CustomTypeOp; use rustc_trait_selection::traits::query::Fallible; use rustc_trait_selection::traits::{self, ObligationCause, PredicateObligations}; -use crate::dataflow::impls::MaybeInitializedPlaces; -use crate::dataflow::move_paths::MoveData; -use crate::dataflow::ResultsCursor; -use crate::transform::{ +use rustc_const_eval::transform::{ check_consts::ConstCx, promote_consts::is_const_fn_in_array_repeat_expression, }; +use rustc_mir_dataflow::impls::MaybeInitializedPlaces; +use rustc_mir_dataflow::move_paths::MoveData; +use rustc_mir_dataflow::ResultsCursor; -use crate::borrow_check::{ +use crate::{ borrow_set::BorrowSet, constraints::{OutlivesConstraint, OutlivesConstraintSet}, diagnostics::UniverseInfo, @@ -68,7 +70,7 @@ use crate::borrow_check::{ macro_rules! span_mirbug { ($context:expr, $elem:expr, $($message:tt)*) => ({ - $crate::borrow_check::type_check::mirbug( + $crate::type_check::mirbug( $context.tcx(), $context.last_span, &format!( @@ -136,6 +138,8 @@ pub(crate) fn type_check<'mir, 'tcx>( upvars: &[Upvar<'tcx>], ) -> MirTypeckResults<'tcx> { let implicit_region_bound = infcx.tcx.mk_region(ty::ReVar(universal_regions.fr_fn_body)); + let mut universe_causes = FxHashMap::default(); + universe_causes.insert(ty::UniverseIndex::from_u32(0), UniverseInfo::other()); let mut constraints = MirTypeckRegionConstraints { placeholder_indices: PlaceholderIndices::default(), placeholder_index_to_region: IndexVec::default(), @@ -144,7 +148,7 @@ pub(crate) fn type_check<'mir, 'tcx>( member_constraints: MemberConstraintSet::default(), closure_bounds_mapping: Default::default(), type_tests: Vec::default(), - universe_causes: IndexVec::from_elem_n(UniverseInfo::other(), 1), + universe_causes, }; let CreateResult { @@ -159,9 +163,9 @@ pub(crate) fn type_check<'mir, 'tcx>( &mut constraints, ); - for _ in ty::UniverseIndex::ROOT..infcx.universe() { + for u in ty::UniverseIndex::ROOT..infcx.universe() { let info = UniverseInfo::other(); - constraints.universe_causes.push(info); + constraints.universe_causes.insert(u, info); } let mut borrowck_context = BorrowCheckContext { @@ -191,16 +195,22 @@ pub(crate) fn type_check<'mir, 'tcx>( opaque_type_values .into_iter() - .filter_map(|(opaque_type_key, decl)| { - let mut revealed_ty = infcx.resolve_vars_if_possible(decl.concrete_ty); - if revealed_ty.has_infer_types_or_consts() { + .filter_map(|(opaque_type_key, mut decl)| { + decl.concrete_ty = infcx.resolve_vars_if_possible(decl.concrete_ty); + trace!( + "finalized opaque type {:?} to {:#?}", + opaque_type_key, + decl.concrete_ty.kind() + ); + if decl.concrete_ty.has_infer_types_or_consts() { infcx.tcx.sess.delay_span_bug( body.span, - &format!("could not resolve {:#?}", revealed_ty.kind()), + &format!("could not resolve {:#?}", decl.concrete_ty.kind()), ); - revealed_ty = infcx.tcx.ty_error(); + decl.concrete_ty = infcx.tcx.ty_error(); } - let concrete_is_opaque = if let ty::Opaque(def_id, _) = revealed_ty.kind() { + let concrete_is_opaque = if let ty::Opaque(def_id, _) = decl.concrete_ty.kind() + { *def_id == opaque_type_key.def_id } else { false @@ -232,7 +242,7 @@ pub(crate) fn type_check<'mir, 'tcx>( ); None } else { - Some((opaque_type_key, revealed_ty)) + Some((opaque_type_key, decl)) } }) .collect() @@ -242,6 +252,18 @@ pub(crate) fn type_check<'mir, 'tcx>( MirTypeckResults { constraints, universal_region_relations, opaque_type_values } } +#[instrument( + skip( + infcx, + body, + promoted, + region_bound_pairs, + borrowck_context, + universal_region_relations, + extra + ), + level = "debug" +)] fn type_check_internal<'a, 'tcx, R>( infcx: &'a InferCtxt<'a, 'tcx>, param_env: ty::ParamEnv<'tcx>, @@ -445,6 +467,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> { if let ty::FnDef(def_id, substs) = *constant.literal.ty().kind() { let instantiated_predicates = tcx.predicates_of(def_id).instantiate(tcx, substs); self.cx.normalize_and_prove_instantiated_predicates( + def_id, instantiated_predicates, location.to_locations(), ); @@ -640,12 +663,17 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { } self.cx.borrowck_context.constraints.outlives_constraints.push(constraint) } - for live_region in liveness_constraints.rows() { - self.cx - .borrowck_context - .constraints - .liveness_constraints - .add_element(live_region, location); + for region in liveness_constraints.rows() { + // If the region is live at at least one location in the promoted MIR, + // then add a liveness constraint to the main MIR for this region + // at the location provided as an argument to this method + if let Some(_) = liveness_constraints.get_elements(region).next() { + self.cx + .borrowck_context + .constraints + .liveness_constraints + .add_element(region, location); + } } if !closure_bounds.is_empty() { @@ -887,8 +915,8 @@ struct BorrowCheckContext<'a, 'tcx> { crate struct MirTypeckResults<'tcx> { crate constraints: MirTypeckRegionConstraints<'tcx>, - pub(in crate::borrow_check) universal_region_relations: Frozen>, - crate opaque_type_values: VecMap, Ty<'tcx>>, + crate universal_region_relations: Frozen>, + crate opaque_type_values: VecMap, OpaqueTypeDecl<'tcx>>, } /// A collection of region constraints that must be satisfied for the @@ -924,7 +952,7 @@ crate struct MirTypeckRegionConstraints<'tcx> { crate closure_bounds_mapping: FxHashMap>, - crate universe_causes: IndexVec>, + crate universe_causes: FxHashMap>, crate type_tests: Vec>, } @@ -1076,7 +1104,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } self.prove_predicate( - ty::PredicateKind::WellFormed(inferred_ty.into()).to_predicate(self.tcx()), + ty::Binder::dummy(ty::PredicateKind::WellFormed(inferred_ty.into())) + .to_predicate(self.tcx()), Locations::All(span), ConstraintCategory::TypeAnnotation, ); @@ -1107,13 +1136,14 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } } + #[instrument(skip(self, data), level = "debug")] fn push_region_constraints( &mut self, locations: Locations, category: ConstraintCategory, data: &QueryRegionConstraints<'tcx>, ) { - debug!("push_region_constraints: constraints generated at {:?} are {:#?}", locations, data); + debug!("constraints generated: {:#?}", data); constraint_conversion::ConstraintConversion::new( self.infcx, @@ -1128,28 +1158,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { .convert_all(data); } - /// Convenient wrapper around `relate_tys::relate_types` -- see - /// that fn for docs. - fn relate_types( - &mut self, - a: Ty<'tcx>, - v: ty::Variance, - b: Ty<'tcx>, - locations: Locations, - category: ConstraintCategory, - ) -> Fallible<()> { - relate_tys::relate_types( - self.infcx, - self.param_env, - a, - v, - b, - locations, - category, - self.borrowck_context, - ) - } - /// Try to relate `sub <: sup` fn sub_types( &mut self, @@ -1173,6 +1181,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { self.relate_types(expected, ty::Variance::Invariant, found, locations, category) } + #[instrument(skip(self), level = "debug")] fn relate_type_and_user_type( &mut self, a: Ty<'tcx>, @@ -1181,11 +1190,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { locations: Locations, category: ConstraintCategory, ) -> Fallible<()> { - debug!( - "relate_type_and_user_type(a={:?}, v={:?}, user_ty={:?}, locations={:?})", - a, v, user_ty, locations, - ); - let annotated_type = self.user_type_annotations[user_ty.base].inferred_ty; let mut curr_projected_ty = PlaceTy::from_ty(annotated_type); @@ -1243,6 +1247,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { /// generics of `foo`). Note that `anon_ty` is not just the opaque type, /// but the entire return type (which may contain opaque types within it). /// * `revealed_ty` would be `Box<(T, u32)>` + #[instrument(skip(self), level = "debug")] fn eq_opaque_type_and_type( &mut self, revealed_ty: Ty<'tcx>, @@ -1250,13 +1255,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { locations: Locations, category: ConstraintCategory, ) -> Fallible<()> { - debug!( - "eq_opaque_type_and_type( \ - revealed_ty={:?}, \ - anon_ty={:?})", - revealed_ty, anon_ty - ); - // Fast path for the common case. if !anon_ty.has_opaque_types() { if let Err(terr) = self.eq_types(anon_ty, revealed_ty, locations, category) { @@ -1276,7 +1274,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { let body = self.body; let mir_def_id = body.source.def_id().expect_local(); - debug!("eq_opaque_type_and_type: mir_def_id={:?}", mir_def_id); + debug!(?mir_def_id); self.fully_perform_op( locations, category, @@ -1298,12 +1296,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { anon_ty, locations.span(body), )); - debug!( - "eq_opaque_type_and_type: \ - instantiated output_ty={:?} \ - revealed_ty={:?}", - output_ty, revealed_ty - ); + debug!(?output_ty, ?revealed_ty); // Make sure that the inferred types are well-formed. I'm // not entirely sure this is needed (the HIR type check @@ -1312,7 +1305,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { obligations.obligations.push(traits::Obligation::new( ObligationCause::dummy(), param_env, - ty::PredicateKind::WellFormed(revealed_ty.into()).to_predicate(infcx.tcx), + ty::Binder::dummy(ty::PredicateKind::WellFormed(revealed_ty.into())) + .to_predicate(infcx.tcx), )); obligations.add( infcx @@ -1320,7 +1314,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { .eq(output_ty, revealed_ty)?, ); - debug!("eq_opaque_type_and_type: equated"); + debug!("equated"); Ok(InferOk { value: (), obligations: obligations.into_vec() }) }, @@ -1360,8 +1354,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { self.infcx.tcx } + #[instrument(skip(self, body, location), level = "debug")] fn check_stmt(&mut self, body: &Body<'tcx>, stmt: &Statement<'tcx>, location: Location) { - debug!("check_stmt: {:?}", stmt); let tcx = self.tcx(); match stmt.kind { StatementKind::Assign(box (ref place, ref rv)) => { @@ -1386,11 +1380,24 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { ConstraintCategory::Return(ReturnConstraint::Normal) } } + Some(l) + if matches!( + body.local_decls[l].local_info, + Some(box LocalInfo::AggregateTemp) + ) => + { + ConstraintCategory::Usage + } Some(l) if !body.local_decls[l].is_user_variable() => { ConstraintCategory::Boring } _ => ConstraintCategory::Assignment, }; + debug!( + "assignment category: {:?} {:?}", + category, + place.as_local().map(|l| &body.local_decls[l]) + ); let place_ty = place.ty(body, tcx).ty; let place_ty = self.normalize(place_ty, location); @@ -1501,13 +1508,13 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } } + #[instrument(skip(self, body, term_location), level = "debug")] fn check_terminator( &mut self, body: &Body<'tcx>, term: &Terminator<'tcx>, term_location: Location, ) { - debug!("check_terminator: {:?}", term); let tcx = self.tcx(); match term.kind { TerminatorKind::Goto { .. } @@ -1582,7 +1589,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { self.check_call_dest(body, term, &sig, destination, term_location); self.prove_predicates( - sig.inputs_and_output.iter().map(|ty| ty::PredicateKind::WellFormed(ty.into())), + sig.inputs_and_output + .iter() + .map(|ty| ty::Binder::dummy(ty::PredicateKind::WellFormed(ty.into()))), term_location.to_locations(), ConstraintCategory::Boring, ); @@ -1996,7 +2005,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { &obligation, &traits::SelectionError::Unimplemented, false, - false, ); } } @@ -2004,13 +2012,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } } - Rvalue::NullaryOp(_, ty) => { - // Even with unsized locals cannot box an unsized value. - if self.unsized_feature_enabled() { - let span = body.source_info(location).span; - self.ensure_place_sized(ty, span); - } - + Rvalue::NullaryOp(_, ty) | Rvalue::ShallowInitBox(_, ty) => { let trait_ref = ty::TraitRef { def_id: tcx.require_lang_item(LangItem::Sized, Some(self.last_span)), substs: tcx.mk_substs_trait(ty, &[]), @@ -2343,6 +2345,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { | Rvalue::AddressOf(..) | Rvalue::Len(..) | Rvalue::Cast(..) + | Rvalue::ShallowInitBox(..) | Rvalue::BinaryOp(..) | Rvalue::CheckedBinaryOp(..) | Rvalue::NullaryOp(..) @@ -2557,9 +2560,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { aggregate_kind, location ); - let instantiated_predicates = match aggregate_kind { + let (def_id, instantiated_predicates) = match aggregate_kind { AggregateKind::Adt(def, _, substs, _, _) => { - tcx.predicates_of(def.did).instantiate(tcx, substs) + (def.did, tcx.predicates_of(def.did).instantiate(tcx, substs)) } // For closures, we have some **extra requirements** we @@ -2584,13 +2587,16 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { // clauses on the struct. AggregateKind::Closure(def_id, substs) | AggregateKind::Generator(def_id, substs, _) => { - self.prove_closure_bounds(tcx, def_id.expect_local(), substs, location) + (*def_id, self.prove_closure_bounds(tcx, def_id.expect_local(), substs, location)) } - AggregateKind::Array(_) | AggregateKind::Tuple => ty::InstantiatedPredicates::empty(), + AggregateKind::Array(_) | AggregateKind::Tuple => { + (CRATE_DEF_ID.to_def_id(), ty::InstantiatedPredicates::empty()) + } }; self.normalize_and_prove_instantiated_predicates( + def_id, instantiated_predicates, location.to_locations(), ); @@ -2665,9 +2671,10 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { tcx.predicates_of(def_id).instantiate(tcx, substs) } + #[instrument(skip(self, body), level = "debug")] fn typeck_mir(&mut self, body: &Body<'tcx>) { self.last_span = body.span; - debug!("run_on_mir: {:?}", body.span); + debug!(?body.span); for (local, local_decl) in body.local_decls.iter_enumerated() { self.check_local(&body, local, local_decl); diff --git a/compiler/rustc_borrowck/src/type_check/relate_tys.rs b/compiler/rustc_borrowck/src/type_check/relate_tys.rs new file mode 100644 index 0000000000..415d1abaa8 --- /dev/null +++ b/compiler/rustc_borrowck/src/type_check/relate_tys.rs @@ -0,0 +1,129 @@ +use rustc_infer::infer::nll_relate::{NormalizationStrategy, TypeRelating, TypeRelatingDelegate}; +use rustc_infer::infer::NllRegionVariableOrigin; +use rustc_middle::mir::ConstraintCategory; +use rustc_middle::ty::relate::TypeRelation; +use rustc_middle::ty::{self, Const, Ty}; +use rustc_trait_selection::traits::query::Fallible; + +use crate::constraints::OutlivesConstraint; +use crate::diagnostics::UniverseInfo; +use crate::type_check::{Locations, TypeChecker}; + +impl<'a, 'tcx> TypeChecker<'a, 'tcx> { + /// Adds sufficient constraints to ensure that `a R b` where `R` depends on `v`: + /// + /// - "Covariant" `a <: b` + /// - "Invariant" `a == b` + /// - "Contravariant" `a :> b` + /// + /// N.B., the type `a` is permitted to have unresolved inference + /// variables, but not the type `b`. + #[instrument(skip(self), level = "debug")] + pub(super) fn relate_types( + &mut self, + a: Ty<'tcx>, + v: ty::Variance, + b: Ty<'tcx>, + locations: Locations, + category: ConstraintCategory, + ) -> Fallible<()> { + TypeRelating::new( + self.infcx, + NllTypeRelatingDelegate::new(self, locations, category, UniverseInfo::relate(a, b)), + v, + ) + .relate(a, b)?; + Ok(()) + } +} + +struct NllTypeRelatingDelegate<'me, 'bccx, 'tcx> { + type_checker: &'me mut TypeChecker<'bccx, 'tcx>, + + /// Where (and why) is this relation taking place? + locations: Locations, + + /// What category do we assign the resulting `'a: 'b` relationships? + category: ConstraintCategory, + + /// Information so that error reporting knows what types we are relating + /// when reporting a bound region error. + universe_info: UniverseInfo<'tcx>, +} + +impl NllTypeRelatingDelegate<'me, 'bccx, 'tcx> { + fn new( + type_checker: &'me mut TypeChecker<'bccx, 'tcx>, + locations: Locations, + category: ConstraintCategory, + universe_info: UniverseInfo<'tcx>, + ) -> Self { + Self { type_checker, locations, category, universe_info } + } +} + +impl TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx> { + fn param_env(&self) -> ty::ParamEnv<'tcx> { + self.type_checker.param_env + } + + fn create_next_universe(&mut self) -> ty::UniverseIndex { + let universe = self.type_checker.infcx.create_next_universe(); + self.type_checker + .borrowck_context + .constraints + .universe_causes + .insert(universe, self.universe_info.clone()); + universe + } + + fn next_existential_region_var(&mut self, from_forall: bool) -> ty::Region<'tcx> { + let origin = NllRegionVariableOrigin::Existential { from_forall }; + self.type_checker.infcx.next_nll_region_var(origin) + } + + fn next_placeholder_region(&mut self, placeholder: ty::PlaceholderRegion) -> ty::Region<'tcx> { + self.type_checker + .borrowck_context + .constraints + .placeholder_region(self.type_checker.infcx, placeholder) + } + + fn generalize_existential(&mut self, universe: ty::UniverseIndex) -> ty::Region<'tcx> { + self.type_checker.infcx.next_nll_region_var_in_universe( + NllRegionVariableOrigin::Existential { from_forall: false }, + universe, + ) + } + + fn push_outlives( + &mut self, + sup: ty::Region<'tcx>, + sub: ty::Region<'tcx>, + info: ty::VarianceDiagInfo<'tcx>, + ) { + let sub = self.type_checker.borrowck_context.universal_regions.to_region_vid(sub); + let sup = self.type_checker.borrowck_context.universal_regions.to_region_vid(sup); + self.type_checker.borrowck_context.constraints.outlives_constraints.push( + OutlivesConstraint { + sup, + sub, + locations: self.locations, + category: self.category, + variance_info: info, + }, + ); + } + + // We don't have to worry about the equality of consts during borrow checking + // as consts always have a static lifetime. + fn const_equate(&mut self, _a: &'tcx Const<'tcx>, _b: &'tcx Const<'tcx>) {} + + fn normalization() -> NormalizationStrategy { + NormalizationStrategy::Eager + } + + fn forbid_inference_vars() -> bool { + true + } +} diff --git a/compiler/rustc_mir/src/borrow_check/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs similarity index 99% rename from compiler/rustc_mir/src/borrow_check/universal_regions.rs rename to compiler/rustc_borrowck/src/universal_regions.rs index 3c9b4272b3..bebd193702 100644 --- a/compiler/rustc_mir/src/borrow_check/universal_regions.rs +++ b/compiler/rustc_borrowck/src/universal_regions.rs @@ -26,7 +26,7 @@ use rustc_middle::ty::subst::{InternalSubsts, Subst, SubstsRef}; use rustc_middle::ty::{self, RegionVid, Ty, TyCtxt}; use std::iter; -use crate::borrow_check::nll::ToRegionVid; +use crate::nll::ToRegionVid; #[derive(Debug)] pub struct UniversalRegions<'tcx> { diff --git a/compiler/rustc_mir/src/borrow_check/used_muts.rs b/compiler/rustc_borrowck/src/used_muts.rs similarity index 99% rename from compiler/rustc_mir/src/borrow_check/used_muts.rs rename to compiler/rustc_borrowck/src/used_muts.rs index e027056842..6022a98095 100644 --- a/compiler/rustc_mir/src/borrow_check/used_muts.rs +++ b/compiler/rustc_borrowck/src/used_muts.rs @@ -1,11 +1,10 @@ +use rustc_data_structures::fx::FxHashSet; use rustc_middle::mir::visit::{PlaceContext, Visitor}; use rustc_middle::mir::{ Local, Location, Place, Statement, StatementKind, Terminator, TerminatorKind, }; -use rustc_data_structures::fx::FxHashSet; - -use crate::borrow_check::MirBorrowckCtxt; +use crate::MirBorrowckCtxt; impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { /// Walks the MIR adding to the set of `used_mut` locals that will be ignored for the purposes diff --git a/compiler/rustc_builtin_macros/Cargo.toml b/compiler/rustc_builtin_macros/Cargo.toml index 2370ac201b..fd34f947f7 100644 --- a/compiler/rustc_builtin_macros/Cargo.toml +++ b/compiler/rustc_builtin_macros/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustc_builtin_macros" version = "0.0.0" -edition = "2018" +edition = "2021" [lib] doctest = false diff --git a/compiler/rustc_builtin_macros/src/asm.rs b/compiler/rustc_builtin_macros/src/asm.rs index 652165fb9b..c032364c00 100644 --- a/compiler/rustc_builtin_macros/src/asm.rs +++ b/compiler/rustc_builtin_macros/src/asm.rs @@ -117,6 +117,10 @@ fn parse_args<'a>( let mut explicit_reg = false; let op = if !is_global_asm && p.eat_keyword(kw::In) { let reg = parse_reg(&mut p, &mut explicit_reg)?; + if p.eat_keyword(kw::Underscore) { + let err = ecx.struct_span_err(p.token.span, "_ cannot be used for input operands"); + return Err(err); + } let expr = p.parse_expr()?; ast::InlineAsmOperand::In { reg, expr } } else if !is_global_asm && p.eat_keyword(sym::out) { @@ -129,6 +133,10 @@ fn parse_args<'a>( ast::InlineAsmOperand::Out { reg, expr, late: true } } else if !is_global_asm && p.eat_keyword(sym::inout) { let reg = parse_reg(&mut p, &mut explicit_reg)?; + if p.eat_keyword(kw::Underscore) { + let err = ecx.struct_span_err(p.token.span, "_ cannot be used for input operands"); + return Err(err); + } let expr = p.parse_expr()?; if p.eat(&token::FatArrow) { let out_expr = @@ -139,6 +147,10 @@ fn parse_args<'a>( } } else if !is_global_asm && p.eat_keyword(sym::inlateout) { let reg = parse_reg(&mut p, &mut explicit_reg)?; + if p.eat_keyword(kw::Underscore) { + let err = ecx.struct_span_err(p.token.span, "_ cannot be used for input operands"); + return Err(err); + } let expr = p.parse_expr()?; if p.eat(&token::FatArrow) { let out_expr = @@ -510,7 +522,7 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, args: AsmArgs) -> Option template_part, Err(err) => { - if let Some(mut err) = err { + if let Some((mut err, _)) = err { err.emit(); } return None; diff --git a/compiler/rustc_builtin_macros/src/cfg_eval.rs b/compiler/rustc_builtin_macros/src/cfg_eval.rs index d7b46f2821..307730f7f5 100644 --- a/compiler/rustc_builtin_macros/src/cfg_eval.rs +++ b/compiler/rustc_builtin_macros/src/cfg_eval.rs @@ -2,6 +2,7 @@ use crate::util::check_builtin_macro_attribute; use rustc_ast as ast; use rustc_ast::mut_visit::MutVisitor; +use rustc_ast::ptr::P; use rustc_ast::tokenstream::CanSynthesizeMissingTokens; use rustc_ast::visit::Visitor; use rustc_ast::{mut_visit, visit}; @@ -9,10 +10,10 @@ use rustc_ast::{AstLike, Attribute}; use rustc_expand::base::{Annotatable, ExtCtxt}; use rustc_expand::config::StripUnconfigured; use rustc_expand::configure; +use rustc_feature::Features; use rustc_parse::parser::ForceCollect; use rustc_session::utils::FlattenNonterminals; - -use rustc_ast::ptr::P; +use rustc_session::Session; use rustc_span::symbol::sym; use rustc_span::Span; use smallvec::SmallVec; @@ -24,21 +25,19 @@ crate fn expand( annotatable: Annotatable, ) -> Vec { check_builtin_macro_attribute(ecx, meta_item, sym::cfg_eval); - vec![cfg_eval(ecx, annotatable)] + vec![cfg_eval(ecx.sess, ecx.ecfg.features, annotatable)] } -crate fn cfg_eval(ecx: &ExtCtxt<'_>, annotatable: Annotatable) -> Annotatable { - CfgEval { - cfg: &mut StripUnconfigured { - sess: ecx.sess, - features: ecx.ecfg.features, - config_tokens: true, - }, - } - .configure_annotatable(annotatable) - // Since the item itself has already been configured by the `InvocationCollector`, - // we know that fold result vector will contain exactly one element. - .unwrap() +crate fn cfg_eval( + sess: &Session, + features: Option<&Features>, + annotatable: Annotatable, +) -> Annotatable { + CfgEval { cfg: &mut StripUnconfigured { sess, features, config_tokens: true } } + .configure_annotatable(annotatable) + // Since the item itself has already been configured by the `InvocationCollector`, + // we know that fold result vector will contain exactly one element. + .unwrap() } struct CfgEval<'a, 'b> { diff --git a/compiler/rustc_builtin_macros/src/concat_idents.rs b/compiler/rustc_builtin_macros/src/concat_idents.rs index 209158ce39..53a456b69a 100644 --- a/compiler/rustc_builtin_macros/src/concat_idents.rs +++ b/compiler/rustc_builtin_macros/src/concat_idents.rs @@ -12,7 +12,7 @@ pub fn expand_concat_idents<'cx>( tts: TokenStream, ) -> Box { if tts.is_empty() { - cx.span_err(sp, "concat_idents! takes 1 or more arguments."); + cx.span_err(sp, "concat_idents! takes 1 or more arguments"); return DummyResult::any(sp); } @@ -22,7 +22,7 @@ pub fn expand_concat_idents<'cx>( match e { TokenTree::Token(Token { kind: token::Comma, .. }) => {} _ => { - cx.span_err(sp, "concat_idents! expecting comma."); + cx.span_err(sp, "concat_idents! expecting comma"); return DummyResult::any(sp); } } @@ -34,7 +34,7 @@ pub fn expand_concat_idents<'cx>( } } - cx.span_err(sp, "concat_idents! requires ident args."); + cx.span_err(sp, "concat_idents! requires ident args"); return DummyResult::any(sp); } } diff --git a/compiler/rustc_builtin_macros/src/derive.rs b/compiler/rustc_builtin_macros/src/derive.rs index e0389f448e..241c90c157 100644 --- a/compiler/rustc_builtin_macros/src/derive.rs +++ b/compiler/rustc_builtin_macros/src/derive.rs @@ -1,12 +1,13 @@ use crate::cfg_eval::cfg_eval; -use rustc_ast::{self as ast, attr, token, ItemKind, MetaItemKind, NestedMetaItem, StmtKind}; +use rustc_ast as ast; +use rustc_ast::{attr, token, GenericParamKind, ItemKind, MetaItemKind, NestedMetaItem, StmtKind}; use rustc_errors::{struct_span_err, Applicability}; use rustc_expand::base::{Annotatable, ExpandResult, ExtCtxt, Indeterminate, MultiItemModifier}; use rustc_feature::AttributeTemplate; use rustc_parse::validate_attr; use rustc_session::Session; -use rustc_span::symbol::sym; +use rustc_span::symbol::{sym, Ident}; use rustc_span::Span; crate struct Expander; @@ -26,8 +27,7 @@ impl MultiItemModifier for Expander { return ExpandResult::Ready(vec![item]); } - let item = cfg_eval(ecx, item); - + let (sess, features) = (ecx.sess, ecx.ecfg.features); let result = ecx.resolver.resolve_derives(ecx.current_expansion.id, ecx.force_mode, &|| { let template = @@ -40,7 +40,8 @@ impl MultiItemModifier for Expander { template, ); - attr.meta_item_list() + let mut resolutions: Vec<_> = attr + .meta_item_list() .unwrap_or_default() .into_iter() .filter_map(|nested_meta| match nested_meta { @@ -56,8 +57,21 @@ impl MultiItemModifier for Expander { report_path_args(sess, &meta); meta.path }) - .map(|path| (path, item.clone(), None)) - .collect() + .map(|path| (path, dummy_annotatable(), None)) + .collect(); + + // Do not configure or clone items unless necessary. + match &mut resolutions[..] { + [] => {} + [(_, first_item, _), others @ ..] => { + *first_item = cfg_eval(sess, features, item.clone()); + for (_, item, _) in others { + *item = first_item.clone(); + } + } + } + + resolutions }); match result { @@ -67,6 +81,18 @@ impl MultiItemModifier for Expander { } } +// The cheapest `Annotatable` to construct. +fn dummy_annotatable() -> Annotatable { + Annotatable::GenericParam(ast::GenericParam { + id: ast::DUMMY_NODE_ID, + ident: Ident::invalid(), + attrs: Default::default(), + bounds: Default::default(), + is_placeholder: false, + kind: GenericParamKind::Lifetime, + }) +} + fn report_bad_target(sess: &Session, item: &Annotatable, span: Span) -> bool { let item_kind = match item { Annotatable::Item(item) => Some(&item.kind), diff --git a/compiler/rustc_builtin_macros/src/deriving/debug.rs b/compiler/rustc_builtin_macros/src/deriving/debug.rs index 14506f296b..ecf70da6d9 100644 --- a/compiler/rustc_builtin_macros/src/deriving/debug.rs +++ b/compiler/rustc_builtin_macros/src/deriving/debug.rs @@ -65,15 +65,29 @@ fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_> // We want to make sure we have the ctxt set so that we can use unstable methods let span = cx.with_def_site_ctxt(span); let name = cx.expr_lit(span, ast::LitKind::Str(ident.name, ast::StrStyle::Cooked)); + let fmt = substr.nonself_args[0].clone(); + + // Special fast path for unit variants. In the common case of an enum that is entirely unit + // variants (i.e. a C-like enum), this fast path allows LLVM to eliminate the entire switch in + // favor of a lookup table. + if let ast::VariantData::Unit(..) = vdata { + let fn_path_write_str = cx.std_path(&[sym::fmt, sym::Formatter, sym::write_str]); + let expr = cx.expr_call_global(span, fn_path_write_str, vec![fmt, name]); + let stmts = vec![cx.stmt_expr(expr)]; + let block = cx.block(span, stmts); + return cx.expr_block(block); + } + let builder = Ident::new(sym::debug_trait_builder, span); let builder_expr = cx.expr_ident(span, builder); - let fmt = substr.nonself_args[0].clone(); - let mut stmts = Vec::with_capacity(fields.len() + 2); let fn_path_finish; match vdata { - ast::VariantData::Tuple(..) | ast::VariantData::Unit(..) => { + ast::VariantData::Unit(..) => { + cx.span_bug(span, "unit variants should have been handled above"); + } + ast::VariantData::Tuple(..) => { // tuple struct/"normal" variant let fn_path_debug_tuple = cx.std_path(&[sym::fmt, sym::Formatter, sym::debug_tuple]); let expr = cx.expr_call_global(span, fn_path_debug_tuple, vec![fmt, name]); diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs index 59f933d422..cd78c016ca 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs @@ -332,20 +332,27 @@ pub fn combine_substructure( RefCell::new(f) } +struct TypeParameter { + bound_generic_params: Vec, + ty: P, +} + /// This method helps to extract all the type parameters referenced from a /// type. For a type parameter ``, it looks for either a `TyPath` that /// is not global and starts with `T`, or a `TyQPath`. +/// Also include bound generic params from the input type. fn find_type_parameters( ty: &ast::Ty, ty_param_names: &[Symbol], cx: &ExtCtxt<'_>, -) -> Vec> { +) -> Vec { use rustc_ast::visit; struct Visitor<'a, 'b> { cx: &'a ExtCtxt<'b>, ty_param_names: &'a [Symbol], - types: Vec>, + bound_generic_params_stack: Vec, + type_params: Vec, } impl<'a, 'b> visit::Visitor<'a> for Visitor<'a, 'b> { @@ -353,7 +360,10 @@ fn find_type_parameters( if let ast::TyKind::Path(_, ref path) = ty.kind { if let Some(segment) = path.segments.first() { if self.ty_param_names.contains(&segment.ident.name) { - self.types.push(P(ty.clone())); + self.type_params.push(TypeParameter { + bound_generic_params: self.bound_generic_params_stack.clone(), + ty: P(ty.clone()), + }); } } } @@ -361,15 +371,35 @@ fn find_type_parameters( visit::walk_ty(self, ty) } + // Place bound generic params on a stack, to extract them when a type is encountered. + fn visit_poly_trait_ref( + &mut self, + trait_ref: &'a ast::PolyTraitRef, + modifier: &'a ast::TraitBoundModifier, + ) { + let stack_len = self.bound_generic_params_stack.len(); + self.bound_generic_params_stack + .extend(trait_ref.bound_generic_params.clone().into_iter()); + + visit::walk_poly_trait_ref(self, trait_ref, modifier); + + self.bound_generic_params_stack.truncate(stack_len); + } + fn visit_mac_call(&mut self, mac: &ast::MacCall) { self.cx.span_err(mac.span(), "`derive` cannot be used on items with type macros"); } } - let mut visitor = Visitor { cx, ty_param_names, types: Vec::new() }; + let mut visitor = Visitor { + cx, + ty_param_names, + bound_generic_params_stack: Vec::new(), + type_params: Vec::new(), + }; visit::Visitor::visit_ty(&mut visitor, ty); - visitor.types + visitor.type_params } impl<'a> TraitDef<'a> { @@ -564,7 +594,7 @@ impl<'a> TraitDef<'a> { GenericParamKind::Const { ty, kw_span, .. } => { let const_nodefault_kind = GenericParamKind::Const { ty: ty.clone(), - kw_span: kw_span.clone(), + kw_span: *kw_span, // We can't have default values inside impl block default: None, @@ -617,11 +647,11 @@ impl<'a> TraitDef<'a> { ty_params.map(|ty_param| ty_param.ident.name).collect(); for field_ty in field_tys { - let tys = find_type_parameters(&field_ty, &ty_param_names, cx); + let field_ty_params = find_type_parameters(&field_ty, &ty_param_names, cx); - for ty in tys { + for field_ty_param in field_ty_params { // if we have already handled this type, skip it - if let ast::TyKind::Path(_, ref p) = ty.kind { + if let ast::TyKind::Path(_, ref p) = field_ty_param.ty.kind { if p.segments.len() == 1 && ty_param_names.contains(&p.segments[0].ident.name) { @@ -639,8 +669,8 @@ impl<'a> TraitDef<'a> { let predicate = ast::WhereBoundPredicate { span: self.span, - bound_generic_params: Vec::new(), - bounded_ty: ty, + bound_generic_params: field_ty_param.bound_generic_params, + bounded_ty: field_ty_param.ty, bounds, }; diff --git a/compiler/rustc_builtin_macros/src/format.rs b/compiler/rustc_builtin_macros/src/format.rs index 8508b3b7ae..f0056cb797 100644 --- a/compiler/rustc_builtin_macros/src/format.rs +++ b/compiler/rustc_builtin_macros/src/format.rs @@ -164,23 +164,22 @@ fn parse_args<'a>( p.clear_expected_tokens(); } - // `Parser::expect` tries to recover using the - // `Parser::unexpected_try_recover` function. This function is able - // to recover if the expected token is a closing delimiter. - // - // As `,` is not a closing delimiter, it will always return an `Err` - // variant. - let mut err = p.expect(&token::Comma).unwrap_err(); - - match token::TokenKind::Comma.similar_tokens() { - Some(tks) if tks.contains(&p.token.kind) => { - // If a similar token is found, then it may be a typo. We - // consider it as a comma, and continue parsing. - err.emit(); - p.bump(); + match p.expect(&token::Comma) { + Err(mut err) => { + match token::TokenKind::Comma.similar_tokens() { + Some(tks) if tks.contains(&p.token.kind) => { + // If a similar token is found, then it may be a typo. We + // consider it as a comma, and continue parsing. + err.emit(); + p.bump(); + } + // Otherwise stop the parsing and return the error. + _ => return Err(err), + } + } + Ok(recovered) => { + assert!(recovered); } - // Otherwise stop the parsing and return the error. - _ => return Err(err), } } first = false; @@ -845,8 +844,7 @@ impl<'a, 'b> Context<'a, 'b> { self.ecx.expr_match(self.macsp, head, vec![arm]) }; - let ident = Ident::from_str_and_span("args", self.macsp); - let args_slice = self.ecx.expr_ident(self.macsp, ident); + let args_slice = self.ecx.expr_addr_of(self.macsp, args_match); // Now create the fmt::Arguments struct with all our locals we created. let (fn_name, fn_args) = if self.all_pieces_simple { @@ -856,25 +854,22 @@ impl<'a, 'b> Context<'a, 'b> { // nonstandard placeholders, if there are any. let fmt = self.ecx.expr_vec_slice(self.macsp, self.pieces); - ("new_v1_formatted", vec![pieces, args_slice, fmt]) + let path = self.ecx.std_path(&[sym::fmt, sym::UnsafeArg, sym::new]); + let unsafe_arg = self.ecx.expr_call_global(self.macsp, path, Vec::new()); + let unsafe_expr = self.ecx.expr_block(P(ast::Block { + stmts: vec![self.ecx.stmt_expr(unsafe_arg)], + id: ast::DUMMY_NODE_ID, + rules: BlockCheckMode::Unsafe(UnsafeSource::CompilerGenerated), + span: self.macsp, + tokens: None, + could_be_bare_literal: false, + })); + + ("new_v1_formatted", vec![pieces, args_slice, fmt, unsafe_expr]) }; let path = self.ecx.std_path(&[sym::fmt, sym::Arguments, Symbol::intern(fn_name)]); - let arguments = self.ecx.expr_call_global(self.macsp, path, fn_args); - let body = self.ecx.expr_block(P(ast::Block { - stmts: vec![self.ecx.stmt_expr(arguments)], - id: ast::DUMMY_NODE_ID, - rules: BlockCheckMode::Unsafe(UnsafeSource::CompilerGenerated), - span: self.macsp, - tokens: None, - could_be_bare_literal: false, - })); - - let ident = Ident::from_str_and_span("args", self.macsp); - let binding_mode = ast::BindingMode::ByRef(ast::Mutability::Not); - let pat = self.ecx.pat_ident_binding_mode(self.macsp, ident, binding_mode); - let arm = self.ecx.arm(self.macsp, pat, body); - self.ecx.expr_match(self.macsp, args_match, vec![arm]) + self.ecx.expr_call_global(self.macsp, path, fn_args) } fn format_arg( @@ -964,17 +959,19 @@ pub fn expand_preparsed_format_args( } Ok(fmt) => fmt, Err(err) => { - if let Some(mut err) = err { + if let Some((mut err, suggested)) = err { let sugg_fmt = match args.len() { 0 => "{}".to_string(), _ => format!("{}{{}}", "{} ".repeat(args.len())), }; - err.span_suggestion( - fmt_sp.shrink_to_lo(), - "you might be missing a string literal to format with", - format!("\"{}\", ", sugg_fmt), - Applicability::MaybeIncorrect, - ); + if !suggested { + err.span_suggestion( + fmt_sp.shrink_to_lo(), + "you might be missing a string literal to format with", + format!("\"{}\", ", sugg_fmt), + Applicability::MaybeIncorrect, + ); + } err.emit(); } return DummyResult::raw_expr(sp, true); @@ -1157,11 +1154,12 @@ pub fn expand_preparsed_format_args( // account for `"` and account for raw strings `r#` let padding = str_style.map(|i| i + 2).unwrap_or(1); for sub in foreign::$kind::iter_subs(fmt_str, padding) { - let trn = match sub.translate() { - Some(trn) => trn, + let (trn, success) = match sub.translate() { + Ok(trn) => (trn, true), + Err(Some(msg)) => (msg, false), // If it has no translation, don't call it out specifically. - None => continue, + _ => continue, }; let pos = sub.position(); @@ -1178,9 +1176,24 @@ pub fn expand_preparsed_format_args( if let Some(inner_sp) = pos { let sp = fmt_sp.from_inner(inner_sp); - suggestions.push((sp, trn)); + + if success { + suggestions.push((sp, trn)); + } else { + diag.span_note( + sp, + &format!("format specifiers use curly braces, and {}", trn), + ); + } } else { - diag.help(&format!("`{}` should be written as `{}`", sub, trn)); + if success { + diag.help(&format!("`{}` should be written as `{}`", sub, trn)); + } else { + diag.note(&format!( + "`{}` should use curly braces, and {}", + sub, trn + )); + } } } diff --git a/compiler/rustc_builtin_macros/src/format_foreign.rs b/compiler/rustc_builtin_macros/src/format_foreign.rs index 0cc520e5bd..bfddd7073f 100644 --- a/compiler/rustc_builtin_macros/src/format_foreign.rs +++ b/compiler/rustc_builtin_macros/src/format_foreign.rs @@ -1,4 +1,4 @@ -pub mod printf { +pub(crate) mod printf { use super::strcursor::StrCursor as Cur; use rustc_span::InnerSpan; @@ -36,10 +36,10 @@ pub mod printf { /// /// This ignores cases where the substitution does not have an exact equivalent, or where /// the substitution would be unnecessary. - pub fn translate(&self) -> Option { + pub fn translate(&self) -> Result> { match *self { Substitution::Format(ref fmt) => fmt.translate(), - Substitution::Escape => None, + Substitution::Escape => Err(None), } } } @@ -68,9 +68,9 @@ pub mod printf { impl Format<'_> { /// Translate this directive into an equivalent Rust formatting directive. /// - /// Returns `None` in cases where the `printf` directive does not have an exact Rust + /// Returns `Err` in cases where the `printf` directive does not have an exact Rust /// equivalent, rather than guessing. - pub fn translate(&self) -> Option { + pub fn translate(&self) -> Result> { use std::fmt::Write; let (c_alt, c_zero, c_left, c_plus) = { @@ -84,7 +84,12 @@ pub mod printf { '0' => c_zero = true, '-' => c_left = true, '+' => c_plus = true, - _ => return None, + _ => { + return Err(Some(format!( + "the flag `{}` is unknown or unsupported", + c + ))); + } } } (c_alt, c_zero, c_left, c_plus) @@ -104,7 +109,9 @@ pub mod printf { let width = match self.width { Some(Num::Next) => { // NOTE: Rust doesn't support this. - return None; + return Err(Some( + "you have to use a positional or named parameter for the width".to_string(), + )); } w @ Some(Num::Arg(_)) => w, w @ Some(Num::Num(_)) => w, @@ -125,13 +132,21 @@ pub mod printf { "p" => (Some(self.type_), false, true), "g" => (Some("e"), true, false), "G" => (Some("E"), true, false), - _ => return None, + _ => { + return Err(Some(format!( + "the conversion specifier `{}` is unknown or unsupported", + self.type_ + ))); + } }; let (fill, width, precision) = match (is_int, width, precision) { (true, Some(_), Some(_)) => { // Rust can't duplicate this insanity. - return None; + return Err(Some( + "width and precision cannot both be specified for integer conversions" + .to_string(), + )); } (true, None, Some(p)) => (Some("0"), Some(p), None), (true, w, None) => (fill, w, None), @@ -169,7 +184,17 @@ pub mod printf { s.push('{'); if let Some(arg) = self.parameter { - write!(s, "{}", arg.checked_sub(1)?).ok()?; + match write!( + s, + "{}", + match arg.checked_sub(1) { + Some(a) => a, + None => return Err(None), + } + ) { + Err(_) => return Err(None), + _ => {} + } } if has_options { @@ -199,12 +224,18 @@ pub mod printf { } if let Some(width) = width { - width.translate(&mut s).ok()?; + match width.translate(&mut s) { + Err(_) => return Err(None), + _ => {} + } } if let Some(precision) = precision { s.push('.'); - precision.translate(&mut s).ok()?; + match precision.translate(&mut s) { + Err(_) => return Err(None), + _ => {} + } } if let Some(type_) = type_ { @@ -213,7 +244,7 @@ pub mod printf { } s.push('}'); - Some(s) + Ok(s) } } @@ -623,11 +654,11 @@ pub mod shell { } } - pub fn translate(&self) -> Option { + pub fn translate(&self) -> Result> { match *self { - Substitution::Ordinal(n, _) => Some(format!("{{{}}}", n)), - Substitution::Name(n, _) => Some(format!("{{{}}}", n)), - Substitution::Escape(_) => None, + Substitution::Ordinal(n, _) => Ok(format!("{{{}}}", n)), + Substitution::Name(n, _) => Ok(format!("{{{}}}", n)), + Substitution::Escape(_) => Err(None), } } } diff --git a/compiler/rustc_builtin_macros/src/format_foreign/printf/tests.rs b/compiler/rustc_builtin_macros/src/format_foreign/printf/tests.rs index 33c54c9cee..1336aab731 100644 --- a/compiler/rustc_builtin_macros/src/format_foreign/printf/tests.rs +++ b/compiler/rustc_builtin_macros/src/format_foreign/printf/tests.rs @@ -3,7 +3,7 @@ use super::{iter_subs, parse_next_substitution as pns, Format as F, Num as N, Su macro_rules! assert_eq_pnsat { ($lhs:expr, $rhs:expr) => { assert_eq!( - pns($lhs).and_then(|(s, _)| s.translate()), + pns($lhs).and_then(|(s, _)| s.translate().ok()), $rhs.map(>::from) ) }; @@ -98,7 +98,7 @@ fn test_parse() { #[test] fn test_iter() { let s = "The %d'th word %% is: `%.*s` %!\n"; - let subs: Vec<_> = iter_subs(s, 0).map(|sub| sub.translate()).collect(); + let subs: Vec<_> = iter_subs(s, 0).map(|sub| sub.translate().ok()).collect(); assert_eq!( subs.iter().map(|ms| ms.as_ref().map(|s| &s[..])).collect::>(), vec![Some("{}"), None, Some("{:.*}"), None] diff --git a/compiler/rustc_builtin_macros/src/format_foreign/shell/tests.rs b/compiler/rustc_builtin_macros/src/format_foreign/shell/tests.rs index ed8fe81dfc..f5f82732f2 100644 --- a/compiler/rustc_builtin_macros/src/format_foreign/shell/tests.rs +++ b/compiler/rustc_builtin_macros/src/format_foreign/shell/tests.rs @@ -3,7 +3,7 @@ use super::{parse_next_substitution as pns, Substitution as S}; macro_rules! assert_eq_pnsat { ($lhs:expr, $rhs:expr) => { assert_eq!( - pns($lhs).and_then(|(f, _)| f.translate()), + pns($lhs).and_then(|(f, _)| f.translate().ok()), $rhs.map(>::from) ) }; @@ -37,7 +37,7 @@ fn test_parse() { fn test_iter() { use super::iter_subs; let s = "The $0'th word $$ is: `$WORD` $!\n"; - let subs: Vec<_> = iter_subs(s, 0).map(|sub| sub.translate()).collect(); + let subs: Vec<_> = iter_subs(s, 0).map(|sub| sub.translate().ok()).collect(); assert_eq!( subs.iter().map(|ms| ms.as_ref().map(|s| &s[..])).collect::>(), vec![Some("{0}"), None, Some("{WORD}")] diff --git a/compiler/rustc_builtin_macros/src/test.rs b/compiler/rustc_builtin_macros/src/test.rs index 99544ddb66..bbca07085e 100644 --- a/compiler/rustc_builtin_macros/src/test.rs +++ b/compiler/rustc_builtin_macros/src/test.rs @@ -382,7 +382,7 @@ fn should_panic(cx: &ExtCtxt<'_>, i: &ast::Item) -> ShouldPanic { .note( "errors in this attribute were erroneously \ allowed and will become a hard error in a \ - future release.", + future release", ) .emit(); ShouldPanic::Yes(None) diff --git a/compiler/rustc_codegen_cranelift/Cargo.lock b/compiler/rustc_codegen_cranelift/Cargo.lock index 23c1fdc6ee..4afddf7686 100644 --- a/compiler/rustc_codegen_cranelift/Cargo.lock +++ b/compiler/rustc_codegen_cranelift/Cargo.lock @@ -33,16 +33,16 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "cranelift-bforest" -version = "0.75.0" -source = "git+https://github.com/bytecodealliance/wasmtime.git#5deda279775dca5e37449c829cda1f6276d6542b" +version = "0.76.0" +source = "git+https://github.com/bytecodealliance/wasmtime.git#9c550fcf41425942ed97c747f0169b2ca81f9c1b" dependencies = [ "cranelift-entity", ] [[package]] name = "cranelift-codegen" -version = "0.75.0" -source = "git+https://github.com/bytecodealliance/wasmtime.git#5deda279775dca5e37449c829cda1f6276d6542b" +version = "0.76.0" +source = "git+https://github.com/bytecodealliance/wasmtime.git#9c550fcf41425942ed97c747f0169b2ca81f9c1b" dependencies = [ "cranelift-bforest", "cranelift-codegen-meta", @@ -57,8 +57,8 @@ dependencies = [ [[package]] name = "cranelift-codegen-meta" -version = "0.75.0" -source = "git+https://github.com/bytecodealliance/wasmtime.git#5deda279775dca5e37449c829cda1f6276d6542b" +version = "0.76.0" +source = "git+https://github.com/bytecodealliance/wasmtime.git#9c550fcf41425942ed97c747f0169b2ca81f9c1b" dependencies = [ "cranelift-codegen-shared", "cranelift-entity", @@ -66,18 +66,18 @@ dependencies = [ [[package]] name = "cranelift-codegen-shared" -version = "0.75.0" -source = "git+https://github.com/bytecodealliance/wasmtime.git#5deda279775dca5e37449c829cda1f6276d6542b" +version = "0.76.0" +source = "git+https://github.com/bytecodealliance/wasmtime.git#9c550fcf41425942ed97c747f0169b2ca81f9c1b" [[package]] name = "cranelift-entity" -version = "0.75.0" -source = "git+https://github.com/bytecodealliance/wasmtime.git#5deda279775dca5e37449c829cda1f6276d6542b" +version = "0.76.0" +source = "git+https://github.com/bytecodealliance/wasmtime.git#9c550fcf41425942ed97c747f0169b2ca81f9c1b" [[package]] name = "cranelift-frontend" -version = "0.75.0" -source = "git+https://github.com/bytecodealliance/wasmtime.git#5deda279775dca5e37449c829cda1f6276d6542b" +version = "0.76.0" +source = "git+https://github.com/bytecodealliance/wasmtime.git#9c550fcf41425942ed97c747f0169b2ca81f9c1b" dependencies = [ "cranelift-codegen", "log", @@ -87,8 +87,8 @@ dependencies = [ [[package]] name = "cranelift-jit" -version = "0.75.0" -source = "git+https://github.com/bytecodealliance/wasmtime.git#5deda279775dca5e37449c829cda1f6276d6542b" +version = "0.76.0" +source = "git+https://github.com/bytecodealliance/wasmtime.git#9c550fcf41425942ed97c747f0169b2ca81f9c1b" dependencies = [ "anyhow", "cranelift-codegen", @@ -104,8 +104,8 @@ dependencies = [ [[package]] name = "cranelift-module" -version = "0.75.0" -source = "git+https://github.com/bytecodealliance/wasmtime.git#5deda279775dca5e37449c829cda1f6276d6542b" +version = "0.76.0" +source = "git+https://github.com/bytecodealliance/wasmtime.git#9c550fcf41425942ed97c747f0169b2ca81f9c1b" dependencies = [ "anyhow", "cranelift-codegen", @@ -115,8 +115,8 @@ dependencies = [ [[package]] name = "cranelift-native" -version = "0.75.0" -source = "git+https://github.com/bytecodealliance/wasmtime.git#5deda279775dca5e37449c829cda1f6276d6542b" +version = "0.76.0" +source = "git+https://github.com/bytecodealliance/wasmtime.git#9c550fcf41425942ed97c747f0169b2ca81f9c1b" dependencies = [ "cranelift-codegen", "libc", @@ -125,8 +125,8 @@ dependencies = [ [[package]] name = "cranelift-object" -version = "0.75.0" -source = "git+https://github.com/bytecodealliance/wasmtime.git#5deda279775dca5e37449c829cda1f6276d6542b" +version = "0.76.0" +source = "git+https://github.com/bytecodealliance/wasmtime.git#9c550fcf41425942ed97c747f0169b2ca81f9c1b" dependencies = [ "anyhow", "cranelift-codegen", diff --git a/compiler/rustc_codegen_cranelift/Cargo.toml b/compiler/rustc_codegen_cranelift/Cargo.toml index 6f40fc0fcb..61d40702a3 100644 --- a/compiler/rustc_codegen_cranelift/Cargo.toml +++ b/compiler/rustc_codegen_cranelift/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustc_codegen_cranelift" version = "0.1.0" -edition = "2018" +edition = "2021" [lib] crate-type = ["dylib"] diff --git a/compiler/rustc_codegen_cranelift/build_sysroot/Cargo.lock b/compiler/rustc_codegen_cranelift/build_sysroot/Cargo.lock index e068f08423..22be21cb8d 100644 --- a/compiler/rustc_codegen_cranelift/build_sysroot/Cargo.lock +++ b/compiler/rustc_codegen_cranelift/build_sysroot/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "addr2line" -version = "0.14.1" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a55f82cfe485775d02112886f4169bde0c5894d75e79ead7eafe7e40a25e45f7" +checksum = "3e61f2b7f93d2c7d2b08263acaa4a363b3e276806c68af6134c44f523bf1aacd" dependencies = [ "compiler_builtins", "gimli", @@ -40,9 +40,9 @@ checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" [[package]] name = "cc" -version = "1.0.69" +version = "1.0.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e70cc2f62c6ce1868963827bd677764c62d07c3d9a3e1fb1177ee1a9ab199eb2" +checksum = "d26a6ce4b6a484fa3edb70f7efa6fc430fd2b87285fe8b84304fd0936faa0dc0" [[package]] name = "cfg-if" @@ -56,7 +56,7 @@ dependencies = [ [[package]] name = "compiler_builtins" -version = "0.1.46" +version = "0.1.50" dependencies = [ "rustc-std-workspace-core", ] @@ -99,9 +99,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.23.0" +version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6503fe142514ca4799d4c26297c4248239fe8838d827db6bd6065c6ed29a6ce" +checksum = "f0a01e0497841a3b2db4f8afa483cce65f7e96a3498bd6c541734792aeac8fe7" dependencies = [ "compiler_builtins", "rustc-std-workspace-alloc", @@ -132,13 +132,23 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.98" +version = "0.2.102" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "320cfe77175da3a483efed4bc0adc1968ca050b098ce4f2f1c13a56626128790" +checksum = "a2a5ac8f984bfcf3a823267e5fde638acc3325f6496633a5da6bb6eb2171e103" dependencies = [ "rustc-std-workspace-core", ] +[[package]] +name = "memchr" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" +dependencies = [ + "compiler_builtins", + "rustc-std-workspace-core", +] + [[package]] name = "miniz_oxide" version = "0.4.4" @@ -154,11 +164,12 @@ dependencies = [ [[package]] name = "object" -version = "0.22.0" +version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d3b63360ec3cb337817c2dbd47ab4a0f170d285d8e5a2064600f3def1402397" +checksum = "39f37e50073ccad23b6d09bcb5b263f4e76d3bb6038e4a3c08e52162ffa8abc2" dependencies = [ "compiler_builtins", + "memchr", "rustc-std-workspace-alloc", "rustc-std-workspace-core", ] @@ -195,9 +206,9 @@ dependencies = [ [[package]] name = "rustc-demangle" -version = "0.1.20" +version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dead70b0b5e03e9c814bcb6b01e03e68f7c57a80aa48c72ec92152ab3e818d49" +checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342" dependencies = [ "compiler_builtins", "rustc-std-workspace-core", @@ -286,9 +297,9 @@ dependencies = [ [[package]] name = "unicode-width" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3" +checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" dependencies = [ "compiler_builtins", "rustc-std-workspace-core", diff --git a/compiler/rustc_codegen_cranelift/build_system/prepare.rs b/compiler/rustc_codegen_cranelift/build_system/prepare.rs index 4b2051b605..ae9a35048b 100644 --- a/compiler/rustc_codegen_cranelift/build_system/prepare.rs +++ b/compiler/rustc_codegen_cranelift/build_system/prepare.rs @@ -28,11 +28,11 @@ pub(crate) fn prepare() { ); clone_repo( - "stdsimd", - "https://github.com/rust-lang/stdsimd", - "be96995d8ddec03fac9a0caf4d4c51c7fbc33507", + "portable-simd", + "https://github.com/rust-lang/portable-simd", + "8cf7a62e5d2552961df51e5200aaa5b7c890a4bf", ); - apply_patches("stdsimd", Path::new("stdsimd")); + apply_patches("portable-simd", Path::new("portable-simd")); clone_repo( "simple-raytracer", @@ -92,7 +92,7 @@ fn prepare_sysroot() { clone_repo( "build_sysroot/compiler-builtins", "https://github.com/rust-lang/compiler-builtins.git", - "0.1.46", + "0.1.50", ); apply_patches("compiler-builtins", Path::new("build_sysroot/compiler-builtins")); } diff --git a/compiler/rustc_codegen_cranelift/clean_all.sh b/compiler/rustc_codegen_cranelift/clean_all.sh index 23e5bf2e0a..865de7d234 100755 --- a/compiler/rustc_codegen_cranelift/clean_all.sh +++ b/compiler/rustc_codegen_cranelift/clean_all.sh @@ -3,4 +3,4 @@ set -e rm -rf build_sysroot/{sysroot_src/,target/,compiler-builtins/,rustc_version} rm -rf target/ build/ perf.data{,.old} -rm -rf rand/ regex/ simple-raytracer/ stdsimd/ +rm -rf rand/ regex/ simple-raytracer/ portable-simd/ diff --git a/compiler/rustc_codegen_cranelift/docs/usage.md b/compiler/rustc_codegen_cranelift/docs/usage.md index 87eec0e818..bcc5745d9d 100644 --- a/compiler/rustc_codegen_cranelift/docs/usage.md +++ b/compiler/rustc_codegen_cranelift/docs/usage.md @@ -24,6 +24,8 @@ $ $cg_clif_dir/build/bin/cg_clif my_crate.rs ## Jit mode +> ⚠⚠⚠ The JIT mode is highly experimental. It may be slower than AOT compilation due to lack of incremental compilation. It may also be hard to setup if you have cargo dependencies. ⚠⚠⚠ + In jit mode cg_clif will immediately execute your code without creating an executable file. > This requires all dependencies to be available as dynamic library. diff --git a/compiler/rustc_codegen_cranelift/example/alloc_example.rs b/compiler/rustc_codegen_cranelift/example/alloc_example.rs index 2a9f7e58e0..bc1594d82e 100644 --- a/compiler/rustc_codegen_cranelift/example/alloc_example.rs +++ b/compiler/rustc_codegen_cranelift/example/alloc_example.rs @@ -1,10 +1,10 @@ -#![feature(start, core_intrinsics, alloc_prelude, alloc_error_handler)] +#![feature(start, core_intrinsics, alloc_error_handler, box_syntax)] #![no_std] extern crate alloc; extern crate alloc_system; -use alloc::prelude::v1::*; +use alloc::boxed::Box; use alloc_system::System; diff --git a/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs b/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs index 6e13e4dcbf..cbfdb3c44f 100644 --- a/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs +++ b/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs @@ -1,4 +1,4 @@ -#![feature(no_core, lang_items, never_type, linkage, extern_types, thread_local)] +#![feature(no_core, lang_items, never_type, linkage, extern_types, thread_local, box_syntax)] #![no_core] #![allow(dead_code, non_camel_case_types)] diff --git a/compiler/rustc_codegen_cranelift/patches/0001-stdsimd-Disable-unsupported-tests.patch b/compiler/rustc_codegen_cranelift/patches/0001-portable-simd-Disable-unsupported-tests.patch similarity index 77% rename from compiler/rustc_codegen_cranelift/patches/0001-stdsimd-Disable-unsupported-tests.patch rename to compiler/rustc_codegen_cranelift/patches/0001-portable-simd-Disable-unsupported-tests.patch index 731c60fda5..2e68369466 100644 --- a/compiler/rustc_codegen_cranelift/patches/0001-stdsimd-Disable-unsupported-tests.patch +++ b/compiler/rustc_codegen_cranelift/patches/0001-portable-simd-Disable-unsupported-tests.patch @@ -4,21 +4,20 @@ Date: Sun, 25 Jul 2021 18:39:31 +0200 Subject: [PATCH] Disable unsupported tests --- - crates/core_simd/src/array.rs | 2 ++ - crates/core_simd/src/lib.rs | 2 +- + crates/core_simd/src/vector.rs | 2 ++ crates/core_simd/src/math.rs | 4 ++++ crates/core_simd/tests/masks.rs | 12 ------------ crates/core_simd/tests/ops_macros.rs | 6 ++++++ crates/core_simd/tests/round.rs | 2 ++ 6 files changed, 15 insertions(+), 13 deletions(-) -diff --git a/crates/core_simd/src/array.rs b/crates/core_simd/src/array.rs +diff --git a/crates/core_simd/src/vector.rs b/crates/core_simd/src/vector.rs index 25c5309..2b3d819 100644 ---- a/crates/core_simd/src/array.rs -+++ b/crates/core_simd/src/array.rs +--- a/crates/core_simd/src/vector.rs ++++ b/crates/core_simd/src/vector.rs @@ -22,6 +22,7 @@ where - #[must_use] - fn splat(val: Self::Scalar) -> Self; + self.0 + } + /* /// SIMD gather: construct a SIMD vector by reading from a slice, using potentially discontiguous indices. @@ -31,27 +30,14 @@ index 25c5309..2b3d819 100644 + */ } - macro_rules! impl_simdarray_for { -diff --git a/crates/core_simd/src/lib.rs b/crates/core_simd/src/lib.rs -index a64904d..299eb11 100644 ---- a/crates/core_simd/src/lib.rs -+++ b/crates/core_simd/src/lib.rs -@@ -1,7 +1,7 @@ - #![no_std] - #![allow(incomplete_features)] - #![feature( -- const_generics, -+ const_generics, - platform_intrinsics, - repr_simd, - simd_ffi, + impl Copy for Simd diff --git a/crates/core_simd/src/math.rs b/crates/core_simd/src/math.rs index 7290a28..e394730 100644 --- a/crates/core_simd/src/math.rs +++ b/crates/core_simd/src/math.rs @@ -2,6 +2,7 @@ macro_rules! impl_uint_arith { - ($(($name:ident, $n:ident)),+) => { - $( impl $name where Self: crate::LanesAtMost32 { + ($($ty:ty),+) => { + $( impl Simd<$ty, LANES> where LaneCount: SupportedLaneCount { + /* /// Lanewise saturating add. @@ -66,8 +52,8 @@ index 7290a28..e394730 100644 } } @@ -46,6 +48,7 @@ macro_rules! impl_int_arith { - ($(($name:ident, $n:ident)),+) => { - $( impl $name where Self: crate::LanesAtMost32 { + ($($ty:ty),+) => { + $( impl Simd<$ty, LANES> where LaneCount: SupportedLaneCount { + /* /// Lanewise saturating add. @@ -85,21 +71,22 @@ diff --git a/crates/core_simd/tests/masks.rs b/crates/core_simd/tests/masks.rs index 61d8e44..2bccae2 100644 --- a/crates/core_simd/tests/masks.rs +++ b/crates/core_simd/tests/masks.rs -@@ -67,18 +67,6 @@ macro_rules! test_mask_api { +@@ -67,19 +67,6 @@ macro_rules! test_mask_api { assert_eq!(int.to_array(), [-1, 0, 0, -1, 0, 0, -1, 0]); - assert_eq!(core_simd::$name::<8>::from_int(int), mask); + 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::$name::<16>::from_array(values); +- let mask = core_simd::Mask::<$type, 16>::from_array(values); - let bitmask = mask.to_bitmask(); - assert_eq!(bitmask, [0b01001001, 0b10000011]); -- assert_eq!(core_simd::$name::<16>::from_bitmask(bitmask), mask); +- assert_eq!(core_simd::Mask::<$type, 16>::from_bitmask(bitmask), mask); - } } } @@ -122,7 +109,7 @@ index cb39e73..fc0ebe1 100644 } + */ - fn sqrt() { + fn recip() { test_helpers::test_unary_elementwise( @@ -581,6 +585,7 @@ macro_rules! impl_float_tests { }); @@ -138,8 +125,8 @@ index cb39e73..fc0ebe1 100644 } + */ } - } - } + + #[cfg(feature = "std")] diff --git a/crates/core_simd/tests/round.rs b/crates/core_simd/tests/round.rs index 37044a7..4cdc6b7 100644 --- a/crates/core_simd/tests/round.rs diff --git a/compiler/rustc_codegen_cranelift/patches/0027-sysroot-128bit-atomic-operations.patch b/compiler/rustc_codegen_cranelift/patches/0027-sysroot-128bit-atomic-operations.patch index cda8153083..e2d07bd126 100644 --- a/compiler/rustc_codegen_cranelift/patches/0027-sysroot-128bit-atomic-operations.patch +++ b/compiler/rustc_codegen_cranelift/patches/0027-sysroot-128bit-atomic-operations.patch @@ -1,4 +1,4 @@ -From 6a4e6f5dc8c8a529a822eb9b57f9e57519595439 Mon Sep 17 00:00:00 2001 +From ad7ffe71baba46865f2e65266ab025920dfdc20b Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Thu, 18 Feb 2021 18:45:28 +0100 Subject: [PATCH] Disable 128bit atomic operations @@ -8,7 +8,8 @@ Cranelift doesn't support them yet library/core/src/panic/unwind_safe.rs | 6 ----- library/core/src/sync/atomic.rs | 38 --------------------------- library/core/tests/atomic.rs | 4 --- - 3 files changed, 48 deletions(-) + library/std/src/time/monotonic.rs | 6 +++-- + 4 files changed, 4 insertions(+), 50 deletions(-) diff --git a/library/core/src/panic/unwind_safe.rs b/library/core/src/panic/unwind_safe.rs index 092b7cf..158cf71 100644 @@ -35,10 +36,10 @@ index 092b7cf..158cf71 100644 #[cfg(target_has_atomic_load_store = "8")] #[stable(feature = "unwind_safe_atomic_refs", since = "1.14.0")] diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs -index 0194c58..25a0038 100644 +index d9de37e..8293fce 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs -@@ -2229,44 +2229,6 @@ atomic_int! { +@@ -2234,44 +2234,6 @@ atomic_int! { "AtomicU64::new(0)", u64 AtomicU64 ATOMIC_U64_INIT } @@ -98,6 +99,38 @@ index b735957..ea728b6 100644 #[cfg(target_has_atomic = "ptr")] assert_eq!(align_of::(), size_of::()); #[cfg(target_has_atomic = "ptr")] +diff --git a/library/std/src/time/monotonic.rs b/library/std/src/time/monotonic.rs +index fa96b7a..2854f9c 100644 +--- a/library/std/src/time/monotonic.rs ++++ b/library/std/src/time/monotonic.rs +@@ -5,7 +5,7 @@ pub(super) fn monotonize(raw: time::Instant) -> time::Instant { + inner::monotonize(raw) + } + +-#[cfg(all(target_has_atomic = "64", not(target_has_atomic = "128")))] ++#[cfg(target_has_atomic = "64")] + pub mod inner { + use crate::sync::atomic::AtomicU64; + use crate::sync::atomic::Ordering::*; +@@ -70,6 +70,7 @@ pub mod inner { + } + } + ++/* + #[cfg(target_has_atomic = "128")] + pub mod inner { + use crate::sync::atomic::AtomicU128; +@@ -94,8 +95,9 @@ pub mod inner { + ZERO.checked_add_duration(&Duration::new(secs, nanos)).unwrap() + } + } ++*/ + +-#[cfg(not(any(target_has_atomic = "64", target_has_atomic = "128")))] ++#[cfg(not(target_has_atomic = "64"))] + pub mod inner { + use crate::cmp; + use crate::sys::time; -- 2.26.2.7.g19db9cfb68 diff --git a/compiler/rustc_codegen_cranelift/rust-toolchain b/compiler/rustc_codegen_cranelift/rust-toolchain index f074ebe7a4..360570b3ae 100644 --- a/compiler/rustc_codegen_cranelift/rust-toolchain +++ b/compiler/rustc_codegen_cranelift/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2021-08-05" +channel = "nightly-2021-09-19" components = ["rust-src", "rustc-dev", "llvm-tools-preview"] diff --git a/compiler/rustc_codegen_cranelift/scripts/filter_profile.rs b/compiler/rustc_codegen_cranelift/scripts/filter_profile.rs index c4801a0a87..a0e99267c2 100755 --- a/compiler/rustc_codegen_cranelift/scripts/filter_profile.rs +++ b/compiler/rustc_codegen_cranelift/scripts/filter_profile.rs @@ -42,7 +42,7 @@ fn main() -> Result<(), Box> { continue; } - if stack.contains("rustc_mir::monomorphize::partitioning::collect_and_partition_mono_items") + if stack.contains("rustc_monomorphize::partitioning::collect_and_partition_mono_items") || stack.contains("rustc_incremental::assert_dep_graph::assert_dep_graph") || stack.contains("rustc_symbol_mangling::test::report_symbol_names") { @@ -81,7 +81,7 @@ fn main() -> Result<(), Box> { } const COLLECT_AND_PARTITION_MONO_ITEMS: &str = - "rustc_mir::monomorphize::partitioning::collect_and_partition_mono_items"; + "rustc_monomorphize::partitioning::collect_and_partition_mono_items"; if let Some(index) = stack.find(COLLECT_AND_PARTITION_MONO_ITEMS) { stack = &stack[..index + COLLECT_AND_PARTITION_MONO_ITEMS.len()]; } @@ -96,7 +96,7 @@ fn main() -> Result<(), Box> { stack = &stack[..index + REPORT_SYMBOL_NAMES.len()]; } - const ENCODE_METADATA: &str = "rustc_middle::ty::context::TyCtxt::encode_metadata"; + const ENCODE_METADATA: &str = "rustc_metadata::rmeta::encoder::encode_metadata"; if let Some(index) = stack.find(ENCODE_METADATA) { stack = &stack[..index + ENCODE_METADATA.len()]; } diff --git a/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh b/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh index 0ac49dd357..b714d47fec 100755 --- a/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh +++ b/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh @@ -11,7 +11,7 @@ pushd rust cargo install ripgrep rm -r src/test/ui/{extern/,panics/,unsized-locals/,thinlto/,simd*,*lto*.rs,linkage*,unwind-*.rs} || true -for test in $(rg --files-with-matches "asm!|catch_unwind|should_panic|lto" src/test/ui); do +for test in $(rg --files-with-matches "asm!|catch_unwind|should_panic|lto|// needs-asm-support" src/test/ui); do rm $test done diff --git a/compiler/rustc_codegen_cranelift/scripts/tests.sh b/compiler/rustc_codegen_cranelift/scripts/tests.sh index 0eef710239..28a7980d66 100755 --- a/compiler/rustc_codegen_cranelift/scripts/tests.sh +++ b/compiler/rustc_codegen_cranelift/scripts/tests.sh @@ -137,8 +137,8 @@ function extended_sysroot_tests() { fi popd - pushd stdsimd - echo "[TEST] rust-lang/stdsimd" + pushd portable-simd + echo "[TEST] rust-lang/portable-simd" ../build/cargo clean ../build/cargo build --all-targets --target $TARGET_TRIPLE if [[ "$HOST_TRIPLE" = "$TARGET_TRIPLE" ]]; then diff --git a/compiler/rustc_codegen_cranelift/src/abi/mod.rs b/compiler/rustc_codegen_cranelift/src/abi/mod.rs index 13790409e5..78fdf9c02d 100644 --- a/compiler/rustc_codegen_cranelift/src/abi/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/abi/mod.rs @@ -5,7 +5,7 @@ mod pass_mode; mod returning; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; -use rustc_middle::ty::layout::FnAbiExt; +use rustc_middle::ty::layout::FnAbiOf; use rustc_target::abi::call::{Conv, FnAbi}; use rustc_target::spec::abi::Abi; @@ -53,7 +53,11 @@ pub(crate) fn get_function_sig<'tcx>( inst: Instance<'tcx>, ) -> Signature { assert!(!inst.substs.needs_infer()); - clif_sig_from_fn_abi(tcx, triple, &FnAbi::of_instance(&RevealAllLayoutCx(tcx), inst, &[])) + clif_sig_from_fn_abi( + tcx, + triple, + &RevealAllLayoutCx(tcx).fn_abi_of_instance(inst, ty::List::empty()), + ) } /// Instance must be monomorphized @@ -305,13 +309,13 @@ pub(crate) fn codegen_terminator_call<'tcx>( span: Span, func: &Operand<'tcx>, args: &[Operand<'tcx>], - destination: Option<(Place<'tcx>, BasicBlock)>, + mir_dest: Option<(Place<'tcx>, BasicBlock)>, ) { let fn_ty = fx.monomorphize(func.ty(fx.mir, fx.tcx)); let fn_sig = fx.tcx.normalize_erasing_late_bound_regions(ParamEnv::reveal_all(), fn_ty.fn_sig(fx.tcx)); - let destination = destination.map(|(place, bb)| (codegen_place(fx, place), bb)); + let destination = mir_dest.map(|(place, bb)| (codegen_place(fx, place), bb)); // Handle special calls like instrinsics and empty drop glue. let instance = if let ty::FnDef(def_id, substs) = *fn_ty.kind() { @@ -350,14 +354,13 @@ pub(crate) fn codegen_terminator_call<'tcx>( }; let extra_args = &args[fn_sig.inputs().len()..]; - let extra_args = extra_args - .iter() - .map(|op_arg| fx.monomorphize(op_arg.ty(fx.mir, fx.tcx))) - .collect::>(); + let extra_args = fx + .tcx + .mk_type_list(extra_args.iter().map(|op_arg| fx.monomorphize(op_arg.ty(fx.mir, fx.tcx)))); let fn_abi = if let Some(instance) = instance { - FnAbi::of_instance(&RevealAllLayoutCx(fx.tcx), instance, &extra_args) + RevealAllLayoutCx(fx.tcx).fn_abi_of_instance(instance, extra_args) } else { - FnAbi::of_fn_ptr(&RevealAllLayoutCx(fx.tcx), fn_ty.fn_sig(fx.tcx), &extra_args) + RevealAllLayoutCx(fx.tcx).fn_abi_of_fn_ptr(fn_ty.fn_sig(fx.tcx), extra_args) }; let is_cold = instance @@ -525,7 +528,8 @@ pub(crate) fn codegen_drop<'tcx>( def: ty::InstanceDef::Virtual(drop_instance.def_id(), 0), substs: drop_instance.substs, }; - let fn_abi = FnAbi::of_instance(&RevealAllLayoutCx(fx.tcx), virtual_drop, &[]); + let fn_abi = + RevealAllLayoutCx(fx.tcx).fn_abi_of_instance(virtual_drop, ty::List::empty()); let sig = clif_sig_from_fn_abi(fx.tcx, fx.triple(), &fn_abi); let sig = fx.bcx.import_signature(sig); @@ -534,7 +538,8 @@ pub(crate) fn codegen_drop<'tcx>( _ => { assert!(!matches!(drop_instance.def, InstanceDef::Virtual(_, _))); - let fn_abi = FnAbi::of_instance(&RevealAllLayoutCx(fx.tcx), drop_instance, &[]); + let fn_abi = + RevealAllLayoutCx(fx.tcx).fn_abi_of_instance(drop_instance, ty::List::empty()); let arg_value = drop_place.place_ref( fx, diff --git a/compiler/rustc_codegen_cranelift/src/abi/pass_mode.rs b/compiler/rustc_codegen_cranelift/src/abi/pass_mode.rs index 44eae706ea..2144e7ed67 100644 --- a/compiler/rustc_codegen_cranelift/src/abi/pass_mode.rs +++ b/compiler/rustc_codegen_cranelift/src/abi/pass_mode.rs @@ -92,9 +92,9 @@ impl<'tcx> ArgAbiExt<'tcx> for ArgAbi<'tcx, Ty<'tcx>> { fn get_abi_param(&self, tcx: TyCtxt<'tcx>) -> SmallVec<[AbiParam; 2]> { match self.mode { PassMode::Ignore => smallvec![], - PassMode::Direct(attrs) => match &self.layout.abi { + PassMode::Direct(attrs) => match self.layout.abi { Abi::Scalar(scalar) => smallvec![apply_arg_attrs_to_abi_param( - AbiParam::new(scalar_to_clif_type(tcx, scalar.clone())), + AbiParam::new(scalar_to_clif_type(tcx, scalar)), attrs )], Abi::Vector { .. } => { @@ -103,10 +103,10 @@ impl<'tcx> ArgAbiExt<'tcx> for ArgAbi<'tcx, Ty<'tcx>> { } _ => unreachable!("{:?}", self.layout.abi), }, - PassMode::Pair(attrs_a, attrs_b) => match &self.layout.abi { + PassMode::Pair(attrs_a, attrs_b) => match self.layout.abi { Abi::ScalarPair(a, b) => { - let a = scalar_to_clif_type(tcx, a.clone()); - let b = scalar_to_clif_type(tcx, b.clone()); + let a = scalar_to_clif_type(tcx, a); + let b = scalar_to_clif_type(tcx, b); smallvec![ apply_arg_attrs_to_abi_param(AbiParam::new(a), attrs_a), apply_arg_attrs_to_abi_param(AbiParam::new(b), attrs_b), @@ -139,9 +139,9 @@ impl<'tcx> ArgAbiExt<'tcx> for ArgAbi<'tcx, Ty<'tcx>> { fn get_abi_return(&self, tcx: TyCtxt<'tcx>) -> (Option, Vec) { match self.mode { PassMode::Ignore => (None, vec![]), - PassMode::Direct(_) => match &self.layout.abi { + PassMode::Direct(_) => match self.layout.abi { Abi::Scalar(scalar) => { - (None, vec![AbiParam::new(scalar_to_clif_type(tcx, scalar.clone()))]) + (None, vec![AbiParam::new(scalar_to_clif_type(tcx, scalar))]) } Abi::Vector { .. } => { let vector_ty = crate::intrinsics::clif_vector_type(tcx, self.layout).unwrap(); @@ -149,10 +149,10 @@ impl<'tcx> ArgAbiExt<'tcx> for ArgAbi<'tcx, Ty<'tcx>> { } _ => unreachable!("{:?}", self.layout.abi), }, - PassMode::Pair(_, _) => match &self.layout.abi { + PassMode::Pair(_, _) => match self.layout.abi { Abi::ScalarPair(a, b) => { - let a = scalar_to_clif_type(tcx, a.clone()); - let b = scalar_to_clif_type(tcx, b.clone()); + let a = scalar_to_clif_type(tcx, a); + let b = scalar_to_clif_type(tcx, b); (None, vec![AbiParam::new(a), AbiParam::new(b)]) } _ => unreachable!("{:?}", self.layout.abi), diff --git a/compiler/rustc_codegen_cranelift/src/archive.rs b/compiler/rustc_codegen_cranelift/src/archive.rs index 22897c43e7..71f510c037 100644 --- a/compiler/rustc_codegen_cranelift/src/archive.rs +++ b/compiler/rustc_codegen_cranelift/src/archive.rs @@ -1,53 +1,51 @@ //! Creation of ar archives like for the lib and staticlib crate type use std::collections::BTreeMap; +use std::convert::TryFrom; use std::fs::File; +use std::io::{self, Read, Seek}; use std::path::{Path, PathBuf}; -use rustc_codegen_ssa::back::archive::{find_library, ArchiveBuilder}; -use rustc_codegen_ssa::METADATA_FILENAME; +use rustc_codegen_ssa::back::archive::ArchiveBuilder; use rustc_session::Session; -use object::{Object, ObjectSymbol, SymbolKind}; +use object::read::archive::ArchiveFile; +use object::{Object, ObjectSymbol, ReadCache, SymbolKind}; #[derive(Debug)] enum ArchiveEntry { - FromArchive { archive_index: usize, entry_index: usize }, + FromArchive { archive_index: usize, file_range: (u64, u64) }, File(PathBuf), } pub(crate) struct ArArchiveBuilder<'a> { sess: &'a Session, dst: PathBuf, - lib_search_paths: Vec, use_gnu_style_archive: bool, no_builtin_ranlib: bool, - src_archives: Vec<(PathBuf, ar::Archive)>, + src_archives: Vec, // Don't use `HashMap` here, as the order is important. `rust.metadata.bin` must always be at // the end of an archive for linkers to not get confused. - entries: Vec<(String, ArchiveEntry)>, + entries: Vec<(Vec, ArchiveEntry)>, } impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> { fn new(sess: &'a Session, output: &Path, input: Option<&Path>) -> Self { - use rustc_codegen_ssa::back::link::archive_search_paths; - let (src_archives, entries) = if let Some(input) = input { - let mut archive = ar::Archive::new(File::open(input).unwrap()); + let read_cache = ReadCache::new(File::open(input).unwrap()); + let archive = ArchiveFile::parse(&read_cache).unwrap(); let mut entries = Vec::new(); - let mut i = 0; - while let Some(entry) = archive.next_entry() { + for entry in archive.members() { let entry = entry.unwrap(); entries.push(( - String::from_utf8(entry.header().identifier().to_vec()).unwrap(), - ArchiveEntry::FromArchive { archive_index: 0, entry_index: i }, + entry.name().to_vec(), + ArchiveEntry::FromArchive { archive_index: 0, file_range: entry.file_range() }, )); - i += 1; } - (vec![(input.to_owned(), archive)], entries) + (vec![read_cache.into_inner()], entries) } else { (vec![], Vec::new()) }; @@ -55,7 +53,6 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> { ArArchiveBuilder { sess, dst: output.to_path_buf(), - lib_search_paths: archive_search_paths(sess), use_gnu_style_archive: sess.target.archive_format == "gnu", // FIXME fix builtin ranlib on macOS no_builtin_ranlib: sess.target.is_like_osx, @@ -66,61 +63,47 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> { } fn src_files(&mut self) -> Vec { - self.entries.iter().map(|(name, _)| name.clone()).collect() + self.entries.iter().map(|(name, _)| String::from_utf8(name.clone()).unwrap()).collect() } fn remove_file(&mut self, name: &str) { let index = self .entries .iter() - .position(|(entry_name, _)| entry_name == name) + .position(|(entry_name, _)| entry_name == name.as_bytes()) .expect("Tried to remove file not existing in src archive"); self.entries.remove(index); } fn add_file(&mut self, file: &Path) { self.entries.push(( - file.file_name().unwrap().to_str().unwrap().to_string(), + file.file_name().unwrap().to_str().unwrap().to_string().into_bytes(), ArchiveEntry::File(file.to_owned()), )); } - fn add_native_library(&mut self, name: rustc_span::symbol::Symbol, verbatim: bool) { - let location = find_library(name, verbatim, &self.lib_search_paths, self.sess); - self.add_archive(location.clone(), |_| false).unwrap_or_else(|e| { - panic!("failed to add native library {}: {}", location.to_string_lossy(), e); - }); - } + fn add_archive(&mut self, archive_path: &Path, mut skip: F) -> std::io::Result<()> + where + F: FnMut(&str) -> bool + 'static, + { + let read_cache = ReadCache::new(std::fs::File::open(&archive_path)?); + let archive = ArchiveFile::parse(&read_cache).unwrap(); + let archive_index = self.src_archives.len(); - fn add_rlib( - &mut self, - rlib: &Path, - name: &str, - lto: bool, - skip_objects: bool, - ) -> std::io::Result<()> { - let obj_start = name.to_owned(); - - self.add_archive(rlib.to_owned(), move |fname: &str| { - // Ignore metadata files, no matter the name. - if fname == METADATA_FILENAME { - return true; + for entry in archive.members() { + let entry = entry.map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?; + let file_name = String::from_utf8(entry.name().to_vec()) + .map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?; + if !skip(&file_name) { + self.entries.push(( + file_name.into_bytes(), + ArchiveEntry::FromArchive { archive_index, file_range: entry.file_range() }, + )); } + } - // Don't include Rust objects if LTO is enabled - if lto && fname.starts_with(&obj_start) && fname.ends_with(".o") { - return true; - } - - // Otherwise if this is *not* a rust object and we're skipping - // objects then skip this file - if skip_objects && (!fname.starts_with(&obj_start) || !fname.ends_with(".o")) { - return true; - } - - // ok, don't skip this - false - }) + self.src_archives.push(read_cache.into_inner()); + Ok(()) } fn update_symbols(&mut self) {} @@ -141,14 +124,14 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> { // FIXME only read the symbol table of the object files to avoid having to keep all // object files in memory at once, or read them twice. let data = match entry { - ArchiveEntry::FromArchive { archive_index, entry_index } => { + ArchiveEntry::FromArchive { archive_index, file_range } => { // FIXME read symbols from symtab - use std::io::Read; - let (ref _src_archive_path, ref mut src_archive) = - self.src_archives[archive_index]; - let mut entry = src_archive.jump_to_entry(entry_index).unwrap(); - let mut data = Vec::new(); - entry.read_to_end(&mut data).unwrap(); + let src_read_cache = &mut self.src_archives[archive_index]; + + src_read_cache.seek(io::SeekFrom::Start(file_range.0)).unwrap(); + let mut data = std::vec::from_elem(0, usize::try_from(file_range.1).unwrap()); + src_read_cache.read_exact(&mut data).unwrap(); + data } ArchiveEntry::File(file) => std::fs::read(file).unwrap_or_else(|err| { @@ -163,7 +146,7 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> { match object::File::parse(&*data) { Ok(object) => { symbol_table.insert( - entry_name.as_bytes().to_vec(), + entry_name.to_vec(), object .symbols() .filter_map(|symbol| { @@ -188,7 +171,8 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> { } else { sess.fatal(&format!( "error parsing `{}` during archive creation: {}", - entry_name, err + String::from_utf8_lossy(&entry_name), + err )); } } @@ -207,7 +191,7 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> { err )); }), - entries.iter().map(|(name, _)| name.as_bytes().to_vec()).collect(), + entries.iter().map(|(name, _)| name.clone()).collect(), ar::GnuSymbolTableFormat::Size32, symbol_table, ) @@ -230,7 +214,7 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> { // Add all files for (entry_name, data) in entries.into_iter() { - let header = ar::Header::new(entry_name.into_bytes(), data.len() as u64); + let header = ar::Header::new(entry_name, data.len() as u64); match builder { BuilderKind::Bsd(ref mut builder) => builder.append(&header, &mut &*data).unwrap(), BuilderKind::Gnu(ref mut builder) => builder.append(&header, &mut &*data).unwrap(), @@ -258,34 +242,9 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> { fn inject_dll_import_lib( &mut self, _lib_name: &str, - _dll_imports: &[rustc_middle::middle::cstore::DllImport], + _dll_imports: &[rustc_session::cstore::DllImport], _tmpdir: &rustc_data_structures::temp_dir::MaybeTempDir, ) { bug!("injecting dll imports is not supported"); } } - -impl<'a> ArArchiveBuilder<'a> { - fn add_archive(&mut self, archive_path: PathBuf, mut skip: F) -> std::io::Result<()> - where - F: FnMut(&str) -> bool + 'static, - { - let mut archive = ar::Archive::new(std::fs::File::open(&archive_path)?); - let archive_index = self.src_archives.len(); - - let mut i = 0; - while let Some(entry) = archive.next_entry() { - let entry = entry?; - let file_name = String::from_utf8(entry.header().identifier().to_vec()) - .map_err(|err| std::io::Error::new(std::io::ErrorKind::InvalidData, err))?; - if !skip(&file_name) { - self.entries - .push((file_name, ArchiveEntry::FromArchive { archive_index, entry_index: i })); - } - i += 1; - } - - self.src_archives.push((archive_path, archive)); - Ok(()) - } -} diff --git a/compiler/rustc_codegen_cranelift/src/backend.rs b/compiler/rustc_codegen_cranelift/src/backend.rs deleted file mode 100644 index 05c06bac27..0000000000 --- a/compiler/rustc_codegen_cranelift/src/backend.rs +++ /dev/null @@ -1,152 +0,0 @@ -//! Abstraction around the object writing crate - -use std::convert::{TryFrom, TryInto}; - -use rustc_data_structures::fx::FxHashMap; -use rustc_session::Session; - -use cranelift_codegen::isa::TargetIsa; -use cranelift_module::FuncId; -use cranelift_object::{ObjectBuilder, ObjectModule, ObjectProduct}; - -use object::write::*; -use object::{RelocationEncoding, SectionKind, SymbolFlags}; - -use gimli::SectionId; - -use crate::debuginfo::{DebugReloc, DebugRelocName}; - -pub(crate) trait WriteMetadata { - fn add_rustc_section(&mut self, symbol_name: String, data: Vec); -} - -impl WriteMetadata for object::write::Object { - fn add_rustc_section(&mut self, symbol_name: String, data: Vec) { - let segment = self.segment_name(object::write::StandardSegment::Data).to_vec(); - let section_id = self.add_section(segment, b".rustc".to_vec(), object::SectionKind::Data); - let offset = self.append_section_data(section_id, &data, 1); - // For MachO and probably PE this is necessary to prevent the linker from throwing away the - // .rustc section. For ELF this isn't necessary, but it also doesn't harm. - self.add_symbol(object::write::Symbol { - name: symbol_name.into_bytes(), - value: offset, - size: data.len() as u64, - kind: object::SymbolKind::Data, - scope: object::SymbolScope::Dynamic, - weak: false, - section: SymbolSection::Section(section_id), - flags: SymbolFlags::None, - }); - } -} - -pub(crate) trait WriteDebugInfo { - type SectionId: Copy; - - fn add_debug_section(&mut self, name: SectionId, data: Vec) -> Self::SectionId; - fn add_debug_reloc( - &mut self, - section_map: &FxHashMap, - from: &Self::SectionId, - reloc: &DebugReloc, - ); -} - -impl WriteDebugInfo for ObjectProduct { - type SectionId = (object::write::SectionId, object::write::SymbolId); - - fn add_debug_section( - &mut self, - id: SectionId, - data: Vec, - ) -> (object::write::SectionId, object::write::SymbolId) { - let name = if self.object.format() == object::BinaryFormat::MachO { - id.name().replace('.', "__") // machO expects __debug_info instead of .debug_info - } else { - id.name().to_string() - } - .into_bytes(); - - let segment = self.object.segment_name(StandardSegment::Debug).to_vec(); - // FIXME use SHT_X86_64_UNWIND for .eh_frame - let section_id = self.object.add_section( - segment, - name, - if id == SectionId::EhFrame { SectionKind::ReadOnlyData } else { SectionKind::Debug }, - ); - self.object - .section_mut(section_id) - .set_data(data, if id == SectionId::EhFrame { 8 } else { 1 }); - let symbol_id = self.object.section_symbol(section_id); - (section_id, symbol_id) - } - - fn add_debug_reloc( - &mut self, - section_map: &FxHashMap, - from: &Self::SectionId, - reloc: &DebugReloc, - ) { - let (symbol, symbol_offset) = match reloc.name { - DebugRelocName::Section(id) => (section_map.get(&id).unwrap().1, 0), - DebugRelocName::Symbol(id) => { - let symbol_id = self.function_symbol(FuncId::from_u32(id.try_into().unwrap())); - self.object - .symbol_section_and_offset(symbol_id) - .expect("Debug reloc for undef sym???") - } - }; - self.object - .add_relocation( - from.0, - Relocation { - offset: u64::from(reloc.offset), - symbol, - kind: reloc.kind, - encoding: RelocationEncoding::Generic, - size: reloc.size * 8, - addend: i64::try_from(symbol_offset).unwrap() + reloc.addend, - }, - ) - .unwrap(); - } -} - -pub(crate) fn with_object(sess: &Session, name: &str, f: impl FnOnce(&mut Object)) -> Vec { - let triple = crate::target_triple(sess); - - let binary_format = match triple.binary_format { - target_lexicon::BinaryFormat::Elf => object::BinaryFormat::Elf, - target_lexicon::BinaryFormat::Coff => object::BinaryFormat::Coff, - target_lexicon::BinaryFormat::Macho => object::BinaryFormat::MachO, - binary_format => sess.fatal(&format!("binary format {} is unsupported", binary_format)), - }; - let architecture = match triple.architecture { - target_lexicon::Architecture::X86_32(_) => object::Architecture::I386, - target_lexicon::Architecture::X86_64 => object::Architecture::X86_64, - target_lexicon::Architecture::Arm(_) => object::Architecture::Arm, - target_lexicon::Architecture::Aarch64(_) => object::Architecture::Aarch64, - architecture => { - sess.fatal(&format!("target architecture {:?} is unsupported", architecture,)) - } - }; - let endian = match triple.endianness().unwrap() { - target_lexicon::Endianness::Little => object::Endianness::Little, - target_lexicon::Endianness::Big => object::Endianness::Big, - }; - - let mut metadata_object = object::write::Object::new(binary_format, architecture, endian); - metadata_object.add_file_symbol(name.as_bytes().to_vec()); - f(&mut metadata_object); - metadata_object.write().unwrap() -} - -pub(crate) fn make_module(sess: &Session, isa: Box, name: String) -> ObjectModule { - let mut builder = - ObjectBuilder::new(isa, name + ".o", cranelift_module::default_libcall_names()).unwrap(); - // Unlike cg_llvm, cg_clif defaults to disabling -Zfunction-sections. For cg_llvm binary size - // is important, while cg_clif cares more about compilation times. Enabling -Zfunction-sections - // can easily double the amount of time necessary to perform linking. - builder.per_function_section(sess.opts.debugging_opts.function_sections.unwrap_or(false)); - ObjectModule::new(builder) -} diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs index e99a227a3a..1b30edd293 100644 --- a/compiler/rustc_codegen_cranelift/src/base.rs +++ b/compiler/rustc_codegen_cranelift/src/base.rs @@ -3,8 +3,7 @@ use cranelift_codegen::binemit::{NullStackMapSink, NullTrapSink}; use rustc_index::vec::IndexVec; use rustc_middle::ty::adjustment::PointerCast; -use rustc_middle::ty::layout::FnAbiExt; -use rustc_target::abi::call::FnAbi; +use rustc_middle::ty::layout::FnAbiOf; use crate::constant::ConstantCx; use crate::prelude::*; @@ -23,7 +22,7 @@ pub(crate) fn codegen_fn<'tcx>( let mir = tcx.instance_mir(instance.def); let _mir_guard = crate::PrintOnPanic(|| { let mut buf = Vec::new(); - rustc_mir::util::write_mir_pretty(tcx, Some(instance.def_id()), &mut buf).unwrap(); + rustc_middle::mir::write_mir_pretty(tcx, Some(instance.def_id()), &mut buf).unwrap(); String::from_utf8_lossy(&buf).into_owned() }); @@ -62,7 +61,7 @@ pub(crate) fn codegen_fn<'tcx>( instance, symbol_name, mir, - fn_abi: Some(FnAbi::of_instance(&RevealAllLayoutCx(tcx), instance, &[])), + fn_abi: Some(RevealAllLayoutCx(tcx).fn_abi_of_instance(instance, ty::List::empty())), bcx, block_map, @@ -702,6 +701,13 @@ fn codegen_stmt<'tcx>( let len = codegen_array_len(fx, place); lval.write_cvalue(fx, CValue::by_val(len, usize_layout)); } + Rvalue::ShallowInitBox(ref operand, content_ty) => { + let content_ty = fx.monomorphize(content_ty); + let box_layout = fx.layout_of(fx.tcx.mk_box(content_ty)); + let operand = codegen_operand(fx, operand); + let operand = operand.load_scalar(fx); + lval.write_cvalue(fx, CValue::by_val(operand, box_layout)); + } Rvalue::NullaryOp(NullOp::Box, content_ty) => { let usize_type = fx.clif_type(fx.tcx.types.usize).unwrap(); let content_ty = fx.monomorphize(content_ty); @@ -726,15 +732,20 @@ fn codegen_stmt<'tcx>( let ptr = fx.bcx.inst_results(call)[0]; lval.write_cvalue(fx, CValue::by_val(ptr, box_layout)); } - Rvalue::NullaryOp(NullOp::SizeOf, ty) => { + Rvalue::NullaryOp(null_op, ty) => { assert!( lval.layout() .ty .is_sized(fx.tcx.at(stmt.source_info.span), ParamEnv::reveal_all()) ); - let ty_size = fx.layout_of(fx.monomorphize(ty)).size.bytes(); + let layout = fx.layout_of(fx.monomorphize(ty)); + let val = match null_op { + NullOp::SizeOf => layout.size.bytes(), + NullOp::AlignOf => layout.align.abi.bytes(), + NullOp::Box => unreachable!(), + }; let val = - CValue::const_val(fx, fx.layout_of(fx.tcx.types.usize), ty_size.into()); + CValue::const_val(fx, fx.layout_of(fx.tcx.types.usize), val.into()); lval.write_cvalue(fx, val); } Rvalue::Aggregate(ref kind, ref operands) => match kind.as_ref() { diff --git a/compiler/rustc_codegen_cranelift/src/bin/cg_clif.rs b/compiler/rustc_codegen_cranelift/src/bin/cg_clif.rs index a044b43b86..b924f2085a 100644 --- a/compiler/rustc_codegen_cranelift/src/bin/cg_clif.rs +++ b/compiler/rustc_codegen_cranelift/src/bin/cg_clif.rs @@ -1,4 +1,7 @@ #![feature(rustc_private, once_cell)] +#![warn(rust_2018_idioms)] +#![warn(unused_lifetimes)] +#![warn(unreachable_pub)] extern crate rustc_data_structures; extern crate rustc_driver; diff --git a/compiler/rustc_codegen_cranelift/src/bin/cg_clif_build_sysroot.rs b/compiler/rustc_codegen_cranelift/src/bin/cg_clif_build_sysroot.rs index e7cd5edbbf..bde4d71b9a 100644 --- a/compiler/rustc_codegen_cranelift/src/bin/cg_clif_build_sysroot.rs +++ b/compiler/rustc_codegen_cranelift/src/bin/cg_clif_build_sysroot.rs @@ -7,8 +7,10 @@ //! target crates. #![feature(rustc_private)] +#![warn(rust_2018_idioms)] +#![warn(unused_lifetimes)] +#![warn(unreachable_pub)] -extern crate rustc_data_structures; extern crate rustc_driver; extern crate rustc_interface; extern crate rustc_session; diff --git a/compiler/rustc_codegen_cranelift/src/common.rs b/compiler/rustc_codegen_cranelift/src/common.rs index 03f462a63b..0e84681d9a 100644 --- a/compiler/rustc_codegen_cranelift/src/common.rs +++ b/compiler/rustc_codegen_cranelift/src/common.rs @@ -1,4 +1,7 @@ use rustc_index::vec::IndexVec; +use rustc_middle::ty::layout::{ + FnAbiError, FnAbiOfHelpers, FnAbiRequest, LayoutError, LayoutOfHelpers, +}; use rustc_middle::ty::SymbolName; use rustc_target::abi::call::FnAbi; use rustc_target::abi::{Integer, Primitive}; @@ -238,7 +241,7 @@ pub(crate) struct FunctionCx<'m, 'clif, 'tcx: 'm> { pub(crate) instance: Instance<'tcx>, pub(crate) symbol_name: SymbolName<'tcx>, pub(crate) mir: &'tcx Body<'tcx>, - pub(crate) fn_abi: Option>>, + pub(crate) fn_abi: Option<&'tcx FnAbi<'tcx, Ty<'tcx>>>, pub(crate) bcx: FunctionBuilder<'clif>, pub(crate) block_map: IndexVec, @@ -256,12 +259,26 @@ pub(crate) struct FunctionCx<'m, 'clif, 'tcx: 'm> { pub(crate) inline_asm_index: u32, } -impl<'tcx> LayoutOf<'tcx> for FunctionCx<'_, '_, 'tcx> { - type Ty = Ty<'tcx>; - type TyAndLayout = TyAndLayout<'tcx>; +impl<'tcx> LayoutOfHelpers<'tcx> for FunctionCx<'_, '_, 'tcx> { + type LayoutOfResult = TyAndLayout<'tcx>; - fn layout_of(&self, ty: Ty<'tcx>) -> TyAndLayout<'tcx> { - RevealAllLayoutCx(self.tcx).layout_of(ty) + #[inline] + fn handle_layout_err(&self, err: LayoutError<'tcx>, span: Span, ty: Ty<'tcx>) -> ! { + RevealAllLayoutCx(self.tcx).handle_layout_err(err, span, ty) + } +} + +impl<'tcx> FnAbiOfHelpers<'tcx> for FunctionCx<'_, '_, 'tcx> { + type FnAbiOfResult = &'tcx FnAbi<'tcx, Ty<'tcx>>; + + #[inline] + fn handle_fn_abi_err( + &self, + err: FnAbiError<'tcx>, + span: Span, + fn_abi_request: FnAbiRequest<'tcx>, + ) -> ! { + RevealAllLayoutCx(self.tcx).handle_fn_abi_err(err, span, fn_abi_request) } } @@ -364,19 +381,53 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> { pub(crate) struct RevealAllLayoutCx<'tcx>(pub(crate) TyCtxt<'tcx>); -impl<'tcx> LayoutOf<'tcx> for RevealAllLayoutCx<'tcx> { - type Ty = Ty<'tcx>; - type TyAndLayout = TyAndLayout<'tcx>; +impl<'tcx> LayoutOfHelpers<'tcx> for RevealAllLayoutCx<'tcx> { + type LayoutOfResult = TyAndLayout<'tcx>; - fn layout_of(&self, ty: Ty<'tcx>) -> TyAndLayout<'tcx> { - assert!(!ty.still_further_specializable()); - self.0.layout_of(ParamEnv::reveal_all().and(&ty)).unwrap_or_else(|e| { - if let layout::LayoutError::SizeOverflow(_) = e { - self.0.sess.fatal(&e.to_string()) - } else { - bug!("failed to get layout for `{}`: {}", ty, e) + #[inline] + fn handle_layout_err(&self, err: LayoutError<'tcx>, span: Span, ty: Ty<'tcx>) -> ! { + if let layout::LayoutError::SizeOverflow(_) = err { + self.0.sess.span_fatal(span, &err.to_string()) + } else { + span_bug!(span, "failed to get layout for `{}`: {}", ty, err) + } + } +} + +impl<'tcx> FnAbiOfHelpers<'tcx> for RevealAllLayoutCx<'tcx> { + type FnAbiOfResult = &'tcx FnAbi<'tcx, Ty<'tcx>>; + + #[inline] + fn handle_fn_abi_err( + &self, + err: FnAbiError<'tcx>, + span: Span, + fn_abi_request: FnAbiRequest<'tcx>, + ) -> ! { + if let FnAbiError::Layout(LayoutError::SizeOverflow(_)) = err { + self.0.sess.span_fatal(span, &err.to_string()) + } else { + match fn_abi_request { + FnAbiRequest::OfFnPtr { sig, extra_args } => { + span_bug!( + span, + "`fn_abi_of_fn_ptr({}, {:?})` failed: {}", + sig, + extra_args, + err + ); + } + FnAbiRequest::OfInstance { instance, extra_args } => { + span_bug!( + span, + "`fn_abi_of_instance({}, {:?})` failed: {}", + instance, + extra_args, + err + ); + } } - }) + } } } diff --git a/compiler/rustc_codegen_cranelift/src/constant.rs b/compiler/rustc_codegen_cranelift/src/constant.rs index 424a0d742d..5c4991f1fb 100644 --- a/compiler/rustc_codegen_cranelift/src/constant.rs +++ b/compiler/rustc_codegen_cranelift/src/constant.rs @@ -129,9 +129,7 @@ pub(crate) fn codegen_constant<'tcx>( }; let const_val = match const_.val { ConstKind::Value(const_val) => const_val, - ConstKind::Unevaluated(uv) - if fx.tcx.is_static(uv.def.did) => - { + ConstKind::Unevaluated(uv) if fx.tcx.is_static(uv.def.did) => { assert!(uv.substs(fx.tcx).is_empty()); assert!(uv.promoted.is_none()); diff --git a/compiler/rustc_codegen_cranelift/src/debuginfo/emit.rs b/compiler/rustc_codegen_cranelift/src/debuginfo/emit.rs index fb6ccd7c53..c8c2d50b03 100644 --- a/compiler/rustc_codegen_cranelift/src/debuginfo/emit.rs +++ b/compiler/rustc_codegen_cranelift/src/debuginfo/emit.rs @@ -1,16 +1,16 @@ //! Write the debuginfo into an object file. +use cranelift_object::ObjectProduct; use rustc_data_structures::fx::FxHashMap; use gimli::write::{Address, AttributeValue, EndianVec, Result, Sections, Writer}; use gimli::{RunTimeEndian, SectionId}; -use crate::backend::WriteDebugInfo; - +use super::object::WriteDebugInfo; use super::DebugContext; impl DebugContext<'_> { - pub(crate) fn emit(&mut self, product: &mut P) { + pub(crate) fn emit(&mut self, product: &mut ObjectProduct) { let unit_range_list_id = self.dwarf.unit.ranges.add(self.unit_range_list.clone()); let root = self.dwarf.unit.root(); let root = self.dwarf.unit.get_mut(root); diff --git a/compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs b/compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs index cabe3e43b3..6d172817cb 100644 --- a/compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs @@ -2,6 +2,7 @@ mod emit; mod line_info; +mod object; mod unwind; use crate::prelude::*; diff --git a/compiler/rustc_codegen_cranelift/src/debuginfo/object.rs b/compiler/rustc_codegen_cranelift/src/debuginfo/object.rs new file mode 100644 index 0000000000..9984dc92c4 --- /dev/null +++ b/compiler/rustc_codegen_cranelift/src/debuginfo/object.rs @@ -0,0 +1,85 @@ +use std::convert::{TryFrom, TryInto}; + +use rustc_data_structures::fx::FxHashMap; + +use cranelift_module::FuncId; +use cranelift_object::ObjectProduct; + +use object::write::{Relocation, StandardSegment}; +use object::{RelocationEncoding, SectionKind}; + +use gimli::SectionId; + +use crate::debuginfo::{DebugReloc, DebugRelocName}; + +pub(super) trait WriteDebugInfo { + type SectionId: Copy; + + fn add_debug_section(&mut self, name: SectionId, data: Vec) -> Self::SectionId; + fn add_debug_reloc( + &mut self, + section_map: &FxHashMap, + from: &Self::SectionId, + reloc: &DebugReloc, + ); +} + +impl WriteDebugInfo for ObjectProduct { + type SectionId = (object::write::SectionId, object::write::SymbolId); + + fn add_debug_section( + &mut self, + id: SectionId, + data: Vec, + ) -> (object::write::SectionId, object::write::SymbolId) { + let name = if self.object.format() == object::BinaryFormat::MachO { + id.name().replace('.', "__") // machO expects __debug_info instead of .debug_info + } else { + id.name().to_string() + } + .into_bytes(); + + let segment = self.object.segment_name(StandardSegment::Debug).to_vec(); + // FIXME use SHT_X86_64_UNWIND for .eh_frame + let section_id = self.object.add_section( + segment, + name, + if id == SectionId::EhFrame { SectionKind::ReadOnlyData } else { SectionKind::Debug }, + ); + self.object + .section_mut(section_id) + .set_data(data, if id == SectionId::EhFrame { 8 } else { 1 }); + let symbol_id = self.object.section_symbol(section_id); + (section_id, symbol_id) + } + + fn add_debug_reloc( + &mut self, + section_map: &FxHashMap, + from: &Self::SectionId, + reloc: &DebugReloc, + ) { + let (symbol, symbol_offset) = match reloc.name { + DebugRelocName::Section(id) => (section_map.get(&id).unwrap().1, 0), + DebugRelocName::Symbol(id) => { + let symbol_id = self.function_symbol(FuncId::from_u32(id.try_into().unwrap())); + self.object + .symbol_section_and_offset(symbol_id) + .expect("Debug reloc for undef sym???") + } + }; + self.object + .add_relocation( + from.0, + Relocation { + offset: u64::from(reloc.offset), + symbol, + kind: reloc.kind, + encoding: RelocationEncoding::Generic, + size: reloc.size * 8, + addend: i64::try_from(symbol_offset).unwrap() + reloc.addend, + }, + ) + .unwrap(); + } +} diff --git a/compiler/rustc_codegen_cranelift/src/debuginfo/unwind.rs b/compiler/rustc_codegen_cranelift/src/debuginfo/unwind.rs index d1251e749f..f0896ea0e1 100644 --- a/compiler/rustc_codegen_cranelift/src/debuginfo/unwind.rs +++ b/compiler/rustc_codegen_cranelift/src/debuginfo/unwind.rs @@ -4,10 +4,11 @@ use crate::prelude::*; use cranelift_codegen::isa::{unwind::UnwindInfo, TargetIsa}; +use cranelift_object::ObjectProduct; use gimli::write::{Address, CieId, EhFrame, FrameTable, Section}; use gimli::RunTimeEndian; -use crate::backend::WriteDebugInfo; +use super::object::WriteDebugInfo; pub(crate) struct UnwindContext { endian: RunTimeEndian, @@ -55,7 +56,7 @@ impl UnwindContext { } } - pub(crate) fn emit(self, product: &mut P) { + pub(crate) fn emit(self, product: &mut ObjectProduct) { let mut eh_frame = EhFrame::from(super::emit::WriterRelocate::new(self.endian)); self.frame_table.write_eh_frame(&mut eh_frame).unwrap(); diff --git a/compiler/rustc_codegen_cranelift/src/driver/aot.rs b/compiler/rustc_codegen_cranelift/src/driver/aot.rs index 3de706ed6d..32cc50eebe 100644 --- a/compiler/rustc_codegen_cranelift/src/driver/aot.rs +++ b/compiler/rustc_codegen_cranelift/src/driver/aot.rs @@ -6,13 +6,15 @@ use std::path::PathBuf; use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece}; use rustc_codegen_ssa::{CodegenResults, CompiledModule, CrateInfo, ModuleKind}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; +use rustc_metadata::EncodedMetadata; use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; -use rustc_middle::middle::cstore::EncodedMetadata; use rustc_middle::mir::mono::{CodegenUnit, MonoItem}; use rustc_session::cgu_reuse_tracker::CguReuse; use rustc_session::config::{DebugInfo, OutputType}; +use rustc_session::Session; -use cranelift_object::ObjectModule; +use cranelift_codegen::isa::TargetIsa; +use cranelift_object::{ObjectBuilder, ObjectModule}; use crate::{prelude::*, BackendConfig}; @@ -24,6 +26,16 @@ impl HashStable for ModuleCodegenResult { } } +fn make_module(sess: &Session, isa: Box, name: String) -> ObjectModule { + let mut builder = + ObjectBuilder::new(isa, name + ".o", cranelift_module::default_libcall_names()).unwrap(); + // Unlike cg_llvm, cg_clif defaults to disabling -Zfunction-sections. For cg_llvm binary size + // is important, while cg_clif cares more about compilation times. Enabling -Zfunction-sections + // can easily double the amount of time necessary to perform linking. + builder.per_function_section(sess.opts.debugging_opts.function_sections.unwrap_or(false)); + ObjectModule::new(builder) +} + fn emit_module( tcx: TyCtxt<'_>, backend_config: &BackendConfig, @@ -104,7 +116,7 @@ fn module_codegen( let mono_items = cgu.items_in_deterministic_order(tcx); let isa = crate::build_isa(tcx.sess, &backend_config); - let mut module = crate::backend::make_module(tcx.sess, isa, cgu_name.as_str().to_string()); + let mut module = make_module(tcx.sess, isa, cgu_name.as_str().to_string()); let mut cx = crate::CodegenCx::new( tcx, @@ -227,8 +239,7 @@ pub(crate) fn run_aot( tcx.sess.abort_if_errors(); let isa = crate::build_isa(tcx.sess, &backend_config); - let mut allocator_module = - crate::backend::make_module(tcx.sess, isa, "allocator_shim".to_string()); + let mut allocator_module = make_module(tcx.sess, isa, "allocator_shim".to_string()); assert_eq!(pointer_ty(tcx), allocator_module.target_config().pointer_type()); let mut allocator_unwind_context = UnwindContext::new(tcx, allocator_module.isa(), true); let created_alloc_shim = @@ -266,9 +277,7 @@ pub(crate) fn run_aot( let tmp_file = tcx.output_filenames(()).temp_path(OutputType::Metadata, Some(&metadata_cgu_name)); - let obj = crate::backend::with_object(tcx.sess, &metadata_cgu_name, |object| { - crate::metadata::write_metadata(tcx, object); - }); + let obj = crate::metadata::new_metadata_object(tcx, &metadata_cgu_name, &metadata); if let Err(err) = std::fs::write(&tmp_file, obj) { tcx.sess.fatal(&format!("error writing metadata object file: {}", err)); diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs index 12f61e0c56..313b62c577 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs @@ -143,8 +143,8 @@ macro validate_simd_type($fx:ident, $intrinsic:ident, $span:ident, $ty:expr) { } pub(crate) fn clif_vector_type<'tcx>(tcx: TyCtxt<'tcx>, layout: TyAndLayout<'tcx>) -> Option { - let (element, count) = match &layout.abi { - Abi::Vector { element, count } => (element.clone(), *count), + let (element, count) = match layout.abi { + Abi::Vector { element, count } => (element, count), _ => unreachable!(), }; @@ -407,11 +407,9 @@ pub(crate) fn codegen_intrinsic_call<'tcx>( destination: Option<(CPlace<'tcx>, BasicBlock)>, span: Span, ) { - let def_id = instance.def_id(); + let intrinsic = fx.tcx.item_name(instance.def_id()); let substs = instance.substs; - let intrinsic = fx.tcx.item_name(def_id); - let ret = match destination { Some((place, _)) => place, None => { @@ -823,7 +821,7 @@ pub(crate) fn codegen_intrinsic_call<'tcx>( dest.write_cvalue(fx, val); }; - pref_align_of | min_align_of | needs_drop | type_id | type_name | variant_count, () { + pref_align_of | needs_drop | type_id | type_name | variant_count, () { let const_val = fx.tcx.const_eval_instance(ParamEnv::reveal_all(), instance, None).unwrap(); let val = crate::constant::codegen_const_value( diff --git a/compiler/rustc_codegen_cranelift/src/lib.rs b/compiler/rustc_codegen_cranelift/src/lib.rs index 6c7c8cbc31..beb97edf09 100644 --- a/compiler/rustc_codegen_cranelift/src/lib.rs +++ b/compiler/rustc_codegen_cranelift/src/lib.rs @@ -1,4 +1,5 @@ -#![feature(rustc_private, decl_macro, never_type, hash_drain_filter, vec_into_raw_parts, once_cell)] +#![feature(rustc_private, decl_macro)] +#![cfg_attr(feature = "jit", feature(never_type, vec_into_raw_parts, once_cell))] #![warn(rust_2018_idioms)] #![warn(unused_lifetimes)] #![warn(unreachable_pub)] @@ -16,7 +17,6 @@ extern crate rustc_incremental; extern crate rustc_index; extern crate rustc_interface; extern crate rustc_metadata; -extern crate rustc_mir; extern crate rustc_session; extern crate rustc_span; extern crate rustc_target; @@ -30,8 +30,8 @@ use std::any::Any; use rustc_codegen_ssa::traits::CodegenBackend; use rustc_codegen_ssa::CodegenResults; use rustc_errors::ErrorReported; +use rustc_metadata::EncodedMetadata; use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; -use rustc_middle::middle::cstore::EncodedMetadata; use rustc_session::config::OutputFilenames; use rustc_session::Session; @@ -45,7 +45,6 @@ mod abi; mod allocator; mod analyze; mod archive; -mod backend; mod base; mod cast; mod codegen_i128; @@ -79,12 +78,12 @@ mod prelude { pub(crate) use rustc_hir::def_id::{DefId, LOCAL_CRATE}; pub(crate) use rustc_middle::bug; pub(crate) use rustc_middle::mir::{self, *}; - pub(crate) use rustc_middle::ty::layout::{self, TyAndLayout}; + pub(crate) use rustc_middle::ty::layout::{self, LayoutOf, TyAndLayout}; pub(crate) use rustc_middle::ty::{ self, FloatTy, Instance, InstanceDef, IntTy, ParamEnv, Ty, TyCtxt, TypeAndMut, TypeFoldable, UintTy, }; - pub(crate) use rustc_target::abi::{Abi, LayoutOf, Scalar, Size, VariantIdx}; + pub(crate) use rustc_target::abi::{Abi, Scalar, Size, VariantIdx}; pub(crate) use rustc_data_structures::fx::FxHashMap; diff --git a/compiler/rustc_codegen_cranelift/src/metadata.rs b/compiler/rustc_codegen_cranelift/src/metadata.rs index db24bf65eb..1c8fd0b01d 100644 --- a/compiler/rustc_codegen_cranelift/src/metadata.rs +++ b/compiler/rustc_codegen_cranelift/src/metadata.rs @@ -1,20 +1,76 @@ //! Writing of the rustc metadata for dylibs +use object::write::{Object, StandardSegment, Symbol, SymbolSection}; +use object::{SectionKind, SymbolFlags, SymbolKind, SymbolScope}; + +use rustc_metadata::EncodedMetadata; use rustc_middle::ty::TyCtxt; -use crate::backend::WriteMetadata; - // Adapted from https://github.com/rust-lang/rust/blob/da573206f87b5510de4b0ee1a9c044127e409bd3/src/librustc_codegen_llvm/base.rs#L47-L112 -pub(crate) fn write_metadata(tcx: TyCtxt<'_>, object: &mut O) { +pub(crate) fn new_metadata_object( + tcx: TyCtxt<'_>, + cgu_name: &str, + metadata: &EncodedMetadata, +) -> Vec { use snap::write::FrameEncoder; use std::io::Write; - let metadata = tcx.encode_metadata(); let mut compressed = rustc_metadata::METADATA_HEADER.to_vec(); - FrameEncoder::new(&mut compressed).write_all(&metadata.raw_data).unwrap(); + FrameEncoder::new(&mut compressed).write_all(metadata.raw_data()).unwrap(); - object.add_rustc_section( - rustc_middle::middle::exported_symbols::metadata_symbol_name(tcx), - compressed, - ); + let triple = crate::target_triple(tcx.sess); + + let binary_format = match triple.binary_format { + target_lexicon::BinaryFormat::Elf => object::BinaryFormat::Elf, + target_lexicon::BinaryFormat::Coff => object::BinaryFormat::Coff, + target_lexicon::BinaryFormat::Macho => object::BinaryFormat::MachO, + binary_format => tcx.sess.fatal(&format!("binary format {} is unsupported", binary_format)), + }; + let architecture = match triple.architecture { + target_lexicon::Architecture::Aarch64(_) => object::Architecture::Aarch64, + target_lexicon::Architecture::Arm(_) => object::Architecture::Arm, + target_lexicon::Architecture::Avr => object::Architecture::Avr, + target_lexicon::Architecture::Hexagon => object::Architecture::Hexagon, + target_lexicon::Architecture::Mips32(_) => object::Architecture::Mips, + target_lexicon::Architecture::Mips64(_) => object::Architecture::Mips64, + target_lexicon::Architecture::Msp430 => object::Architecture::Msp430, + target_lexicon::Architecture::Powerpc => object::Architecture::PowerPc, + target_lexicon::Architecture::Powerpc64 => object::Architecture::PowerPc64, + target_lexicon::Architecture::Powerpc64le => todo!(), + target_lexicon::Architecture::Riscv32(_) => object::Architecture::Riscv32, + target_lexicon::Architecture::Riscv64(_) => object::Architecture::Riscv64, + target_lexicon::Architecture::S390x => object::Architecture::S390x, + target_lexicon::Architecture::Sparc64 => object::Architecture::Sparc64, + target_lexicon::Architecture::Sparcv9 => object::Architecture::Sparc64, + target_lexicon::Architecture::X86_32(_) => object::Architecture::I386, + target_lexicon::Architecture::X86_64 => object::Architecture::X86_64, + architecture => { + tcx.sess.fatal(&format!("target architecture {:?} is unsupported", architecture,)) + } + }; + let endian = match triple.endianness().unwrap() { + target_lexicon::Endianness::Little => object::Endianness::Little, + target_lexicon::Endianness::Big => object::Endianness::Big, + }; + + let mut object = Object::new(binary_format, architecture, endian); + object.add_file_symbol(cgu_name.as_bytes().to_vec()); + + let segment = object.segment_name(StandardSegment::Data).to_vec(); + let section_id = object.add_section(segment, b".rustc".to_vec(), SectionKind::Data); + let offset = object.append_section_data(section_id, &compressed, 1); + // For MachO and probably PE this is necessary to prevent the linker from throwing away the + // .rustc section. For ELF this isn't necessary, but it also doesn't harm. + object.add_symbol(Symbol { + name: rustc_middle::middle::exported_symbols::metadata_symbol_name(tcx).into_bytes(), + value: offset, + size: compressed.len() as u64, + kind: SymbolKind::Data, + scope: SymbolScope::Dynamic, + weak: false, + section: SymbolSection::Section(section_id), + flags: SymbolFlags::None, + }); + + object.write().unwrap() } diff --git a/compiler/rustc_codegen_cranelift/src/pretty_clif.rs b/compiler/rustc_codegen_cranelift/src/pretty_clif.rs index 05db74745a..ec846d7196 100644 --- a/compiler/rustc_codegen_cranelift/src/pretty_clif.rs +++ b/compiler/rustc_codegen_cranelift/src/pretty_clif.rs @@ -61,9 +61,8 @@ use cranelift_codegen::{ write::{FuncWriter, PlainWriter}, }; -use rustc_middle::ty::layout::FnAbiExt; +use rustc_middle::ty::layout::FnAbiOf; use rustc_session::config::OutputType; -use rustc_target::abi::call::FnAbi; use crate::prelude::*; @@ -81,7 +80,10 @@ impl CommentWriter { vec![ format!("symbol {}", tcx.symbol_name(instance).name), format!("instance {:?}", instance), - format!("abi {:?}", FnAbi::of_instance(&RevealAllLayoutCx(tcx), instance, &[])), + format!( + "abi {:?}", + RevealAllLayoutCx(tcx).fn_abi_of_instance(instance, ty::List::empty()) + ), String::new(), ] } else { diff --git a/compiler/rustc_codegen_cranelift/src/value_and_place.rs b/compiler/rustc_codegen_cranelift/src/value_and_place.rs index 364b3da92b..30d5340935 100644 --- a/compiler/rustc_codegen_cranelift/src/value_and_place.rs +++ b/compiler/rustc_codegen_cranelift/src/value_and_place.rs @@ -49,11 +49,7 @@ fn codegen_field<'tcx>( } } -fn scalar_pair_calculate_b_offset( - tcx: TyCtxt<'_>, - a_scalar: &Scalar, - b_scalar: &Scalar, -) -> Offset32 { +fn scalar_pair_calculate_b_offset(tcx: TyCtxt<'_>, a_scalar: Scalar, b_scalar: Scalar) -> Offset32 { let b_offset = a_scalar.value.size(&tcx).align_to(b_scalar.value.align(&tcx).abi); Offset32::new(b_offset.bytes().try_into().unwrap()) } @@ -124,12 +120,10 @@ impl<'tcx> CValue<'tcx> { match self.0 { CValueInner::ByRef(ptr, None) => { let clif_ty = match layout.abi { - Abi::Scalar(ref scalar) => scalar_to_clif_type(fx.tcx, scalar.clone()), - Abi::Vector { ref element, count } => { - scalar_to_clif_type(fx.tcx, element.clone()) - .by(u16::try_from(count).unwrap()) - .unwrap() - } + Abi::Scalar(scalar) => scalar_to_clif_type(fx.tcx, scalar), + Abi::Vector { element, count } => scalar_to_clif_type(fx.tcx, element) + .by(u16::try_from(count).unwrap()) + .unwrap(), _ => unreachable!("{:?}", layout.ty), }; let mut flags = MemFlags::new(); @@ -147,13 +141,13 @@ impl<'tcx> CValue<'tcx> { let layout = self.1; match self.0 { CValueInner::ByRef(ptr, None) => { - let (a_scalar, b_scalar) = match &layout.abi { + let (a_scalar, b_scalar) = match layout.abi { Abi::ScalarPair(a, b) => (a, b), _ => unreachable!("load_scalar_pair({:?})", self), }; let b_offset = scalar_pair_calculate_b_offset(fx.tcx, a_scalar, b_scalar); - let clif_ty1 = scalar_to_clif_type(fx.tcx, a_scalar.clone()); - let clif_ty2 = scalar_to_clif_type(fx.tcx, b_scalar.clone()); + let clif_ty1 = scalar_to_clif_type(fx.tcx, a_scalar); + let clif_ty2 = scalar_to_clif_type(fx.tcx, b_scalar); let mut flags = MemFlags::new(); flags.set_notrap(); let val1 = ptr.load(fx, clif_ty1, flags); @@ -564,7 +558,7 @@ impl<'tcx> CPlace<'tcx> { to_ptr.store(fx, val, flags); return; } - Abi::ScalarPair(ref a_scalar, ref b_scalar) => { + Abi::ScalarPair(a_scalar, b_scalar) => { let (value, extra) = from.load_scalar_pair(fx); let b_offset = scalar_pair_calculate_b_offset(fx.tcx, a_scalar, b_scalar); to_ptr.store(fx, value, flags); diff --git a/compiler/rustc_codegen_gcc/.github/workflows/main.yml b/compiler/rustc_codegen_gcc/.github/workflows/main.yml new file mode 100644 index 0000000000..98bed8ef38 --- /dev/null +++ b/compiler/rustc_codegen_gcc/.github/workflows/main.yml @@ -0,0 +1,96 @@ +name: CI + +on: + - push + - pull_request + +jobs: + build: + runs-on: ubuntu-latest + + strategy: + fail-fast: false + + steps: + - uses: actions/checkout@v2 + + - name: Install packages + run: sudo apt-get install ninja-build ripgrep + + - name: Download artifact + uses: dawidd6/action-download-artifact@v2 + with: + workflow: main.yml + name: libgccjit.so + path: gcc-build + repo: antoyo/gcc + + - name: Setup path to libgccjit + run: | + echo $(readlink -f gcc-build) > gcc_path + ln gcc-build/libgccjit.so gcc-build/libgccjit.so.0 + + - name: Set LIBRARY_PATH + run: | + echo "LIBRARY_PATH=$(cat gcc_path)" >> $GITHUB_ENV + echo "LD_LIBRARY_PATH=$(cat gcc_path)" >> $GITHUB_ENV + + # https://github.com/actions/cache/issues/133 + - name: Fixup owner of ~/.cargo/ + # Don't remove the trailing /. It is necessary to follow the symlink. + run: sudo chown -R $(whoami):$(id -ng) ~/.cargo/ + + - name: Cache cargo installed crates + uses: actions/cache@v1.1.2 + with: + path: ~/.cargo/bin + key: cargo-installed-crates2-ubuntu-latest + + - name: Cache cargo registry + uses: actions/cache@v1 + with: + path: ~/.cargo/registry + key: ${{ runner.os }}-cargo-registry2-${{ hashFiles('**/Cargo.lock') }} + + - name: Cache cargo index + uses: actions/cache@v1 + with: + path: ~/.cargo/git + key: ${{ runner.os }}-cargo-index-${{ hashFiles('**/Cargo.lock') }} + + - name: Cache cargo target dir + uses: actions/cache@v1.1.2 + with: + path: target + key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('rust-toolchain') }} + + - name: Build + run: | + ./prepare_build.sh + ./build.sh + cargo test + ./clean_all.sh + + - name: Prepare dependencies + run: | + git config --global user.email "user@example.com" + git config --global user.name "User" + ./prepare.sh + + # Compile is a separate step, as the actions-rs/cargo action supports error annotations + - name: Compile + uses: actions-rs/cargo@v1.0.3 + with: + command: build + args: --release + + - name: Test + run: | + # Enable backtraces for easier debugging + export RUST_BACKTRACE=1 + + # Reduce amount of benchmark runs as they are slow + export COMPILE_RUNS=2 + export RUN_RUNS=2 + + ./test.sh --release diff --git a/compiler/rustc_codegen_gcc/Cargo.lock b/compiler/rustc_codegen_gcc/Cargo.lock new file mode 100644 index 0000000000..60a2101c68 --- /dev/null +++ b/compiler/rustc_codegen_gcc/Cargo.lock @@ -0,0 +1,373 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "aho-corasick" +version = "0.7.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" +dependencies = [ + "memchr", +] + +[[package]] +name = "ar" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "450575f58f7bee32816abbff470cbc47797397c2a81e0eaced4b98436daf52e1" + +[[package]] +name = "autocfg" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "crc32fast" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81156fece84ab6a9f2afdb109ce3ae577e42b1228441eded99bd77f627953b1a" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "fm" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68fda3cff2cce84c19e5dfa5179a4b35d2c0f18b893f108002b8a6a54984acca" +dependencies = [ + "regex", +] + +[[package]] +name = "gccjit" +version = "1.0.0" +source = "git+https://github.com/antoyo/gccjit.rs#2d4fea7319f80531b2e5d264fca9f1c498a3a62e" +dependencies = [ + "gccjit_sys", +] + +[[package]] +name = "gccjit_sys" +version = "0.0.1" +source = "git+https://github.com/antoyo/gccjit.rs#2d4fea7319f80531b2e5d264fca9f1c498a3a62e" +dependencies = [ + "libc 0.1.12", +] + +[[package]] +name = "getopts" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5" +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", + "libc 0.2.102", + "wasi", +] + +[[package]] +name = "hashbrown" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" + +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc 0.2.102", +] + +[[package]] +name = "indexmap" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc633605454125dec4b66843673f01c7df2b89479b32e0ed634e43a91cff62a5" +dependencies = [ + "autocfg", + "hashbrown", +] + +[[package]] +name = "lang_tester" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96bd995a092cac79868250589869b5a5d656b02a02bd74c8ebdc566dc7203090" +dependencies = [ + "fm", + "getopts", + "libc 0.2.102", + "num_cpus", + "termcolor", + "threadpool", + "wait-timeout", + "walkdir", +] + +[[package]] +name = "libc" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e32a70cf75e5846d53a673923498228bbec6a8624708a9ea5645f075d6276122" + +[[package]] +name = "libc" +version = "0.2.102" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2a5ac8f984bfcf3a823267e5fde638acc3325f6496633a5da6bb6eb2171e103" + +[[package]] +name = "memchr" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" + +[[package]] +name = "num_cpus" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3" +dependencies = [ + "hermit-abi", + "libc 0.2.102", +] + +[[package]] +name = "object" +version = "0.25.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a38f2be3697a57b4060074ff41b44c16870d916ad7877c17696e063257482bc7" +dependencies = [ + "crc32fast", + "indexmap", + "memchr", +] + +[[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.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8" +dependencies = [ + "libc 0.2.102", + "rand_chacha", + "rand_core", + "rand_hc", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rand_hc" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7" +dependencies = [ + "rand_core", +] + +[[package]] +name = "redox_syscall" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff" +dependencies = [ + "bitflags", +] + +[[package]] +name = "regex" +version = "1.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.6.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" + +[[package]] +name = "remove_dir_all" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" +dependencies = [ + "winapi", +] + +[[package]] +name = "rustc_codegen_gcc" +version = "0.1.0" +dependencies = [ + "ar", + "gccjit", + "lang_tester", + "object", + "target-lexicon", + "tempfile", +] + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "target-lexicon" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab0e7238dcc7b40a7be719a25365910f6807bd864f4cce6b2e6b873658e2b19d" + +[[package]] +name = "tempfile" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22" +dependencies = [ + "cfg-if", + "libc 0.2.102", + "rand", + "redox_syscall", + "remove_dir_all", + "winapi", +] + +[[package]] +name = "termcolor" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "threadpool" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa" +dependencies = [ + "num_cpus", +] + +[[package]] +name = "unicode-width" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" + +[[package]] +name = "wait-timeout" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6" +dependencies = [ + "libc 0.2.102", +] + +[[package]] +name = "walkdir" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56" +dependencies = [ + "same-file", + "winapi", + "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.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-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi", +] + +[[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/compiler/rustc_codegen_gcc/Cargo.toml b/compiler/rustc_codegen_gcc/Cargo.toml new file mode 100644 index 0000000000..9e8c195c15 --- /dev/null +++ b/compiler/rustc_codegen_gcc/Cargo.toml @@ -0,0 +1,51 @@ +[package] +name = "rustc_codegen_gcc" +version = "0.1.0" +authors = ["Antoni Boucher "] +edition = "2018" +license = "MIT OR Apache-2.0" + +[lib] +crate-type = ["dylib"] + +[[test]] +name = "lang_tests" +path = "tests/lib.rs" +harness = false + +[dependencies] +gccjit = { git = "https://github.com/antoyo/gccjit.rs" } + +# Local copy. +#gccjit = { path = "../gccjit.rs" } + +target-lexicon = "0.10.0" + +ar = "0.8.0" + +[dependencies.object] +version = "0.25.0" +default-features = false +features = ["read", "std", "write"] # We don't need WASM support. + +[dev-dependencies] +lang_tester = "0.3.9" +tempfile = "3.1.0" + +[profile.dev] +# By compiling dependencies with optimizations, performing tests gets much faster. +opt-level = 3 + +[profile.dev.package.rustc_codegen_gcc] +# Disabling optimizations for cg_gccjit itself makes compilation after a change faster. +opt-level = 0 + +# Disable optimizations and debuginfo of build scripts and some of the heavy build deps, as the +# execution time of build scripts is so fast that optimizing them slows down the total build time. +[profile.dev.build-override] +opt-level = 0 +debug = false + +[profile.release.build-override] +opt-level = 0 +debug = false diff --git a/compiler/rustc_codegen_gcc/LICENSE-APACHE b/compiler/rustc_codegen_gcc/LICENSE-APACHE new file mode 100644 index 0000000000..1b5ec8b78e --- /dev/null +++ b/compiler/rustc_codegen_gcc/LICENSE-APACHE @@ -0,0 +1,176 @@ + 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 diff --git a/vendor/dissimilar/LICENSE-MIT b/compiler/rustc_codegen_gcc/LICENSE-MIT similarity index 100% rename from vendor/dissimilar/LICENSE-MIT rename to compiler/rustc_codegen_gcc/LICENSE-MIT diff --git a/compiler/rustc_codegen_gcc/Readme.md b/compiler/rustc_codegen_gcc/Readme.md new file mode 100644 index 0000000000..709d93c6ed --- /dev/null +++ b/compiler/rustc_codegen_gcc/Readme.md @@ -0,0 +1,135 @@ +# WIP libgccjit codegen backend for rust + +This is a GCC codegen for rustc, which means it can be loaded by the existing rustc frontend, but benefits from GCC: more architectures are supported and GCC's optimizations are used. + +**Despite its name, libgccjit can be used for ahead-of-time compilation, as is used here.** + +## Motivation + +The primary goal of this project is to be able to compile Rust code on platforms unsupported by LLVM. +A secondary goal is to check if using the gcc backend will provide any run-time speed improvement for the programs compiled using rustc. + +## Building + +**This requires a patched libgccjit in order to work. +The patches in [this repostory](https://github.com/antoyo/libgccjit-patches) need to be applied. +(Those patches should work when applied on master, but in case it doesn't work, they are known to work when applied on 079c23cfe079f203d5df83fea8e92a60c7d7e878.) +You can also use my [fork of gcc](https://github.com/antoyo/gcc) which already includes these patches.** + +**Put the path to your custom build of libgccjit in the file `gcc_path`.** + +```bash +$ git clone https://github.com/rust-lang/rustc_codegen_gcc.git +$ cd rustc_codegen_gcc +$ ./prepare_build.sh # download and patch sysroot src +$ ./build.sh --release +``` + +To run the tests: + +```bash +$ ./prepare.sh # download and patch sysroot src and install hyperfine for benchmarking +$ ./test.sh --release +``` + +## Usage + +`$cg_gccjit_dir` is the directory you cloned this repo into in the following instructions. + +### Cargo + +```bash +$ CHANNEL="release" $cg_gccjit_dir/cargo.sh run +``` + +If you compiled cg_gccjit in debug mode (aka you didn't pass `--release` to `./test.sh`) you should use `CHANNEL="debug"` instead or omit `CHANNEL="release"` completely. + +### Rustc + +> You should prefer using the Cargo method. + +```bash +$ rustc +$(cat $cg_gccjit_dir/rust-toolchain) -Cpanic=abort -Zcodegen-backend=$cg_gccjit_dir/target/release/librustc_codegen_gcc.so --sysroot $cg_gccjit_dir/build_sysroot/sysroot my_crate.rs +``` + +## Env vars + +
+
CG_GCCJIT_INCR_CACHE_DISABLED
+
Don't cache object files in the incremental cache. Useful during development of cg_gccjit + to make it possible to use incremental mode for all analyses performed by rustc without caching + object files when their content should have been changed by a change to cg_gccjit.
+
CG_GCCJIT_DISPLAY_CG_TIME
+
Display the time it took to perform codegen for a crate
+
+ +## Debugging + +Sometimes, libgccjit will crash and output an error like this: + +``` +during RTL pass: expand +libgccjit.so: error: in expmed_mode_index, at expmed.h:249 +0x7f0da2e61a35 expmed_mode_index + ../../../gcc/gcc/expmed.h:249 +0x7f0da2e61aa4 expmed_op_cost_ptr + ../../../gcc/gcc/expmed.h:271 +0x7f0da2e620dc sdiv_cost_ptr + ../../../gcc/gcc/expmed.h:540 +0x7f0da2e62129 sdiv_cost + ../../../gcc/gcc/expmed.h:558 +0x7f0da2e73c12 expand_divmod(int, tree_code, machine_mode, rtx_def*, rtx_def*, rtx_def*, int) + ../../../gcc/gcc/expmed.c:4335 +0x7f0da2ea1423 expand_expr_real_2(separate_ops*, rtx_def*, machine_mode, expand_modifier) + ../../../gcc/gcc/expr.c:9240 +0x7f0da2cd1a1e expand_gimple_stmt_1 + ../../../gcc/gcc/cfgexpand.c:3796 +0x7f0da2cd1c30 expand_gimple_stmt + ../../../gcc/gcc/cfgexpand.c:3857 +0x7f0da2cd90a9 expand_gimple_basic_block + ../../../gcc/gcc/cfgexpand.c:5898 +0x7f0da2cdade8 execute + ../../../gcc/gcc/cfgexpand.c:6582 +``` + +To see the code which causes this error, call the following function: + +```c +gcc_jit_context_dump_to_file(ctxt, "/tmp/output.c", 1 /* update_locations */) +``` + +This will create a C-like file and add the locations into the IR pointing to this C file. +Then, rerun the program and it will output the location in the second line: + +``` +libgccjit.so: /tmp/something.c:61322:0: error: in expmed_mode_index, at expmed.h:249 +``` + +Or add a breakpoint to `add_error` in gdb and print the line number using: + +``` +p loc->m_line +``` + +### How to use a custom-build rustc + + * Build the stage2 compiler (`rustup toolchain link debug-current build/x86_64-unknown-linux-gnu/stage2`). + * Clean and rebuild the codegen with `debug-current` in the file `rust-toolchain`. + +### How to build a cross-compiling libgccjit + +#### Building libgccjit + + * Follow these instructions: https://preshing.com/20141119/how-to-build-a-gcc-cross-compiler/ with the following changes: + * Configure gcc with `../gcc/configure --enable-host-shared --disable-multilib --enable-languages=c,jit,c++ --disable-bootstrap --enable-checking=release --prefix=/opt/m68k-gcc/ --target=m68k-linux --without-headers`. + * Some shells, like fish, don't define the environment variable `$MACHTYPE`. + * Add `CFLAGS="-Wno-error=attributes -g -O2"` at the end of the configure command for building glibc (`CFLAGS="-Wno-error=attributes -Wno-error=array-parameter -Wno-error=stringop-overflow -Wno-error=array-bounds -g -O2"` for glibc 2.31, which is useful for Debian). + +#### Configuring rustc_codegen_gcc + + * Set `TARGET_TRIPLE="m68k-unknown-linux-gnu"` in config.sh. + * Since rustc doesn't support this architecture yet, set it back to `TARGET_TRIPLE="mips-unknown-linux-gnu"` (or another target having the same attributes). Alternatively, create a [target specification file](https://book.avr-rust.com/005.1-the-target-specification-json-file.html) (note that the `arch` specified in this file must be supported by the rust compiler). + * Set `linker='-Clinker=m68k-linux-gcc'`. + * Set the path to the cross-compiling libgccjit in `gcc_path`. + * Disable the 128-bit integer types if the target doesn't support them by using `let i128_type = context.new_type::();` in `context.rs` (same for u128_type). + * (might not be necessary) Disable the compilation of libstd.so (and possibly libcore.so?). diff --git a/compiler/rustc_codegen_gcc/build.sh b/compiler/rustc_codegen_gcc/build.sh new file mode 100755 index 0000000000..17a0d2ab3f --- /dev/null +++ b/compiler/rustc_codegen_gcc/build.sh @@ -0,0 +1,31 @@ +#!/bin/bash + +#set -x +set -e + +if [ -f ./gcc_path ]; then + export GCC_PATH=$(cat gcc_path) +else + echo 'Please put the path to your custom build of libgccjit in the file `gcc_path`, see Readme.md for details' + exit 1 +fi + +export LD_LIBRARY_PATH="$GCC_PATH" +export LIBRARY_PATH="$GCC_PATH" + +if [[ "$1" == "--release" ]]; then + export CHANNEL='release' + CARGO_INCREMENTAL=1 cargo rustc --release +else + echo $LD_LIBRARY_PATH + export CHANNEL='debug' + cargo rustc +fi + +source config.sh + +rm -r target/out || true +mkdir -p target/out/gccjit + +echo "[BUILD] sysroot" +time ./build_sysroot/build_sysroot.sh $CHANNEL diff --git a/compiler/rustc_codegen_gcc/build_sysroot/Cargo.toml b/compiler/rustc_codegen_gcc/build_sysroot/Cargo.toml new file mode 100644 index 0000000000..cfadf47cc3 --- /dev/null +++ b/compiler/rustc_codegen_gcc/build_sysroot/Cargo.toml @@ -0,0 +1,19 @@ +[package] +authors = ["bjorn3 "] +name = "sysroot" +version = "0.0.0" + +[dependencies] +core = { path = "./sysroot_src/library/core" } +compiler_builtins = "0.1" +alloc = { path = "./sysroot_src/library/alloc" } +std = { path = "./sysroot_src/library/std", features = ["panic_unwind", "backtrace"] } +test = { path = "./sysroot_src/library/test" } + +[patch.crates-io] +rustc-std-workspace-core = { path = "./sysroot_src/library/rustc-std-workspace-core" } +rustc-std-workspace-alloc = { path = "./sysroot_src/library/rustc-std-workspace-alloc" } +rustc-std-workspace-std = { path = "./sysroot_src/library/rustc-std-workspace-std" } + +[profile.release] +debug = true diff --git a/compiler/rustc_codegen_gcc/build_sysroot/build_sysroot.sh b/compiler/rustc_codegen_gcc/build_sysroot/build_sysroot.sh new file mode 100755 index 0000000000..d1dcf495db --- /dev/null +++ b/compiler/rustc_codegen_gcc/build_sysroot/build_sysroot.sh @@ -0,0 +1,30 @@ +#!/bin/bash + +# Requires the CHANNEL env var to be set to `debug` or `release.` + +set -e +cd $(dirname "$0") + +pushd ../ >/dev/null +source ./config.sh +popd >/dev/null + +# Cleanup for previous run +# v Clean target dir except for build scripts and incremental cache +rm -r target/*/{debug,release}/{build,deps,examples,libsysroot*,native} 2>/dev/null || true +rm Cargo.lock test_target/Cargo.lock 2>/dev/null || true +rm -r sysroot/ 2>/dev/null || true + +# Build libs +export RUSTFLAGS="$RUSTFLAGS -Z force-unstable-if-unmarked -Cpanic=abort" +if [[ "$1" == "--release" ]]; then + sysroot_channel='release' + RUSTFLAGS="$RUSTFLAGS -Zmir-opt-level=3" cargo build --target $TARGET_TRIPLE --release +else + sysroot_channel='debug' + cargo build --target $TARGET_TRIPLE +fi + +# Copy files to sysroot +mkdir -p sysroot/lib/rustlib/$TARGET_TRIPLE/lib/ +cp -r target/$TARGET_TRIPLE/$sysroot_channel/deps/* sysroot/lib/rustlib/$TARGET_TRIPLE/lib/ diff --git a/compiler/rustc_codegen_gcc/build_sysroot/prepare_sysroot_src.sh b/compiler/rustc_codegen_gcc/build_sysroot/prepare_sysroot_src.sh new file mode 100755 index 0000000000..071e7ed1f8 --- /dev/null +++ b/compiler/rustc_codegen_gcc/build_sysroot/prepare_sysroot_src.sh @@ -0,0 +1,39 @@ +#!/bin/bash +set -e +cd $(dirname "$0") + +SRC_DIR=$(dirname $(rustup which rustc))"/../lib/rustlib/src/rust/" +DST_DIR="sysroot_src" + +if [ ! -e $SRC_DIR ]; then + echo "Please install rust-src component" + exit 1 +fi + +rm -rf $DST_DIR +mkdir -p $DST_DIR/library +cp -r $SRC_DIR/library $DST_DIR/ + +pushd $DST_DIR +echo "[GIT] init" +git init +echo "[GIT] add" +git add . +echo "[GIT] commit" + +# This is needed on systems where nothing is configured. +# git really needs something here, or it will fail. +# Even using --author is not enough. +git config user.email || git config user.email "none@example.com" +git config user.name || git config user.name "None" + +git commit -m "Initial commit" -q +for file in $(ls ../../patches/ | grep -v patcha); do +echo "[GIT] apply" $file +git apply ../../patches/$file +git add -A +git commit --no-gpg-sign -m "Patch $file" +done +popd + +echo "Successfully prepared libcore for building" diff --git a/compiler/rustc_codegen_gcc/build_sysroot/src/lib.rs b/compiler/rustc_codegen_gcc/build_sysroot/src/lib.rs new file mode 100644 index 0000000000..0c9ac1ac8e --- /dev/null +++ b/compiler/rustc_codegen_gcc/build_sysroot/src/lib.rs @@ -0,0 +1 @@ +#![no_std] diff --git a/compiler/rustc_codegen_gcc/cargo.sh b/compiler/rustc_codegen_gcc/cargo.sh new file mode 100755 index 0000000000..1001c52205 --- /dev/null +++ b/compiler/rustc_codegen_gcc/cargo.sh @@ -0,0 +1,23 @@ +#!/bin/bash + +if [ -z $CHANNEL ]; then +export CHANNEL='debug' +fi + +pushd $(dirname "$0") >/dev/null +source config.sh + +# read nightly compiler from rust-toolchain file +TOOLCHAIN=$(cat rust-toolchain) + +popd >/dev/null + +if [[ $(rustc -V) != $(rustc +${TOOLCHAIN} -V) ]]; then + echo "rustc_codegen_gcc is build for $(rustc +${TOOLCHAIN} -V) but the default rustc version is $(rustc -V)." + echo "Using $(rustc +${TOOLCHAIN} -V)." +fi + +cmd=$1 +shift + +RUSTDOCFLAGS="$RUSTFLAGS" cargo +${TOOLCHAIN} $cmd --target $TARGET_TRIPLE $@ diff --git a/compiler/rustc_codegen_gcc/clean_all.sh b/compiler/rustc_codegen_gcc/clean_all.sh new file mode 100755 index 0000000000..a77d1486fe --- /dev/null +++ b/compiler/rustc_codegen_gcc/clean_all.sh @@ -0,0 +1,5 @@ +#!/bin/bash --verbose +set -e + +rm -rf target/ build_sysroot/{sysroot/,sysroot_src/,target/,Cargo.lock} perf.data{,.old} +rm -rf regex/ simple-raytracer/ diff --git a/compiler/rustc_codegen_gcc/config.sh b/compiler/rustc_codegen_gcc/config.sh new file mode 100644 index 0000000000..87df2f2102 --- /dev/null +++ b/compiler/rustc_codegen_gcc/config.sh @@ -0,0 +1,52 @@ +set -e + +export CARGO_INCREMENTAL=0 + +if [ -f ./gcc_path ]; then + export GCC_PATH=$(cat gcc_path) +else + echo 'Please put the path to your custom build of libgccjit in the file `gcc_path`, see Readme.md for details' + exit 1 +fi + +unamestr=`uname` +if [[ "$unamestr" == 'Linux' ]]; then + dylib_ext='so' +elif [[ "$unamestr" == 'Darwin' ]]; then + dylib_ext='dylib' +else + echo "Unsupported os" + exit 1 +fi + +HOST_TRIPLE=$(rustc -vV | grep host | cut -d: -f2 | tr -d " ") +TARGET_TRIPLE=$HOST_TRIPLE +#TARGET_TRIPLE="m68k-unknown-linux-gnu" + +linker='' +RUN_WRAPPER='' +if [[ "$HOST_TRIPLE" != "$TARGET_TRIPLE" ]]; then + if [[ "$TARGET_TRIPLE" == "m68k-unknown-linux-gnu" ]]; then + TARGET_TRIPLE="mips-unknown-linux-gnu" + linker='-Clinker=m68k-linux-gcc' + elif [[ "$TARGET_TRIPLE" == "aarch64-unknown-linux-gnu" ]]; then + # We are cross-compiling for aarch64. Use the correct linker and run tests in qemu. + linker='-Clinker=aarch64-linux-gnu-gcc' + RUN_WRAPPER='qemu-aarch64 -L /usr/aarch64-linux-gnu' + else + echo "Unknown non-native platform" + fi +fi + +export RUSTFLAGS="$linker -Cpanic=abort -Zsymbol-mangling-version=v0 -Cdebuginfo=2 -Clto=off -Zpanic-abort-tests -Zcodegen-backend=$(pwd)/target/${CHANNEL:-debug}/librustc_codegen_gcc.$dylib_ext --sysroot $(pwd)/build_sysroot/sysroot" + +# FIXME(antoyo): remove once the atomic shim is gone +if [[ `uname` == 'Darwin' ]]; then + export RUSTFLAGS="$RUSTFLAGS -Clink-arg=-undefined -Clink-arg=dynamic_lookup" +fi + +RUSTC="rustc $RUSTFLAGS -L crate=target/out --out-dir target/out" +export RUSTC_LOG=warn # display metadata load errors + +export LD_LIBRARY_PATH="$(pwd)/target/out:$(pwd)/build_sysroot/sysroot/lib/rustlib/$TARGET_TRIPLE/lib:$GCC_PATH" +export DYLD_LIBRARY_PATH=$LD_LIBRARY_PATH diff --git a/compiler/rustc_codegen_gcc/example/alloc_example.rs b/compiler/rustc_codegen_gcc/example/alloc_example.rs new file mode 100644 index 0000000000..74ea7ec4ed --- /dev/null +++ b/compiler/rustc_codegen_gcc/example/alloc_example.rs @@ -0,0 +1,41 @@ +#![feature(start, box_syntax, core_intrinsics, alloc_error_handler)] +#![no_std] + +extern crate alloc; +extern crate alloc_system; + +use alloc::boxed::Box; + +use alloc_system::System; + +#[global_allocator] +static ALLOC: System = System; + +#[link(name = "c")] +extern "C" { + fn puts(s: *const u8) -> i32; +} + +#[panic_handler] +fn panic_handler(_: &core::panic::PanicInfo) -> ! { + unsafe { + core::intrinsics::abort(); + } +} + +#[alloc_error_handler] +fn alloc_error_handler(_: alloc::alloc::Layout) -> ! { + unsafe { + core::intrinsics::abort(); + } +} + +#[start] +fn main(_argc: isize, _argv: *const *const u8) -> isize { + let world: Box<&str> = box "Hello World!\0"; + unsafe { + puts(*world as *const str as *const u8); + } + + 0 +} diff --git a/compiler/rustc_codegen_gcc/example/alloc_system.rs b/compiler/rustc_codegen_gcc/example/alloc_system.rs new file mode 100644 index 0000000000..5f66ca67f2 --- /dev/null +++ b/compiler/rustc_codegen_gcc/example/alloc_system.rs @@ -0,0 +1,212 @@ +// Copyright 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. +#![no_std] +#![feature(allocator_api, rustc_private)] +#![cfg_attr(any(unix, target_os = "redox"), feature(libc))] + +// The minimum alignment guaranteed by the architecture. This value is used to +// add fast paths for low alignment values. +#[cfg(all(any(target_arch = "x86", + target_arch = "arm", + target_arch = "mips", + target_arch = "powerpc", + target_arch = "powerpc64")))] +const MIN_ALIGN: usize = 8; +#[cfg(all(any(target_arch = "x86_64", + target_arch = "aarch64", + target_arch = "mips64", + target_arch = "s390x", + target_arch = "sparc64")))] +const MIN_ALIGN: usize = 16; + +pub struct System; +#[cfg(any(windows, unix, target_os = "redox"))] +mod realloc_fallback { + use core::alloc::{GlobalAlloc, Layout}; + use core::cmp; + use core::ptr; + impl super::System { + pub(crate) unsafe fn realloc_fallback(&self, ptr: *mut u8, old_layout: Layout, + new_size: usize) -> *mut u8 { + // Docs for GlobalAlloc::realloc require this to be valid: + let new_layout = Layout::from_size_align_unchecked(new_size, old_layout.align()); + let new_ptr = GlobalAlloc::alloc(self, new_layout); + if !new_ptr.is_null() { + let size = cmp::min(old_layout.size(), new_size); + ptr::copy_nonoverlapping(ptr, new_ptr, size); + GlobalAlloc::dealloc(self, ptr, old_layout); + } + new_ptr + } + } +} +#[cfg(any(unix, target_os = "redox"))] +mod platform { + extern crate libc; + use core::ptr; + use MIN_ALIGN; + use System; + use core::alloc::{GlobalAlloc, Layout}; + unsafe impl GlobalAlloc for System { + #[inline] + unsafe fn alloc(&self, layout: Layout) -> *mut u8 { + if layout.align() <= MIN_ALIGN && layout.align() <= layout.size() { + libc::malloc(layout.size()) as *mut u8 + } else { + #[cfg(target_os = "macos")] + { + if layout.align() > (1 << 31) { + return ptr::null_mut() + } + } + aligned_malloc(&layout) + } + } + #[inline] + unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 { + if layout.align() <= MIN_ALIGN && layout.align() <= layout.size() { + libc::calloc(layout.size(), 1) as *mut u8 + } else { + let ptr = self.alloc(layout.clone()); + if !ptr.is_null() { + ptr::write_bytes(ptr, 0, layout.size()); + } + ptr + } + } + #[inline] + unsafe fn dealloc(&self, ptr: *mut u8, _layout: Layout) { + libc::free(ptr as *mut libc::c_void) + } + #[inline] + unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 { + if layout.align() <= MIN_ALIGN && layout.align() <= new_size { + libc::realloc(ptr as *mut libc::c_void, new_size) as *mut u8 + } else { + self.realloc_fallback(ptr, layout, new_size) + } + } + } + #[cfg(any(target_os = "android", + target_os = "hermit", + target_os = "redox", + target_os = "solaris"))] + #[inline] + unsafe fn aligned_malloc(layout: &Layout) -> *mut u8 { + // On android we currently target API level 9 which unfortunately + // doesn't have the `posix_memalign` API used below. Instead we use + // `memalign`, but this unfortunately has the property on some systems + // where the memory returned cannot be deallocated by `free`! + // + // Upon closer inspection, however, this appears to work just fine with + // Android, so for this platform we should be fine to call `memalign` + // (which is present in API level 9). Some helpful references could + // possibly be chromium using memalign [1], attempts at documenting that + // memalign + free is ok [2] [3], or the current source of chromium + // which still uses memalign on android [4]. + // + // [1]: https://codereview.chromium.org/10796020/ + // [2]: https://code.google.com/p/android/issues/detail?id=35391 + // [3]: https://bugs.chromium.org/p/chromium/issues/detail?id=138579 + // [4]: https://chromium.googlesource.com/chromium/src/base/+/master/ + // /memory/aligned_memory.cc + libc::memalign(layout.align(), layout.size()) as *mut u8 + } + #[cfg(not(any(target_os = "android", + target_os = "hermit", + target_os = "redox", + target_os = "solaris")))] + #[inline] + unsafe fn aligned_malloc(layout: &Layout) -> *mut u8 { + let mut out = ptr::null_mut(); + let ret = libc::posix_memalign(&mut out, layout.align(), layout.size()); + if ret != 0 { + ptr::null_mut() + } else { + out as *mut u8 + } + } +} +#[cfg(windows)] +#[allow(nonstandard_style)] +mod platform { + use MIN_ALIGN; + use System; + use core::alloc::{GlobalAlloc, Layout}; + type LPVOID = *mut u8; + type HANDLE = LPVOID; + type SIZE_T = usize; + type DWORD = u32; + type BOOL = i32; + extern "system" { + fn GetProcessHeap() -> HANDLE; + fn HeapAlloc(hHeap: HANDLE, dwFlags: DWORD, dwBytes: SIZE_T) -> LPVOID; + fn HeapReAlloc(hHeap: HANDLE, dwFlags: DWORD, lpMem: LPVOID, dwBytes: SIZE_T) -> LPVOID; + fn HeapFree(hHeap: HANDLE, dwFlags: DWORD, lpMem: LPVOID) -> BOOL; + fn GetLastError() -> DWORD; + } + #[repr(C)] + struct Header(*mut u8); + const HEAP_ZERO_MEMORY: DWORD = 0x00000008; + unsafe fn get_header<'a>(ptr: *mut u8) -> &'a mut Header { + &mut *(ptr as *mut Header).offset(-1) + } + unsafe fn align_ptr(ptr: *mut u8, align: usize) -> *mut u8 { + let aligned = ptr.add(align - (ptr as usize & (align - 1))); + *get_header(aligned) = Header(ptr); + aligned + } + #[inline] + unsafe fn allocate_with_flags(layout: Layout, flags: DWORD) -> *mut u8 { + let ptr = if layout.align() <= MIN_ALIGN { + HeapAlloc(GetProcessHeap(), flags, layout.size()) + } else { + let size = layout.size() + layout.align(); + let ptr = HeapAlloc(GetProcessHeap(), flags, size); + if ptr.is_null() { + ptr + } else { + align_ptr(ptr, layout.align()) + } + }; + ptr as *mut u8 + } + unsafe impl GlobalAlloc for System { + #[inline] + unsafe fn alloc(&self, layout: Layout) -> *mut u8 { + allocate_with_flags(layout, 0) + } + #[inline] + unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 { + allocate_with_flags(layout, HEAP_ZERO_MEMORY) + } + #[inline] + unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { + if layout.align() <= MIN_ALIGN { + let err = HeapFree(GetProcessHeap(), 0, ptr as LPVOID); + debug_assert!(err != 0, "Failed to free heap memory: {}", + GetLastError()); + } else { + let header = get_header(ptr); + let err = HeapFree(GetProcessHeap(), 0, header.0 as LPVOID); + debug_assert!(err != 0, "Failed to free heap memory: {}", + GetLastError()); + } + } + #[inline] + unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 { + if layout.align() <= MIN_ALIGN { + HeapReAlloc(GetProcessHeap(), 0, ptr as LPVOID, new_size) as *mut u8 + } else { + self.realloc_fallback(ptr, layout, new_size) + } + } + } +} diff --git a/compiler/rustc_codegen_gcc/example/arbitrary_self_types_pointers_and_wrappers.rs b/compiler/rustc_codegen_gcc/example/arbitrary_self_types_pointers_and_wrappers.rs new file mode 100644 index 0000000000..ddeb752f93 --- /dev/null +++ b/compiler/rustc_codegen_gcc/example/arbitrary_self_types_pointers_and_wrappers.rs @@ -0,0 +1,69 @@ +// Adapted from rustc run-pass test suite + +#![feature(arbitrary_self_types, unsize, coerce_unsized, dispatch_from_dyn)] +#![feature(rustc_attrs)] + +use std::{ + ops::{Deref, CoerceUnsized, DispatchFromDyn}, + marker::Unsize, +}; + +struct Ptr(Box); + +impl Deref for Ptr { + type Target = T; + + fn deref(&self) -> &T { + &*self.0 + } +} + +impl + ?Sized, U: ?Sized> CoerceUnsized> for Ptr {} +impl + ?Sized, U: ?Sized> DispatchFromDyn> for Ptr {} + +struct Wrapper(T); + +impl Deref for Wrapper { + type Target = T; + + fn deref(&self) -> &T { + &self.0 + } +} + +impl, U> CoerceUnsized> for Wrapper {} +impl, U> DispatchFromDyn> for Wrapper {} + + +trait Trait { + // This method isn't object-safe yet. Unsized by-value `self` is object-safe (but not callable + // without unsized_locals), but wrappers arond `Self` currently are not. + // FIXME (mikeyhew) uncomment this when unsized rvalues object-safety is implemented + // fn wrapper(self: Wrapper) -> i32; + fn ptr_wrapper(self: Ptr>) -> i32; + fn wrapper_ptr(self: Wrapper>) -> i32; + fn wrapper_ptr_wrapper(self: Wrapper>>) -> i32; +} + +impl Trait for i32 { + fn ptr_wrapper(self: Ptr>) -> i32 { + **self + } + fn wrapper_ptr(self: Wrapper>) -> i32 { + **self + } + fn wrapper_ptr_wrapper(self: Wrapper>>) -> i32 { + ***self + } +} + +fn main() { + let pw = Ptr(Box::new(Wrapper(5))) as Ptr>; + assert_eq!(pw.ptr_wrapper(), 5); + + let wp = Wrapper(Ptr(Box::new(6))) as Wrapper>; + assert_eq!(wp.wrapper_ptr(), 6); + + let wpw = Wrapper(Ptr(Box::new(Wrapper(7)))) as Wrapper>>; + assert_eq!(wpw.wrapper_ptr_wrapper(), 7); +} diff --git a/compiler/rustc_codegen_gcc/example/dst-field-align.rs b/compiler/rustc_codegen_gcc/example/dst-field-align.rs new file mode 100644 index 0000000000..6c338e9991 --- /dev/null +++ b/compiler/rustc_codegen_gcc/example/dst-field-align.rs @@ -0,0 +1,67 @@ +// run-pass +#![allow(dead_code)] +struct Foo { + a: u16, + b: T +} + +trait Bar { + fn get(&self) -> usize; +} + +impl Bar for usize { + fn get(&self) -> usize { *self } +} + +struct Baz { + a: T +} + +struct HasDrop { + ptr: Box, + data: T +} + +fn main() { + // Test that zero-offset works properly + let b : Baz = Baz { a: 7 }; + assert_eq!(b.a.get(), 7); + let b : &Baz = &b; + assert_eq!(b.a.get(), 7); + + // Test that the field is aligned properly + let f : Foo = Foo { a: 0, b: 11 }; + assert_eq!(f.b.get(), 11); + let ptr1 : *const u8 = &f.b as *const _ as *const u8; + + let f : &Foo = &f; + let ptr2 : *const u8 = &f.b as *const _ as *const u8; + assert_eq!(f.b.get(), 11); + + // The pointers should be the same + assert_eq!(ptr1, ptr2); + + // Test that nested DSTs work properly + let f : Foo> = Foo { a: 0, b: Foo { a: 1, b: 17 }}; + assert_eq!(f.b.b.get(), 17); + let f : &Foo> = &f; + assert_eq!(f.b.b.get(), 17); + + // Test that get the pointer via destructuring works + + let f : Foo = Foo { a: 0, b: 11 }; + let f : &Foo = &f; + let &Foo { a: _, b: ref bar } = f; + assert_eq!(bar.get(), 11); + + // Make sure that drop flags don't screw things up + + let d : HasDrop> = HasDrop { + ptr: Box::new(0), + data: Baz { a: [1,2,3,4] } + }; + assert_eq!([1,2,3,4], d.data.a); + + let d : &HasDrop> = &d; + assert_eq!(&[1,2,3,4], &d.data.a); +} diff --git a/compiler/rustc_codegen_gcc/example/example.rs b/compiler/rustc_codegen_gcc/example/example.rs new file mode 100644 index 0000000000..5878e8548d --- /dev/null +++ b/compiler/rustc_codegen_gcc/example/example.rs @@ -0,0 +1,208 @@ +#![feature(no_core, unboxed_closures)] +#![no_core] +#![allow(dead_code)] + +extern crate mini_core; + +use mini_core::*; + +fn abc(a: u8) -> u8 { + a * 2 +} + +fn bcd(b: bool, a: u8) -> u8 { + if b { + a * 2 + } else { + a * 3 + } +} + +fn call() { + abc(42); +} + +fn indirect_call() { + let f: fn() = call; + f(); +} + +enum BoolOption { + Some(bool), + None, +} + +fn option_unwrap_or(o: BoolOption, d: bool) -> bool { + match o { + BoolOption::Some(b) => b, + BoolOption::None => d, + } +} + +fn ret_42() -> u8 { + 42 +} + +fn return_str() -> &'static str { + "hello world" +} + +fn promoted_val() -> &'static u8 { + &(1 * 2) +} + +fn cast_ref_to_raw_ptr(abc: &u8) -> *const u8 { + abc as *const u8 +} + +fn cmp_raw_ptr(a: *const u8, b: *const u8) -> bool { + a == b +} + +fn int_cast(a: u16, b: i16) -> (u8, u16, u32, usize, i8, i16, i32, isize, u8, u32) { + ( + a as u8, a as u16, a as u32, a as usize, a as i8, a as i16, a as i32, a as isize, b as u8, + b as u32, + ) +} + +fn char_cast(c: char) -> u8 { + c as u8 +} + +pub struct DebugTuple(()); + +fn debug_tuple() -> DebugTuple { + DebugTuple(()) +} + +fn size_of() -> usize { + intrinsics::size_of::() +} + +fn use_size_of() -> usize { + size_of::() +} + +unsafe fn use_copy_intrinsic(src: *const u8, dst: *mut u8) { + intrinsics::copy::(src, dst, 1); +} + +unsafe fn use_copy_intrinsic_ref(src: *const u8, dst: *mut u8) { + let copy2 = &intrinsics::copy::; + copy2(src, dst, 1); +} + +const ABC: u8 = 6 * 7; + +fn use_const() -> u8 { + ABC +} + +pub fn call_closure_3arg() { + (|_, _, _| {})(0u8, 42u16, 0u8) +} + +pub fn call_closure_2arg() { + (|_, _| {})(0u8, 42u16) +} + +struct IsNotEmpty; + +impl<'a, 'b> FnOnce<(&'a &'b [u16],)> for IsNotEmpty { + type Output = (u8, u8); + + #[inline] + extern "rust-call" fn call_once(mut self, arg: (&'a &'b [u16],)) -> (u8, u8) { + self.call_mut(arg) + } +} + +impl<'a, 'b> FnMut<(&'a &'b [u16],)> for IsNotEmpty { + #[inline] + extern "rust-call" fn call_mut(&mut self, _arg: (&'a &'b [u16],)) -> (u8, u8) { + (0, 42) + } +} + +pub fn call_is_not_empty() { + IsNotEmpty.call_once((&(&[0u16] as &[_]),)); +} + +fn eq_char(a: char, b: char) -> bool { + a == b +} + +unsafe fn transmute(c: char) -> u32 { + intrinsics::transmute(c) +} + +unsafe fn deref_str_ptr(s: *const str) -> &'static str { + &*s +} + +fn use_array(arr: [u8; 3]) -> u8 { + arr[1] +} + +fn repeat_array() -> [u8; 3] { + [0; 3] +} + +fn array_as_slice(arr: &[u8; 3]) -> &[u8] { + arr +} + +unsafe fn use_ctlz_nonzero(a: u16) -> u16 { + intrinsics::ctlz_nonzero(a) +} + +fn ptr_as_usize(ptr: *const u8) -> usize { + ptr as usize +} + +fn float_cast(a: f32, b: f64) -> (f64, f32) { + (a as f64, b as f32) +} + +fn int_to_float(a: u8, b: i32) -> (f64, f32) { + (a as f64, b as f32) +} + +fn make_array() -> [u8; 3] { + [42, 0, 5] +} + +fn some_promoted_tuple() -> &'static (&'static str, &'static str) { + &("abc", "some") +} + +fn index_slice(s: &[u8]) -> u8 { + s[2] +} + +pub struct StrWrapper { + s: str, +} + +fn str_wrapper_get(w: &StrWrapper) -> &str { + &w.s +} + +fn i16_as_i8(a: i16) -> i8 { + a as i8 +} + +struct Unsized(u8, str); + +fn get_sized_field_ref_from_unsized_type(u: &Unsized) -> &u8 { + &u.0 +} + +fn get_unsized_field_ref_from_unsized_type(u: &Unsized) -> &str { + &u.1 +} + +pub fn reuse_byref_argument_storage(a: (u8, u16, u32)) -> u8 { + a.0 +} diff --git a/compiler/rustc_codegen_gcc/example/mini_core.rs b/compiler/rustc_codegen_gcc/example/mini_core.rs new file mode 100644 index 0000000000..1067cee881 --- /dev/null +++ b/compiler/rustc_codegen_gcc/example/mini_core.rs @@ -0,0 +1,585 @@ +#![feature( + no_core, lang_items, intrinsics, unboxed_closures, type_ascription, extern_types, + untagged_unions, decl_macro, rustc_attrs, transparent_unions, auto_traits, + thread_local +)] +#![no_core] +#![allow(dead_code)] + +#[no_mangle] +unsafe extern "C" fn _Unwind_Resume() { + intrinsics::unreachable(); +} + +#[lang = "sized"] +pub trait Sized {} + +#[lang = "unsize"] +pub trait Unsize {} + +#[lang = "coerce_unsized"] +pub trait CoerceUnsized {} + +impl<'a, 'b: 'a, T: ?Sized + Unsize, U: ?Sized> CoerceUnsized<&'a U> for &'b T {} +impl<'a, T: ?Sized + Unsize, U: ?Sized> CoerceUnsized<&'a mut U> for &'a mut T {} +impl, U: ?Sized> CoerceUnsized<*const U> for *const T {} +impl, U: ?Sized> CoerceUnsized<*mut U> for *mut T {} + +#[lang = "dispatch_from_dyn"] +pub trait DispatchFromDyn {} + +// &T -> &U +impl<'a, T: ?Sized+Unsize, U: ?Sized> DispatchFromDyn<&'a U> for &'a T {} +// &mut T -> &mut U +impl<'a, T: ?Sized+Unsize, U: ?Sized> DispatchFromDyn<&'a mut U> for &'a mut T {} +// *const T -> *const U +impl, U: ?Sized> DispatchFromDyn<*const U> for *const T {} +// *mut T -> *mut U +impl, U: ?Sized> DispatchFromDyn<*mut U> for *mut T {} +impl, U: ?Sized> DispatchFromDyn> for Box {} + +#[lang = "receiver"] +pub trait Receiver {} + +impl Receiver for &T {} +impl Receiver for &mut T {} +impl Receiver for Box {} + +#[lang = "copy"] +pub unsafe trait Copy {} + +unsafe impl Copy for bool {} +unsafe impl Copy for u8 {} +unsafe impl Copy for u16 {} +unsafe impl Copy for u32 {} +unsafe impl Copy for u64 {} +unsafe impl Copy for usize {} +unsafe impl Copy for i8 {} +unsafe impl Copy for i16 {} +unsafe impl Copy for i32 {} +unsafe impl Copy for isize {} +unsafe impl Copy for f32 {} +unsafe impl Copy for char {} +unsafe impl<'a, T: ?Sized> Copy for &'a T {} +unsafe impl Copy for *const T {} +unsafe impl Copy for *mut T {} + +#[lang = "sync"] +pub unsafe trait Sync {} + +unsafe impl Sync for bool {} +unsafe impl Sync for u8 {} +unsafe impl Sync for u16 {} +unsafe impl Sync for u32 {} +unsafe impl Sync for u64 {} +unsafe impl Sync for usize {} +unsafe impl Sync for i8 {} +unsafe impl Sync for i16 {} +unsafe impl Sync for i32 {} +unsafe impl Sync for isize {} +unsafe impl Sync for char {} +unsafe impl<'a, T: ?Sized> Sync for &'a T {} +unsafe impl Sync for [u8; 16] {} + +#[lang = "freeze"] +unsafe auto trait Freeze {} + +unsafe impl Freeze for PhantomData {} +unsafe impl Freeze for *const T {} +unsafe impl Freeze for *mut T {} +unsafe impl Freeze for &T {} +unsafe impl Freeze for &mut T {} + +#[lang = "structural_peq"] +pub trait StructuralPartialEq {} + +#[lang = "structural_teq"] +pub trait StructuralEq {} + +#[lang = "not"] +pub trait Not { + type Output; + + fn not(self) -> Self::Output; +} + +impl Not for bool { + type Output = bool; + + fn not(self) -> bool { + !self + } +} + +#[lang = "mul"] +pub trait Mul { + type Output; + + #[must_use] + fn mul(self, rhs: RHS) -> Self::Output; +} + +impl Mul for u8 { + type Output = Self; + + fn mul(self, rhs: Self) -> Self::Output { + self * rhs + } +} + +impl Mul for usize { + type Output = Self; + + fn mul(self, rhs: Self) -> Self::Output { + self * rhs + } +} + +#[lang = "add"] +pub trait Add { + type Output; + + fn add(self, rhs: RHS) -> Self::Output; +} + +impl Add for u8 { + type Output = Self; + + fn add(self, rhs: Self) -> Self { + self + rhs + } +} + +impl Add for i8 { + type Output = Self; + + fn add(self, rhs: Self) -> Self { + self + rhs + } +} + +impl Add for usize { + type Output = Self; + + fn add(self, rhs: Self) -> Self { + self + rhs + } +} + +#[lang = "sub"] +pub trait Sub { + type Output; + + fn sub(self, rhs: RHS) -> Self::Output; +} + +impl Sub for usize { + type Output = Self; + + fn sub(self, rhs: Self) -> Self { + self - rhs + } +} + +impl Sub for u8 { + type Output = Self; + + fn sub(self, rhs: Self) -> Self { + self - rhs + } +} + +impl Sub for i8 { + type Output = Self; + + fn sub(self, rhs: Self) -> Self { + self - rhs + } +} + +impl Sub for i16 { + type Output = Self; + + fn sub(self, rhs: Self) -> Self { + self - rhs + } +} + +#[lang = "rem"] +pub trait Rem { + type Output; + + fn rem(self, rhs: RHS) -> Self::Output; +} + +impl Rem for usize { + type Output = Self; + + fn rem(self, rhs: Self) -> Self { + self % rhs + } +} + +#[lang = "bitor"] +pub trait BitOr { + type Output; + + #[must_use] + fn bitor(self, rhs: RHS) -> Self::Output; +} + +impl BitOr for bool { + type Output = bool; + + fn bitor(self, rhs: bool) -> bool { + self | rhs + } +} + +impl<'a> BitOr for &'a bool { + type Output = bool; + + fn bitor(self, rhs: bool) -> bool { + *self | rhs + } +} + +#[lang = "eq"] +pub trait PartialEq { + fn eq(&self, other: &Rhs) -> bool; + fn ne(&self, other: &Rhs) -> bool; +} + +impl PartialEq for u8 { + fn eq(&self, other: &u8) -> bool { + (*self) == (*other) + } + fn ne(&self, other: &u8) -> bool { + (*self) != (*other) + } +} + +impl PartialEq for u16 { + fn eq(&self, other: &u16) -> bool { + (*self) == (*other) + } + fn ne(&self, other: &u16) -> bool { + (*self) != (*other) + } +} + +impl PartialEq for u32 { + fn eq(&self, other: &u32) -> bool { + (*self) == (*other) + } + fn ne(&self, other: &u32) -> bool { + (*self) != (*other) + } +} + + +impl PartialEq for u64 { + fn eq(&self, other: &u64) -> bool { + (*self) == (*other) + } + fn ne(&self, other: &u64) -> bool { + (*self) != (*other) + } +} + +impl PartialEq for usize { + fn eq(&self, other: &usize) -> bool { + (*self) == (*other) + } + fn ne(&self, other: &usize) -> bool { + (*self) != (*other) + } +} + +impl PartialEq for i8 { + fn eq(&self, other: &i8) -> bool { + (*self) == (*other) + } + fn ne(&self, other: &i8) -> bool { + (*self) != (*other) + } +} + +impl PartialEq for i32 { + fn eq(&self, other: &i32) -> bool { + (*self) == (*other) + } + fn ne(&self, other: &i32) -> bool { + (*self) != (*other) + } +} + +impl PartialEq for isize { + fn eq(&self, other: &isize) -> bool { + (*self) == (*other) + } + fn ne(&self, other: &isize) -> bool { + (*self) != (*other) + } +} + +impl PartialEq for char { + fn eq(&self, other: &char) -> bool { + (*self) == (*other) + } + fn ne(&self, other: &char) -> bool { + (*self) != (*other) + } +} + +impl PartialEq for *const T { + fn eq(&self, other: &*const T) -> bool { + *self == *other + } + fn ne(&self, other: &*const T) -> bool { + *self != *other + } +} + +#[lang = "neg"] +pub trait Neg { + type Output; + + fn neg(self) -> Self::Output; +} + +impl Neg for i8 { + type Output = i8; + + fn neg(self) -> i8 { + -self + } +} + +impl Neg for i16 { + type Output = i16; + + fn neg(self) -> i16 { + self + } +} + +impl Neg for isize { + type Output = isize; + + fn neg(self) -> isize { + -self + } +} + +impl Neg for f32 { + type Output = f32; + + fn neg(self) -> f32 { + -self + } +} + +pub enum Option { + Some(T), + None, +} + +pub use Option::*; + +#[lang = "phantom_data"] +pub struct PhantomData; + +#[lang = "fn_once"] +#[rustc_paren_sugar] +pub trait FnOnce { + #[lang = "fn_once_output"] + type Output; + + extern "rust-call" fn call_once(self, args: Args) -> Self::Output; +} + +#[lang = "fn_mut"] +#[rustc_paren_sugar] +pub trait FnMut: FnOnce { + extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output; +} + +#[lang = "panic"] +#[track_caller] +pub fn panic(_msg: &str) -> ! { + unsafe { + libc::puts("Panicking\n\0" as *const str as *const u8); + intrinsics::abort(); + } +} + +#[lang = "panic_bounds_check"] +#[track_caller] +fn panic_bounds_check(index: usize, len: usize) -> ! { + unsafe { + libc::printf("index out of bounds: the len is %d but the index is %d\n\0" as *const str as *const i8, len, index); + intrinsics::abort(); + } +} + +#[lang = "eh_personality"] +fn eh_personality() -> ! { + loop {} +} + +#[lang = "drop_in_place"] +#[allow(unconditional_recursion)] +pub unsafe fn drop_in_place(to_drop: *mut T) { + // Code here does not matter - this is replaced by the + // real drop glue by the compiler. + drop_in_place(to_drop); +} + +#[lang = "deref"] +pub trait Deref { + type Target: ?Sized; + + fn deref(&self) -> &Self::Target; +} + +#[lang = "owned_box"] +pub struct Box(*mut T); + +impl, U: ?Sized> CoerceUnsized> for Box {} + +impl Drop for Box { + fn drop(&mut self) { + // drop is currently performed by compiler. + } +} + +impl Deref for Box { + type Target = T; + + fn deref(&self) -> &Self::Target { + &**self + } +} + +#[lang = "exchange_malloc"] +unsafe fn allocate(size: usize, _align: usize) -> *mut u8 { + libc::malloc(size) +} + +#[lang = "box_free"] +unsafe fn box_free(ptr: *mut T) { + libc::free(ptr as *mut u8); +} + +#[lang = "drop"] +pub trait Drop { + fn drop(&mut self); +} + +#[lang = "manually_drop"] +#[repr(transparent)] +pub struct ManuallyDrop { + pub value: T, +} + +#[lang = "maybe_uninit"] +#[repr(transparent)] +pub union MaybeUninit { + pub uninit: (), + pub value: ManuallyDrop, +} + +pub mod intrinsics { + extern "rust-intrinsic" { + pub fn abort() -> !; + pub fn size_of() -> usize; + pub fn size_of_val(val: *const T) -> usize; + pub fn min_align_of() -> usize; + pub fn min_align_of_val(val: *const T) -> usize; + pub fn copy(src: *const T, dst: *mut T, count: usize); + pub fn transmute(e: T) -> U; + pub fn ctlz_nonzero(x: T) -> T; + pub fn needs_drop() -> bool; + pub fn bitreverse(x: T) -> T; + pub fn bswap(x: T) -> T; + pub fn write_bytes(dst: *mut T, val: u8, count: usize); + pub fn unreachable() -> !; + } +} + +pub mod libc { + #[link(name = "c")] + extern "C" { + pub fn puts(s: *const u8) -> i32; + pub fn printf(format: *const i8, ...) -> i32; + pub fn malloc(size: usize) -> *mut u8; + pub fn free(ptr: *mut u8); + pub fn memcpy(dst: *mut u8, src: *const u8, size: usize); + pub fn memmove(dst: *mut u8, src: *const u8, size: usize); + pub fn strncpy(dst: *mut u8, src: *const u8, size: usize); + } +} + +#[lang = "index"] +pub trait Index { + type Output: ?Sized; + fn index(&self, index: Idx) -> &Self::Output; +} + +impl Index for [T; 3] { + type Output = T; + + fn index(&self, index: usize) -> &Self::Output { + &self[index] + } +} + +impl Index for [T] { + type Output = T; + + fn index(&self, index: usize) -> &Self::Output { + &self[index] + } +} + +extern { + type VaListImpl; +} + +#[lang = "va_list"] +#[repr(transparent)] +pub struct VaList<'a>(&'a mut VaListImpl); + +#[rustc_builtin_macro] +#[rustc_macro_transparency = "semitransparent"] +pub macro stringify($($t:tt)*) { /* compiler built-in */ } + +#[rustc_builtin_macro] +#[rustc_macro_transparency = "semitransparent"] +pub macro file() { /* compiler built-in */ } + +#[rustc_builtin_macro] +#[rustc_macro_transparency = "semitransparent"] +pub macro line() { /* compiler built-in */ } + +#[rustc_builtin_macro] +#[rustc_macro_transparency = "semitransparent"] +pub macro cfg() { /* compiler built-in */ } + +pub static A_STATIC: u8 = 42; + +#[lang = "panic_location"] +struct PanicLocation { + file: &'static str, + line: u32, + column: u32, +} + +#[no_mangle] +pub fn get_tls() -> u8 { + #[thread_local] + static A: u8 = 42; + + A +} diff --git a/compiler/rustc_codegen_gcc/example/mini_core_hello_world.rs b/compiler/rustc_codegen_gcc/example/mini_core_hello_world.rs new file mode 100644 index 0000000000..69d591565a --- /dev/null +++ b/compiler/rustc_codegen_gcc/example/mini_core_hello_world.rs @@ -0,0 +1,424 @@ +// Adapted from https://github.com/sunfishcode/mir2cranelift/blob/master/rust-examples/nocore-hello-world.rs + +#![feature( + no_core, unboxed_closures, start, lang_items, box_syntax, never_type, linkage, + extern_types, thread_local +)] +#![no_core] +#![allow(dead_code, non_camel_case_types)] + +extern crate mini_core; + +use mini_core::*; +use mini_core::libc::*; + +unsafe extern "C" fn my_puts(s: *const u8) { + puts(s); +} + +#[lang = "termination"] +trait Termination { + fn report(self) -> i32; +} + +impl Termination for () { + fn report(self) -> i32 { + unsafe { + NUM = 6 * 7 + 1 + (1u8 == 1u8) as u8; // 44 + *NUM_REF as i32 + } + } +} + +trait SomeTrait { + fn object_safe(&self); +} + +impl SomeTrait for &'static str { + fn object_safe(&self) { + unsafe { + puts(*self as *const str as *const u8); + } + } +} + +struct NoisyDrop { + text: &'static str, + inner: NoisyDropInner, +} + +struct NoisyDropInner; + +impl Drop for NoisyDrop { + fn drop(&mut self) { + unsafe { + puts(self.text as *const str as *const u8); + } + } +} + +impl Drop for NoisyDropInner { + fn drop(&mut self) { + unsafe { + puts("Inner got dropped!\0" as *const str as *const u8); + } + } +} + +impl SomeTrait for NoisyDrop { + fn object_safe(&self) {} +} + +enum Ordering { + Less = -1, + Equal = 0, + Greater = 1, +} + +#[lang = "start"] +fn start( + main: fn() -> T, + argc: isize, + argv: *const *const u8, +) -> isize { + if argc == 3 { + unsafe { puts(*argv); } + unsafe { puts(*((argv as usize + intrinsics::size_of::<*const u8>()) as *const *const u8)); } + unsafe { puts(*((argv as usize + 2 * intrinsics::size_of::<*const u8>()) as *const *const u8)); } + } + + main().report(); + 0 +} + +static mut NUM: u8 = 6 * 7; +static NUM_REF: &'static u8 = unsafe { &NUM }; + +macro_rules! assert { + ($e:expr) => { + if !$e { + panic(stringify!(! $e)); + } + }; +} + +macro_rules! assert_eq { + ($l:expr, $r: expr) => { + if $l != $r { + panic(stringify!($l != $r)); + } + } +} + +struct Unique { + pointer: *const T, + _marker: PhantomData, +} + +impl CoerceUnsized> for Unique where T: Unsize {} + +unsafe fn zeroed() -> T { + let mut uninit = MaybeUninit { uninit: () }; + intrinsics::write_bytes(&mut uninit.value.value as *mut T, 0, 1); + uninit.value.value +} + +fn take_f32(_f: f32) {} +fn take_unique(_u: Unique<()>) {} + +fn return_u128_pair() -> (u128, u128) { + (0, 0) +} + +fn call_return_u128_pair() { + return_u128_pair(); +} + +fn main() { + take_unique(Unique { + pointer: 0 as *const (), + _marker: PhantomData, + }); + take_f32(0.1); + + //call_return_u128_pair(); + + let slice = &[0, 1] as &[i32]; + let slice_ptr = slice as *const [i32] as *const i32; + + assert_eq!(slice_ptr as usize % 4, 0); + + //return; + + unsafe { + printf("Hello %s\n\0" as *const str as *const i8, "printf\0" as *const str as *const i8); + + let hello: &[u8] = b"Hello\0" as &[u8; 6]; + let ptr: *const u8 = hello as *const [u8] as *const u8; + puts(ptr); + + let world: Box<&str> = box "World!\0"; + puts(*world as *const str as *const u8); + world as Box; + + assert_eq!(intrinsics::bitreverse(0b10101000u8), 0b00010101u8); + + assert_eq!(intrinsics::bswap(0xabu8), 0xabu8); + assert_eq!(intrinsics::bswap(0xddccu16), 0xccddu16); + assert_eq!(intrinsics::bswap(0xffee_ddccu32), 0xccdd_eeffu32); + assert_eq!(intrinsics::bswap(0x1234_5678_ffee_ddccu64), 0xccdd_eeff_7856_3412u64); + + assert_eq!(intrinsics::size_of_val(hello) as u8, 6); + + let chars = &['C', 'h', 'a', 'r', 's']; + let chars = chars as &[char]; + assert_eq!(intrinsics::size_of_val(chars) as u8, 4 * 5); + + let a: &dyn SomeTrait = &"abc\0"; + a.object_safe(); + + assert_eq!(intrinsics::size_of_val(a) as u8, 16); + assert_eq!(intrinsics::size_of_val(&0u32) as u8, 4); + + assert_eq!(intrinsics::min_align_of::() as u8, 2); + assert_eq!(intrinsics::min_align_of_val(&a) as u8, intrinsics::min_align_of::<&str>() as u8); + + assert!(!intrinsics::needs_drop::()); + assert!(intrinsics::needs_drop::()); + + Unique { + pointer: 0 as *const &str, + _marker: PhantomData, + } as Unique; + + struct MyDst(T); + + intrinsics::size_of_val(&MyDst([0u8; 4]) as &MyDst<[u8]>); + + struct Foo { + x: u8, + y: !, + } + + unsafe fn uninitialized() -> T { + MaybeUninit { uninit: () }.value.value + } + + zeroed::<(u8, u8)>(); + #[allow(unreachable_code)] + { + if false { + zeroed::(); + zeroed::(); + uninitialized::(); + } + } + } + + let _ = box NoisyDrop { + text: "Boxed outer got dropped!\0", + inner: NoisyDropInner, + } as Box; + + const FUNC_REF: Option = Some(main); + match FUNC_REF { + Some(_) => {}, + None => assert!(false), + } + + match Ordering::Less { + Ordering::Less => {}, + _ => assert!(false), + } + + [NoisyDropInner, NoisyDropInner]; + + let x = &[0u32, 42u32] as &[u32]; + match x { + [] => assert_eq!(0u32, 1), + [_, ref y @ ..] => assert_eq!(&x[1] as *const u32 as usize, &y[0] as *const u32 as usize), + } + + assert_eq!(((|()| 42u8) as fn(()) -> u8)(()), 42); + + extern { + #[linkage = "weak"] + static ABC: *const u8; + } + + { + extern { + #[linkage = "weak"] + static ABC: *const u8; + } + } + + // TODO(antoyo): to make this work, support weak linkage. + //unsafe { assert_eq!(ABC as usize, 0); } + + &mut (|| Some(0 as *const ())) as &mut dyn FnMut() -> Option<*const ()>; + + let f = 1000.0; + assert_eq!(f as u8, 255); + let f2 = -1000.0; + assert_eq!(f2 as i8, -128); + assert_eq!(f2 as u8, 0); + + static ANOTHER_STATIC: &u8 = &A_STATIC; + assert_eq!(*ANOTHER_STATIC, 42); + + check_niche_behavior(); + + extern "C" { + type ExternType; + } + + struct ExternTypeWrapper { + _a: ExternType, + } + + let nullptr = 0 as *const (); + let extern_nullptr = nullptr as *const ExternTypeWrapper; + extern_nullptr as *const (); + let slice_ptr = &[] as *const [u8]; + slice_ptr as *const u8; + + #[cfg(not(jit))] + test_tls(); +} + +#[repr(C)] +enum c_void { + _1, + _2, +} + +type c_int = i32; +type c_ulong = u64; + +type pthread_t = c_ulong; + +#[repr(C)] +struct pthread_attr_t { + __size: [u64; 7], +} + +#[link(name = "pthread")] +extern "C" { + fn pthread_attr_init(attr: *mut pthread_attr_t) -> c_int; + + fn pthread_create( + native: *mut pthread_t, + attr: *const pthread_attr_t, + f: extern "C" fn(_: *mut c_void) -> *mut c_void, + value: *mut c_void + ) -> c_int; + + fn pthread_join( + native: pthread_t, + value: *mut *mut c_void + ) -> c_int; +} + +#[thread_local] +#[cfg(not(jit))] +static mut TLS: u8 = 42; + +#[cfg(not(jit))] +extern "C" fn mutate_tls(_: *mut c_void) -> *mut c_void { + unsafe { TLS = 0; } + 0 as *mut c_void +} + +#[cfg(not(jit))] +fn test_tls() { + unsafe { + let mut attr: pthread_attr_t = zeroed(); + let mut thread: pthread_t = 0; + + assert_eq!(TLS, 42); + + if pthread_attr_init(&mut attr) != 0 { + assert!(false); + } + + if pthread_create(&mut thread, &attr, mutate_tls, 0 as *mut c_void) != 0 { + assert!(false); + } + + let mut res = 0 as *mut c_void; + pthread_join(thread, &mut res); + + // TLS of main thread must not have been changed by the other thread. + assert_eq!(TLS, 42); + + puts("TLS works!\n\0" as *const str as *const u8); + } +} + +// Copied ui/issues/issue-61696.rs + +pub enum Infallible {} + +// The check that the `bool` field of `V1` is encoding a "niche variant" +// (i.e. not `V1`, so `V3` or `V4`) used to be mathematically incorrect, +// causing valid `V1` values to be interpreted as other variants. +pub enum E1 { + V1 { f: bool }, + V2 { f: Infallible }, + V3, + V4, +} + +// Computing the discriminant used to be done using the niche type (here `u8`, +// from the `bool` field of `V1`), overflowing for variants with large enough +// indices (`V3` and `V4`), causing them to be interpreted as other variants. +pub enum E2 { + V1 { f: bool }, + + /*_00*/ _01(X), _02(X), _03(X), _04(X), _05(X), _06(X), _07(X), + _08(X), _09(X), _0A(X), _0B(X), _0C(X), _0D(X), _0E(X), _0F(X), + _10(X), _11(X), _12(X), _13(X), _14(X), _15(X), _16(X), _17(X), + _18(X), _19(X), _1A(X), _1B(X), _1C(X), _1D(X), _1E(X), _1F(X), + _20(X), _21(X), _22(X), _23(X), _24(X), _25(X), _26(X), _27(X), + _28(X), _29(X), _2A(X), _2B(X), _2C(X), _2D(X), _2E(X), _2F(X), + _30(X), _31(X), _32(X), _33(X), _34(X), _35(X), _36(X), _37(X), + _38(X), _39(X), _3A(X), _3B(X), _3C(X), _3D(X), _3E(X), _3F(X), + _40(X), _41(X), _42(X), _43(X), _44(X), _45(X), _46(X), _47(X), + _48(X), _49(X), _4A(X), _4B(X), _4C(X), _4D(X), _4E(X), _4F(X), + _50(X), _51(X), _52(X), _53(X), _54(X), _55(X), _56(X), _57(X), + _58(X), _59(X), _5A(X), _5B(X), _5C(X), _5D(X), _5E(X), _5F(X), + _60(X), _61(X), _62(X), _63(X), _64(X), _65(X), _66(X), _67(X), + _68(X), _69(X), _6A(X), _6B(X), _6C(X), _6D(X), _6E(X), _6F(X), + _70(X), _71(X), _72(X), _73(X), _74(X), _75(X), _76(X), _77(X), + _78(X), _79(X), _7A(X), _7B(X), _7C(X), _7D(X), _7E(X), _7F(X), + _80(X), _81(X), _82(X), _83(X), _84(X), _85(X), _86(X), _87(X), + _88(X), _89(X), _8A(X), _8B(X), _8C(X), _8D(X), _8E(X), _8F(X), + _90(X), _91(X), _92(X), _93(X), _94(X), _95(X), _96(X), _97(X), + _98(X), _99(X), _9A(X), _9B(X), _9C(X), _9D(X), _9E(X), _9F(X), + _A0(X), _A1(X), _A2(X), _A3(X), _A4(X), _A5(X), _A6(X), _A7(X), + _A8(X), _A9(X), _AA(X), _AB(X), _AC(X), _AD(X), _AE(X), _AF(X), + _B0(X), _B1(X), _B2(X), _B3(X), _B4(X), _B5(X), _B6(X), _B7(X), + _B8(X), _B9(X), _BA(X), _BB(X), _BC(X), _BD(X), _BE(X), _BF(X), + _C0(X), _C1(X), _C2(X), _C3(X), _C4(X), _C5(X), _C6(X), _C7(X), + _C8(X), _C9(X), _CA(X), _CB(X), _CC(X), _CD(X), _CE(X), _CF(X), + _D0(X), _D1(X), _D2(X), _D3(X), _D4(X), _D5(X), _D6(X), _D7(X), + _D8(X), _D9(X), _DA(X), _DB(X), _DC(X), _DD(X), _DE(X), _DF(X), + _E0(X), _E1(X), _E2(X), _E3(X), _E4(X), _E5(X), _E6(X), _E7(X), + _E8(X), _E9(X), _EA(X), _EB(X), _EC(X), _ED(X), _EE(X), _EF(X), + _F0(X), _F1(X), _F2(X), _F3(X), _F4(X), _F5(X), _F6(X), _F7(X), + _F8(X), _F9(X), _FA(X), _FB(X), _FC(X), _FD(X), _FE(X), _FF(X), + + V3, + V4, +} + +fn check_niche_behavior () { + if let E1::V2 { .. } = (E1::V1 { f: true }) { + intrinsics::abort(); + } + + if let E2::V1 { .. } = E2::V3:: { + intrinsics::abort(); + } +} diff --git a/compiler/rustc_codegen_gcc/example/mod_bench.rs b/compiler/rustc_codegen_gcc/example/mod_bench.rs new file mode 100644 index 0000000000..2e2b0052de --- /dev/null +++ b/compiler/rustc_codegen_gcc/example/mod_bench.rs @@ -0,0 +1,37 @@ +#![feature(start, box_syntax, core_intrinsics, lang_items)] +#![no_std] + +#[link(name = "c")] +extern {} + +#[panic_handler] +fn panic_handler(_: &core::panic::PanicInfo) -> ! { + unsafe { + core::intrinsics::abort(); + } +} + +#[lang="eh_personality"] +fn eh_personality(){} + +// Required for rustc_codegen_llvm +#[no_mangle] +unsafe extern "C" fn _Unwind_Resume() { + core::intrinsics::unreachable(); +} + +#[start] +fn main(_argc: isize, _argv: *const *const u8) -> isize { + for i in 2..100_000_000 { + black_box((i + 1) % i); + } + + 0 +} + +#[inline(never)] +fn black_box(i: u32) { + if i != 1 { + unsafe { core::intrinsics::abort(); } + } +} diff --git a/compiler/rustc_codegen_gcc/example/std_example.rs b/compiler/rustc_codegen_gcc/example/std_example.rs new file mode 100644 index 0000000000..eba0eb8289 --- /dev/null +++ b/compiler/rustc_codegen_gcc/example/std_example.rs @@ -0,0 +1,278 @@ +#![feature(core_intrinsics, generators, generator_trait, is_sorted)] + +use std::arch::x86_64::*; +use std::io::Write; +use std::ops::Generator; + +extern { + pub fn printf(format: *const i8, ...) -> i32; +} + +fn main() { + let mutex = std::sync::Mutex::new(()); + let _guard = mutex.lock().unwrap(); + + let _ = ::std::iter::repeat('a' as u8).take(10).collect::>(); + let stderr = ::std::io::stderr(); + let mut stderr = stderr.lock(); + + std::thread::spawn(move || { + println!("Hello from another thread!"); + }); + + writeln!(stderr, "some {} text", "").unwrap(); + + let _ = std::process::Command::new("true").env("c", "d").spawn(); + + println!("cargo:rustc-link-lib=z"); + + static ONCE: std::sync::Once = std::sync::Once::new(); + ONCE.call_once(|| {}); + + let _eq = LoopState::Continue(()) == LoopState::Break(()); + + // Make sure ByValPair values with differently sized components are correctly passed + map(None::<(u8, Box)>); + + println!("{}", 2.3f32.exp()); + println!("{}", 2.3f32.exp2()); + println!("{}", 2.3f32.abs()); + println!("{}", 2.3f32.sqrt()); + println!("{}", 2.3f32.floor()); + println!("{}", 2.3f32.ceil()); + println!("{}", 2.3f32.min(1.0)); + println!("{}", 2.3f32.max(1.0)); + println!("{}", 2.3f32.powi(2)); + println!("{}", 2.3f32.log2()); + assert_eq!(2.3f32.copysign(-1.0), -2.3f32); + println!("{}", 2.3f32.powf(2.0)); + + assert_eq!(-128i8, (-128i8).saturating_sub(1)); + assert_eq!(127i8, 127i8.saturating_sub(-128)); + assert_eq!(-128i8, (-128i8).saturating_add(-128)); + assert_eq!(127i8, 127i8.saturating_add(1)); + + assert_eq!(-32768i16, (-32768i16).saturating_add(-32768)); + assert_eq!(32767i16, 32767i16.saturating_add(1)); + + assert_eq!(0b0000000000000000000000000010000010000000000000000000000000000000_0000000000100000000000000000000000001000000000000100000000000000u128.leading_zeros(), 26); + assert_eq!(0b0000000000000000000000000010000000000000000000000000000000000000_0000000000000000000000000000000000001000000000000000000010000000u128.trailing_zeros(), 7); + + let _d = 0i128.checked_div(2i128); + let _d = 0u128.checked_div(2u128); + assert_eq!(1u128 + 2, 3); + + assert_eq!(0b100010000000000000000000000000000u128 >> 10, 0b10001000000000000000000u128); + assert_eq!(0xFEDCBA987654321123456789ABCDEFu128 >> 64, 0xFEDCBA98765432u128); + assert_eq!(0xFEDCBA987654321123456789ABCDEFu128 as i128 >> 64, 0xFEDCBA98765432i128); + + let tmp = 353985398u128; + assert_eq!(tmp * 932490u128, 330087843781020u128); + + let tmp = -0x1234_5678_9ABC_DEF0i64; + assert_eq!(tmp as i128, -0x1234_5678_9ABC_DEF0i128); + + // Check that all u/i128 <-> float casts work correctly. + let houndred_u128 = 100u128; + let houndred_i128 = 100i128; + let houndred_f32 = 100.0f32; + let houndred_f64 = 100.0f64; + assert_eq!(houndred_u128 as f32, 100.0); + assert_eq!(houndred_u128 as f64, 100.0); + assert_eq!(houndred_f32 as u128, 100); + assert_eq!(houndred_f64 as u128, 100); + assert_eq!(houndred_i128 as f32, 100.0); + assert_eq!(houndred_i128 as f64, 100.0); + assert_eq!(houndred_f32 as i128, 100); + assert_eq!(houndred_f64 as i128, 100); + + let _a = 1u32 << 2u8; + + let empty: [i32; 0] = []; + assert!(empty.is_sorted()); + + println!("{:?}", std::intrinsics::caller_location()); + + /*unsafe { + test_simd(); + }*/ + + Box::pin(move |mut _task_context| { + yield (); + }).as_mut().resume(0); + + println!("End"); +} + +/*#[target_feature(enable = "sse2")] +unsafe fn test_simd() { + let x = _mm_setzero_si128(); + let y = _mm_set1_epi16(7); + let or = _mm_or_si128(x, y); + let cmp_eq = _mm_cmpeq_epi8(y, y); + let cmp_lt = _mm_cmplt_epi8(y, y); + + /*assert_eq!(std::mem::transmute::<_, [u16; 8]>(or), [7, 7, 7, 7, 7, 7, 7, 7]); + assert_eq!(std::mem::transmute::<_, [u16; 8]>(cmp_eq), [0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff]); + assert_eq!(std::mem::transmute::<_, [u16; 8]>(cmp_lt), [0, 0, 0, 0, 0, 0, 0, 0]); + + test_mm_slli_si128(); + test_mm_movemask_epi8(); + test_mm256_movemask_epi8(); + test_mm_add_epi8(); + test_mm_add_pd(); + test_mm_cvtepi8_epi16(); + test_mm_cvtsi128_si64(); + + // FIXME(#666) implement `#[rustc_arg_required_const(..)]` support + //test_mm_extract_epi8(); + + let mask1 = _mm_movemask_epi8(dbg!(_mm_setr_epi8(255u8 as i8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0))); + assert_eq!(mask1, 1);*/ +}*/ + +/*#[target_feature(enable = "sse2")] +unsafe fn test_mm_slli_si128() { + #[rustfmt::skip] + let a = _mm_setr_epi8( + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + ); + let r = _mm_slli_si128(a, 1); + let e = _mm_setr_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + assert_eq_m128i(r, e); + + #[rustfmt::skip] + let a = _mm_setr_epi8( + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + ); + let r = _mm_slli_si128(a, 15); + let e = _mm_setr_epi8(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1); + assert_eq_m128i(r, e); + + #[rustfmt::skip] + let a = _mm_setr_epi8( + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + ); + let r = _mm_slli_si128(a, 16); + assert_eq_m128i(r, _mm_set1_epi8(0)); + + #[rustfmt::skip] + let a = _mm_setr_epi8( + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + ); + let r = _mm_slli_si128(a, -1); + assert_eq_m128i(_mm_set1_epi8(0), r); + + #[rustfmt::skip] + let a = _mm_setr_epi8( + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + ); + let r = _mm_slli_si128(a, -0x80000000); + assert_eq_m128i(r, _mm_set1_epi8(0)); +} + +#[target_feature(enable = "sse2")] +unsafe fn test_mm_movemask_epi8() { + #[rustfmt::skip] + let a = _mm_setr_epi8( + 0b1000_0000u8 as i8, 0b0, 0b1000_0000u8 as i8, 0b01, + 0b0101, 0b1111_0000u8 as i8, 0, 0, + 0, 0, 0b1111_0000u8 as i8, 0b0101, + 0b01, 0b1000_0000u8 as i8, 0b0, 0b1000_0000u8 as i8, + ); + let r = _mm_movemask_epi8(a); + assert_eq!(r, 0b10100100_00100101); +} + +#[target_feature(enable = "avx2")] +unsafe fn test_mm256_movemask_epi8() { + let a = _mm256_set1_epi8(-1); + let r = _mm256_movemask_epi8(a); + let e = -1; + assert_eq!(r, e); +} + +#[target_feature(enable = "sse2")] +unsafe fn test_mm_add_epi8() { + let a = _mm_setr_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + #[rustfmt::skip] + let b = _mm_setr_epi8( + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + ); + let r = _mm_add_epi8(a, b); + #[rustfmt::skip] + let e = _mm_setr_epi8( + 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, + ); + assert_eq_m128i(r, e); +} + +#[target_feature(enable = "sse2")] +unsafe fn test_mm_add_pd() { + let a = _mm_setr_pd(1.0, 2.0); + let b = _mm_setr_pd(5.0, 10.0); + let r = _mm_add_pd(a, b); + assert_eq_m128d(r, _mm_setr_pd(6.0, 12.0)); +} + +fn assert_eq_m128i(x: std::arch::x86_64::__m128i, y: std::arch::x86_64::__m128i) { + unsafe { + assert_eq!(std::mem::transmute::<_, [u8; 16]>(x), std::mem::transmute::<_, [u8; 16]>(y)); + } +} + +#[target_feature(enable = "sse2")] +pub unsafe fn assert_eq_m128d(a: __m128d, b: __m128d) { + if _mm_movemask_pd(_mm_cmpeq_pd(a, b)) != 0b11 { + panic!("{:?} != {:?}", a, b); + } +} + +#[target_feature(enable = "sse2")] +unsafe fn test_mm_cvtsi128_si64() { + let r = _mm_cvtsi128_si64(std::mem::transmute::<[i64; 2], _>([5, 0])); + assert_eq!(r, 5); +} + +#[target_feature(enable = "sse4.1")] +unsafe fn test_mm_cvtepi8_epi16() { + let a = _mm_set1_epi8(10); + let r = _mm_cvtepi8_epi16(a); + let e = _mm_set1_epi16(10); + assert_eq_m128i(r, e); + let a = _mm_set1_epi8(-10); + let r = _mm_cvtepi8_epi16(a); + let e = _mm_set1_epi16(-10); + assert_eq_m128i(r, e); +} + +#[target_feature(enable = "sse4.1")] +unsafe fn test_mm_extract_epi8() { + #[rustfmt::skip] + let a = _mm_setr_epi8( + -1, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 14, 15 + ); + let r1 = _mm_extract_epi8(a, 0); + let r2 = _mm_extract_epi8(a, 19); + assert_eq!(r1, 0xFF); + assert_eq!(r2, 3); +}*/ + +#[derive(PartialEq)] +enum LoopState { + Continue(()), + Break(()) +} + +pub enum Instruction { + Increment, + Loop, +} + +fn map(a: Option<(u8, Box)>) -> Option> { + match a { + None => None, + Some((_, instr)) => Some(instr), + } +} diff --git a/compiler/rustc_codegen_gcc/example/subslice-patterns-const-eval.rs b/compiler/rustc_codegen_gcc/example/subslice-patterns-const-eval.rs new file mode 100644 index 0000000000..2cb84786f5 --- /dev/null +++ b/compiler/rustc_codegen_gcc/example/subslice-patterns-const-eval.rs @@ -0,0 +1,97 @@ +// Based on https://github.com/rust-lang/rust/blob/c5840f9d252c2f5cc16698dbf385a29c5de3ca07/src/test/ui/array-slice-vec/subslice-patterns-const-eval-match.rs + +// Test that array subslice patterns are correctly handled in const evaluation. + +// run-pass + +#[derive(PartialEq, Debug, Clone)] +struct N(u8); + +#[derive(PartialEq, Debug, Clone)] +struct Z; + +macro_rules! n { + ($($e:expr),* $(,)?) => { + [$(N($e)),*] + } +} + +// This macro has an unused variable so that it can be repeated base on the +// number of times a repeated variable (`$e` in `z`) occurs. +macro_rules! zed { + ($e:expr) => { Z } +} + +macro_rules! z { + ($($e:expr),* $(,)?) => { + [$(zed!($e)),*] + } +} + +// Compare constant evaluation and runtime evaluation of a given expression. +macro_rules! compare_evaluation { + ($e:expr, $t:ty $(,)?) => {{ + const CONST_EVAL: $t = $e; + const fn const_eval() -> $t { $e } + static CONST_EVAL2: $t = const_eval(); + let runtime_eval = $e; + assert_eq!(CONST_EVAL, runtime_eval); + assert_eq!(CONST_EVAL2, runtime_eval); + }} +} + +// Repeat `$test`, substituting the given macro variables with the given +// identifiers. +// +// For example: +// +// repeat! { +// ($name); X; Y: +// struct $name; +// } +// +// Expands to: +// +// struct X; struct Y; +// +// This is used to repeat the tests using both the `N` and `Z` +// types. +macro_rules! repeat { + (($($dollar:tt $placeholder:ident)*); $($($values:ident),+);*: $($test:tt)*) => { + macro_rules! single { + ($($dollar $placeholder:ident),*) => { $($test)* } + } + $(single!($($values),+);)* + } +} + +fn main() { + repeat! { + ($arr $Ty); n, N; z, Z: + compare_evaluation!({ let [_, x @ .., _] = $arr!(1, 2, 3, 4); x }, [$Ty; 2]); + compare_evaluation!({ let [_, ref x @ .., _] = $arr!(1, 2, 3, 4); x }, &'static [$Ty; 2]); + compare_evaluation!({ let [_, x @ .., _] = &$arr!(1, 2, 3, 4); x }, &'static [$Ty; 2]); + + compare_evaluation!({ let [_, _, x @ .., _, _] = $arr!(1, 2, 3, 4); x }, [$Ty; 0]); + compare_evaluation!( + { let [_, _, ref x @ .., _, _] = $arr!(1, 2, 3, 4); x }, + &'static [$Ty; 0], + ); + compare_evaluation!( + { let [_, _, x @ .., _, _] = &$arr!(1, 2, 3, 4); x }, + &'static [$Ty; 0], + ); + + compare_evaluation!({ let [_, .., x] = $arr!(1, 2, 3, 4); x }, $Ty); + compare_evaluation!({ let [_, .., ref x] = $arr!(1, 2, 3, 4); x }, &'static $Ty); + compare_evaluation!({ let [_, _y @ .., x] = &$arr!(1, 2, 3, 4); x }, &'static $Ty); + } + + compare_evaluation!({ let [_, .., N(x)] = n!(1, 2, 3, 4); x }, u8); + compare_evaluation!({ let [_, .., N(ref x)] = n!(1, 2, 3, 4); x }, &'static u8); + compare_evaluation!({ let [_, .., N(x)] = &n!(1, 2, 3, 4); x }, &'static u8); + + compare_evaluation!({ let [N(x), .., _] = n!(1, 2, 3, 4); x }, u8); + compare_evaluation!({ let [N(ref x), .., _] = n!(1, 2, 3, 4); x }, &'static u8); + compare_evaluation!({ let [N(x), .., _] = &n!(1, 2, 3, 4); x }, &'static u8); +} diff --git a/compiler/rustc_codegen_gcc/example/track-caller-attribute.rs b/compiler/rustc_codegen_gcc/example/track-caller-attribute.rs new file mode 100644 index 0000000000..93bab17e46 --- /dev/null +++ b/compiler/rustc_codegen_gcc/example/track-caller-attribute.rs @@ -0,0 +1,40 @@ +// Based on https://github.com/anp/rust/blob/175631311716d7dfeceec40d2587cde7142ffa8c/src/test/ui/rfc-2091-track-caller/track-caller-attribute.rs + +// run-pass + +use std::panic::Location; + +#[track_caller] +fn tracked() -> &'static Location<'static> { + Location::caller() +} + +fn nested_intrinsic() -> &'static Location<'static> { + Location::caller() +} + +fn nested_tracked() -> &'static Location<'static> { + tracked() +} + +fn main() { + let location = Location::caller(); + assert_eq!(location.file(), file!()); + assert_eq!(location.line(), 21); + assert_eq!(location.column(), 20); + + let tracked = tracked(); + assert_eq!(tracked.file(), file!()); + assert_eq!(tracked.line(), 26); + assert_eq!(tracked.column(), 19); + + let nested = nested_intrinsic(); + assert_eq!(nested.file(), file!()); + assert_eq!(nested.line(), 13); + assert_eq!(nested.column(), 5); + + let contained = nested_tracked(); + assert_eq!(contained.file(), file!()); + assert_eq!(contained.line(), 17); + assert_eq!(contained.column(), 5); +} diff --git a/compiler/rustc_codegen_gcc/patches/0022-core-Disable-not-compiling-tests.patch b/compiler/rustc_codegen_gcc/patches/0022-core-Disable-not-compiling-tests.patch new file mode 100644 index 0000000000..aae62a938b --- /dev/null +++ b/compiler/rustc_codegen_gcc/patches/0022-core-Disable-not-compiling-tests.patch @@ -0,0 +1,63 @@ +From f6befc4bb51d84f5f1cf35938a168c953d421350 Mon Sep 17 00:00:00 2001 +From: bjorn3 +Date: Sun, 24 Nov 2019 15:10:23 +0100 +Subject: [PATCH] [core] Disable not compiling tests + +--- + library/core/tests/Cargo.toml | 8 ++++++++ + library/core/tests/num/flt2dec/mod.rs | 1 - + library/core/tests/num/int_macros.rs | 2 ++ + library/core/tests/num/uint_macros.rs | 2 ++ + library/core/tests/ptr.rs | 2 ++ + library/core/tests/slice.rs | 2 ++ + 6 files changed, 16 insertions(+), 1 deletion(-) + create mode 100644 library/core/tests/Cargo.toml + +diff --git a/library/core/tests/Cargo.toml b/library/core/tests/Cargo.toml +new file mode 100644 +index 0000000..46fd999 +--- /dev/null ++++ b/library/core/tests/Cargo.toml +@@ -0,0 +1,8 @@ ++[package] ++name = "core" ++version = "0.0.0" ++edition = "2018" ++ ++[lib] ++name = "coretests" ++path = "lib.rs" +diff --git a/library/core/tests/num/flt2dec/mod.rs b/library/core/tests/num/flt2dec/mod.rs +index a35897e..f0bf645 100644 +--- a/library/core/tests/num/flt2dec/mod.rs ++++ b/library/core/tests/num/flt2dec/mod.rs +@@ -13,7 +13,6 @@ mod strategy { + mod dragon; + mod grisu; + } +-mod random; + + pub fn decode_finite(v: T) -> Decoded { + match decode(v).1 { +diff --git a/library/core/tests/slice.rs b/library/core/tests/slice.rs +index 6609bc3..241b497 100644 +--- a/library/core/tests/slice.rs ++++ b/library/core/tests/slice.rs +@@ -1209,6 +1209,7 @@ fn brute_force_rotate_test_1() { + } + } + ++/* + #[test] + #[cfg(not(target_arch = "wasm32"))] + fn sort_unstable() { +@@ -1394,6 +1395,7 @@ fn partition_at_index() { + v.select_nth_unstable(0); + assert!(v == [0xDEADBEEF]); + } ++*/ + + #[test] + #[should_panic(expected = "index 0 greater than length of slice")] +-- +2.21.0 (Apple Git-122) diff --git a/compiler/rustc_codegen_gcc/patches/0023-core-Ignore-failing-tests.patch b/compiler/rustc_codegen_gcc/patches/0023-core-Ignore-failing-tests.patch new file mode 100644 index 0000000000..ee5ba449fb --- /dev/null +++ b/compiler/rustc_codegen_gcc/patches/0023-core-Ignore-failing-tests.patch @@ -0,0 +1,49 @@ +From dd82e95c9de212524e14fc60155de1ae40156dfc Mon Sep 17 00:00:00 2001 +From: bjorn3 +Date: Sun, 24 Nov 2019 15:34:06 +0100 +Subject: [PATCH] [core] Ignore failing tests + +--- + library/core/tests/iter.rs | 4 ++++ + library/core/tests/num/bignum.rs | 10 ++++++++++ + library/core/tests/num/mod.rs | 5 +++-- + library/core/tests/time.rs | 1 + + 4 files changed, 18 insertions(+), 2 deletions(-) + +diff --git a/library/core/tests/array.rs b/library/core/tests/array.rs +index 4bc44e9..8e3c7a4 100644 +--- a/library/core/tests/array.rs ++++ b/library/core/tests/array.rs +@@ -242,6 +242,7 @@ fn iterator_drops() { + assert_eq!(i.get(), 5); + } + ++/* + // This test does not work on targets without panic=unwind support. + // To work around this problem, test is marked is should_panic, so it will + // be automagically skipped on unsuitable targets, such as +@@ -283,6 +284,7 @@ fn array_default_impl_avoids_leaks_on_panic() { + assert_eq!(COUNTER.load(Relaxed), 0); + panic!("test succeeded") + } ++*/ + + #[test] + fn empty_array_is_always_default() { +@@ -304,6 +304,7 @@ fn array_map() { + assert_eq!(b, [1, 2, 3]); + } + ++/* + // See note on above test for why `should_panic` is used. + #[test] + #[should_panic(expected = "test succeeded")] +@@ -332,6 +333,7 @@ fn array_map_drop_safety() { + assert_eq!(DROPPED.load(Ordering::SeqCst), num_to_create); + panic!("test succeeded") + } ++*/ + + #[test] + fn cell_allows_array_cycle() { +-- 2.21.0 (Apple Git-122) diff --git a/compiler/rustc_codegen_gcc/prepare.sh b/compiler/rustc_codegen_gcc/prepare.sh new file mode 100755 index 0000000000..503fa29b36 --- /dev/null +++ b/compiler/rustc_codegen_gcc/prepare.sh @@ -0,0 +1,22 @@ +#!/bin/bash --verbose +set -e + +source prepare_build.sh + +cargo install hyperfine || echo "Skipping hyperfine install" + +git clone https://github.com/rust-lang/regex.git || echo "rust-lang/regex has already been cloned" +pushd regex +git checkout -- . +git checkout 341f207c1071f7290e3f228c710817c280c8dca1 +popd + +git clone https://github.com/ebobby/simple-raytracer || echo "ebobby/simple-raytracer has already been cloned" +pushd simple-raytracer +git checkout -- . +git checkout 804a7a21b9e673a482797aa289a18ed480e4d813 + +# build with cg_llvm for perf comparison +cargo build +mv target/debug/main raytracer_cg_llvm +popd diff --git a/compiler/rustc_codegen_gcc/prepare_build.sh b/compiler/rustc_codegen_gcc/prepare_build.sh new file mode 100755 index 0000000000..ccf5350983 --- /dev/null +++ b/compiler/rustc_codegen_gcc/prepare_build.sh @@ -0,0 +1,5 @@ +#!/bin/bash --verbose +set -e + +rustup component add rust-src rustc-dev llvm-tools-preview +./build_sysroot/prepare_sysroot_src.sh diff --git a/compiler/rustc_codegen_gcc/rust-toolchain b/compiler/rustc_codegen_gcc/rust-toolchain new file mode 100644 index 0000000000..d311a33f80 --- /dev/null +++ b/compiler/rustc_codegen_gcc/rust-toolchain @@ -0,0 +1 @@ +nightly-2021-09-28 diff --git a/compiler/rustc_codegen_gcc/rustup.sh b/compiler/rustc_codegen_gcc/rustup.sh new file mode 100755 index 0000000000..01ce5bb78b --- /dev/null +++ b/compiler/rustc_codegen_gcc/rustup.sh @@ -0,0 +1,29 @@ +#!/bin/bash + +set -e + +case $1 in + "prepare") + TOOLCHAIN=$(date +%Y-%m-%d) + + echo "=> Installing new nightly" + rustup toolchain install --profile minimal nightly-${TOOLCHAIN} # Sanity check to see if the nightly exists + echo nightly-${TOOLCHAIN} > rust-toolchain + + echo "=> Uninstalling all old nighlies" + for nightly in $(rustup toolchain list | grep nightly | grep -v $TOOLCHAIN | grep -v nightly-x86_64); do + rustup toolchain uninstall $nightly + done + + ./clean_all.sh + ./prepare.sh + ;; + "commit") + git add rust-toolchain + git commit -m "Rustup to $(rustc -V)" + ;; + *) + echo "Unknown command '$1'" + echo "Usage: ./rustup.sh prepare|commit" + ;; +esac diff --git a/compiler/rustc_codegen_gcc/src/abi.rs b/compiler/rustc_codegen_gcc/src/abi.rs new file mode 100644 index 0000000000..ce428c589a --- /dev/null +++ b/compiler/rustc_codegen_gcc/src/abi.rs @@ -0,0 +1,160 @@ +use gccjit::{ToRValue, Type}; +use rustc_codegen_ssa::traits::{AbiBuilderMethods, BaseTypeMethods}; +use rustc_middle::bug; +use rustc_middle::ty::Ty; +use rustc_target::abi::call::{CastTarget, FnAbi, PassMode, Reg, RegKind}; + +use crate::builder::Builder; +use crate::context::CodegenCx; +use crate::intrinsic::ArgAbiExt; +use crate::type_of::LayoutGccExt; + +impl<'a, 'gcc, 'tcx> AbiBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { + fn apply_attrs_callsite(&mut self, _fn_abi: &FnAbi<'tcx, Ty<'tcx>>, _callsite: Self::Value) { + // TODO(antoyo) + } + + fn get_param(&self, index: usize) -> Self::Value { + self.cx.current_func.borrow().expect("current func") + .get_param(index as i32) + .to_rvalue() + } +} + +impl GccType for CastTarget { + fn gcc_type<'gcc>(&self, cx: &CodegenCx<'gcc, '_>) -> Type<'gcc> { + let rest_gcc_unit = self.rest.unit.gcc_type(cx); + let (rest_count, rem_bytes) = + if self.rest.unit.size.bytes() == 0 { + (0, 0) + } + else { + (self.rest.total.bytes() / self.rest.unit.size.bytes(), self.rest.total.bytes() % self.rest.unit.size.bytes()) + }; + + if self.prefix.iter().all(|x| x.is_none()) { + // Simplify to a single unit when there is no prefix and size <= unit size + if self.rest.total <= self.rest.unit.size { + return rest_gcc_unit; + } + + // Simplify to array when all chunks are the same size and type + if rem_bytes == 0 { + return cx.type_array(rest_gcc_unit, rest_count); + } + } + + // Create list of fields in the main structure + let mut args: Vec<_> = self + .prefix + .iter() + .flat_map(|option_kind| { + option_kind.map(|kind| Reg { kind, size: self.prefix_chunk_size }.gcc_type(cx)) + }) + .chain((0..rest_count).map(|_| rest_gcc_unit)) + .collect(); + + // Append final integer + if rem_bytes != 0 { + // Only integers can be really split further. + assert_eq!(self.rest.unit.kind, RegKind::Integer); + args.push(cx.type_ix(rem_bytes * 8)); + } + + cx.type_struct(&args, false) + } +} + +pub trait GccType { + fn gcc_type<'gcc>(&self, cx: &CodegenCx<'gcc, '_>) -> Type<'gcc>; +} + +impl GccType for Reg { + fn gcc_type<'gcc>(&self, cx: &CodegenCx<'gcc, '_>) -> Type<'gcc> { + match self.kind { + RegKind::Integer => cx.type_ix(self.size.bits()), + RegKind::Float => { + match self.size.bits() { + 32 => cx.type_f32(), + 64 => cx.type_f64(), + _ => bug!("unsupported float: {:?}", self), + } + }, + RegKind::Vector => unimplemented!(), //cx.type_vector(cx.type_i8(), self.size.bytes()), + } + } +} + +pub trait FnAbiGccExt<'gcc, 'tcx> { + // TODO(antoyo): return a function pointer type instead? + fn gcc_type(&self, cx: &CodegenCx<'gcc, 'tcx>) -> (Type<'gcc>, Vec>, bool); + fn ptr_to_gcc_type(&self, cx: &CodegenCx<'gcc, 'tcx>) -> Type<'gcc>; +} + +impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> { + fn gcc_type(&self, cx: &CodegenCx<'gcc, 'tcx>) -> (Type<'gcc>, Vec>, bool) { + let args_capacity: usize = self.args.iter().map(|arg| + if arg.pad.is_some() { + 1 + } + else { + 0 + } + + if let PassMode::Pair(_, _) = arg.mode { + 2 + } else { + 1 + } + ).sum(); + let mut argument_tys = Vec::with_capacity( + if let PassMode::Indirect { .. } = self.ret.mode { + 1 + } + else { + 0 + } + args_capacity, + ); + + let return_ty = + match self.ret.mode { + PassMode::Ignore => cx.type_void(), + PassMode::Direct(_) | PassMode::Pair(..) => self.ret.layout.immediate_gcc_type(cx), + PassMode::Cast(cast) => cast.gcc_type(cx), + PassMode::Indirect { .. } => { + argument_tys.push(cx.type_ptr_to(self.ret.memory_ty(cx))); + cx.type_void() + } + }; + + for arg in &self.args { + // add padding + if let Some(ty) = arg.pad { + argument_tys.push(ty.gcc_type(cx)); + } + + let arg_ty = match arg.mode { + PassMode::Ignore => continue, + PassMode::Direct(_) => arg.layout.immediate_gcc_type(cx), + PassMode::Pair(..) => { + argument_tys.push(arg.layout.scalar_pair_element_gcc_type(cx, 0, true)); + argument_tys.push(arg.layout.scalar_pair_element_gcc_type(cx, 1, true)); + continue; + } + PassMode::Indirect { extra_attrs: Some(_), .. } => { + unimplemented!(); + } + PassMode::Cast(cast) => cast.gcc_type(cx), + PassMode::Indirect { extra_attrs: None, .. } => cx.type_ptr_to(arg.memory_ty(cx)), + }; + argument_tys.push(arg_ty); + } + + (return_ty, argument_tys, self.c_variadic) + } + + fn ptr_to_gcc_type(&self, cx: &CodegenCx<'gcc, 'tcx>) -> Type<'gcc> { + let (return_type, params, variadic) = self.gcc_type(cx); + let pointer_type = cx.context.new_function_pointer_type(None, return_type, ¶ms, variadic); + pointer_type + } +} diff --git a/compiler/rustc_codegen_gcc/src/allocator.rs b/compiler/rustc_codegen_gcc/src/allocator.rs new file mode 100644 index 0000000000..6378a31202 --- /dev/null +++ b/compiler/rustc_codegen_gcc/src/allocator.rs @@ -0,0 +1,116 @@ +use gccjit::{FunctionType, ToRValue}; +use rustc_ast::expand::allocator::{AllocatorKind, AllocatorTy, ALLOCATOR_METHODS}; +use rustc_middle::bug; +use rustc_middle::ty::TyCtxt; +use rustc_span::symbol::sym; + +use crate::GccContext; + +pub(crate) unsafe fn codegen(tcx: TyCtxt<'_>, mods: &mut GccContext, _module_name: &str, kind: AllocatorKind, has_alloc_error_handler: bool) { + let context = &mods.context; + let usize = + match tcx.sess.target.pointer_width { + 16 => context.new_type::(), + 32 => context.new_type::(), + 64 => context.new_type::(), + tws => bug!("Unsupported target word size for int: {}", tws), + }; + let i8 = context.new_type::(); + let i8p = i8.make_pointer(); + let void = context.new_type::<()>(); + + for method in ALLOCATOR_METHODS { + let mut types = Vec::with_capacity(method.inputs.len()); + for ty in method.inputs.iter() { + match *ty { + AllocatorTy::Layout => { + types.push(usize); + types.push(usize); + } + AllocatorTy::Ptr => types.push(i8p), + AllocatorTy::Usize => types.push(usize), + + AllocatorTy::ResultPtr | AllocatorTy::Unit => panic!("invalid allocator arg"), + } + } + let output = match method.output { + AllocatorTy::ResultPtr => Some(i8p), + AllocatorTy::Unit => None, + + AllocatorTy::Layout | AllocatorTy::Usize | AllocatorTy::Ptr => { + panic!("invalid allocator output") + } + }; + let name = format!("__rust_{}", method.name); + + let args: Vec<_> = types.iter().enumerate() + .map(|(index, typ)| context.new_parameter(None, *typ, &format!("param{}", index))) + .collect(); + let func = context.new_function(None, FunctionType::Exported, output.unwrap_or(void), &args, name, false); + + if tcx.sess.target.options.default_hidden_visibility { + // TODO(antoyo): set visibility. + } + if tcx.sess.must_emit_unwind_tables() { + // TODO(antoyo): emit unwind tables. + } + + let callee = kind.fn_name(method.name); + let args: Vec<_> = types.iter().enumerate() + .map(|(index, typ)| context.new_parameter(None, *typ, &format!("param{}", index))) + .collect(); + let callee = context.new_function(None, FunctionType::Extern, output.unwrap_or(void), &args, callee, false); + // TODO(antoyo): set visibility. + + let block = func.new_block("entry"); + + let args = args + .iter() + .enumerate() + .map(|(i, _)| func.get_param(i as i32).to_rvalue()) + .collect::>(); + let ret = context.new_call(None, callee, &args); + //llvm::LLVMSetTailCall(ret, True); + if output.is_some() { + block.end_with_return(None, ret); + } + else { + block.end_with_void_return(None); + } + + // TODO(@Commeownist): Check if we need to emit some extra debugging info in certain circumstances + // as described in https://github.com/rust-lang/rust/commit/77a96ed5646f7c3ee8897693decc4626fe380643 + } + + let types = [usize, usize]; + let name = "__rust_alloc_error_handler".to_string(); + let args: Vec<_> = types.iter().enumerate() + .map(|(index, typ)| context.new_parameter(None, *typ, &format!("param{}", index))) + .collect(); + let func = context.new_function(None, FunctionType::Exported, void, &args, name, false); + + let kind = + if has_alloc_error_handler { + AllocatorKind::Global + } + else { + AllocatorKind::Default + }; + let callee = kind.fn_name(sym::oom); + let args: Vec<_> = types.iter().enumerate() + .map(|(index, typ)| context.new_parameter(None, *typ, &format!("param{}", index))) + .collect(); + let callee = context.new_function(None, FunctionType::Extern, void, &args, callee, false); + //llvm::LLVMRustSetVisibility(callee, llvm::Visibility::Hidden); + + let block = func.new_block("entry"); + + let args = args + .iter() + .enumerate() + .map(|(i, _)| func.get_param(i as i32).to_rvalue()) + .collect::>(); + let _ret = context.new_call(None, callee, &args); + //llvm::LLVMSetTailCall(ret, True); + block.end_with_void_return(None); +} diff --git a/compiler/rustc_codegen_gcc/src/archive.rs b/compiler/rustc_codegen_gcc/src/archive.rs new file mode 100644 index 0000000000..11dd6d49aa --- /dev/null +++ b/compiler/rustc_codegen_gcc/src/archive.rs @@ -0,0 +1,217 @@ +use std::fs::File; +use std::path::{Path, PathBuf}; + +use rustc_codegen_ssa::back::archive::ArchiveBuilder; +use rustc_session::Session; + +use rustc_data_structures::temp_dir::MaybeTempDir; +use rustc_session::cstore::DllImport; + +struct ArchiveConfig<'a> { + sess: &'a Session, + dst: PathBuf, + use_native_ar: bool, + use_gnu_style_archive: bool, +} + +#[derive(Debug)] +enum ArchiveEntry { + FromArchive { + archive_index: usize, + entry_index: usize, + }, + File(PathBuf), +} + +pub struct ArArchiveBuilder<'a> { + config: ArchiveConfig<'a>, + src_archives: Vec<(PathBuf, ar::Archive)>, + // Don't use `HashMap` here, as the order is important. `rust.metadata.bin` must always be at + // the end of an archive for linkers to not get confused. + entries: Vec<(String, ArchiveEntry)>, +} + +impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> { + fn new(sess: &'a Session, output: &Path, input: Option<&Path>) -> Self { + let config = ArchiveConfig { + sess, + dst: output.to_path_buf(), + use_native_ar: false, + // FIXME test for linux and System V derivatives instead + use_gnu_style_archive: sess.target.options.archive_format == "gnu", + }; + + let (src_archives, entries) = if let Some(input) = input { + let mut archive = ar::Archive::new(File::open(input).unwrap()); + let mut entries = Vec::new(); + + let mut i = 0; + while let Some(entry) = archive.next_entry() { + let entry = entry.unwrap(); + entries.push(( + String::from_utf8(entry.header().identifier().to_vec()).unwrap(), + ArchiveEntry::FromArchive { + archive_index: 0, + entry_index: i, + }, + )); + i += 1; + } + + (vec![(input.to_owned(), archive)], entries) + } else { + (vec![], Vec::new()) + }; + + ArArchiveBuilder { + config, + src_archives, + entries, + } + } + + fn src_files(&mut self) -> Vec { + self.entries.iter().map(|(name, _)| name.clone()).collect() + } + + fn remove_file(&mut self, name: &str) { + let index = self + .entries + .iter() + .position(|(entry_name, _)| entry_name == name) + .expect("Tried to remove file not existing in src archive"); + self.entries.remove(index); + } + + fn add_file(&mut self, file: &Path) { + self.entries.push(( + file.file_name().unwrap().to_str().unwrap().to_string(), + ArchiveEntry::File(file.to_owned()), + )); + } + + fn add_archive(&mut self, archive_path: &Path, mut skip: F) -> std::io::Result<()> + where + F: FnMut(&str) -> bool + 'static, + { + let mut archive = ar::Archive::new(std::fs::File::open(&archive_path)?); + let archive_index = self.src_archives.len(); + + let mut i = 0; + while let Some(entry) = archive.next_entry() { + let entry = entry?; + let file_name = String::from_utf8(entry.header().identifier().to_vec()) + .map_err(|err| std::io::Error::new(std::io::ErrorKind::InvalidData, err))?; + if !skip(&file_name) { + self.entries + .push((file_name, ArchiveEntry::FromArchive { archive_index, entry_index: i })); + } + i += 1; + } + + self.src_archives.push((archive_path.to_owned(), archive)); + Ok(()) + } + + fn update_symbols(&mut self) { + } + + fn build(mut self) { + use std::process::Command; + + fn add_file_using_ar(archive: &Path, file: &Path) { + Command::new("ar") + .arg("r") // add or replace file + .arg("-c") // silence created file message + .arg(archive) + .arg(&file) + .status() + .unwrap(); + } + + enum BuilderKind<'a> { + Bsd(ar::Builder), + Gnu(ar::GnuBuilder), + NativeAr(&'a Path), + } + + let mut builder = if self.config.use_native_ar { + BuilderKind::NativeAr(&self.config.dst) + } else if self.config.use_gnu_style_archive { + BuilderKind::Gnu(ar::GnuBuilder::new( + File::create(&self.config.dst).unwrap(), + self.entries + .iter() + .map(|(name, _)| name.as_bytes().to_vec()) + .collect(), + )) + } else { + BuilderKind::Bsd(ar::Builder::new(File::create(&self.config.dst).unwrap())) + }; + + // Add all files + for (entry_name, entry) in self.entries.into_iter() { + match entry { + ArchiveEntry::FromArchive { + archive_index, + entry_index, + } => { + let (ref src_archive_path, ref mut src_archive) = + self.src_archives[archive_index]; + let entry = src_archive.jump_to_entry(entry_index).unwrap(); + let header = entry.header().clone(); + + match builder { + BuilderKind::Bsd(ref mut builder) => { + builder.append(&header, entry).unwrap() + } + BuilderKind::Gnu(ref mut builder) => { + builder.append(&header, entry).unwrap() + } + BuilderKind::NativeAr(archive_file) => { + Command::new("ar") + .arg("x") + .arg(src_archive_path) + .arg(&entry_name) + .status() + .unwrap(); + add_file_using_ar(archive_file, Path::new(&entry_name)); + std::fs::remove_file(entry_name).unwrap(); + } + } + } + ArchiveEntry::File(file) => + match builder { + BuilderKind::Bsd(ref mut builder) => { + builder + .append_file(entry_name.as_bytes(), &mut File::open(file).expect("file for bsd builder")) + .unwrap() + }, + BuilderKind::Gnu(ref mut builder) => { + builder + .append_file(entry_name.as_bytes(), &mut File::open(&file).expect(&format!("file {:?} for gnu builder", file))) + .unwrap() + }, + BuilderKind::NativeAr(archive_file) => add_file_using_ar(archive_file, &file), + }, + } + } + + // Finalize archive + std::mem::drop(builder); + + // Run ranlib to be able to link the archive + let status = std::process::Command::new("ranlib") + .arg(self.config.dst) + .status() + .expect("Couldn't run ranlib"); + + if !status.success() { + self.config.sess.fatal(&format!("Ranlib exited with code {:?}", status.code())); + } + } + + fn inject_dll_import_lib(&mut self, _lib_name: &str, _dll_imports: &[DllImport], _tmpdir: &MaybeTempDir) { + unimplemented!(); + } +} diff --git a/compiler/rustc_codegen_gcc/src/asm.rs b/compiler/rustc_codegen_gcc/src/asm.rs new file mode 100644 index 0000000000..3b77097e9a --- /dev/null +++ b/compiler/rustc_codegen_gcc/src/asm.rs @@ -0,0 +1,785 @@ +use gccjit::{LValue, RValue, ToRValue, Type}; +use rustc_ast::ast::{InlineAsmOptions, InlineAsmTemplatePiece}; +use rustc_codegen_ssa::mir::operand::OperandValue; +use rustc_codegen_ssa::mir::place::PlaceRef; +use rustc_codegen_ssa::traits::{AsmBuilderMethods, AsmMethods, BaseTypeMethods, BuilderMethods, GlobalAsmOperandRef, InlineAsmOperandRef}; + +use rustc_hir::LlvmInlineAsmInner; +use rustc_middle::{bug, ty::Instance}; +use rustc_span::{Span, Symbol}; +use rustc_target::asm::*; + +use std::borrow::Cow; + +use crate::builder::Builder; +use crate::context::CodegenCx; +use crate::type_of::LayoutGccExt; + + +// Rust asm! and GCC Extended Asm semantics differ substantially. +// +// 1. Rust asm operands go along as one list of operands. Operands themselves indicate +// if they're "in" or "out". "In" and "out" operands can interleave. One operand can be +// both "in" and "out" (`inout(reg)`). +// +// GCC asm has two different lists for "in" and "out" operands. In terms of gccjit, +// this means that all "out" operands must go before "in" operands. "In" and "out" operands +// cannot interleave. +// +// 2. Operand lists in both Rust and GCC are indexed. Index starts from 0. Indexes are important +// because the asm template refers to operands by index. +// +// Mapping from Rust to GCC index would be 1-1 if it wasn't for... +// +// 3. Clobbers. GCC has a separate list of clobbers, and clobbers don't have indexes. +// Contrary, Rust expresses clobbers through "out" operands that aren't tied to +// a variable (`_`), and such "clobbers" do have index. +// +// 4. Furthermore, GCC Extended Asm does not support explicit register constraints +// (like `out("eax")`) directly, offering so-called "local register variables" +// as a workaround. These variables need to be declared and initialized *before* +// the Extended Asm block but *after* normal local variables +// (see comment in `codegen_inline_asm` for explanation). +// +// With that in mind, let's see how we translate Rust syntax to GCC +// (from now on, `CC` stands for "constraint code"): +// +// * `out(reg_class) var` -> translated to output operand: `"=CC"(var)` +// * `inout(reg_class) var` -> translated to output operand: `"+CC"(var)` +// * `in(reg_class) var` -> translated to input operand: `"CC"(var)` +// +// * `out(reg_class) _` -> translated to one `=r(tmp)`, where "tmp" is a temporary unused variable +// +// * `out("explicit register") _` -> not translated to any operands, register is simply added to clobbers list +// +// * `inout(reg_class) in_var => out_var` -> translated to two operands: +// output: `"=CC"(in_var)` +// input: `"num"(out_var)` where num is the GCC index +// of the corresponding output operand +// +// * `inout(reg_class) in_var => _` -> same as `inout(reg_class) in_var => tmp`, +// where "tmp" is a temporary unused variable +// +// * `out/in/inout("explicit register") var` -> translated to one or two operands as described above +// with `"r"(var)` constraint, +// and one register variable assigned to the desired register. +// + +const ATT_SYNTAX_INS: &str = ".att_syntax noprefix\n\t"; +const INTEL_SYNTAX_INS: &str = "\n\t.intel_syntax noprefix"; + + +struct AsmOutOperand<'a, 'tcx, 'gcc> { + rust_idx: usize, + constraint: &'a str, + late: bool, + readwrite: bool, + + tmp_var: LValue<'gcc>, + out_place: Option>> +} + +struct AsmInOperand<'a, 'tcx> { + rust_idx: usize, + constraint: Cow<'a, str>, + val: RValue<'tcx> +} + +impl AsmOutOperand<'_, '_, '_> { + fn to_constraint(&self) -> String { + let mut res = String::with_capacity(self.constraint.len() + self.late as usize + 1); + + let sign = if self.readwrite { '+' } else { '=' }; + res.push(sign); + if !self.late { + res.push('&'); + } + + res.push_str(&self.constraint); + res + } +} + +enum ConstraintOrRegister { + Constraint(&'static str), + Register(&'static str) +} + + +impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { + fn codegen_llvm_inline_asm(&mut self, _ia: &LlvmInlineAsmInner, _outputs: Vec>>, _inputs: Vec>, span: Span) -> bool { + self.sess().struct_span_err(span, "GCC backend does not support `llvm_asm!`") + .help("consider using the `asm!` macro instead") + .emit(); + + // We return `true` even if we've failed to generate the asm + // because we want to suppress the "malformed inline assembly" error + // generated by the frontend. + true + } + + fn codegen_inline_asm(&mut self, template: &[InlineAsmTemplatePiece], rust_operands: &[InlineAsmOperandRef<'tcx, Self>], options: InlineAsmOptions, _span: &[Span]) { + let asm_arch = self.tcx.sess.asm_arch.unwrap(); + let is_x86 = matches!(asm_arch, InlineAsmArch::X86 | InlineAsmArch::X86_64); + let att_dialect = is_x86 && options.contains(InlineAsmOptions::ATT_SYNTAX); + let intel_dialect = is_x86 && !options.contains(InlineAsmOptions::ATT_SYNTAX); + + // GCC index of an output operand equals its position in the array + let mut outputs = vec![]; + + // GCC index of an input operand equals its position in the array + // added to `outputs.len()` + let mut inputs = vec![]; + + // Clobbers collected from `out("explicit register") _` and `inout("expl_reg") var => _` + let mut clobbers = vec![]; + + // We're trying to preallocate space for the template + let mut constants_len = 0; + + // There are rules we must adhere to if we want GCC to do the right thing: + // + // * Every local variable that the asm block uses as an output must be declared *before* + // the asm block. + // * There must be no instructions whatsoever between the register variables and the asm. + // + // Therefore, the backend must generate the instructions strictly in this order: + // + // 1. Output variables. + // 2. Register variables. + // 3. The asm block. + // + // We also must make sure that no input operands are emitted before output operands. + // + // This is why we work in passes, first emitting local vars, then local register vars. + // Also, we don't emit any asm operands immediately; we save them to + // the one of the buffers to be emitted later. + + // 1. Normal variables (and saving operands to buffers). + for (rust_idx, op) in rust_operands.iter().enumerate() { + match *op { + InlineAsmOperandRef::Out { reg, late, place } => { + use ConstraintOrRegister::*; + + let (constraint, ty) = match (reg_to_gcc(reg), place) { + (Constraint(constraint), Some(place)) => (constraint, place.layout.gcc_type(self.cx, false)), + // When `reg` is a class and not an explicit register but the out place is not specified, + // we need to create an unused output variable to assign the output to. This var + // needs to be of a type that's "compatible" with the register class, but specific type + // doesn't matter. + (Constraint(constraint), None) => (constraint, dummy_output_type(self.cx, reg.reg_class())), + (Register(_), Some(_)) => { + // left for the next pass + continue + }, + (Register(reg_name), None) => { + // `clobber_abi` can add lots of clobbers that are not supported by the target, + // such as AVX-512 registers, so we just ignore unsupported registers + let is_target_supported = reg.reg_class().supported_types(asm_arch).iter() + .any(|&(_, feature)| { + if let Some(feature) = feature { + self.tcx.sess.target_features.contains(&Symbol::intern(feature)) + } else { + true // Register class is unconditionally supported + } + }); + + if is_target_supported && !clobbers.contains(®_name) { + clobbers.push(reg_name); + } + continue + } + }; + + let tmp_var = self.current_func().new_local(None, ty, "output_register"); + outputs.push(AsmOutOperand { + constraint, + rust_idx, + late, + readwrite: false, + tmp_var, + out_place: place + }); + } + + InlineAsmOperandRef::In { reg, value } => { + if let ConstraintOrRegister::Constraint(constraint) = reg_to_gcc(reg) { + inputs.push(AsmInOperand { + constraint: Cow::Borrowed(constraint), + rust_idx, + val: value.immediate() + }); + } + else { + // left for the next pass + continue + } + } + + InlineAsmOperandRef::InOut { reg, late, in_value, out_place } => { + let constraint = if let ConstraintOrRegister::Constraint(constraint) = reg_to_gcc(reg) { + constraint + } + else { + // left for the next pass + continue + }; + + // Rustc frontend guarantees that input and output types are "compatible", + // so we can just use input var's type for the output variable. + // + // This decision is also backed by the fact that LLVM needs in and out + // values to be of *exactly the same type*, not just "compatible". + // I'm not sure if GCC is so picky too, but better safe than sorry. + let ty = in_value.layout.gcc_type(self.cx, false); + let tmp_var = self.current_func().new_local(None, ty, "output_register"); + + // If the out_place is None (i.e `inout(reg) _` syntax was used), we translate + // it to one "readwrite (+) output variable", otherwise we translate it to two + // "out and tied in" vars as described above. + let readwrite = out_place.is_none(); + outputs.push(AsmOutOperand { + constraint, + rust_idx, + late, + readwrite, + tmp_var, + out_place, + }); + + if !readwrite { + let out_gcc_idx = outputs.len() - 1; + let constraint = Cow::Owned(out_gcc_idx.to_string()); + + inputs.push(AsmInOperand { + constraint, + rust_idx, + val: in_value.immediate() + }); + } + } + + InlineAsmOperandRef::Const { ref string } => { + constants_len += string.len() + att_dialect as usize; + } + + InlineAsmOperandRef::SymFn { instance } => { + constants_len += self.tcx.symbol_name(instance).name.len(); + } + InlineAsmOperandRef::SymStatic { def_id } => { + constants_len += self.tcx.symbol_name(Instance::mono(self.tcx, def_id)).name.len(); + } + } + } + + // 2. Register variables. + for (rust_idx, op) in rust_operands.iter().enumerate() { + match *op { + // `out("explicit register") var` + InlineAsmOperandRef::Out { reg, late, place } => { + if let ConstraintOrRegister::Register(reg_name) = reg_to_gcc(reg) { + let out_place = if let Some(place) = place { + place + } + else { + // processed in the previous pass + continue + }; + + let ty = out_place.layout.gcc_type(self.cx, false); + let tmp_var = self.current_func().new_local(None, ty, "output_register"); + tmp_var.set_register_name(reg_name); + + outputs.push(AsmOutOperand { + constraint: "r".into(), + rust_idx, + late, + readwrite: false, + tmp_var, + out_place: Some(out_place) + }); + } + + // processed in the previous pass + } + + // `in("explicit register") var` + InlineAsmOperandRef::In { reg, value } => { + if let ConstraintOrRegister::Register(reg_name) = reg_to_gcc(reg) { + let ty = value.layout.gcc_type(self.cx, false); + let reg_var = self.current_func().new_local(None, ty, "input_register"); + reg_var.set_register_name(reg_name); + self.llbb().add_assignment(None, reg_var, value.immediate()); + + inputs.push(AsmInOperand { + constraint: "r".into(), + rust_idx, + val: reg_var.to_rvalue() + }); + } + + // processed in the previous pass + } + + // `inout("explicit register") in_var => out_var` + InlineAsmOperandRef::InOut { reg, late, in_value, out_place } => { + if let ConstraintOrRegister::Register(reg_name) = reg_to_gcc(reg) { + let out_place = if let Some(place) = out_place { + place + } + else { + // processed in the previous pass + continue + }; + + // See explanation in the first pass. + let ty = in_value.layout.gcc_type(self.cx, false); + let tmp_var = self.current_func().new_local(None, ty, "output_register"); + tmp_var.set_register_name(reg_name); + + outputs.push(AsmOutOperand { + constraint: "r".into(), + rust_idx, + late, + readwrite: false, + tmp_var, + out_place: Some(out_place) + }); + + let constraint = Cow::Owned((outputs.len() - 1).to_string()); + inputs.push(AsmInOperand { + constraint, + rust_idx, + val: in_value.immediate() + }); + } + + // processed in the previous pass + } + + InlineAsmOperandRef::Const { .. } + | InlineAsmOperandRef::SymFn { .. } + | InlineAsmOperandRef::SymStatic { .. } => { + // processed in the previous pass + } + } + } + + // 3. Build the template string + + let mut template_str = String::with_capacity(estimate_template_length(template, constants_len, att_dialect)); + if !intel_dialect { + template_str.push_str(ATT_SYNTAX_INS); + } + + for piece in template { + match *piece { + InlineAsmTemplatePiece::String(ref string) => { + // TODO(@Commeownist): switch to `Iterator::intersperse` once it's stable + let mut iter = string.split('%'); + if let Some(s) = iter.next() { + template_str.push_str(s); + } + + for s in iter { + template_str.push_str("%%"); + template_str.push_str(s); + } + } + InlineAsmTemplatePiece::Placeholder { operand_idx, modifier, span: _ } => { + let mut push_to_template = |modifier, gcc_idx| { + use std::fmt::Write; + + template_str.push('%'); + if let Some(modifier) = modifier { + template_str.push(modifier); + } + write!(template_str, "{}", gcc_idx).expect("pushing to string failed"); + }; + + match rust_operands[operand_idx] { + InlineAsmOperandRef::Out { reg, .. } => { + let modifier = modifier_to_gcc(asm_arch, reg.reg_class(), modifier); + let gcc_index = outputs.iter() + .position(|op| operand_idx == op.rust_idx) + .expect("wrong rust index"); + push_to_template(modifier, gcc_index); + } + + InlineAsmOperandRef::In { reg, .. } => { + let modifier = modifier_to_gcc(asm_arch, reg.reg_class(), modifier); + let in_gcc_index = inputs.iter() + .position(|op| operand_idx == op.rust_idx) + .expect("wrong rust index"); + let gcc_index = in_gcc_index + outputs.len(); + push_to_template(modifier, gcc_index); + } + + InlineAsmOperandRef::InOut { reg, .. } => { + let modifier = modifier_to_gcc(asm_arch, reg.reg_class(), modifier); + + // The input register is tied to the output, so we can just use the index of the output register + let gcc_index = outputs.iter() + .position(|op| operand_idx == op.rust_idx) + .expect("wrong rust index"); + push_to_template(modifier, gcc_index); + } + + InlineAsmOperandRef::SymFn { instance } => { + let name = self.tcx.symbol_name(instance).name; + template_str.push_str(name); + } + + InlineAsmOperandRef::SymStatic { def_id } => { + // TODO(@Commeownist): This may not be sufficient for all kinds of statics. + // Some statics may need the `@plt` suffix, like thread-local vars. + let instance = Instance::mono(self.tcx, def_id); + let name = self.tcx.symbol_name(instance).name; + template_str.push_str(name); + } + + InlineAsmOperandRef::Const { ref string } => { + // Const operands get injected directly into the template + if att_dialect { + template_str.push('$'); + } + template_str.push_str(string); + } + } + } + } + } + + if !intel_dialect { + template_str.push_str(INTEL_SYNTAX_INS); + } + + // 4. Generate Extended Asm block + + let block = self.llbb(); + let extended_asm = block.add_extended_asm(None, &template_str); + + for op in &outputs { + extended_asm.add_output_operand(None, &op.to_constraint(), op.tmp_var); + } + + for op in &inputs { + extended_asm.add_input_operand(None, &op.constraint, op.val); + } + + for clobber in clobbers.iter() { + extended_asm.add_clobber(clobber); + } + + if !options.contains(InlineAsmOptions::PRESERVES_FLAGS) { + // TODO(@Commeownist): I'm not 100% sure this one clobber is sufficient + // on all architectures. For instance, what about FP stack? + extended_asm.add_clobber("cc"); + } + if !options.contains(InlineAsmOptions::NOMEM) { + extended_asm.add_clobber("memory"); + } + if !options.contains(InlineAsmOptions::PURE) { + extended_asm.set_volatile_flag(true); + } + if !options.contains(InlineAsmOptions::NOSTACK) { + // TODO(@Commeownist): figure out how to align stack + } + if options.contains(InlineAsmOptions::NORETURN) { + let builtin_unreachable = self.context.get_builtin_function("__builtin_unreachable"); + let builtin_unreachable: RValue<'gcc> = unsafe { std::mem::transmute(builtin_unreachable) }; + self.call(self.type_void(), builtin_unreachable, &[], None); + } + + // Write results to outputs. + // + // We need to do this because: + // 1. Turning `PlaceRef` into `RValue` is error-prone and has nasty edge cases + // (especially with current `rustc_backend_ssa` API). + // 2. Not every output operand has an `out_place`, and it's required by `add_output_operand`. + // + // Instead, we generate a temporary output variable for each output operand, and then this loop, + // generates `out_place = tmp_var;` assignments if out_place exists. + for op in &outputs { + if let Some(place) = op.out_place { + OperandValue::Immediate(op.tmp_var.to_rvalue()).store(self, place); + } + } + + } +} + +fn estimate_template_length(template: &[InlineAsmTemplatePiece], constants_len: usize, att_dialect: bool) -> usize { + let len: usize = template.iter().map(|piece| { + match *piece { + InlineAsmTemplatePiece::String(ref string) => { + string.len() + } + InlineAsmTemplatePiece::Placeholder { .. } => { + // '%' + 1 char modifier + 1 char index + 3 + } + } + }) + .sum(); + + // increase it by 5% to account for possible '%' signs that'll be duplicated + // I pulled the number out of blue, but should be fair enough + // as the upper bound + let mut res = (len as f32 * 1.05) as usize + constants_len; + + if att_dialect { + res += INTEL_SYNTAX_INS.len() + ATT_SYNTAX_INS.len(); + } + res +} + +/// Converts a register class to a GCC constraint code. +fn reg_to_gcc(reg: InlineAsmRegOrRegClass) -> ConstraintOrRegister { + let constraint = match reg { + // For vector registers LLVM wants the register name to match the type size. + InlineAsmRegOrRegClass::Reg(reg) => { + match reg { + InlineAsmReg::X86(_) => { + // TODO(antoyo): add support for vector register. + // + // // For explicit registers, we have to create a register variable: https://stackoverflow.com/a/31774784/389119 + return ConstraintOrRegister::Register(match reg.name() { + // Some of registers' names does not map 1-1 from rust to gcc + "st(0)" => "st", + + name => name, + }); + } + + _ => unimplemented!(), + } + }, + InlineAsmRegOrRegClass::RegClass(reg) => match reg { + InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::preg) => unimplemented!(), + InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::reg) => unimplemented!(), + InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg) => unimplemented!(), + InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg_low16) => unimplemented!(), + InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg) => unimplemented!(), + InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg_thumb) => unimplemented!(), + InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg) + | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg_low16) + | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg_low8) => unimplemented!(), + InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg_low16) + | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg_low8) + | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg_low4) => unimplemented!(), + InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg) + | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg) => unimplemented!(), + InlineAsmRegClass::Bpf(_) => unimplemented!(), + InlineAsmRegClass::Hexagon(HexagonInlineAsmRegClass::reg) => unimplemented!(), + InlineAsmRegClass::Mips(MipsInlineAsmRegClass::reg) => unimplemented!(), + InlineAsmRegClass::Mips(MipsInlineAsmRegClass::freg) => unimplemented!(), + InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg16) => unimplemented!(), + InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg32) => unimplemented!(), + InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg64) => unimplemented!(), + InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::reg) => unimplemented!(), + InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::reg_nonzero) => unimplemented!(), + InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::freg) => unimplemented!(), + InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::cr) + | InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::xer) => { + unreachable!("clobber-only") + }, + InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::reg) => unimplemented!(), + InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::freg) => unimplemented!(), + InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::vreg) => unimplemented!(), + InlineAsmRegClass::X86(X86InlineAsmRegClass::reg) => "r", + InlineAsmRegClass::X86(X86InlineAsmRegClass::reg_abcd) => "Q", + InlineAsmRegClass::X86(X86InlineAsmRegClass::reg_byte) => "q", + InlineAsmRegClass::X86(X86InlineAsmRegClass::xmm_reg) + | InlineAsmRegClass::X86(X86InlineAsmRegClass::ymm_reg) => "x", + InlineAsmRegClass::X86(X86InlineAsmRegClass::zmm_reg) => "v", + InlineAsmRegClass::X86(X86InlineAsmRegClass::kreg) => unimplemented!(), + InlineAsmRegClass::Wasm(WasmInlineAsmRegClass::local) => unimplemented!(), + InlineAsmRegClass::X86( + X86InlineAsmRegClass::x87_reg | X86InlineAsmRegClass::mmx_reg, + ) => unreachable!("clobber-only"), + InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => { + bug!("GCC backend does not support SPIR-V") + } + InlineAsmRegClass::S390x(S390xInlineAsmRegClass::reg) => unimplemented!(), + InlineAsmRegClass::S390x(S390xInlineAsmRegClass::freg) => unimplemented!(), + InlineAsmRegClass::Err => unreachable!(), + } + }; + + ConstraintOrRegister::Constraint(constraint) +} + +/// Type to use for outputs that are discarded. It doesn't really matter what +/// the type is, as long as it is valid for the constraint code. +fn dummy_output_type<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, reg: InlineAsmRegClass) -> Type<'gcc> { + match reg { + InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::reg) => cx.type_i32(), + InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::preg) => unimplemented!(), + InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg) + | InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg_low16) => { + unimplemented!() + } + InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg) + | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg_thumb) => cx.type_i32(), + InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg) + | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg_low16) => cx.type_f32(), + InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg) + | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg_low16) + | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg_low8) => cx.type_f64(), + InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg) + | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg_low8) + | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg_low4) => { + unimplemented!() + } + InlineAsmRegClass::Bpf(_) => unimplemented!(), + InlineAsmRegClass::Hexagon(HexagonInlineAsmRegClass::reg) => cx.type_i32(), + InlineAsmRegClass::Mips(MipsInlineAsmRegClass::reg) => cx.type_i32(), + InlineAsmRegClass::Mips(MipsInlineAsmRegClass::freg) => cx.type_f32(), + InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg16) => cx.type_i16(), + InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg32) => cx.type_i32(), + InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg64) => cx.type_i64(), + InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::reg) => cx.type_i32(), + InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::reg_nonzero) => cx.type_i32(), + InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::freg) => cx.type_f64(), + InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::cr) + | InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::xer) => { + unreachable!("clobber-only") + }, + InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::reg) => cx.type_i32(), + InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::freg) => cx.type_f32(), + InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::vreg) => cx.type_f32(), + InlineAsmRegClass::X86(X86InlineAsmRegClass::reg) + | InlineAsmRegClass::X86(X86InlineAsmRegClass::reg_abcd) => cx.type_i32(), + InlineAsmRegClass::X86(X86InlineAsmRegClass::reg_byte) => cx.type_i8(), + InlineAsmRegClass::X86(X86InlineAsmRegClass::mmx_reg) => unimplemented!(), + InlineAsmRegClass::X86(X86InlineAsmRegClass::xmm_reg) + | InlineAsmRegClass::X86(X86InlineAsmRegClass::ymm_reg) + | InlineAsmRegClass::X86(X86InlineAsmRegClass::zmm_reg) => cx.type_f32(), + InlineAsmRegClass::X86(X86InlineAsmRegClass::x87_reg) => unimplemented!(), + InlineAsmRegClass::X86(X86InlineAsmRegClass::kreg) => cx.type_i16(), + InlineAsmRegClass::Wasm(WasmInlineAsmRegClass::local) => cx.type_i32(), + InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => { + bug!("LLVM backend does not support SPIR-V") + }, + InlineAsmRegClass::S390x(S390xInlineAsmRegClass::reg) => cx.type_i32(), + InlineAsmRegClass::S390x(S390xInlineAsmRegClass::freg) => cx.type_f64(), + InlineAsmRegClass::Err => unreachable!(), + } +} + +impl<'gcc, 'tcx> AsmMethods for CodegenCx<'gcc, 'tcx> { + fn codegen_global_asm(&self, template: &[InlineAsmTemplatePiece], operands: &[GlobalAsmOperandRef], options: InlineAsmOptions, _line_spans: &[Span]) { + let asm_arch = self.tcx.sess.asm_arch.unwrap(); + + // Default to Intel syntax on x86 + let intel_syntax = matches!(asm_arch, InlineAsmArch::X86 | InlineAsmArch::X86_64) + && !options.contains(InlineAsmOptions::ATT_SYNTAX); + + // Build the template string + let mut template_str = String::new(); + for piece in template { + match *piece { + InlineAsmTemplatePiece::String(ref string) => { + for line in string.lines() { + // NOTE: gcc does not allow inline comment, so remove them. + let line = + if let Some(index) = line.rfind("//") { + &line[..index] + } + else { + line + }; + template_str.push_str(line); + template_str.push('\n'); + } + }, + InlineAsmTemplatePiece::Placeholder { operand_idx, modifier: _, span: _ } => { + match operands[operand_idx] { + GlobalAsmOperandRef::Const { ref string } => { + // Const operands get injected directly into the + // template. Note that we don't need to escape % + // here unlike normal inline assembly. + template_str.push_str(string); + } + } + } + } + } + + let template_str = + if intel_syntax { + format!("{}\n\t.intel_syntax noprefix", template_str) + } + else { + format!(".att_syntax\n\t{}\n\t.intel_syntax noprefix", template_str) + }; + // NOTE: seems like gcc will put the asm in the wrong section, so set it to .text manually. + let template_str = format!(".pushsection .text\n{}\n.popsection", template_str); + self.context.add_top_level_asm(None, &template_str); + } +} + +fn modifier_to_gcc(arch: InlineAsmArch, reg: InlineAsmRegClass, modifier: Option) -> Option { + match reg { + InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::reg) => modifier, + InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::preg) => modifier, + InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg) + | InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg_low16) => { + unimplemented!() + } + InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg) + | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg_thumb) => unimplemented!(), + InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg) + | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg_low16) => unimplemented!(), + InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg) + | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg_low16) + | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg_low8) => unimplemented!(), + InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg) + | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg_low8) + | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg_low4) => { + unimplemented!() + } + InlineAsmRegClass::Bpf(_) => unimplemented!(), + InlineAsmRegClass::Hexagon(_) => unimplemented!(), + InlineAsmRegClass::Mips(_) => unimplemented!(), + InlineAsmRegClass::Nvptx(_) => unimplemented!(), + InlineAsmRegClass::PowerPC(_) => unimplemented!(), + InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::reg) + | InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::freg) => unimplemented!(), + InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::vreg) => unimplemented!(), + InlineAsmRegClass::X86(X86InlineAsmRegClass::reg) + | InlineAsmRegClass::X86(X86InlineAsmRegClass::reg_abcd) => match modifier { + None => if arch == InlineAsmArch::X86_64 { Some('q') } else { Some('k') }, + Some('l') => Some('b'), + Some('h') => Some('h'), + Some('x') => Some('w'), + Some('e') => Some('k'), + Some('r') => Some('q'), + _ => unreachable!(), + }, + InlineAsmRegClass::X86(X86InlineAsmRegClass::reg_byte) => None, + InlineAsmRegClass::X86(reg @ X86InlineAsmRegClass::xmm_reg) + | InlineAsmRegClass::X86(reg @ X86InlineAsmRegClass::ymm_reg) + | InlineAsmRegClass::X86(reg @ X86InlineAsmRegClass::zmm_reg) => match (reg, modifier) { + (X86InlineAsmRegClass::xmm_reg, None) => Some('x'), + (X86InlineAsmRegClass::ymm_reg, None) => Some('t'), + (X86InlineAsmRegClass::zmm_reg, None) => Some('g'), + (_, Some('x')) => Some('x'), + (_, Some('y')) => Some('t'), + (_, Some('z')) => Some('g'), + _ => unreachable!(), + }, + InlineAsmRegClass::X86(X86InlineAsmRegClass::kreg) => None, + InlineAsmRegClass::X86(X86InlineAsmRegClass::x87_reg | X86InlineAsmRegClass::mmx_reg) => { + unreachable!("clobber-only") + } + InlineAsmRegClass::Wasm(WasmInlineAsmRegClass::local) => unimplemented!(), + InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => { + bug!("LLVM backend does not support SPIR-V") + }, + InlineAsmRegClass::S390x(S390xInlineAsmRegClass::reg) => unimplemented!(), + InlineAsmRegClass::S390x(S390xInlineAsmRegClass::freg) => unimplemented!(), + InlineAsmRegClass::Err => unreachable!(), + } +} diff --git a/compiler/rustc_codegen_gcc/src/back/mod.rs b/compiler/rustc_codegen_gcc/src/back/mod.rs new file mode 100644 index 0000000000..d692799d76 --- /dev/null +++ b/compiler/rustc_codegen_gcc/src/back/mod.rs @@ -0,0 +1 @@ +pub mod write; diff --git a/compiler/rustc_codegen_gcc/src/back/write.rs b/compiler/rustc_codegen_gcc/src/back/write.rs new file mode 100644 index 0000000000..c3e3847823 --- /dev/null +++ b/compiler/rustc_codegen_gcc/src/back/write.rs @@ -0,0 +1,78 @@ +use std::fs; + +use gccjit::OutputKind; +use rustc_codegen_ssa::{CompiledModule, ModuleCodegen}; +use rustc_codegen_ssa::back::write::{CodegenContext, EmitObj, ModuleConfig}; +use rustc_errors::Handler; +use rustc_session::config::OutputType; +use rustc_span::fatal_error::FatalError; +use rustc_target::spec::SplitDebuginfo; + +use crate::{GccCodegenBackend, GccContext}; + +pub(crate) unsafe fn codegen(cgcx: &CodegenContext, _diag_handler: &Handler, module: ModuleCodegen, config: &ModuleConfig) -> Result { + let _timer = cgcx.prof.generic_activity_with_arg("LLVM_module_codegen", &module.name[..]); + { + let context = &module.module_llvm.context; + + let module_name = module.name.clone(); + let module_name = Some(&module_name[..]); + + let _bc_out = cgcx.output_filenames.temp_path(OutputType::Bitcode, module_name); + let obj_out = cgcx.output_filenames.temp_path(OutputType::Object, module_name); + + if config.bitcode_needed() { + // TODO(antoyo) + } + + if config.emit_ir { + unimplemented!(); + } + + if config.emit_asm { + let _timer = cgcx + .prof + .generic_activity_with_arg("LLVM_module_codegen_emit_asm", &module.name[..]); + let path = cgcx.output_filenames.temp_path(OutputType::Assembly, module_name); + context.compile_to_file(OutputKind::Assembler, path.to_str().expect("path to str")); + } + + match config.emit_obj { + EmitObj::ObjectCode(_) => { + let _timer = cgcx + .prof + .generic_activity_with_arg("LLVM_module_codegen_emit_obj", &module.name[..]); + match &*module.name { + "std_example.7rcbfp3g-cgu.15" => { + println!("Dumping reproducer {}", module.name); + let _ = fs::create_dir("/tmp/reproducers"); + // FIXME(antoyo): segfault in dump_reproducer_to_file() might be caused by + // transmuting an rvalue to an lvalue. + // Segfault is actually in gcc::jit::reproducer::get_identifier_as_lvalue + context.dump_reproducer_to_file(&format!("/tmp/reproducers/{}.c", module.name)); + println!("Dumped reproducer {}", module.name); + }, + _ => (), + } + context.compile_to_file(OutputKind::ObjectFile, obj_out.to_str().expect("path to str")); + } + + EmitObj::Bitcode => { + // TODO(antoyo) + } + + EmitObj::None => {} + } + } + + Ok(module.into_compiled_module( + config.emit_obj != EmitObj::None, + cgcx.target_can_use_split_dwarf && cgcx.split_debuginfo == SplitDebuginfo::Unpacked, + config.emit_bc, + &cgcx.output_filenames, + )) +} + +pub(crate) fn link(_cgcx: &CodegenContext, _diag_handler: &Handler, mut _modules: Vec>) -> Result, FatalError> { + unimplemented!(); +} diff --git a/compiler/rustc_codegen_gcc/src/base.rs b/compiler/rustc_codegen_gcc/src/base.rs new file mode 100644 index 0000000000..9f96096574 --- /dev/null +++ b/compiler/rustc_codegen_gcc/src/base.rs @@ -0,0 +1,165 @@ +use std::env; +use std::time::Instant; + +use gccjit::{ + Context, + FunctionType, + GlobalKind, +}; +use rustc_middle::dep_graph; +use rustc_middle::middle::exported_symbols; +use rustc_middle::ty::TyCtxt; +use rustc_middle::mir::mono::Linkage; +use rustc_codegen_ssa::{ModuleCodegen, ModuleKind}; +use rustc_codegen_ssa::base::maybe_create_entry_wrapper; +use rustc_codegen_ssa::mono_item::MonoItemExt; +use rustc_codegen_ssa::traits::DebugInfoMethods; +use rustc_metadata::EncodedMetadata; +use rustc_session::config::DebugInfo; +use rustc_span::Symbol; + +use crate::GccContext; +use crate::builder::Builder; +use crate::context::CodegenCx; + +pub fn global_linkage_to_gcc(linkage: Linkage) -> GlobalKind { + match linkage { + Linkage::External => GlobalKind::Imported, + Linkage::AvailableExternally => GlobalKind::Imported, + Linkage::LinkOnceAny => unimplemented!(), + Linkage::LinkOnceODR => unimplemented!(), + Linkage::WeakAny => unimplemented!(), + Linkage::WeakODR => unimplemented!(), + Linkage::Appending => unimplemented!(), + Linkage::Internal => GlobalKind::Internal, + Linkage::Private => GlobalKind::Internal, + Linkage::ExternalWeak => GlobalKind::Imported, // TODO(antoyo): should be weak linkage. + Linkage::Common => unimplemented!(), + } +} + +pub fn linkage_to_gcc(linkage: Linkage) -> FunctionType { + match linkage { + Linkage::External => FunctionType::Exported, + Linkage::AvailableExternally => FunctionType::Extern, + Linkage::LinkOnceAny => unimplemented!(), + Linkage::LinkOnceODR => unimplemented!(), + Linkage::WeakAny => FunctionType::Exported, // FIXME(antoyo): should be similar to linkonce. + Linkage::WeakODR => unimplemented!(), + Linkage::Appending => unimplemented!(), + Linkage::Internal => FunctionType::Internal, + Linkage::Private => FunctionType::Internal, + Linkage::ExternalWeak => unimplemented!(), + Linkage::Common => unimplemented!(), + } +} + +pub fn compile_codegen_unit<'tcx>(tcx: TyCtxt<'tcx>, cgu_name: Symbol) -> (ModuleCodegen, u64) { + let prof_timer = tcx.prof.generic_activity("codegen_module"); + let start_time = Instant::now(); + + let dep_node = tcx.codegen_unit(cgu_name).codegen_dep_node(tcx); + let (module, _) = tcx.dep_graph.with_task(dep_node, tcx, cgu_name, module_codegen, dep_graph::hash_result); + let time_to_codegen = start_time.elapsed(); + drop(prof_timer); + + // We assume that the cost to run GCC on a CGU is proportional to + // the time we needed for codegenning it. + let cost = time_to_codegen.as_secs() * 1_000_000_000 + time_to_codegen.subsec_nanos() as u64; + + fn module_codegen(tcx: TyCtxt<'_>, cgu_name: Symbol) -> ModuleCodegen { + let cgu = tcx.codegen_unit(cgu_name); + // Instantiate monomorphizations without filling out definitions yet... + //let llvm_module = ModuleLlvm::new(tcx, &cgu_name.as_str()); + let context = Context::default(); + // TODO(antoyo): only set on x86 platforms. + context.add_command_line_option("-masm=intel"); + for arg in &tcx.sess.opts.cg.llvm_args { + context.add_command_line_option(arg); + } + context.add_command_line_option("-fno-semantic-interposition"); + if env::var("CG_GCCJIT_DUMP_CODE").as_deref() == Ok("1") { + context.set_dump_code_on_compile(true); + } + if env::var("CG_GCCJIT_DUMP_GIMPLE").as_deref() == Ok("1") { + context.set_dump_initial_gimple(true); + } + context.set_debug_info(true); + if env::var("CG_GCCJIT_DUMP_EVERYTHING").as_deref() == Ok("1") { + context.set_dump_everything(true); + } + if env::var("CG_GCCJIT_KEEP_INTERMEDIATES").as_deref() == Ok("1") { + context.set_keep_intermediates(true); + } + + { + let cx = CodegenCx::new(&context, cgu, tcx); + + let mono_items = cgu.items_in_deterministic_order(tcx); + for &(mono_item, (linkage, visibility)) in &mono_items { + mono_item.predefine::>(&cx, linkage, visibility); + } + + // ... and now that we have everything pre-defined, fill out those definitions. + for &(mono_item, _) in &mono_items { + mono_item.define::>(&cx); + } + + // If this codegen unit contains the main function, also create the + // wrapper here + maybe_create_entry_wrapper::>(&cx); + + // Finalize debuginfo + if cx.sess().opts.debuginfo != DebugInfo::None { + cx.debuginfo_finalize(); + } + } + + ModuleCodegen { + name: cgu_name.to_string(), + module_llvm: GccContext { + context + }, + kind: ModuleKind::Regular, + } + } + + (module, cost) +} + +pub fn write_compressed_metadata<'tcx>(tcx: TyCtxt<'tcx>, metadata: &EncodedMetadata, gcc_module: &mut GccContext) { + use snap::write::FrameEncoder; + use std::io::Write; + + // Historical note: + // + // When using link.exe it was seen that the section name `.note.rustc` + // was getting shortened to `.note.ru`, and according to the PE and COFF + // specification: + // + // > Executable images do not use a string table and do not support + // > section names longer than 8 characters + // + // https://docs.microsoft.com/en-us/windows/win32/debug/pe-format + // + // As a result, we choose a slightly shorter name! As to why + // `.note.rustc` works on MinGW, see + // https://github.com/llvm/llvm-project/blob/llvmorg-12.0.0/lld/COFF/Writer.cpp#L1190-L1197 + let section_name = if tcx.sess.target.is_like_osx { "__DATA,.rustc" } else { ".rustc" }; + + let context = &gcc_module.context; + let mut compressed = rustc_metadata::METADATA_HEADER.to_vec(); + FrameEncoder::new(&mut compressed).write_all(&metadata.raw_data()).unwrap(); + + let name = exported_symbols::metadata_symbol_name(tcx); + let typ = context.new_array_type(None, context.new_type::(), compressed.len() as i32); + let global = context.new_global(None, GlobalKind::Exported, typ, name); + global.global_set_initializer(&compressed); + global.set_link_section(section_name); + + // Also generate a .section directive to force no + // flags, at least for ELF outputs, so that the + // metadata doesn't get loaded into memory. + let directive = format!(".section {}", section_name); + context.add_top_level_asm(None, &directive); +} diff --git a/compiler/rustc_codegen_gcc/src/builder.rs b/compiler/rustc_codegen_gcc/src/builder.rs new file mode 100644 index 0000000000..ac908418ee --- /dev/null +++ b/compiler/rustc_codegen_gcc/src/builder.rs @@ -0,0 +1,1540 @@ +use std::borrow::Cow; +use std::cell::Cell; +use std::convert::TryFrom; +use std::ops::Deref; + +use gccjit::FunctionType; +use gccjit::{ + BinaryOp, + Block, + ComparisonOp, + Function, + LValue, + RValue, + ToRValue, + Type, + UnaryOp, +}; +use rustc_codegen_ssa::MemFlags; +use rustc_codegen_ssa::common::{AtomicOrdering, AtomicRmwBinOp, IntPredicate, RealPredicate, SynchronizationScope}; +use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue}; +use rustc_codegen_ssa::mir::place::PlaceRef; +use rustc_codegen_ssa::traits::{ + BackendTypes, + BaseTypeMethods, + BuilderMethods, + ConstMethods, + DerivedTypeMethods, + LayoutTypeMethods, + HasCodegen, + OverflowOp, + StaticBuilderMethods, +}; +use rustc_middle::ty::{ParamEnv, Ty, TyCtxt}; +use rustc_middle::ty::layout::{FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasParamEnv, HasTyCtxt, LayoutError, LayoutOfHelpers, TyAndLayout}; +use rustc_span::Span; +use rustc_span::def_id::DefId; +use rustc_target::abi::{ + self, + call::FnAbi, + Align, + HasDataLayout, + Size, + TargetDataLayout, + WrappingRange, +}; +use rustc_target::spec::{HasTargetSpec, Target}; + +use crate::common::{SignType, TypeReflection, type_is_pointer}; +use crate::context::CodegenCx; +use crate::type_of::LayoutGccExt; + +// TODO(antoyo) +type Funclet = (); + +// TODO(antoyo): remove this variable. +static mut RETURN_VALUE_COUNT: usize = 0; + +enum ExtremumOperation { + Max, + Min, +} + +trait EnumClone { + fn clone(&self) -> Self; +} + +impl EnumClone for AtomicOrdering { + fn clone(&self) -> Self { + match *self { + AtomicOrdering::NotAtomic => AtomicOrdering::NotAtomic, + AtomicOrdering::Unordered => AtomicOrdering::Unordered, + AtomicOrdering::Monotonic => AtomicOrdering::Monotonic, + AtomicOrdering::Acquire => AtomicOrdering::Acquire, + AtomicOrdering::Release => AtomicOrdering::Release, + AtomicOrdering::AcquireRelease => AtomicOrdering::AcquireRelease, + AtomicOrdering::SequentiallyConsistent => AtomicOrdering::SequentiallyConsistent, + } + } +} + +pub struct Builder<'a: 'gcc, 'gcc, 'tcx> { + pub cx: &'a CodegenCx<'gcc, 'tcx>, + pub block: Option>, + stack_var_count: Cell, +} + +impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { + fn with_cx(cx: &'a CodegenCx<'gcc, 'tcx>) -> Self { + Builder { + cx, + block: None, + stack_var_count: Cell::new(0), + } + } + + fn atomic_extremum(&mut self, operation: ExtremumOperation, dst: RValue<'gcc>, src: RValue<'gcc>, order: AtomicOrdering) -> RValue<'gcc> { + let size = self.cx.int_width(src.get_type()) / 8; + + let func = self.current_func(); + + let load_ordering = + match order { + // TODO(antoyo): does this make sense? + AtomicOrdering::AcquireRelease | AtomicOrdering::Release => AtomicOrdering::Acquire, + _ => order.clone(), + }; + let previous_value = self.atomic_load(dst.get_type(), dst, load_ordering.clone(), Size::from_bytes(size)); + let previous_var = func.new_local(None, previous_value.get_type(), "previous_value"); + let return_value = func.new_local(None, previous_value.get_type(), "return_value"); + self.llbb().add_assignment(None, previous_var, previous_value); + self.llbb().add_assignment(None, return_value, previous_var.to_rvalue()); + + let while_block = func.new_block("while"); + let after_block = func.new_block("after_while"); + self.llbb().end_with_jump(None, while_block); + + // NOTE: since jumps were added and compare_exchange doesn't expect this, the current blocks in the + // state need to be updated. + self.block = Some(while_block); + *self.cx.current_block.borrow_mut() = Some(while_block); + + let comparison_operator = + match operation { + ExtremumOperation::Max => ComparisonOp::LessThan, + ExtremumOperation::Min => ComparisonOp::GreaterThan, + }; + + let cond1 = self.context.new_comparison(None, comparison_operator, previous_var.to_rvalue(), self.context.new_cast(None, src, previous_value.get_type())); + let compare_exchange = self.compare_exchange(dst, previous_var, src, order, load_ordering, false); + let cond2 = self.cx.context.new_unary_op(None, UnaryOp::LogicalNegate, compare_exchange.get_type(), compare_exchange); + let cond = self.cx.context.new_binary_op(None, BinaryOp::LogicalAnd, self.cx.bool_type, cond1, cond2); + + while_block.end_with_conditional(None, cond, while_block, after_block); + + // NOTE: since jumps were added in a place rustc does not expect, the current blocks in the + // state need to be updated. + self.block = Some(after_block); + *self.cx.current_block.borrow_mut() = Some(after_block); + + return_value.to_rvalue() + } + + fn compare_exchange(&self, dst: RValue<'gcc>, cmp: LValue<'gcc>, src: RValue<'gcc>, order: AtomicOrdering, failure_order: AtomicOrdering, weak: bool) -> RValue<'gcc> { + let size = self.cx.int_width(src.get_type()); + let compare_exchange = self.context.get_builtin_function(&format!("__atomic_compare_exchange_{}", size / 8)); + let order = self.context.new_rvalue_from_int(self.i32_type, order.to_gcc()); + let failure_order = self.context.new_rvalue_from_int(self.i32_type, failure_order.to_gcc()); + let weak = self.context.new_rvalue_from_int(self.bool_type, weak as i32); + + let void_ptr_type = self.context.new_type::<*mut ()>(); + let volatile_void_ptr_type = void_ptr_type.make_volatile(); + let dst = self.context.new_cast(None, dst, volatile_void_ptr_type); + let expected = self.context.new_cast(None, cmp.get_address(None), void_ptr_type); + + // NOTE: not sure why, but we have the wrong type here. + let int_type = compare_exchange.get_param(2).to_rvalue().get_type(); + let src = self.context.new_cast(None, src, int_type); + self.context.new_call(None, compare_exchange, &[dst, expected, src, weak, order, failure_order]) + } + + pub fn assign(&self, lvalue: LValue<'gcc>, value: RValue<'gcc>) { + self.llbb().add_assignment(None, lvalue, value); + } + + fn check_call<'b>(&mut self, _typ: &str, func: Function<'gcc>, args: &'b [RValue<'gcc>]) -> Cow<'b, [RValue<'gcc>]> { + let mut all_args_match = true; + let mut param_types = vec![]; + let param_count = func.get_param_count(); + for (index, arg) in args.iter().enumerate().take(param_count) { + let param = func.get_param(index as i32); + let param = param.to_rvalue().get_type(); + if param != arg.get_type() { + all_args_match = false; + } + param_types.push(param); + } + + if all_args_match { + return Cow::Borrowed(args); + } + + let casted_args: Vec<_> = param_types + .into_iter() + .zip(args.iter()) + .enumerate() + .map(|(_i, (expected_ty, &actual_val))| { + let actual_ty = actual_val.get_type(); + if expected_ty != actual_ty { + self.bitcast(actual_val, expected_ty) + } + else { + actual_val + } + }) + .collect(); + + Cow::Owned(casted_args) + } + + fn check_ptr_call<'b>(&mut self, _typ: &str, func_ptr: RValue<'gcc>, args: &'b [RValue<'gcc>]) -> Cow<'b, [RValue<'gcc>]> { + let mut all_args_match = true; + let mut param_types = vec![]; + let gcc_func = func_ptr.get_type().is_function_ptr_type().expect("function ptr"); + for (index, arg) in args.iter().enumerate().take(gcc_func.get_param_count()) { + let param = gcc_func.get_param_type(index); + if param != arg.get_type() { + all_args_match = false; + } + param_types.push(param); + } + + if all_args_match { + return Cow::Borrowed(args); + } + + let casted_args: Vec<_> = param_types + .into_iter() + .zip(args.iter()) + .enumerate() + .map(|(_i, (expected_ty, &actual_val))| { + let actual_ty = actual_val.get_type(); + if expected_ty != actual_ty { + self.bitcast(actual_val, expected_ty) + } + else { + actual_val + } + }) + .collect(); + + Cow::Owned(casted_args) + } + + fn check_store(&mut self, val: RValue<'gcc>, ptr: RValue<'gcc>) -> RValue<'gcc> { + let dest_ptr_ty = self.cx.val_ty(ptr).make_pointer(); // TODO(antoyo): make sure make_pointer() is okay here. + let stored_ty = self.cx.val_ty(val); + let stored_ptr_ty = self.cx.type_ptr_to(stored_ty); + + if dest_ptr_ty == stored_ptr_ty { + ptr + } + else { + self.bitcast(ptr, stored_ptr_ty) + } + } + + pub fn current_func(&self) -> Function<'gcc> { + self.block.expect("block").get_function() + } + + fn function_call(&mut self, func: RValue<'gcc>, args: &[RValue<'gcc>], _funclet: Option<&Funclet>) -> RValue<'gcc> { + // TODO(antoyo): remove when the API supports a different type for functions. + let func: Function<'gcc> = self.cx.rvalue_as_function(func); + let args = self.check_call("call", func, args); + + // gccjit requires to use the result of functions, even when it's not used. + // That's why we assign the result to a local or call add_eval(). + let return_type = func.get_return_type(); + let current_block = self.current_block.borrow().expect("block"); + let void_type = self.context.new_type::<()>(); + let current_func = current_block.get_function(); + if return_type != void_type { + unsafe { RETURN_VALUE_COUNT += 1 }; + let result = current_func.new_local(None, return_type, &format!("returnValue{}", unsafe { RETURN_VALUE_COUNT })); + current_block.add_assignment(None, result, self.cx.context.new_call(None, func, &args)); + result.to_rvalue() + } + else { + current_block.add_eval(None, self.cx.context.new_call(None, func, &args)); + // Return dummy value when not having return value. + self.context.new_rvalue_from_long(self.isize_type, 0) + } + } + + fn function_ptr_call(&mut self, func_ptr: RValue<'gcc>, args: &[RValue<'gcc>], _funclet: Option<&Funclet>) -> RValue<'gcc> { + let args = self.check_ptr_call("call", func_ptr, args); + + // gccjit requires to use the result of functions, even when it's not used. + // That's why we assign the result to a local or call add_eval(). + let gcc_func = func_ptr.get_type().is_function_ptr_type().expect("function ptr"); + let mut return_type = gcc_func.get_return_type(); + let current_block = self.current_block.borrow().expect("block"); + let void_type = self.context.new_type::<()>(); + let current_func = current_block.get_function(); + + // FIXME(antoyo): As a temporary workaround for unsupported LLVM intrinsics. + if gcc_func.get_param_count() == 0 && format!("{:?}", func_ptr) == "__builtin_ia32_pmovmskb128" { + return_type = self.int_type; + } + + if return_type != void_type { + unsafe { RETURN_VALUE_COUNT += 1 }; + let result = current_func.new_local(None, return_type, &format!("returnValue{}", unsafe { RETURN_VALUE_COUNT })); + current_block.add_assignment(None, result, self.cx.context.new_call_through_ptr(None, func_ptr, &args)); + result.to_rvalue() + } + else { + if gcc_func.get_param_count() == 0 { + // FIXME(antoyo): As a temporary workaround for unsupported LLVM intrinsics. + current_block.add_eval(None, self.cx.context.new_call_through_ptr(None, func_ptr, &[])); + } + else { + current_block.add_eval(None, self.cx.context.new_call_through_ptr(None, func_ptr, &args)); + } + // Return dummy value when not having return value. + let result = current_func.new_local(None, self.isize_type, "dummyValueThatShouldNeverBeUsed"); + current_block.add_assignment(None, result, self.context.new_rvalue_from_long(self.isize_type, 0)); + result.to_rvalue() + } + } + + pub fn overflow_call(&mut self, func: Function<'gcc>, args: &[RValue<'gcc>], _funclet: Option<&Funclet>) -> RValue<'gcc> { + // gccjit requires to use the result of functions, even when it's not used. + // That's why we assign the result to a local. + let return_type = self.context.new_type::(); + let current_block = self.current_block.borrow().expect("block"); + let current_func = current_block.get_function(); + // TODO(antoyo): return the new_call() directly? Since the overflow function has no side-effects. + unsafe { RETURN_VALUE_COUNT += 1 }; + let result = current_func.new_local(None, return_type, &format!("returnValue{}", unsafe { RETURN_VALUE_COUNT })); + current_block.add_assignment(None, result, self.cx.context.new_call(None, func, &args)); + result.to_rvalue() + } +} + +impl<'gcc, 'tcx> HasCodegen<'tcx> for Builder<'_, 'gcc, 'tcx> { + type CodegenCx = CodegenCx<'gcc, 'tcx>; +} + +impl<'tcx> HasTyCtxt<'tcx> for Builder<'_, '_, 'tcx> { + fn tcx(&self) -> TyCtxt<'tcx> { + self.cx.tcx() + } +} + +impl HasDataLayout for Builder<'_, '_, '_> { + fn data_layout(&self) -> &TargetDataLayout { + self.cx.data_layout() + } +} + +impl<'tcx> LayoutOfHelpers<'tcx> for Builder<'_, '_, 'tcx> { + type LayoutOfResult = TyAndLayout<'tcx>; + + #[inline] + fn handle_layout_err(&self, err: LayoutError<'tcx>, span: Span, ty: Ty<'tcx>) -> ! { + self.cx.handle_layout_err(err, span, ty) + } +} + +impl<'tcx> FnAbiOfHelpers<'tcx> for Builder<'_, '_, 'tcx> { + type FnAbiOfResult = &'tcx FnAbi<'tcx, Ty<'tcx>>; + + #[inline] + fn handle_fn_abi_err( + &self, + err: FnAbiError<'tcx>, + span: Span, + fn_abi_request: FnAbiRequest<'tcx>, + ) -> ! { + self.cx.handle_fn_abi_err(err, span, fn_abi_request) + } +} + +impl<'gcc, 'tcx> Deref for Builder<'_, 'gcc, 'tcx> { + type Target = CodegenCx<'gcc, 'tcx>; + + fn deref(&self) -> &Self::Target { + self.cx + } +} + +impl<'gcc, 'tcx> BackendTypes for Builder<'_, 'gcc, 'tcx> { + type Value = as BackendTypes>::Value; + type Function = as BackendTypes>::Function; + type BasicBlock = as BackendTypes>::BasicBlock; + type Type = as BackendTypes>::Type; + type Funclet = as BackendTypes>::Funclet; + + type DIScope = as BackendTypes>::DIScope; + type DILocation = as BackendTypes>::DILocation; + type DIVariable = as BackendTypes>::DIVariable; +} + +impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { + fn build(cx: &'a CodegenCx<'gcc, 'tcx>, block: Block<'gcc>) -> Self { + let mut bx = Builder::with_cx(cx); + *cx.current_block.borrow_mut() = Some(block); + bx.block = Some(block); + bx + } + + fn build_sibling_block(&mut self, name: &str) -> Self { + let block = self.append_sibling_block(name); + Self::build(self.cx, block) + } + + fn llbb(&self) -> Block<'gcc> { + self.block.expect("block") + } + + fn append_block(cx: &'a CodegenCx<'gcc, 'tcx>, func: RValue<'gcc>, name: &str) -> Block<'gcc> { + let func = cx.rvalue_as_function(func); + func.new_block(name) + } + + fn append_sibling_block(&mut self, name: &str) -> Block<'gcc> { + let func = self.current_func(); + func.new_block(name) + } + + fn ret_void(&mut self) { + self.llbb().end_with_void_return(None) + } + + fn ret(&mut self, value: RValue<'gcc>) { + let value = + if self.structs_as_pointer.borrow().contains(&value) { + // NOTE: hack to workaround a limitation of the rustc API: see comment on + // CodegenCx.structs_as_pointer + value.dereference(None).to_rvalue() + } + else { + value + }; + self.llbb().end_with_return(None, value); + } + + fn br(&mut self, dest: Block<'gcc>) { + self.llbb().end_with_jump(None, dest) + } + + fn cond_br(&mut self, cond: RValue<'gcc>, then_block: Block<'gcc>, else_block: Block<'gcc>) { + self.llbb().end_with_conditional(None, cond, then_block, else_block) + } + + fn switch(&mut self, value: RValue<'gcc>, default_block: Block<'gcc>, cases: impl ExactSizeIterator)>) { + let mut gcc_cases = vec![]; + let typ = self.val_ty(value); + for (on_val, dest) in cases { + let on_val = self.const_uint_big(typ, on_val); + gcc_cases.push(self.context.new_case(on_val, on_val, dest)); + } + self.block.expect("block").end_with_switch(None, value, default_block, &gcc_cases); + } + + fn invoke(&mut self, _typ: Type<'gcc>, _func: RValue<'gcc>, _args: &[RValue<'gcc>], then: Block<'gcc>, catch: Block<'gcc>, _funclet: Option<&Funclet>) -> RValue<'gcc> { + let condition = self.context.new_rvalue_from_int(self.bool_type, 0); + self.llbb().end_with_conditional(None, condition, then, catch); + self.context.new_rvalue_from_int(self.int_type, 0) + + // TODO(antoyo) + } + + fn unreachable(&mut self) { + let func = self.context.get_builtin_function("__builtin_unreachable"); + let block = self.block.expect("block"); + block.add_eval(None, self.context.new_call(None, func, &[])); + let return_type = block.get_function().get_return_type(); + let void_type = self.context.new_type::<()>(); + if return_type == void_type { + block.end_with_void_return(None) + } + else { + let return_value = self.current_func() + .new_local(None, return_type, "unreachableReturn"); + block.end_with_return(None, return_value) + } + } + + fn add(&mut self, a: RValue<'gcc>, mut b: RValue<'gcc>) -> RValue<'gcc> { + // FIXME(antoyo): this should not be required. + if format!("{:?}", a.get_type()) != format!("{:?}", b.get_type()) { + b = self.context.new_cast(None, b, a.get_type()); + } + a + b + } + + fn fadd(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { + a + b + } + + fn sub(&mut self, a: RValue<'gcc>, mut b: RValue<'gcc>) -> RValue<'gcc> { + if a.get_type() != b.get_type() { + b = self.context.new_cast(None, b, a.get_type()); + } + a - b + } + + fn fsub(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { + a - b + } + + fn mul(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { + a * b + } + + fn fmul(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { + a * b + } + + fn udiv(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { + // TODO(antoyo): convert the arguments to unsigned? + a / b + } + + fn exactudiv(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { + // TODO(antoyo): convert the arguments to unsigned? + // TODO(antoyo): poison if not exact. + a / b + } + + fn sdiv(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { + // TODO(antoyo): convert the arguments to signed? + a / b + } + + fn exactsdiv(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { + // TODO(antoyo): posion if not exact. + // FIXME(antoyo): rustc_codegen_ssa::mir::intrinsic uses different types for a and b but they + // should be the same. + let typ = a.get_type().to_signed(self); + let b = self.context.new_cast(None, b, typ); + a / b + } + + fn fdiv(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { + a / b + } + + fn urem(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { + a % b + } + + fn srem(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { + a % b + } + + fn frem(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { + if a.get_type() == self.cx.float_type { + let fmodf = self.context.get_builtin_function("fmodf"); + // FIXME(antoyo): this seems to produce the wrong result. + return self.context.new_call(None, fmodf, &[a, b]); + } + assert_eq!(a.get_type(), self.cx.double_type); + + let fmod = self.context.get_builtin_function("fmod"); + return self.context.new_call(None, fmod, &[a, b]); + } + + fn shl(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { + // FIXME(antoyo): remove the casts when libgccjit can shift an unsigned number by an unsigned number. + let a_type = a.get_type(); + let b_type = b.get_type(); + if a_type.is_unsigned(self) && b_type.is_signed(self) { + let a = self.context.new_cast(None, a, b_type); + let result = a << b; + self.context.new_cast(None, result, a_type) + } + else if a_type.is_signed(self) && b_type.is_unsigned(self) { + let b = self.context.new_cast(None, b, a_type); + a << b + } + else { + a << b + } + } + + fn lshr(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { + // FIXME(antoyo): remove the casts when libgccjit can shift an unsigned number by an unsigned number. + // TODO(antoyo): cast to unsigned to do a logical shift if that does not work. + let a_type = a.get_type(); + let b_type = b.get_type(); + if a_type.is_unsigned(self) && b_type.is_signed(self) { + let a = self.context.new_cast(None, a, b_type); + let result = a >> b; + self.context.new_cast(None, result, a_type) + } + else if a_type.is_signed(self) && b_type.is_unsigned(self) { + let b = self.context.new_cast(None, b, a_type); + a >> b + } + else { + a >> b + } + } + + fn ashr(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { + // TODO(antoyo): check whether behavior is an arithmetic shift for >> . + // FIXME(antoyo): remove the casts when libgccjit can shift an unsigned number by an unsigned number. + let a_type = a.get_type(); + let b_type = b.get_type(); + if a_type.is_unsigned(self) && b_type.is_signed(self) { + let a = self.context.new_cast(None, a, b_type); + let result = a >> b; + self.context.new_cast(None, result, a_type) + } + else if a_type.is_signed(self) && b_type.is_unsigned(self) { + let b = self.context.new_cast(None, b, a_type); + a >> b + } + else { + a >> b + } + } + + fn and(&mut self, a: RValue<'gcc>, mut b: RValue<'gcc>) -> RValue<'gcc> { + // FIXME(antoyo): hack by putting the result in a variable to workaround this bug: + // https://gcc.gnu.org/bugzilla//show_bug.cgi?id=95498 + if a.get_type() != b.get_type() { + b = self.context.new_cast(None, b, a.get_type()); + } + let res = self.current_func().new_local(None, b.get_type(), "andResult"); + self.llbb().add_assignment(None, res, a & b); + res.to_rvalue() + } + + fn or(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { + // FIXME(antoyo): hack by putting the result in a variable to workaround this bug: + // https://gcc.gnu.org/bugzilla//show_bug.cgi?id=95498 + let res = self.current_func().new_local(None, b.get_type(), "orResult"); + self.llbb().add_assignment(None, res, a | b); + res.to_rvalue() + } + + fn xor(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { + a ^ b + } + + fn neg(&mut self, a: RValue<'gcc>) -> RValue<'gcc> { + // TODO(antoyo): use new_unary_op()? + self.cx.context.new_rvalue_from_long(a.get_type(), 0) - a + } + + fn fneg(&mut self, a: RValue<'gcc>) -> RValue<'gcc> { + self.cx.context.new_unary_op(None, UnaryOp::Minus, a.get_type(), a) + } + + fn not(&mut self, a: RValue<'gcc>) -> RValue<'gcc> { + let operation = + if a.get_type().is_bool() { + UnaryOp::LogicalNegate + } + else { + UnaryOp::BitwiseNegate + }; + self.cx.context.new_unary_op(None, operation, a.get_type(), a) + } + + fn unchecked_sadd(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { + a + b + } + + fn unchecked_uadd(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { + a + b + } + + fn unchecked_ssub(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { + a - b + } + + fn unchecked_usub(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { + // TODO(antoyo): should generate poison value? + a - b + } + + fn unchecked_smul(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { + a * b + } + + fn unchecked_umul(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { + a * b + } + + fn fadd_fast(&mut self, _lhs: RValue<'gcc>, _rhs: RValue<'gcc>) -> RValue<'gcc> { + unimplemented!(); + } + + fn fsub_fast(&mut self, _lhs: RValue<'gcc>, _rhs: RValue<'gcc>) -> RValue<'gcc> { + unimplemented!(); + } + + fn fmul_fast(&mut self, _lhs: RValue<'gcc>, _rhs: RValue<'gcc>) -> RValue<'gcc> { + unimplemented!(); + } + + fn fdiv_fast(&mut self, _lhs: RValue<'gcc>, _rhs: RValue<'gcc>) -> RValue<'gcc> { + unimplemented!(); + } + + fn frem_fast(&mut self, _lhs: RValue<'gcc>, _rhs: RValue<'gcc>) -> RValue<'gcc> { + unimplemented!(); + } + + fn checked_binop(&mut self, oop: OverflowOp, typ: Ty<'_>, lhs: Self::Value, rhs: Self::Value) -> (Self::Value, Self::Value) { + use rustc_middle::ty::{Int, IntTy::*, Uint, UintTy::*}; + + let new_kind = + match typ.kind() { + Int(t @ Isize) => Int(t.normalize(self.tcx.sess.target.pointer_width)), + Uint(t @ Usize) => Uint(t.normalize(self.tcx.sess.target.pointer_width)), + t @ (Uint(_) | Int(_)) => t.clone(), + _ => panic!("tried to get overflow intrinsic for op applied to non-int type"), + }; + + // TODO(antoyo): remove duplication with intrinsic? + let name = + match oop { + OverflowOp::Add => + match new_kind { + Int(I8) => "__builtin_add_overflow", + Int(I16) => "__builtin_add_overflow", + Int(I32) => "__builtin_sadd_overflow", + Int(I64) => "__builtin_saddll_overflow", + Int(I128) => "__builtin_add_overflow", + + Uint(U8) => "__builtin_add_overflow", + Uint(U16) => "__builtin_add_overflow", + Uint(U32) => "__builtin_uadd_overflow", + Uint(U64) => "__builtin_uaddll_overflow", + Uint(U128) => "__builtin_add_overflow", + + _ => unreachable!(), + }, + OverflowOp::Sub => + match new_kind { + Int(I8) => "__builtin_sub_overflow", + Int(I16) => "__builtin_sub_overflow", + Int(I32) => "__builtin_ssub_overflow", + Int(I64) => "__builtin_ssubll_overflow", + Int(I128) => "__builtin_sub_overflow", + + Uint(U8) => "__builtin_sub_overflow", + Uint(U16) => "__builtin_sub_overflow", + Uint(U32) => "__builtin_usub_overflow", + Uint(U64) => "__builtin_usubll_overflow", + Uint(U128) => "__builtin_sub_overflow", + + _ => unreachable!(), + }, + OverflowOp::Mul => + match new_kind { + Int(I8) => "__builtin_mul_overflow", + Int(I16) => "__builtin_mul_overflow", + Int(I32) => "__builtin_smul_overflow", + Int(I64) => "__builtin_smulll_overflow", + Int(I128) => "__builtin_mul_overflow", + + Uint(U8) => "__builtin_mul_overflow", + Uint(U16) => "__builtin_mul_overflow", + Uint(U32) => "__builtin_umul_overflow", + Uint(U64) => "__builtin_umulll_overflow", + Uint(U128) => "__builtin_mul_overflow", + + _ => unreachable!(), + }, + }; + + let intrinsic = self.context.get_builtin_function(&name); + let res = self.current_func() + // TODO(antoyo): is it correct to use rhs type instead of the parameter typ? + .new_local(None, rhs.get_type(), "binopResult") + .get_address(None); + let overflow = self.overflow_call(intrinsic, &[lhs, rhs, res], None); + (res.dereference(None).to_rvalue(), overflow) + } + + fn alloca(&mut self, ty: Type<'gcc>, align: Align) -> RValue<'gcc> { + // FIXME(antoyo): this check that we don't call get_aligned() a second time on a type. + // Ideally, we shouldn't need to do this check. + let aligned_type = + if ty == self.cx.u128_type || ty == self.cx.i128_type { + ty + } + else { + ty.get_aligned(align.bytes()) + }; + // TODO(antoyo): It might be better to return a LValue, but fixing the rustc API is non-trivial. + self.stack_var_count.set(self.stack_var_count.get() + 1); + self.current_func().new_local(None, aligned_type, &format!("stack_var_{}", self.stack_var_count.get())).get_address(None) + } + + fn dynamic_alloca(&mut self, _ty: Type<'gcc>, _align: Align) -> RValue<'gcc> { + unimplemented!(); + } + + fn array_alloca(&mut self, _ty: Type<'gcc>, _len: RValue<'gcc>, _align: Align) -> RValue<'gcc> { + unimplemented!(); + } + + fn load(&mut self, _ty: Type<'gcc>, ptr: RValue<'gcc>, _align: Align) -> RValue<'gcc> { + // TODO(antoyo): use ty. + let block = self.llbb(); + let function = block.get_function(); + // NOTE: instead of returning the dereference here, we have to assign it to a variable in + // the current basic block. Otherwise, it could be used in another basic block, causing a + // dereference after a drop, for instance. + // TODO(antoyo): handle align. + let deref = ptr.dereference(None).to_rvalue(); + let value_type = deref.get_type(); + unsafe { RETURN_VALUE_COUNT += 1 }; + let loaded_value = function.new_local(None, value_type, &format!("loadedValue{}", unsafe { RETURN_VALUE_COUNT })); + block.add_assignment(None, loaded_value, deref); + loaded_value.to_rvalue() + } + + fn volatile_load(&mut self, _ty: Type<'gcc>, ptr: RValue<'gcc>) -> RValue<'gcc> { + // TODO(antoyo): use ty. + let ptr = self.context.new_cast(None, ptr, ptr.get_type().make_volatile()); + ptr.dereference(None).to_rvalue() + } + + fn atomic_load(&mut self, _ty: Type<'gcc>, ptr: RValue<'gcc>, order: AtomicOrdering, size: Size) -> RValue<'gcc> { + // TODO(antoyo): use ty. + // TODO(antoyo): handle alignment. + let atomic_load = self.context.get_builtin_function(&format!("__atomic_load_{}", size.bytes())); + let ordering = self.context.new_rvalue_from_int(self.i32_type, order.to_gcc()); + + let volatile_const_void_ptr_type = self.context.new_type::<*mut ()>().make_const().make_volatile(); + let ptr = self.context.new_cast(None, ptr, volatile_const_void_ptr_type); + self.context.new_call(None, atomic_load, &[ptr, ordering]) + } + + fn load_operand(&mut self, place: PlaceRef<'tcx, RValue<'gcc>>) -> OperandRef<'tcx, RValue<'gcc>> { + assert_eq!(place.llextra.is_some(), place.layout.is_unsized()); + + if place.layout.is_zst() { + return OperandRef::new_zst(self, place.layout); + } + + fn scalar_load_metadata<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>, load: RValue<'gcc>, scalar: &abi::Scalar) { + let vr = scalar.valid_range.clone(); + match scalar.value { + abi::Int(..) => { + if !scalar.is_always_valid(bx) { + bx.range_metadata(load, scalar.valid_range); + } + } + abi::Pointer if vr.start < vr.end && !vr.contains(0) => { + bx.nonnull_metadata(load); + } + _ => {} + } + } + + let val = + if let Some(llextra) = place.llextra { + OperandValue::Ref(place.llval, Some(llextra), place.align) + } + else if place.layout.is_gcc_immediate() { + let load = self.load(place.llval.get_type(), place.llval, place.align); + if let abi::Abi::Scalar(ref scalar) = place.layout.abi { + scalar_load_metadata(self, load, scalar); + } + OperandValue::Immediate(self.to_immediate(load, place.layout)) + } + else if let abi::Abi::ScalarPair(ref a, ref b) = place.layout.abi { + let b_offset = a.value.size(self).align_to(b.value.align(self).abi); + let pair_type = place.layout.gcc_type(self, false); + + let mut load = |i, scalar: &abi::Scalar, align| { + let llptr = self.struct_gep(pair_type, place.llval, i as u64); + let load = self.load(llptr.get_type(), llptr, align); + scalar_load_metadata(self, load, scalar); + if scalar.is_bool() { self.trunc(load, self.type_i1()) } else { load } + }; + + OperandValue::Pair( + load(0, a, place.align), + load(1, b, place.align.restrict_for_offset(b_offset)), + ) + } + else { + OperandValue::Ref(place.llval, None, place.align) + }; + + OperandRef { val, layout: place.layout } + } + + fn write_operand_repeatedly(mut self, cg_elem: OperandRef<'tcx, RValue<'gcc>>, count: u64, dest: PlaceRef<'tcx, RValue<'gcc>>) -> Self { + let zero = self.const_usize(0); + let count = self.const_usize(count); + let start = dest.project_index(&mut self, zero).llval; + let end = dest.project_index(&mut self, count).llval; + + let mut header_bx = self.build_sibling_block("repeat_loop_header"); + let mut body_bx = self.build_sibling_block("repeat_loop_body"); + let next_bx = self.build_sibling_block("repeat_loop_next"); + + let ptr_type = start.get_type(); + let current = self.llbb().get_function().new_local(None, ptr_type, "loop_var"); + let current_val = current.to_rvalue(); + self.assign(current, start); + + self.br(header_bx.llbb()); + + let keep_going = header_bx.icmp(IntPredicate::IntNE, current_val, end); + header_bx.cond_br(keep_going, body_bx.llbb(), next_bx.llbb()); + + let align = dest.align.restrict_for_offset(dest.layout.field(self.cx(), 0).size); + cg_elem.val.store(&mut body_bx, PlaceRef::new_sized_aligned(current_val, cg_elem.layout, align)); + + let next = body_bx.inbounds_gep(self.backend_type(cg_elem.layout), current.to_rvalue(), &[self.const_usize(1)]); + body_bx.llbb().add_assignment(None, current, next); + body_bx.br(header_bx.llbb()); + + next_bx + } + + fn range_metadata(&mut self, _load: RValue<'gcc>, _range: WrappingRange) { + // TODO(antoyo) + } + + fn nonnull_metadata(&mut self, _load: RValue<'gcc>) { + // TODO(antoyo) + } + + fn store(&mut self, val: RValue<'gcc>, ptr: RValue<'gcc>, align: Align) -> RValue<'gcc> { + self.store_with_flags(val, ptr, align, MemFlags::empty()) + } + + fn store_with_flags(&mut self, val: RValue<'gcc>, ptr: RValue<'gcc>, _align: Align, _flags: MemFlags) -> RValue<'gcc> { + let ptr = self.check_store(val, ptr); + self.llbb().add_assignment(None, ptr.dereference(None), val); + // TODO(antoyo): handle align and flags. + // NOTE: dummy value here since it's never used. FIXME(antoyo): API should not return a value here? + self.cx.context.new_rvalue_zero(self.type_i32()) + } + + fn atomic_store(&mut self, value: RValue<'gcc>, ptr: RValue<'gcc>, order: AtomicOrdering, size: Size) { + // TODO(antoyo): handle alignment. + let atomic_store = self.context.get_builtin_function(&format!("__atomic_store_{}", size.bytes())); + let ordering = self.context.new_rvalue_from_int(self.i32_type, order.to_gcc()); + let volatile_const_void_ptr_type = self.context.new_type::<*mut ()>().make_const().make_volatile(); + let ptr = self.context.new_cast(None, ptr, volatile_const_void_ptr_type); + + // FIXME(antoyo): fix libgccjit to allow comparing an integer type with an aligned integer type because + // the following cast is required to avoid this error: + // gcc_jit_context_new_call: mismatching types for argument 2 of function "__atomic_store_4": assignment to param arg1 (type: int) from loadedValue3577 (type: unsigned int __attribute__((aligned(4)))) + let int_type = atomic_store.get_param(1).to_rvalue().get_type(); + let value = self.context.new_cast(None, value, int_type); + self.llbb() + .add_eval(None, self.context.new_call(None, atomic_store, &[ptr, value, ordering])); + } + + fn gep(&mut self, _typ: Type<'gcc>, ptr: RValue<'gcc>, indices: &[RValue<'gcc>]) -> RValue<'gcc> { + let mut result = ptr; + for index in indices { + result = self.context.new_array_access(None, result, *index).get_address(None).to_rvalue(); + } + result + } + + fn inbounds_gep(&mut self, _typ: Type<'gcc>, ptr: RValue<'gcc>, indices: &[RValue<'gcc>]) -> RValue<'gcc> { + // FIXME(antoyo): would be safer if doing the same thing (loop) as gep. + // TODO(antoyo): specify inbounds somehow. + match indices.len() { + 1 => { + self.context.new_array_access(None, ptr, indices[0]).get_address(None) + }, + 2 => { + let array = ptr.dereference(None); // TODO(antoyo): assert that first index is 0? + self.context.new_array_access(None, array, indices[1]).get_address(None) + }, + _ => unimplemented!(), + } + } + + fn struct_gep(&mut self, value_type: Type<'gcc>, ptr: RValue<'gcc>, idx: u64) -> RValue<'gcc> { + // FIXME(antoyo): it would be better if the API only called this on struct, not on arrays. + assert_eq!(idx as usize as u64, idx); + let value = ptr.dereference(None).to_rvalue(); + + if value_type.is_array().is_some() { + let index = self.context.new_rvalue_from_long(self.u64_type, i64::try_from(idx).expect("i64::try_from")); + let element = self.context.new_array_access(None, value, index); + element.get_address(None) + } + else if let Some(vector_type) = value_type.is_vector() { + let array_type = vector_type.get_element_type().make_pointer(); + let array = self.bitcast(ptr, array_type); + let index = self.context.new_rvalue_from_long(self.u64_type, i64::try_from(idx).expect("i64::try_from")); + let element = self.context.new_array_access(None, array, index); + element.get_address(None) + } + else if let Some(struct_type) = value_type.is_struct() { + ptr.dereference_field(None, struct_type.get_field(idx as i32)).get_address(None) + } + else { + panic!("Unexpected type {:?}", value_type); + } + } + + /* Casts */ + fn trunc(&mut self, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> { + // TODO(antoyo): check that it indeed truncate the value. + self.context.new_cast(None, value, dest_ty) + } + + fn sext(&mut self, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> { + // TODO(antoyo): check that it indeed sign extend the value. + if dest_ty.is_vector().is_some() { + // TODO(antoyo): nothing to do as it is only for LLVM? + return value; + } + self.context.new_cast(None, value, dest_ty) + } + + fn fptoui(&mut self, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> { + self.context.new_cast(None, value, dest_ty) + } + + fn fptosi(&mut self, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> { + self.context.new_cast(None, value, dest_ty) + } + + fn uitofp(&mut self, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> { + self.context.new_cast(None, value, dest_ty) + } + + fn sitofp(&mut self, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> { + self.context.new_cast(None, value, dest_ty) + } + + fn fptrunc(&mut self, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> { + // TODO(antoyo): make sure it truncates. + self.context.new_cast(None, value, dest_ty) + } + + fn fpext(&mut self, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> { + self.context.new_cast(None, value, dest_ty) + } + + fn ptrtoint(&mut self, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> { + self.cx.ptrtoint(self.block.expect("block"), value, dest_ty) + } + + fn inttoptr(&mut self, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> { + self.cx.inttoptr(self.block.expect("block"), value, dest_ty) + } + + fn bitcast(&mut self, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> { + self.cx.const_bitcast(value, dest_ty) + } + + fn intcast(&mut self, value: RValue<'gcc>, dest_typ: Type<'gcc>, _is_signed: bool) -> RValue<'gcc> { + // NOTE: is_signed is for value, not dest_typ. + self.cx.context.new_cast(None, value, dest_typ) + } + + fn pointercast(&mut self, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> { + let val_type = value.get_type(); + match (type_is_pointer(val_type), type_is_pointer(dest_ty)) { + (false, true) => { + // NOTE: Projecting a field of a pointer type will attemp a cast from a signed char to + // a pointer, which is not supported by gccjit. + return self.cx.context.new_cast(None, self.inttoptr(value, val_type.make_pointer()), dest_ty); + }, + (false, false) => { + // When they are not pointers, we want a transmute (or reinterpret_cast). + self.bitcast(value, dest_ty) + }, + (true, true) => self.cx.context.new_cast(None, value, dest_ty), + (true, false) => unimplemented!(), + } + } + + /* Comparisons */ + fn icmp(&mut self, op: IntPredicate, mut lhs: RValue<'gcc>, mut rhs: RValue<'gcc>) -> RValue<'gcc> { + let left_type = lhs.get_type(); + let right_type = rhs.get_type(); + if left_type != right_type { + // NOTE: because libgccjit cannot compare function pointers. + if left_type.is_function_ptr_type().is_some() && right_type.is_function_ptr_type().is_some() { + lhs = self.context.new_cast(None, lhs, self.usize_type.make_pointer()); + rhs = self.context.new_cast(None, rhs, self.usize_type.make_pointer()); + } + // NOTE: hack because we try to cast a vector type to the same vector type. + else if format!("{:?}", left_type) != format!("{:?}", right_type) { + rhs = self.context.new_cast(None, rhs, left_type); + } + } + self.context.new_comparison(None, op.to_gcc_comparison(), lhs, rhs) + } + + fn fcmp(&mut self, op: RealPredicate, lhs: RValue<'gcc>, rhs: RValue<'gcc>) -> RValue<'gcc> { + self.context.new_comparison(None, op.to_gcc_comparison(), lhs, rhs) + } + + /* Miscellaneous instructions */ + fn memcpy(&mut self, dst: RValue<'gcc>, dst_align: Align, src: RValue<'gcc>, src_align: Align, size: RValue<'gcc>, flags: MemFlags) { + if flags.contains(MemFlags::NONTEMPORAL) { + // HACK(nox): This is inefficient but there is no nontemporal memcpy. + let val = self.load(src.get_type(), src, src_align); + let ptr = self.pointercast(dst, self.type_ptr_to(self.val_ty(val))); + self.store_with_flags(val, ptr, dst_align, flags); + return; + } + let size = self.intcast(size, self.type_size_t(), false); + let _is_volatile = flags.contains(MemFlags::VOLATILE); + let dst = self.pointercast(dst, self.type_i8p()); + let src = self.pointercast(src, self.type_ptr_to(self.type_void())); + let memcpy = self.context.get_builtin_function("memcpy"); + let block = self.block.expect("block"); + // TODO(antoyo): handle aligns and is_volatile. + block.add_eval(None, self.context.new_call(None, memcpy, &[dst, src, size])); + } + + fn memmove(&mut self, dst: RValue<'gcc>, dst_align: Align, src: RValue<'gcc>, src_align: Align, size: RValue<'gcc>, flags: MemFlags) { + if flags.contains(MemFlags::NONTEMPORAL) { + // HACK(nox): This is inefficient but there is no nontemporal memmove. + let val = self.load(src.get_type(), src, src_align); + let ptr = self.pointercast(dst, self.type_ptr_to(self.val_ty(val))); + self.store_with_flags(val, ptr, dst_align, flags); + return; + } + let size = self.intcast(size, self.type_size_t(), false); + let _is_volatile = flags.contains(MemFlags::VOLATILE); + let dst = self.pointercast(dst, self.type_i8p()); + let src = self.pointercast(src, self.type_ptr_to(self.type_void())); + + let memmove = self.context.get_builtin_function("memmove"); + let block = self.block.expect("block"); + // TODO(antoyo): handle is_volatile. + block.add_eval(None, self.context.new_call(None, memmove, &[dst, src, size])); + } + + fn memset(&mut self, ptr: RValue<'gcc>, fill_byte: RValue<'gcc>, size: RValue<'gcc>, _align: Align, flags: MemFlags) { + let _is_volatile = flags.contains(MemFlags::VOLATILE); + let ptr = self.pointercast(ptr, self.type_i8p()); + let memset = self.context.get_builtin_function("memset"); + let block = self.block.expect("block"); + // TODO(antoyo): handle align and is_volatile. + let fill_byte = self.context.new_cast(None, fill_byte, self.i32_type); + let size = self.intcast(size, self.type_size_t(), false); + block.add_eval(None, self.context.new_call(None, memset, &[ptr, fill_byte, size])); + } + + fn select(&mut self, cond: RValue<'gcc>, then_val: RValue<'gcc>, mut else_val: RValue<'gcc>) -> RValue<'gcc> { + let func = self.current_func(); + let variable = func.new_local(None, then_val.get_type(), "selectVar"); + let then_block = func.new_block("then"); + let else_block = func.new_block("else"); + let after_block = func.new_block("after"); + self.llbb().end_with_conditional(None, cond, then_block, else_block); + + then_block.add_assignment(None, variable, then_val); + then_block.end_with_jump(None, after_block); + + if then_val.get_type() != else_val.get_type() { + else_val = self.context.new_cast(None, else_val, then_val.get_type()); + } + else_block.add_assignment(None, variable, else_val); + else_block.end_with_jump(None, after_block); + + // NOTE: since jumps were added in a place rustc does not expect, the current blocks in the + // state need to be updated. + self.block = Some(after_block); + *self.cx.current_block.borrow_mut() = Some(after_block); + + variable.to_rvalue() + } + + #[allow(dead_code)] + fn va_arg(&mut self, _list: RValue<'gcc>, _ty: Type<'gcc>) -> RValue<'gcc> { + unimplemented!(); + } + + fn extract_element(&mut self, _vec: RValue<'gcc>, _idx: RValue<'gcc>) -> RValue<'gcc> { + unimplemented!(); + } + + fn vector_splat(&mut self, _num_elts: usize, _elt: RValue<'gcc>) -> RValue<'gcc> { + unimplemented!(); + } + + fn extract_value(&mut self, aggregate_value: RValue<'gcc>, idx: u64) -> RValue<'gcc> { + // FIXME(antoyo): it would be better if the API only called this on struct, not on arrays. + assert_eq!(idx as usize as u64, idx); + let value_type = aggregate_value.get_type(); + + if value_type.is_array().is_some() { + let index = self.context.new_rvalue_from_long(self.u64_type, i64::try_from(idx).expect("i64::try_from")); + let element = self.context.new_array_access(None, aggregate_value, index); + element.get_address(None) + } + else if value_type.is_vector().is_some() { + panic!(); + } + else if let Some(pointer_type) = value_type.get_pointee() { + if let Some(struct_type) = pointer_type.is_struct() { + // NOTE: hack to workaround a limitation of the rustc API: see comment on + // CodegenCx.structs_as_pointer + aggregate_value.dereference_field(None, struct_type.get_field(idx as i32)).to_rvalue() + } + else { + panic!("Unexpected type {:?}", value_type); + } + } + else if let Some(struct_type) = value_type.is_struct() { + aggregate_value.access_field(None, struct_type.get_field(idx as i32)).to_rvalue() + } + else { + panic!("Unexpected type {:?}", value_type); + } + } + + fn insert_value(&mut self, aggregate_value: RValue<'gcc>, value: RValue<'gcc>, idx: u64) -> RValue<'gcc> { + // FIXME(antoyo): it would be better if the API only called this on struct, not on arrays. + assert_eq!(idx as usize as u64, idx); + let value_type = aggregate_value.get_type(); + + let lvalue = + if value_type.is_array().is_some() { + let index = self.context.new_rvalue_from_long(self.u64_type, i64::try_from(idx).expect("i64::try_from")); + self.context.new_array_access(None, aggregate_value, index) + } + else if value_type.is_vector().is_some() { + panic!(); + } + else if let Some(pointer_type) = value_type.get_pointee() { + if let Some(struct_type) = pointer_type.is_struct() { + // NOTE: hack to workaround a limitation of the rustc API: see comment on + // CodegenCx.structs_as_pointer + aggregate_value.dereference_field(None, struct_type.get_field(idx as i32)) + } + else { + panic!("Unexpected type {:?}", value_type); + } + } + else { + panic!("Unexpected type {:?}", value_type); + }; + + let lvalue_type = lvalue.to_rvalue().get_type(); + let value = + // NOTE: sometimes, rustc will create a value with the wrong type. + if lvalue_type != value.get_type() { + self.context.new_cast(None, value, lvalue_type) + } + else { + value + }; + + self.llbb().add_assignment(None, lvalue, value); + + aggregate_value + } + + fn landing_pad(&mut self, _ty: Type<'gcc>, _pers_fn: RValue<'gcc>, _num_clauses: usize) -> RValue<'gcc> { + let field1 = self.context.new_field(None, self.u8_type, "landing_pad_field_1"); + let field2 = self.context.new_field(None, self.i32_type, "landing_pad_field_1"); + let struct_type = self.context.new_struct_type(None, "landing_pad", &[field1, field2]); + self.current_func().new_local(None, struct_type.as_type(), "landing_pad") + .to_rvalue() + // TODO(antoyo): Properly implement unwinding. + // the above is just to make the compilation work as it seems + // rustc_codegen_ssa now calls the unwinding builder methods even on panic=abort. + } + + fn set_cleanup(&mut self, _landing_pad: RValue<'gcc>) { + // TODO(antoyo) + } + + fn resume(&mut self, _exn: RValue<'gcc>) -> RValue<'gcc> { + unimplemented!(); + } + + fn cleanup_pad(&mut self, _parent: Option>, _args: &[RValue<'gcc>]) -> Funclet { + unimplemented!(); + } + + fn cleanup_ret(&mut self, _funclet: &Funclet, _unwind: Option>) -> RValue<'gcc> { + unimplemented!(); + } + + fn catch_pad(&mut self, _parent: RValue<'gcc>, _args: &[RValue<'gcc>]) -> Funclet { + unimplemented!(); + } + + fn catch_switch(&mut self, _parent: Option>, _unwind: Option>, _num_handlers: usize) -> RValue<'gcc> { + unimplemented!(); + } + + fn add_handler(&mut self, _catch_switch: RValue<'gcc>, _handler: Block<'gcc>) { + unimplemented!(); + } + + fn set_personality_fn(&mut self, _personality: RValue<'gcc>) { + // TODO(antoyo) + } + + // Atomic Operations + fn atomic_cmpxchg(&mut self, dst: RValue<'gcc>, cmp: RValue<'gcc>, src: RValue<'gcc>, order: AtomicOrdering, failure_order: AtomicOrdering, weak: bool) -> RValue<'gcc> { + let expected = self.current_func().new_local(None, cmp.get_type(), "expected"); + self.llbb().add_assignment(None, expected, cmp); + let success = self.compare_exchange(dst, expected, src, order, failure_order, weak); + + let pair_type = self.cx.type_struct(&[src.get_type(), self.bool_type], false); + let result = self.current_func().new_local(None, pair_type, "atomic_cmpxchg_result"); + let align = Align::from_bits(64).expect("align"); // TODO(antoyo): use good align. + + let value_type = result.to_rvalue().get_type(); + if let Some(struct_type) = value_type.is_struct() { + self.store(success, result.access_field(None, struct_type.get_field(1)).get_address(None), align); + // NOTE: since success contains the call to the intrinsic, it must be stored before + // expected so that we store expected after the call. + self.store(expected.to_rvalue(), result.access_field(None, struct_type.get_field(0)).get_address(None), align); + } + // TODO(antoyo): handle when value is not a struct. + + result.to_rvalue() + } + + fn atomic_rmw(&mut self, op: AtomicRmwBinOp, dst: RValue<'gcc>, src: RValue<'gcc>, order: AtomicOrdering) -> RValue<'gcc> { + let size = self.cx.int_width(src.get_type()) / 8; + let name = + match op { + AtomicRmwBinOp::AtomicXchg => format!("__atomic_exchange_{}", size), + AtomicRmwBinOp::AtomicAdd => format!("__atomic_fetch_add_{}", size), + AtomicRmwBinOp::AtomicSub => format!("__atomic_fetch_sub_{}", size), + AtomicRmwBinOp::AtomicAnd => format!("__atomic_fetch_and_{}", size), + AtomicRmwBinOp::AtomicNand => format!("__atomic_fetch_nand_{}", size), + AtomicRmwBinOp::AtomicOr => format!("__atomic_fetch_or_{}", size), + AtomicRmwBinOp::AtomicXor => format!("__atomic_fetch_xor_{}", size), + AtomicRmwBinOp::AtomicMax => return self.atomic_extremum(ExtremumOperation::Max, dst, src, order), + AtomicRmwBinOp::AtomicMin => return self.atomic_extremum(ExtremumOperation::Min, dst, src, order), + AtomicRmwBinOp::AtomicUMax => return self.atomic_extremum(ExtremumOperation::Max, dst, src, order), + AtomicRmwBinOp::AtomicUMin => return self.atomic_extremum(ExtremumOperation::Min, dst, src, order), + }; + + + let atomic_function = self.context.get_builtin_function(name); + let order = self.context.new_rvalue_from_int(self.i32_type, order.to_gcc()); + + let void_ptr_type = self.context.new_type::<*mut ()>(); + let volatile_void_ptr_type = void_ptr_type.make_volatile(); + let dst = self.context.new_cast(None, dst, volatile_void_ptr_type); + // FIXME(antoyo): not sure why, but we have the wrong type here. + let new_src_type = atomic_function.get_param(1).to_rvalue().get_type(); + let src = self.context.new_cast(None, src, new_src_type); + let res = self.context.new_call(None, atomic_function, &[dst, src, order]); + self.context.new_cast(None, res, src.get_type()) + } + + fn atomic_fence(&mut self, order: AtomicOrdering, scope: SynchronizationScope) { + let name = + match scope { + SynchronizationScope::SingleThread => "__atomic_signal_fence", + SynchronizationScope::CrossThread => "__atomic_thread_fence", + }; + let thread_fence = self.context.get_builtin_function(name); + let order = self.context.new_rvalue_from_int(self.i32_type, order.to_gcc()); + self.llbb().add_eval(None, self.context.new_call(None, thread_fence, &[order])); + } + + fn set_invariant_load(&mut self, load: RValue<'gcc>) { + // NOTE: Hack to consider vtable function pointer as non-global-variable function pointer. + self.normal_function_addresses.borrow_mut().insert(load); + // TODO(antoyo) + } + + fn lifetime_start(&mut self, _ptr: RValue<'gcc>, _size: Size) { + // TODO(antoyo) + } + + fn lifetime_end(&mut self, _ptr: RValue<'gcc>, _size: Size) { + // TODO(antoyo) + } + + fn call(&mut self, _typ: Type<'gcc>, func: RValue<'gcc>, args: &[RValue<'gcc>], funclet: Option<&Funclet>) -> RValue<'gcc> { + // FIXME(antoyo): remove when having a proper API. + let gcc_func = unsafe { std::mem::transmute(func) }; + if self.functions.borrow().values().find(|value| **value == gcc_func).is_some() { + self.function_call(func, args, funclet) + } + else { + // If it's a not function that was defined, it's a function pointer. + self.function_ptr_call(func, args, funclet) + } + } + + fn zext(&mut self, value: RValue<'gcc>, dest_typ: Type<'gcc>) -> RValue<'gcc> { + // FIXME(antoyo): this does not zero-extend. + if value.get_type().is_bool() && dest_typ.is_i8(&self.cx) { + // FIXME(antoyo): hack because base::from_immediate converts i1 to i8. + // Fix the code in codegen_ssa::base::from_immediate. + return value; + } + self.context.new_cast(None, value, dest_typ) + } + + fn cx(&self) -> &CodegenCx<'gcc, 'tcx> { + self.cx + } + + fn do_not_inline(&mut self, _llret: RValue<'gcc>) { + unimplemented!(); + } + + fn set_span(&mut self, _span: Span) {} + + fn from_immediate(&mut self, val: Self::Value) -> Self::Value { + if self.cx().val_ty(val) == self.cx().type_i1() { + self.zext(val, self.cx().type_i8()) + } + else { + val + } + } + + fn to_immediate_scalar(&mut self, val: Self::Value, scalar: abi::Scalar) -> Self::Value { + if scalar.is_bool() { + return self.trunc(val, self.cx().type_i1()); + } + val + } + + fn fptoui_sat(&mut self, _val: RValue<'gcc>, _dest_ty: Type<'gcc>) -> Option> { + None + } + + fn fptosi_sat(&mut self, _val: RValue<'gcc>, _dest_ty: Type<'gcc>) -> Option> { + None + } + + fn instrprof_increment(&mut self, _fn_name: RValue<'gcc>, _hash: RValue<'gcc>, _num_counters: RValue<'gcc>, _index: RValue<'gcc>) { + unimplemented!(); + } +} + +impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { + pub fn shuffle_vector(&mut self, v1: RValue<'gcc>, v2: RValue<'gcc>, mask: RValue<'gcc>) -> RValue<'gcc> { + let return_type = v1.get_type(); + let params = [ + self.context.new_parameter(None, return_type, "v1"), + self.context.new_parameter(None, return_type, "v2"), + self.context.new_parameter(None, mask.get_type(), "mask"), + ]; + let shuffle = self.context.new_function(None, FunctionType::Extern, return_type, ¶ms, "_mm_shuffle_epi8", false); + self.context.new_call(None, shuffle, &[v1, v2, mask]) + } +} + +impl<'a, 'gcc, 'tcx> StaticBuilderMethods for Builder<'a, 'gcc, 'tcx> { + fn get_static(&mut self, def_id: DefId) -> RValue<'gcc> { + // Forward to the `get_static` method of `CodegenCx` + self.cx().get_static(def_id).get_address(None) + } +} + +impl<'tcx> HasParamEnv<'tcx> for Builder<'_, '_, 'tcx> { + fn param_env(&self) -> ParamEnv<'tcx> { + self.cx.param_env() + } +} + +impl<'tcx> HasTargetSpec for Builder<'_, '_, 'tcx> { + fn target_spec(&self) -> &Target { + &self.cx.target_spec() + } +} + +trait ToGccComp { + fn to_gcc_comparison(&self) -> ComparisonOp; +} + +impl ToGccComp for IntPredicate { + fn to_gcc_comparison(&self) -> ComparisonOp { + match *self { + IntPredicate::IntEQ => ComparisonOp::Equals, + IntPredicate::IntNE => ComparisonOp::NotEquals, + IntPredicate::IntUGT => ComparisonOp::GreaterThan, + IntPredicate::IntUGE => ComparisonOp::GreaterThanEquals, + IntPredicate::IntULT => ComparisonOp::LessThan, + IntPredicate::IntULE => ComparisonOp::LessThanEquals, + IntPredicate::IntSGT => ComparisonOp::GreaterThan, + IntPredicate::IntSGE => ComparisonOp::GreaterThanEquals, + IntPredicate::IntSLT => ComparisonOp::LessThan, + IntPredicate::IntSLE => ComparisonOp::LessThanEquals, + } + } +} + +impl ToGccComp for RealPredicate { + fn to_gcc_comparison(&self) -> ComparisonOp { + // TODO(antoyo): check that ordered vs non-ordered is respected. + match *self { + RealPredicate::RealPredicateFalse => unreachable!(), + RealPredicate::RealOEQ => ComparisonOp::Equals, + RealPredicate::RealOGT => ComparisonOp::GreaterThan, + RealPredicate::RealOGE => ComparisonOp::GreaterThanEquals, + RealPredicate::RealOLT => ComparisonOp::LessThan, + RealPredicate::RealOLE => ComparisonOp::LessThanEquals, + RealPredicate::RealONE => ComparisonOp::NotEquals, + RealPredicate::RealORD => unreachable!(), + RealPredicate::RealUNO => unreachable!(), + RealPredicate::RealUEQ => ComparisonOp::Equals, + RealPredicate::RealUGT => ComparisonOp::GreaterThan, + RealPredicate::RealUGE => ComparisonOp::GreaterThan, + RealPredicate::RealULT => ComparisonOp::LessThan, + RealPredicate::RealULE => ComparisonOp::LessThan, + RealPredicate::RealUNE => ComparisonOp::NotEquals, + RealPredicate::RealPredicateTrue => unreachable!(), + } + } +} + +#[repr(C)] +#[allow(non_camel_case_types)] +enum MemOrdering { + __ATOMIC_RELAXED, + __ATOMIC_CONSUME, + __ATOMIC_ACQUIRE, + __ATOMIC_RELEASE, + __ATOMIC_ACQ_REL, + __ATOMIC_SEQ_CST, +} + +trait ToGccOrdering { + fn to_gcc(self) -> i32; +} + +impl ToGccOrdering for AtomicOrdering { + fn to_gcc(self) -> i32 { + use MemOrdering::*; + + let ordering = + match self { + AtomicOrdering::NotAtomic => __ATOMIC_RELAXED, // TODO(antoyo): check if that's the same. + AtomicOrdering::Unordered => __ATOMIC_RELAXED, + AtomicOrdering::Monotonic => __ATOMIC_RELAXED, // TODO(antoyo): check if that's the same. + AtomicOrdering::Acquire => __ATOMIC_ACQUIRE, + AtomicOrdering::Release => __ATOMIC_RELEASE, + AtomicOrdering::AcquireRelease => __ATOMIC_ACQ_REL, + AtomicOrdering::SequentiallyConsistent => __ATOMIC_SEQ_CST, + }; + ordering as i32 + } +} diff --git a/compiler/rustc_codegen_gcc/src/callee.rs b/compiler/rustc_codegen_gcc/src/callee.rs new file mode 100644 index 0000000000..76419b103d --- /dev/null +++ b/compiler/rustc_codegen_gcc/src/callee.rs @@ -0,0 +1,77 @@ +use gccjit::{FunctionType, RValue}; +use rustc_codegen_ssa::traits::BaseTypeMethods; +use rustc_middle::ty::{self, Instance, TypeFoldable}; +use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt}; + +use crate::abi::FnAbiGccExt; +use crate::context::CodegenCx; + +/// Codegens a reference to a fn/method item, monomorphizing and +/// inlining as it goes. +/// +/// # Parameters +/// +/// - `cx`: the crate context +/// - `instance`: the instance to be instantiated +pub fn get_fn<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, instance: Instance<'tcx>) -> RValue<'gcc> { + let tcx = cx.tcx(); + + assert!(!instance.substs.needs_infer()); + assert!(!instance.substs.has_escaping_bound_vars()); + + if let Some(&func) = cx.function_instances.borrow().get(&instance) { + return func; + } + + let sym = tcx.symbol_name(instance).name; + + let fn_abi = cx.fn_abi_of_instance(instance, ty::List::empty()); + + let func = + if let Some(func) = cx.get_declared_value(&sym) { + // Create a fn pointer with the new signature. + let ptrty = fn_abi.ptr_to_gcc_type(cx); + + // This is subtle and surprising, but sometimes we have to bitcast + // the resulting fn pointer. The reason has to do with external + // functions. If you have two crates that both bind the same C + // library, they may not use precisely the same types: for + // example, they will probably each declare their own structs, + // which are distinct types from LLVM's point of view (nominal + // types). + // + // Now, if those two crates are linked into an application, and + // they contain inlined code, you can wind up with a situation + // where both of those functions wind up being loaded into this + // application simultaneously. In that case, the same function + // (from LLVM's point of view) requires two types. But of course + // LLVM won't allow one function to have two types. + // + // What we currently do, therefore, is declare the function with + // one of the two types (whichever happens to come first) and then + // bitcast as needed when the function is referenced to make sure + // it has the type we expect. + // + // This can occur on either a crate-local or crate-external + // reference. It also occurs when testing libcore and in some + // other weird situations. Annoying. + if cx.val_ty(func) != ptrty { + // TODO(antoyo): cast the pointer. + func + } + else { + func + } + } + else { + cx.linkage.set(FunctionType::Extern); + let func = cx.declare_fn(&sym, &fn_abi); + + // TODO(antoyo): set linkage and attributes. + func + }; + + cx.function_instances.borrow_mut().insert(instance, func); + + func +} diff --git a/compiler/rustc_codegen_gcc/src/common.rs b/compiler/rustc_codegen_gcc/src/common.rs new file mode 100644 index 0000000000..bda08b653f --- /dev/null +++ b/compiler/rustc_codegen_gcc/src/common.rs @@ -0,0 +1,450 @@ +use std::convert::TryFrom; +use std::convert::TryInto; + +use gccjit::LValue; +use gccjit::{Block, CType, RValue, Type, ToRValue}; +use rustc_codegen_ssa::mir::place::PlaceRef; +use rustc_codegen_ssa::traits::{ + BaseTypeMethods, + ConstMethods, + DerivedTypeMethods, + MiscMethods, + StaticMethods, +}; +use rustc_middle::mir::Mutability; +use rustc_middle::ty::ScalarInt; +use rustc_middle::ty::layout::{TyAndLayout, LayoutOf}; +use rustc_middle::mir::interpret::{Allocation, GlobalAlloc, Scalar}; +use rustc_span::Symbol; +use rustc_target::abi::{self, HasDataLayout, Pointer, Size}; + +use crate::consts::const_alloc_to_gcc; +use crate::context::CodegenCx; +use crate::type_of::LayoutGccExt; + +impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { + pub fn const_bytes(&self, bytes: &[u8]) -> RValue<'gcc> { + bytes_in_context(self, bytes) + } + + fn const_cstr(&self, symbol: Symbol, _null_terminated: bool) -> LValue<'gcc> { + // TODO(antoyo): handle null_terminated. + if let Some(&value) = self.const_cstr_cache.borrow().get(&symbol) { + return value; + } + + let global = self.global_string(&*symbol.as_str()); + + self.const_cstr_cache.borrow_mut().insert(symbol, global); + global + } + + fn global_string(&self, string: &str) -> LValue<'gcc> { + // TODO(antoyo): handle non-null-terminated strings. + let string = self.context.new_string_literal(&*string); + let sym = self.generate_local_symbol_name("str"); + let global = self.declare_private_global(&sym, self.val_ty(string)); + global.global_set_initializer_value(string); + global + // TODO(antoyo): set linkage. + } + + pub fn inttoptr(&self, block: Block<'gcc>, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> { + let func = block.get_function(); + let local = func.new_local(None, value.get_type(), "intLocal"); + block.add_assignment(None, local, value); + let value_address = local.get_address(None); + + let ptr = self.context.new_cast(None, value_address, dest_ty.make_pointer()); + ptr.dereference(None).to_rvalue() + } + + pub fn ptrtoint(&self, block: Block<'gcc>, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> { + // TODO(antoyo): when libgccjit allow casting from pointer to int, remove this. + let func = block.get_function(); + let local = func.new_local(None, value.get_type(), "ptrLocal"); + block.add_assignment(None, local, value); + let ptr_address = local.get_address(None); + + let ptr = self.context.new_cast(None, ptr_address, dest_ty.make_pointer()); + ptr.dereference(None).to_rvalue() + } +} + +pub fn bytes_in_context<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, bytes: &[u8]) -> RValue<'gcc> { + let context = &cx.context; + let byte_type = context.new_type::(); + let typ = context.new_array_type(None, byte_type, bytes.len() as i32); + let elements: Vec<_> = + bytes.iter() + .map(|&byte| context.new_rvalue_from_int(byte_type, byte as i32)) + .collect(); + context.new_rvalue_from_array(None, typ, &elements) +} + +pub fn type_is_pointer<'gcc>(typ: Type<'gcc>) -> bool { + typ.get_pointee().is_some() +} + +impl<'gcc, 'tcx> ConstMethods<'tcx> for CodegenCx<'gcc, 'tcx> { + fn const_null(&self, typ: Type<'gcc>) -> RValue<'gcc> { + if type_is_pointer(typ) { + self.context.new_null(typ) + } + else { + self.const_int(typ, 0) + } + } + + fn const_undef(&self, typ: Type<'gcc>) -> RValue<'gcc> { + let local = self.current_func.borrow().expect("func") + .new_local(None, typ, "undefined"); + if typ.is_struct().is_some() { + // NOTE: hack to workaround a limitation of the rustc API: see comment on + // CodegenCx.structs_as_pointer + let pointer = local.get_address(None); + self.structs_as_pointer.borrow_mut().insert(pointer); + pointer + } + else { + local.to_rvalue() + } + } + + fn const_int(&self, typ: Type<'gcc>, int: i64) -> RValue<'gcc> { + self.context.new_rvalue_from_long(typ, i64::try_from(int).expect("i64::try_from")) + } + + fn const_uint(&self, typ: Type<'gcc>, int: u64) -> RValue<'gcc> { + self.context.new_rvalue_from_long(typ, u64::try_from(int).expect("u64::try_from") as i64) + } + + fn const_uint_big(&self, typ: Type<'gcc>, num: u128) -> RValue<'gcc> { + let num64: Result = num.try_into(); + if let Ok(num) = num64 { + // FIXME(antoyo): workaround for a bug where libgccjit is expecting a constant. + // The operations >> 64 and | low are making the normal case a non-constant. + return self.context.new_rvalue_from_long(typ, num as i64); + } + + if num >> 64 != 0 { + // FIXME(antoyo): use a new function new_rvalue_from_unsigned_long()? + let low = self.context.new_rvalue_from_long(self.u64_type, num as u64 as i64); + let high = self.context.new_rvalue_from_long(typ, (num >> 64) as u64 as i64); + + let sixty_four = self.context.new_rvalue_from_long(typ, 64); + (high << sixty_four) | self.context.new_cast(None, low, typ) + } + else if typ.is_i128(self) { + let num = self.context.new_rvalue_from_long(self.u64_type, num as u64 as i64); + self.context.new_cast(None, num, typ) + } + else { + self.context.new_rvalue_from_long(typ, num as u64 as i64) + } + } + + fn const_bool(&self, val: bool) -> RValue<'gcc> { + self.const_uint(self.type_i1(), val as u64) + } + + fn const_i32(&self, i: i32) -> RValue<'gcc> { + self.const_int(self.type_i32(), i as i64) + } + + fn const_u32(&self, i: u32) -> RValue<'gcc> { + self.const_uint(self.type_u32(), i as u64) + } + + fn const_u64(&self, i: u64) -> RValue<'gcc> { + self.const_uint(self.type_u64(), i) + } + + fn const_usize(&self, i: u64) -> RValue<'gcc> { + let bit_size = self.data_layout().pointer_size.bits(); + if bit_size < 64 { + // make sure it doesn't overflow + assert!(i < (1 << bit_size)); + } + + self.const_uint(self.usize_type, i) + } + + fn const_u8(&self, _i: u8) -> RValue<'gcc> { + unimplemented!(); + } + + fn const_real(&self, _t: Type<'gcc>, _val: f64) -> RValue<'gcc> { + unimplemented!(); + } + + fn const_str(&self, s: Symbol) -> (RValue<'gcc>, RValue<'gcc>) { + let len = s.as_str().len(); + let cs = self.const_ptrcast(self.const_cstr(s, false).get_address(None), + self.type_ptr_to(self.layout_of(self.tcx.types.str_).gcc_type(self, true)), + ); + (cs, self.const_usize(len as u64)) + } + + fn const_struct(&self, values: &[RValue<'gcc>], packed: bool) -> RValue<'gcc> { + let fields: Vec<_> = values.iter() + .map(|value| value.get_type()) + .collect(); + // TODO(antoyo): cache the type? It's anonymous, so probably not. + let typ = self.type_struct(&fields, packed); + let struct_type = typ.is_struct().expect("struct type"); + self.context.new_rvalue_from_struct(None, struct_type, values) + } + + fn const_to_opt_uint(&self, _v: RValue<'gcc>) -> Option { + // TODO(antoyo) + None + } + + fn const_to_opt_u128(&self, _v: RValue<'gcc>, _sign_ext: bool) -> Option { + // TODO(antoyo) + None + } + + fn scalar_to_backend(&self, cv: Scalar, layout: abi::Scalar, ty: Type<'gcc>) -> RValue<'gcc> { + let bitsize = if layout.is_bool() { 1 } else { layout.value.size(self).bits() }; + match cv { + Scalar::Int(ScalarInt::ZST) => { + assert_eq!(0, layout.value.size(self).bytes()); + self.const_undef(self.type_ix(0)) + } + Scalar::Int(int) => { + let data = int.assert_bits(layout.value.size(self)); + + // FIXME(antoyo): there's some issues with using the u128 code that follows, so hard-code + // the paths for floating-point values. + if ty == self.float_type { + return self.context.new_rvalue_from_double(ty, f32::from_bits(data as u32) as f64); + } + else if ty == self.double_type { + return self.context.new_rvalue_from_double(ty, f64::from_bits(data as u64)); + } + + let value = self.const_uint_big(self.type_ix(bitsize), data); + if layout.value == Pointer { + self.inttoptr(self.current_block.borrow().expect("block"), value, ty) + } else { + self.const_bitcast(value, ty) + } + } + Scalar::Ptr(ptr, _size) => { + let (alloc_id, offset) = ptr.into_parts(); + let base_addr = + match self.tcx.global_alloc(alloc_id) { + GlobalAlloc::Memory(alloc) => { + let init = const_alloc_to_gcc(self, alloc); + let value = + match alloc.mutability { + Mutability::Mut => self.static_addr_of_mut(init, alloc.align, None), + _ => self.static_addr_of(init, alloc.align, None), + }; + if !self.sess().fewer_names() { + // TODO(antoyo): set value name. + } + value + }, + GlobalAlloc::Function(fn_instance) => { + self.get_fn_addr(fn_instance) + }, + GlobalAlloc::Static(def_id) => { + assert!(self.tcx.is_static(def_id)); + self.get_static(def_id).get_address(None) + }, + }; + let ptr_type = base_addr.get_type(); + let base_addr = self.const_bitcast(base_addr, self.usize_type); + let offset = self.context.new_rvalue_from_long(self.usize_type, offset.bytes() as i64); + let ptr = self.const_bitcast(base_addr + offset, ptr_type); + if layout.value != Pointer { + self.const_bitcast(ptr.dereference(None).to_rvalue(), ty) + } + else { + self.const_bitcast(ptr, ty) + } + } + } + } + + fn const_data_from_alloc(&self, alloc: &Allocation) -> Self::Value { + const_alloc_to_gcc(self, alloc) + } + + fn from_const_alloc(&self, layout: TyAndLayout<'tcx>, alloc: &Allocation, offset: Size) -> PlaceRef<'tcx, RValue<'gcc>> { + assert_eq!(alloc.align, layout.align.abi); + let ty = self.type_ptr_to(layout.gcc_type(self, true)); + let value = + if layout.size == Size::ZERO { + let value = self.const_usize(alloc.align.bytes()); + self.context.new_cast(None, value, ty) + } + else { + let init = const_alloc_to_gcc(self, alloc); + let base_addr = self.static_addr_of(init, alloc.align, None); + + let array = self.const_bitcast(base_addr, self.type_i8p()); + let value = self.context.new_array_access(None, array, self.const_usize(offset.bytes())).get_address(None); + self.const_bitcast(value, ty) + }; + PlaceRef::new_sized(value, layout) + } + + fn const_ptrcast(&self, val: RValue<'gcc>, ty: Type<'gcc>) -> RValue<'gcc> { + self.context.new_cast(None, val, ty) + } +} + +pub trait SignType<'gcc, 'tcx> { + fn is_signed(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool; + fn is_unsigned(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool; + fn to_signed(&self, cx: &CodegenCx<'gcc, 'tcx>) -> Type<'gcc>; + fn to_unsigned(&self, cx: &CodegenCx<'gcc, 'tcx>) -> Type<'gcc>; +} + +impl<'gcc, 'tcx> SignType<'gcc, 'tcx> for Type<'gcc> { + fn is_signed(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool { + self.is_i8(cx) || self.is_i16(cx) || self.is_i32(cx) || self.is_i64(cx) || self.is_i128(cx) + } + + fn is_unsigned(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool { + self.is_u8(cx) || self.is_u16(cx) || self.is_u32(cx) || self.is_u64(cx) || self.is_u128(cx) + } + + fn to_signed(&self, cx: &CodegenCx<'gcc, 'tcx>) -> Type<'gcc> { + if self.is_u8(cx) { + cx.i8_type + } + else if self.is_u16(cx) { + cx.i16_type + } + else if self.is_u32(cx) { + cx.i32_type + } + else if self.is_u64(cx) { + cx.i64_type + } + else if self.is_u128(cx) { + cx.i128_type + } + else { + self.clone() + } + } + + fn to_unsigned(&self, cx: &CodegenCx<'gcc, 'tcx>) -> Type<'gcc> { + if self.is_i8(cx) { + cx.u8_type + } + else if self.is_i16(cx) { + cx.u16_type + } + else if self.is_i32(cx) { + cx.u32_type + } + else if self.is_i64(cx) { + cx.u64_type + } + else if self.is_i128(cx) { + cx.u128_type + } + else { + self.clone() + } + } +} + +pub trait TypeReflection<'gcc, 'tcx> { + fn is_uchar(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool; + fn is_ushort(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool; + fn is_uint(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool; + fn is_ulong(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool; + fn is_ulonglong(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool; + + fn is_i8(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool; + fn is_u8(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool; + fn is_i16(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool; + fn is_u16(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool; + fn is_i32(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool; + fn is_u32(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool; + fn is_i64(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool; + fn is_u64(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool; + fn is_i128(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool; + fn is_u128(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool; + + fn is_f32(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool; + fn is_f64(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool; +} + +impl<'gcc, 'tcx> TypeReflection<'gcc, 'tcx> for Type<'gcc> { + fn is_uchar(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool { + self.unqualified() == cx.u8_type + } + + fn is_ushort(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool { + self.unqualified() == cx.u16_type + } + + fn is_uint(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool { + self.unqualified() == cx.uint_type + } + + fn is_ulong(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool { + self.unqualified() == cx.ulong_type + } + + fn is_ulonglong(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool { + self.unqualified() == cx.ulonglong_type + } + + fn is_i8(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool { + self.unqualified() == cx.i8_type + } + + fn is_u8(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool { + self.unqualified() == cx.u8_type + } + + fn is_i16(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool { + self.unqualified() == cx.i16_type + } + + fn is_u16(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool { + self.unqualified() == cx.u16_type + } + + fn is_i32(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool { + self.unqualified() == cx.i32_type + } + + fn is_u32(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool { + self.unqualified() == cx.u32_type + } + + fn is_i64(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool { + self.unqualified() == cx.i64_type + } + + fn is_u64(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool { + self.unqualified() == cx.u64_type + } + + fn is_i128(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool { + self.unqualified() == cx.context.new_c_type(CType::Int128t) + } + + fn is_u128(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool { + self.unqualified() == cx.context.new_c_type(CType::UInt128t) + } + + fn is_f32(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool { + self.unqualified() == cx.context.new_type::() + } + + fn is_f64(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool { + self.unqualified() == cx.context.new_type::() + } +} diff --git a/compiler/rustc_codegen_gcc/src/consts.rs b/compiler/rustc_codegen_gcc/src/consts.rs new file mode 100644 index 0000000000..205498acc3 --- /dev/null +++ b/compiler/rustc_codegen_gcc/src/consts.rs @@ -0,0 +1,390 @@ +use gccjit::{LValue, RValue, ToRValue, Type}; +use rustc_codegen_ssa::traits::{BaseTypeMethods, ConstMethods, DerivedTypeMethods, StaticMethods}; +use rustc_hir as hir; +use rustc_hir::Node; +use rustc_middle::{bug, span_bug}; +use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs}; +use rustc_middle::mir::mono::MonoItem; +use rustc_middle::ty::{self, Instance, Ty}; +use rustc_middle::ty::layout::LayoutOf; +use rustc_middle::mir::interpret::{self, Allocation, ErrorHandled, Scalar as InterpScalar, read_target_uint}; +use rustc_span::Span; +use rustc_span::def_id::DefId; +use rustc_target::abi::{self, Align, HasDataLayout, Primitive, Size, WrappingRange}; + +use crate::base; +use crate::context::CodegenCx; +use crate::type_of::LayoutGccExt; + +impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { + pub fn const_bitcast(&self, value: RValue<'gcc>, typ: Type<'gcc>) -> RValue<'gcc> { + if value.get_type() == self.bool_type.make_pointer() { + if let Some(pointee) = typ.get_pointee() { + if pointee.is_vector().is_some() { + panic!() + } + } + } + self.context.new_bitcast(None, value, typ) + } +} + +impl<'gcc, 'tcx> StaticMethods for CodegenCx<'gcc, 'tcx> { + fn static_addr_of(&self, cv: RValue<'gcc>, align: Align, kind: Option<&str>) -> RValue<'gcc> { + if let Some(global_value) = self.const_globals.borrow().get(&cv) { + // TODO(antoyo): upgrade alignment. + return *global_value; + } + let global_value = self.static_addr_of_mut(cv, align, kind); + // TODO(antoyo): set global constant. + self.const_globals.borrow_mut().insert(cv, global_value); + global_value + } + + fn codegen_static(&self, def_id: DefId, is_mutable: bool) { + let attrs = self.tcx.codegen_fn_attrs(def_id); + + let value = + match codegen_static_initializer(&self, def_id) { + Ok((value, _)) => value, + // Error has already been reported + Err(_) => return, + }; + + let global = self.get_static(def_id); + + // boolean SSA values are i1, but they have to be stored in i8 slots, + // otherwise some LLVM optimization passes don't work as expected + let val_llty = self.val_ty(value); + let value = + if val_llty == self.type_i1() { + unimplemented!(); + } + else { + value + }; + + let instance = Instance::mono(self.tcx, def_id); + let ty = instance.ty(self.tcx, ty::ParamEnv::reveal_all()); + let gcc_type = self.layout_of(ty).gcc_type(self, true); + + // TODO(antoyo): set alignment. + + let value = + if value.get_type() != gcc_type { + self.context.new_bitcast(None, value, gcc_type) + } + else { + value + }; + global.global_set_initializer_value(value); + + // As an optimization, all shared statics which do not have interior + // mutability are placed into read-only memory. + if !is_mutable { + if self.type_is_freeze(ty) { + // TODO(antoyo): set global constant. + } + } + + if attrs.flags.contains(CodegenFnAttrFlags::THREAD_LOCAL) { + // Do not allow LLVM to change the alignment of a TLS on macOS. + // + // By default a global's alignment can be freely increased. + // This allows LLVM to generate more performant instructions + // e.g., using load-aligned into a SIMD register. + // + // However, on macOS 10.10 or below, the dynamic linker does not + // respect any alignment given on the TLS (radar 24221680). + // This will violate the alignment assumption, and causing segfault at runtime. + // + // This bug is very easy to trigger. In `println!` and `panic!`, + // the `LOCAL_STDOUT`/`LOCAL_STDERR` handles are stored in a TLS, + // which the values would be `mem::replace`d on initialization. + // The implementation of `mem::replace` will use SIMD + // whenever the size is 32 bytes or higher. LLVM notices SIMD is used + // and tries to align `LOCAL_STDOUT`/`LOCAL_STDERR` to a 32-byte boundary, + // which macOS's dyld disregarded and causing crashes + // (see issues #51794, #51758, #50867, #48866 and #44056). + // + // To workaround the bug, we trick LLVM into not increasing + // the global's alignment by explicitly assigning a section to it + // (equivalent to automatically generating a `#[link_section]` attribute). + // See the comment in the `GlobalValue::canIncreaseAlignment()` function + // of `lib/IR/Globals.cpp` for why this works. + // + // When the alignment is not increased, the optimized `mem::replace` + // will use load-unaligned instructions instead, and thus avoiding the crash. + // + // We could remove this hack whenever we decide to drop macOS 10.10 support. + if self.tcx.sess.target.options.is_like_osx { + // The `inspect` method is okay here because we checked relocations, and + // because we are doing this access to inspect the final interpreter state + // (not as part of the interpreter execution). + // + // FIXME: This check requires that the (arbitrary) value of undefined bytes + // happens to be zero. Instead, we should only check the value of defined bytes + // and set all undefined bytes to zero if this allocation is headed for the + // BSS. + unimplemented!(); + } + } + + // Wasm statics with custom link sections get special treatment as they + // go into custom sections of the wasm executable. + if self.tcx.sess.opts.target_triple.triple().starts_with("wasm32") { + if let Some(_section) = attrs.link_section { + unimplemented!(); + } + } else { + // TODO(antoyo): set link section. + } + + if attrs.flags.contains(CodegenFnAttrFlags::USED) { + self.add_used_global(global.to_rvalue()); + } + } + + /// Add a global value to a list to be stored in the `llvm.used` variable, an array of i8*. + fn add_used_global(&self, _global: RValue<'gcc>) { + // TODO(antoyo) + } + + fn add_compiler_used_global(&self, _global: RValue<'gcc>) { + // TODO(antoyo) + } +} + +impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { + pub fn static_addr_of_mut(&self, cv: RValue<'gcc>, align: Align, kind: Option<&str>) -> RValue<'gcc> { + let global = + match kind { + Some(kind) if !self.tcx.sess.fewer_names() => { + let name = self.generate_local_symbol_name(kind); + // TODO(antoyo): check if it's okay that TLS is off here. + // TODO(antoyo): check if it's okay that link_section is None here. + // TODO(antoyo): set alignment here as well. + let global = self.define_global(&name[..], self.val_ty(cv), false, None); + // TODO(antoyo): set linkage. + global + } + _ => { + let typ = self.val_ty(cv).get_aligned(align.bytes()); + let global = self.declare_unnamed_global(typ); + global + }, + }; + // FIXME(antoyo): I think the name coming from generate_local_symbol_name() above cannot be used + // globally. + global.global_set_initializer_value(cv); + // TODO(antoyo): set unnamed address. + global.get_address(None) + } + + pub fn get_static(&self, def_id: DefId) -> LValue<'gcc> { + let instance = Instance::mono(self.tcx, def_id); + let fn_attrs = self.tcx.codegen_fn_attrs(def_id); + if let Some(&global) = self.instances.borrow().get(&instance) { + return global; + } + + let defined_in_current_codegen_unit = + self.codegen_unit.items().contains_key(&MonoItem::Static(def_id)); + assert!( + !defined_in_current_codegen_unit, + "consts::get_static() should always hit the cache for \ + statics defined in the same CGU, but did not for `{:?}`", + def_id + ); + + let ty = instance.ty(self.tcx, ty::ParamEnv::reveal_all()); + let sym = self.tcx.symbol_name(instance).name; + + let global = + if let Some(def_id) = def_id.as_local() { + let id = self.tcx.hir().local_def_id_to_hir_id(def_id); + let llty = self.layout_of(ty).gcc_type(self, true); + // FIXME: refactor this to work without accessing the HIR + let global = match self.tcx.hir().get(id) { + Node::Item(&hir::Item { span, kind: hir::ItemKind::Static(..), .. }) => { + if let Some(global) = self.get_declared_value(&sym) { + if self.val_ty(global) != self.type_ptr_to(llty) { + span_bug!(span, "Conflicting types for static"); + } + } + + let is_tls = fn_attrs.flags.contains(CodegenFnAttrFlags::THREAD_LOCAL); + let global = self.declare_global(&sym, llty, is_tls, fn_attrs.link_section); + + if !self.tcx.is_reachable_non_generic(def_id) { + // TODO(antoyo): set visibility. + } + + global + } + + Node::ForeignItem(&hir::ForeignItem { + span, + kind: hir::ForeignItemKind::Static(..), + .. + }) => { + let fn_attrs = self.tcx.codegen_fn_attrs(def_id); + check_and_apply_linkage(&self, &fn_attrs, ty, sym, span) + } + + item => bug!("get_static: expected static, found {:?}", item), + }; + + global + } + else { + // FIXME(nagisa): perhaps the map of externs could be offloaded to llvm somehow? + //debug!("get_static: sym={} item_attr={:?}", sym, self.tcx.item_attrs(def_id)); + + let attrs = self.tcx.codegen_fn_attrs(def_id); + let span = self.tcx.def_span(def_id); + let global = check_and_apply_linkage(&self, &attrs, ty, sym, span); + + let needs_dll_storage_attr = false; // TODO(antoyo) + + // If this assertion triggers, there's something wrong with commandline + // argument validation. + debug_assert!( + !(self.tcx.sess.opts.cg.linker_plugin_lto.enabled() + && self.tcx.sess.target.options.is_like_msvc + && self.tcx.sess.opts.cg.prefer_dynamic) + ); + + if needs_dll_storage_attr { + // This item is external but not foreign, i.e., it originates from an external Rust + // crate. Since we don't know whether this crate will be linked dynamically or + // statically in the final application, we always mark such symbols as 'dllimport'. + // If final linkage happens to be static, we rely on compiler-emitted __imp_ stubs + // to make things work. + // + // However, in some scenarios we defer emission of statics to downstream + // crates, so there are cases where a static with an upstream DefId + // is actually present in the current crate. We can find out via the + // is_codegened_item query. + if !self.tcx.is_codegened_item(def_id) { + unimplemented!(); + } + } + global + }; + + // TODO(antoyo): set dll storage class. + + self.instances.borrow_mut().insert(instance, global); + global + } +} + +pub fn const_alloc_to_gcc<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, alloc: &Allocation) -> RValue<'gcc> { + let mut llvals = Vec::with_capacity(alloc.relocations().len() + 1); + let dl = cx.data_layout(); + let pointer_size = dl.pointer_size.bytes() as usize; + + let mut next_offset = 0; + for &(offset, alloc_id) in alloc.relocations().iter() { + let offset = offset.bytes(); + assert_eq!(offset as usize as u64, offset); + let offset = offset as usize; + if offset > next_offset { + // This `inspect` is okay since we have checked that it is not within a relocation, it + // is within the bounds of the allocation, and it doesn't affect interpreter execution + // (we inspect the result after interpreter execution). Any undef byte is replaced with + // some arbitrary byte value. + // + // FIXME: relay undef bytes to codegen as undef const bytes + let bytes = alloc.inspect_with_uninit_and_ptr_outside_interpreter(next_offset..offset); + llvals.push(cx.const_bytes(bytes)); + } + let ptr_offset = + read_target_uint( dl.endian, + // This `inspect` is okay since it is within the bounds of the allocation, it doesn't + // affect interpreter execution (we inspect the result after interpreter execution), + // and we properly interpret the relocation as a relocation pointer offset. + alloc.inspect_with_uninit_and_ptr_outside_interpreter(offset..(offset + pointer_size)), + ) + .expect("const_alloc_to_llvm: could not read relocation pointer") + as u64; + llvals.push(cx.scalar_to_backend( + InterpScalar::from_pointer( + interpret::Pointer::new(alloc_id, Size::from_bytes(ptr_offset)), + &cx.tcx, + ), + abi::Scalar { value: Primitive::Pointer, valid_range: WrappingRange { start: 0, end: !0 } }, + cx.type_i8p(), + )); + next_offset = offset + pointer_size; + } + if alloc.len() >= next_offset { + let range = next_offset..alloc.len(); + // This `inspect` is okay since we have check that it is after all relocations, it is + // within the bounds of the allocation, and it doesn't affect interpreter execution (we + // inspect the result after interpreter execution). Any undef byte is replaced with some + // arbitrary byte value. + // + // FIXME: relay undef bytes to codegen as undef const bytes + let bytes = alloc.inspect_with_uninit_and_ptr_outside_interpreter(range); + llvals.push(cx.const_bytes(bytes)); + } + + cx.const_struct(&llvals, true) +} + +pub fn codegen_static_initializer<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, def_id: DefId) -> Result<(RValue<'gcc>, &'tcx Allocation), ErrorHandled> { + let alloc = cx.tcx.eval_static_initializer(def_id)?; + Ok((const_alloc_to_gcc(cx, alloc), alloc)) +} + +fn check_and_apply_linkage<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, attrs: &CodegenFnAttrs, ty: Ty<'tcx>, sym: &str, span: Span) -> LValue<'gcc> { + let is_tls = attrs.flags.contains(CodegenFnAttrFlags::THREAD_LOCAL); + let llty = cx.layout_of(ty).gcc_type(cx, true); + if let Some(linkage) = attrs.linkage { + // If this is a static with a linkage specified, then we need to handle + // it a little specially. The typesystem prevents things like &T and + // extern "C" fn() from being non-null, so we can't just declare a + // static and call it a day. Some linkages (like weak) will make it such + // that the static actually has a null value. + let llty2 = + if let ty::RawPtr(ref mt) = ty.kind() { + cx.layout_of(mt.ty).gcc_type(cx, true) + } + else { + cx.sess().span_fatal( + span, + "must have type `*const T` or `*mut T` due to `#[linkage]` attribute", + ) + }; + // Declare a symbol `foo` with the desired linkage. + let global1 = cx.declare_global_with_linkage(&sym, llty2, base::global_linkage_to_gcc(linkage)); + + // Declare an internal global `extern_with_linkage_foo` which + // is initialized with the address of `foo`. If `foo` is + // discarded during linking (for example, if `foo` has weak + // linkage and there are no definitions), then + // `extern_with_linkage_foo` will instead be initialized to + // zero. + let mut real_name = "_rust_extern_with_linkage_".to_string(); + real_name.push_str(&sym); + let global2 = cx.define_global(&real_name, llty, is_tls, attrs.link_section); + // TODO(antoyo): set linkage. + global2.global_set_initializer_value(global1.get_address(None)); + // TODO(antoyo): use global_set_initializer() when it will work. + global2 + } + else { + // Generate an external declaration. + // FIXME(nagisa): investigate whether it can be changed into define_global + + // Thread-local statics in some other crate need to *always* be linked + // against in a thread-local fashion, so we need to be sure to apply the + // thread-local attribute locally if it was present remotely. If we + // don't do this then linker errors can be generated where the linker + // complains that one object files has a thread local version of the + // symbol and another one doesn't. + cx.declare_global(&sym, llty, is_tls, attrs.link_section) + } +} diff --git a/compiler/rustc_codegen_gcc/src/context.rs b/compiler/rustc_codegen_gcc/src/context.rs new file mode 100644 index 0000000000..7677ade731 --- /dev/null +++ b/compiler/rustc_codegen_gcc/src/context.rs @@ -0,0 +1,475 @@ +use std::cell::{Cell, RefCell}; + +use gccjit::{ + Block, + Context, + CType, + Function, + FunctionType, + LValue, + RValue, + Struct, + Type, +}; +use rustc_codegen_ssa::base::wants_msvc_seh; +use rustc_codegen_ssa::traits::{ + BackendTypes, + MiscMethods, +}; +use rustc_data_structures::base_n; +use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_middle::span_bug; +use rustc_middle::mir::mono::CodegenUnit; +use rustc_middle::ty::{self, Instance, ParamEnv, PolyExistentialTraitRef, Ty, TyCtxt}; +use rustc_middle::ty::layout::{FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasParamEnv, HasTyCtxt, LayoutError, TyAndLayout, LayoutOfHelpers}; +use rustc_session::Session; +use rustc_span::{Span, Symbol}; +use rustc_target::abi::{call::FnAbi, HasDataLayout, PointeeInfo, Size, TargetDataLayout, VariantIdx}; +use rustc_target::spec::{HasTargetSpec, Target, TlsModel}; + +use crate::callee::get_fn; +use crate::declare::mangle_name; + +#[derive(Clone)] +pub struct FuncSig<'gcc> { + pub params: Vec>, + pub return_type: Type<'gcc>, +} + +pub struct CodegenCx<'gcc, 'tcx> { + pub check_overflow: bool, + pub codegen_unit: &'tcx CodegenUnit<'tcx>, + pub context: &'gcc Context<'gcc>, + + // TODO(antoyo): First set it to a dummy block to avoid using Option? + pub current_block: RefCell>>, + pub current_func: RefCell>>, + pub normal_function_addresses: RefCell>>, + + pub functions: RefCell>>, + + pub tls_model: gccjit::TlsModel, + + pub bool_type: Type<'gcc>, + pub i8_type: Type<'gcc>, + pub i16_type: Type<'gcc>, + pub i32_type: Type<'gcc>, + pub i64_type: Type<'gcc>, + pub i128_type: Type<'gcc>, + pub isize_type: Type<'gcc>, + + pub u8_type: Type<'gcc>, + pub u16_type: Type<'gcc>, + pub u32_type: Type<'gcc>, + pub u64_type: Type<'gcc>, + pub u128_type: Type<'gcc>, + pub usize_type: Type<'gcc>, + + pub int_type: Type<'gcc>, + pub uint_type: Type<'gcc>, + pub long_type: Type<'gcc>, + pub ulong_type: Type<'gcc>, + pub ulonglong_type: Type<'gcc>, + pub sizet_type: Type<'gcc>, + + pub float_type: Type<'gcc>, + pub double_type: Type<'gcc>, + + pub linkage: Cell, + pub scalar_types: RefCell, Type<'gcc>>>, + pub types: RefCell, Option), Type<'gcc>>>, + pub tcx: TyCtxt<'tcx>, + + pub struct_types: RefCell>, Type<'gcc>>>, + + pub types_with_fields_to_set: RefCell, (Struct<'gcc>, TyAndLayout<'tcx>)>>, + + /// Cache instances of monomorphic and polymorphic items + pub instances: RefCell, LValue<'gcc>>>, + /// Cache function instances of monomorphic and polymorphic items + pub function_instances: RefCell, RValue<'gcc>>>, + /// Cache generated vtables + pub vtables: RefCell, Option>), RValue<'gcc>>>, + + /// Cache of emitted const globals (value -> global) + pub const_globals: RefCell, RValue<'gcc>>>, + + /// Cache of constant strings, + pub const_cstr_cache: RefCell>>, + + /// Cache of globals. + pub globals: RefCell>>, + + /// A counter that is used for generating local symbol names + local_gen_sym_counter: Cell, + pub global_gen_sym_counter: Cell, + + eh_personality: Cell>>, + + pub pointee_infos: RefCell, Size), Option>>, + + /// NOTE: a hack is used because the rustc API is not suitable to libgccjit and as such, + /// `const_undef()` returns struct as pointer so that they can later be assigned a value. + /// As such, this set remembers which of these pointers were returned by this function so that + /// they can be deferenced later. + /// FIXME(antoyo): fix the rustc API to avoid having this hack. + pub structs_as_pointer: RefCell>>, +} + +impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { + pub fn new(context: &'gcc Context<'gcc>, codegen_unit: &'tcx CodegenUnit<'tcx>, tcx: TyCtxt<'tcx>) -> Self { + let check_overflow = tcx.sess.overflow_checks(); + // TODO(antoyo): fix this mess. libgccjit seems to return random type when using new_int_type(). + let isize_type = context.new_c_type(CType::LongLong); + let usize_type = context.new_c_type(CType::ULongLong); + let bool_type = context.new_type::(); + let i8_type = context.new_type::(); + let i16_type = context.new_type::(); + let i32_type = context.new_type::(); + let i64_type = context.new_c_type(CType::LongLong); + let i128_type = context.new_c_type(CType::Int128t).get_aligned(8); // TODO(antoyo): should the alignment be hard-coded? + let u8_type = context.new_type::(); + let u16_type = context.new_type::(); + let u32_type = context.new_type::(); + let u64_type = context.new_c_type(CType::ULongLong); + let u128_type = context.new_c_type(CType::UInt128t).get_aligned(8); // TODO(antoyo): should the alignment be hard-coded? + + let tls_model = to_gcc_tls_mode(tcx.sess.tls_model()); + + let float_type = context.new_type::(); + let double_type = context.new_type::(); + + let int_type = context.new_c_type(CType::Int); + let uint_type = context.new_c_type(CType::UInt); + let long_type = context.new_c_type(CType::Long); + let ulong_type = context.new_c_type(CType::ULong); + let ulonglong_type = context.new_c_type(CType::ULongLong); + let sizet_type = context.new_c_type(CType::SizeT); + + assert_eq!(isize_type, i64_type); + assert_eq!(usize_type, u64_type); + + let mut functions = FxHashMap::default(); + let builtins = [ + "__builtin_unreachable", "abort", "__builtin_expect", "__builtin_add_overflow", "__builtin_mul_overflow", + "__builtin_saddll_overflow", /*"__builtin_sadd_overflow",*/ "__builtin_smulll_overflow", /*"__builtin_smul_overflow",*/ + "__builtin_ssubll_overflow", /*"__builtin_ssub_overflow",*/ "__builtin_sub_overflow", "__builtin_uaddll_overflow", + "__builtin_uadd_overflow", "__builtin_umulll_overflow", "__builtin_umul_overflow", "__builtin_usubll_overflow", + "__builtin_usub_overflow", "sqrtf", "sqrt", "__builtin_powif", "__builtin_powi", "sinf", "sin", "cosf", "cos", + "powf", "pow", "expf", "exp", "exp2f", "exp2", "logf", "log", "log10f", "log10", "log2f", "log2", "fmaf", + "fma", "fabsf", "fabs", "fminf", "fmin", "fmaxf", "fmax", "copysignf", "copysign", "floorf", "floor", "ceilf", + "ceil", "truncf", "trunc", "rintf", "rint", "nearbyintf", "nearbyint", "roundf", "round", + "__builtin_expect_with_probability", + ]; + + for builtin in builtins.iter() { + functions.insert(builtin.to_string(), context.get_builtin_function(builtin)); + } + + Self { + check_overflow, + codegen_unit, + context, + current_block: RefCell::new(None), + current_func: RefCell::new(None), + normal_function_addresses: Default::default(), + functions: RefCell::new(functions), + + tls_model, + + bool_type, + i8_type, + i16_type, + i32_type, + i64_type, + i128_type, + isize_type, + usize_type, + u8_type, + u16_type, + u32_type, + u64_type, + u128_type, + int_type, + uint_type, + long_type, + ulong_type, + ulonglong_type, + sizet_type, + + float_type, + double_type, + + linkage: Cell::new(FunctionType::Internal), + instances: Default::default(), + function_instances: Default::default(), + vtables: Default::default(), + const_globals: Default::default(), + const_cstr_cache: Default::default(), + globals: Default::default(), + scalar_types: Default::default(), + types: Default::default(), + tcx, + struct_types: Default::default(), + types_with_fields_to_set: Default::default(), + local_gen_sym_counter: Cell::new(0), + global_gen_sym_counter: Cell::new(0), + eh_personality: Cell::new(None), + pointee_infos: Default::default(), + structs_as_pointer: Default::default(), + } + } + + pub fn rvalue_as_function(&self, value: RValue<'gcc>) -> Function<'gcc> { + let function: Function<'gcc> = unsafe { std::mem::transmute(value) }; + debug_assert!(self.functions.borrow().values().find(|value| **value == function).is_some(), + "{:?} ({:?}) is not a function", value, value.get_type()); + function + } + + pub fn sess(&self) -> &Session { + &self.tcx.sess + } +} + +impl<'gcc, 'tcx> BackendTypes for CodegenCx<'gcc, 'tcx> { + type Value = RValue<'gcc>; + type Function = RValue<'gcc>; + + type BasicBlock = Block<'gcc>; + type Type = Type<'gcc>; + type Funclet = (); // TODO(antoyo) + + type DIScope = (); // TODO(antoyo) + type DILocation = (); // TODO(antoyo) + type DIVariable = (); // TODO(antoyo) +} + +impl<'gcc, 'tcx> MiscMethods<'tcx> for CodegenCx<'gcc, 'tcx> { + fn vtables(&self) -> &RefCell, Option>), RValue<'gcc>>> { + &self.vtables + } + + fn get_fn(&self, instance: Instance<'tcx>) -> RValue<'gcc> { + let func = get_fn(self, instance); + *self.current_func.borrow_mut() = Some(self.rvalue_as_function(func)); + func + } + + fn get_fn_addr(&self, instance: Instance<'tcx>) -> RValue<'gcc> { + let func = get_fn(self, instance); + let func = self.rvalue_as_function(func); + let ptr = func.get_address(None); + + // TODO(antoyo): don't do this twice: i.e. in declare_fn and here. + // FIXME(antoyo): the rustc API seems to call get_fn_addr() when not needed (e.g. for FFI). + + self.normal_function_addresses.borrow_mut().insert(ptr); + + ptr + } + + fn eh_personality(&self) -> RValue<'gcc> { + // The exception handling personality function. + // + // If our compilation unit has the `eh_personality` lang item somewhere + // within it, then we just need to codegen that. Otherwise, we're + // building an rlib which will depend on some upstream implementation of + // this function, so we just codegen a generic reference to it. We don't + // specify any of the types for the function, we just make it a symbol + // that LLVM can later use. + // + // Note that MSVC is a little special here in that we don't use the + // `eh_personality` lang item at all. Currently LLVM has support for + // both Dwarf and SEH unwind mechanisms for MSVC targets and uses the + // *name of the personality function* to decide what kind of unwind side + // tables/landing pads to emit. It looks like Dwarf is used by default, + // injecting a dependency on the `_Unwind_Resume` symbol for resuming + // an "exception", but for MSVC we want to force SEH. This means that we + // can't actually have the personality function be our standard + // `rust_eh_personality` function, but rather we wired it up to the + // CRT's custom personality function, which forces LLVM to consider + // landing pads as "landing pads for SEH". + if let Some(llpersonality) = self.eh_personality.get() { + return llpersonality; + } + let tcx = self.tcx; + let llfn = match tcx.lang_items().eh_personality() { + Some(def_id) if !wants_msvc_seh(self.sess()) => self.get_fn_addr( + ty::Instance::resolve( + tcx, + ty::ParamEnv::reveal_all(), + def_id, + tcx.intern_substs(&[]), + ) + .unwrap().unwrap(), + ), + _ => { + let _name = if wants_msvc_seh(self.sess()) { + "__CxxFrameHandler3" + } else { + "rust_eh_personality" + }; + //let func = self.declare_func(name, self.type_i32(), &[], true); + // FIXME(antoyo): this hack should not be needed. That will probably be removed when + // unwinding support is added. + self.context.new_rvalue_from_int(self.int_type, 0) + } + }; + // TODO(antoyo): apply target cpu attributes. + self.eh_personality.set(Some(llfn)); + llfn + } + + fn sess(&self) -> &Session { + &self.tcx.sess + } + + fn check_overflow(&self) -> bool { + self.check_overflow + } + + fn codegen_unit(&self) -> &'tcx CodegenUnit<'tcx> { + self.codegen_unit + } + + fn used_statics(&self) -> &RefCell>> { + unimplemented!(); + } + + fn set_frame_pointer_type(&self, _llfn: RValue<'gcc>) { + // TODO(antoyo) + } + + fn apply_target_cpu_attr(&self, _llfn: RValue<'gcc>) { + // TODO(antoyo) + } + + fn create_used_variable(&self) { + unimplemented!(); + } + + fn declare_c_main(&self, fn_type: Self::Type) -> Option { + if self.get_declared_value("main").is_none() { + Some(self.declare_cfn("main", fn_type)) + } + else { + // If the symbol already exists, it is an error: for example, the user wrote + // #[no_mangle] extern "C" fn main(..) {..} + // instead of #[start] + None + } + } + + fn compiler_used_statics(&self) -> &RefCell>> { + unimplemented!() + } + + fn create_compiler_used_variable(&self) { + unimplemented!() + } +} + +impl<'gcc, 'tcx> HasTyCtxt<'tcx> for CodegenCx<'gcc, 'tcx> { + fn tcx(&self) -> TyCtxt<'tcx> { + self.tcx + } +} + +impl<'gcc, 'tcx> HasDataLayout for CodegenCx<'gcc, 'tcx> { + fn data_layout(&self) -> &TargetDataLayout { + &self.tcx.data_layout + } +} + +impl<'gcc, 'tcx> HasTargetSpec for CodegenCx<'gcc, 'tcx> { + fn target_spec(&self) -> &Target { + &self.tcx.sess.target + } +} + +impl<'gcc, 'tcx> LayoutOfHelpers<'tcx> for CodegenCx<'gcc, 'tcx> { + type LayoutOfResult = TyAndLayout<'tcx>; + + #[inline] + fn handle_layout_err(&self, err: LayoutError<'tcx>, span: Span, ty: Ty<'tcx>) -> ! { + if let LayoutError::SizeOverflow(_) = err { + self.sess().span_fatal(span, &err.to_string()) + } else { + span_bug!(span, "failed to get layout for `{}`: {}", ty, err) + } + } +} + +impl<'gcc, 'tcx> FnAbiOfHelpers<'tcx> for CodegenCx<'gcc, 'tcx> { + type FnAbiOfResult = &'tcx FnAbi<'tcx, Ty<'tcx>>; + + #[inline] + fn handle_fn_abi_err( + &self, + err: FnAbiError<'tcx>, + span: Span, + fn_abi_request: FnAbiRequest<'tcx>, + ) -> ! { + if let FnAbiError::Layout(LayoutError::SizeOverflow(_)) = err { + self.sess().span_fatal(span, &err.to_string()) + } else { + match fn_abi_request { + FnAbiRequest::OfFnPtr { sig, extra_args } => { + span_bug!( + span, + "`fn_abi_of_fn_ptr({}, {:?})` failed: {}", + sig, + extra_args, + err + ); + } + FnAbiRequest::OfInstance { instance, extra_args } => { + span_bug!( + span, + "`fn_abi_of_instance({}, {:?})` failed: {}", + instance, + extra_args, + err + ); + } + } + } + } +} + +impl<'tcx, 'gcc> HasParamEnv<'tcx> for CodegenCx<'gcc, 'tcx> { + fn param_env(&self) -> ParamEnv<'tcx> { + ParamEnv::reveal_all() + } +} + +impl<'b, 'tcx> CodegenCx<'b, 'tcx> { + /// Generates a new symbol name with the given prefix. This symbol name must + /// only be used for definitions with `internal` or `private` linkage. + pub fn generate_local_symbol_name(&self, prefix: &str) -> String { + let idx = self.local_gen_sym_counter.get(); + self.local_gen_sym_counter.set(idx + 1); + // Include a '.' character, so there can be no accidental conflicts with + // user defined names + let mut name = String::with_capacity(prefix.len() + 6); + name.push_str(prefix); + name.push_str("."); + base_n::push_str(idx as u128, base_n::ALPHANUMERIC_ONLY, &mut name); + name + } +} + +pub fn unit_name<'tcx>(codegen_unit: &CodegenUnit<'tcx>) -> String { + let name = &codegen_unit.name().to_string(); + mangle_name(&name.replace('-', "_")) +} + +fn to_gcc_tls_mode(tls_model: TlsModel) -> gccjit::TlsModel { + match tls_model { + TlsModel::GeneralDynamic => gccjit::TlsModel::GlobalDynamic, + TlsModel::LocalDynamic => gccjit::TlsModel::LocalDynamic, + TlsModel::InitialExec => gccjit::TlsModel::InitialExec, + TlsModel::LocalExec => gccjit::TlsModel::LocalExec, + } +} diff --git a/compiler/rustc_codegen_gcc/src/coverageinfo.rs b/compiler/rustc_codegen_gcc/src/coverageinfo.rs new file mode 100644 index 0000000000..872fc2472e --- /dev/null +++ b/compiler/rustc_codegen_gcc/src/coverageinfo.rs @@ -0,0 +1,69 @@ +use gccjit::RValue; +use rustc_codegen_ssa::traits::{CoverageInfoBuilderMethods, CoverageInfoMethods}; +use rustc_hir::def_id::DefId; +use rustc_middle::mir::coverage::{ + CodeRegion, + CounterValueReference, + ExpressionOperandId, + InjectedExpressionId, + Op, +}; +use rustc_middle::ty::Instance; + +use crate::builder::Builder; +use crate::context::CodegenCx; + +impl<'a, 'gcc, 'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { + fn set_function_source_hash( + &mut self, + _instance: Instance<'tcx>, + _function_source_hash: u64, + ) -> bool { + unimplemented!(); + } + + fn add_coverage_counter(&mut self, _instance: Instance<'tcx>, _id: CounterValueReference, _region: CodeRegion) -> bool { + // TODO(antoyo) + false + } + + fn add_coverage_counter_expression(&mut self, _instance: Instance<'tcx>, _id: InjectedExpressionId, _lhs: ExpressionOperandId, _op: Op, _rhs: ExpressionOperandId, _region: Option) -> bool { + // TODO(antoyo) + false + } + + fn add_coverage_unreachable(&mut self, _instance: Instance<'tcx>, _region: CodeRegion) -> bool { + // TODO(antoyo) + false + } +} + +impl<'gcc, 'tcx> CoverageInfoMethods<'tcx> for CodegenCx<'gcc, 'tcx> { + fn coverageinfo_finalize(&self) { + // TODO(antoyo) + } + + fn get_pgo_func_name_var(&self, _instance: Instance<'tcx>) -> RValue<'gcc> { + unimplemented!(); + } + + /// Functions with MIR-based coverage are normally codegenned _only_ if + /// called. LLVM coverage tools typically expect every function to be + /// defined (even if unused), with at least one call to LLVM intrinsic + /// `instrprof.increment`. + /// + /// Codegen a small function that will never be called, with one counter + /// that will never be incremented. + /// + /// For used/called functions, the coverageinfo was already added to the + /// `function_coverage_map` (keyed by function `Instance`) during codegen. + /// But in this case, since the unused function was _not_ previously + /// codegenned, collect the coverage `CodeRegion`s from the MIR and add + /// them. The first `CodeRegion` is used to add a single counter, with the + /// same counter ID used in the injected `instrprof.increment` intrinsic + /// call. Since the function is never called, all other `CodeRegion`s can be + /// added as `unreachable_region`s. + fn define_unused_fn(&self, _def_id: DefId) { + unimplemented!(); + } +} diff --git a/compiler/rustc_codegen_gcc/src/debuginfo.rs b/compiler/rustc_codegen_gcc/src/debuginfo.rs new file mode 100644 index 0000000000..31959fa19c --- /dev/null +++ b/compiler/rustc_codegen_gcc/src/debuginfo.rs @@ -0,0 +1,62 @@ +use gccjit::RValue; +use rustc_codegen_ssa::mir::debuginfo::{FunctionDebugContext, VariableKind}; +use rustc_codegen_ssa::traits::{DebugInfoBuilderMethods, DebugInfoMethods}; +use rustc_middle::mir; +use rustc_middle::ty::{Instance, PolyExistentialTraitRef, Ty}; +use rustc_span::{SourceFile, Span, Symbol}; +use rustc_target::abi::Size; +use rustc_target::abi::call::FnAbi; + +use crate::builder::Builder; +use crate::context::CodegenCx; + +impl<'a, 'gcc, 'tcx> DebugInfoBuilderMethods for Builder<'a, 'gcc, 'tcx> { + // FIXME(eddyb) find a common convention for all of the debuginfo-related + // names (choose between `dbg`, `debug`, `debuginfo`, `debug_info` etc.). + fn dbg_var_addr(&mut self, _dbg_var: Self::DIVariable, _scope_metadata: Self::DIScope, _variable_alloca: Self::Value, _direct_offset: Size, _indirect_offsets: &[Size]) { + unimplemented!(); + } + + fn insert_reference_to_gdb_debug_scripts_section_global(&mut self) { + // TODO(antoyo): insert reference to gdb debug scripts section global. + } + + fn set_var_name(&mut self, _value: RValue<'gcc>, _name: &str) { + unimplemented!(); + } + + fn set_dbg_loc(&mut self, _dbg_loc: Self::DILocation) { + unimplemented!(); + } +} + +impl<'gcc, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'gcc, 'tcx> { + fn create_vtable_metadata(&self, _ty: Ty<'tcx>, _trait_ref: Option>, _vtable: Self::Value) { + // TODO(antoyo) + } + + fn create_function_debug_context(&self, _instance: Instance<'tcx>, _fn_abi: &FnAbi<'tcx, Ty<'tcx>>, _llfn: RValue<'gcc>, _mir: &mir::Body<'tcx>) -> Option> { + // TODO(antoyo) + None + } + + fn extend_scope_to_file(&self, _scope_metadata: Self::DIScope, _file: &SourceFile) -> Self::DIScope { + unimplemented!(); + } + + fn debuginfo_finalize(&self) { + // TODO(antoyo) + } + + fn create_dbg_var(&self, _variable_name: Symbol, _variable_type: Ty<'tcx>, _scope_metadata: Self::DIScope, _variable_kind: VariableKind, _span: Span) -> Self::DIVariable { + unimplemented!(); + } + + fn dbg_scope_fn(&self, _instance: Instance<'tcx>, _fn_abi: &FnAbi<'tcx, Ty<'tcx>>, _maybe_definition_llfn: Option>) -> Self::DIScope { + unimplemented!(); + } + + fn dbg_loc(&self, _scope: Self::DIScope, _inlined_at: Option, _span: Span) -> Self::DILocation { + unimplemented!(); + } +} diff --git a/compiler/rustc_codegen_gcc/src/declare.rs b/compiler/rustc_codegen_gcc/src/declare.rs new file mode 100644 index 0000000000..b79a50d1ee --- /dev/null +++ b/compiler/rustc_codegen_gcc/src/declare.rs @@ -0,0 +1,144 @@ +use gccjit::{Function, FunctionType, GlobalKind, LValue, RValue, Type}; +use rustc_codegen_ssa::traits::BaseTypeMethods; +use rustc_middle::ty::Ty; +use rustc_span::Symbol; +use rustc_target::abi::call::FnAbi; + +use crate::abi::FnAbiGccExt; +use crate::context::{CodegenCx, unit_name}; +use crate::intrinsic::llvm; + +impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { + pub fn get_or_insert_global(&self, name: &str, ty: Type<'gcc>, is_tls: bool, link_section: Option) -> LValue<'gcc> { + if self.globals.borrow().contains_key(name) { + let typ = self.globals.borrow().get(name).expect("global").get_type(); + let global = self.context.new_global(None, GlobalKind::Imported, typ, name); + if is_tls { + global.set_tls_model(self.tls_model); + } + if let Some(link_section) = link_section { + global.set_link_section(&link_section.as_str()); + } + global + } + else { + self.declare_global(name, ty, is_tls, link_section) + } + } + + pub fn declare_unnamed_global(&self, ty: Type<'gcc>) -> LValue<'gcc> { + let index = self.global_gen_sym_counter.get(); + self.global_gen_sym_counter.set(index + 1); + let name = format!("global_{}_{}", index, unit_name(&self.codegen_unit)); + self.context.new_global(None, GlobalKind::Exported, ty, &name) + } + + pub fn declare_global_with_linkage(&self, name: &str, ty: Type<'gcc>, linkage: GlobalKind) -> LValue<'gcc> { + let global = self.context.new_global(None, linkage, ty, name); + let global_address = global.get_address(None); + self.globals.borrow_mut().insert(name.to_string(), global_address); + global + } + + /*pub fn declare_func(&self, name: &str, return_type: Type<'gcc>, params: &[Type<'gcc>], variadic: bool) -> RValue<'gcc> { + self.linkage.set(FunctionType::Exported); + let func = declare_raw_fn(self, name, () /*llvm::CCallConv*/, return_type, params, variadic); + // FIXME(antoyo): this is a wrong cast. That requires changing the compiler API. + unsafe { std::mem::transmute(func) } + }*/ + + pub fn declare_global(&self, name: &str, ty: Type<'gcc>, is_tls: bool, link_section: Option) -> LValue<'gcc> { + let global = self.context.new_global(None, GlobalKind::Exported, ty, name); + if is_tls { + global.set_tls_model(self.tls_model); + } + if let Some(link_section) = link_section { + global.set_link_section(&link_section.as_str()); + } + let global_address = global.get_address(None); + self.globals.borrow_mut().insert(name.to_string(), global_address); + global + } + + pub fn declare_private_global(&self, name: &str, ty: Type<'gcc>) -> LValue<'gcc> { + let global = self.context.new_global(None, GlobalKind::Internal, ty, name); + let global_address = global.get_address(None); + self.globals.borrow_mut().insert(name.to_string(), global_address); + global + } + + pub fn declare_cfn(&self, name: &str, _fn_type: Type<'gcc>) -> RValue<'gcc> { + // TODO(antoyo): use the fn_type parameter. + let const_string = self.context.new_type::().make_pointer().make_pointer(); + let return_type = self.type_i32(); + let variadic = false; + self.linkage.set(FunctionType::Exported); + let func = declare_raw_fn(self, name, () /*llvm::CCallConv*/, return_type, &[self.type_i32(), const_string], variadic); + // NOTE: it is needed to set the current_func here as well, because get_fn() is not called + // for the main function. + *self.current_func.borrow_mut() = Some(func); + // FIXME(antoyo): this is a wrong cast. That requires changing the compiler API. + unsafe { std::mem::transmute(func) } + } + + pub fn declare_fn(&self, name: &str, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> RValue<'gcc> { + let (return_type, params, variadic) = fn_abi.gcc_type(self); + let func = declare_raw_fn(self, name, () /*fn_abi.llvm_cconv()*/, return_type, ¶ms, variadic); + // FIXME(antoyo): this is a wrong cast. That requires changing the compiler API. + unsafe { std::mem::transmute(func) } + } + + pub fn define_global(&self, name: &str, ty: Type<'gcc>, is_tls: bool, link_section: Option) -> LValue<'gcc> { + self.get_or_insert_global(name, ty, is_tls, link_section) + } + + pub fn get_declared_value(&self, name: &str) -> Option> { + // TODO(antoyo): use a different field than globals, because this seems to return a function? + self.globals.borrow().get(name).cloned() + } +} + +/// Declare a function. +/// +/// If there’s a value with the same name already declared, the function will +/// update the declaration and return existing Value instead. +fn declare_raw_fn<'gcc>(cx: &CodegenCx<'gcc, '_>, name: &str, _callconv: () /*llvm::CallConv*/, return_type: Type<'gcc>, param_types: &[Type<'gcc>], variadic: bool) -> Function<'gcc> { + if name.starts_with("llvm.") { + return llvm::intrinsic(name, cx); + } + let func = + if cx.functions.borrow().contains_key(name) { + *cx.functions.borrow().get(name).expect("function") + } + else { + let params: Vec<_> = param_types.into_iter().enumerate() + .map(|(index, param)| cx.context.new_parameter(None, *param, &format!("param{}", index))) // TODO(antoyo): set name. + .collect(); + let func = cx.context.new_function(None, cx.linkage.get(), return_type, ¶ms, mangle_name(name), variadic); + cx.functions.borrow_mut().insert(name.to_string(), func); + func + }; + + // TODO(antoyo): set function calling convention. + // TODO(antoyo): set unnamed address. + // TODO(antoyo): set no red zone function attribute. + // TODO(antoyo): set attributes for optimisation. + // TODO(antoyo): set attributes for non lazy bind. + + // FIXME(antoyo): invalid cast. + func +} + +// FIXME(antoyo): this is a hack because libgccjit currently only supports alpha, num and _. +// Unsupported characters: `$` and `.`. +pub fn mangle_name(name: &str) -> String { + name.replace(|char: char| { + if !char.is_alphanumeric() && char != '_' { + debug_assert!("$.".contains(char), "Unsupported char in function name: {}", char); + true + } + else { + false + } + }, "_") +} diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/llvm.rs b/compiler/rustc_codegen_gcc/src/intrinsic/llvm.rs new file mode 100644 index 0000000000..b074febc52 --- /dev/null +++ b/compiler/rustc_codegen_gcc/src/intrinsic/llvm.rs @@ -0,0 +1,22 @@ +use gccjit::Function; + +use crate::context::CodegenCx; + +pub fn intrinsic<'gcc, 'tcx>(name: &str, cx: &CodegenCx<'gcc, 'tcx>) -> Function<'gcc> { + let _gcc_name = + match name { + "llvm.x86.xgetbv" => { + let gcc_name = "__builtin_trap"; + let func = cx.context.get_builtin_function(gcc_name); + cx.functions.borrow_mut().insert(gcc_name.to_string(), func); + return func; + }, + // NOTE: this doc specifies the equivalent GCC builtins: http://huonw.github.io/llvmint/llvmint/x86/index.html + "llvm.x86.sse2.cmp.pd" => "__builtin_ia32_cmppd", + "llvm.x86.sse2.movmsk.pd" => "__builtin_ia32_movmskpd", + "llvm.x86.sse2.pmovmskb.128" => "__builtin_ia32_pmovmskb128", + _ => unimplemented!("unsupported LLVM intrinsic {}", name) + }; + + unimplemented!(); +} diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs new file mode 100644 index 0000000000..375d422cb2 --- /dev/null +++ b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs @@ -0,0 +1,1067 @@ +pub mod llvm; +mod simd; + +use gccjit::{ComparisonOp, Function, RValue, ToRValue, Type, UnaryOp}; +use rustc_codegen_ssa::MemFlags; +use rustc_codegen_ssa::base::wants_msvc_seh; +use rustc_codegen_ssa::common::{IntPredicate, span_invalid_monomorphization_error}; +use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue}; +use rustc_codegen_ssa::mir::place::PlaceRef; +use rustc_codegen_ssa::traits::{ArgAbiMethods, BaseTypeMethods, BuilderMethods, ConstMethods, IntrinsicCallMethods}; +use rustc_middle::bug; +use rustc_middle::ty::{self, Instance, Ty}; +use rustc_middle::ty::layout::LayoutOf; +use rustc_span::{Span, Symbol, symbol::kw, sym}; +use rustc_target::abi::HasDataLayout; +use rustc_target::abi::call::{ArgAbi, FnAbi, PassMode}; +use rustc_target::spec::PanicStrategy; + +use crate::abi::GccType; +use crate::builder::Builder; +use crate::common::{SignType, TypeReflection}; +use crate::context::CodegenCx; +use crate::type_of::LayoutGccExt; +use crate::intrinsic::simd::generic_simd_intrinsic; + +fn get_simple_intrinsic<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, name: Symbol) -> Option> { + let gcc_name = match name { + sym::sqrtf32 => "sqrtf", + sym::sqrtf64 => "sqrt", + sym::powif32 => "__builtin_powif", + sym::powif64 => "__builtin_powi", + sym::sinf32 => "sinf", + sym::sinf64 => "sin", + sym::cosf32 => "cosf", + sym::cosf64 => "cos", + sym::powf32 => "powf", + sym::powf64 => "pow", + sym::expf32 => "expf", + sym::expf64 => "exp", + sym::exp2f32 => "exp2f", + sym::exp2f64 => "exp2", + sym::logf32 => "logf", + sym::logf64 => "log", + sym::log10f32 => "log10f", + sym::log10f64 => "log10", + sym::log2f32 => "log2f", + sym::log2f64 => "log2", + sym::fmaf32 => "fmaf", + sym::fmaf64 => "fma", + sym::fabsf32 => "fabsf", + sym::fabsf64 => "fabs", + sym::minnumf32 => "fminf", + sym::minnumf64 => "fmin", + sym::maxnumf32 => "fmaxf", + sym::maxnumf64 => "fmax", + sym::copysignf32 => "copysignf", + sym::copysignf64 => "copysign", + sym::floorf32 => "floorf", + sym::floorf64 => "floor", + sym::ceilf32 => "ceilf", + sym::ceilf64 => "ceil", + sym::truncf32 => "truncf", + sym::truncf64 => "trunc", + sym::rintf32 => "rintf", + sym::rintf64 => "rint", + sym::nearbyintf32 => "nearbyintf", + sym::nearbyintf64 => "nearbyint", + sym::roundf32 => "roundf", + sym::roundf64 => "round", + sym::abort => "abort", + _ => return None, + }; + Some(cx.context.get_builtin_function(&gcc_name)) +} + +impl<'a, 'gcc, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { + fn codegen_intrinsic_call(&mut self, instance: Instance<'tcx>, fn_abi: &FnAbi<'tcx, Ty<'tcx>>, args: &[OperandRef<'tcx, RValue<'gcc>>], llresult: RValue<'gcc>, span: Span) { + let tcx = self.tcx; + let callee_ty = instance.ty(tcx, ty::ParamEnv::reveal_all()); + + let (def_id, substs) = match *callee_ty.kind() { + ty::FnDef(def_id, substs) => (def_id, substs), + _ => bug!("expected fn item type, found {}", callee_ty), + }; + + let sig = callee_ty.fn_sig(tcx); + let sig = tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), sig); + let arg_tys = sig.inputs(); + let ret_ty = sig.output(); + let name = tcx.item_name(def_id); + let name_str = &*name.as_str(); + + let llret_ty = self.layout_of(ret_ty).gcc_type(self, true); + let result = PlaceRef::new_sized(llresult, fn_abi.ret.layout); + + let simple = get_simple_intrinsic(self, name); + let llval = + match name { + _ if simple.is_some() => { + // FIXME(antoyo): remove this cast when the API supports function. + let func = unsafe { std::mem::transmute(simple.expect("simple")) }; + self.call(self.type_void(), func, &args.iter().map(|arg| arg.immediate()).collect::>(), None) + }, + sym::likely => { + self.expect(args[0].immediate(), true) + } + sym::unlikely => { + self.expect(args[0].immediate(), false) + } + kw::Try => { + try_intrinsic( + self, + args[0].immediate(), + args[1].immediate(), + args[2].immediate(), + llresult, + ); + return; + } + sym::breakpoint => { + unimplemented!(); + } + sym::va_copy => { + unimplemented!(); + } + sym::va_arg => { + unimplemented!(); + } + + sym::volatile_load | sym::unaligned_volatile_load => { + let tp_ty = substs.type_at(0); + let mut ptr = args[0].immediate(); + if let PassMode::Cast(ty) = fn_abi.ret.mode { + ptr = self.pointercast(ptr, self.type_ptr_to(ty.gcc_type(self))); + } + let load = self.volatile_load(ptr.get_type(), ptr); + // TODO(antoyo): set alignment. + self.to_immediate(load, self.layout_of(tp_ty)) + } + sym::volatile_store => { + let dst = args[0].deref(self.cx()); + args[1].val.volatile_store(self, dst); + return; + } + sym::unaligned_volatile_store => { + let dst = args[0].deref(self.cx()); + args[1].val.unaligned_volatile_store(self, dst); + return; + } + sym::prefetch_read_data + | sym::prefetch_write_data + | sym::prefetch_read_instruction + | sym::prefetch_write_instruction => { + unimplemented!(); + } + sym::ctlz + | sym::ctlz_nonzero + | sym::cttz + | sym::cttz_nonzero + | sym::ctpop + | sym::bswap + | sym::bitreverse + | sym::rotate_left + | sym::rotate_right + | sym::saturating_add + | sym::saturating_sub => { + let ty = arg_tys[0]; + match int_type_width_signed(ty, self) { + Some((width, signed)) => match name { + sym::ctlz | sym::cttz => { + let func = self.current_func.borrow().expect("func"); + let then_block = func.new_block("then"); + let else_block = func.new_block("else"); + let after_block = func.new_block("after"); + + let arg = args[0].immediate(); + let result = func.new_local(None, arg.get_type(), "zeros"); + let zero = self.cx.context.new_rvalue_zero(arg.get_type()); + let cond = self.cx.context.new_comparison(None, ComparisonOp::Equals, arg, zero); + self.llbb().end_with_conditional(None, cond, then_block, else_block); + + let zero_result = self.cx.context.new_rvalue_from_long(arg.get_type(), width as i64); + then_block.add_assignment(None, result, zero_result); + then_block.end_with_jump(None, after_block); + + // NOTE: since jumps were added in a place + // count_leading_zeroes() does not expect, the current blocks + // in the state need to be updated. + *self.current_block.borrow_mut() = Some(else_block); + self.block = Some(else_block); + + let zeros = + match name { + sym::ctlz => self.count_leading_zeroes(width, arg), + sym::cttz => self.count_trailing_zeroes(width, arg), + _ => unreachable!(), + }; + else_block.add_assignment(None, result, zeros); + else_block.end_with_jump(None, after_block); + + // NOTE: since jumps were added in a place rustc does not + // expect, the current blocks in the state need to be updated. + *self.current_block.borrow_mut() = Some(after_block); + self.block = Some(after_block); + + result.to_rvalue() + } + sym::ctlz_nonzero => { + self.count_leading_zeroes(width, args[0].immediate()) + }, + sym::cttz_nonzero => { + self.count_trailing_zeroes(width, args[0].immediate()) + } + sym::ctpop => self.pop_count(args[0].immediate()), + sym::bswap => { + if width == 8 { + args[0].immediate() // byte swap a u8/i8 is just a no-op + } + else { + // TODO(antoyo): check if it's faster to use string literals and a + // match instead of format!. + let bswap = self.cx.context.get_builtin_function(&format!("__builtin_bswap{}", width)); + let mut arg = args[0].immediate(); + // FIXME(antoyo): this cast should not be necessary. Remove + // when having proper sized integer types. + let param_type = bswap.get_param(0).to_rvalue().get_type(); + if param_type != arg.get_type() { + arg = self.bitcast(arg, param_type); + } + self.cx.context.new_call(None, bswap, &[arg]) + } + }, + sym::bitreverse => self.bit_reverse(width, args[0].immediate()), + sym::rotate_left | sym::rotate_right => { + // TODO(antoyo): implement using algorithm from: + // https://blog.regehr.org/archives/1063 + // for other platforms. + let is_left = name == sym::rotate_left; + let val = args[0].immediate(); + let raw_shift = args[1].immediate(); + if is_left { + self.rotate_left(val, raw_shift, width) + } + else { + self.rotate_right(val, raw_shift, width) + } + }, + sym::saturating_add => { + self.saturating_add(args[0].immediate(), args[1].immediate(), signed, width) + }, + sym::saturating_sub => { + self.saturating_sub(args[0].immediate(), args[1].immediate(), signed, width) + }, + _ => bug!(), + }, + None => { + span_invalid_monomorphization_error( + tcx.sess, + span, + &format!( + "invalid monomorphization of `{}` intrinsic: \ + expected basic integer type, found `{}`", + name, ty + ), + ); + return; + } + } + } + + sym::raw_eq => { + use rustc_target::abi::Abi::*; + let tp_ty = substs.type_at(0); + let layout = self.layout_of(tp_ty).layout; + let _use_integer_compare = match layout.abi { + Scalar(_) | ScalarPair(_, _) => true, + Uninhabited | Vector { .. } => false, + Aggregate { .. } => { + // For rusty ABIs, small aggregates are actually passed + // as `RegKind::Integer` (see `FnAbi::adjust_for_abi`), + // so we re-use that same threshold here. + layout.size <= self.data_layout().pointer_size * 2 + } + }; + + let a = args[0].immediate(); + let b = args[1].immediate(); + if layout.size.bytes() == 0 { + self.const_bool(true) + } + /*else if use_integer_compare { + let integer_ty = self.type_ix(layout.size.bits()); // FIXME(antoyo): LLVM creates an integer of 96 bits for [i32; 3], but gcc doesn't support this, so it creates an integer of 128 bits. + let ptr_ty = self.type_ptr_to(integer_ty); + let a_ptr = self.bitcast(a, ptr_ty); + let a_val = self.load(integer_ty, a_ptr, layout.align.abi); + let b_ptr = self.bitcast(b, ptr_ty); + let b_val = self.load(integer_ty, b_ptr, layout.align.abi); + self.icmp(IntPredicate::IntEQ, a_val, b_val) + }*/ + else { + let void_ptr_type = self.context.new_type::<*const ()>(); + let a_ptr = self.bitcast(a, void_ptr_type); + let b_ptr = self.bitcast(b, void_ptr_type); + let n = self.context.new_cast(None, self.const_usize(layout.size.bytes()), self.sizet_type); + let builtin = self.context.get_builtin_function("memcmp"); + let cmp = self.context.new_call(None, builtin, &[a_ptr, b_ptr, n]); + self.icmp(IntPredicate::IntEQ, cmp, self.const_i32(0)) + } + } + + sym::black_box => { + args[0].val.store(self, result); + + let block = self.llbb(); + let extended_asm = block.add_extended_asm(None, ""); + extended_asm.add_input_operand(None, "r", result.llval); + extended_asm.add_clobber("memory"); + extended_asm.set_volatile_flag(true); + + // We have copied the value to `result` already. + return; + } + + _ if name_str.starts_with("simd_") => { + match generic_simd_intrinsic(self, name, callee_ty, args, ret_ty, llret_ty, span) { + Ok(llval) => llval, + Err(()) => return, + } + } + + _ => bug!("unknown intrinsic '{}'", name), + }; + + if !fn_abi.ret.is_ignore() { + if let PassMode::Cast(ty) = fn_abi.ret.mode { + let ptr_llty = self.type_ptr_to(ty.gcc_type(self)); + let ptr = self.pointercast(result.llval, ptr_llty); + self.store(llval, ptr, result.align); + } + else { + OperandRef::from_immediate_or_packed_pair(self, llval, result.layout) + .val + .store(self, result); + } + } + } + + fn abort(&mut self) { + let func = self.context.get_builtin_function("abort"); + let func: RValue<'gcc> = unsafe { std::mem::transmute(func) }; + self.call(self.type_void(), func, &[], None); + } + + fn assume(&mut self, value: Self::Value) { + // TODO(antoyo): switch to asumme when it exists. + // Or use something like this: + // #define __assume(cond) do { if (!(cond)) __builtin_unreachable(); } while (0) + self.expect(value, true); + } + + fn expect(&mut self, cond: Self::Value, _expected: bool) -> Self::Value { + // TODO(antoyo) + cond + } + + fn sideeffect(&mut self) { + // TODO(antoyo) + } + + fn va_start(&mut self, _va_list: RValue<'gcc>) -> RValue<'gcc> { + unimplemented!(); + } + + fn va_end(&mut self, _va_list: RValue<'gcc>) -> RValue<'gcc> { + unimplemented!(); + } +} + +impl<'a, 'gcc, 'tcx> ArgAbiMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { + fn store_fn_arg(&mut self, arg_abi: &ArgAbi<'tcx, Ty<'tcx>>, idx: &mut usize, dst: PlaceRef<'tcx, Self::Value>) { + arg_abi.store_fn_arg(self, idx, dst) + } + + fn store_arg(&mut self, arg_abi: &ArgAbi<'tcx, Ty<'tcx>>, val: RValue<'gcc>, dst: PlaceRef<'tcx, RValue<'gcc>>) { + arg_abi.store(self, val, dst) + } + + fn arg_memory_ty(&self, arg_abi: &ArgAbi<'tcx, Ty<'tcx>>) -> Type<'gcc> { + arg_abi.memory_ty(self) + } +} + +pub trait ArgAbiExt<'gcc, 'tcx> { + fn memory_ty(&self, cx: &CodegenCx<'gcc, 'tcx>) -> Type<'gcc>; + fn store(&self, bx: &mut Builder<'_, 'gcc, 'tcx>, val: RValue<'gcc>, dst: PlaceRef<'tcx, RValue<'gcc>>); + fn store_fn_arg(&self, bx: &mut Builder<'_, 'gcc, 'tcx>, idx: &mut usize, dst: PlaceRef<'tcx, RValue<'gcc>>); +} + +impl<'gcc, 'tcx> ArgAbiExt<'gcc, 'tcx> for ArgAbi<'tcx, Ty<'tcx>> { + /// Gets the LLVM type for a place of the original Rust type of + /// this argument/return, i.e., the result of `type_of::type_of`. + fn memory_ty(&self, cx: &CodegenCx<'gcc, 'tcx>) -> Type<'gcc> { + self.layout.gcc_type(cx, true) + } + + /// Stores a direct/indirect value described by this ArgAbi into a + /// place for the original Rust type of this argument/return. + /// Can be used for both storing formal arguments into Rust variables + /// or results of call/invoke instructions into their destinations. + fn store(&self, bx: &mut Builder<'_, 'gcc, 'tcx>, val: RValue<'gcc>, dst: PlaceRef<'tcx, RValue<'gcc>>) { + if self.is_ignore() { + return; + } + if self.is_sized_indirect() { + OperandValue::Ref(val, None, self.layout.align.abi).store(bx, dst) + } + else if self.is_unsized_indirect() { + bug!("unsized `ArgAbi` must be handled through `store_fn_arg`"); + } + else if let PassMode::Cast(cast) = self.mode { + // FIXME(eddyb): Figure out when the simpler Store is safe, clang + // uses it for i16 -> {i8, i8}, but not for i24 -> {i8, i8, i8}. + let can_store_through_cast_ptr = false; + if can_store_through_cast_ptr { + let cast_ptr_llty = bx.type_ptr_to(cast.gcc_type(bx)); + let cast_dst = bx.pointercast(dst.llval, cast_ptr_llty); + bx.store(val, cast_dst, self.layout.align.abi); + } + else { + // The actual return type is a struct, but the ABI + // adaptation code has cast it into some scalar type. The + // code that follows is the only reliable way I have + // found to do a transform like i64 -> {i32,i32}. + // Basically we dump the data onto the stack then memcpy it. + // + // Other approaches I tried: + // - Casting rust ret pointer to the foreign type and using Store + // is (a) unsafe if size of foreign type > size of rust type and + // (b) runs afoul of strict aliasing rules, yielding invalid + // assembly under -O (specifically, the store gets removed). + // - Truncating foreign type to correct integral type and then + // bitcasting to the struct type yields invalid cast errors. + + // We instead thus allocate some scratch space... + let scratch_size = cast.size(bx); + let scratch_align = cast.align(bx); + let llscratch = bx.alloca(cast.gcc_type(bx), scratch_align); + bx.lifetime_start(llscratch, scratch_size); + + // ... where we first store the value... + bx.store(val, llscratch, scratch_align); + + // ... and then memcpy it to the intended destination. + bx.memcpy( + dst.llval, + self.layout.align.abi, + llscratch, + scratch_align, + bx.const_usize(self.layout.size.bytes()), + MemFlags::empty(), + ); + + bx.lifetime_end(llscratch, scratch_size); + } + } + else { + OperandValue::Immediate(val).store(bx, dst); + } + } + + fn store_fn_arg<'a>(&self, bx: &mut Builder<'a, 'gcc, 'tcx>, idx: &mut usize, dst: PlaceRef<'tcx, RValue<'gcc>>) { + let mut next = || { + let val = bx.current_func().get_param(*idx as i32); + *idx += 1; + val.to_rvalue() + }; + match self.mode { + PassMode::Ignore => {} + PassMode::Pair(..) => { + OperandValue::Pair(next(), next()).store(bx, dst); + } + PassMode::Indirect { extra_attrs: Some(_), .. } => { + OperandValue::Ref(next(), Some(next()), self.layout.align.abi).store(bx, dst); + } + PassMode::Direct(_) | PassMode::Indirect { extra_attrs: None, .. } | PassMode::Cast(_) => { + let next_arg = next(); + self.store(bx, next_arg.to_rvalue(), dst); + } + } + } +} + +fn int_type_width_signed<'gcc, 'tcx>(ty: Ty<'tcx>, cx: &CodegenCx<'gcc, 'tcx>) -> Option<(u64, bool)> { + match ty.kind() { + ty::Int(t) => Some(( + match t { + rustc_middle::ty::IntTy::Isize => u64::from(cx.tcx.sess.target.pointer_width), + rustc_middle::ty::IntTy::I8 => 8, + rustc_middle::ty::IntTy::I16 => 16, + rustc_middle::ty::IntTy::I32 => 32, + rustc_middle::ty::IntTy::I64 => 64, + rustc_middle::ty::IntTy::I128 => 128, + }, + true, + )), + ty::Uint(t) => Some(( + match t { + rustc_middle::ty::UintTy::Usize => u64::from(cx.tcx.sess.target.pointer_width), + rustc_middle::ty::UintTy::U8 => 8, + rustc_middle::ty::UintTy::U16 => 16, + rustc_middle::ty::UintTy::U32 => 32, + rustc_middle::ty::UintTy::U64 => 64, + rustc_middle::ty::UintTy::U128 => 128, + }, + false, + )), + _ => None, + } +} + +impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { + fn bit_reverse(&mut self, width: u64, value: RValue<'gcc>) -> RValue<'gcc> { + let result_type = value.get_type(); + let typ = result_type.to_unsigned(self.cx); + + let value = + if result_type.is_signed(self.cx) { + self.context.new_bitcast(None, value, typ) + } + else { + value + }; + + let context = &self.cx.context; + let result = + match width { + 8 => { + // First step. + let left = self.and(value, context.new_rvalue_from_int(typ, 0xF0)); + let left = self.lshr(left, context.new_rvalue_from_int(typ, 4)); + let right = self.and(value, context.new_rvalue_from_int(typ, 0x0F)); + let right = self.shl(right, context.new_rvalue_from_int(typ, 4)); + let step1 = self.or(left, right); + + // Second step. + let left = self.and(step1, context.new_rvalue_from_int(typ, 0xCC)); + let left = self.lshr(left, context.new_rvalue_from_int(typ, 2)); + let right = self.and(step1, context.new_rvalue_from_int(typ, 0x33)); + let right = self.shl(right, context.new_rvalue_from_int(typ, 2)); + let step2 = self.or(left, right); + + // Third step. + let left = self.and(step2, context.new_rvalue_from_int(typ, 0xAA)); + let left = self.lshr(left, context.new_rvalue_from_int(typ, 1)); + let right = self.and(step2, context.new_rvalue_from_int(typ, 0x55)); + let right = self.shl(right, context.new_rvalue_from_int(typ, 1)); + let step3 = self.or(left, right); + + step3 + }, + 16 => { + // First step. + let left = self.and(value, context.new_rvalue_from_int(typ, 0x5555)); + let left = self.shl(left, context.new_rvalue_from_int(typ, 1)); + let right = self.and(value, context.new_rvalue_from_int(typ, 0xAAAA)); + let right = self.lshr(right, context.new_rvalue_from_int(typ, 1)); + let step1 = self.or(left, right); + + // Second step. + let left = self.and(step1, context.new_rvalue_from_int(typ, 0x3333)); + let left = self.shl(left, context.new_rvalue_from_int(typ, 2)); + let right = self.and(step1, context.new_rvalue_from_int(typ, 0xCCCC)); + let right = self.lshr(right, context.new_rvalue_from_int(typ, 2)); + let step2 = self.or(left, right); + + // Third step. + let left = self.and(step2, context.new_rvalue_from_int(typ, 0x0F0F)); + let left = self.shl(left, context.new_rvalue_from_int(typ, 4)); + let right = self.and(step2, context.new_rvalue_from_int(typ, 0xF0F0)); + let right = self.lshr(right, context.new_rvalue_from_int(typ, 4)); + let step3 = self.or(left, right); + + // Fourth step. + let left = self.and(step3, context.new_rvalue_from_int(typ, 0x00FF)); + let left = self.shl(left, context.new_rvalue_from_int(typ, 8)); + let right = self.and(step3, context.new_rvalue_from_int(typ, 0xFF00)); + let right = self.lshr(right, context.new_rvalue_from_int(typ, 8)); + let step4 = self.or(left, right); + + step4 + }, + 32 => { + // TODO(antoyo): Refactor with other implementations. + // First step. + let left = self.and(value, context.new_rvalue_from_long(typ, 0x55555555)); + let left = self.shl(left, context.new_rvalue_from_long(typ, 1)); + let right = self.and(value, context.new_rvalue_from_long(typ, 0xAAAAAAAA)); + let right = self.lshr(right, context.new_rvalue_from_long(typ, 1)); + let step1 = self.or(left, right); + + // Second step. + let left = self.and(step1, context.new_rvalue_from_long(typ, 0x33333333)); + let left = self.shl(left, context.new_rvalue_from_long(typ, 2)); + let right = self.and(step1, context.new_rvalue_from_long(typ, 0xCCCCCCCC)); + let right = self.lshr(right, context.new_rvalue_from_long(typ, 2)); + let step2 = self.or(left, right); + + // Third step. + let left = self.and(step2, context.new_rvalue_from_long(typ, 0x0F0F0F0F)); + let left = self.shl(left, context.new_rvalue_from_long(typ, 4)); + let right = self.and(step2, context.new_rvalue_from_long(typ, 0xF0F0F0F0)); + let right = self.lshr(right, context.new_rvalue_from_long(typ, 4)); + let step3 = self.or(left, right); + + // Fourth step. + let left = self.and(step3, context.new_rvalue_from_long(typ, 0x00FF00FF)); + let left = self.shl(left, context.new_rvalue_from_long(typ, 8)); + let right = self.and(step3, context.new_rvalue_from_long(typ, 0xFF00FF00)); + let right = self.lshr(right, context.new_rvalue_from_long(typ, 8)); + let step4 = self.or(left, right); + + // Fifth step. + let left = self.and(step4, context.new_rvalue_from_long(typ, 0x0000FFFF)); + let left = self.shl(left, context.new_rvalue_from_long(typ, 16)); + let right = self.and(step4, context.new_rvalue_from_long(typ, 0xFFFF0000)); + let right = self.lshr(right, context.new_rvalue_from_long(typ, 16)); + let step5 = self.or(left, right); + + step5 + }, + 64 => { + // First step. + let left = self.shl(value, context.new_rvalue_from_long(typ, 32)); + let right = self.lshr(value, context.new_rvalue_from_long(typ, 32)); + let step1 = self.or(left, right); + + // Second step. + let left = self.and(step1, context.new_rvalue_from_long(typ, 0x0001FFFF0001FFFF)); + let left = self.shl(left, context.new_rvalue_from_long(typ, 15)); + let right = self.and(step1, context.new_rvalue_from_long(typ, 0xFFFE0000FFFE0000u64 as i64)); // TODO(antoyo): transmute the number instead? + let right = self.lshr(right, context.new_rvalue_from_long(typ, 17)); + let step2 = self.or(left, right); + + // Third step. + let left = self.lshr(step2, context.new_rvalue_from_long(typ, 10)); + let left = self.xor(step2, left); + let temp = self.and(left, context.new_rvalue_from_long(typ, 0x003F801F003F801F)); + + let left = self.shl(temp, context.new_rvalue_from_long(typ, 10)); + let left = self.or(temp, left); + let step3 = self.xor(left, step2); + + // Fourth step. + let left = self.lshr(step3, context.new_rvalue_from_long(typ, 4)); + let left = self.xor(step3, left); + let temp = self.and(left, context.new_rvalue_from_long(typ, 0x0E0384210E038421)); + + let left = self.shl(temp, context.new_rvalue_from_long(typ, 4)); + let left = self.or(temp, left); + let step4 = self.xor(left, step3); + + // Fifth step. + let left = self.lshr(step4, context.new_rvalue_from_long(typ, 2)); + let left = self.xor(step4, left); + let temp = self.and(left, context.new_rvalue_from_long(typ, 0x2248884222488842)); + + let left = self.shl(temp, context.new_rvalue_from_long(typ, 2)); + let left = self.or(temp, left); + let step5 = self.xor(left, step4); + + step5 + }, + 128 => { + // TODO(antoyo): find a more efficient implementation? + let sixty_four = self.context.new_rvalue_from_long(typ, 64); + let high = self.context.new_cast(None, value >> sixty_four, self.u64_type); + let low = self.context.new_cast(None, value, self.u64_type); + + let reversed_high = self.bit_reverse(64, high); + let reversed_low = self.bit_reverse(64, low); + + let new_low = self.context.new_cast(None, reversed_high, typ); + let new_high = self.context.new_cast(None, reversed_low, typ) << sixty_four; + + new_low | new_high + }, + _ => { + panic!("cannot bit reverse with width = {}", width); + }, + }; + + self.context.new_bitcast(None, result, result_type) + } + + fn count_leading_zeroes(&self, width: u64, arg: RValue<'gcc>) -> RValue<'gcc> { + // TODO(antoyo): use width? + let arg_type = arg.get_type(); + let count_leading_zeroes = + if arg_type.is_uint(&self.cx) { + "__builtin_clz" + } + else if arg_type.is_ulong(&self.cx) { + "__builtin_clzl" + } + else if arg_type.is_ulonglong(&self.cx) { + "__builtin_clzll" + } + else if width == 128 { + // Algorithm from: https://stackoverflow.com/a/28433850/389119 + let array_type = self.context.new_array_type(None, arg_type, 3); + let result = self.current_func() + .new_local(None, array_type, "count_loading_zeroes_results"); + + let sixty_four = self.context.new_rvalue_from_long(arg_type, 64); + let high = self.context.new_cast(None, arg >> sixty_four, self.u64_type); + let low = self.context.new_cast(None, arg, self.u64_type); + + let zero = self.context.new_rvalue_zero(self.usize_type); + let one = self.context.new_rvalue_one(self.usize_type); + let two = self.context.new_rvalue_from_long(self.usize_type, 2); + + let clzll = self.context.get_builtin_function("__builtin_clzll"); + + let first_elem = self.context.new_array_access(None, result, zero); + let first_value = self.context.new_cast(None, self.context.new_call(None, clzll, &[high]), arg_type); + self.llbb() + .add_assignment(None, first_elem, first_value); + + let second_elem = self.context.new_array_access(None, result, one); + let second_value = self.context.new_cast(None, self.context.new_call(None, clzll, &[low]), arg_type) + sixty_four; + self.llbb() + .add_assignment(None, second_elem, second_value); + + let third_elem = self.context.new_array_access(None, result, two); + let third_value = self.context.new_rvalue_from_long(arg_type, 128); + self.llbb() + .add_assignment(None, third_elem, third_value); + + let not_high = self.context.new_unary_op(None, UnaryOp::LogicalNegate, self.u64_type, high); + let not_low = self.context.new_unary_op(None, UnaryOp::LogicalNegate, self.u64_type, low); + let not_low_and_not_high = not_low & not_high; + let index = not_high + not_low_and_not_high; + + let res = self.context.new_array_access(None, result, index); + + return self.context.new_cast(None, res, arg_type); + } + else { + let count_leading_zeroes = self.context.get_builtin_function("__builtin_clz"); + let arg = self.context.new_cast(None, arg, self.uint_type); + let diff = self.int_width(self.uint_type) - self.int_width(arg_type); + let diff = self.context.new_rvalue_from_long(self.int_type, diff); + let res = self.context.new_call(None, count_leading_zeroes, &[arg]) - diff; + return self.context.new_cast(None, res, arg_type); + }; + let count_leading_zeroes = self.context.get_builtin_function(count_leading_zeroes); + let res = self.context.new_call(None, count_leading_zeroes, &[arg]); + self.context.new_cast(None, res, arg_type) + } + + fn count_trailing_zeroes(&self, _width: u64, arg: RValue<'gcc>) -> RValue<'gcc> { + let result_type = arg.get_type(); + let arg = + if result_type.is_signed(self.cx) { + let new_type = result_type.to_unsigned(self.cx); + self.context.new_bitcast(None, arg, new_type) + } + else { + arg + }; + let arg_type = arg.get_type(); + let (count_trailing_zeroes, expected_type) = + if arg_type.is_uchar(&self.cx) || arg_type.is_ushort(&self.cx) || arg_type.is_uint(&self.cx) { + // NOTE: we don't need to & 0xFF for uchar because the result is undefined on zero. + ("__builtin_ctz", self.cx.uint_type) + } + else if arg_type.is_ulong(&self.cx) { + ("__builtin_ctzl", self.cx.ulong_type) + } + else if arg_type.is_ulonglong(&self.cx) { + ("__builtin_ctzll", self.cx.ulonglong_type) + } + else if arg_type.is_u128(&self.cx) { + // Adapted from the algorithm to count leading zeroes from: https://stackoverflow.com/a/28433850/389119 + let array_type = self.context.new_array_type(None, arg_type, 3); + let result = self.current_func() + .new_local(None, array_type, "count_loading_zeroes_results"); + + let sixty_four = self.context.new_rvalue_from_long(arg_type, 64); + let high = self.context.new_cast(None, arg >> sixty_four, self.u64_type); + let low = self.context.new_cast(None, arg, self.u64_type); + + let zero = self.context.new_rvalue_zero(self.usize_type); + let one = self.context.new_rvalue_one(self.usize_type); + let two = self.context.new_rvalue_from_long(self.usize_type, 2); + + let ctzll = self.context.get_builtin_function("__builtin_ctzll"); + + let first_elem = self.context.new_array_access(None, result, zero); + let first_value = self.context.new_cast(None, self.context.new_call(None, ctzll, &[low]), arg_type); + self.llbb() + .add_assignment(None, first_elem, first_value); + + let second_elem = self.context.new_array_access(None, result, one); + let second_value = self.context.new_cast(None, self.context.new_call(None, ctzll, &[high]), arg_type) + sixty_four; + self.llbb() + .add_assignment(None, second_elem, second_value); + + let third_elem = self.context.new_array_access(None, result, two); + let third_value = self.context.new_rvalue_from_long(arg_type, 128); + self.llbb() + .add_assignment(None, third_elem, third_value); + + let not_low = self.context.new_unary_op(None, UnaryOp::LogicalNegate, self.u64_type, low); + let not_high = self.context.new_unary_op(None, UnaryOp::LogicalNegate, self.u64_type, high); + let not_low_and_not_high = not_low & not_high; + let index = not_low + not_low_and_not_high; + + let res = self.context.new_array_access(None, result, index); + + return self.context.new_bitcast(None, res, result_type); + } + else { + unimplemented!("count_trailing_zeroes for {:?}", arg_type); + }; + let count_trailing_zeroes = self.context.get_builtin_function(count_trailing_zeroes); + let arg = + if arg_type != expected_type { + self.context.new_cast(None, arg, expected_type) + } + else { + arg + }; + let res = self.context.new_call(None, count_trailing_zeroes, &[arg]); + self.context.new_bitcast(None, res, result_type) + } + + fn int_width(&self, typ: Type<'gcc>) -> i64 { + self.cx.int_width(typ) as i64 + } + + fn pop_count(&self, value: RValue<'gcc>) -> RValue<'gcc> { + // TODO(antoyo): use the optimized version with fewer operations. + let result_type = value.get_type(); + let value_type = result_type.to_unsigned(self.cx); + + let value = + if result_type.is_signed(self.cx) { + self.context.new_bitcast(None, value, value_type) + } + else { + value + }; + + if value_type.is_u128(&self.cx) { + // TODO(antoyo): implement in the normal algorithm below to have a more efficient + // implementation (that does not require a call to __popcountdi2). + let popcount = self.context.get_builtin_function("__builtin_popcountll"); + let sixty_four = self.context.new_rvalue_from_long(value_type, 64); + let high = self.context.new_cast(None, value >> sixty_four, self.cx.ulonglong_type); + let high = self.context.new_call(None, popcount, &[high]); + let low = self.context.new_cast(None, value, self.cx.ulonglong_type); + let low = self.context.new_call(None, popcount, &[low]); + let res = high + low; + return self.context.new_bitcast(None, res, result_type); + } + + // First step. + let mask = self.context.new_rvalue_from_long(value_type, 0x5555555555555555); + let left = value & mask; + let shifted = value >> self.context.new_rvalue_from_int(value_type, 1); + let right = shifted & mask; + let value = left + right; + + // Second step. + let mask = self.context.new_rvalue_from_long(value_type, 0x3333333333333333); + let left = value & mask; + let shifted = value >> self.context.new_rvalue_from_int(value_type, 2); + let right = shifted & mask; + let value = left + right; + + // Third step. + let mask = self.context.new_rvalue_from_long(value_type, 0x0F0F0F0F0F0F0F0F); + let left = value & mask; + let shifted = value >> self.context.new_rvalue_from_int(value_type, 4); + let right = shifted & mask; + let value = left + right; + + if value_type.is_u8(&self.cx) { + return self.context.new_bitcast(None, value, result_type); + } + + // Fourth step. + let mask = self.context.new_rvalue_from_long(value_type, 0x00FF00FF00FF00FF); + let left = value & mask; + let shifted = value >> self.context.new_rvalue_from_int(value_type, 8); + let right = shifted & mask; + let value = left + right; + + if value_type.is_u16(&self.cx) { + return self.context.new_bitcast(None, value, result_type); + } + + // Fifth step. + let mask = self.context.new_rvalue_from_long(value_type, 0x0000FFFF0000FFFF); + let left = value & mask; + let shifted = value >> self.context.new_rvalue_from_int(value_type, 16); + let right = shifted & mask; + let value = left + right; + + if value_type.is_u32(&self.cx) { + return self.context.new_bitcast(None, value, result_type); + } + + // Sixth step. + let mask = self.context.new_rvalue_from_long(value_type, 0x00000000FFFFFFFF); + let left = value & mask; + let shifted = value >> self.context.new_rvalue_from_int(value_type, 32); + let right = shifted & mask; + let value = left + right; + + self.context.new_bitcast(None, value, result_type) + } + + // Algorithm from: https://blog.regehr.org/archives/1063 + fn rotate_left(&mut self, value: RValue<'gcc>, shift: RValue<'gcc>, width: u64) -> RValue<'gcc> { + let max = self.context.new_rvalue_from_long(shift.get_type(), width as i64); + let shift = shift % max; + let lhs = self.shl(value, shift); + let result_and = + self.and( + self.context.new_unary_op(None, UnaryOp::Minus, shift.get_type(), shift), + self.context.new_rvalue_from_long(shift.get_type(), width as i64 - 1), + ); + let rhs = self.lshr(value, result_and); + self.or(lhs, rhs) + } + + // Algorithm from: https://blog.regehr.org/archives/1063 + fn rotate_right(&mut self, value: RValue<'gcc>, shift: RValue<'gcc>, width: u64) -> RValue<'gcc> { + let max = self.context.new_rvalue_from_long(shift.get_type(), width as i64); + let shift = shift % max; + let lhs = self.lshr(value, shift); + let result_and = + self.and( + self.context.new_unary_op(None, UnaryOp::Minus, shift.get_type(), shift), + self.context.new_rvalue_from_long(shift.get_type(), width as i64 - 1), + ); + let rhs = self.shl(value, result_and); + self.or(lhs, rhs) + } + + fn saturating_add(&mut self, lhs: RValue<'gcc>, rhs: RValue<'gcc>, signed: bool, width: u64) -> RValue<'gcc> { + let func = self.current_func.borrow().expect("func"); + + if signed { + // Algorithm from: https://stackoverflow.com/a/56531252/389119 + let after_block = func.new_block("after"); + let func_name = + match width { + 8 => "__builtin_add_overflow", + 16 => "__builtin_add_overflow", + 32 => "__builtin_sadd_overflow", + 64 => "__builtin_saddll_overflow", + 128 => "__builtin_add_overflow", + _ => unreachable!(), + }; + let overflow_func = self.context.get_builtin_function(func_name); + let result_type = lhs.get_type(); + let res = func.new_local(None, result_type, "saturating_sum"); + let overflow = self.overflow_call(overflow_func, &[lhs, rhs, res.get_address(None)], None); + + let then_block = func.new_block("then"); + + let unsigned_type = self.context.new_int_type(width as i32 / 8, false); + let shifted = self.context.new_cast(None, lhs, unsigned_type) >> self.context.new_rvalue_from_int(unsigned_type, width as i32 - 1); + let uint_max = self.context.new_unary_op(None, UnaryOp::BitwiseNegate, unsigned_type, + self.context.new_rvalue_from_int(unsigned_type, 0) + ); + let int_max = uint_max >> self.context.new_rvalue_one(unsigned_type); + then_block.add_assignment(None, res, self.context.new_cast(None, shifted + int_max, result_type)); + then_block.end_with_jump(None, after_block); + + self.llbb().end_with_conditional(None, overflow, then_block, after_block); + + // NOTE: since jumps were added in a place rustc does not + // expect, the current blocks in the state need to be updated. + *self.current_block.borrow_mut() = Some(after_block); + self.block = Some(after_block); + + res.to_rvalue() + } + else { + // Algorithm from: http://locklessinc.com/articles/sat_arithmetic/ + let res = lhs + rhs; + let res_type = res.get_type(); + let cond = self.context.new_comparison(None, ComparisonOp::LessThan, res, lhs); + let value = self.context.new_unary_op(None, UnaryOp::Minus, res_type, self.context.new_cast(None, cond, res_type)); + res | value + } + } + + // Algorithm from: https://locklessinc.com/articles/sat_arithmetic/ + fn saturating_sub(&mut self, lhs: RValue<'gcc>, rhs: RValue<'gcc>, signed: bool, width: u64) -> RValue<'gcc> { + if signed { + // Also based on algorithm from: https://stackoverflow.com/a/56531252/389119 + let func_name = + match width { + 8 => "__builtin_sub_overflow", + 16 => "__builtin_sub_overflow", + 32 => "__builtin_ssub_overflow", + 64 => "__builtin_ssubll_overflow", + 128 => "__builtin_sub_overflow", + _ => unreachable!(), + }; + let overflow_func = self.context.get_builtin_function(func_name); + let result_type = lhs.get_type(); + let func = self.current_func.borrow().expect("func"); + let res = func.new_local(None, result_type, "saturating_diff"); + let overflow = self.overflow_call(overflow_func, &[lhs, rhs, res.get_address(None)], None); + + let then_block = func.new_block("then"); + let after_block = func.new_block("after"); + + let unsigned_type = self.context.new_int_type(width as i32 / 8, false); + let shifted = self.context.new_cast(None, lhs, unsigned_type) >> self.context.new_rvalue_from_int(unsigned_type, width as i32 - 1); + let uint_max = self.context.new_unary_op(None, UnaryOp::BitwiseNegate, unsigned_type, + self.context.new_rvalue_from_int(unsigned_type, 0) + ); + let int_max = uint_max >> self.context.new_rvalue_one(unsigned_type); + then_block.add_assignment(None, res, self.context.new_cast(None, shifted + int_max, result_type)); + then_block.end_with_jump(None, after_block); + + self.llbb().end_with_conditional(None, overflow, then_block, after_block); + + // NOTE: since jumps were added in a place rustc does not + // expect, the current blocks in the state need to be updated. + *self.current_block.borrow_mut() = Some(after_block); + self.block = Some(after_block); + + res.to_rvalue() + } + else { + let res = lhs - rhs; + let comparison = self.context.new_comparison(None, ComparisonOp::LessThanEquals, res, lhs); + let comparison = self.context.new_cast(None, comparison, lhs.get_type()); + let unary_op = self.context.new_unary_op(None, UnaryOp::Minus, comparison.get_type(), comparison); + self.and(res, unary_op) + } + } +} + +fn try_intrinsic<'gcc, 'tcx>(bx: &mut Builder<'_, 'gcc, 'tcx>, try_func: RValue<'gcc>, data: RValue<'gcc>, _catch_func: RValue<'gcc>, dest: RValue<'gcc>) { + if bx.sess().panic_strategy() == PanicStrategy::Abort { + bx.call(bx.type_void(), try_func, &[data], None); + // Return 0 unconditionally from the intrinsic call; + // we can never unwind. + let ret_align = bx.tcx.data_layout.i32_align.abi; + bx.store(bx.const_i32(0), dest, ret_align); + } + else if wants_msvc_seh(bx.sess()) { + unimplemented!(); + } + else { + unimplemented!(); + } +} diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs b/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs new file mode 100644 index 0000000000..26a42217e4 --- /dev/null +++ b/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs @@ -0,0 +1,167 @@ +use gccjit::{RValue, Type}; +use rustc_codegen_ssa::base::compare_simd_types; +use rustc_codegen_ssa::common::{TypeKind, span_invalid_monomorphization_error}; +use rustc_codegen_ssa::mir::operand::OperandRef; +use rustc_codegen_ssa::traits::{BaseTypeMethods, BuilderMethods}; +use rustc_hir as hir; +use rustc_middle::span_bug; +use rustc_middle::ty::layout::HasTyCtxt; +use rustc_middle::ty::{self, Ty}; +use rustc_span::{Span, Symbol, sym}; + +use crate::builder::Builder; + +pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>, name: Symbol, callee_ty: Ty<'tcx>, args: &[OperandRef<'tcx, RValue<'gcc>>], ret_ty: Ty<'tcx>, llret_ty: Type<'gcc>, span: Span) -> Result, ()> { + // macros for error handling: + macro_rules! emit_error { + ($msg: tt) => { + emit_error!($msg, ) + }; + ($msg: tt, $($fmt: tt)*) => { + span_invalid_monomorphization_error( + bx.sess(), span, + &format!(concat!("invalid monomorphization of `{}` intrinsic: ", $msg), + name, $($fmt)*)); + } + } + + macro_rules! return_error { + ($($fmt: tt)*) => { + { + emit_error!($($fmt)*); + return Err(()); + } + } + } + + macro_rules! require { + ($cond: expr, $($fmt: tt)*) => { + if !$cond { + return_error!($($fmt)*); + } + }; + } + + macro_rules! require_simd { + ($ty: expr, $position: expr) => { + require!($ty.is_simd(), "expected SIMD {} type, found non-SIMD `{}`", $position, $ty) + }; + } + + let tcx = bx.tcx(); + let sig = + tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), callee_ty.fn_sig(tcx)); + let arg_tys = sig.inputs(); + let name_str = &*name.as_str(); + + // every intrinsic below takes a SIMD vector as its first argument + require_simd!(arg_tys[0], "input"); + let in_ty = arg_tys[0]; + + let comparison = match name { + sym::simd_eq => Some(hir::BinOpKind::Eq), + sym::simd_ne => Some(hir::BinOpKind::Ne), + sym::simd_lt => Some(hir::BinOpKind::Lt), + sym::simd_le => Some(hir::BinOpKind::Le), + sym::simd_gt => Some(hir::BinOpKind::Gt), + sym::simd_ge => Some(hir::BinOpKind::Ge), + _ => None, + }; + + let (in_len, in_elem) = arg_tys[0].simd_size_and_type(bx.tcx()); + if let Some(cmp_op) = comparison { + require_simd!(ret_ty, "return"); + + let (out_len, out_ty) = ret_ty.simd_size_and_type(bx.tcx()); + require!( + in_len == out_len, + "expected return type with length {} (same as input type `{}`), \ + found `{}` with length {}", + in_len, + in_ty, + ret_ty, + out_len + ); + require!( + bx.type_kind(bx.element_type(llret_ty)) == TypeKind::Integer, + "expected return type with integer elements, found `{}` with non-integer `{}`", + ret_ty, + out_ty + ); + + return Ok(compare_simd_types( + bx, + args[0].immediate(), + args[1].immediate(), + in_elem, + llret_ty, + cmp_op, + )); + } + + if let Some(stripped) = name_str.strip_prefix("simd_shuffle") { + let n: u64 = stripped.parse().unwrap_or_else(|_| { + span_bug!(span, "bad `simd_shuffle` instruction only caught in codegen?") + }); + + require_simd!(ret_ty, "return"); + + let (out_len, out_ty) = ret_ty.simd_size_and_type(bx.tcx()); + require!( + out_len == n, + "expected return type of length {}, found `{}` with length {}", + n, + ret_ty, + out_len + ); + require!( + in_elem == out_ty, + "expected return element type `{}` (element of input `{}`), \ + found `{}` with element type `{}`", + in_elem, + in_ty, + ret_ty, + out_ty + ); + + let vector = args[2].immediate(); + + return Ok(bx.shuffle_vector( + args[0].immediate(), + args[1].immediate(), + vector, + )); + } + + macro_rules! arith_binary { + ($($name: ident: $($($p: ident),* => $call: ident),*;)*) => { + $(if name == sym::$name { + match in_elem.kind() { + $($(ty::$p(_))|* => { + return Ok(bx.$call(args[0].immediate(), args[1].immediate())) + })* + _ => {}, + } + require!(false, + "unsupported operation on `{}` with element `{}`", + in_ty, + in_elem) + })* + } + } + + arith_binary! { + simd_add: Uint, Int => add, Float => fadd; + simd_sub: Uint, Int => sub, Float => fsub; + simd_mul: Uint, Int => mul, Float => fmul; + simd_div: Uint => udiv, Int => sdiv, Float => fdiv; + simd_rem: Uint => urem, Int => srem, Float => frem; + simd_shl: Uint, Int => shl; + simd_shr: Uint => lshr, Int => ashr; + simd_and: Uint, Int => and; + simd_or: Uint, Int => or; // FIXME(antoyo): calling `or` might not work on vectors. + simd_xor: Uint, Int => xor; + } + + unimplemented!("simd {}", name); +} diff --git a/compiler/rustc_codegen_gcc/src/lib.rs b/compiler/rustc_codegen_gcc/src/lib.rs new file mode 100644 index 0000000000..629003d798 --- /dev/null +++ b/compiler/rustc_codegen_gcc/src/lib.rs @@ -0,0 +1,293 @@ +/* + * TODO(antoyo): support #[inline] attributes. + * TODO(antoyo): support LTO. + * + * TODO(antoyo): remove the patches. + */ + +#![feature(rustc_private, decl_macro, associated_type_bounds, never_type, trusted_len)] +#![allow(broken_intra_doc_links)] +#![recursion_limit="256"] +#![warn(rust_2018_idioms)] +#![warn(unused_lifetimes)] + +extern crate rustc_ast; +extern crate rustc_codegen_ssa; +extern crate rustc_data_structures; +extern crate rustc_errors; +extern crate rustc_hir; +extern crate rustc_metadata; +extern crate rustc_middle; +extern crate rustc_session; +extern crate rustc_span; +extern crate rustc_symbol_mangling; +extern crate rustc_target; +extern crate snap; + +// This prevents duplicating functions and statics that are already part of the host rustc process. +#[allow(unused_extern_crates)] +extern crate rustc_driver; + +mod abi; +mod allocator; +mod archive; +mod asm; +mod back; +mod base; +mod builder; +mod callee; +mod common; +mod consts; +mod context; +mod coverageinfo; +mod debuginfo; +mod declare; +mod intrinsic; +mod mono_item; +mod type_; +mod type_of; + +use std::any::Any; +use std::sync::Arc; + +use gccjit::{Context, OptimizationLevel}; +use rustc_ast::expand::allocator::AllocatorKind; +use rustc_codegen_ssa::{CodegenResults, CompiledModule, ModuleCodegen}; +use rustc_codegen_ssa::base::codegen_crate; +use rustc_codegen_ssa::back::write::{CodegenContext, FatLTOInput, ModuleConfig, TargetMachineFactoryFn}; +use rustc_codegen_ssa::back::lto::{LtoModuleCodegen, SerializedModule, ThinModule}; +use rustc_codegen_ssa::target_features::supported_target_features; +use rustc_codegen_ssa::traits::{CodegenBackend, ExtraBackendMethods, ModuleBufferMethods, ThinBufferMethods, WriteBackendMethods}; +use rustc_data_structures::fx::FxHashMap; +use rustc_errors::{ErrorReported, Handler}; +use rustc_metadata::EncodedMetadata; +use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; +use rustc_middle::ty::TyCtxt; +use rustc_session::config::{Lto, OptLevel, OutputFilenames}; +use rustc_session::Session; +use rustc_span::Symbol; +use rustc_span::fatal_error::FatalError; + +pub struct PrintOnPanic String>(pub F); + +impl String> Drop for PrintOnPanic { + fn drop(&mut self) { + if ::std::thread::panicking() { + println!("{}", (self.0)()); + } + } +} + +#[derive(Clone)] +pub struct GccCodegenBackend; + +impl CodegenBackend for GccCodegenBackend { + fn init(&self, sess: &Session) { + if sess.lto() != Lto::No { + sess.warn("LTO is not supported. You may get a linker error."); + } + } + + fn codegen_crate<'tcx>(&self, tcx: TyCtxt<'tcx>, metadata: EncodedMetadata, need_metadata_module: bool) -> Box { + let target_cpu = target_cpu(tcx.sess); + let res = codegen_crate(self.clone(), tcx, target_cpu.to_string(), metadata, need_metadata_module); + + rustc_symbol_mangling::test::report_symbol_names(tcx); + + Box::new(res) + } + + fn join_codegen(&self, ongoing_codegen: Box, sess: &Session) -> Result<(CodegenResults, FxHashMap), ErrorReported> { + let (codegen_results, work_products) = ongoing_codegen + .downcast::>() + .expect("Expected GccCodegenBackend's OngoingCodegen, found Box") + .join(sess); + + Ok((codegen_results, work_products)) + } + + fn link(&self, sess: &Session, codegen_results: CodegenResults, outputs: &OutputFilenames) -> Result<(), ErrorReported> { + use rustc_codegen_ssa::back::link::link_binary; + + link_binary::>( + sess, + &codegen_results, + outputs, + ) + } + + fn target_features(&self, sess: &Session) -> Vec { + target_features(sess) + } +} + +impl ExtraBackendMethods for GccCodegenBackend { + fn new_metadata<'tcx>(&self, _tcx: TyCtxt<'tcx>, _mod_name: &str) -> Self::Module { + GccContext { + context: Context::default(), + } + } + + fn write_compressed_metadata<'tcx>(&self, tcx: TyCtxt<'tcx>, metadata: &EncodedMetadata, gcc_module: &mut Self::Module) { + base::write_compressed_metadata(tcx, metadata, gcc_module) + } + + fn codegen_allocator<'tcx>(&self, tcx: TyCtxt<'tcx>, mods: &mut Self::Module, module_name: &str, kind: AllocatorKind, has_alloc_error_handler: bool) { + unsafe { allocator::codegen(tcx, mods, module_name, kind, has_alloc_error_handler) } + } + + fn compile_codegen_unit<'tcx>(&self, tcx: TyCtxt<'tcx>, cgu_name: Symbol) -> (ModuleCodegen, u64) { + base::compile_codegen_unit(tcx, cgu_name) + } + + fn target_machine_factory(&self, _sess: &Session, _opt_level: OptLevel) -> TargetMachineFactoryFn { + // TODO(antoyo): set opt level. + Arc::new(|_| { + Ok(()) + }) + } + + fn target_cpu<'b>(&self, _sess: &'b Session) -> &'b str { + unimplemented!(); + } + + fn tune_cpu<'b>(&self, _sess: &'b Session) -> Option<&'b str> { + None + // TODO(antoyo) + } +} + +pub struct ModuleBuffer; + +impl ModuleBufferMethods for ModuleBuffer { + fn data(&self) -> &[u8] { + unimplemented!(); + } +} + +pub struct ThinBuffer; + +impl ThinBufferMethods for ThinBuffer { + fn data(&self) -> &[u8] { + unimplemented!(); + } +} + +pub struct GccContext { + context: Context<'static>, +} + +unsafe impl Send for GccContext {} +// FIXME(antoyo): that shouldn't be Sync. Parallel compilation is currently disabled with "-Zno-parallel-llvm". Try to disable it here. +unsafe impl Sync for GccContext {} + +impl WriteBackendMethods for GccCodegenBackend { + type Module = GccContext; + type TargetMachine = (); + type ModuleBuffer = ModuleBuffer; + type Context = (); + type ThinData = (); + type ThinBuffer = ThinBuffer; + + fn run_fat_lto(_cgcx: &CodegenContext, mut modules: Vec>, _cached_modules: Vec<(SerializedModule, WorkProduct)>) -> Result, FatalError> { + // TODO(antoyo): implement LTO by sending -flto to libgccjit and adding the appropriate gcc linker plugins. + // NOTE: implemented elsewhere. + // TODO: what is implemented elsewhere ^ ? + let module = + match modules.remove(0) { + FatLTOInput::InMemory(module) => module, + FatLTOInput::Serialized { .. } => { + unimplemented!(); + } + }; + Ok(LtoModuleCodegen::Fat { module: Some(module), _serialized_bitcode: vec![] }) + } + + fn run_thin_lto(_cgcx: &CodegenContext, _modules: Vec<(String, Self::ThinBuffer)>, _cached_modules: Vec<(SerializedModule, WorkProduct)>) -> Result<(Vec>, Vec), FatalError> { + unimplemented!(); + } + + fn print_pass_timings(&self) { + unimplemented!(); + } + + unsafe fn optimize(_cgcx: &CodegenContext, _diag_handler: &Handler, module: &ModuleCodegen, config: &ModuleConfig) -> Result<(), FatalError> { + module.module_llvm.context.set_optimization_level(to_gcc_opt_level(config.opt_level)); + Ok(()) + } + + unsafe fn optimize_thin(_cgcx: &CodegenContext, _thin: &mut ThinModule) -> Result, FatalError> { + unimplemented!(); + } + + unsafe fn codegen(cgcx: &CodegenContext, diag_handler: &Handler, module: ModuleCodegen, config: &ModuleConfig) -> Result { + back::write::codegen(cgcx, diag_handler, module, config) + } + + fn prepare_thin(_module: ModuleCodegen) -> (String, Self::ThinBuffer) { + unimplemented!(); + } + + fn serialize_module(_module: ModuleCodegen) -> (String, Self::ModuleBuffer) { + unimplemented!(); + } + + fn run_lto_pass_manager(_cgcx: &CodegenContext, _module: &ModuleCodegen, _config: &ModuleConfig, _thin: bool) -> Result<(), FatalError> { + // TODO(antoyo) + Ok(()) + } + + fn run_link(cgcx: &CodegenContext, diag_handler: &Handler, modules: Vec>) -> Result, FatalError> { + back::write::link(cgcx, diag_handler, modules) + } +} + +/// This is the entrypoint for a hot plugged rustc_codegen_gccjit +#[no_mangle] +pub fn __rustc_codegen_backend() -> Box { + Box::new(GccCodegenBackend) +} + +fn to_gcc_opt_level(optlevel: Option) -> OptimizationLevel { + match optlevel { + None => OptimizationLevel::None, + Some(level) => { + match level { + OptLevel::No => OptimizationLevel::None, + OptLevel::Less => OptimizationLevel::Limited, + OptLevel::Default => OptimizationLevel::Standard, + OptLevel::Aggressive => OptimizationLevel::Aggressive, + OptLevel::Size | OptLevel::SizeMin => OptimizationLevel::Limited, + } + }, + } +} + +fn handle_native(name: &str) -> &str { + if name != "native" { + return name; + } + + unimplemented!(); +} + +pub fn target_cpu(sess: &Session) -> &str { + let name = sess.opts.cg.target_cpu.as_ref().unwrap_or(&sess.target.cpu); + handle_native(name) +} + +pub fn target_features(sess: &Session) -> Vec { + supported_target_features(sess) + .iter() + .filter_map( + |&(feature, gate)| { + if sess.is_nightly_build() || gate.is_none() { Some(feature) } else { None } + }, + ) + .filter(|_feature| { + // TODO(antoyo): implement a way to get enabled feature in libgccjit. + false + }) + .map(|feature| Symbol::intern(feature)) + .collect() +} diff --git a/compiler/rustc_codegen_gcc/src/mono_item.rs b/compiler/rustc_codegen_gcc/src/mono_item.rs new file mode 100644 index 0000000000..e21d40b6c3 --- /dev/null +++ b/compiler/rustc_codegen_gcc/src/mono_item.rs @@ -0,0 +1,38 @@ +use rustc_codegen_ssa::traits::PreDefineMethods; +use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; +use rustc_middle::mir::mono::{Linkage, Visibility}; +use rustc_middle::ty::{self, Instance, TypeFoldable}; +use rustc_middle::ty::layout::{FnAbiOf, LayoutOf}; +use rustc_span::def_id::DefId; + +use crate::base; +use crate::context::CodegenCx; +use crate::type_of::LayoutGccExt; + +impl<'gcc, 'tcx> PreDefineMethods<'tcx> for CodegenCx<'gcc, 'tcx> { + fn predefine_static(&self, def_id: DefId, _linkage: Linkage, _visibility: Visibility, symbol_name: &str) { + let attrs = self.tcx.codegen_fn_attrs(def_id); + let instance = Instance::mono(self.tcx, def_id); + let ty = instance.ty(self.tcx, ty::ParamEnv::reveal_all()); + let gcc_type = self.layout_of(ty).gcc_type(self, true); + + let is_tls = attrs.flags.contains(CodegenFnAttrFlags::THREAD_LOCAL); + let global = self.define_global(symbol_name, gcc_type, is_tls, attrs.link_section); + + // TODO(antoyo): set linkage and visibility. + self.instances.borrow_mut().insert(instance, global); + } + + fn predefine_fn(&self, instance: Instance<'tcx>, linkage: Linkage, _visibility: Visibility, symbol_name: &str) { + assert!(!instance.substs.needs_infer()); + + let fn_abi = self.fn_abi_of_instance(instance, ty::List::empty()); + self.linkage.set(base::linkage_to_gcc(linkage)); + let _decl = self.declare_fn(symbol_name, &fn_abi); + //let attrs = self.tcx.codegen_fn_attrs(instance.def_id()); + + // TODO(antoyo): call set_link_section() to allow initializing argc/argv. + // TODO(antoyo): set unique comdat. + // TODO(antoyo): use inline attribute from there in linkage.set() above. + } +} diff --git a/compiler/rustc_codegen_gcc/src/type_.rs b/compiler/rustc_codegen_gcc/src/type_.rs new file mode 100644 index 0000000000..3545e1b628 --- /dev/null +++ b/compiler/rustc_codegen_gcc/src/type_.rs @@ -0,0 +1,282 @@ +use std::convert::TryInto; + +use gccjit::{RValue, Struct, Type}; +use rustc_codegen_ssa::traits::{BaseTypeMethods, DerivedTypeMethods}; +use rustc_codegen_ssa::common::TypeKind; +use rustc_middle::bug; +use rustc_middle::ty::layout::TyAndLayout; +use rustc_target::abi::{AddressSpace, Align, Integer, Size}; + +use crate::common::TypeReflection; +use crate::context::CodegenCx; +use crate::type_of::LayoutGccExt; + +impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { + pub fn type_ix(&self, num_bits: u64) -> Type<'gcc> { + // gcc only supports 1, 2, 4 or 8-byte integers. + // FIXME(antoyo): this is misleading to use the next power of two as rustc_codegen_ssa + // sometimes use 96-bit numbers and the following code will give an integer of a different + // size. + let bytes = (num_bits / 8).next_power_of_two() as i32; + match bytes { + 1 => self.i8_type, + 2 => self.i16_type, + 4 => self.i32_type, + 8 => self.i64_type, + 16 => self.i128_type, + _ => panic!("unexpected num_bits: {}", num_bits), + } + } + + pub fn type_void(&self) -> Type<'gcc> { + self.context.new_type::<()>() + } + + pub fn type_size_t(&self) -> Type<'gcc> { + self.context.new_type::() + } + + pub fn type_u8(&self) -> Type<'gcc> { + self.u8_type + } + + pub fn type_u16(&self) -> Type<'gcc> { + self.u16_type + } + + pub fn type_u32(&self) -> Type<'gcc> { + self.u32_type + } + + pub fn type_u64(&self) -> Type<'gcc> { + self.u64_type + } + + pub fn type_u128(&self) -> Type<'gcc> { + self.u128_type + } + + pub fn type_pointee_for_align(&self, align: Align) -> Type<'gcc> { + // FIXME(eddyb) We could find a better approximation if ity.align < align. + let ity = Integer::approximate_align(self, align); + self.type_from_integer(ity) + } +} + +impl<'gcc, 'tcx> BaseTypeMethods<'tcx> for CodegenCx<'gcc, 'tcx> { + fn type_i1(&self) -> Type<'gcc> { + self.bool_type + } + + fn type_i8(&self) -> Type<'gcc> { + self.i8_type + } + + fn type_i16(&self) -> Type<'gcc> { + self.i16_type + } + + fn type_i32(&self) -> Type<'gcc> { + self.i32_type + } + + fn type_i64(&self) -> Type<'gcc> { + self.i64_type + } + + fn type_i128(&self) -> Type<'gcc> { + self.i128_type + } + + fn type_isize(&self) -> Type<'gcc> { + self.isize_type + } + + fn type_f32(&self) -> Type<'gcc> { + self.context.new_type::() + } + + fn type_f64(&self) -> Type<'gcc> { + self.context.new_type::() + } + + fn type_func(&self, params: &[Type<'gcc>], return_type: Type<'gcc>) -> Type<'gcc> { + self.context.new_function_pointer_type(None, return_type, params, false) + } + + fn type_struct(&self, fields: &[Type<'gcc>], _packed: bool) -> Type<'gcc> { + let types = fields.to_vec(); + if let Some(typ) = self.struct_types.borrow().get(fields) { + return typ.clone(); + } + let fields: Vec<_> = fields.iter().enumerate() + .map(|(index, field)| self.context.new_field(None, *field, &format!("field{}_TODO", index))) + .collect(); + // TODO(antoyo): use packed. + let typ = self.context.new_struct_type(None, "struct", &fields).as_type(); + self.struct_types.borrow_mut().insert(types, typ); + typ + } + + fn type_kind(&self, typ: Type<'gcc>) -> TypeKind { + if typ.is_integral() { + TypeKind::Integer + } + else if typ.is_vector().is_some() { + TypeKind::Vector + } + else { + // TODO(antoyo): support other types. + TypeKind::Void + } + } + + fn type_ptr_to(&self, ty: Type<'gcc>) -> Type<'gcc> { + ty.make_pointer() + } + + fn type_ptr_to_ext(&self, ty: Type<'gcc>, _address_space: AddressSpace) -> Type<'gcc> { + // TODO(antoyo): use address_space + ty.make_pointer() + } + + fn element_type(&self, ty: Type<'gcc>) -> Type<'gcc> { + if let Some(typ) = ty.is_array() { + typ + } + else if let Some(vector_type) = ty.is_vector() { + vector_type.get_element_type() + } + else if let Some(typ) = ty.get_pointee() { + typ + } + else { + unreachable!() + } + } + + fn vector_length(&self, _ty: Type<'gcc>) -> usize { + unimplemented!(); + } + + fn float_width(&self, typ: Type<'gcc>) -> usize { + let f32 = self.context.new_type::(); + let f64 = self.context.new_type::(); + if typ == f32 { + 32 + } + else if typ == f64 { + 64 + } + else { + panic!("Cannot get width of float type {:?}", typ); + } + // TODO(antoyo): support other sizes. + } + + fn int_width(&self, typ: Type<'gcc>) -> u64 { + if typ.is_i8(self) || typ.is_u8(self) { + 8 + } + else if typ.is_i16(self) || typ.is_u16(self) { + 16 + } + else if typ.is_i32(self) || typ.is_u32(self) { + 32 + } + else if typ.is_i64(self) || typ.is_u64(self) { + 64 + } + else if typ.is_i128(self) || typ.is_u128(self) { + 128 + } + else { + panic!("Cannot get width of int type {:?}", typ); + } + } + + fn val_ty(&self, value: RValue<'gcc>) -> Type<'gcc> { + value.get_type() + } +} + +impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { + pub fn type_padding_filler(&self, size: Size, align: Align) -> Type<'gcc> { + let unit = Integer::approximate_align(self, align); + let size = size.bytes(); + let unit_size = unit.size().bytes(); + assert_eq!(size % unit_size, 0); + self.type_array(self.type_from_integer(unit), size / unit_size) + } + + pub fn set_struct_body(&self, typ: Struct<'gcc>, fields: &[Type<'gcc>], _packed: bool) { + // TODO(antoyo): use packed. + let fields: Vec<_> = fields.iter().enumerate() + .map(|(index, field)| self.context.new_field(None, *field, &format!("field_{}", index))) + .collect(); + typ.set_fields(None, &fields); + } + + pub fn type_named_struct(&self, name: &str) -> Struct<'gcc> { + self.context.new_opaque_struct_type(None, name) + } + + pub fn type_array(&self, ty: Type<'gcc>, mut len: u64) -> Type<'gcc> { + if let Some(struct_type) = ty.is_struct() { + if struct_type.get_field_count() == 0 { + // NOTE: since gccjit only supports i32 for the array size and libcore's tests uses a + // size of usize::MAX in test_binary_search, we workaround this by setting the size to + // zero for ZSTs. + // FIXME(antoyo): fix gccjit API. + len = 0; + } + } + + // NOTE: see note above. Some other test uses usize::MAX. + if len == u64::MAX { + len = 0; + } + + let len: i32 = len.try_into().expect("array len"); + + self.context.new_array_type(None, ty, len) + } +} + +pub fn struct_fields<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, layout: TyAndLayout<'tcx>) -> (Vec>, bool) { + let field_count = layout.fields.count(); + + let mut packed = false; + let mut offset = Size::ZERO; + let mut prev_effective_align = layout.align.abi; + let mut result: Vec<_> = Vec::with_capacity(1 + field_count * 2); + for i in layout.fields.index_by_increasing_offset() { + let target_offset = layout.fields.offset(i as usize); + let field = layout.field(cx, i); + let effective_field_align = + layout.align.abi.min(field.align.abi).restrict_for_offset(target_offset); + packed |= effective_field_align < field.align.abi; + + assert!(target_offset >= offset); + let padding = target_offset - offset; + let padding_align = prev_effective_align.min(effective_field_align); + assert_eq!(offset.align_to(padding_align) + padding, target_offset); + result.push(cx.type_padding_filler(padding, padding_align)); + + result.push(field.gcc_type(cx, !field.ty.is_any_ptr())); // FIXME(antoyo): might need to check if the type is inside another, like Box. + offset = target_offset + field.size; + prev_effective_align = effective_field_align; + } + if !layout.is_unsized() && field_count > 0 { + if offset > layout.size { + bug!("layout: {:#?} stride: {:?} offset: {:?}", layout, layout.size, offset); + } + let padding = layout.size - offset; + let padding_align = prev_effective_align; + assert_eq!(offset.align_to(padding_align) + padding, layout.size); + result.push(cx.type_padding_filler(padding, padding_align)); + assert_eq!(result.len(), 1 + field_count * 2); + } + + (result, packed) +} diff --git a/compiler/rustc_codegen_gcc/src/type_of.rs b/compiler/rustc_codegen_gcc/src/type_of.rs new file mode 100644 index 0000000000..9c39c8f91a --- /dev/null +++ b/compiler/rustc_codegen_gcc/src/type_of.rs @@ -0,0 +1,359 @@ +use std::fmt::Write; + +use gccjit::{Struct, Type}; +use crate::rustc_codegen_ssa::traits::{BaseTypeMethods, DerivedTypeMethods, LayoutTypeMethods}; +use rustc_middle::bug; +use rustc_middle::ty::{self, Ty, TypeFoldable}; +use rustc_middle::ty::layout::{FnAbiOf, LayoutOf, TyAndLayout}; +use rustc_middle::ty::print::with_no_trimmed_paths; +use rustc_target::abi::{self, Abi, F32, F64, FieldsShape, Int, Integer, Pointer, PointeeInfo, Size, TyAbiInterface, Variants}; +use rustc_target::abi::call::{CastTarget, FnAbi, Reg}; + +use crate::abi::{FnAbiGccExt, GccType}; +use crate::context::CodegenCx; +use crate::type_::struct_fields; + +impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { + fn type_from_unsigned_integer(&self, i: Integer) -> Type<'gcc> { + use Integer::*; + match i { + I8 => self.type_u8(), + I16 => self.type_u16(), + I32 => self.type_u32(), + I64 => self.type_u64(), + I128 => self.type_u128(), + } + } +} + +pub fn uncached_gcc_type<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, layout: TyAndLayout<'tcx>, defer: &mut Option<(Struct<'gcc>, TyAndLayout<'tcx>)>) -> Type<'gcc> { + match layout.abi { + Abi::Scalar(_) => bug!("handled elsewhere"), + Abi::Vector { ref element, count } => { + let element = layout.scalar_gcc_type_at(cx, element, Size::ZERO); + return cx.context.new_vector_type(element, count); + }, + Abi::ScalarPair(..) => { + return cx.type_struct( + &[ + layout.scalar_pair_element_gcc_type(cx, 0, false), + layout.scalar_pair_element_gcc_type(cx, 1, false), + ], + false, + ); + } + Abi::Uninhabited | Abi::Aggregate { .. } => {} + } + + let name = match layout.ty.kind() { + // FIXME(eddyb) producing readable type names for trait objects can result + // in problematically distinct types due to HRTB and subtyping (see #47638). + // ty::Dynamic(..) | + ty::Adt(..) | ty::Closure(..) | ty::Foreign(..) | ty::Generator(..) | ty::Str + if !cx.sess().fewer_names() => + { + let mut name = with_no_trimmed_paths(|| layout.ty.to_string()); + if let (&ty::Adt(def, _), &Variants::Single { index }) = + (layout.ty.kind(), &layout.variants) + { + if def.is_enum() && !def.variants.is_empty() { + write!(&mut name, "::{}", def.variants[index].ident).unwrap(); + } + } + if let (&ty::Generator(_, _, _), &Variants::Single { index }) = + (layout.ty.kind(), &layout.variants) + { + write!(&mut name, "::{}", ty::GeneratorSubsts::variant_name(index)).unwrap(); + } + Some(name) + } + ty::Adt(..) => { + // If `Some` is returned then a named struct is created in LLVM. Name collisions are + // avoided by LLVM (with increasing suffixes). If rustc doesn't generate names then that + // can improve perf. + // FIXME(antoyo): I don't think that's true for libgccjit. + Some(String::new()) + } + _ => None, + }; + + match layout.fields { + FieldsShape::Primitive | FieldsShape::Union(_) => { + let fill = cx.type_padding_filler(layout.size, layout.align.abi); + let packed = false; + match name { + None => cx.type_struct(&[fill], packed), + Some(ref name) => { + let gcc_type = cx.type_named_struct(name); + cx.set_struct_body(gcc_type, &[fill], packed); + gcc_type.as_type() + }, + } + } + FieldsShape::Array { count, .. } => cx.type_array(layout.field(cx, 0).gcc_type(cx, true), count), + FieldsShape::Arbitrary { .. } => + match name { + None => { + let (gcc_fields, packed) = struct_fields(cx, layout); + cx.type_struct(&gcc_fields, packed) + }, + Some(ref name) => { + let gcc_type = cx.type_named_struct(name); + *defer = Some((gcc_type, layout)); + gcc_type.as_type() + }, + }, + } +} + +pub trait LayoutGccExt<'tcx> { + fn is_gcc_immediate(&self) -> bool; + fn is_gcc_scalar_pair(&self) -> bool; + fn gcc_type<'gcc>(&self, cx: &CodegenCx<'gcc, 'tcx>, set_fields: bool) -> Type<'gcc>; + fn immediate_gcc_type<'gcc>(&self, cx: &CodegenCx<'gcc, 'tcx>) -> Type<'gcc>; + fn scalar_gcc_type_at<'gcc>(&self, cx: &CodegenCx<'gcc, 'tcx>, scalar: &abi::Scalar, offset: Size) -> Type<'gcc>; + fn scalar_pair_element_gcc_type<'gcc>(&self, cx: &CodegenCx<'gcc, 'tcx>, index: usize, immediate: bool) -> Type<'gcc>; + fn gcc_field_index(&self, index: usize) -> u64; + fn pointee_info_at<'gcc>(&self, cx: &CodegenCx<'gcc, 'tcx>, offset: Size) -> Option; +} + +impl<'tcx> LayoutGccExt<'tcx> for TyAndLayout<'tcx> { + fn is_gcc_immediate(&self) -> bool { + match self.abi { + Abi::Scalar(_) | Abi::Vector { .. } => true, + Abi::ScalarPair(..) => false, + Abi::Uninhabited | Abi::Aggregate { .. } => self.is_zst(), + } + } + + fn is_gcc_scalar_pair(&self) -> bool { + match self.abi { + Abi::ScalarPair(..) => true, + Abi::Uninhabited | Abi::Scalar(_) | Abi::Vector { .. } | Abi::Aggregate { .. } => false, + } + } + + /// Gets the GCC type corresponding to a Rust type, i.e., `rustc_middle::ty::Ty`. + /// The pointee type of the pointer in `PlaceRef` is always this type. + /// For sized types, it is also the right LLVM type for an `alloca` + /// containing a value of that type, and most immediates (except `bool`). + /// Unsized types, however, are represented by a "minimal unit", e.g. + /// `[T]` becomes `T`, while `str` and `Trait` turn into `i8` - this + /// is useful for indexing slices, as `&[T]`'s data pointer is `T*`. + /// If the type is an unsized struct, the regular layout is generated, + /// with the inner-most trailing unsized field using the "minimal unit" + /// of that field's type - this is useful for taking the address of + /// that field and ensuring the struct has the right alignment. + //TODO(antoyo): do we still need the set_fields parameter? + fn gcc_type<'gcc>(&self, cx: &CodegenCx<'gcc, 'tcx>, set_fields: bool) -> Type<'gcc> { + if let Abi::Scalar(ref scalar) = self.abi { + // Use a different cache for scalars because pointers to DSTs + // can be either fat or thin (data pointers of fat pointers). + if let Some(&ty) = cx.scalar_types.borrow().get(&self.ty) { + return ty; + } + let ty = + match *self.ty.kind() { + ty::Ref(_, ty, _) | ty::RawPtr(ty::TypeAndMut { ty, .. }) => { + cx.type_ptr_to(cx.layout_of(ty).gcc_type(cx, set_fields)) + } + ty::Adt(def, _) if def.is_box() => { + cx.type_ptr_to(cx.layout_of(self.ty.boxed_ty()).gcc_type(cx, true)) + } + ty::FnPtr(sig) => cx.fn_ptr_backend_type(&cx.fn_abi_of_fn_ptr(sig, ty::List::empty())), + _ => self.scalar_gcc_type_at(cx, scalar, Size::ZERO), + }; + cx.scalar_types.borrow_mut().insert(self.ty, ty); + return ty; + } + + // Check the cache. + let variant_index = + match self.variants { + Variants::Single { index } => Some(index), + _ => None, + }; + let cached_type = cx.types.borrow().get(&(self.ty, variant_index)).cloned(); + if let Some(ty) = cached_type { + let type_to_set_fields = cx.types_with_fields_to_set.borrow_mut().remove(&ty); + if let Some((struct_type, layout)) = type_to_set_fields { + // Since we might be trying to generate a type containing another type which is not + // completely generated yet, we deferred setting the fields until now. + let (fields, packed) = struct_fields(cx, layout); + cx.set_struct_body(struct_type, &fields, packed); + } + return ty; + } + + assert!(!self.ty.has_escaping_bound_vars(), "{:?} has escaping bound vars", self.ty); + + // Make sure lifetimes are erased, to avoid generating distinct LLVM + // types for Rust types that only differ in the choice of lifetimes. + let normal_ty = cx.tcx.erase_regions(self.ty); + + let mut defer = None; + let ty = + if self.ty != normal_ty { + let mut layout = cx.layout_of(normal_ty); + if let Some(v) = variant_index { + layout = layout.for_variant(cx, v); + } + layout.gcc_type(cx, true) + } + else { + uncached_gcc_type(cx, *self, &mut defer) + }; + + cx.types.borrow_mut().insert((self.ty, variant_index), ty); + + if let Some((ty, layout)) = defer { + let (fields, packed) = struct_fields(cx, layout); + cx.set_struct_body(ty, &fields, packed); + } + + ty + } + + fn immediate_gcc_type<'gcc>(&self, cx: &CodegenCx<'gcc, 'tcx>) -> Type<'gcc> { + if let Abi::Scalar(ref scalar) = self.abi { + if scalar.is_bool() { + return cx.type_i1(); + } + } + self.gcc_type(cx, true) + } + + fn scalar_gcc_type_at<'gcc>(&self, cx: &CodegenCx<'gcc, 'tcx>, scalar: &abi::Scalar, offset: Size) -> Type<'gcc> { + match scalar.value { + Int(i, true) => cx.type_from_integer(i), + Int(i, false) => cx.type_from_unsigned_integer(i), + F32 => cx.type_f32(), + F64 => cx.type_f64(), + Pointer => { + // If we know the alignment, pick something better than i8. + let pointee = + if let Some(pointee) = self.pointee_info_at(cx, offset) { + cx.type_pointee_for_align(pointee.align) + } + else { + cx.type_i8() + }; + cx.type_ptr_to(pointee) + } + } + } + + fn scalar_pair_element_gcc_type<'gcc>(&self, cx: &CodegenCx<'gcc, 'tcx>, index: usize, immediate: bool) -> Type<'gcc> { + // TODO(antoyo): remove llvm hack: + // HACK(eddyb) special-case fat pointers until LLVM removes + // pointee types, to avoid bitcasting every `OperandRef::deref`. + match self.ty.kind() { + ty::Ref(..) | ty::RawPtr(_) => { + return self.field(cx, index).gcc_type(cx, true); + } + ty::Adt(def, _) if def.is_box() => { + let ptr_ty = cx.tcx.mk_mut_ptr(self.ty.boxed_ty()); + return cx.layout_of(ptr_ty).scalar_pair_element_gcc_type(cx, index, immediate); + } + _ => {} + } + + let (a, b) = match self.abi { + Abi::ScalarPair(ref a, ref b) => (a, b), + _ => bug!("TyAndLayout::scalar_pair_element_llty({:?}): not applicable", self), + }; + let scalar = [a, b][index]; + + // Make sure to return the same type `immediate_gcc_type` would when + // dealing with an immediate pair. This means that `(bool, bool)` is + // effectively represented as `{i8, i8}` in memory and two `i1`s as an + // immediate, just like `bool` is typically `i8` in memory and only `i1` + // when immediate. We need to load/store `bool` as `i8` to avoid + // crippling LLVM optimizations or triggering other LLVM bugs with `i1`. + // TODO(antoyo): this bugs certainly don't happen in this case since the bool type is used instead of i1. + if scalar.is_bool() { + return cx.type_i1(); + } + + let offset = + if index == 0 { + Size::ZERO + } + else { + a.value.size(cx).align_to(b.value.align(cx).abi) + }; + self.scalar_gcc_type_at(cx, scalar, offset) + } + + fn gcc_field_index(&self, index: usize) -> u64 { + match self.abi { + Abi::Scalar(_) | Abi::ScalarPair(..) => { + bug!("TyAndLayout::gcc_field_index({:?}): not applicable", self) + } + _ => {} + } + match self.fields { + FieldsShape::Primitive | FieldsShape::Union(_) => { + bug!("TyAndLayout::gcc_field_index({:?}): not applicable", self) + } + + FieldsShape::Array { .. } => index as u64, + + FieldsShape::Arbitrary { .. } => 1 + (self.fields.memory_index(index) as u64) * 2, + } + } + + fn pointee_info_at<'a>(&self, cx: &CodegenCx<'a, 'tcx>, offset: Size) -> Option { + if let Some(&pointee) = cx.pointee_infos.borrow().get(&(self.ty, offset)) { + return pointee; + } + + let result = Ty::ty_and_layout_pointee_info_at(*self, cx, offset); + + cx.pointee_infos.borrow_mut().insert((self.ty, offset), result); + result + } +} + +impl<'gcc, 'tcx> LayoutTypeMethods<'tcx> for CodegenCx<'gcc, 'tcx> { + fn backend_type(&self, layout: TyAndLayout<'tcx>) -> Type<'gcc> { + layout.gcc_type(self, true) + } + + fn immediate_backend_type(&self, layout: TyAndLayout<'tcx>) -> Type<'gcc> { + layout.immediate_gcc_type(self) + } + + fn is_backend_immediate(&self, layout: TyAndLayout<'tcx>) -> bool { + layout.is_gcc_immediate() + } + + fn is_backend_scalar_pair(&self, layout: TyAndLayout<'tcx>) -> bool { + layout.is_gcc_scalar_pair() + } + + fn backend_field_index(&self, layout: TyAndLayout<'tcx>, index: usize) -> u64 { + layout.gcc_field_index(index) + } + + fn scalar_pair_element_backend_type(&self, layout: TyAndLayout<'tcx>, index: usize, immediate: bool) -> Type<'gcc> { + layout.scalar_pair_element_gcc_type(self, index, immediate) + } + + fn cast_backend_type(&self, ty: &CastTarget) -> Type<'gcc> { + ty.gcc_type(self) + } + + fn fn_ptr_backend_type(&self, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> Type<'gcc> { + fn_abi.ptr_to_gcc_type(self) + } + + fn reg_backend_type(&self, _ty: &Reg) -> Type<'gcc> { + unimplemented!(); + } + + fn fn_decl_backend_type(&self, _fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> Type<'gcc> { + // FIXME(antoyo): return correct type. + self.type_void() + } +} diff --git a/compiler/rustc_codegen_gcc/test.sh b/compiler/rustc_codegen_gcc/test.sh new file mode 100755 index 0000000000..944d0ce516 --- /dev/null +++ b/compiler/rustc_codegen_gcc/test.sh @@ -0,0 +1,217 @@ +#!/bin/bash + +# TODO(antoyo): rewrite to cargo-make (or just) or something like that to only rebuild the sysroot when needed? + +set -e + +if [ -f ./gcc_path ]; then + export GCC_PATH=$(cat gcc_path) +else + echo 'Please put the path to your custom build of libgccjit in the file `gcc_path`, see Readme.md for details' + exit 1 +fi + +export LD_LIBRARY_PATH="$GCC_PATH" +export LIBRARY_PATH="$GCC_PATH" + +if [[ "$1" == "--release" ]]; then + export CHANNEL='release' + CARGO_INCREMENTAL=1 cargo rustc --release + shift +else + echo $LD_LIBRARY_PATH + export CHANNEL='debug' + cargo rustc +fi + +source config.sh + +function clean() { + rm -r target/out || true + mkdir -p target/out/gccjit +} + +function mini_tests() { + echo "[BUILD] mini_core" + $RUSTC example/mini_core.rs --crate-name mini_core --crate-type lib,dylib --target $TARGET_TRIPLE + + echo "[BUILD] example" + $RUSTC example/example.rs --crate-type lib --target $TARGET_TRIPLE + + echo "[AOT] mini_core_hello_world" + $RUSTC example/mini_core_hello_world.rs --crate-name mini_core_hello_world --crate-type bin -g --target $TARGET_TRIPLE + $RUN_WRAPPER ./target/out/mini_core_hello_world abc bcd +} + +function build_sysroot() { + echo "[BUILD] sysroot" + time ./build_sysroot/build_sysroot.sh +} + +function std_tests() { + echo "[AOT] arbitrary_self_types_pointers_and_wrappers" + $RUSTC example/arbitrary_self_types_pointers_and_wrappers.rs --crate-name arbitrary_self_types_pointers_and_wrappers --crate-type bin --target $TARGET_TRIPLE + $RUN_WRAPPER ./target/out/arbitrary_self_types_pointers_and_wrappers + + echo "[AOT] alloc_system" + $RUSTC example/alloc_system.rs --crate-type lib --target "$TARGET_TRIPLE" + + echo "[AOT] alloc_example" + $RUSTC example/alloc_example.rs --crate-type bin --target $TARGET_TRIPLE + $RUN_WRAPPER ./target/out/alloc_example + + echo "[AOT] dst_field_align" + # FIXME(antoyo): Re-add -Zmir-opt-level=2 once rust-lang/rust#67529 is fixed. + $RUSTC example/dst-field-align.rs --crate-name dst_field_align --crate-type bin --target $TARGET_TRIPLE + $RUN_WRAPPER ./target/out/dst_field_align || (echo $?; false) + + echo "[AOT] std_example" + $RUSTC example/std_example.rs --crate-type bin --target $TARGET_TRIPLE + $RUN_WRAPPER ./target/out/std_example --target $TARGET_TRIPLE + + echo "[AOT] subslice-patterns-const-eval" + $RUSTC example/subslice-patterns-const-eval.rs --crate-type bin -Cpanic=abort --target $TARGET_TRIPLE + $RUN_WRAPPER ./target/out/subslice-patterns-const-eval + + echo "[AOT] track-caller-attribute" + $RUSTC example/track-caller-attribute.rs --crate-type bin -Cpanic=abort --target $TARGET_TRIPLE + $RUN_WRAPPER ./target/out/track-caller-attribute + + echo "[BUILD] mod_bench" + $RUSTC example/mod_bench.rs --crate-type bin --target $TARGET_TRIPLE +} + +# FIXME(antoyo): linker gives multiple definitions error on Linux +#echo "[BUILD] sysroot in release mode" +#./build_sysroot/build_sysroot.sh --release + +# TODO(antoyo): uncomment when it works. +#pushd simple-raytracer +#if [[ "$HOST_TRIPLE" = "$TARGET_TRIPLE" ]]; then + #echo "[BENCH COMPILE] ebobby/simple-raytracer" + #hyperfine --runs ${RUN_RUNS:-10} --warmup 1 --prepare "rm -r target/*/debug || true" \ + #"RUSTFLAGS='' cargo build --target $TARGET_TRIPLE" \ + #"../cargo.sh build" + + #echo "[BENCH RUN] ebobby/simple-raytracer" + #cp ./target/*/debug/main ./raytracer_cg_gccjit + #hyperfine --runs ${RUN_RUNS:-10} ./raytracer_cg_llvm ./raytracer_cg_gccjit +#else + #echo "[BENCH COMPILE] ebobby/simple-raytracer (skipped)" + #echo "[COMPILE] ebobby/simple-raytracer" + #../cargo.sh build + #echo "[BENCH RUN] ebobby/simple-raytracer (skipped)" +#fi +#popd + +function test_libcore() { + pushd build_sysroot/sysroot_src/library/core/tests + echo "[TEST] libcore" + rm -r ./target || true + ../../../../../cargo.sh test + popd +} + +# TODO(antoyo): uncomment when it works. +#pushd regex +#echo "[TEST] rust-lang/regex example shootout-regex-dna" +#../cargo.sh clean +## Make sure `[codegen mono items] start` doesn't poison the diff +#../cargo.sh build --example shootout-regex-dna +#cat examples/regexdna-input.txt | ../cargo.sh run --example shootout-regex-dna | grep -v "Spawned thread" > res.txt +#diff -u res.txt examples/regexdna-output.txt + +#echo "[TEST] rust-lang/regex tests" +#../cargo.sh test --tests -- --exclude-should-panic --test-threads 1 -Zunstable-options +#popd + +#echo +#echo "[BENCH COMPILE] mod_bench" + +#COMPILE_MOD_BENCH_INLINE="$RUSTC example/mod_bench.rs --crate-type bin -Zmir-opt-level=3 -O --crate-name mod_bench_inline" +#COMPILE_MOD_BENCH_LLVM_0="rustc example/mod_bench.rs --crate-type bin -Copt-level=0 -o target/out/mod_bench_llvm_0 -Cpanic=abort" +#COMPILE_MOD_BENCH_LLVM_1="rustc example/mod_bench.rs --crate-type bin -Copt-level=1 -o target/out/mod_bench_llvm_1 -Cpanic=abort" +#COMPILE_MOD_BENCH_LLVM_2="rustc example/mod_bench.rs --crate-type bin -Copt-level=2 -o target/out/mod_bench_llvm_2 -Cpanic=abort" +#COMPILE_MOD_BENCH_LLVM_3="rustc example/mod_bench.rs --crate-type bin -Copt-level=3 -o target/out/mod_bench_llvm_3 -Cpanic=abort" + +## Use 100 runs, because a single compilations doesn't take more than ~150ms, so it isn't very slow +#hyperfine --runs ${COMPILE_RUNS:-100} "$COMPILE_MOD_BENCH_INLINE" "$COMPILE_MOD_BENCH_LLVM_0" "$COMPILE_MOD_BENCH_LLVM_1" "$COMPILE_MOD_BENCH_LLVM_2" "$COMPILE_MOD_BENCH_LLVM_3" + +#echo +#echo "[BENCH RUN] mod_bench" +#hyperfine --runs ${RUN_RUNS:-10} ./target/out/mod_bench{,_inline} ./target/out/mod_bench_llvm_* + +function test_rustc() { + echo + echo "[TEST] rust-lang/rust" + + rust_toolchain=$(cat rust-toolchain) + + git clone https://github.com/rust-lang/rust.git || true + cd rust + git fetch + git checkout $(rustc -V | cut -d' ' -f3 | tr -d '(') + export RUSTFLAGS= + + rm config.toml || true + + cat > config.toml <>() + .join("\n"); + Some(lines) + }) + .test_cmds(move |path| { + // Test command 1: Compile `x.rs` into `tempdir/x`. + let mut exe = PathBuf::new(); + exe.push(&tempdir); + exe.push(path.file_stem().expect("file_stem")); + let mut compiler = Command::new("rustc"); + compiler.args(&[ + &format!("-Zcodegen-backend={}/target/debug/librustc_codegen_gcc.so", current_dir), + "--sysroot", &format!("{}/build_sysroot/sysroot/", current_dir), + "-Zno-parallel-llvm", + "-C", "panic=abort", + "-C", "link-arg=-lc", + "-o", exe.to_str().expect("to_str"), + path.to_str().expect("to_str"), + ]); + // Test command 2: run `tempdir/x`. + let runtime = Command::new(exe); + vec![("Compiler", compiler), ("Run-time", runtime)] + }) + .run(); +} diff --git a/compiler/rustc_codegen_gcc/tests/run/abort1.rs b/compiler/rustc_codegen_gcc/tests/run/abort1.rs new file mode 100644 index 0000000000..291af5993a --- /dev/null +++ b/compiler/rustc_codegen_gcc/tests/run/abort1.rs @@ -0,0 +1,51 @@ +// Compiler: +// +// Run-time: +// status: signal + +#![feature(auto_traits, lang_items, no_core, start, intrinsics)] + +#![no_std] +#![no_core] + +/* + * Core + */ + +// Because we don't have core yet. +#[lang = "sized"] +pub trait Sized {} + +#[lang = "copy"] +trait Copy { +} + +impl Copy for isize {} + +#[lang = "receiver"] +trait Receiver { +} + +#[lang = "freeze"] +pub(crate) unsafe auto trait Freeze {} + +mod intrinsics { + use super::Sized; + + extern "rust-intrinsic" { + pub fn abort() -> !; + } +} + +/* + * Code + */ + +fn test_fail() -> ! { + unsafe { intrinsics::abort() }; +} + +#[start] +fn main(mut argc: isize, _argv: *const *const u8) -> isize { + test_fail(); +} diff --git a/compiler/rustc_codegen_gcc/tests/run/abort2.rs b/compiler/rustc_codegen_gcc/tests/run/abort2.rs new file mode 100644 index 0000000000..3c87c56789 --- /dev/null +++ b/compiler/rustc_codegen_gcc/tests/run/abort2.rs @@ -0,0 +1,53 @@ +// Compiler: +// +// Run-time: +// status: signal + +#![feature(auto_traits, lang_items, no_core, start, intrinsics)] + +#![no_std] +#![no_core] + +/* + * Core + */ + +// Because we don't have core yet. +#[lang = "sized"] +pub trait Sized {} + +#[lang = "copy"] +trait Copy { +} + +impl Copy for isize {} + +#[lang = "receiver"] +trait Receiver { +} + +#[lang = "freeze"] +pub(crate) unsafe auto trait Freeze {} + +mod intrinsics { + use super::Sized; + + extern "rust-intrinsic" { + pub fn abort() -> !; + } +} + +/* + * Code + */ + +fn fail() -> i32 { + unsafe { intrinsics::abort() }; + 0 +} + +#[start] +fn main(mut argc: isize, _argv: *const *const u8) -> isize { + fail(); + 0 +} diff --git a/compiler/rustc_codegen_gcc/tests/run/array.rs b/compiler/rustc_codegen_gcc/tests/run/array.rs new file mode 100644 index 0000000000..8b621d8a35 --- /dev/null +++ b/compiler/rustc_codegen_gcc/tests/run/array.rs @@ -0,0 +1,229 @@ +// Compiler: +// +// Run-time: +// status: 0 +// stdout: 42 +// 7 +// 5 +// 10 + +#![feature(arbitrary_self_types, auto_traits, lang_items, no_core, start, intrinsics)] + +#![no_std] +#![no_core] + +/* + * Core + */ + +// Because we don't have core yet. +#[lang = "sized"] +pub trait Sized {} + +#[lang = "copy"] +trait Copy { +} + +impl Copy for isize {} +impl Copy for usize {} +impl Copy for i32 {} +impl Copy for u8 {} +impl Copy for i8 {} +impl Copy for i16 {} + +#[lang = "receiver"] +trait Receiver { +} + +#[lang = "freeze"] +pub(crate) unsafe auto trait Freeze {} + +mod libc { + #[link(name = "c")] + extern "C" { + pub fn printf(format: *const i8, ...) -> i32; + pub fn puts(s: *const u8) -> i32; + } +} + +#[lang = "index"] +pub trait Index { + type Output: ?Sized; + fn index(&self, index: Idx) -> &Self::Output; +} + +impl Index for [T; 3] { + type Output = T; + + fn index(&self, index: usize) -> &Self::Output { + &self[index] + } +} + +impl Index for [T] { + type Output = T; + + fn index(&self, index: usize) -> &Self::Output { + &self[index] + } +} + +#[lang = "drop_in_place"] +#[allow(unconditional_recursion)] +pub unsafe fn drop_in_place(to_drop: *mut T) { + // Code here does not matter - this is replaced by the + // real drop glue by the compiler. + drop_in_place(to_drop); +} + +#[lang = "panic"] +#[track_caller] +#[no_mangle] +pub fn panic(_msg: &str) -> ! { + unsafe { + libc::puts("Panicking\0" as *const str as *const u8); + intrinsics::abort(); + } +} + +#[lang = "panic_location"] +struct PanicLocation { + file: &'static str, + line: u32, + column: u32, +} + +#[lang = "panic_bounds_check"] +#[track_caller] +#[no_mangle] +fn panic_bounds_check(index: usize, len: usize) -> ! { + unsafe { + libc::printf("index out of bounds: the len is %d but the index is %d\n\0" as *const str as *const i8, len, index); + intrinsics::abort(); + } +} + +mod intrinsics { + extern "rust-intrinsic" { + pub fn abort() -> !; + } +} + +#[lang = "add"] +trait Add { + type Output; + + fn add(self, rhs: RHS) -> Self::Output; +} + +impl Add for u8 { + type Output = Self; + + fn add(self, rhs: Self) -> Self { + self + rhs + } +} + +impl Add for i8 { + type Output = Self; + + fn add(self, rhs: Self) -> Self { + self + rhs + } +} + +impl Add for i32 { + type Output = Self; + + fn add(self, rhs: Self) -> Self { + self + rhs + } +} + +impl Add for usize { + type Output = Self; + + fn add(self, rhs: Self) -> Self { + self + rhs + } +} + +impl Add for isize { + type Output = Self; + + fn add(self, rhs: Self) -> Self { + self + rhs + } +} + +#[lang = "sub"] +pub trait Sub { + type Output; + + fn sub(self, rhs: RHS) -> Self::Output; +} + +impl Sub for usize { + type Output = Self; + + fn sub(self, rhs: Self) -> Self { + self - rhs + } +} + +impl Sub for isize { + type Output = Self; + + fn sub(self, rhs: Self) -> Self { + self - rhs + } +} + +impl Sub for u8 { + type Output = Self; + + fn sub(self, rhs: Self) -> Self { + self - rhs + } +} + +impl Sub for i8 { + type Output = Self; + + fn sub(self, rhs: Self) -> Self { + self - rhs + } +} + +impl Sub for i16 { + type Output = Self; + + fn sub(self, rhs: Self) -> Self { + self - rhs + } +} + + +/* + * Code + */ + +static mut ONE: usize = 1; + +fn make_array() -> [u8; 3] { + [42, 10, 5] +} + +#[start] +fn main(argc: isize, _argv: *const *const u8) -> isize { + let array = [42, 7, 5]; + let array2 = make_array(); + unsafe { + libc::printf(b"%ld\n\0" as *const u8 as *const i8, array[ONE - 1]); + libc::printf(b"%ld\n\0" as *const u8 as *const i8, array[ONE]); + libc::printf(b"%ld\n\0" as *const u8 as *const i8, array[ONE + 1]); + + libc::printf(b"%d\n\0" as *const u8 as *const i8, array2[argc as usize] as u32); + } + 0 +} diff --git a/compiler/rustc_codegen_gcc/tests/run/asm.rs b/compiler/rustc_codegen_gcc/tests/run/asm.rs new file mode 100644 index 0000000000..9c0055b0b6 --- /dev/null +++ b/compiler/rustc_codegen_gcc/tests/run/asm.rs @@ -0,0 +1,153 @@ +// Compiler: +// +// Run-time: +// status: 0 + +#![feature(asm, global_asm)] + +global_asm!(" + .global add_asm +add_asm: + mov rax, rdi + add rax, rsi + ret" +); + +extern "C" { + fn add_asm(a: i64, b: i64) -> i64; +} + +fn main() { + unsafe { + asm!("nop"); + } + + let x: u64; + unsafe { + asm!("mov $5, {}", + out(reg) x, + options(att_syntax) + ); + } + assert_eq!(x, 5); + + let x: u64; + let input: u64 = 42; + unsafe { + asm!("mov {input}, {output}", + "add $1, {output}", + input = in(reg) input, + output = out(reg) x, + options(att_syntax) + ); + } + assert_eq!(x, 43); + + let x: u64; + unsafe { + asm!("mov {}, 6", + out(reg) x, + ); + } + assert_eq!(x, 6); + + let x: u64; + let input: u64 = 42; + unsafe { + asm!("mov {output}, {input}", + "add {output}, 1", + input = in(reg) input, + output = out(reg) x, + ); + } + assert_eq!(x, 43); + + // check inout(reg_class) x + let mut x: u64 = 42; + unsafe { + asm!("add {0}, {0}", + inout(reg) x + ); + } + assert_eq!(x, 84); + + // check inout("reg") x + let mut x: u64 = 42; + unsafe { + asm!("add r11, r11", + inout("r11") x + ); + } + assert_eq!(x, 84); + + // check a mix of + // in("reg") + // inout(class) x => y + // inout (class) x + let x: u64 = 702; + let y: u64 = 100; + let res: u64; + let mut rem: u64 = 0; + unsafe { + asm!("div r11", + in("r11") y, + inout("eax") x => res, + inout("edx") rem, + ); + } + assert_eq!(res, 7); + assert_eq!(rem, 2); + + // check const + let mut x: u64 = 42; + unsafe { + asm!("add {}, {}", + inout(reg) x, + const 1 + ); + } + assert_eq!(x, 43); + + // check const (ATT syntax) + let mut x: u64 = 42; + unsafe { + asm!("add {}, {}", + const 1, + inout(reg) x, + options(att_syntax) + ); + } + assert_eq!(x, 43); + + // check sym fn + extern "C" fn foo() -> u64 { 42 } + let x: u64; + unsafe { + asm!("call {}", sym foo, lateout("rax") x); + } + assert_eq!(x, 42); + + // check sym fn (ATT syntax) + let x: u64; + unsafe { + asm!("call {}", sym foo, lateout("rax") x, options(att_syntax)); + } + assert_eq!(x, 42); + + // check sym static + static FOO: u64 = 42; + let x: u64; + unsafe { + asm!("mov {1}, qword ptr [rip + {0}]", sym FOO, lateout(reg) x); + } + assert_eq!(x, 42); + + // check sym static (ATT syntax) + let x: u64; + unsafe { + asm!("movq {0}(%rip), {1}", sym FOO, lateout(reg) x, options(att_syntax)); + } + assert_eq!(x, 42); + + assert_eq!(unsafe { add_asm(40, 2) }, 42); +} diff --git a/compiler/rustc_codegen_gcc/tests/run/assign.rs b/compiler/rustc_codegen_gcc/tests/run/assign.rs new file mode 100644 index 0000000000..cc8647006c --- /dev/null +++ b/compiler/rustc_codegen_gcc/tests/run/assign.rs @@ -0,0 +1,153 @@ +// Compiler: +// +// Run-time: +// stdout: 2 +// 7 8 +// 10 + +#![allow(unused_attributes)] +#![feature(auto_traits, lang_items, no_core, start, intrinsics, track_caller)] + +#![no_std] +#![no_core] + +/* + * Core + */ + +// Because we don't have core yet. +#[lang = "sized"] +pub trait Sized {} + +#[lang = "copy"] +trait Copy { +} + +impl Copy for isize {} +impl Copy for *mut i32 {} +impl Copy for usize {} +impl Copy for u8 {} +impl Copy for i8 {} +impl Copy for i32 {} + +#[lang = "receiver"] +trait Receiver { +} + +#[lang = "freeze"] +pub(crate) unsafe auto trait Freeze {} + +#[lang = "panic_location"] +struct PanicLocation { + file: &'static str, + line: u32, + column: u32, +} + +mod libc { + #[link(name = "c")] + extern "C" { + pub fn puts(s: *const u8) -> i32; + pub fn fflush(stream: *mut i32) -> i32; + pub fn printf(format: *const i8, ...) -> i32; + + pub static STDOUT: *mut i32; + } +} + +mod intrinsics { + extern "rust-intrinsic" { + pub fn abort() -> !; + } +} + +#[lang = "panic"] +#[track_caller] +#[no_mangle] +pub fn panic(_msg: &str) -> ! { + unsafe { + libc::puts("Panicking\0" as *const str as *const u8); + libc::fflush(libc::STDOUT); + intrinsics::abort(); + } +} + +#[lang = "add"] +trait Add { + type Output; + + fn add(self, rhs: RHS) -> Self::Output; +} + +impl Add for u8 { + type Output = Self; + + fn add(self, rhs: Self) -> Self { + self + rhs + } +} + +impl Add for i8 { + type Output = Self; + + fn add(self, rhs: Self) -> Self { + self + rhs + } +} + +impl Add for i32 { + type Output = Self; + + fn add(self, rhs: Self) -> Self { + self + rhs + } +} + +impl Add for usize { + type Output = Self; + + fn add(self, rhs: Self) -> Self { + self + rhs + } +} + +impl Add for isize { + type Output = Self; + + fn add(self, rhs: Self) -> Self { + self + rhs + } +} + +/* + * Code + */ + +fn inc_ref(num: &mut isize) -> isize { + *num = *num + 5; + *num + 1 +} + +fn inc(num: isize) -> isize { + num + 1 +} + + +#[start] +fn main(mut argc: isize, _argv: *const *const u8) -> isize { + argc = inc(argc); + unsafe { + libc::printf(b"%ld\n\0" as *const u8 as *const i8, argc); + } + + let b = inc_ref(&mut argc); + unsafe { + libc::printf(b"%ld %ld\n\0" as *const u8 as *const i8, argc, b); + } + + argc = 10; + unsafe { + libc::printf(b"%ld\n\0" as *const u8 as *const i8, argc); + } + 0 +} diff --git a/compiler/rustc_codegen_gcc/tests/run/closure.rs b/compiler/rustc_codegen_gcc/tests/run/closure.rs new file mode 100644 index 0000000000..7121a5f0d5 --- /dev/null +++ b/compiler/rustc_codegen_gcc/tests/run/closure.rs @@ -0,0 +1,230 @@ +// Compiler: +// +// Run-time: +// status: 0 +// stdout: Arg: 1 +// Argument: 1 +// String arg: 1 +// Int argument: 2 +// Both args: 11 + +#![feature(arbitrary_self_types, auto_traits, lang_items, no_core, start, intrinsics, + unboxed_closures)] + +#![no_std] +#![no_core] + +/* + * Core + */ + +// Because we don't have core yet. +#[lang = "sized"] +pub trait Sized {} + +#[lang = "copy"] +trait Copy { +} + +impl Copy for isize {} +impl Copy for usize {} +impl Copy for i32 {} +impl Copy for u32 {} +impl Copy for u8 {} +impl Copy for i8 {} + +#[lang = "receiver"] +trait Receiver { +} + +#[lang = "freeze"] +pub(crate) unsafe auto trait Freeze {} + +mod libc { + #[link(name = "c")] + extern "C" { + pub fn puts(s: *const u8) -> i32; + pub fn printf(format: *const i8, ...) -> i32; + } +} + +#[lang = "index"] +pub trait Index { + type Output: ?Sized; + fn index(&self, index: Idx) -> &Self::Output; +} + +impl Index for [T; 3] { + type Output = T; + + fn index(&self, index: usize) -> &Self::Output { + &self[index] + } +} + +impl Index for [T] { + type Output = T; + + fn index(&self, index: usize) -> &Self::Output { + &self[index] + } +} + +#[lang = "drop_in_place"] +#[allow(unconditional_recursion)] +pub unsafe fn drop_in_place(to_drop: *mut T) { + // Code here does not matter - this is replaced by the + // real drop glue by the compiler. + drop_in_place(to_drop); +} + +#[lang = "panic_location"] +struct PanicLocation { + file: &'static str, + line: u32, + column: u32, +} + +#[lang = "panic_bounds_check"] +#[track_caller] +#[no_mangle] +fn panic_bounds_check(index: usize, len: usize) -> ! { + unsafe { + libc::printf("index out of bounds: the len is %d but the index is %d\n\0" as *const str as *const i8, len, index); + intrinsics::abort(); + } +} + +mod intrinsics { + extern "rust-intrinsic" { + pub fn abort() -> !; + } +} + +#[lang = "unsize"] +pub trait Unsize {} + +#[lang = "coerce_unsized"] +pub trait CoerceUnsized {} + +impl<'a, 'b: 'a, T: ?Sized + Unsize, U: ?Sized> CoerceUnsized<&'a U> for &'b T {} +impl<'a, T: ?Sized + Unsize, U: ?Sized> CoerceUnsized<&'a mut U> for &'a mut T {} +impl, U: ?Sized> CoerceUnsized<*const U> for *const T {} +impl, U: ?Sized> CoerceUnsized<*mut U> for *mut T {} + +#[lang = "fn_once"] +#[rustc_paren_sugar] +pub trait FnOnce { + #[lang = "fn_once_output"] + type Output; + + extern "rust-call" fn call_once(self, args: Args) -> Self::Output; +} + +#[lang = "fn_mut"] +#[rustc_paren_sugar] +pub trait FnMut: FnOnce { + extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output; +} + +#[lang = "add"] +trait Add { + type Output; + + fn add(self, rhs: RHS) -> Self::Output; +} + +impl Add for u8 { + type Output = Self; + + fn add(self, rhs: Self) -> Self { + self + rhs + } +} + +impl Add for i8 { + type Output = Self; + + fn add(self, rhs: Self) -> Self { + self + rhs + } +} + +impl Add for i32 { + type Output = Self; + + fn add(self, rhs: Self) -> Self { + self + rhs + } +} + +impl Add for usize { + type Output = Self; + + fn add(self, rhs: Self) -> Self { + self + rhs + } +} + +impl Add for isize { + type Output = Self; + + fn add(self, rhs: Self) -> Self { + self + rhs + } +} + +#[lang = "panic"] +#[track_caller] +#[no_mangle] +pub fn panic(_msg: &str) -> ! { + unsafe { + libc::puts("Panicking\0" as *const str as *const u8); + intrinsics::abort(); + } +} + +/* + * Code + */ + +#[start] +fn main(mut argc: isize, _argv: *const *const u8) -> isize { + let string = "Arg: %d\n\0"; + let mut closure = || { + unsafe { + libc::printf(string as *const str as *const i8, argc); + } + }; + closure(); + + let mut closure = || { + unsafe { + libc::printf("Argument: %d\n\0" as *const str as *const i8, argc); + } + }; + closure(); + + let mut closure = |string| { + unsafe { + libc::printf(string as *const str as *const i8, argc); + } + }; + closure("String arg: %d\n\0"); + + let mut closure = |arg: isize| { + unsafe { + libc::printf("Int argument: %d\n\0" as *const str as *const i8, arg); + } + }; + closure(argc + 1); + + let mut closure = |string, arg: isize| { + unsafe { + libc::printf(string as *const str as *const i8, arg); + } + }; + closure("Both args: %d\n\0", argc + 10); + + 0 +} diff --git a/compiler/rustc_codegen_gcc/tests/run/condition.rs b/compiler/rustc_codegen_gcc/tests/run/condition.rs new file mode 100644 index 0000000000..6a2e2d5bb1 --- /dev/null +++ b/compiler/rustc_codegen_gcc/tests/run/condition.rs @@ -0,0 +1,320 @@ +// Compiler: +// +// Run-time: +// status: 0 +// stdout: true +// 1 + +#![feature(arbitrary_self_types, auto_traits, lang_items, no_core, start, intrinsics)] + +#![no_std] +#![no_core] + +/* + * Core + */ + +// Because we don't have core yet. +#[lang = "sized"] +pub trait Sized {} + +#[lang = "copy"] +trait Copy { +} + +impl Copy for isize {} +impl Copy for usize {} +impl Copy for u64 {} +impl Copy for i32 {} +impl Copy for u32 {} +impl Copy for bool {} +impl Copy for u16 {} +impl Copy for i16 {} +impl Copy for char {} +impl Copy for i8 {} +impl Copy for u8 {} + +#[lang = "receiver"] +trait Receiver { +} + +#[lang = "freeze"] +pub(crate) unsafe auto trait Freeze {} + +mod libc { + #[link(name = "c")] + extern "C" { + pub fn printf(format: *const i8, ...) -> i32; + pub fn puts(s: *const u8) -> i32; + } +} + +#[lang = "index"] +pub trait Index { + type Output: ?Sized; + fn index(&self, index: Idx) -> &Self::Output; +} + +impl Index for [T; 3] { + type Output = T; + + fn index(&self, index: usize) -> &Self::Output { + &self[index] + } +} + +impl Index for [T] { + type Output = T; + + fn index(&self, index: usize) -> &Self::Output { + &self[index] + } +} + +#[lang = "drop_in_place"] +#[allow(unconditional_recursion)] +pub unsafe fn drop_in_place(to_drop: *mut T) { + // Code here does not matter - this is replaced by the + // real drop glue by the compiler. + drop_in_place(to_drop); +} + +#[lang = "panic"] +#[track_caller] +#[no_mangle] +pub fn panic(_msg: &str) -> ! { + unsafe { + libc::puts("Panicking\0" as *const str as *const u8); + intrinsics::abort(); + } +} + +#[lang = "panic_location"] +struct PanicLocation { + file: &'static str, + line: u32, + column: u32, +} + +#[lang = "panic_bounds_check"] +#[track_caller] +#[no_mangle] +fn panic_bounds_check(index: usize, len: usize) -> ! { + unsafe { + libc::printf("index out of bounds: the len is %d but the index is %d\n\0" as *const str as *const i8, len, index); + intrinsics::abort(); + } +} + +mod intrinsics { + extern "rust-intrinsic" { + pub fn abort() -> !; + } +} + +#[lang = "add"] +trait Add { + type Output; + + fn add(self, rhs: RHS) -> Self::Output; +} + +impl Add for u8 { + type Output = Self; + + fn add(self, rhs: Self) -> Self { + self + rhs + } +} + +impl Add for i8 { + type Output = Self; + + fn add(self, rhs: Self) -> Self { + self + rhs + } +} + +impl Add for i32 { + type Output = Self; + + fn add(self, rhs: Self) -> Self { + self + rhs + } +} + +impl Add for usize { + type Output = Self; + + fn add(self, rhs: Self) -> Self { + self + rhs + } +} + +impl Add for isize { + type Output = Self; + + fn add(self, rhs: Self) -> Self { + self + rhs + } +} + +#[lang = "sub"] +pub trait Sub { + type Output; + + fn sub(self, rhs: RHS) -> Self::Output; +} + +impl Sub for usize { + type Output = Self; + + fn sub(self, rhs: Self) -> Self { + self - rhs + } +} + +impl Sub for isize { + type Output = Self; + + fn sub(self, rhs: Self) -> Self { + self - rhs + } +} + +impl Sub for u8 { + type Output = Self; + + fn sub(self, rhs: Self) -> Self { + self - rhs + } +} + +impl Sub for i8 { + type Output = Self; + + fn sub(self, rhs: Self) -> Self { + self - rhs + } +} + +impl Sub for i16 { + type Output = Self; + + fn sub(self, rhs: Self) -> Self { + self - rhs + } +} + +#[lang = "eq"] +pub trait PartialEq { + fn eq(&self, other: &Rhs) -> bool; + fn ne(&self, other: &Rhs) -> bool; +} + +impl PartialEq for u8 { + fn eq(&self, other: &u8) -> bool { + (*self) == (*other) + } + fn ne(&self, other: &u8) -> bool { + (*self) != (*other) + } +} + +impl PartialEq for u16 { + fn eq(&self, other: &u16) -> bool { + (*self) == (*other) + } + fn ne(&self, other: &u16) -> bool { + (*self) != (*other) + } +} + +impl PartialEq for u32 { + fn eq(&self, other: &u32) -> bool { + (*self) == (*other) + } + fn ne(&self, other: &u32) -> bool { + (*self) != (*other) + } +} + + +impl PartialEq for u64 { + fn eq(&self, other: &u64) -> bool { + (*self) == (*other) + } + fn ne(&self, other: &u64) -> bool { + (*self) != (*other) + } +} + +impl PartialEq for usize { + fn eq(&self, other: &usize) -> bool { + (*self) == (*other) + } + fn ne(&self, other: &usize) -> bool { + (*self) != (*other) + } +} + +impl PartialEq for i8 { + fn eq(&self, other: &i8) -> bool { + (*self) == (*other) + } + fn ne(&self, other: &i8) -> bool { + (*self) != (*other) + } +} + +impl PartialEq for i32 { + fn eq(&self, other: &i32) -> bool { + (*self) == (*other) + } + fn ne(&self, other: &i32) -> bool { + (*self) != (*other) + } +} + +impl PartialEq for isize { + fn eq(&self, other: &isize) -> bool { + (*self) == (*other) + } + fn ne(&self, other: &isize) -> bool { + (*self) != (*other) + } +} + +impl PartialEq for char { + fn eq(&self, other: &char) -> bool { + (*self) == (*other) + } + fn ne(&self, other: &char) -> bool { + (*self) != (*other) + } +} + +/* + * Code + */ + +#[start] +fn main(argc: isize, _argv: *const *const u8) -> isize { + unsafe { + if argc == 1 { + libc::printf(b"true\n\0" as *const u8 as *const i8); + } + + let string = + match argc { + 1 => b"1\n\0", + 2 => b"2\n\0", + 3 => b"3\n\0", + 4 => b"4\n\0", + 5 => b"5\n\0", + _ => b"_\n\0", + }; + libc::printf(string as *const u8 as *const i8); + } + 0 +} diff --git a/compiler/rustc_codegen_gcc/tests/run/empty_main.rs b/compiler/rustc_codegen_gcc/tests/run/empty_main.rs new file mode 100644 index 0000000000..c02cfd2a85 --- /dev/null +++ b/compiler/rustc_codegen_gcc/tests/run/empty_main.rs @@ -0,0 +1,39 @@ +// Compiler: +// +// Run-time: +// status: 0 + +#![feature(auto_traits, lang_items, no_core, start)] + +#![no_std] +#![no_core] + +/* + * Core + */ + +// Because we don't have core yet. +#[lang = "sized"] +pub trait Sized {} + +#[lang = "copy"] +trait Copy { +} + +impl Copy for isize {} + +#[lang = "receiver"] +trait Receiver { +} + +#[lang = "freeze"] +pub(crate) unsafe auto trait Freeze {} + +/* + * Code + */ + +#[start] +fn main(mut argc: isize, _argv: *const *const u8) -> isize { + 0 +} diff --git a/compiler/rustc_codegen_gcc/tests/run/exit.rs b/compiler/rustc_codegen_gcc/tests/run/exit.rs new file mode 100644 index 0000000000..956e53dd4a --- /dev/null +++ b/compiler/rustc_codegen_gcc/tests/run/exit.rs @@ -0,0 +1,49 @@ +// Compiler: +// +// Run-time: +// status: 2 + +#![feature(auto_traits, lang_items, no_core, start, intrinsics)] + +#![no_std] +#![no_core] + +mod libc { + #[link(name = "c")] + extern "C" { + pub fn exit(status: i32); + } +} + +/* + * Core + */ + +// Because we don't have core yet. +#[lang = "sized"] +pub trait Sized {} + +#[lang = "copy"] +trait Copy { +} + +impl Copy for isize {} + +#[lang = "receiver"] +trait Receiver { +} + +#[lang = "freeze"] +pub(crate) unsafe auto trait Freeze {} + +/* + * Code + */ + +#[start] +fn main(mut argc: isize, _argv: *const *const u8) -> isize { + unsafe { + libc::exit(2); + } + 0 +} diff --git a/compiler/rustc_codegen_gcc/tests/run/exit_code.rs b/compiler/rustc_codegen_gcc/tests/run/exit_code.rs new file mode 100644 index 0000000000..eeab352095 --- /dev/null +++ b/compiler/rustc_codegen_gcc/tests/run/exit_code.rs @@ -0,0 +1,39 @@ +// Compiler: +// +// Run-time: +// status: 1 + +#![feature(auto_traits, lang_items, no_core, start)] + +#![no_std] +#![no_core] + +/* + * Core + */ + +// Because we don't have core yet. +#[lang = "sized"] +pub trait Sized {} + +#[lang = "copy"] +trait Copy { +} + +impl Copy for isize {} + +#[lang = "receiver"] +trait Receiver { +} + +#[lang = "freeze"] +pub(crate) unsafe auto trait Freeze {} + +/* + * Code + */ + +#[start] +fn main(mut argc: isize, _argv: *const *const u8) -> isize { + 1 +} diff --git a/compiler/rustc_codegen_gcc/tests/run/fun_ptr.rs b/compiler/rustc_codegen_gcc/tests/run/fun_ptr.rs new file mode 100644 index 0000000000..a226fff79e --- /dev/null +++ b/compiler/rustc_codegen_gcc/tests/run/fun_ptr.rs @@ -0,0 +1,223 @@ +// Compiler: +// +// Run-time: +// status: 0 +// stdout: 1 + +#![feature(arbitrary_self_types, auto_traits, lang_items, no_core, start, intrinsics)] + +#![no_std] +#![no_core] + +/* + * Core + */ + +// Because we don't have core yet. +#[lang = "sized"] +pub trait Sized {} + +#[lang = "copy"] +trait Copy { +} + +impl Copy for isize {} +impl Copy for usize {} +impl Copy for i32 {} +impl Copy for u8 {} +impl Copy for i8 {} +impl Copy for i16 {} + +#[lang = "receiver"] +trait Receiver { +} + +#[lang = "freeze"] +pub(crate) unsafe auto trait Freeze {} + +mod libc { + #[link(name = "c")] + extern "C" { + pub fn printf(format: *const i8, ...) -> i32; + pub fn puts(s: *const u8) -> i32; + } +} + +#[lang = "index"] +pub trait Index { + type Output: ?Sized; + fn index(&self, index: Idx) -> &Self::Output; +} + +impl Index for [T; 3] { + type Output = T; + + fn index(&self, index: usize) -> &Self::Output { + &self[index] + } +} + +impl Index for [T] { + type Output = T; + + fn index(&self, index: usize) -> &Self::Output { + &self[index] + } +} + +#[lang = "drop_in_place"] +#[allow(unconditional_recursion)] +pub unsafe fn drop_in_place(to_drop: *mut T) { + // Code here does not matter - this is replaced by the + // real drop glue by the compiler. + drop_in_place(to_drop); +} + +#[lang = "panic"] +#[track_caller] +#[no_mangle] +pub fn panic(_msg: &str) -> ! { + unsafe { + libc::puts("Panicking\0" as *const str as *const u8); + intrinsics::abort(); + } +} + +#[lang = "panic_location"] +struct PanicLocation { + file: &'static str, + line: u32, + column: u32, +} + +#[lang = "panic_bounds_check"] +#[track_caller] +#[no_mangle] +fn panic_bounds_check(index: usize, len: usize) -> ! { + unsafe { + libc::printf("index out of bounds: the len is %d but the index is %d\n\0" as *const str as *const i8, len, index); + intrinsics::abort(); + } +} + +mod intrinsics { + extern "rust-intrinsic" { + pub fn abort() -> !; + } +} + +#[lang = "add"] +trait Add { + type Output; + + fn add(self, rhs: RHS) -> Self::Output; +} + +impl Add for u8 { + type Output = Self; + + fn add(self, rhs: Self) -> Self { + self + rhs + } +} + +impl Add for i8 { + type Output = Self; + + fn add(self, rhs: Self) -> Self { + self + rhs + } +} + +impl Add for i32 { + type Output = Self; + + fn add(self, rhs: Self) -> Self { + self + rhs + } +} + +impl Add for usize { + type Output = Self; + + fn add(self, rhs: Self) -> Self { + self + rhs + } +} + +impl Add for isize { + type Output = Self; + + fn add(self, rhs: Self) -> Self { + self + rhs + } +} + +#[lang = "sub"] +pub trait Sub { + type Output; + + fn sub(self, rhs: RHS) -> Self::Output; +} + +impl Sub for usize { + type Output = Self; + + fn sub(self, rhs: Self) -> Self { + self - rhs + } +} + +impl Sub for isize { + type Output = Self; + + fn sub(self, rhs: Self) -> Self { + self - rhs + } +} + +impl Sub for u8 { + type Output = Self; + + fn sub(self, rhs: Self) -> Self { + self - rhs + } +} + +impl Sub for i8 { + type Output = Self; + + fn sub(self, rhs: Self) -> Self { + self - rhs + } +} + +impl Sub for i16 { + type Output = Self; + + fn sub(self, rhs: Self) -> Self { + self - rhs + } +} + + +/* + * Code + */ + +fn i16_as_i8(a: i16) -> i8 { + a as i8 +} + +fn call_func(func: fn(i16) -> i8, param: i16) -> i8 { + func(param) +} + +#[start] +fn main(argc: isize, _argv: *const *const u8) -> isize { + unsafe { + let result = call_func(i16_as_i8, argc as i16) as isize; + libc::printf(b"%ld\n\0" as *const u8 as *const i8, result); + } + 0 +} diff --git a/compiler/rustc_codegen_gcc/tests/run/int_overflow.rs b/compiler/rustc_codegen_gcc/tests/run/int_overflow.rs new file mode 100644 index 0000000000..7111703ca2 --- /dev/null +++ b/compiler/rustc_codegen_gcc/tests/run/int_overflow.rs @@ -0,0 +1,129 @@ +// Compiler: +// +// Run-time: +// stdout: Panicking +// status: signal + +#![allow(unused_attributes)] +#![feature(auto_traits, lang_items, no_core, start, intrinsics)] + +#![no_std] +#![no_core] + +/* + * Core + */ + +// Because we don't have core yet. +#[lang = "sized"] +pub trait Sized {} + +#[lang = "copy"] +trait Copy { +} + +impl Copy for isize {} +impl Copy for *mut i32 {} +impl Copy for usize {} +impl Copy for i32 {} +impl Copy for u8 {} +impl Copy for i8 {} + +#[lang = "receiver"] +trait Receiver { +} + +#[lang = "freeze"] +pub(crate) unsafe auto trait Freeze {} + +#[lang = "panic_location"] +struct PanicLocation { + file: &'static str, + line: u32, + column: u32, +} + +mod libc { + #[link(name = "c")] + extern "C" { + pub fn puts(s: *const u8) -> i32; + pub fn fflush(stream: *mut i32) -> i32; + + pub static STDOUT: *mut i32; + } +} + +mod intrinsics { + extern "rust-intrinsic" { + pub fn abort() -> !; + } +} + +#[lang = "panic"] +#[track_caller] +#[no_mangle] +pub fn panic(_msg: &str) -> ! { + unsafe { + libc::puts("Panicking\0" as *const str as *const u8); + libc::fflush(libc::STDOUT); + intrinsics::abort(); + } +} + +#[lang = "add"] +trait Add { + type Output; + + fn add(self, rhs: RHS) -> Self::Output; +} + +impl Add for u8 { + type Output = Self; + + fn add(self, rhs: Self) -> Self { + self + rhs + } +} + +impl Add for i8 { + type Output = Self; + + fn add(self, rhs: Self) -> Self { + self + rhs + } +} + +impl Add for i32 { + type Output = Self; + + fn add(self, rhs: Self) -> Self { + self + rhs + } +} + +impl Add for usize { + type Output = Self; + + fn add(self, rhs: Self) -> Self { + self + rhs + } +} + +impl Add for isize { + type Output = Self; + + fn add(self, rhs: Self) -> Self { + self + rhs + } +} + +/* + * Code + */ + +#[start] +fn main(mut argc: isize, _argv: *const *const u8) -> isize { + let int = 9223372036854775807isize; + let int = int + argc; + int +} diff --git a/compiler/rustc_codegen_gcc/tests/run/mut_ref.rs b/compiler/rustc_codegen_gcc/tests/run/mut_ref.rs new file mode 100644 index 0000000000..e8876009cc --- /dev/null +++ b/compiler/rustc_codegen_gcc/tests/run/mut_ref.rs @@ -0,0 +1,165 @@ + +// Compiler: +// +// Run-time: +// stdout: 2 +// 7 +// 6 +// 11 + +#![allow(unused_attributes)] +#![feature(auto_traits, lang_items, no_core, start, intrinsics, track_caller)] + +#![no_std] +#![no_core] + +/* + * Core + */ + +// Because we don't have core yet. +#[lang = "sized"] +pub trait Sized {} + +#[lang = "copy"] +trait Copy { +} + +impl Copy for isize {} +impl Copy for *mut i32 {} +impl Copy for usize {} +impl Copy for u8 {} +impl Copy for i8 {} +impl Copy for i32 {} + +#[lang = "receiver"] +trait Receiver { +} + +#[lang = "freeze"] +pub(crate) unsafe auto trait Freeze {} + +#[lang = "panic_location"] +struct PanicLocation { + file: &'static str, + line: u32, + column: u32, +} + +mod libc { + #[link(name = "c")] + extern "C" { + pub fn puts(s: *const u8) -> i32; + pub fn fflush(stream: *mut i32) -> i32; + pub fn printf(format: *const i8, ...) -> i32; + + pub static STDOUT: *mut i32; + } +} + +mod intrinsics { + extern "rust-intrinsic" { + pub fn abort() -> !; + } +} + +#[lang = "panic"] +#[track_caller] +#[no_mangle] +pub fn panic(_msg: &str) -> ! { + unsafe { + libc::puts("Panicking\0" as *const str as *const u8); + libc::fflush(libc::STDOUT); + intrinsics::abort(); + } +} + +#[lang = "add"] +trait Add { + type Output; + + fn add(self, rhs: RHS) -> Self::Output; +} + +impl Add for u8 { + type Output = Self; + + fn add(self, rhs: Self) -> Self { + self + rhs + } +} + +impl Add for i8 { + type Output = Self; + + fn add(self, rhs: Self) -> Self { + self + rhs + } +} + +impl Add for i32 { + type Output = Self; + + fn add(self, rhs: Self) -> Self { + self + rhs + } +} + +impl Add for usize { + type Output = Self; + + fn add(self, rhs: Self) -> Self { + self + rhs + } +} + +impl Add for isize { + type Output = Self; + + fn add(self, rhs: Self) -> Self { + self + rhs + } +} + +/* + * Code + */ + +struct Test { + field: isize, +} + +fn test(num: isize) -> Test { + Test { + field: num + 1, + } +} + +fn update_num(num: &mut isize) { + *num = *num + 5; +} + +#[start] +fn main(mut argc: isize, _argv: *const *const u8) -> isize { + let mut test = test(argc); + unsafe { + libc::printf(b"%ld\n\0" as *const u8 as *const i8, test.field); + } + update_num(&mut test.field); + unsafe { + libc::printf(b"%ld\n\0" as *const u8 as *const i8, test.field); + } + + update_num(&mut argc); + unsafe { + libc::printf(b"%ld\n\0" as *const u8 as *const i8, argc); + } + + let refe = &mut argc; + *refe = *refe + 5; + unsafe { + libc::printf(b"%ld\n\0" as *const u8 as *const i8, argc); + } + + 0 +} diff --git a/compiler/rustc_codegen_gcc/tests/run/operations.rs b/compiler/rustc_codegen_gcc/tests/run/operations.rs new file mode 100644 index 0000000000..4dc375309e --- /dev/null +++ b/compiler/rustc_codegen_gcc/tests/run/operations.rs @@ -0,0 +1,221 @@ +// Compiler: +// +// Run-time: +// stdout: 41 +// 39 +// 10 + +#![allow(unused_attributes)] +#![feature(auto_traits, lang_items, no_core, start, intrinsics, arbitrary_self_types)] + +#![no_std] +#![no_core] + +/* + * Core + */ + +// Because we don't have core yet. +#[lang = "sized"] +pub trait Sized {} + +#[lang = "copy"] +trait Copy { +} + +impl Copy for isize {} +impl Copy for *mut i32 {} +impl Copy for usize {} +impl Copy for u8 {} +impl Copy for i8 {} +impl Copy for i16 {} +impl Copy for i32 {} + +#[lang = "deref"] +pub trait Deref { + type Target: ?Sized; + + fn deref(&self) -> &Self::Target; +} + +#[lang = "receiver"] +trait Receiver { +} + +#[lang = "freeze"] +pub(crate) unsafe auto trait Freeze {} + +#[lang = "panic_location"] +struct PanicLocation { + file: &'static str, + line: u32, + column: u32, +} + +mod libc { + #[link(name = "c")] + extern "C" { + pub fn printf(format: *const i8, ...) -> i32; + pub fn puts(s: *const u8) -> i32; + pub fn fflush(stream: *mut i32) -> i32; + + pub static STDOUT: *mut i32; + } +} + +mod intrinsics { + extern "rust-intrinsic" { + pub fn abort() -> !; + } +} + +#[lang = "panic"] +#[track_caller] +#[no_mangle] +pub fn panic(_msg: &str) -> ! { + unsafe { + libc::puts("Panicking\0" as *const str as *const u8); + libc::fflush(libc::STDOUT); + intrinsics::abort(); + } +} + +#[lang = "add"] +trait Add { + type Output; + + fn add(self, rhs: RHS) -> Self::Output; +} + +impl Add for u8 { + type Output = Self; + + fn add(self, rhs: Self) -> Self { + self + rhs + } +} + +impl Add for i8 { + type Output = Self; + + fn add(self, rhs: Self) -> Self { + self + rhs + } +} + +impl Add for i32 { + type Output = Self; + + fn add(self, rhs: Self) -> Self { + self + rhs + } +} + +impl Add for usize { + type Output = Self; + + fn add(self, rhs: Self) -> Self { + self + rhs + } +} + +impl Add for isize { + type Output = Self; + + fn add(self, rhs: Self) -> Self { + self + rhs + } +} + +#[lang = "sub"] +pub trait Sub { + type Output; + + fn sub(self, rhs: RHS) -> Self::Output; +} + +impl Sub for usize { + type Output = Self; + + fn sub(self, rhs: Self) -> Self { + self - rhs + } +} + +impl Sub for isize { + type Output = Self; + + fn sub(self, rhs: Self) -> Self { + self - rhs + } +} + +impl Sub for u8 { + type Output = Self; + + fn sub(self, rhs: Self) -> Self { + self - rhs + } +} + +impl Sub for i8 { + type Output = Self; + + fn sub(self, rhs: Self) -> Self { + self - rhs + } +} + +impl Sub for i16 { + type Output = Self; + + fn sub(self, rhs: Self) -> Self { + self - rhs + } +} + +#[lang = "mul"] +pub trait Mul { + type Output; + + #[must_use] + fn mul(self, rhs: RHS) -> Self::Output; +} + +impl Mul for u8 { + type Output = Self; + + fn mul(self, rhs: Self) -> Self::Output { + self * rhs + } +} + +impl Mul for usize { + type Output = Self; + + fn mul(self, rhs: Self) -> Self::Output { + self * rhs + } +} + +impl Mul for isize { + type Output = Self; + + fn mul(self, rhs: Self) -> Self::Output { + self * rhs + } +} + +/* + * Code + */ + +#[start] +fn main(mut argc: isize, _argv: *const *const u8) -> isize { + unsafe { + libc::printf(b"%ld\n\0" as *const u8 as *const i8, 40 + argc); + libc::printf(b"%ld\n\0" as *const u8 as *const i8, 40 - argc); + libc::printf(b"%ld\n\0" as *const u8 as *const i8, 10 * argc); + } + 0 +} diff --git a/compiler/rustc_codegen_gcc/tests/run/ptr_cast.rs b/compiler/rustc_codegen_gcc/tests/run/ptr_cast.rs new file mode 100644 index 0000000000..6ac099ea14 --- /dev/null +++ b/compiler/rustc_codegen_gcc/tests/run/ptr_cast.rs @@ -0,0 +1,222 @@ +// Compiler: +// +// Run-time: +// status: 0 +// stdout: 1 + +#![feature(arbitrary_self_types, auto_traits, lang_items, no_core, start, intrinsics)] + +#![no_std] +#![no_core] + +/* + * Core + */ + +// Because we don't have core yet. +#[lang = "sized"] +pub trait Sized {} + +#[lang = "copy"] +trait Copy { +} + +impl Copy for isize {} +impl Copy for usize {} +impl Copy for i32 {} +impl Copy for u8 {} +impl Copy for i8 {} +impl Copy for i16 {} + +#[lang = "receiver"] +trait Receiver { +} + +#[lang = "freeze"] +pub(crate) unsafe auto trait Freeze {} + +mod libc { + #[link(name = "c")] + extern "C" { + pub fn printf(format: *const i8, ...) -> i32; + pub fn puts(s: *const u8) -> i32; + } +} + +#[lang = "index"] +pub trait Index { + type Output: ?Sized; + fn index(&self, index: Idx) -> &Self::Output; +} + +impl Index for [T; 3] { + type Output = T; + + fn index(&self, index: usize) -> &Self::Output { + &self[index] + } +} + +impl Index for [T] { + type Output = T; + + fn index(&self, index: usize) -> &Self::Output { + &self[index] + } +} + +#[lang = "drop_in_place"] +#[allow(unconditional_recursion)] +pub unsafe fn drop_in_place(to_drop: *mut T) { + // Code here does not matter - this is replaced by the + // real drop glue by the compiler. + drop_in_place(to_drop); +} + +#[lang = "panic"] +#[track_caller] +#[no_mangle] +pub fn panic(_msg: &str) -> ! { + unsafe { + libc::puts("Panicking\0" as *const str as *const u8); + intrinsics::abort(); + } +} + +#[lang = "panic_location"] +struct PanicLocation { + file: &'static str, + line: u32, + column: u32, +} + +#[lang = "panic_bounds_check"] +#[track_caller] +#[no_mangle] +fn panic_bounds_check(index: usize, len: usize) -> ! { + unsafe { + libc::printf("index out of bounds: the len is %d but the index is %d\n\0" as *const str as *const i8, len, index); + intrinsics::abort(); + } +} + +mod intrinsics { + extern "rust-intrinsic" { + pub fn abort() -> !; + } +} + +#[lang = "add"] +trait Add { + type Output; + + fn add(self, rhs: RHS) -> Self::Output; +} + +impl Add for u8 { + type Output = Self; + + fn add(self, rhs: Self) -> Self { + self + rhs + } +} + +impl Add for i8 { + type Output = Self; + + fn add(self, rhs: Self) -> Self { + self + rhs + } +} + +impl Add for i32 { + type Output = Self; + + fn add(self, rhs: Self) -> Self { + self + rhs + } +} + +impl Add for usize { + type Output = Self; + + fn add(self, rhs: Self) -> Self { + self + rhs + } +} + +impl Add for isize { + type Output = Self; + + fn add(self, rhs: Self) -> Self { + self + rhs + } +} + +#[lang = "sub"] +pub trait Sub { + type Output; + + fn sub(self, rhs: RHS) -> Self::Output; +} + +impl Sub for usize { + type Output = Self; + + fn sub(self, rhs: Self) -> Self { + self - rhs + } +} + +impl Sub for isize { + type Output = Self; + + fn sub(self, rhs: Self) -> Self { + self - rhs + } +} + +impl Sub for u8 { + type Output = Self; + + fn sub(self, rhs: Self) -> Self { + self - rhs + } +} + +impl Sub for i8 { + type Output = Self; + + fn sub(self, rhs: Self) -> Self { + self - rhs + } +} + +impl Sub for i16 { + type Output = Self; + + fn sub(self, rhs: Self) -> Self { + self - rhs + } +} + + +/* + * Code + */ + +static mut ONE: usize = 1; + +fn make_array() -> [u8; 3] { + [42, 10, 5] +} + +#[start] +fn main(argc: isize, _argv: *const *const u8) -> isize { + unsafe { + let ptr = ONE as *mut usize; + let value = ptr as usize; + libc::printf(b"%ld\n\0" as *const u8 as *const i8, value); + } + 0 +} diff --git a/compiler/rustc_codegen_gcc/tests/run/return-tuple.rs b/compiler/rustc_codegen_gcc/tests/run/return-tuple.rs new file mode 100644 index 0000000000..6fa10dca06 --- /dev/null +++ b/compiler/rustc_codegen_gcc/tests/run/return-tuple.rs @@ -0,0 +1,72 @@ +// Compiler: +// +// Run-time: +// status: 0 +// stdout: 10 +// 10 +// 42 + +#![feature(auto_traits, lang_items, no_core, start, intrinsics)] + +#![no_std] +#![no_core] + +#[lang = "copy"] +pub unsafe trait Copy {} + +unsafe impl Copy for bool {} +unsafe impl Copy for u8 {} +unsafe impl Copy for u16 {} +unsafe impl Copy for u32 {} +unsafe impl Copy for u64 {} +unsafe impl Copy for usize {} +unsafe impl Copy for i8 {} +unsafe impl Copy for i16 {} +unsafe impl Copy for i32 {} +unsafe impl Copy for isize {} +unsafe impl Copy for f32 {} +unsafe impl Copy for char {} + +mod libc { + #[link(name = "c")] + extern "C" { + pub fn printf(format: *const i8, ...) -> i32; + } +} + +/* + * Core + */ + +// Because we don't have core yet. +#[lang = "sized"] +pub trait Sized {} + +#[lang = "receiver"] +trait Receiver { +} + +#[lang = "freeze"] +pub(crate) unsafe auto trait Freeze {} + +/* + * Code + */ + +fn int_cast(a: u16, b: i16) -> (u8, u16, u32, usize, i8, i16, i32, isize, u8, u32) { + ( + a as u8, a as u16, a as u32, a as usize, a as i8, a as i16, a as i32, a as isize, b as u8, + b as u32, + ) +} + +#[start] +fn main(argc: isize, _argv: *const *const u8) -> isize { + let (a, b, c, d, e, f, g, h, i, j) = int_cast(10, 42); + unsafe { + libc::printf(b"%d\n\0" as *const u8 as *const i8, c); + libc::printf(b"%ld\n\0" as *const u8 as *const i8, d); + libc::printf(b"%ld\n\0" as *const u8 as *const i8, j); + } + 0 +} diff --git a/compiler/rustc_codegen_gcc/tests/run/slice.rs b/compiler/rustc_codegen_gcc/tests/run/slice.rs new file mode 100644 index 0000000000..ad9258ed0b --- /dev/null +++ b/compiler/rustc_codegen_gcc/tests/run/slice.rs @@ -0,0 +1,128 @@ +// Compiler: +// +// Run-time: +// status: 0 +// stdout: 5 + +#![feature(arbitrary_self_types, auto_traits, lang_items, no_core, start, intrinsics)] + +#![no_std] +#![no_core] + +/* + * Core + */ + +// Because we don't have core yet. +#[lang = "sized"] +pub trait Sized {} + +#[lang = "copy"] +trait Copy { +} + +impl Copy for isize {} +impl Copy for usize {} +impl Copy for i32 {} +impl Copy for u32 {} + +#[lang = "receiver"] +trait Receiver { +} + +#[lang = "freeze"] +pub(crate) unsafe auto trait Freeze {} + +mod libc { + #[link(name = "c")] + extern "C" { + pub fn printf(format: *const i8, ...) -> i32; + } +} + +#[lang = "index"] +pub trait Index { + type Output: ?Sized; + fn index(&self, index: Idx) -> &Self::Output; +} + +impl Index for [T; 3] { + type Output = T; + + fn index(&self, index: usize) -> &Self::Output { + &self[index] + } +} + +impl Index for [T] { + type Output = T; + + fn index(&self, index: usize) -> &Self::Output { + &self[index] + } +} + +#[lang = "unsize"] +pub trait Unsize {} + +#[lang = "coerce_unsized"] +pub trait CoerceUnsized {} + +impl<'a, 'b: 'a, T: ?Sized + Unsize, U: ?Sized> CoerceUnsized<&'a U> for &'b T {} +impl<'a, T: ?Sized + Unsize, U: ?Sized> CoerceUnsized<&'a mut U> for &'a mut T {} +impl, U: ?Sized> CoerceUnsized<*const U> for *const T {} +impl, U: ?Sized> CoerceUnsized<*mut U> for *mut T {} + +#[lang = "drop_in_place"] +#[allow(unconditional_recursion)] +pub unsafe fn drop_in_place(to_drop: *mut T) { + // Code here does not matter - this is replaced by the + // real drop glue by the compiler. + drop_in_place(to_drop); +} + +#[lang = "panic_location"] +struct PanicLocation { + file: &'static str, + line: u32, + column: u32, +} + +#[lang = "panic_bounds_check"] +#[track_caller] +#[no_mangle] +fn panic_bounds_check(index: usize, len: usize) -> ! { + unsafe { + libc::printf("index out of bounds: the len is %d but the index is %d\n\0" as *const str as *const i8, len, index); + intrinsics::abort(); + } +} + +mod intrinsics { + use super::Sized; + + extern "rust-intrinsic" { + pub fn abort() -> !; + } +} + +/* + * Code + */ + +static mut TWO: usize = 2; + +fn index_slice(s: &[u32]) -> u32 { + unsafe { + s[TWO] + } +} + +#[start] +fn main(mut argc: isize, _argv: *const *const u8) -> isize { + let array = [42, 7, 5]; + unsafe { + libc::printf(b"%ld\n\0" as *const u8 as *const i8, index_slice(&array)); + } + 0 +} diff --git a/compiler/rustc_codegen_gcc/tests/run/static.rs b/compiler/rustc_codegen_gcc/tests/run/static.rs new file mode 100644 index 0000000000..ab89f6aff4 --- /dev/null +++ b/compiler/rustc_codegen_gcc/tests/run/static.rs @@ -0,0 +1,106 @@ +// Compiler: +// +// Run-time: +// status: 0 +// stdout: 10 +// 14 +// 1 +// 12 +// 12 +// 1 + +#![feature(auto_traits, lang_items, no_core, start, intrinsics)] + +#![no_std] +#![no_core] + +/* + * Core + */ + +// Because we don't have core yet. +#[lang = "sized"] +pub trait Sized {} + +#[lang = "copy"] +trait Copy { +} + +impl Copy for isize {} + +#[lang = "receiver"] +trait Receiver { +} + +#[lang = "freeze"] +pub(crate) unsafe auto trait Freeze {} + +mod intrinsics { + use super::Sized; + + extern "rust-intrinsic" { + pub fn abort() -> !; + } +} + +mod libc { + #[link(name = "c")] + extern "C" { + pub fn printf(format: *const i8, ...) -> i32; + } +} + +#[lang = "structural_peq"] +pub trait StructuralPartialEq {} + +#[lang = "structural_teq"] +pub trait StructuralEq {} + +#[lang = "drop_in_place"] +#[allow(unconditional_recursion)] +pub unsafe fn drop_in_place(to_drop: *mut T) { + // Code here does not matter - this is replaced by the + // real drop glue by the compiler. + drop_in_place(to_drop); +} + +/* + * Code + */ + +struct Test { + field: isize, +} + +struct WithRef { + refe: &'static Test, +} + +static mut CONSTANT: isize = 10; + +static mut TEST: Test = Test { + field: 12, +}; + +static mut TEST2: Test = Test { + field: 14, +}; + +static mut WITH_REF: WithRef = WithRef { + refe: unsafe { &TEST }, +}; + +#[start] +fn main(mut argc: isize, _argv: *const *const u8) -> isize { + unsafe { + libc::printf(b"%ld\n\0" as *const u8 as *const i8, CONSTANT); + libc::printf(b"%ld\n\0" as *const u8 as *const i8, TEST2.field); + TEST2.field = argc; + libc::printf(b"%ld\n\0" as *const u8 as *const i8, TEST2.field); + libc::printf(b"%ld\n\0" as *const u8 as *const i8, WITH_REF.refe.field); + WITH_REF.refe = &TEST2; + libc::printf(b"%ld\n\0" as *const u8 as *const i8, TEST.field); + libc::printf(b"%ld\n\0" as *const u8 as *const i8, WITH_REF.refe.field); + } + 0 +} diff --git a/compiler/rustc_codegen_gcc/tests/run/structs.rs b/compiler/rustc_codegen_gcc/tests/run/structs.rs new file mode 100644 index 0000000000..6c8884855a --- /dev/null +++ b/compiler/rustc_codegen_gcc/tests/run/structs.rs @@ -0,0 +1,70 @@ +// Compiler: +// +// Run-time: +// status: 0 +// stdout: 1 +// 2 + +#![feature(auto_traits, lang_items, no_core, start, intrinsics)] + +#![no_std] +#![no_core] + +/* + * Core + */ + +// Because we don't have core yet. +#[lang = "sized"] +pub trait Sized {} + +#[lang = "copy"] +trait Copy { +} + +impl Copy for isize {} + +#[lang = "receiver"] +trait Receiver { +} + +#[lang = "freeze"] +pub(crate) unsafe auto trait Freeze {} + +mod libc { + #[link(name = "c")] + extern "C" { + pub fn printf(format: *const i8, ...) -> i32; + } +} + +/* + * Code + */ + +struct Test { + field: isize, +} + +struct Two { + two: isize, +} + +fn one() -> isize { + 1 +} + +#[start] +fn main(mut argc: isize, _argv: *const *const u8) -> isize { + let test = Test { + field: one(), + }; + let two = Two { + two: 2, + }; + unsafe { + libc::printf(b"%ld\n\0" as *const u8 as *const i8, test.field); + libc::printf(b"%ld\n\0" as *const u8 as *const i8, two.two); + } + 0 +} diff --git a/compiler/rustc_codegen_gcc/tests/run/tuple.rs b/compiler/rustc_codegen_gcc/tests/run/tuple.rs new file mode 100644 index 0000000000..0b670bf267 --- /dev/null +++ b/compiler/rustc_codegen_gcc/tests/run/tuple.rs @@ -0,0 +1,51 @@ +// Compiler: +// +// Run-time: +// status: 0 +// stdout: 3 + +#![feature(auto_traits, lang_items, no_core, start, intrinsics)] + +#![no_std] +#![no_core] + +/* + * Core + */ + +// Because we don't have core yet. +#[lang = "sized"] +pub trait Sized {} + +#[lang = "copy"] +trait Copy { +} + +impl Copy for isize {} + +#[lang = "receiver"] +trait Receiver { +} + +#[lang = "freeze"] +pub(crate) unsafe auto trait Freeze {} + +mod libc { + #[link(name = "c")] + extern "C" { + pub fn printf(format: *const i8, ...) -> i32; + } +} + +/* + * Code + */ + +#[start] +fn main(mut argc: isize, _argv: *const *const u8) -> isize { + let test: (isize, isize, isize) = (3, 1, 4); + unsafe { + libc::printf(b"%ld\n\0" as *const u8 as *const i8, test.0); + } + 0 +} diff --git a/compiler/rustc_codegen_llvm/Cargo.toml b/compiler/rustc_codegen_llvm/Cargo.toml index 521ce34418..a6a553b31a 100644 --- a/compiler/rustc_codegen_llvm/Cargo.toml +++ b/compiler/rustc_codegen_llvm/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustc_codegen_llvm" version = "0.0.0" -edition = "2018" +edition = "2021" [lib] test = false @@ -16,6 +16,7 @@ snap = "1" tracing = "0.1" rustc_middle = { path = "../rustc_middle" } rustc-demangle = "0.1.21" +rustc_arena = { path = "../rustc_arena" } rustc_attr = { path = "../rustc_attr" } rustc_codegen_ssa = { path = "../rustc_codegen_ssa" } rustc_data_structures = { path = "../rustc_data_structures" } @@ -25,6 +26,7 @@ rustc_hir = { path = "../rustc_hir" } rustc_index = { path = "../rustc_index" } rustc_llvm = { path = "../rustc_llvm" } rustc_metadata = { path = "../rustc_metadata" } +rustc_query_system = { path = "../rustc_query_system" } rustc_session = { path = "../rustc_session" } rustc_serialize = { path = "../rustc_serialize" } rustc_target = { path = "../rustc_target" } diff --git a/compiler/rustc_codegen_llvm/src/abi.rs b/compiler/rustc_codegen_llvm/src/abi.rs index abf0ea8cc0..dca9c1f04d 100644 --- a/compiler/rustc_codegen_llvm/src/abi.rs +++ b/compiler/rustc_codegen_llvm/src/abi.rs @@ -11,11 +11,12 @@ use rustc_codegen_ssa::mir::place::PlaceRef; use rustc_codegen_ssa::traits::*; use rustc_codegen_ssa::MemFlags; use rustc_middle::bug; +use rustc_middle::ty::layout::LayoutOf; pub use rustc_middle::ty::layout::{FAT_PTR_ADDR, FAT_PTR_EXTRA}; use rustc_middle::ty::Ty; use rustc_target::abi::call::ArgAbi; pub use rustc_target::abi::call::*; -use rustc_target::abi::{self, HasDataLayout, Int, LayoutOf}; +use rustc_target::abi::{self, HasDataLayout, Int}; pub use rustc_target::spec::abi::Abi; use libc::c_uint; @@ -510,7 +511,12 @@ impl<'tcx> FnAbiLlvmExt<'tcx> for FnAbi<'tcx, Ty<'tcx>> { } fn apply_attrs_callsite(&self, bx: &mut Builder<'a, 'll, 'tcx>, callsite: &'ll Value) { - // FIXME(wesleywiser, eddyb): We should apply `nounwind` and `noreturn` as appropriate to this callsite. + if self.ret.layout.abi.is_uninhabited() { + llvm::Attribute::NoReturn.apply_callsite(llvm::AttributePlace::Function, callsite); + } + if !self.can_unwind { + llvm::Attribute::NoUnwind.apply_callsite(llvm::AttributePlace::Function, callsite); + } let mut i = 0; let mut apply = |cx: &CodegenCx<'_, '_>, attrs: &ArgAttributes| { @@ -520,7 +526,7 @@ impl<'tcx> FnAbiLlvmExt<'tcx> for FnAbi<'tcx, Ty<'tcx>> { }; match self.ret.mode { PassMode::Direct(ref attrs) => { - attrs.apply_attrs_to_callsite(llvm::AttributePlace::ReturnValue, &bx.cx, callsite); + attrs.apply_attrs_to_callsite(llvm::AttributePlace::ReturnValue, bx.cx, callsite); } PassMode::Indirect { ref attrs, extra_attrs: _, on_stack } => { assert!(!on_stack); @@ -535,16 +541,13 @@ impl<'tcx> FnAbiLlvmExt<'tcx> for FnAbi<'tcx, Ty<'tcx>> { } _ => {} } - if let abi::Abi::Scalar(ref scalar) = self.ret.layout.abi { + if let abi::Abi::Scalar(scalar) = self.ret.layout.abi { // If the value is a boolean, the range is 0..2 and that ultimately // become 0..0 when the type becomes i1, which would be rejected // by the LLVM verifier. if let Int(..) = scalar.value { - if !scalar.is_bool() { - let range = scalar.valid_range_exclusive(bx); - if range.start != range.end { - bx.range_metadata(callsite, range); - } + if !scalar.is_bool() && !scalar.is_always_valid(bx) { + bx.range_metadata(callsite, scalar.valid_range); } } } diff --git a/compiler/rustc_codegen_llvm/src/allocator.rs b/compiler/rustc_codegen_llvm/src/allocator.rs index 2d79b73cf9..30d91b41a8 100644 --- a/compiler/rustc_codegen_llvm/src/allocator.rs +++ b/compiler/rustc_codegen_llvm/src/allocator.rs @@ -3,19 +3,22 @@ use libc::c_uint; use rustc_ast::expand::allocator::{AllocatorKind, AllocatorTy, ALLOCATOR_METHODS}; use rustc_middle::bug; use rustc_middle::ty::TyCtxt; +use rustc_session::config::DebugInfo; use rustc_span::symbol::sym; +use crate::debuginfo; use crate::llvm::{self, False, True}; use crate::ModuleLlvm; pub(crate) unsafe fn codegen( tcx: TyCtxt<'_>, - mods: &mut ModuleLlvm, + module_llvm: &mut ModuleLlvm, + module_name: &str, kind: AllocatorKind, has_alloc_error_handler: bool, ) { - let llcx = &*mods.llcx; - let llmod = mods.llmod(); + let llcx = &*module_llvm.llcx; + let llmod = module_llvm.llmod(); let usize = match tcx.sess.target.pointer_width { 16 => llvm::LLVMInt16TypeInContext(llcx), 32 => llvm::LLVMInt32TypeInContext(llcx), @@ -132,4 +135,10 @@ pub(crate) unsafe fn codegen( llvm::LLVMSetTailCall(ret, True); llvm::LLVMBuildRetVoid(llbuilder); llvm::LLVMDisposeBuilder(llbuilder); + + if tcx.sess.opts.debuginfo != DebugInfo::None { + let dbg_cx = debuginfo::CrateDebugContext::new(llmod); + debuginfo::metadata::compile_unit_metadata(tcx, module_name, &dbg_cx); + dbg_cx.finalize(tcx.sess); + } } diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs index e0d312727a..341a888241 100644 --- a/compiler/rustc_codegen_llvm/src/asm.rs +++ b/compiler/rustc_codegen_llvm/src/asm.rs @@ -105,7 +105,7 @@ impl AsmBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> { let r = r.unwrap(); // Again, based on how many outputs we have - let outputs = ia.outputs.iter().zip(&outputs).filter(|&(ref o, _)| !o.is_indirect); + let outputs = ia.outputs.iter().zip(&outputs).filter(|&(o, _)| !o.is_indirect); for (i, (_, &place)) in outputs.enumerate() { let v = if num_outputs == 1 { r } else { self.extract_value(r, i as u64) }; OperandValue::Immediate(v).store(self, place); @@ -331,7 +331,7 @@ impl AsmBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> { let output_type = match &output_types[..] { [] => self.type_void(), [ty] => ty, - tys => self.type_struct(&tys, false), + tys => self.type_struct(tys, false), }; let dialect = match asm_arch { InlineAsmArch::X86 | InlineAsmArch::X86_64 @@ -792,7 +792,7 @@ fn dummy_output_type(cx: &CodegenCx<'ll, 'tcx>, reg: InlineAsmRegClass) -> &'ll /// Helper function to get the LLVM type for a Scalar. Pointers are returned as /// the equivalent integer type. -fn llvm_asm_scalar_type(cx: &CodegenCx<'ll, 'tcx>, scalar: &Scalar) -> &'ll Type { +fn llvm_asm_scalar_type(cx: &CodegenCx<'ll, 'tcx>, scalar: Scalar) -> &'ll Type { match scalar.value { Primitive::Int(Integer::I8, _) => cx.type_i8(), Primitive::Int(Integer::I16, _) => cx.type_i16(), @@ -812,7 +812,7 @@ fn llvm_fixup_input( reg: InlineAsmRegClass, layout: &TyAndLayout<'tcx>, ) -> &'ll Value { - match (reg, &layout.abi) { + match (reg, layout.abi) { (InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg), Abi::Scalar(s)) => { if let Primitive::Int(Integer::I8, _) = s.value { let vec_ty = bx.cx.type_vector(bx.cx.type_i8(), 8); @@ -835,7 +835,7 @@ fn llvm_fixup_input( Abi::Vector { element, count }, ) if layout.size.bytes() == 8 => { let elem_ty = llvm_asm_scalar_type(bx.cx, element); - let vec_ty = bx.cx.type_vector(elem_ty, *count); + let vec_ty = bx.cx.type_vector(elem_ty, count); let indices: Vec<_> = (0..count * 2).map(|x| bx.const_i32(x as i32)).collect(); bx.shuffle_vector(value, bx.const_undef(vec_ty), bx.const_vector(&indices)) } @@ -890,7 +890,7 @@ fn llvm_fixup_output( reg: InlineAsmRegClass, layout: &TyAndLayout<'tcx>, ) -> &'ll Value { - match (reg, &layout.abi) { + match (reg, layout.abi) { (InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg), Abi::Scalar(s)) => { if let Primitive::Int(Integer::I8, _) = s.value { bx.extract_element(value, bx.const_i32(0)) @@ -910,8 +910,8 @@ fn llvm_fixup_output( Abi::Vector { element, count }, ) if layout.size.bytes() == 8 => { let elem_ty = llvm_asm_scalar_type(bx.cx, element); - let vec_ty = bx.cx.type_vector(elem_ty, *count * 2); - let indices: Vec<_> = (0..*count).map(|x| bx.const_i32(x as i32)).collect(); + let vec_ty = bx.cx.type_vector(elem_ty, count * 2); + let indices: Vec<_> = (0..count).map(|x| bx.const_i32(x as i32)).collect(); bx.shuffle_vector(value, bx.const_undef(vec_ty), bx.const_vector(&indices)) } (InlineAsmRegClass::X86(X86InlineAsmRegClass::reg_abcd), Abi::Scalar(s)) @@ -965,7 +965,7 @@ fn llvm_fixup_output_type( reg: InlineAsmRegClass, layout: &TyAndLayout<'tcx>, ) -> &'ll Type { - match (reg, &layout.abi) { + match (reg, layout.abi) { (InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg), Abi::Scalar(s)) => { if let Primitive::Int(Integer::I8, _) = s.value { cx.type_vector(cx.type_i8(), 8) diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs index 56b93f8346..659cf9ea07 100644 --- a/compiler/rustc_codegen_llvm/src/attributes.rs +++ b/compiler/rustc_codegen_llvm/src/attributes.rs @@ -263,6 +263,10 @@ pub fn from_fn_attrs(cx: &CodegenCx<'ll, 'tcx>, llfn: &'ll Value, instance: ty:: attributes::emit_uwtable(llfn, true); } + if cx.sess().opts.debugging_opts.profile_sample_use.is_some() { + llvm::AddFunctionAttrString(llfn, Function, cstr!("use-sample-profile")); + } + // FIXME: none of these three functions interact with source level attributes. set_frame_pointer_type(cx, llfn); set_instrument_function(cx, llfn); @@ -305,9 +309,12 @@ pub fn from_fn_attrs(cx: &CodegenCx<'ll, 'tcx>, llfn: &'ll Value, instance: ty:: let mut function_features = codegen_fn_attrs .target_features .iter() - .map(|f| { + .flat_map(|f| { let feature = &f.as_str(); - format!("+{}", llvm_util::to_llvm_feature(cx.tcx.sess, feature)) + llvm_util::to_llvm_feature(cx.tcx.sess, feature) + .into_iter() + .map(|f| format!("+{}", f)) + .collect::>() }) .chain(codegen_fn_attrs.instruction_set.iter().map(|x| match x { InstructionSetAttr::ArmA32 => "-thumb-mode".to_string(), diff --git a/compiler/rustc_codegen_llvm/src/back/archive.rs b/compiler/rustc_codegen_llvm/src/back/archive.rs index 6ac7093b7d..2fb5a0f9fa 100644 --- a/compiler/rustc_codegen_llvm/src/back/archive.rs +++ b/compiler/rustc_codegen_llvm/src/back/archive.rs @@ -9,18 +9,15 @@ use std::str; use crate::llvm::archive_ro::{ArchiveRO, Child}; use crate::llvm::{self, ArchiveKind, LLVMMachineType, LLVMRustCOFFShortExport}; -use rustc_codegen_ssa::back::archive::{find_library, ArchiveBuilder}; -use rustc_codegen_ssa::{looks_like_rust_object_file, METADATA_FILENAME}; +use rustc_codegen_ssa::back::archive::ArchiveBuilder; use rustc_data_structures::temp_dir::MaybeTempDir; -use rustc_middle::middle::cstore::{DllCallingConvention, DllImport}; +use rustc_session::cstore::{DllCallingConvention, DllImport}; use rustc_session::Session; -use rustc_span::symbol::Symbol; struct ArchiveConfig<'a> { pub sess: &'a Session, pub dst: PathBuf, pub src: Option, - pub lib_search_paths: Vec, } /// Helper for adding many files to an archive. @@ -54,13 +51,7 @@ fn is_relevant_child(c: &Child<'_>) -> bool { } fn archive_config<'a>(sess: &'a Session, output: &Path, input: Option<&Path>) -> ArchiveConfig<'a> { - use rustc_codegen_ssa::back::link::archive_search_paths; - ArchiveConfig { - sess, - dst: output.to_path_buf(), - src: input.map(|p| p.to_path_buf()), - lib_search_paths: archive_search_paths(sess), - } + ArchiveConfig { sess, dst: output.to_path_buf(), src: input.map(|p| p.to_path_buf()) } } /// Map machine type strings to values of LLVM's MachineTypes enum. @@ -111,57 +102,23 @@ impl<'a> ArchiveBuilder<'a> for LlvmArchiveBuilder<'a> { .collect() } - /// Adds all of the contents of a native library to this archive. This will - /// search in the relevant locations for a library named `name`. - fn add_native_library(&mut self, name: Symbol, verbatim: bool) { - let location = - find_library(name, verbatim, &self.config.lib_search_paths, self.config.sess); - self.add_archive(&location, |_| false).unwrap_or_else(|e| { - self.config.sess.fatal(&format!( - "failed to add native library {}: {}", - location.to_string_lossy(), - e - )); + fn add_archive(&mut self, archive: &Path, skip: F) -> io::Result<()> + where + F: FnMut(&str) -> bool + 'static, + { + let archive_ro = match ArchiveRO::open(archive) { + Ok(ar) => ar, + Err(e) => return Err(io::Error::new(io::ErrorKind::Other, e)), + }; + if self.additions.iter().any(|ar| ar.path() == archive) { + return Ok(()); + } + self.additions.push(Addition::Archive { + path: archive.to_path_buf(), + archive: archive_ro, + skip: Box::new(skip), }); - } - - /// Adds all of the contents of the rlib at the specified path to this - /// archive. - /// - /// This ignores adding the bytecode from the rlib, and if LTO is enabled - /// then the object file also isn't added. - fn add_rlib( - &mut self, - rlib: &Path, - name: &str, - lto: bool, - skip_objects: bool, - ) -> io::Result<()> { - // Ignoring obj file starting with the crate name - // as simple comparison is not enough - there - // might be also an extra name suffix - let obj_start = name.to_owned(); - - self.add_archive(rlib, move |fname: &str| { - // Ignore metadata files, no matter the name. - if fname == METADATA_FILENAME { - return true; - } - - // Don't include Rust objects if LTO is enabled - if lto && looks_like_rust_object_file(fname) { - return true; - } - - // Otherwise if this is *not* a rust object and we're skipping - // objects then skip this file - if skip_objects && (!fname.starts_with(&obj_start) || !fname.ends_with(".o")) { - return true; - } - - // ok, don't skip this - false - }) + Ok(()) } /// Adds an arbitrary file to this archive @@ -206,13 +163,13 @@ impl<'a> ArchiveBuilder<'a> for LlvmArchiveBuilder<'a> { // All import names are Rust identifiers and therefore cannot contain \0 characters. // FIXME: when support for #[link_name] implemented, ensure that import.name values don't // have any \0 characters - let import_name_vector: Vec = dll_imports + let import_name_and_ordinal_vector: Vec<(CString, Option)> = dll_imports .iter() .map(|import: &DllImport| { if self.config.sess.target.arch == "x86" { - LlvmArchiveBuilder::i686_decorated_name(import) + (LlvmArchiveBuilder::i686_decorated_name(import), import.ordinal) } else { - CString::new(import.name.to_string()).unwrap() + (CString::new(import.name.to_string()).unwrap(), import.ordinal) } }) .collect(); @@ -227,9 +184,9 @@ impl<'a> ArchiveBuilder<'a> for LlvmArchiveBuilder<'a> { dll_imports.iter().map(|import| import.name.to_string()).collect::>().join(", "), ); - let ffi_exports: Vec = import_name_vector + let ffi_exports: Vec = import_name_and_ordinal_vector .iter() - .map(|name_z| LLVMRustCOFFShortExport::from_name(name_z.as_ptr())) + .map(|(name_z, ordinal)| LLVMRustCOFFShortExport::new(name_z.as_ptr(), *ordinal)) .collect(); let result = unsafe { crate::llvm::LLVMRustWriteImportLibrary( @@ -270,25 +227,6 @@ impl<'a> LlvmArchiveBuilder<'a> { self.src_archive.as_ref().unwrap().as_ref() } - fn add_archive(&mut self, archive: &Path, skip: F) -> io::Result<()> - where - F: FnMut(&str) -> bool + 'static, - { - let archive_ro = match ArchiveRO::open(archive) { - Ok(ar) => ar, - Err(e) => return Err(io::Error::new(io::ErrorKind::Other, e)), - }; - if self.additions.iter().any(|ar| ar.path() == archive) { - return Ok(()); - } - self.additions.push(Addition::Archive { - path: archive.to_path_buf(), - archive: archive_ro, - skip: Box::new(skip), - }); - Ok(()) - } - fn llvm_archive_kind(&self) -> Result { let kind = &*self.config.sess.target.archive_format; kind.parse().map_err(|_| kind) diff --git a/compiler/rustc_codegen_llvm/src/back/lto.rs b/compiler/rustc_codegen_llvm/src/back/lto.rs index f612785e5a..97780de9ba 100644 --- a/compiler/rustc_codegen_llvm/src/back/lto.rs +++ b/compiler/rustc_codegen_llvm/src/back/lto.rs @@ -109,7 +109,7 @@ fn prepare_lto( .extend(exported_symbols[&cnum].iter().filter_map(symbol_filter)); } - let archive = ArchiveRO::open(&path).expect("wanted an rlib"); + let archive = ArchiveRO::open(path).expect("wanted an rlib"); let obj_files = archive .iter() .filter_map(|child| child.ok().and_then(|c| c.name().map(|name| (name, c)))) @@ -316,14 +316,28 @@ fn fat_lto( .generic_activity_with_arg("LLVM_fat_lto_link_module", format!("{:?}", name)); info!("linking {:?}", name); let data = bc_decoded.data(); - linker.add(&data).map_err(|()| { + linker.add(data).map_err(|()| { let msg = format!("failed to load bc of {:?}", name); - write::llvm_err(&diag_handler, &msg) + write::llvm_err(diag_handler, &msg) })?; serialized_bitcode.push(bc_decoded); } drop(linker); - save_temp_bitcode(&cgcx, &module, "lto.input"); + save_temp_bitcode(cgcx, &module, "lto.input"); + + // Fat LTO also suffers from the invalid DWARF issue similar to Thin LTO. + // Here we rewrite all `DICompileUnit` pointers if there is only one `DICompileUnit`. + // This only works around the problem when codegen-units = 1. + // Refer to the comments in the `optimize_thin_module` function for more details. + let mut cu1 = ptr::null_mut(); + let mut cu2 = ptr::null_mut(); + unsafe { llvm::LLVMRustLTOGetDICompileUnit(llmod, &mut cu1, &mut cu2) }; + if !cu2.is_null() { + let _timer = + cgcx.prof.generic_activity_with_arg("LLVM_fat_lto_patch_debuginfo", &*module.name); + unsafe { llvm::LLVMRustLTOPatchDICompileUnit(llmod, cu1) }; + save_temp_bitcode(cgcx, &module, "fat-lto-after-patch"); + } // Internalize everything below threshold to help strip out more modules and such. unsafe { @@ -333,14 +347,14 @@ fn fat_lto( ptr as *const *const libc::c_char, symbols_below_threshold.len() as libc::size_t, ); - save_temp_bitcode(&cgcx, &module, "lto.after-restriction"); + save_temp_bitcode(cgcx, &module, "lto.after-restriction"); } if cgcx.no_landing_pads { unsafe { llvm::LLVMRustMarkAllFunctionsNounwind(llmod); } - save_temp_bitcode(&cgcx, &module, "lto.after-nounwind"); + save_temp_bitcode(cgcx, &module, "lto.after-nounwind"); } } @@ -484,7 +498,7 @@ fn thin_lto( symbols_below_threshold.as_ptr(), symbols_below_threshold.len() as u32, ) - .ok_or_else(|| write::llvm_err(&diag_handler, "failed to prepare thin LTO context"))?; + .ok_or_else(|| write::llvm_err(diag_handler, "failed to prepare thin LTO context"))?; let data = ThinData(data); @@ -558,7 +572,7 @@ fn thin_lto( if let Some(path) = key_map_path { if let Err(err) = curr_key_map.save_to_file(&path) { let msg = format!("Error while writing ThinLTO key data: {}", err); - return Err(write::llvm_err(&diag_handler, &msg)); + return Err(write::llvm_err(diag_handler, &msg)); } } @@ -582,7 +596,7 @@ pub(crate) fn run_pass_manager( // tools/lto/LTOCodeGenerator.cpp debug!("running the pass manager"); unsafe { - if write::should_use_new_llvm_pass_manager(config) { + if write::should_use_new_llvm_pass_manager(cgcx, config) { let opt_stage = if thin { llvm::OptStage::ThinLTO } else { llvm::OptStage::FatLTO }; let opt_level = config.opt_level.unwrap_or(config::OptLevel::No); write::optimize_with_new_llvm_pass_manager( @@ -730,8 +744,7 @@ pub unsafe fn optimize_thin_module( // crates but for locally codegened modules we may be able to reuse // that LLVM Context and Module. let llcx = llvm::LLVMRustContextCreate(cgcx.fewer_names); - let llmod_raw = - parse_module(llcx, &module_name, thin_module.data(), &diag_handler)? as *const _; + let llmod_raw = parse_module(llcx, module_name, thin_module.data(), &diag_handler)? as *const _; let module = ModuleCodegen { module_llvm: ModuleLlvm { llmod_raw, llcx, tm }, name: thin_module.name().to_string(), @@ -740,7 +753,7 @@ pub unsafe fn optimize_thin_module( { let target = &*module.module_llvm.tm; let llmod = module.module_llvm.llmod(); - save_temp_bitcode(&cgcx, &module, "thin-lto-input"); + save_temp_bitcode(cgcx, &module, "thin-lto-input"); // Before we do much else find the "main" `DICompileUnit` that we'll be // using below. If we find more than one though then rustc has changed @@ -748,7 +761,7 @@ pub unsafe fn optimize_thin_module( // an error. let mut cu1 = ptr::null_mut(); let mut cu2 = ptr::null_mut(); - llvm::LLVMRustThinLTOGetDICompileUnit(llmod, &mut cu1, &mut cu2); + llvm::LLVMRustLTOGetDICompileUnit(llmod, &mut cu1, &mut cu2); if !cu2.is_null() { let msg = "multiple source DICompileUnits found"; return Err(write::llvm_err(&diag_handler, msg)); @@ -761,7 +774,7 @@ pub unsafe fn optimize_thin_module( .prof .generic_activity_with_arg("LLVM_thin_lto_remove_landing_pads", thin_module.name()); llvm::LLVMRustMarkAllFunctionsNounwind(llmod); - save_temp_bitcode(&cgcx, &module, "thin-lto-after-nounwind"); + save_temp_bitcode(cgcx, &module, "thin-lto-after-nounwind"); } // Up next comes the per-module local analyses that we do for Thin LTO. @@ -847,7 +860,7 @@ pub unsafe fn optimize_thin_module( let _timer = cgcx .prof .generic_activity_with_arg("LLVM_thin_lto_patch_debuginfo", thin_module.name()); - llvm::LLVMRustThinLTOPatchDICompileUnit(llmod, cu1); + llvm::LLVMRustLTOPatchDICompileUnit(llmod, cu1); save_temp_bitcode(cgcx, &module, "thin-lto-after-patch"); } @@ -933,7 +946,7 @@ pub fn parse_module<'a>( llvm::LLVMRustParseBitcodeForLTO(cx, data.as_ptr(), data.len(), name.as_ptr()).ok_or_else( || { let msg = "failed to parse bitcode for LTO module"; - write::llvm_err(&diag_handler, msg) + write::llvm_err(diag_handler, msg) }, ) } diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs index 791604a182..b6d682f232 100644 --- a/compiler/rustc_codegen_llvm/src/back/write.rs +++ b/compiler/rustc_codegen_llvm/src/back/write.rs @@ -41,7 +41,7 @@ use std::sync::Arc; pub fn llvm_err(handler: &rustc_errors::Handler, msg: &str) -> FatalError { match llvm::last_error() { Some(err) => handler.fatal(&format!("{}: {}", msg, err)), - None => handler.fatal(&msg), + None => handler.fatal(msg), } } @@ -96,7 +96,7 @@ pub fn create_target_machine(tcx: TyCtxt<'_>, mod_name: &str) -> &'static mut ll None }; let config = TargetMachineFactoryConfig { split_dwarf_file }; - target_machine_factory(&tcx.sess, tcx.backend_optimization_level(()))(config) + target_machine_factory(tcx.sess, tcx.backend_optimization_level(()))(config) .unwrap_or_else(|err| llvm_err(tcx.sess.diagnostic(), &err).raise()) } @@ -129,7 +129,8 @@ fn to_pass_builder_opt_level(cfg: config::OptLevel) -> llvm::PassBuilderOptLevel fn to_llvm_relocation_model(relocation_model: RelocModel) -> llvm::RelocModel { match relocation_model { RelocModel::Static => llvm::RelocModel::Static, - RelocModel::Pic => llvm::RelocModel::PIC, + // LLVM doesn't have a PIE relocation model, it represents PIE as PIC with an extra attribute. + RelocModel::Pic | RelocModel::Pie => llvm::RelocModel::PIC, RelocModel::DynamicNoPic => llvm::RelocModel::DynamicNoPic, RelocModel::Ropi => llvm::RelocModel::ROPI, RelocModel::Rwpi => llvm::RelocModel::RWPI, @@ -369,9 +370,22 @@ fn get_pgo_use_path(config: &ModuleConfig) -> Option { .map(|path_buf| CString::new(path_buf.to_string_lossy().as_bytes()).unwrap()) } -pub(crate) fn should_use_new_llvm_pass_manager(config: &ModuleConfig) -> bool { - // The new pass manager is disabled by default. - config.new_llvm_pass_manager.unwrap_or(false) +fn get_pgo_sample_use_path(config: &ModuleConfig) -> Option { + config + .pgo_sample_use + .as_ref() + .map(|path_buf| CString::new(path_buf.to_string_lossy().as_bytes()).unwrap()) +} + +pub(crate) fn should_use_new_llvm_pass_manager( + _cgcx: &CodegenContext, + config: &ModuleConfig, +) -> bool { + // The new pass manager is causing significant performance issues such as #91128, and is + // therefore disabled in stable versions of rustc by default. + config + .new_llvm_pass_manager + .unwrap_or(false) } pub(crate) unsafe fn optimize_with_new_llvm_pass_manager( @@ -387,6 +401,7 @@ pub(crate) unsafe fn optimize_with_new_llvm_pass_manager( let using_thin_buffers = opt_stage == llvm::OptStage::PreLinkThinLTO || config.bitcode_needed(); let pgo_gen_path = get_pgo_gen_path(config); let pgo_use_path = get_pgo_use_path(config); + let pgo_sample_use_path = get_pgo_sample_use_path(config); let is_lto = opt_stage == llvm::OptStage::ThinLTO || opt_stage == llvm::OptStage::FatLTO; // Sanitizer instrumentation is only inserted during the pre-link optimization stage. let sanitizer_options = if !is_lto { @@ -404,13 +419,15 @@ pub(crate) unsafe fn optimize_with_new_llvm_pass_manager( None }; - let llvm_selfprofiler = if cgcx.prof.llvm_recording_enabled() { - let mut llvm_profiler = LlvmSelfProfiler::new(cgcx.prof.get_self_profiler().unwrap()); - &mut llvm_profiler as *mut _ as *mut c_void + let mut llvm_profiler = if cgcx.prof.llvm_recording_enabled() { + Some(LlvmSelfProfiler::new(cgcx.prof.get_self_profiler().unwrap())) } else { - std::ptr::null_mut() + None }; + let llvm_selfprofiler = + llvm_profiler.as_mut().map(|s| s as *mut _ as *mut c_void).unwrap_or(std::ptr::null_mut()); + let extra_passes = config.passes.join(","); // FIXME: NewPM doesn't provide a facility to pass custom InlineParams. @@ -435,6 +452,8 @@ pub(crate) unsafe fn optimize_with_new_llvm_pass_manager( pgo_use_path.as_ref().map_or(std::ptr::null(), |s| s.as_ptr()), config.instrument_coverage, config.instrument_gcov, + pgo_sample_use_path.as_ref().map_or(std::ptr::null(), |s| s.as_ptr()), + config.debug_info_for_profiling, llvm_selfprofiler, selfprofile_before_pass_callback, selfprofile_after_pass_callback, @@ -468,7 +487,7 @@ pub(crate) unsafe fn optimize( } if let Some(opt_level) = config.opt_level { - if should_use_new_llvm_pass_manager(config) { + if should_use_new_llvm_pass_manager(cgcx, config) { let opt_stage = match cgcx.lto { Lto::Fat => llvm::OptStage::PreLinkFatLTO, Lto::Thin | Lto::ThinLocal => llvm::OptStage::PreLinkThinLTO, @@ -540,6 +559,9 @@ pub(crate) unsafe fn optimize( if config.instrument_coverage { llvm::LLVMRustAddPass(mpm, find_pass("instrprof").unwrap()); } + if config.debug_info_for_profiling { + llvm::LLVMRustAddPass(mpm, find_pass("add-discriminators").unwrap()); + } add_sanitizer_passes(config, &mut extra_passes); @@ -554,7 +576,7 @@ pub(crate) unsafe fn optimize( let prepare_for_thin_lto = cgcx.lto == Lto::Thin || cgcx.lto == Lto::ThinLocal || (cgcx.lto != Lto::Fat && cgcx.opts.cg.linker_plugin_lto.enabled()); - with_llvm_pmb(llmod, &config, opt_level, prepare_for_thin_lto, &mut |b| { + with_llvm_pmb(llmod, config, opt_level, prepare_for_thin_lto, &mut |b| { llvm::LLVMRustAddLastExtensionPasses( b, extra_passes.as_ptr(), @@ -656,9 +678,9 @@ pub(crate) fn link( let _timer = cgcx.prof.generic_activity_with_arg("LLVM_link_module", format!("{:?}", module.name)); let buffer = ModuleBuffer::new(module.module_llvm.llmod()); - linker.add(&buffer.data()).map_err(|()| { + linker.add(buffer.data()).map_err(|()| { let msg = format!("failed to serialize module {:?}", module.name); - llvm_err(&diag_handler, &msg) + llvm_err(diag_handler, &msg) })?; } drop(linker); @@ -997,6 +1019,7 @@ pub unsafe fn with_llvm_pmb( let inline_threshold = config.inline_threshold; let pgo_gen_path = get_pgo_gen_path(config); let pgo_use_path = get_pgo_use_path(config); + let pgo_sample_use_path = get_pgo_sample_use_path(config); llvm::LLVMRustConfigurePassManagerBuilder( builder, @@ -1007,6 +1030,7 @@ pub unsafe fn with_llvm_pmb( prepare_for_thin_lto, pgo_gen_path.as_ref().map_or(ptr::null(), |s| s.as_ptr()), pgo_use_path.as_ref().map_or(ptr::null(), |s| s.as_ptr()), + pgo_sample_use_path.as_ref().map_or(ptr::null(), |s| s.as_ptr()), ); llvm::LLVMPassManagerBuilderSetSizeLevel(builder, opt_size as u32); diff --git a/compiler/rustc_codegen_llvm/src/base.rs b/compiler/rustc_codegen_llvm/src/base.rs index a6bdbd1189..3026c2fa03 100644 --- a/compiler/rustc_codegen_llvm/src/base.rs +++ b/compiler/rustc_codegen_llvm/src/base.rs @@ -25,9 +25,9 @@ use rustc_codegen_ssa::mono_item::MonoItemExt; use rustc_codegen_ssa::traits::*; use rustc_codegen_ssa::{ModuleCodegen, ModuleKind}; use rustc_data_structures::small_c_str::SmallCStr; +use rustc_metadata::EncodedMetadata; use rustc_middle::dep_graph; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs; -use rustc_middle::middle::cstore::EncodedMetadata; use rustc_middle::middle::exported_symbols; use rustc_middle::mir::mono::{Linkage, Visibility}; use rustc_middle::ty::TyCtxt; @@ -64,7 +64,7 @@ pub fn write_compressed_metadata<'tcx>( let (metadata_llcx, metadata_llmod) = (&*llvm_module.llcx, llvm_module.llmod()); let mut compressed = rustc_metadata::METADATA_HEADER.to_vec(); - FrameEncoder::new(&mut compressed).write_all(&metadata.raw_data).unwrap(); + FrameEncoder::new(&mut compressed).write_all(metadata.raw_data()).unwrap(); let llmeta = common::bytes_in_context(metadata_llcx, &compressed); let llconst = common::struct_in_context(metadata_llcx, &[llmeta], false); diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index 47529f719b..d5deacf381 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -15,15 +15,17 @@ use rustc_codegen_ssa::traits::*; use rustc_codegen_ssa::MemFlags; use rustc_data_structures::small_c_str::SmallCStr; use rustc_hir::def_id::DefId; -use rustc_middle::ty::layout::TyAndLayout; +use rustc_middle::ty::layout::{ + FnAbiError, FnAbiOfHelpers, FnAbiRequest, LayoutError, LayoutOfHelpers, TyAndLayout, +}; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_span::Span; -use rustc_target::abi::{self, Align, Size}; +use rustc_target::abi::{self, call::FnAbi, Align, Size, WrappingRange}; use rustc_target::spec::{HasTargetSpec, Target}; use std::borrow::Cow; use std::ffi::CStr; use std::iter; -use std::ops::{Deref, Range}; +use std::ops::Deref; use std::ptr; use tracing::debug; @@ -84,16 +86,30 @@ impl ty::layout::HasParamEnv<'tcx> for Builder<'_, '_, 'tcx> { impl HasTargetSpec for Builder<'_, '_, 'tcx> { #[inline] fn target_spec(&self) -> &Target { - &self.cx.target_spec() + self.cx.target_spec() } } -impl abi::LayoutOf<'tcx> for Builder<'_, '_, 'tcx> { - type Ty = Ty<'tcx>; - type TyAndLayout = TyAndLayout<'tcx>; +impl LayoutOfHelpers<'tcx> for Builder<'_, '_, 'tcx> { + type LayoutOfResult = TyAndLayout<'tcx>; - fn layout_of(&self, ty: Ty<'tcx>) -> Self::TyAndLayout { - self.cx.layout_of(ty) + #[inline] + fn handle_layout_err(&self, err: LayoutError<'tcx>, span: Span, ty: Ty<'tcx>) -> ! { + self.cx.handle_layout_err(err, span, ty) + } +} + +impl FnAbiOfHelpers<'tcx> for Builder<'_, '_, 'tcx> { + type FnAbiOfResult = &'tcx FnAbi<'tcx, Ty<'tcx>>; + + #[inline] + fn handle_fn_abi_err( + &self, + err: FnAbiError<'tcx>, + span: Span, + fn_abi_request: FnAbiRequest<'tcx>, + ) -> ! { + self.cx.handle_fn_abi_err(err, span, fn_abi_request) } } @@ -382,7 +398,7 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { val } } - fn to_immediate_scalar(&mut self, val: Self::Value, scalar: &abi::Scalar) -> Self::Value { + fn to_immediate_scalar(&mut self, val: Self::Value, scalar: abi::Scalar) -> Self::Value { if scalar.is_bool() { return self.trunc(val, self.cx().type_i1()); } @@ -460,16 +476,15 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { fn scalar_load_metadata<'a, 'll, 'tcx>( bx: &mut Builder<'a, 'll, 'tcx>, load: &'ll Value, - scalar: &abi::Scalar, + scalar: abi::Scalar, ) { match scalar.value { abi::Int(..) => { - let range = scalar.valid_range_exclusive(bx); - if range.start != range.end { - bx.range_metadata(load, range); + if !scalar.is_always_valid(bx) { + bx.range_metadata(load, scalar.valid_range); } } - abi::Pointer if !scalar.valid_range.contains_zero() => { + abi::Pointer if !scalar.valid_range.contains(0) => { bx.nonnull_metadata(load); } _ => {} @@ -489,17 +504,17 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { } let llval = const_llval.unwrap_or_else(|| { let load = self.load(place.layout.llvm_type(self), place.llval, place.align); - if let abi::Abi::Scalar(ref scalar) = place.layout.abi { + if let abi::Abi::Scalar(scalar) = place.layout.abi { scalar_load_metadata(self, load, scalar); } load }); OperandValue::Immediate(self.to_immediate(llval, place.layout)) - } else if let abi::Abi::ScalarPair(ref a, ref b) = place.layout.abi { + } else if let abi::Abi::ScalarPair(a, b) = place.layout.abi { let b_offset = a.value.size(self).align_to(b.value.align(self).abi); let pair_ty = place.layout.llvm_type(self); - let mut load = |i, scalar: &abi::Scalar, align| { + let mut load = |i, scalar: abi::Scalar, align| { let llptr = self.struct_gep(pair_ty, place.llval, i as u64); let llty = place.layout.scalar_pair_element_llvm_type(self, i, false); let load = self.load(llty, llptr, align); @@ -555,7 +570,7 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { next_bx } - fn range_metadata(&mut self, load: &'ll Value, range: Range) { + fn range_metadata(&mut self, load: &'ll Value, range: WrappingRange) { if self.sess().target.arch == "amdgpu" { // amdgpu/LLVM does something weird and thinks an i64 value is // split into a v2i32, halving the bitwidth LLVM expects, @@ -568,7 +583,7 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { let llty = self.cx.val_ty(load); let v = [ self.cx.const_uint_big(llty, range.start), - self.cx.const_uint_big(llty, range.end), + self.cx.const_uint_big(llty, range.end.wrapping_add(1)), ]; llvm::LLVMSetMetadata( @@ -813,6 +828,7 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { } fn fcmp(&mut self, op: RealPredicate, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { + let op = llvm::RealPredicate::from_generic(op); unsafe { llvm::LLVMBuildFCmp(self.llbuilder, op as c_uint, lhs, rhs, UNNAMED) } } diff --git a/compiler/rustc_codegen_llvm/src/callee.rs b/compiler/rustc_codegen_llvm/src/callee.rs index bb16c90cd1..1bc924d3b9 100644 --- a/compiler/rustc_codegen_llvm/src/callee.rs +++ b/compiler/rustc_codegen_llvm/src/callee.rs @@ -4,7 +4,7 @@ //! and methods are represented as just a fn ptr and not a full //! closure. -use crate::abi::{FnAbi, FnAbiLlvmExt}; +use crate::abi::FnAbiLlvmExt; use crate::attributes; use crate::context::CodegenCx; use crate::llvm; @@ -12,7 +12,7 @@ use crate::value::Value; use rustc_codegen_ssa::traits::*; use tracing::debug; -use rustc_middle::ty::layout::{FnAbiExt, HasTyCtxt}; +use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt}; use rustc_middle::ty::{self, Instance, TypeFoldable}; /// Codegens a reference to a fn/method item, monomorphizing and @@ -42,9 +42,9 @@ pub fn get_fn(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'tcx>) -> &'ll Value sym ); - let fn_abi = FnAbi::of_instance(cx, instance, &[]); + let fn_abi = cx.fn_abi_of_instance(instance, ty::List::empty()); - let llfn = if let Some(llfn) = cx.get_declared_value(&sym) { + let llfn = if let Some(llfn) = cx.get_declared_value(sym) { // Create a fn pointer with the new signature. let llptrty = fn_abi.ptr_to_llvm_type(cx); @@ -79,7 +79,7 @@ pub fn get_fn(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'tcx>) -> &'ll Value llfn } } else { - let llfn = cx.declare_fn(&sym, &fn_abi); + let llfn = cx.declare_fn(sym, fn_abi); debug!("get_fn: not casting pointer!"); attributes::from_fn_attrs(cx, llfn, instance); @@ -175,7 +175,7 @@ pub fn get_fn(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'tcx>) -> &'ll Value // should use dllimport for functions. if cx.use_dll_storage_attrs && tcx.is_dllimport_foreign_item(instance_def_id) - && tcx.sess.target.env != "gnu" + && !matches!(tcx.sess.target.env.as_ref(), "gnu" | "uclibc") { llvm::LLVMSetDLLStorageClass(llfn, llvm::DLLStorageClass::DllImport); } diff --git a/compiler/rustc_codegen_llvm/src/common.rs b/compiler/rustc_codegen_llvm/src/common.rs index 5532f53e40..73a8d46443 100644 --- a/compiler/rustc_codegen_llvm/src/common.rs +++ b/compiler/rustc_codegen_llvm/src/common.rs @@ -12,9 +12,10 @@ use rustc_codegen_ssa::mir::place::PlaceRef; use rustc_codegen_ssa::traits::*; use rustc_middle::bug; use rustc_middle::mir::interpret::{Allocation, GlobalAlloc, Scalar}; -use rustc_middle::ty::{layout::TyAndLayout, ScalarInt}; +use rustc_middle::ty::layout::{LayoutOf, TyAndLayout}; +use rustc_middle::ty::ScalarInt; use rustc_span::symbol::Symbol; -use rustc_target::abi::{self, AddressSpace, HasDataLayout, LayoutOf, Pointer, Size}; +use rustc_target::abi::{self, AddressSpace, HasDataLayout, Pointer, Size}; use libc::{c_char, c_uint}; use tracing::debug; @@ -227,7 +228,7 @@ impl ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> { }) } - fn scalar_to_backend(&self, cv: Scalar, layout: &abi::Scalar, llty: &'ll Type) -> &'ll Value { + fn scalar_to_backend(&self, cv: Scalar, layout: abi::Scalar, llty: &'ll Type) -> &'ll Value { let bitsize = if layout.is_bool() { 1 } else { layout.value.size(self).bits() }; match cv { Scalar::Int(ScalarInt::ZST) => { diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs index a4e4fc4fff..1afa6f0283 100644 --- a/compiler/rustc_codegen_llvm/src/consts.rs +++ b/compiler/rustc_codegen_llvm/src/consts.rs @@ -15,10 +15,11 @@ use rustc_middle::mir::interpret::{ Scalar as InterpScalar, }; use rustc_middle::mir::mono::MonoItem; +use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::{self, Instance, Ty}; use rustc_middle::{bug, span_bug}; use rustc_target::abi::{ - AddressSpace, Align, HasDataLayout, LayoutOf, Primitive, Scalar, Size, WrappingRange, + AddressSpace, Align, HasDataLayout, Primitive, Scalar, Size, WrappingRange, }; use std::ops::Range; use tracing::debug; @@ -110,7 +111,7 @@ pub fn const_alloc_to_llvm(cx: &CodegenCx<'ll, '_>, alloc: &Allocation) -> &'ll Pointer::new(alloc_id, Size::from_bytes(ptr_offset)), &cx.tcx, ), - &Scalar { value: Primitive::Pointer, valid_range: WrappingRange { start: 0, end: !0 } }, + Scalar { value: Primitive::Pointer, valid_range: WrappingRange { start: 0, end: !0 } }, cx.type_i8p_ext(address_space), )); next_offset = offset + pointer_size; @@ -177,7 +178,7 @@ fn check_and_apply_linkage( }; unsafe { // Declare a symbol `foo` with the desired linkage. - let g1 = cx.declare_global(&sym, llty2); + let g1 = cx.declare_global(sym, llty2); llvm::LLVMRustSetLinkage(g1, base::linkage_to_llvm(linkage)); // Declare an internal global `extern_with_linkage_foo` which @@ -187,7 +188,7 @@ fn check_and_apply_linkage( // `extern_with_linkage_foo` will instead be initialized to // zero. let mut real_name = "_rust_extern_with_linkage_".to_string(); - real_name.push_str(&sym); + real_name.push_str(sym); let g2 = cx.define_global(&real_name, llty).unwrap_or_else(|| { cx.sess().span_fatal( cx.tcx.def_span(span_def_id), @@ -201,7 +202,7 @@ fn check_and_apply_linkage( } else { // Generate an external declaration. // FIXME(nagisa): investigate whether it can be changed into define_global - cx.declare_global(&sym, llty) + cx.declare_global(sym, llty) } } @@ -233,7 +234,7 @@ impl CodegenCx<'ll, 'tcx> { _ => self.define_private_global(self.val_ty(cv)), }; llvm::LLVMSetInitializer(gv, cv); - set_global_alignment(&self, gv, align); + set_global_alignment(self, gv, align); llvm::SetUnnamedAddress(gv, llvm::UnnamedAddr::Global); gv } @@ -278,7 +279,7 @@ impl CodegenCx<'ll, 'tcx> { g } else { - check_and_apply_linkage(&self, &fn_attrs, ty, sym, def_id) + check_and_apply_linkage(self, fn_attrs, ty, sym, def_id) }; // Thread-local statics in some other crate need to *always* be linked @@ -368,7 +369,7 @@ impl StaticMethods for CodegenCx<'ll, 'tcx> { unsafe { let attrs = self.tcx.codegen_fn_attrs(def_id); - let (v, alloc) = match codegen_static_initializer(&self, def_id) { + let (v, alloc) = match codegen_static_initializer(self, def_id) { Ok(v) => v, // Error has already been reported Err(_) => return, @@ -416,7 +417,7 @@ impl StaticMethods for CodegenCx<'ll, 'tcx> { self.statics_to_rauw.borrow_mut().push((g, new_g)); new_g }; - set_global_alignment(&self, g, self.align_of(ty)); + set_global_alignment(self, g, self.align_of(ty)); llvm::LLVMSetInitializer(g, v); if self.should_assume_dso_local(g, true) { @@ -429,7 +430,7 @@ impl StaticMethods for CodegenCx<'ll, 'tcx> { llvm::LLVMSetGlobalConstant(g, llvm::True); } - debuginfo::create_global_var_metadata(&self, def_id, g); + debuginfo::create_global_var_metadata(self, def_id, g); if attrs.flags.contains(CodegenFnAttrFlags::THREAD_LOCAL) { llvm::set_thread_local_mode(g, self.tls_model); @@ -517,7 +518,7 @@ impl StaticMethods for CodegenCx<'ll, 'tcx> { ); } } else { - base::set_link_section(g, &attrs); + base::set_link_section(g, attrs); } if attrs.flags.contains(CodegenFnAttrFlags::USED) { diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index 45da18d4a2..257a0ac89d 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -14,15 +14,20 @@ use rustc_codegen_ssa::traits::*; use rustc_data_structures::base_n; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::small_c_str::SmallCStr; -use rustc_middle::bug; use rustc_middle::mir::mono::CodegenUnit; -use rustc_middle::ty::layout::{HasParamEnv, LayoutError, TyAndLayout}; +use rustc_middle::ty::layout::{ + FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasParamEnv, LayoutError, LayoutOfHelpers, + TyAndLayout, +}; use rustc_middle::ty::{self, Instance, Ty, TyCtxt}; +use rustc_middle::{bug, span_bug}; use rustc_session::config::{CFGuard, CrateType, DebugInfo}; use rustc_session::Session; -use rustc_span::source_map::{Span, DUMMY_SP}; +use rustc_span::source_map::Span; use rustc_span::symbol::Symbol; -use rustc_target::abi::{HasDataLayout, LayoutOf, PointeeInfo, Size, TargetDataLayout, VariantIdx}; +use rustc_target::abi::{ + call::FnAbi, HasDataLayout, PointeeInfo, Size, TargetDataLayout, VariantIdx, +}; use rustc_target::spec::{HasTargetSpec, RelocModel, Target, TlsModel}; use smallvec::SmallVec; @@ -190,11 +195,14 @@ pub unsafe fn create_module( let llvm_target = SmallCStr::new(&sess.target.llvm_target); llvm::LLVMRustSetNormalizedTarget(llmod, llvm_target.as_ptr()); - if sess.relocation_model() == RelocModel::Pic { + let reloc_model = sess.relocation_model(); + if matches!(reloc_model, RelocModel::Pic | RelocModel::Pie) { llvm::LLVMRustSetModulePICLevel(llmod); // PIE is potentially more effective than PIC, but can only be used in executables. // If all our outputs are executables, then we can relax PIC to PIE. - if sess.crate_types().iter().all(|ty| *ty == CrateType::Executable) { + if reloc_model == RelocModel::Pie + || sess.crate_types().iter().all(|ty| *ty == CrateType::Executable) + { llvm::LLVMRustSetModulePIELevel(llmod); } } @@ -355,7 +363,7 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { fn create_used_variable_impl(&self, name: &'static CStr, values: &[&'ll Value]) { let section = cstr!("llvm.metadata"); - let array = self.const_array(&self.type_ptr_to(self.type_i8()), values); + let array = self.const_array(self.type_ptr_to(self.type_i8()), values); unsafe { let g = llvm::LLVMAddGlobal(self.llmod, self.val_ty(array), name.as_ptr()); @@ -439,7 +447,7 @@ impl MiscMethods<'tcx> for CodegenCx<'ll, 'tcx> { } fn sess(&self) -> &Session { - &self.tcx.sess + self.tcx.sess } fn check_overflow(&self) -> bool { @@ -835,27 +843,58 @@ impl ty::layout::HasTyCtxt<'tcx> for CodegenCx<'ll, 'tcx> { } } -impl LayoutOf<'tcx> for CodegenCx<'ll, 'tcx> { - type Ty = Ty<'tcx>; - type TyAndLayout = TyAndLayout<'tcx>; - - fn layout_of(&self, ty: Ty<'tcx>) -> Self::TyAndLayout { - self.spanned_layout_of(ty, DUMMY_SP) - } - - fn spanned_layout_of(&self, ty: Ty<'tcx>, span: Span) -> Self::TyAndLayout { - self.tcx.layout_of(ty::ParamEnv::reveal_all().and(ty)).unwrap_or_else(|e| { - if let LayoutError::SizeOverflow(_) = e { - self.sess().span_fatal(span, &e.to_string()) - } else { - bug!("failed to get layout for `{}`: {}", ty, e) - } - }) - } -} - impl<'tcx, 'll> HasParamEnv<'tcx> for CodegenCx<'ll, 'tcx> { fn param_env(&self) -> ty::ParamEnv<'tcx> { ty::ParamEnv::reveal_all() } } + +impl LayoutOfHelpers<'tcx> for CodegenCx<'ll, 'tcx> { + type LayoutOfResult = TyAndLayout<'tcx>; + + #[inline] + fn handle_layout_err(&self, err: LayoutError<'tcx>, span: Span, ty: Ty<'tcx>) -> ! { + if let LayoutError::SizeOverflow(_) = err { + self.sess().span_fatal(span, &err.to_string()) + } else { + span_bug!(span, "failed to get layout for `{}`: {}", ty, err) + } + } +} + +impl FnAbiOfHelpers<'tcx> for CodegenCx<'ll, 'tcx> { + type FnAbiOfResult = &'tcx FnAbi<'tcx, Ty<'tcx>>; + + #[inline] + fn handle_fn_abi_err( + &self, + err: FnAbiError<'tcx>, + span: Span, + fn_abi_request: FnAbiRequest<'tcx>, + ) -> ! { + if let FnAbiError::Layout(LayoutError::SizeOverflow(_)) = err { + self.sess().span_fatal(span, &err.to_string()) + } else { + match fn_abi_request { + FnAbiRequest::OfFnPtr { sig, extra_args } => { + span_bug!( + span, + "`fn_abi_of_fn_ptr({}, {:?})` failed: {}", + sig, + extra_args, + err + ); + } + FnAbiRequest::OfInstance { instance, extra_args } => { + span_bug!( + span, + "`fn_abi_of_instance({}, {:?})` failed: {}", + instance, + extra_args, + err + ); + } + } + } + } +} diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs index d2a2e739ff..6830864ba0 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs @@ -73,7 +73,7 @@ pub fn finalize<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>) { mapgen.write_coverage_mapping(expressions, counter_regions, coverage_mapping_buffer); }); debug_assert!( - coverage_mapping_buffer.len() > 0, + !coverage_mapping_buffer.is_empty(), "Every `FunctionCoverage` should have at least one counter" ); @@ -311,8 +311,7 @@ fn add_unused_functions<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>) { // for each region in it's MIR. // Convert the `HashSet` of `codegenned_def_ids` to a sortable vector, and sort them. - let mut sorted_codegenned_def_ids: Vec = - codegenned_def_ids.iter().map(|def_id| *def_id).collect(); + let mut sorted_codegenned_def_ids: Vec = codegenned_def_ids.iter().copied().collect(); sorted_codegenned_def_ids.sort_unstable(); let mut first_covered_def_id_by_file: FxHashMap = FxHashMap::default(); diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs index 019bf4a09a..ef11e2972e 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs @@ -1,6 +1,6 @@ use crate::llvm; -use crate::abi::{Abi, FnAbi}; +use crate::abi::Abi; use crate::builder::Builder; use crate::common::CodegenCx; @@ -20,7 +20,7 @@ use rustc_middle::mir::coverage::{ CodeRegion, CounterValueReference, ExpressionOperandId, InjectedExpressionId, Op, }; use rustc_middle::ty; -use rustc_middle::ty::layout::FnAbiExt; +use rustc_middle::ty::layout::FnAbiOf; use rustc_middle::ty::subst::InternalSubsts; use rustc_middle::ty::Instance; @@ -199,9 +199,8 @@ fn declare_unused_fn(cx: &CodegenCx<'ll, 'tcx>, def_id: &DefId) -> Instance<'tcx ); let llfn = cx.declare_fn( - &tcx.symbol_name(instance).name, - &FnAbi::of_fn_ptr( - cx, + tcx.symbol_name(instance).name, + cx.fn_abi_of_fn_ptr( ty::Binder::dummy(tcx.mk_fn_sig( iter::once(tcx.mk_unit()), tcx.mk_unit(), @@ -209,7 +208,7 @@ fn declare_unused_fn(cx: &CodegenCx<'ll, 'tcx>, def_id: &DefId) -> Instance<'tcx hir::Unsafety::Unsafe, Abi::Rust, )), - &[], + ty::List::empty(), ), ); diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs b/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs index c2725b83f5..58f8573a2a 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs @@ -3,12 +3,11 @@ use super::utils::DIB; use rustc_codegen_ssa::mir::debuginfo::{DebugScope, FunctionDebugContext}; use rustc_codegen_ssa::traits::*; -use crate::abi::FnAbi; use crate::common::CodegenCx; use crate::llvm; use crate::llvm::debuginfo::{DILocation, DIScope}; use rustc_middle::mir::{Body, SourceScope}; -use rustc_middle::ty::layout::FnAbiExt; +use rustc_middle::ty::layout::FnAbiOf; use rustc_middle::ty::{self, Instance}; use rustc_session::config::DebugInfo; @@ -42,7 +41,7 @@ pub fn compute_mir_scopes( // Instantiate all scopes. for idx in 0..mir.source_scopes.len() { let scope = SourceScope::new(idx); - make_mir_scope(cx, instance, &mir, fn_dbg_scope, &has_variables, debug_context, scope); + make_mir_scope(cx, instance, mir, fn_dbg_scope, &has_variables, debug_context, scope); } } @@ -94,8 +93,8 @@ fn make_mir_scope( ty::ParamEnv::reveal_all(), callee, ); - let callee_fn_abi = FnAbi::of_instance(cx, callee, &[]); - cx.dbg_scope_fn(callee, &callee_fn_abi, None) + let callee_fn_abi = cx.fn_abi_of_instance(callee, ty::List::empty()); + cx.dbg_scope_fn(callee, callee_fn_abi, None) } None => unsafe { llvm::LLVMRustDIBuilderCreateLexicalBlock( diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs b/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs index c33d35cc28..ae1f83d944 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs @@ -59,10 +59,8 @@ pub fn get_or_insert_gdb_debug_scripts_section_global(cx: &CodegenCx<'ll, '_>) - } pub fn needs_gdb_debug_scripts_section(cx: &CodegenCx<'_, '_>) -> bool { - let omit_gdb_pretty_printer_section = cx - .tcx - .sess - .contains_name(&cx.tcx.hir().krate_attrs(), sym::omit_gdb_pretty_printer_section); + let omit_gdb_pretty_printer_section = + cx.tcx.sess.contains_name(cx.tcx.hir().krate_attrs(), sym::omit_gdb_pretty_printer_section); !omit_gdb_pretty_printer_section && cx.sess().opts.debuginfo != DebugInfo::None diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index 346c51c542..cd29f2af01 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -2,7 +2,7 @@ use self::MemberDescriptionFactory::*; use self::RecursiveTypeDescription::*; use super::namespace::mangled_name_of_instance; -use super::type_names::compute_debuginfo_type_name; +use super::type_names::{compute_debuginfo_type_name, compute_debuginfo_vtable_name}; use super::utils::{ create_DIArray, debug_context, get_namespace_for_item, is_node_local_to_unit, DIB, }; @@ -26,18 +26,19 @@ use rustc_fs_util::path_to_c_string; use rustc_hir::def::CtorKind; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_index::vec::{Idx, IndexVec}; -use rustc_middle::ich::NodeIdHashingMode; use rustc_middle::mir::{self, GeneratorLayout}; -use rustc_middle::ty::layout::{self, IntegerExt, PrimitiveExt, TyAndLayout}; +use rustc_middle::ty::layout::{self, IntegerExt, LayoutOf, PrimitiveExt, TyAndLayout}; use rustc_middle::ty::subst::GenericArgKind; -use rustc_middle::ty::Instance; -use rustc_middle::ty::{self, AdtKind, GeneratorSubsts, ParamEnv, Ty, TyCtxt}; +use rustc_middle::ty::{ + self, AdtKind, GeneratorSubsts, Instance, ParamEnv, Ty, TyCtxt, COMMON_VTABLE_ENTRIES, +}; use rustc_middle::{bug, span_bug}; +use rustc_query_system::ich::NodeIdHashingMode; use rustc_session::config::{self, DebugInfo}; -use rustc_span::symbol::{Interner, Symbol}; +use rustc_span::symbol::Symbol; use rustc_span::FileNameDisplayPreference; use rustc_span::{self, SourceFile, SourceFileHash, Span}; -use rustc_target::abi::{Abi, Align, HasDataLayout, Integer, LayoutOf, TagEncoding}; +use rustc_target::abi::{Abi, Align, HasDataLayout, Integer, TagEncoding}; use rustc_target::abi::{Int, Pointer, F32, F64}; use rustc_target::abi::{Primitive, Size, VariantIdx, Variants}; use tracing::debug; @@ -89,8 +90,54 @@ pub const UNKNOWN_COLUMN_NUMBER: c_uint = 0; pub const NO_SCOPE_METADATA: Option<&DIScope> = None; -#[derive(Copy, Debug, Hash, Eq, PartialEq, Clone)] -pub struct UniqueTypeId(Symbol); +mod unique_type_id { + use super::*; + use rustc_arena::DroplessArena; + + #[derive(Copy, Hash, Eq, PartialEq, Clone)] + pub(super) struct UniqueTypeId(u32); + + // The `&'static str`s in this type actually point into the arena. + // + // The `FxHashMap`+`Vec` pair could be replaced by `FxIndexSet`, but #75278 + // found that to regress performance up to 2% in some cases. This might be + // revisited after further improvements to `indexmap`. + #[derive(Default)] + pub(super) struct TypeIdInterner { + arena: DroplessArena, + names: FxHashMap<&'static str, UniqueTypeId>, + strings: Vec<&'static str>, + } + + impl TypeIdInterner { + #[inline] + pub(super) fn intern(&mut self, string: &str) -> UniqueTypeId { + if let Some(&name) = self.names.get(string) { + return name; + } + + let name = UniqueTypeId(self.strings.len() as u32); + + // `from_utf8_unchecked` is safe since we just allocated a `&str` which is known to be + // UTF-8. + let string: &str = + unsafe { std::str::from_utf8_unchecked(self.arena.alloc_slice(string.as_bytes())) }; + // It is safe to extend the arena allocation to `'static` because we only access + // these while the arena is still alive. + let string: &'static str = unsafe { &*(string as *const str) }; + self.strings.push(string); + self.names.insert(string, name); + name + } + + // Get the symbol as a string. `Symbol::as_str()` should be used in + // preference to this function. + pub(super) fn get(&self, symbol: UniqueTypeId) -> &str { + self.strings[symbol.0 as usize] + } + } +} +use unique_type_id::*; /// The `TypeMap` is where the `CrateDebugContext` holds the type metadata nodes /// created so far. The metadata nodes are indexed by `UniqueTypeId`, and, for @@ -99,7 +146,7 @@ pub struct UniqueTypeId(Symbol); #[derive(Default)] pub struct TypeMap<'ll, 'tcx> { /// The `UniqueTypeId`s created so far. - unique_id_interner: Interner, + unique_id_interner: TypeIdInterner, /// A map from `UniqueTypeId` to debuginfo metadata for that type. This is a 1:1 mapping. unique_id_to_metadata: FxHashMap, /// A map from types to debuginfo metadata. This is an N:1 mapping. @@ -166,8 +213,7 @@ impl TypeMap<'ll, 'tcx> { /// Gets the string representation of a `UniqueTypeId`. This method will fail if /// the ID is unknown. fn get_unique_type_id_as_string(&self, unique_type_id: UniqueTypeId) -> &str { - let UniqueTypeId(interner_key) = unique_type_id; - self.unique_id_interner.get(interner_key) + self.unique_id_interner.get(unique_type_id) } /// Gets the `UniqueTypeId` for the given type. If the `UniqueTypeId` for the given @@ -197,9 +243,9 @@ impl TypeMap<'ll, 'tcx> { let unique_type_id = hasher.finish::().to_hex(); let key = self.unique_id_interner.intern(&unique_type_id); - self.type_to_unique_id.insert(type_, UniqueTypeId(key)); + self.type_to_unique_id.insert(type_, key); - UniqueTypeId(key) + key } /// Gets the `UniqueTypeId` for an enum variant. Enum variants are not really @@ -215,7 +261,7 @@ impl TypeMap<'ll, 'tcx> { let enum_variant_type_id = format!("{}::{}", self.get_unique_type_id_as_string(enum_type_id), variant_name); let interner_key = self.unique_id_interner.intern(&enum_variant_type_id); - UniqueTypeId(interner_key) + interner_key } /// Gets the unique type ID string for an enum variant part. @@ -432,7 +478,7 @@ fn subroutine_type_metadata( let signature_metadata: Vec<_> = iter::once( // return type match signature.output().kind() { - ty::Tuple(ref tys) if tys.is_empty() => None, + ty::Tuple(tys) if tys.is_empty() => None, _ => Some(type_metadata(cx, signature.output(), span)), }, ) @@ -602,7 +648,7 @@ pub fn type_metadata(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>, usage_site_span: Sp ty::Never | ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Float(_) => { MetadataCreationResult::new(basic_type_metadata(cx, t), false) } - ty::Tuple(ref elements) if elements.is_empty() => { + ty::Tuple(elements) if elements.is_empty() => { MetadataCreationResult::new(basic_type_metadata(cx, t), false) } ty::Array(typ, _) | ty::Slice(typ) => { @@ -701,7 +747,7 @@ pub fn type_metadata(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>, usage_site_span: Sp .finalize(cx) } }, - ty::Tuple(ref elements) => { + ty::Tuple(elements) => { let tys: Vec<_> = elements.iter().map(|k| k.expect_ty()).collect(); prepare_tuple_metadata(cx, t, &tys, unique_type_id, usage_site_span, NO_SCOPE_METADATA) .finalize(cx) @@ -887,7 +933,7 @@ fn basic_type_metadata(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'ll DIType { let (name, encoding) = match t.kind() { ty::Never => ("!", DW_ATE_unsigned), - ty::Tuple(ref elements) if elements.is_empty() => ("()", DW_ATE_unsigned), + ty::Tuple(elements) if elements.is_empty() => ("()", DW_ATE_unsigned), ty::Bool => ("bool", DW_ATE_boolean), ty::Char => ("char", DW_ATE_unsigned_char), ty::Int(int_ty) if msvc_like_names => (int_ty.msvc_basic_name(), DW_ATE_signed), @@ -1078,7 +1124,7 @@ pub fn compile_unit_metadata( let gcov_cu_info = [ path_to_mdstring(debug_context.llcontext, &output_filenames.with_extension("gcno")), - path_to_mdstring(debug_context.llcontext, &gcda_path), + path_to_mdstring(debug_context.llcontext, gcda_path), cu_desc_metadata, ]; let gcov_metadata = llvm::LLVMMDNodeInContext( @@ -1656,7 +1702,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> { Variants::Multiple { tag_encoding: TagEncoding::Niche { ref niche_variants, niche_start, dataful_variant }, - ref tag, + tag, ref variants, tag_field, } => { @@ -1918,17 +1964,13 @@ impl<'tcx> VariantInfo<'_, 'tcx> { } fn source_info(&self, cx: &CodegenCx<'ll, 'tcx>) -> Option> { - match self { - VariantInfo::Generator { def_id, variant_index, .. } => { - let span = cx.tcx.generator_layout(*def_id).unwrap().variant_source_info - [*variant_index] - .span; - if !span.is_dummy() { - let loc = cx.lookup_debug_loc(span.lo()); - return Some(SourceInfo { file: file_metadata(cx, &loc.file), line: loc.line }); - } + if let VariantInfo::Generator { def_id, variant_index, .. } = self { + let span = + cx.tcx.generator_layout(*def_id).unwrap().variant_source_info[*variant_index].span; + if !span.is_dummy() { + let loc = cx.lookup_debug_loc(span.lo()); + return Some(SourceInfo { file: file_metadata(cx, &loc.file), line: loc.line }); } - _ => {} } None } @@ -1949,11 +1991,11 @@ fn describe_enum_variant( let unique_type_id = debug_context(cx) .type_map .borrow_mut() - .get_unique_type_id_of_enum_variant(cx, layout.ty, &variant_name); + .get_unique_type_id_of_enum_variant(cx, layout.ty, variant_name); create_struct_stub( cx, layout.ty, - &variant_name, + variant_name, unique_type_id, Some(containing_scope), DIFlags::FlagZero, @@ -2082,10 +2124,8 @@ fn prepare_enum_metadata( let layout = cx.layout_of(enum_type); - if let ( - &Abi::Scalar(_), - &Variants::Multiple { tag_encoding: TagEncoding::Direct, ref tag, .. }, - ) = (&layout.abi, &layout.variants) + if let (Abi::Scalar(_), Variants::Multiple { tag_encoding: TagEncoding::Direct, tag, .. }) = + (layout.abi, &layout.variants) { return FinalMetadata(discriminant_type_metadata(tag.value)); } @@ -2093,8 +2133,8 @@ fn prepare_enum_metadata( if use_enum_fallback(cx) { let discriminant_type_metadata = match layout.variants { Variants::Single { .. } => None, - Variants::Multiple { tag_encoding: TagEncoding::Niche { .. }, ref tag, .. } - | Variants::Multiple { tag_encoding: TagEncoding::Direct, ref tag, .. } => { + Variants::Multiple { tag_encoding: TagEncoding::Niche { .. }, tag, .. } + | Variants::Multiple { tag_encoding: TagEncoding::Direct, tag, .. } => { Some(discriminant_type_metadata(tag.value)) } }; @@ -2146,9 +2186,7 @@ fn prepare_enum_metadata( // A single-variant enum has no discriminant. Variants::Single { .. } => None, - Variants::Multiple { - tag_encoding: TagEncoding::Niche { .. }, ref tag, tag_field, .. - } => { + Variants::Multiple { tag_encoding: TagEncoding::Niche { .. }, tag, tag_field, .. } => { // Find the integer type of the correct size. let size = tag.value.size(cx); let align = tag.value.align(cx); @@ -2179,7 +2217,7 @@ fn prepare_enum_metadata( } } - Variants::Multiple { tag_encoding: TagEncoding::Direct, ref tag, tag_field, .. } => { + Variants::Multiple { tag_encoding: TagEncoding::Direct, tag, tag_field, .. } => { let discr_type = tag.value.to_ty(cx.tcx); let (size, align) = cx.size_and_align_of(discr_type); @@ -2344,7 +2382,7 @@ fn set_members_of_composite_type( { let mut composite_types_completed = debug_context(cx).composite_types_completed.borrow_mut(); - if !composite_types_completed.insert(&composite_type_metadata) { + if !composite_types_completed.insert(composite_type_metadata) { bug!( "debuginfo::set_members_of_composite_type() - \ Already completed forward declaration re-encountered." @@ -2554,11 +2592,45 @@ pub fn create_global_var_metadata(cx: &CodegenCx<'ll, '_>, def_id: DefId, global } } +/// Generates LLVM debuginfo for a vtable. +fn vtable_type_metadata( + cx: &CodegenCx<'ll, 'tcx>, + ty: Ty<'tcx>, + poly_trait_ref: Option>, +) -> &'ll DIType { + let tcx = cx.tcx; + + let vtable_entries = if let Some(poly_trait_ref) = poly_trait_ref { + let trait_ref = poly_trait_ref.with_self_ty(tcx, ty); + let trait_ref = tcx.erase_regions(trait_ref); + + tcx.vtable_entries(trait_ref) + } else { + COMMON_VTABLE_ENTRIES + }; + + // FIXME: We describe the vtable as an array of *const () pointers. The length of the array is + // correct - but we could create a more accurate description, e.g. by describing it + // as a struct where each field has a name that corresponds to the name of the method + // it points to. + // However, this is not entirely straightforward because there might be multiple + // methods with the same name if the vtable is for multiple traits. So for now we keep + // things simple instead of adding some ad-hoc disambiguation scheme. + let vtable_type = tcx.mk_array(tcx.mk_imm_ptr(tcx.types.unit), vtable_entries.len() as u64); + + type_metadata(cx, vtable_type, rustc_span::DUMMY_SP) +} + /// Creates debug information for the given vtable, which is for the /// given type. /// /// Adds the created metadata nodes directly to the crate's IR. -pub fn create_vtable_metadata(cx: &CodegenCx<'ll, 'tcx>, ty: Ty<'tcx>, vtable: &'ll Value) { +pub fn create_vtable_metadata( + cx: &CodegenCx<'ll, 'tcx>, + ty: Ty<'tcx>, + poly_trait_ref: Option>, + vtable: &'ll Value, +) { if cx.dbg_cx.is_none() { return; } @@ -2568,42 +2640,16 @@ pub fn create_vtable_metadata(cx: &CodegenCx<'ll, 'tcx>, ty: Ty<'tcx>, vtable: & return; } - let type_metadata = type_metadata(cx, ty, rustc_span::DUMMY_SP); + let vtable_name = compute_debuginfo_vtable_name(cx.tcx, ty, poly_trait_ref); + let vtable_type = vtable_type_metadata(cx, ty, poly_trait_ref); unsafe { - // `LLVMRustDIBuilderCreateStructType()` wants an empty array. A null - // pointer will lead to hard to trace and debug LLVM assertions - // later on in `llvm/lib/IR/Value.cpp`. - let empty_array = create_DIArray(DIB(cx), &[]); - let name = "vtable"; - - // Create a new one each time. We don't want metadata caching - // here, because each vtable will refer to a unique containing - // type. - let vtable_type = llvm::LLVMRustDIBuilderCreateStructType( - DIB(cx), - NO_SCOPE_METADATA, - name.as_ptr().cast(), - name.len(), - unknown_file_metadata(cx), - UNKNOWN_LINE_NUMBER, - Size::ZERO.bits(), - cx.tcx.data_layout.pointer_align.abi.bits() as u32, - DIFlags::FlagArtificial, - None, - empty_array, - 0, - Some(type_metadata), - name.as_ptr().cast(), - name.len(), - ); - let linkage_name = ""; llvm::LLVMRustDIBuilderCreateStaticVariable( DIB(cx), NO_SCOPE_METADATA, - name.as_ptr().cast(), - name.len(), + vtable_name.as_ptr().cast(), + vtable_name.len(), linkage_name.as_ptr().cast(), linkage_name.len(), unknown_file_metadata(cx), diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs index 914376d58d..1f1bd73c7d 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs @@ -25,13 +25,14 @@ use rustc_data_structures::sync::Lrc; use rustc_hir::def_id::{DefId, DefIdMap}; use rustc_index::vec::IndexVec; use rustc_middle::mir; -use rustc_middle::ty::layout::HasTyCtxt; +use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf}; use rustc_middle::ty::subst::{GenericArgKind, SubstsRef}; use rustc_middle::ty::{self, Instance, ParamEnv, Ty, TypeFoldable}; use rustc_session::config::{self, DebugInfo}; +use rustc_session::Session; use rustc_span::symbol::Symbol; use rustc_span::{self, BytePos, Pos, SourceFile, SourceFileAndLine, Span}; -use rustc_target::abi::{LayoutOf, Primitive, Size}; +use rustc_target::abi::{Primitive, Size}; use libc::c_uint; use smallvec::SmallVec; @@ -95,45 +96,52 @@ impl<'a, 'tcx> CrateDebugContext<'a, 'tcx> { composite_types_completed: Default::default(), } } + + pub fn finalize(&self, sess: &Session) { + unsafe { + llvm::LLVMRustDIBuilderFinalize(self.builder); + + // Debuginfo generation in LLVM by default uses a higher + // version of dwarf than macOS currently understands. We can + // instruct LLVM to emit an older version of dwarf, however, + // for macOS to understand. For more info see #11352 + // This can be overridden using --llvm-opts -dwarf-version,N. + // Android has the same issue (#22398) + if let Some(version) = sess.target.dwarf_version { + llvm::LLVMRustAddModuleFlag(self.llmod, "Dwarf Version\0".as_ptr().cast(), version) + } + + // Indicate that we want CodeView debug information on MSVC + if sess.target.is_like_msvc { + llvm::LLVMRustAddModuleFlag(self.llmod, "CodeView\0".as_ptr().cast(), 1) + } + + // Prevent bitcode readers from deleting the debug info. + let ptr = "Debug Info Version\0".as_ptr(); + llvm::LLVMRustAddModuleFlag( + self.llmod, + ptr.cast(), + llvm::LLVMRustDebugMetadataVersion(), + ); + } + } } /// Creates any deferred debug metadata nodes pub fn finalize(cx: &CodegenCx<'_, '_>) { - if cx.dbg_cx.is_none() { - return; - } + if let Some(dbg_cx) = &cx.dbg_cx { + debug!("finalize"); - debug!("finalize"); - - if gdb::needs_gdb_debug_scripts_section(cx) { - // Add a .debug_gdb_scripts section to this compile-unit. This will - // cause GDB to try and load the gdb_load_rust_pretty_printers.py file, - // which activates the Rust pretty printers for binary this section is - // contained in. - gdb::get_or_insert_gdb_debug_scripts_section_global(cx); - } - - unsafe { - llvm::LLVMRustDIBuilderFinalize(DIB(cx)); - // Debuginfo generation in LLVM by default uses a higher - // version of dwarf than macOS currently understands. We can - // instruct LLVM to emit an older version of dwarf, however, - // for macOS to understand. For more info see #11352 - // This can be overridden using --llvm-opts -dwarf-version,N. - // Android has the same issue (#22398) - if let Some(version) = cx.sess().target.dwarf_version { - llvm::LLVMRustAddModuleFlag(cx.llmod, "Dwarf Version\0".as_ptr().cast(), version) + if gdb::needs_gdb_debug_scripts_section(cx) { + // Add a .debug_gdb_scripts section to this compile-unit. This will + // cause GDB to try and load the gdb_load_rust_pretty_printers.py file, + // which activates the Rust pretty printers for binary this section is + // contained in. + gdb::get_or_insert_gdb_debug_scripts_section_global(cx); } - // Indicate that we want CodeView debug information on MSVC - if cx.sess().target.is_like_msvc { - llvm::LLVMRustAddModuleFlag(cx.llmod, "CodeView\0".as_ptr().cast(), 1) - } - - // Prevent bitcode readers from deleting the debug info. - let ptr = "Debug Info Version\0".as_ptr(); - llvm::LLVMRustAddModuleFlag(cx.llmod, ptr.cast(), llvm::LLVMRustDebugMetadataVersion()); - }; + dbg_cx.finalize(cx.sess()); + } } impl DebugInfoBuilderMethods for Builder<'a, 'll, 'tcx> { @@ -320,7 +328,7 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { // name if necessary. let generics = self.tcx().generics_of(enclosing_fn_def_id); let substs = instance.substs.truncate_to(self.tcx(), generics); - let template_parameters = get_template_parameters(self, &generics, substs, &mut name); + let template_parameters = get_template_parameters(self, generics, substs, &mut name); let linkage_name = &mangled_name_of_instance(self, instance).name; // Omit the linkage_name if it is the same as subprogram name. @@ -542,8 +550,13 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { unsafe { llvm::LLVMRustDIBuilderCreateDebugLocation(line, col, scope, inlined_at) } } - fn create_vtable_metadata(&self, ty: Ty<'tcx>, vtable: Self::Value) { - metadata::create_vtable_metadata(self, ty, vtable) + fn create_vtable_metadata( + &self, + ty: Ty<'tcx>, + trait_ref: Option>, + vtable: Self::Value, + ) { + metadata::create_vtable_metadata(self, ty, trait_ref, vtable) } fn extend_scope_to_file( @@ -551,7 +564,7 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { scope_metadata: &'ll DIScope, file: &rustc_span::SourceFile, ) -> &'ll DILexicalBlock { - metadata::extend_scope_to_file(&self, scope_metadata, file) + metadata::extend_scope_to_file(self, scope_metadata, file) } fn debuginfo_finalize(&self) { diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index e30c49295b..c43141c769 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -15,12 +15,12 @@ use rustc_codegen_ssa::mir::operand::OperandRef; use rustc_codegen_ssa::mir::place::PlaceRef; use rustc_codegen_ssa::traits::*; use rustc_hir as hir; -use rustc_middle::ty::layout::{FnAbiExt, HasTyCtxt}; +use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, LayoutOf}; use rustc_middle::ty::{self, Ty}; use rustc_middle::{bug, span_bug}; use rustc_span::{sym, symbol::kw, Span, Symbol}; -use rustc_target::abi::{self, HasDataLayout, LayoutOf, Primitive}; -use rustc_target::spec::PanicStrategy; +use rustc_target::abi::{self, HasDataLayout, Primitive}; +use rustc_target::spec::{HasTargetSpec, PanicStrategy}; use std::cmp::Ordering; use std::iter; @@ -71,7 +71,7 @@ fn get_simple_intrinsic(cx: &CodegenCx<'ll, '_>, name: Symbol) -> Option<(&'ll T sym::roundf64 => "llvm.round.f64", _ => return None, }; - Some(cx.get_intrinsic(&llvm_name)) + Some(cx.get_intrinsic(llvm_name)) } impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> { @@ -96,7 +96,6 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> { let arg_tys = sig.inputs(); let ret_ty = sig.output(); let name = tcx.item_name(def_id); - let name_str = &*name.as_str(); let llret_ty = self.layout_of(ret_ty).llvm_type(self); let result = PlaceRef::new_sized(llresult, fn_abi.ret.layout); @@ -133,7 +132,7 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> { } sym::va_arg => { match fn_abi.ret.layout.abi { - abi::Abi::Scalar(ref scalar) => { + abi::Abi::Scalar(scalar) => { match scalar.value { Primitive::Int(..) => { if self.cx().size_of(ret_ty).bytes() < 4 { @@ -230,9 +229,14 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> { &[args[0].immediate(), y], ) } - sym::ctlz_nonzero | sym::cttz_nonzero => { + sym::ctlz_nonzero => { let y = self.const_bool(true); - let llvm_name = &format!("llvm.{}.i{}", &name_str[..4], width); + let llvm_name = &format!("llvm.ctlz.i{}", width); + self.call_intrinsic(llvm_name, &[args[0].immediate(), y]) + } + sym::cttz_nonzero => { + let y = self.const_bool(true); + let llvm_name = &format!("llvm.cttz.i{}", width); self.call_intrinsic(llvm_name, &[args[0].immediate(), y]) } sym::ctpop => self.call_intrinsic( @@ -353,7 +357,7 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> { return; } - _ if name_str.starts_with("simd_") => { + _ if name.as_str().starts_with("simd_") => { match generic_simd_intrinsic(self, name, callee_ty, args, ret_ty, llret_ty, span) { Ok(llval) => llval, Err(()) => return, @@ -737,9 +741,9 @@ fn gen_fn<'ll, 'tcx>( rust_fn_sig: ty::PolyFnSig<'tcx>, codegen: &mut dyn FnMut(Builder<'_, 'll, 'tcx>), ) -> (&'ll Type, &'ll Value) { - let fn_abi = FnAbi::of_fn_ptr(cx, rust_fn_sig, &[]); + let fn_abi = cx.fn_abi_of_fn_ptr(rust_fn_sig, ty::List::empty()); let llty = fn_abi.llvm_type(cx); - let llfn = cx.declare_fn(name, &fn_abi); + let llfn = cx.declare_fn(name, fn_abi); cx.set_frame_pointer_type(llfn); cx.apply_target_cpu_attr(llfn); // FIXME(eddyb) find a nicer way to do this. @@ -843,7 +847,6 @@ fn generic_simd_intrinsic( let sig = tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), callee_ty.fn_sig(tcx)); let arg_tys = sig.inputs(); - let name_str = &*name.as_str(); if name == sym::simd_select_bitmask { let in_ty = arg_tys[0]; @@ -917,13 +920,30 @@ fn generic_simd_intrinsic( )); } - if let Some(stripped) = name_str.strip_prefix("simd_shuffle") { - let n: u64 = stripped.parse().unwrap_or_else(|_| { - span_bug!(span, "bad `simd_shuffle` instruction only caught in codegen?") - }); + if let Some(stripped) = name.as_str().strip_prefix("simd_shuffle") { + // If this intrinsic is the older "simd_shuffleN" form, simply parse the integer. + // If there is no suffix, use the index array length. + let n: u64 = if stripped.is_empty() { + // Make sure this is actually an array, since typeck only checks the length-suffixed + // version of this intrinsic. + match args[2].layout.ty.kind() { + ty::Array(ty, len) if matches!(ty.kind(), ty::Uint(ty::UintTy::U32)) => { + len.try_eval_usize(bx.cx.tcx, ty::ParamEnv::reveal_all()).unwrap_or_else(|| { + span_bug!(span, "could not evaluate shuffle index array length") + }) + } + _ => return_error!( + "simd_shuffle index must be an array of `u32`, got `{}`", + args[2].layout.ty + ), + } + } else { + stripped.parse().unwrap_or_else(|_| { + span_bug!(span, "bad `simd_shuffle` instruction only caught in codegen?") + }) + }; require_simd!(ret_ty, "return"); - let (out_len, out_ty) = ret_ty.simd_size_and_type(bx.tcx()); require!( out_len == n, @@ -1139,7 +1159,7 @@ fn generic_simd_intrinsic( _ => return_error!("unrecognized intrinsic `{}`", name), }; let llvm_name = &format!("llvm.{0}.v{1}{2}", intr_name, in_len, elem_ty_str); - let f = bx.declare_cfn(&llvm_name, llvm::UnnamedAddr::No, fn_ty); + let f = bx.declare_cfn(llvm_name, llvm::UnnamedAddr::No, fn_ty); let c = bx.call(fn_ty, f, &args.iter().map(|arg| arg.immediate()).collect::>(), None); Ok(c) @@ -1170,11 +1190,28 @@ fn generic_simd_intrinsic( // FIXME: use: // https://github.com/llvm-mirror/llvm/blob/master/include/llvm/IR/Function.h#L182 // https://github.com/llvm-mirror/llvm/blob/master/include/llvm/IR/Intrinsics.h#L81 - fn llvm_vector_str(elem_ty: Ty<'_>, vec_len: u64, no_pointers: usize) -> String { + fn llvm_vector_str( + elem_ty: Ty<'_>, + vec_len: u64, + no_pointers: usize, + bx: &Builder<'a, 'll, 'tcx>, + ) -> String { let p0s: String = "p0".repeat(no_pointers); match *elem_ty.kind() { - ty::Int(v) => format!("v{}{}i{}", vec_len, p0s, v.bit_width().unwrap()), - ty::Uint(v) => format!("v{}{}i{}", vec_len, p0s, v.bit_width().unwrap()), + ty::Int(v) => format!( + "v{}{}i{}", + vec_len, + p0s, + // Normalize to prevent crash if v: IntTy::Isize + v.normalize(bx.target_spec().pointer_width).bit_width().unwrap() + ), + ty::Uint(v) => format!( + "v{}{}i{}", + vec_len, + p0s, + // Normalize to prevent crash if v: UIntTy::Usize + v.normalize(bx.target_spec().pointer_width).bit_width().unwrap() + ), ty::Float(v) => format!("v{}{}f{}", vec_len, p0s, v.bit_width()), _ => unreachable!(), } @@ -1310,11 +1347,11 @@ fn generic_simd_intrinsic( // Type of the vector of pointers: let llvm_pointer_vec_ty = llvm_vector_ty(bx, underlying_ty, in_len, pointer_count); - let llvm_pointer_vec_str = llvm_vector_str(underlying_ty, in_len, pointer_count); + let llvm_pointer_vec_str = llvm_vector_str(underlying_ty, in_len, pointer_count, bx); // Type of the vector of elements: let llvm_elem_vec_ty = llvm_vector_ty(bx, underlying_ty, in_len, pointer_count - 1); - let llvm_elem_vec_str = llvm_vector_str(underlying_ty, in_len, pointer_count - 1); + let llvm_elem_vec_str = llvm_vector_str(underlying_ty, in_len, pointer_count - 1, bx); let llvm_intrinsic = format!("llvm.masked.gather.{}.{}", llvm_elem_vec_str, llvm_pointer_vec_str); @@ -1438,11 +1475,11 @@ fn generic_simd_intrinsic( // Type of the vector of pointers: let llvm_pointer_vec_ty = llvm_vector_ty(bx, underlying_ty, in_len, pointer_count); - let llvm_pointer_vec_str = llvm_vector_str(underlying_ty, in_len, pointer_count); + let llvm_pointer_vec_str = llvm_vector_str(underlying_ty, in_len, pointer_count, bx); // Type of the vector of elements: let llvm_elem_vec_ty = llvm_vector_ty(bx, underlying_ty, in_len, pointer_count - 1); - let llvm_elem_vec_str = llvm_vector_str(underlying_ty, in_len, pointer_count - 1); + let llvm_elem_vec_str = llvm_vector_str(underlying_ty, in_len, pointer_count - 1, bx); let llvm_intrinsic = format!("llvm.masked.scatter.{}.{}", llvm_elem_vec_str, llvm_pointer_vec_str); @@ -1773,7 +1810,7 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#, let vec_ty = bx.cx.type_vector(elem_ty, in_len as u64); let fn_ty = bx.type_func(&[vec_ty, vec_ty], vec_ty); - let f = bx.declare_cfn(&llvm_intrinsic, llvm::UnnamedAddr::No, fn_ty); + let f = bx.declare_cfn(llvm_intrinsic, llvm::UnnamedAddr::No, fn_ty); let v = bx.call(fn_ty, f, &[lhs, rhs], None); return Ok(v); } diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs index 1e6e5252b2..8f4d79e714 100644 --- a/compiler/rustc_codegen_llvm/src/lib.rs +++ b/compiler/rustc_codegen_llvm/src/lib.rs @@ -27,8 +27,8 @@ use rustc_codegen_ssa::ModuleCodegen; use rustc_codegen_ssa::{CodegenResults, CompiledModule}; use rustc_data_structures::fx::FxHashMap; use rustc_errors::{ErrorReported, FatalError, Handler}; +use rustc_metadata::EncodedMetadata; use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; -use rustc_middle::middle::cstore::EncodedMetadata; use rustc_middle::ty::TyCtxt; use rustc_session::config::{OptLevel, OutputFilenames, PrintRequest}; use rustc_session::Session; @@ -92,11 +92,12 @@ impl ExtraBackendMethods for LlvmCodegenBackend { fn codegen_allocator<'tcx>( &self, tcx: TyCtxt<'tcx>, - mods: &mut ModuleLlvm, + module_llvm: &mut ModuleLlvm, + module_name: &str, kind: AllocatorKind, has_alloc_error_handler: bool, ) { - unsafe { allocator::codegen(tcx, mods, kind, has_alloc_error_handler) } + unsafe { allocator::codegen(tcx, module_llvm, module_name, kind, has_alloc_error_handler) } } fn compile_codegen_unit( &self, @@ -210,9 +211,16 @@ impl CodegenBackend for LlvmCodegenBackend { match req { PrintRequest::RelocationModels => { println!("Available relocation models:"); - for name in - &["static", "pic", "dynamic-no-pic", "ropi", "rwpi", "ropi-rwpi", "default"] - { + for name in &[ + "static", + "pic", + "pie", + "dynamic-no-pic", + "ropi", + "rwpi", + "ropi-rwpi", + "default", + ] { println!(" {}", name); } println!(); @@ -331,7 +339,7 @@ impl ModuleLlvm { unsafe { let llcx = llvm::LLVMRustContextCreate(cgcx.fewer_names); let llmod_raw = back::lto::parse_module(llcx, name, buffer, handler)?; - let tm_factory_config = TargetMachineFactoryConfig::new(&cgcx, name.to_str().unwrap()); + let tm_factory_config = TargetMachineFactoryConfig::new(cgcx, name.to_str().unwrap()); let tm = match (cgcx.tm_factory)(tm_factory_config) { Ok(m) => m, Err(e) => { diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 3f2ed02d90..4c9ae4faf7 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -34,11 +34,18 @@ pub enum LLVMRustResult { #[repr(C)] pub struct LLVMRustCOFFShortExport { pub name: *const c_char, + pub ordinal_present: bool, + // value of `ordinal` only important when `ordinal_present` is true + pub ordinal: u16, } impl LLVMRustCOFFShortExport { - pub fn from_name(name: *const c_char) -> LLVMRustCOFFShortExport { - LLVMRustCOFFShortExport { name } + pub fn new(name: *const c_char, ordinal: Option) -> LLVMRustCOFFShortExport { + LLVMRustCOFFShortExport { + name, + ordinal_present: ordinal.is_some(), + ordinal: ordinal.unwrap_or(0), + } } } @@ -216,6 +223,33 @@ pub enum RealPredicate { RealPredicateTrue = 15, } +impl RealPredicate { + pub fn from_generic(realp: rustc_codegen_ssa::common::RealPredicate) -> Self { + match realp { + rustc_codegen_ssa::common::RealPredicate::RealPredicateFalse => { + RealPredicate::RealPredicateFalse + } + rustc_codegen_ssa::common::RealPredicate::RealOEQ => RealPredicate::RealOEQ, + rustc_codegen_ssa::common::RealPredicate::RealOGT => RealPredicate::RealOGT, + rustc_codegen_ssa::common::RealPredicate::RealOGE => RealPredicate::RealOGE, + rustc_codegen_ssa::common::RealPredicate::RealOLT => RealPredicate::RealOLT, + rustc_codegen_ssa::common::RealPredicate::RealOLE => RealPredicate::RealOLE, + rustc_codegen_ssa::common::RealPredicate::RealONE => RealPredicate::RealONE, + rustc_codegen_ssa::common::RealPredicate::RealORD => RealPredicate::RealORD, + rustc_codegen_ssa::common::RealPredicate::RealUNO => RealPredicate::RealUNO, + rustc_codegen_ssa::common::RealPredicate::RealUEQ => RealPredicate::RealUEQ, + rustc_codegen_ssa::common::RealPredicate::RealUGT => RealPredicate::RealUGT, + rustc_codegen_ssa::common::RealPredicate::RealUGE => RealPredicate::RealUGE, + rustc_codegen_ssa::common::RealPredicate::RealULT => RealPredicate::RealULT, + rustc_codegen_ssa::common::RealPredicate::RealULE => RealPredicate::RealULE, + rustc_codegen_ssa::common::RealPredicate::RealUNE => RealPredicate::RealUNE, + rustc_codegen_ssa::common::RealPredicate::RealPredicateTrue => { + RealPredicate::RealPredicateTrue + } + } + } +} + /// LLVMTypeKind #[derive(Copy, Clone, PartialEq, Debug)] #[repr(C)] @@ -789,7 +823,7 @@ pub mod coverageinfo { start_line, start_col, end_line, - end_col: ((1 as u32) << 31) | end_col, + end_col: (1_u32 << 31) | end_col, kind: RegionKind::GapRegion, } } @@ -2176,6 +2210,7 @@ extern "C" { PrepareForThinLTO: bool, PGOGenPath: *const c_char, PGOUsePath: *const c_char, + PGOSampleUsePath: *const c_char, ); pub fn LLVMRustAddLibraryInfo( PM: &PassManager<'a>, @@ -2210,6 +2245,8 @@ extern "C" { PGOUsePath: *const c_char, InstrumentCoverage: bool, InstrumentGCOV: bool, + PGOSampleUsePath: *const c_char, + DebugInfoForProfiling: bool, llvm_selfprofiler: *mut c_void, begin_callback: SelfProfileBeforePassCallback, end_callback: SelfProfileAfterPassCallback, @@ -2377,12 +2414,8 @@ extern "C" { len: usize, out_len: &mut usize, ) -> *const u8; - pub fn LLVMRustThinLTOGetDICompileUnit( - M: &Module, - CU1: &mut *mut c_void, - CU2: &mut *mut c_void, - ); - pub fn LLVMRustThinLTOPatchDICompileUnit(M: &Module, CU: *mut c_void); + pub fn LLVMRustLTOGetDICompileUnit(M: &Module, CU1: &mut *mut c_void, CU2: &mut *mut c_void); + pub fn LLVMRustLTOPatchDICompileUnit(M: &Module, CU: *mut c_void); pub fn LLVMRustLinkerNew(M: &'a Module) -> &'a mut Linker<'a>; pub fn LLVMRustLinkerAdd( diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index 3b64ec1a99..c2136f1612 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -166,25 +166,32 @@ pub fn time_trace_profiler_finish(file_name: &str) { // Though note that Rust can also be build with an external precompiled version of LLVM // which might lead to failures if the oldest tested / supported LLVM version // doesn't yet support the relevant intrinsics -pub fn to_llvm_feature<'a>(sess: &Session, s: &'a str) -> &'a str { +pub fn to_llvm_feature<'a>(sess: &Session, s: &'a str) -> Vec<&'a str> { let arch = if sess.target.arch == "x86_64" { "x86" } else { &*sess.target.arch }; match (arch, s) { - ("x86", "pclmulqdq") => "pclmul", - ("x86", "rdrand") => "rdrnd", - ("x86", "bmi1") => "bmi", - ("x86", "cmpxchg16b") => "cx16", - ("x86", "avx512vaes") => "vaes", - ("x86", "avx512gfni") => "gfni", - ("x86", "avx512vpclmulqdq") => "vpclmulqdq", - ("aarch64", "fp") => "fp-armv8", - ("aarch64", "fp16") => "fullfp16", - ("aarch64", "fhm") => "fp16fml", - ("aarch64", "rcpc2") => "rcpc-immo", - ("aarch64", "dpb") => "ccpp", - ("aarch64", "dpb2") => "ccdp", - ("aarch64", "frintts") => "fptoint", - ("aarch64", "fcma") => "complxnum", - (_, s) => s, + ("x86", "sse4.2") => { + if get_version() >= (14, 0, 0) { + vec!["sse4.2", "crc32"] + } else { + vec!["sse4.2"] + } + } + ("x86", "pclmulqdq") => vec!["pclmul"], + ("x86", "rdrand") => vec!["rdrnd"], + ("x86", "bmi1") => vec!["bmi"], + ("x86", "cmpxchg16b") => vec!["cx16"], + ("x86", "avx512vaes") => vec!["vaes"], + ("x86", "avx512gfni") => vec!["gfni"], + ("x86", "avx512vpclmulqdq") => vec!["vpclmulqdq"], + ("aarch64", "fp") => vec!["fp-armv8"], + ("aarch64", "fp16") => vec!["fullfp16"], + ("aarch64", "fhm") => vec!["fp16fml"], + ("aarch64", "rcpc2") => vec!["rcpc-immo"], + ("aarch64", "dpb") => vec!["ccpp"], + ("aarch64", "dpb2") => vec!["ccdp"], + ("aarch64", "frintts") => vec!["fptoint"], + ("aarch64", "fcma") => vec!["complxnum"], + (_, s) => vec![s], } } @@ -198,9 +205,13 @@ pub fn target_features(sess: &Session) -> Vec { }, ) .filter(|feature| { - let llvm_feature = to_llvm_feature(sess, feature); - let cstr = CString::new(llvm_feature).unwrap(); - unsafe { llvm::LLVMRustHasFeature(target_machine, cstr.as_ptr()) } + for llvm_feature in to_llvm_feature(sess, feature) { + let cstr = CString::new(llvm_feature).unwrap(); + if unsafe { llvm::LLVMRustHasFeature(target_machine, cstr.as_ptr()) } { + return true; + } + } + false }) .map(|feature| Symbol::intern(feature)) .collect() @@ -253,12 +264,19 @@ fn print_target_features(sess: &Session, tm: &llvm::TargetMachine) { let mut rustc_target_features = supported_target_features(sess) .iter() .filter_map(|(feature, _gate)| { - let llvm_feature = to_llvm_feature(sess, *feature); - // LLVM asserts that these are sorted. LLVM and Rust both use byte comparison for these strings. - target_features.binary_search_by_key(&llvm_feature, |(f, _d)| *f).ok().map(|index| { - let (_f, desc) = target_features.remove(index); - (*feature, desc) - }) + for llvm_feature in to_llvm_feature(sess, *feature) { + // LLVM asserts that these are sorted. LLVM and Rust both use byte comparison for these strings. + match target_features.binary_search_by_key(&llvm_feature, |(f, _d)| (*f)).ok().map( + |index| { + let (_f, desc) = target_features.remove(index); + (*feature, desc) + }, + ) { + Some(v) => return Some(v), + None => {} + } + } + None }) .collect::>(); rustc_target_features.extend_from_slice(&[( @@ -280,7 +298,7 @@ fn print_target_features(sess: &Session, tm: &llvm::TargetMachine) { for (feature, desc) in &target_features { println!(" {1:0$} - {2}.", max_feature_len, feature, desc); } - if target_features.len() == 0 { + if target_features.is_empty() { println!(" Target features listing is not supported by this LLVM version."); } println!("\nUse +feature to enable a feature, or -feature to disable it."); @@ -373,30 +391,38 @@ pub fn llvm_global_features(sess: &Session) -> Vec { let filter = |s: &str| { if s.is_empty() { - return None; + return vec![]; } let feature = if s.starts_with('+') || s.starts_with('-') { &s[1..] } else { - return Some(s.to_string()); + return vec![s.to_string()]; }; // Rustc-specific feature requests like `+crt-static` or `-crt-static` // are not passed down to LLVM. if RUSTC_SPECIFIC_FEATURES.contains(&feature) { - return None; + return vec![]; } // ... otherwise though we run through `to_llvm_feature` feature when // passing requests down to LLVM. This means that all in-language // features also work on the command line instead of having two // different names when the LLVM name and the Rust name differ. - Some(format!("{}{}", &s[..1], to_llvm_feature(sess, feature))) + to_llvm_feature(sess, feature).iter().map(|f| format!("{}{}", &s[..1], f)).collect() }; // Features implied by an implicit or explicit `--target`. - features.extend(sess.target.features.split(',').filter_map(&filter)); + features.extend(sess.target.features.split(',').flat_map(&filter)); // -Ctarget-features - features.extend(sess.opts.cg.target_feature.split(',').filter_map(&filter)); + features.extend(sess.opts.cg.target_feature.split(',').flat_map(&filter)); + + // FIXME: Move outline-atomics to target definition when earliest supported LLVM is 12. + if get_version() >= (12, 0, 0) + && sess.target.llvm_target.contains("aarch64-unknown-linux") + && sess.target.llvm_target != "aarch64-unknown-linux-musl" + { + features.push("+outline-atomics".to_string()); + } features } diff --git a/compiler/rustc_codegen_llvm/src/mono_item.rs b/compiler/rustc_codegen_llvm/src/mono_item.rs index 8a8ece640f..88498cf47d 100644 --- a/compiler/rustc_codegen_llvm/src/mono_item.rs +++ b/compiler/rustc_codegen_llvm/src/mono_item.rs @@ -1,4 +1,3 @@ -use crate::abi::FnAbi; use crate::attributes; use crate::base; use crate::context::CodegenCx; @@ -8,10 +7,9 @@ use rustc_codegen_ssa::traits::*; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; pub use rustc_middle::mir::mono::MonoItem; use rustc_middle::mir::mono::{Linkage, Visibility}; -use rustc_middle::ty::layout::FnAbiExt; +use rustc_middle::ty::layout::{FnAbiOf, LayoutOf}; use rustc_middle::ty::{self, Instance, TypeFoldable}; use rustc_session::config::CrateType; -use rustc_target::abi::LayoutOf; use rustc_target::spec::RelocModel; use tracing::debug; @@ -54,11 +52,11 @@ impl PreDefineMethods<'tcx> for CodegenCx<'ll, 'tcx> { ) { assert!(!instance.substs.needs_infer()); - let fn_abi = FnAbi::of_instance(self, instance, &[]); - let lldecl = self.declare_fn(symbol_name, &fn_abi); + let fn_abi = self.fn_abi_of_instance(instance, ty::List::empty()); + let lldecl = self.declare_fn(symbol_name, fn_abi); unsafe { llvm::LLVMRustSetLinkage(lldecl, base::linkage_to_llvm(linkage)) }; let attrs = self.tcx.codegen_fn_attrs(instance.def_id()); - base::set_link_section(lldecl, &attrs); + base::set_link_section(lldecl, attrs); if linkage == Linkage::LinkOnceODR || linkage == Linkage::WeakODR { llvm::SetUniqueComdat(self.llmod, lldecl); } @@ -145,6 +143,8 @@ impl CodegenCx<'ll, 'tcx> { return true; } - return false; + // With pie relocation model calls of functions defined in the translation + // unit can use copy relocations. + self.tcx.sess.relocation_model() == RelocModel::Pie && !is_declaration } } diff --git a/compiler/rustc_codegen_llvm/src/type_.rs b/compiler/rustc_codegen_llvm/src/type_.rs index c7f4287e28..2ae0a08f19 100644 --- a/compiler/rustc_codegen_llvm/src/type_.rs +++ b/compiler/rustc_codegen_llvm/src/type_.rs @@ -248,7 +248,7 @@ impl Type { } fn ptr_to(&self, address_space: AddressSpace) -> &Type { - unsafe { llvm::LLVMPointerType(&self, address_space.0) } + unsafe { llvm::LLVMPointerType(self, address_space.0) } } } diff --git a/compiler/rustc_codegen_llvm/src/type_of.rs b/compiler/rustc_codegen_llvm/src/type_of.rs index 9818905464..f8c919ec2a 100644 --- a/compiler/rustc_codegen_llvm/src/type_of.rs +++ b/compiler/rustc_codegen_llvm/src/type_of.rs @@ -1,15 +1,14 @@ -use crate::abi::FnAbi; use crate::common::*; use crate::context::TypeLowering; use crate::type_::Type; use rustc_codegen_ssa::traits::*; use rustc_middle::bug; -use rustc_middle::ty::layout::{FnAbiExt, TyAndLayout}; -use rustc_middle::ty::print::with_no_trimmed_paths; +use rustc_middle::ty::layout::{FnAbiOf, LayoutOf, TyAndLayout}; +use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths}; use rustc_middle::ty::{self, Ty, TypeFoldable}; use rustc_target::abi::{Abi, AddressSpace, Align, FieldsShape}; use rustc_target::abi::{Int, Pointer, F32, F64}; -use rustc_target::abi::{LayoutOf, PointeeInfo, Scalar, Size, TyAbiInterface, Variants}; +use rustc_target::abi::{PointeeInfo, Scalar, Size, TyAbiInterface, Variants}; use smallvec::{smallvec, SmallVec}; use tracing::debug; @@ -23,7 +22,7 @@ fn uncached_llvm_type<'a, 'tcx>( ) -> &'a Type { match layout.abi { Abi::Scalar(_) => bug!("handled elsewhere"), - Abi::Vector { ref element, count } => { + Abi::Vector { element, count } => { let element = layout.scalar_llvm_type_at(cx, element, Size::ZERO); return cx.type_vector(element, count); } @@ -44,7 +43,8 @@ fn uncached_llvm_type<'a, 'tcx>( // in problematically distinct types due to HRTB and subtyping (see #47638). // ty::Dynamic(..) | ty::Adt(..) | ty::Closure(..) | ty::Foreign(..) | ty::Generator(..) | ty::Str => { - let mut name = with_no_trimmed_paths(|| layout.ty.to_string()); + let mut name = + with_no_visible_paths(|| with_no_trimmed_paths(|| layout.ty.to_string())); if let (&ty::Adt(def, _), &Variants::Single { index }) = (layout.ty.kind(), &layout.variants) { @@ -177,7 +177,7 @@ pub trait LayoutLlvmExt<'tcx> { fn scalar_llvm_type_at<'a>( &self, cx: &CodegenCx<'a, 'tcx>, - scalar: &Scalar, + scalar: Scalar, offset: Size, ) -> &'a Type; fn scalar_pair_element_llvm_type<'a>( @@ -218,7 +218,7 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> { /// of that field's type - this is useful for taking the address of /// that field and ensuring the struct has the right alignment. fn llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> &'a Type { - if let Abi::Scalar(ref scalar) = self.abi { + if let Abi::Scalar(scalar) = self.abi { // Use a different cache for scalars because pointers to DSTs // can be either fat or thin (data pointers of fat pointers). if let Some(&llty) = cx.scalar_lltypes.borrow().get(&self.ty) { @@ -231,7 +231,9 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> { ty::Adt(def, _) if def.is_box() => { cx.type_ptr_to(cx.layout_of(self.ty.boxed_ty()).llvm_type(cx)) } - ty::FnPtr(sig) => cx.fn_ptr_backend_type(&FnAbi::of_fn_ptr(cx, sig, &[])), + ty::FnPtr(sig) => { + cx.fn_ptr_backend_type(cx.fn_abi_of_fn_ptr(sig, ty::List::empty())) + } _ => self.scalar_llvm_type_at(cx, scalar, Size::ZERO), }; cx.scalar_lltypes.borrow_mut().insert(self.ty, llty); @@ -243,7 +245,7 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> { Variants::Single { index } => Some(index), _ => None, }; - if let Some(ref llty) = cx.type_lowering.borrow().get(&(self.ty, variant_index)) { + if let Some(llty) = cx.type_lowering.borrow().get(&(self.ty, variant_index)) { return llty.lltype; } @@ -268,10 +270,9 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> { }; debug!("--> mapped {:#?} to llty={:?}", self, llty); - cx.type_lowering.borrow_mut().insert( - (self.ty, variant_index), - TypeLowering { lltype: llty, field_remapping: field_remapping }, - ); + cx.type_lowering + .borrow_mut() + .insert((self.ty, variant_index), TypeLowering { lltype: llty, field_remapping }); if let Some((llty, layout)) = defer { let (llfields, packed, new_field_remapping) = struct_llfields(cx, layout); @@ -286,7 +287,7 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> { } fn immediate_llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> &'a Type { - if let Abi::Scalar(ref scalar) = self.abi { + if let Abi::Scalar(scalar) = self.abi { if scalar.is_bool() { return cx.type_i1(); } @@ -297,7 +298,7 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> { fn scalar_llvm_type_at<'a>( &self, cx: &CodegenCx<'a, 'tcx>, - scalar: &Scalar, + scalar: Scalar, offset: Size, ) -> &'a Type { match scalar.value { @@ -337,7 +338,7 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> { } let (a, b) = match self.abi { - Abi::ScalarPair(ref a, ref b) => (a, b), + Abi::ScalarPair(a, b) => (a, b), _ => bug!("TyAndLayout::scalar_pair_element_llty({:?}): not applicable", self), }; let scalar = [a, b][index]; diff --git a/compiler/rustc_codegen_llvm/src/va_arg.rs b/compiler/rustc_codegen_llvm/src/va_arg.rs index 2208ec37a4..591f659f11 100644 --- a/compiler/rustc_codegen_llvm/src/va_arg.rs +++ b/compiler/rustc_codegen_llvm/src/va_arg.rs @@ -7,9 +7,9 @@ use rustc_codegen_ssa::{ common::IntPredicate, traits::{BaseTypeMethods, BuilderMethods, ConstMethods, DerivedTypeMethods}, }; -use rustc_middle::ty::layout::HasTyCtxt; +use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf}; use rustc_middle::ty::Ty; -use rustc_target::abi::{Align, Endian, HasDataLayout, LayoutOf, Size}; +use rustc_target::abi::{Align, Endian, HasDataLayout, Size}; fn round_pointer_up_to_alignment( bx: &mut Builder<'a, 'll, 'tcx>, @@ -125,7 +125,7 @@ fn emit_aapcs_va_arg( // if the offset >= 0 then the value will be on the stack let mut reg_off_v = bx.load(bx.type_i32(), reg_off, offset_align); let use_stack = bx.icmp(IntPredicate::IntSGE, reg_off_v, zero); - bx.cond_br(use_stack, &on_stack.llbb(), &maybe_reg.llbb()); + bx.cond_br(use_stack, on_stack.llbb(), maybe_reg.llbb()); // The value at this point might be in a register, but there is a chance that // it could be on the stack so we have to update the offset and then check @@ -142,7 +142,7 @@ fn emit_aapcs_va_arg( // Check to see if we have overflowed the registers as a result of this. // If we have then we need to use the stack for this value let use_stack = maybe_reg.icmp(IntPredicate::IntSGT, new_reg_off_v, zero); - maybe_reg.cond_br(use_stack, &on_stack.llbb(), &in_reg.llbb()); + maybe_reg.cond_br(use_stack, on_stack.llbb(), in_reg.llbb()); let top_type = bx.type_i8p(); let top = in_reg.struct_gep(va_list_ty, va_list_addr, reg_top_index); @@ -158,17 +158,17 @@ fn emit_aapcs_va_arg( let reg_type = layout.llvm_type(bx); let reg_addr = in_reg.bitcast(reg_addr, bx.cx.type_ptr_to(reg_type)); let reg_value = in_reg.load(reg_type, reg_addr, layout.align.abi); - in_reg.br(&end.llbb()); + in_reg.br(end.llbb()); // On Stack block let stack_value = emit_ptr_va_arg(&mut on_stack, list, target_ty, false, Align::from_bytes(8).unwrap(), true); - on_stack.br(&end.llbb()); + on_stack.br(end.llbb()); let val = end.phi( layout.immediate_llvm_type(bx), &[reg_value, stack_value], - &[&in_reg.llbb(), &on_stack.llbb()], + &[in_reg.llbb(), on_stack.llbb()], ); *bx = end; diff --git a/compiler/rustc_codegen_ssa/Cargo.toml b/compiler/rustc_codegen_ssa/Cargo.toml index 1446624b88..83dd625611 100644 --- a/compiler/rustc_codegen_ssa/Cargo.toml +++ b/compiler/rustc_codegen_ssa/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustc_codegen_ssa" version = "0.0.0" -edition = "2018" +edition = "2021" [lib] test = false @@ -32,6 +32,8 @@ rustc_hir = { path = "../rustc_hir" } rustc_incremental = { path = "../rustc_incremental" } rustc_index = { path = "../rustc_index" } rustc_macros = { path = "../rustc_macros" } +rustc_metadata = { path = "../rustc_metadata" } +rustc_query_system = { path = "../rustc_query_system" } rustc_target = { path = "../rustc_target" } rustc_session = { path = "../rustc_session" } diff --git a/compiler/rustc_codegen_ssa/src/back/archive.rs b/compiler/rustc_codegen_ssa/src/back/archive.rs index 63f457bb97..3db948a16f 100644 --- a/compiler/rustc_codegen_ssa/src/back/archive.rs +++ b/compiler/rustc_codegen_ssa/src/back/archive.rs @@ -1,12 +1,12 @@ use rustc_data_structures::temp_dir::MaybeTempDir; -use rustc_middle::middle::cstore::DllImport; +use rustc_session::cstore::DllImport; use rustc_session::Session; use rustc_span::symbol::Symbol; use std::io; use std::path::{Path, PathBuf}; -pub fn find_library( +pub(super) fn find_library( name: Symbol, verbatim: bool, search_paths: &[PathBuf], @@ -48,14 +48,9 @@ pub trait ArchiveBuilder<'a> { fn remove_file(&mut self, name: &str); fn src_files(&mut self) -> Vec; - fn add_rlib( - &mut self, - path: &Path, - name: &str, - lto: bool, - skip_objects: bool, - ) -> io::Result<()>; - fn add_native_library(&mut self, name: Symbol, verbatim: bool); + fn add_archive(&mut self, archive: &Path, skip: F) -> io::Result<()> + where + F: FnMut(&str) -> bool + 'static; fn update_symbols(&mut self); fn build(self); diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index f5463bca33..cf1c605889 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -3,10 +3,10 @@ use rustc_data_structures::temp_dir::MaybeTempDir; use rustc_errors::{ErrorReported, Handler}; use rustc_fs_util::fix_windows_verbatim_for_gcc; use rustc_hir::def_id::CrateNum; -use rustc_middle::middle::cstore::DllImport; use rustc_middle::middle::dependency_format::Linkage; use rustc_session::config::{self, CFGuard, CrateType, DebugInfo, LdImpl, Strip}; use rustc_session::config::{OutputFilenames, OutputType, PrintRequest}; +use rustc_session::cstore::DllImport; use rustc_session::output::{check_file_is_writeable, invalid_output_for_target, out_filename}; use rustc_session::search_paths::PathKind; use rustc_session::utils::NativeLibKind; @@ -19,7 +19,7 @@ use rustc_target::spec::crt_objects::{CrtObjects, CrtObjectsFallback}; use rustc_target::spec::{LinkOutputKind, LinkerFlavor, LldFlavor, SplitDebuginfo}; use rustc_target::spec::{PanicStrategy, RelocModel, RelroLevel, SanitizerSet, Target}; -use super::archive::ArchiveBuilder; +use super::archive::{find_library, ArchiveBuilder}; use super::command::Command; use super::linker::{self, Linker}; use super::rpath::{self, RPathConfig}; @@ -36,6 +36,7 @@ use regex::Regex; use tempfile::Builder as TempFileBuilder; use std::ffi::OsString; +use std::lazy::OnceCell; use std::path::{Path, PathBuf}; use std::process::{ExitStatus, Output, Stdio}; use std::{ascii, char, env, fmt, fs, io, mem, str}; @@ -230,6 +231,9 @@ fn link_rlib<'a, B: ArchiveBuilder<'a>>( tmpdir: &MaybeTempDir, ) -> Result { info!("preparing rlib to {:?}", out_filename); + + let lib_search_paths = archive_search_paths(sess); + let mut ab = ::new(sess, out_filename, None); for obj in codegen_results.modules.iter().filter_map(|m| m.object.as_ref()) { @@ -254,6 +258,19 @@ fn link_rlib<'a, B: ArchiveBuilder<'a>>( // metadata of the rlib we're generating somehow. for lib in codegen_results.crate_info.used_libraries.iter() { match lib.kind { + NativeLibKind::Static { bundle: None | Some(true), whole_archive: Some(true) } + if flavor == RlibFlavor::Normal => + { + // Don't allow mixing +bundle with +whole_archive since an rlib may contain + // multiple native libs, some of which are +whole-archive and some of which are + // -whole-archive and it isn't clear how we can currently handle such a + // situation correctly. + // See https://github.com/rust-lang/rust/issues/88085#issuecomment-901050897 + sess.err( + "the linking modifiers `+bundle` and `+whole-archive` are not compatible \ + with each other when generating rlibs", + ); + } NativeLibKind::Static { bundle: None | Some(true), .. } => {} NativeLibKind::Static { bundle: Some(false), .. } | NativeLibKind::Dylib { .. } @@ -262,7 +279,15 @@ fn link_rlib<'a, B: ArchiveBuilder<'a>>( | NativeLibKind::Unspecified => continue, } if let Some(name) = lib.name { - ab.add_native_library(name, lib.verbatim.unwrap_or(false)); + let location = + find_library(name, lib.verbatim.unwrap_or(false), &lib_search_paths, sess); + ab.add_archive(&location, |_| false).unwrap_or_else(|e| { + sess.fatal(&format!( + "failed to add native library {}: {}", + location.to_string_lossy(), + e + )); + }); } } @@ -302,7 +327,7 @@ fn link_rlib<'a, B: ArchiveBuilder<'a>>( // metadata in rlib files is wrapped in a "dummy" object file for // the target platform so the rlib can be processed entirely by // normal linkers for the platform. - let metadata = create_metadata_file(sess, &codegen_results.metadata.raw_data); + let metadata = create_metadata_file(sess, codegen_results.metadata.raw_data()); ab.add_file(&emit_metadata(sess, &metadata, tmpdir)); // After adding all files to the archive, we need to update the @@ -541,13 +566,35 @@ fn link_staticlib<'a, B: ArchiveBuilder<'a>>( matches!(lib.kind, NativeLibKind::Static { bundle: None | Some(true), .. }) && !relevant_lib(sess, lib) }); - ab.add_rlib( - path, - &name.as_str(), - are_upstream_rust_objects_already_included(sess) - && !ignored_for_lto(sess, &codegen_results.crate_info, cnum), - skip_object_files, - ) + + let lto = are_upstream_rust_objects_already_included(sess) + && !ignored_for_lto(sess, &codegen_results.crate_info, cnum); + + // Ignoring obj file starting with the crate name + // as simple comparison is not enough - there + // might be also an extra name suffix + let obj_start = name.as_str().to_owned(); + + ab.add_archive(path, move |fname: &str| { + // Ignore metadata files, no matter the name. + if fname == METADATA_FILENAME { + return true; + } + + // Don't include Rust objects if LTO is enabled + if lto && looks_like_rust_object_file(fname) { + return true; + } + + // Otherwise if this is *not* a rust object and we're skipping + // objects then skip this file + if skip_object_files && (!fname.starts_with(&obj_start) || !fname.ends_with(".o")) { + return true; + } + + // ok, don't skip this + false + }) .unwrap(); all_native_libs.extend(codegen_results.crate_info.native_libraries[&cnum].iter().cloned()); @@ -590,7 +637,7 @@ fn link_dwarf_object<'a>(sess: &'a Session, executable_out_filename: &Path) { cmd.arg("-o"); cmd.arg(&dwp_out_filename); - let mut new_path = sess.host_filesearch(PathKind::All).get_tools_search_paths(false); + let mut new_path = sess.get_tools_search_paths(false); if let Some(path) = env::var_os("PATH") { new_path.extend(env::split_paths(&path)); } @@ -796,19 +843,18 @@ fn link_natively<'a, B: ArchiveBuilder<'a>>( let msg_bus = "clang: error: unable to execute command: Bus error: 10"; if out.contains(msg_segv) || out.contains(msg_bus) { warn!( + ?cmd, %out, "looks like the linker segfaulted when we tried to call it, \ - automatically retrying again. cmd = {:?}, out = {}.", - cmd, out, + automatically retrying again", ); continue; } if is_illegal_instruction(&output.status) { warn!( + ?cmd, %out, status = %output.status, "looks like the linker hit an illegal instruction when we \ - tried to call it, automatically retrying again. cmd = {:?}, ]\ - out = {}, status = {}.", - cmd, out, output.status, + tried to call it, automatically retrying again.", ); continue; } @@ -977,14 +1023,20 @@ fn link_natively<'a, B: ArchiveBuilder<'a>>( } if sess.target.is_like_osx { - if let Some(option) = osx_strip_opt(sess.opts.debugging_opts.strip) { - strip_symbols_in_osx(sess, &out_filename, option); + match sess.opts.debugging_opts.strip { + Strip::Debuginfo => strip_symbols_in_osx(sess, &out_filename, Some("-S")), + Strip::Symbols => strip_symbols_in_osx(sess, &out_filename, None), + Strip::None => {} } } } -fn strip_symbols_in_osx<'a>(sess: &'a Session, out_filename: &Path, option: &str) { - let prog = Command::new("strip").arg(option).arg(out_filename).output(); +fn strip_symbols_in_osx<'a>(sess: &'a Session, out_filename: &Path, option: Option<&str>) { + let mut cmd = Command::new("strip"); + if let Some(option) = option { + cmd.arg(option); + } + let prog = cmd.arg(out_filename).output(); match prog { Ok(prog) => { if !prog.status.success() { @@ -1002,14 +1054,6 @@ fn strip_symbols_in_osx<'a>(sess: &'a Session, out_filename: &Path, option: &str } } -fn osx_strip_opt<'a>(strip: Strip) -> Option<&'a str> { - match strip { - Strip::Debuginfo => Some("-S"), - Strip::Symbols => Some("-x"), - Strip::None => None, - } -} - fn escape_string(s: &[u8]) -> String { str::from_utf8(s).map(|s| s.to_owned()).unwrap_or_else(|_| { let mut x = "Non-UTF-8 output: ".to_string(); @@ -1218,10 +1262,11 @@ fn preserve_objects_for_their_debuginfo(sess: &Session) -> bool { sess.split_debuginfo() == SplitDebuginfo::Unpacked } -pub fn archive_search_paths(sess: &Session) -> Vec { +fn archive_search_paths(sess: &Session) -> Vec { sess.target_filesearch(PathKind::Native).search_path_dirs() } +#[derive(PartialEq)] enum RlibFlavor { Normal, StaticlibBase, @@ -1442,9 +1487,13 @@ fn exec_linker( fn link_output_kind(sess: &Session, crate_type: CrateType) -> LinkOutputKind { let kind = match (crate_type, sess.crt_static(Some(crate_type)), sess.relocation_model()) { (CrateType::Executable, _, _) if sess.is_wasi_reactor() => LinkOutputKind::WasiReactorExe, - (CrateType::Executable, false, RelocModel::Pic) => LinkOutputKind::DynamicPicExe, + (CrateType::Executable, false, RelocModel::Pic | RelocModel::Pie) => { + LinkOutputKind::DynamicPicExe + } (CrateType::Executable, false, _) => LinkOutputKind::DynamicNoPicExe, - (CrateType::Executable, true, RelocModel::Pic) => LinkOutputKind::StaticPicExe, + (CrateType::Executable, true, RelocModel::Pic | RelocModel::Pie) => { + LinkOutputKind::StaticPicExe + } (CrateType::Executable, true, _) => LinkOutputKind::StaticNoPicExe, (_, true, _) => LinkOutputKind::StaticDylib, (_, false, _) => LinkOutputKind::DynamicDylib, @@ -2001,7 +2050,7 @@ fn add_local_native_libraries( let relevant_libs = codegen_results.crate_info.used_libraries.iter().filter(|l| relevant_lib(sess, l)); - let search_path = archive_search_paths(sess); + let search_path = OnceCell::new(); let mut last = (NativeLibKind::Unspecified, None); for lib in relevant_libs { let name = match lib.name { @@ -2023,7 +2072,11 @@ fn add_local_native_libraries( } NativeLibKind::Static { bundle: None | Some(true), .. } | NativeLibKind::Static { whole_archive: Some(true), .. } => { - cmd.link_whole_staticlib(name, verbatim, &search_path); + cmd.link_whole_staticlib( + name, + verbatim, + &search_path.get_or_init(|| archive_search_paths(sess)), + ); } NativeLibKind::Static { .. } => cmd.link_staticlib(name, verbatim), NativeLibKind::RawDylib => { @@ -2116,6 +2169,7 @@ fn add_upstream_rust_crates<'a, B: ArchiveBuilder<'a>>( } let mut compiler_builtins = None; + let search_path = OnceCell::new(); for &cnum in deps.iter() { if group_start == Some(cnum) { @@ -2149,16 +2203,35 @@ fn add_upstream_rust_crates<'a, B: ArchiveBuilder<'a>>( // external build system already has the native dependencies defined, and it // will provide them to the linker itself. if sess.opts.debugging_opts.link_native_libraries { - // Skip if this library is the same as the last. let mut last = None; for lib in &codegen_results.crate_info.native_libraries[&cnum] { - if lib.name.is_some() - && relevant_lib(sess, lib) - && matches!(lib.kind, NativeLibKind::Static { bundle: Some(false), .. }) - && last != lib.name - { - cmd.link_staticlib(lib.name.unwrap(), lib.verbatim.unwrap_or(false)); - last = lib.name; + if !relevant_lib(sess, lib) { + // Skip libraries if they are disabled by `#[link(cfg=...)]` + continue; + } + + // Skip if this library is the same as the last. + if last == lib.name { + continue; + } + + if let Some(static_lib_name) = lib.name { + if let NativeLibKind::Static { bundle: Some(false), whole_archive } = + lib.kind + { + let verbatim = lib.verbatim.unwrap_or(false); + if whole_archive == Some(true) { + cmd.link_whole_staticlib( + static_lib_name, + verbatim, + search_path.get_or_init(|| archive_search_paths(sess)), + ); + } else { + cmd.link_staticlib(static_lib_name, verbatim); + } + + last = lib.name; + } } } } @@ -2483,8 +2556,7 @@ fn add_gcc_ld_path(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) { match ld_impl { LdImpl::Lld => { if sess.target.lld_flavor == LldFlavor::Ld64 { - let tools_path = - sess.host_filesearch(PathKind::All).get_tools_search_paths(false); + let tools_path = sess.get_tools_search_paths(false); let ld64_exe = tools_path .into_iter() .map(|p| p.join("gcc-ld")) @@ -2499,8 +2571,7 @@ fn add_gcc_ld_path(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) { arg }); } else { - let tools_path = - sess.host_filesearch(PathKind::All).get_tools_search_paths(false); + let tools_path = sess.get_tools_search_paths(false); let lld_path = tools_path .into_iter() .map(|p| p.join("gcc-ld")) diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index 9e1c6a169f..429dc45d6a 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -15,7 +15,6 @@ use rustc_middle::middle::dependency_format::Linkage; use rustc_middle::ty::TyCtxt; use rustc_serialize::{json, Encoder}; use rustc_session::config::{self, CrateType, DebugInfo, LinkerPluginLto, Lto, OptLevel, Strip}; -use rustc_session::search_paths::PathKind; use rustc_session::Session; use rustc_span::symbol::Symbol; use rustc_target::spec::{LinkOutputKind, LinkerFlavor, LldFlavor}; @@ -101,7 +100,7 @@ pub fn get_linker<'a>( // The compiler's sysroot often has some bundled tools, so add it to the // PATH for the child. - let mut new_path = sess.host_filesearch(PathKind::All).get_tools_search_paths(self_contained); + let mut new_path = sess.get_tools_search_paths(self_contained); let mut msvc_changed_path = false; if sess.target.is_like_msvc { if let Some(ref tool) = msvc_tool { @@ -287,6 +286,9 @@ impl<'a> GccLinker<'a> { config::OptLevel::Aggressive => "O3", }; + if let Some(path) = &self.sess.opts.debugging_opts.profile_sample_use { + self.linker_arg(&format!("-plugin-opt=sample-profile={}", path.display())); + }; self.linker_arg(&format!("-plugin-opt={}", opt_level)); self.linker_arg(&format!("-plugin-opt=mcpu={}", self.target_cpu)); } diff --git a/compiler/rustc_codegen_ssa/src/back/metadata.rs b/compiler/rustc_codegen_ssa/src/back/metadata.rs index 0fff319580..ffeb926e64 100644 --- a/compiler/rustc_codegen_ssa/src/back/metadata.rs +++ b/compiler/rustc_codegen_ssa/src/back/metadata.rs @@ -8,7 +8,7 @@ use rustc_data_structures::memmap::Mmap; use rustc_data_structures::owning_ref::OwningRef; use rustc_data_structures::rustc_erase_owner; use rustc_data_structures::sync::MetadataRef; -use rustc_middle::middle::cstore::MetadataLoader; +use rustc_session::cstore::MetadataLoader; use rustc_target::spec::Target; use crate::METADATA_FILENAME; diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index 41823f7d80..da34612ce7 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -21,8 +21,8 @@ use rustc_hir::def_id::{CrateNum, LOCAL_CRATE}; use rustc_incremental::{ copy_cgu_workproduct_to_incr_comp_cache_dir, in_incr_comp_dir, in_incr_comp_dir_sess, }; +use rustc_metadata::EncodedMetadata; use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; -use rustc_middle::middle::cstore::EncodedMetadata; use rustc_middle::middle::exported_symbols::SymbolExportLevel; use rustc_middle::ty::TyCtxt; use rustc_session::cgu_reuse_tracker::CguReuseTracker; @@ -83,6 +83,8 @@ pub struct ModuleConfig { pub pgo_gen: SwitchWithOptPath, pub pgo_use: Option, + pub pgo_sample_use: Option, + pub debug_info_for_profiling: bool, pub instrument_coverage: bool, pub instrument_gcov: bool, @@ -176,6 +178,8 @@ impl ModuleConfig { SwitchWithOptPath::Disabled ), pgo_use: if_regular!(sess.opts.cg.profile_use.clone(), None), + pgo_sample_use: if_regular!(sess.opts.debugging_opts.profile_sample_use.clone(), None), + debug_info_for_profiling: sess.opts.debugging_opts.debug_info_for_profiling, instrument_coverage: if_regular!(sess.instrument_coverage(), false), instrument_gcov: if_regular!( // compiler_builtins overrides the codegen-units settings, diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index a5143a755f..9bb4982754 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -18,18 +18,18 @@ use rustc_hir as hir; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_hir::lang_items::LangItem; use rustc_index::vec::Idx; +use rustc_metadata::EncodedMetadata; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs; -use rustc_middle::middle::cstore::EncodedMetadata; use rustc_middle::middle::lang_items; use rustc_middle::mir::mono::{CodegenUnit, CodegenUnitNameBuilder, MonoItem}; -use rustc_middle::ty::layout::{HasTyCtxt, TyAndLayout}; +use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, TyAndLayout}; use rustc_middle::ty::query::Providers; use rustc_middle::ty::{self, Instance, Ty, TyCtxt}; use rustc_session::cgu_reuse_tracker::CguReuse; use rustc_session::config::{self, EntryFnType}; use rustc_session::Session; use rustc_span::symbol::sym; -use rustc_target::abi::{Align, LayoutOf, VariantIdx}; +use rustc_target::abi::{Align, VariantIdx}; use std::convert::TryFrom; use std::ops::{Deref, DerefMut}; @@ -538,12 +538,18 @@ pub fn codegen_crate( } else if let Some(kind) = tcx.allocator_kind(()) { let llmod_id = cgu_name_builder.build_cgu_name(LOCAL_CRATE, &["crate"], Some("allocator")).to_string(); - let mut modules = backend.new_metadata(tcx, &llmod_id); + let mut module_llvm = backend.new_metadata(tcx, &llmod_id); tcx.sess.time("write_allocator_module", || { - backend.codegen_allocator(tcx, &mut modules, kind, tcx.lang_items().oom().is_some()) + backend.codegen_allocator( + tcx, + &mut module_llvm, + &llmod_id, + kind, + tcx.lang_items().oom().is_some(), + ) }); - Some(ModuleCodegen { name: llmod_id, module_llvm: modules, kind: ModuleKind::Allocator }) + Some(ModuleCodegen { name: llmod_id, module_llvm, kind: ModuleKind::Allocator }) } else { None }; diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs index f0b32c9630..accb54e464 100644 --- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs +++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs @@ -16,10 +16,10 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::definitions::{DefPathData, DefPathDataName, DisambiguatedDefPathData}; -use rustc_middle::ich::NodeIdHashingMode; use rustc_middle::ty::layout::IntegerExt; use rustc_middle::ty::subst::{GenericArgKind, SubstsRef}; use rustc_middle::ty::{self, AdtDef, ExistentialProjection, Ty, TyCtxt}; +use rustc_query_system::ich::NodeIdHashingMode; use rustc_target::abi::{Integer, TagEncoding, Variants}; use smallvec::SmallVec; @@ -404,7 +404,7 @@ fn push_debuginfo_type_name<'tcx>( // calculate the range of values for the dataful variant let dataful_discriminant_range = - &dataful_variant_layout.largest_niche.as_ref().unwrap().scalar.valid_range; + dataful_variant_layout.largest_niche.unwrap().scalar.valid_range; let min = dataful_discriminant_range.start; let min = tag.value.size(&tcx).truncate(min); @@ -446,6 +446,59 @@ fn push_debuginfo_type_name<'tcx>( } } +/// Computes a name for the global variable storing a vtable. +/// +/// The name is of the form: +/// +/// `::{vtable}` +/// +/// or, when generating C++-like names: +/// +/// `impl$::vtable$` +pub fn compute_debuginfo_vtable_name<'tcx>( + tcx: TyCtxt<'tcx>, + t: Ty<'tcx>, + trait_ref: Option>, +) -> String { + let cpp_like_names = cpp_like_names(tcx); + + let mut vtable_name = String::with_capacity(64); + + if cpp_like_names { + vtable_name.push_str("impl$<"); + } else { + vtable_name.push('<'); + } + + let mut visited = FxHashSet::default(); + push_debuginfo_type_name(tcx, t, true, &mut vtable_name, &mut visited); + + if cpp_like_names { + vtable_name.push_str(", "); + } else { + vtable_name.push_str(" as "); + } + + if let Some(trait_ref) = trait_ref { + let trait_ref = + tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), trait_ref); + push_item_name(tcx, trait_ref.def_id, true, &mut vtable_name); + visited.clear(); + push_generic_params_internal(tcx, trait_ref.substs, &mut vtable_name, &mut visited); + } else { + vtable_name.push_str("_"); + } + + push_close_angle_bracket(cpp_like_names, &mut vtable_name); + + let suffix = if cpp_like_names { "::vtable$" } else { "::{vtable}" }; + + vtable_name.reserve_exact(suffix.len()); + vtable_name.push_str(suffix); + + vtable_name +} + pub fn push_item_name(tcx: TyCtxt<'tcx>, def_id: DefId, qualified: bool, output: &mut String) { let def_key = tcx.def_key(def_id); if qualified { diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index b6ee70c419..b759e3a7a7 100644 --- a/compiler/rustc_codegen_ssa/src/lib.rs +++ b/compiler/rustc_codegen_ssa/src/lib.rs @@ -3,6 +3,7 @@ #![feature(box_patterns)] #![feature(try_blocks)] #![feature(in_band_lifetimes)] +#![feature(once_cell)] #![feature(nll)] #![feature(associated_type_bounds)] #![recursion_limit = "256"] @@ -24,10 +25,10 @@ use rustc_data_structures::sync::Lrc; use rustc_hir::def_id::CrateNum; use rustc_hir::LangItem; use rustc_middle::dep_graph::WorkProduct; -use rustc_middle::middle::cstore::{self, CrateSource}; use rustc_middle::middle::dependency_format::Dependencies; use rustc_middle::ty::query::Providers; use rustc_session::config::{CrateType, OutputFilenames, OutputType, RUST_CGU_EXT}; +use rustc_session::cstore::{self, CrateSource}; use rustc_session::utils::NativeLibKind; use rustc_span::symbol::Symbol; use std::path::{Path, PathBuf}; @@ -157,7 +158,7 @@ pub struct CodegenResults { pub modules: Vec, pub allocator_module: Option, pub metadata_module: Option, - pub metadata: rustc_middle::middle::cstore::EncodedMetadata, + pub metadata: rustc_metadata::EncodedMetadata, pub crate_info: CrateInfo, } diff --git a/compiler/rustc_codegen_ssa/src/meth.rs b/compiler/rustc_codegen_ssa/src/meth.rs index 3267d3206f..6ab429669c 100644 --- a/compiler/rustc_codegen_ssa/src/meth.rs +++ b/compiler/rustc_codegen_ssa/src/meth.rs @@ -78,7 +78,7 @@ pub fn get_vtable<'tcx, Cx: CodegenMethods<'tcx>>( let align = cx.data_layout().pointer_align.abi; let vtable = cx.static_addr_of(vtable_const, align, Some("vtable")); - cx.create_vtable_metadata(ty, vtable); + cx.create_vtable_metadata(ty, trait_ref, vtable); cx.vtables().borrow_mut().insert((ty, trait_ref), vtable); vtable } diff --git a/compiler/rustc_codegen_ssa/src/mir/analyze.rs b/compiler/rustc_codegen_ssa/src/mir/analyze.rs index b6def164fa..8d75b2e7a3 100644 --- a/compiler/rustc_codegen_ssa/src/mir/analyze.rs +++ b/compiler/rustc_codegen_ssa/src/mir/analyze.rs @@ -9,8 +9,7 @@ use rustc_index::vec::IndexVec; use rustc_middle::mir::traversal; use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor}; use rustc_middle::mir::{self, Location, TerminatorKind}; -use rustc_middle::ty::layout::HasTyCtxt; -use rustc_target::abi::LayoutOf; +use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf}; pub fn non_ssa_locals<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( fx: &FunctionCx<'a, 'tcx, Bx>, diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index 2a76ad0fb1..b0a5631549 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -14,13 +14,13 @@ use rustc_hir::lang_items::LangItem; use rustc_index::vec::Idx; use rustc_middle::mir::AssertKind; use rustc_middle::mir::{self, SwitchTargets}; -use rustc_middle::ty::layout::{FnAbiExt, HasTyCtxt}; -use rustc_middle::ty::print::with_no_trimmed_paths; +use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf}; +use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths}; use rustc_middle::ty::{self, Instance, Ty, TypeFoldable}; use rustc_span::source_map::Span; use rustc_span::{sym, Symbol}; use rustc_target::abi::call::{ArgAbi, FnAbi, PassMode}; -use rustc_target::abi::{self, HasDataLayout, LayoutOf}; +use rustc_target::abi::{self, HasDataLayout, WrappingRange}; use rustc_target::spec::abi::Abi; /// Used by `FunctionCx::codegen_terminator` for emitting common patterns @@ -124,7 +124,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> { &self, fx: &mut FunctionCx<'a, 'tcx, Bx>, bx: &mut Bx, - fn_abi: FnAbi<'tcx, Ty<'tcx>>, + fn_abi: &'tcx FnAbi<'tcx, Ty<'tcx>>, fn_ptr: Bx::Value, llargs: &[Bx::Value], destination: Option<(ReturnDest<'tcx, Bx::Value>, mir::BasicBlock)>, @@ -337,7 +337,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { def: ty::InstanceDef::Virtual(drop_fn.def_id(), 0), substs: drop_fn.substs, }; - let fn_abi = FnAbi::of_instance(&bx, virtual_drop, &[]); + let fn_abi = bx.fn_abi_of_instance(virtual_drop, ty::List::empty()); let vtable = args[1]; args = &args[..1]; ( @@ -346,7 +346,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { fn_abi, ) } - _ => (bx.get_fn_addr(drop_fn), FnAbi::of_instance(&bx, drop_fn, &[])), + _ => (bx.get_fn_addr(drop_fn), bx.fn_abi_of_instance(drop_fn, ty::List::empty())), }; helper.do_call( self, @@ -433,7 +433,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // Obtain the panic entry point. let def_id = common::langcall(bx.tcx(), Some(span), "", lang_item); let instance = ty::Instance::mono(bx.tcx(), def_id); - let fn_abi = FnAbi::of_instance(&bx, instance, &[]); + let fn_abi = bx.fn_abi_of_instance(instance, ty::List::empty()); let llfn = bx.get_fn_addr(instance); // Codegen the actual panic invoke/call. @@ -476,15 +476,20 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { UninitValid => !layout.might_permit_raw_init(bx, /*zero:*/ false), }; if do_panic { - let msg_str = with_no_trimmed_paths(|| { - if layout.abi.is_uninhabited() { - // Use this error even for the other intrinsics as it is more precise. - format!("attempted to instantiate uninhabited type `{}`", ty) - } else if intrinsic == ZeroValid { - format!("attempted to zero-initialize type `{}`, which is invalid", ty) - } else { - format!("attempted to leave type `{}` uninitialized, which is invalid", ty) - } + let msg_str = with_no_visible_paths(|| { + with_no_trimmed_paths(|| { + if layout.abi.is_uninhabited() { + // Use this error even for the other intrinsics as it is more precise. + format!("attempted to instantiate uninhabited type `{}`", ty) + } else if intrinsic == ZeroValid { + format!("attempted to zero-initialize type `{}`, which is invalid", ty) + } else { + format!( + "attempted to leave type `{}` uninitialized, which is invalid", + ty + ) + } + }) }); let msg = bx.const_str(Symbol::intern(&msg_str)); let location = self.get_caller_location(bx, source_info).immediate(); @@ -494,7 +499,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let def_id = common::langcall(bx.tcx(), Some(source_info.span), "", LangItem::Panic); let instance = ty::Instance::mono(bx.tcx(), def_id); - let fn_abi = FnAbi::of_instance(bx, instance, &[]); + let fn_abi = bx.fn_abi_of_instance(instance, ty::List::empty()); let llfn = bx.get_fn_addr(instance); // Codegen the actual panic invoke/call. @@ -570,17 +575,14 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { }; let extra_args = &args[sig.inputs().skip_binder().len()..]; - let extra_args = extra_args - .iter() - .map(|op_arg| { - let op_ty = op_arg.ty(self.mir, bx.tcx()); - self.monomorphize(op_ty) - }) - .collect::>(); + let extra_args = bx.tcx().mk_type_list(extra_args.iter().map(|op_arg| { + let op_ty = op_arg.ty(self.mir, bx.tcx()); + self.monomorphize(op_ty) + })); let fn_abi = match instance { - Some(instance) => FnAbi::of_instance(&bx, instance, &extra_args), - None => FnAbi::of_fn_ptr(&bx, sig, &extra_args), + Some(instance) => bx.fn_abi_of_instance(instance, extra_args), + None => bx.fn_abi_of_fn_ptr(sig, extra_args), }; if intrinsic == Some(sym::transmute) { @@ -665,8 +667,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { if i == 2 && intrinsic.as_str().starts_with("simd_shuffle") { if let mir::Operand::Constant(constant) = arg { let c = self.eval_mir_constant(constant); - let (llval, ty) = - self.simd_shuffle_indices(&bx, constant.span, constant.ty(), c); + let (llval, ty) = self.simd_shuffle_indices( + &bx, + constant.span, + self.monomorphize(constant.ty()), + c, + ); return OperandRef { val: Immediate(llval), layout: bx.layout_of(ty), @@ -776,22 +782,30 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { self.codegen_argument(&mut bx, op, &mut llargs, &fn_abi.args[i]); } - if let Some(tup) = untuple { + let num_untupled = untuple.map(|tup| { self.codegen_arguments_untupled( &mut bx, tup, &mut llargs, &fn_abi.args[first_args.len()..], ) - } + }); let needs_location = instance.map_or(false, |i| i.def.requires_caller_location(self.cx.tcx())); if needs_location { + let mir_args = if let Some(num_untupled) = num_untupled { + first_args.len() + num_untupled + } else { + args.len() + }; assert_eq!( fn_abi.args.len(), - args.len() + 1, - "#[track_caller] fn's must have 1 more argument in their ABI than in their MIR", + mir_args + 1, + "#[track_caller] fn's must have 1 more argument in their ABI than in their MIR: {:?} {:?} {:?}", + instance, + fn_span, + fn_abi, ); let location = self.get_caller_location(&mut bx, mir::SourceInfo { span: fn_span, ..source_info }); @@ -1102,9 +1116,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // the load would just produce `OperandValue::Ref` instead // of the `OperandValue::Immediate` we need for the call. llval = bx.load(bx.backend_type(arg.layout), llval, align); - if let abi::Abi::Scalar(ref scalar) = arg.layout.abi { + if let abi::Abi::Scalar(scalar) = arg.layout.abi { if scalar.is_bool() { - bx.range_metadata(llval, 0..2); + bx.range_metadata(llval, WrappingRange { start: 0, end: 1 }); } } // We store bools as `i8` so we need to truncate to `i1`. @@ -1121,7 +1135,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { operand: &mir::Operand<'tcx>, llargs: &mut Vec, args: &[ArgAbi<'tcx, Ty<'tcx>>], - ) { + ) -> usize { let tuple = self.codegen_operand(bx, operand); // Handle both by-ref and immediate tuples. @@ -1141,6 +1155,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { self.codegen_argument(bx, op, llargs, &args[i]); } } + tuple.layout.fields.count() } fn get_caller_location( @@ -1424,7 +1439,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let src = self.codegen_operand(bx, src); // Special-case transmutes between scalars as simple bitcasts. - match (&src.layout.abi, &dst.layout.abi) { + match (src.layout.abi, dst.layout.abi) { (abi::Abi::Scalar(src_scalar), abi::Abi::Scalar(dst_scalar)) => { // HACK(eddyb) LLVM doesn't like `bitcast`s between pointers and non-pointers. if (src_scalar.value == abi::Pointer) == (dst_scalar.value == abi::Pointer) { diff --git a/compiler/rustc_codegen_ssa/src/mir/constant.rs b/compiler/rustc_codegen_ssa/src/mir/constant.rs index fa8a53e60b..93b39dc8e9 100644 --- a/compiler/rustc_codegen_ssa/src/mir/constant.rs +++ b/compiler/rustc_codegen_ssa/src/mir/constant.rs @@ -68,7 +68,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { if let Some(prim) = field.val.try_to_scalar() { let layout = bx.layout_of(field_ty); let scalar = match layout.abi { - Abi::Scalar(ref x) => x, + Abi::Scalar(x) => x, _ => bug!("from_const: invalid ByVal layout: {:#?}", layout), }; bx.scalar_to_backend(prim, scalar, bx.immediate_backend_type(layout)) diff --git a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs index c139f915e6..c710fcc2c1 100644 --- a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs +++ b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs @@ -3,9 +3,11 @@ use rustc_index::vec::IndexVec; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::mir; use rustc_middle::ty; +use rustc_middle::ty::layout::LayoutOf; use rustc_session::config::DebugInfo; use rustc_span::symbol::{kw, Symbol}; use rustc_span::{BytePos, Span}; +use rustc_target::abi::Abi; use rustc_target::abi::Size; use super::operand::{OperandRef, OperandValue}; @@ -368,21 +370,14 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { { let arg_index = place.local.index() - 1; if target_is_msvc { - // Rust compiler decomposes every &str or slice argument into two components: - // a pointer to the memory address where the data is stored and a usize representing - // the length of the str (or slice). These components will later be used to reconstruct - // the original argument inside the body of the function that owns it (see the - // definition of debug_introduce_local for more details). - // - // Since the original argument is declared inside a function rather than being passed - // in as an argument, it must be marked as a LocalVariable for MSVC debuggers to visualize - // its data correctly. (See issue #81894 for an in-depth description of the problem). - match *var_ty.kind() { - ty::Ref(_, inner_type, _) => match *inner_type.kind() { - ty::Slice(_) | ty::Str => VariableKind::LocalVariable, - _ => VariableKind::ArgumentVariable(arg_index + 1), - }, - _ => VariableKind::ArgumentVariable(arg_index + 1), + // ScalarPair parameters are spilled to the stack so they need to + // be marked as a `LocalVariable` for MSVC debuggers to visualize + // their data correctly. (See #81894 & #88625) + let var_ty_layout = self.cx.layout_of(var_ty); + if let Abi::ScalarPair(_, _) = var_ty_layout.abi { + VariableKind::LocalVariable + } else { + VariableKind::ArgumentVariable(arg_index + 1) } } else { // FIXME(eddyb) shouldn't `ArgumentVariable` indices be diff --git a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs index 75999225c0..f943157dc6 100644 --- a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs +++ b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs @@ -104,7 +104,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } } sym::pref_align_of - | sym::min_align_of | sym::needs_drop | sym::type_id | sym::type_name diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs index e2edd44826..476ddbd939 100644 --- a/compiler/rustc_codegen_ssa/src/mir/mod.rs +++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs @@ -2,7 +2,7 @@ use crate::traits::*; use rustc_errors::ErrorReported; use rustc_middle::mir; use rustc_middle::mir::interpret::ErrorHandled; -use rustc_middle::ty::layout::{FnAbiExt, HasTyCtxt, TyAndLayout}; +use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, TyAndLayout}; use rustc_middle::ty::{self, Instance, Ty, TypeFoldable}; use rustc_target::abi::call::{FnAbi, PassMode}; @@ -29,7 +29,7 @@ pub struct FunctionCx<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> { cx: &'a Bx::CodegenCx, - fn_abi: FnAbi<'tcx, Ty<'tcx>>, + fn_abi: &'tcx FnAbi<'tcx, Ty<'tcx>>, /// When unwinding is initiated, we have to store this personality /// value somewhere so that we can load it and re-use it in the @@ -129,6 +129,7 @@ impl<'a, 'tcx, V: CodegenObject> LocalRef<'tcx, V> { /////////////////////////////////////////////////////////////////////////// +#[instrument(level = "debug", skip(cx))] pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( cx: &'a Bx::CodegenCx, instance: Instance<'tcx>, @@ -139,7 +140,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( let mir = cx.tcx().instance_mir(instance.def); - let fn_abi = FnAbi::of_instance(cx, instance, &[]); + let fn_abi = cx.fn_abi_of_instance(instance, ty::List::empty()); debug!("fn_abi: {:?}", fn_abi); let debug_context = cx.create_function_debug_context(instance, &fn_abi, llfn, &mir); @@ -152,20 +153,11 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( } let cleanup_kinds = analyze::cleanup_kinds(&mir); - // Allocate a `Block` for every basic block, except - // the start block, if nothing loops back to it. - let reentrant_start_block = !mir.predecessors()[mir::START_BLOCK].is_empty(); - let cached_llbbs: IndexVec> = - mir.basic_blocks() - .indices() - .map(|bb| { - if bb == mir::START_BLOCK && !reentrant_start_block { - Some(start_llbb) - } else { - None - } - }) - .collect(); + let cached_llbbs: IndexVec> = mir + .basic_blocks() + .indices() + .map(|bb| if bb == mir::START_BLOCK { Some(start_llbb) } else { None }) + .collect(); let mut fx = FunctionCx { instance, @@ -247,11 +239,6 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( // Apply debuginfo to the newly allocated locals. fx.debug_introduce_locals(&mut bx); - // Branch to the START block, if it's not the entry block. - if reentrant_start_block { - bx.br(fx.llbb(mir::START_BLOCK)); - } - // Codegen the body of each block using reverse postorder // FIXME(eddyb) reuse RPO iterator between `analysis` and this. for (bb, _) in traversal::reverse_postorder(&mir) { @@ -271,6 +258,8 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( let mut idx = 0; let mut llarg_idx = fx.fn_abi.ret.is_indirect() as usize; + let mut num_untupled = None; + let args = mir .args_iter() .enumerate() @@ -299,6 +288,11 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( let pr_field = place.project_field(bx, i); bx.store_fn_arg(arg, &mut llarg_idx, pr_field); } + assert_eq!( + None, + num_untupled.replace(tupled_arg_tys.len()), + "Replaced existing num_tupled" + ); return LocalRef::Place(place); } @@ -375,10 +369,17 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( .collect::>(); if fx.instance.def.requires_caller_location(bx.tcx()) { + let mir_args = if let Some(num_untupled) = num_untupled { + // Subtract off the tupled argument that gets 'expanded' + args.len() - 1 + num_untupled + } else { + args.len() + }; assert_eq!( fx.fn_abi.args.len(), - args.len() + 1, - "#[track_caller] fn's must have 1 more argument in their ABI than in their MIR", + mir_args + 1, + "#[track_caller] instance {:?} must have 1 more argument in their ABI than in their MIR", + fx.instance ); let arg = fx.fn_abi.args.last().unwrap(); diff --git a/compiler/rustc_codegen_ssa/src/mir/operand.rs b/compiler/rustc_codegen_ssa/src/mir/operand.rs index cfb2befdf9..ce6cec67ad 100644 --- a/compiler/rustc_codegen_ssa/src/mir/operand.rs +++ b/compiler/rustc_codegen_ssa/src/mir/operand.rs @@ -8,9 +8,9 @@ use crate::MemFlags; use rustc_middle::mir; use rustc_middle::mir::interpret::{ConstValue, Pointer, Scalar}; -use rustc_middle::ty::layout::TyAndLayout; +use rustc_middle::ty::layout::{LayoutOf, TyAndLayout}; use rustc_middle::ty::Ty; -use rustc_target::abi::{Abi, Align, LayoutOf, Size}; +use rustc_target::abi::{Abi, Align, Size}; use std::fmt; @@ -79,7 +79,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> { let val = match val { ConstValue::Scalar(x) => { let scalar = match layout.abi { - Abi::Scalar(ref x) => x, + Abi::Scalar(x) => x, _ => bug!("from_const: invalid ByVal layout: {:#?}", layout), }; let llval = bx.scalar_to_backend(x, scalar, bx.immediate_backend_type(layout)); @@ -87,7 +87,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> { } ConstValue::Slice { data, start, end } => { let a_scalar = match layout.abi { - Abi::ScalarPair(ref a, _) => a, + Abi::ScalarPair(a, _) => a, _ => bug!("from_const: invalid ScalarPair layout: {:#?}", layout), }; let a = Scalar::from_pointer( @@ -162,7 +162,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> { llval: V, layout: TyAndLayout<'tcx>, ) -> Self { - let val = if let Abi::ScalarPair(ref a, ref b) = layout.abi { + let val = if let Abi::ScalarPair(a, b) = layout.abi { debug!("Operand::from_immediate_or_packed_pair: unpacking {:?} @ {:?}", llval, layout); // Deconstruct the immediate aggregate. @@ -185,7 +185,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> { let field = self.layout.field(bx.cx(), i); let offset = self.layout.fields.offset(i); - let mut val = match (self.val, &self.layout.abi) { + let mut val = match (self.val, self.layout.abi) { // If the field is ZST, it has no data. _ if field.is_zst() => { return OperandRef::new_zst(bx, field); @@ -200,7 +200,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> { } // Extract a scalar component from a pair. - (OperandValue::Pair(a_llval, b_llval), &Abi::ScalarPair(ref a, ref b)) => { + (OperandValue::Pair(a_llval, b_llval), Abi::ScalarPair(a, b)) => { if offset.bytes() == 0 { assert_eq!(field.size, a.value.size(bx.cx())); OperandValue::Immediate(a_llval) @@ -212,14 +212,14 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> { } // `#[repr(simd)]` types are also immediate. - (OperandValue::Immediate(llval), &Abi::Vector { .. }) => { + (OperandValue::Immediate(llval), Abi::Vector { .. }) => { OperandValue::Immediate(bx.extract_element(llval, bx.cx().const_usize(i as u64))) } _ => bug!("OperandRef::extract_field({:?}): not applicable", self), }; - match (&mut val, &field.abi) { + match (&mut val, field.abi) { (OperandValue::Immediate(llval), _) => { // Bools in union fields needs to be truncated. *llval = bx.to_immediate(*llval, field); @@ -308,7 +308,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandValue { } OperandValue::Pair(a, b) => { let (a_scalar, b_scalar) = match dest.layout.abi { - Abi::ScalarPair(ref a, ref b) => (a, b), + Abi::ScalarPair(a, b) => (a, b), _ => bug!("store_with_flags: invalid ScalarPair layout: {:#?}", dest.layout), }; let ty = bx.backend_type(dest.layout); diff --git a/compiler/rustc_codegen_ssa/src/mir/place.rs b/compiler/rustc_codegen_ssa/src/mir/place.rs index 20be46606a..4b07ed1a1e 100644 --- a/compiler/rustc_codegen_ssa/src/mir/place.rs +++ b/compiler/rustc_codegen_ssa/src/mir/place.rs @@ -8,10 +8,10 @@ use crate::MemFlags; use rustc_middle::mir; use rustc_middle::mir::tcx::PlaceTy; -use rustc_middle::ty::layout::{HasTyCtxt, TyAndLayout}; +use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, TyAndLayout}; use rustc_middle::ty::{self, Ty}; use rustc_target::abi::{Abi, Align, FieldsShape, Int, TagEncoding}; -use rustc_target::abi::{LayoutOf, VariantIdx, Variants}; +use rustc_target::abi::{VariantIdx, Variants}; #[derive(Copy, Clone, Debug)] pub struct PlaceRef<'tcx, V> { @@ -99,7 +99,7 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> { // Also handles the first field of Scalar, ScalarPair, and Vector layouts. self.llval } - Abi::ScalarPair(ref a, ref b) + Abi::ScalarPair(a, b) if offset == a.value.size(bx.cx()).align_to(b.value.align(bx.cx()).abi) => { // Offset matches second field. @@ -222,7 +222,7 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> { .map_or(index.as_u32() as u128, |discr| discr.val); return bx.cx().const_uint_big(cast_to, discr_val); } - Variants::Multiple { ref tag, ref tag_encoding, tag_field, .. } => { + Variants::Multiple { tag, ref tag_encoding, tag_field, .. } => { (tag, tag_encoding, tag_field) } }; diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs index 02e2db54e7..f087b9f781 100644 --- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs +++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs @@ -11,10 +11,10 @@ use rustc_apfloat::{ieee, Float, Round, Status}; use rustc_hir::lang_items::LangItem; use rustc_middle::mir; use rustc_middle::ty::cast::{CastTy, IntTy}; -use rustc_middle::ty::layout::HasTyCtxt; +use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf}; use rustc_middle::ty::{self, adjustment::PointerCast, Instance, Ty, TyCtxt}; use rustc_span::source_map::{Span, DUMMY_SP}; -use rustc_target::abi::{Abi, Int, LayoutOf, Variants}; +use rustc_target::abi::{Abi, Int, Variants}; impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { pub fn codegen_rvalue( @@ -300,7 +300,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let llval = operand.immediate(); let mut signed = false; - if let Abi::Scalar(ref scalar) = operand.layout.abi { + if let Abi::Scalar(scalar) = operand.layout.abi { if let Int(_, s) = scalar.value { // We use `i1` for bytes that are always `0` or `1`, // e.g., `#[repr(i8)] enum E { A, B }`, but we can't @@ -308,8 +308,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // then `i1 1` (i.e., E::B) is effectively `i8 -1`. signed = !scalar.is_bool() && s; - let er = scalar.valid_range_exclusive(bx.cx()); - if er.end != er.start + if !scalar.is_always_valid(bx.cx()) && scalar.valid_range.end >= scalar.valid_range.start { // We want `table[e as usize ± k]` to not @@ -487,20 +486,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { ) } - mir::Rvalue::NullaryOp(mir::NullOp::SizeOf, ty) => { - let ty = self.monomorphize(ty); - assert!(bx.cx().type_is_sized(ty)); - let val = bx.cx().const_usize(bx.cx().layout_of(ty).size.bytes()); - let tcx = self.cx.tcx(); - ( - bx, - OperandRef { - val: OperandValue::Immediate(val), - layout: self.cx.layout_of(tcx.types.usize), - }, - ) - } - mir::Rvalue::NullaryOp(mir::NullOp::Box, content_ty) => { let content_ty = self.monomorphize(content_ty); let content_layout = bx.cx().layout_of(content_ty); @@ -525,6 +510,27 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let operand = OperandRef { val: OperandValue::Immediate(val), layout: box_layout }; (bx, operand) } + + mir::Rvalue::NullaryOp(null_op, ty) => { + let ty = self.monomorphize(ty); + assert!(bx.cx().type_is_sized(ty)); + let layout = bx.cx().layout_of(ty); + let val = match null_op { + mir::NullOp::SizeOf => layout.size.bytes(), + mir::NullOp::AlignOf => layout.align.abi.bytes(), + mir::NullOp::Box => unreachable!(), + }; + let val = bx.cx().const_usize(val); + let tcx = self.cx.tcx(); + ( + bx, + OperandRef { + val: OperandValue::Immediate(val), + layout: self.cx.layout_of(tcx.types.usize), + }, + ) + } + mir::Rvalue::ThreadLocalRef(def_id) => { assert!(bx.cx().tcx().is_static(def_id)); let static_ = bx.get_static(def_id); @@ -544,6 +550,18 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { OperandRef::new_zst(&mut bx, self.cx.layout_of(self.monomorphize(ty))); (bx, operand) } + mir::Rvalue::ShallowInitBox(ref operand, content_ty) => { + let operand = self.codegen_operand(&mut bx, operand); + let lloperand = operand.immediate(); + + let content_ty = self.monomorphize(content_ty); + let box_layout = bx.cx().layout_of(bx.tcx().mk_box(content_ty)); + let llty_ptr = bx.cx().backend_type(box_layout); + + let val = bx.pointercast(lloperand, llty_ptr); + let operand = OperandRef { val: OperandValue::Immediate(val), layout: box_layout }; + (bx, operand) + } } } @@ -757,6 +775,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { mir::Rvalue::AddressOf(..) | mir::Rvalue::Len(..) | mir::Rvalue::Cast(..) | // (*) + mir::Rvalue::ShallowInitBox(..) | // (*) mir::Rvalue::BinaryOp(..) | mir::Rvalue::CheckedBinaryOp(..) | mir::Rvalue::UnaryOp(..) | diff --git a/compiler/rustc_codegen_ssa/src/mono_item.rs b/compiler/rustc_codegen_ssa/src/mono_item.rs index 48d753e0d8..5f0f50ae2d 100644 --- a/compiler/rustc_codegen_ssa/src/mono_item.rs +++ b/compiler/rustc_codegen_ssa/src/mono_item.rs @@ -4,8 +4,7 @@ use crate::traits::*; use rustc_hir as hir; use rustc_middle::mir::mono::MonoItem; use rustc_middle::mir::mono::{Linkage, Visibility}; -use rustc_middle::ty::layout::HasTyCtxt; -use rustc_target::abi::LayoutOf; +use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf}; pub trait MonoItemExt<'a, 'tcx> { fn define>(&self, cx: &'a Bx::CodegenCx); diff --git a/compiler/rustc_codegen_ssa/src/traits/backend.rs b/compiler/rustc_codegen_ssa/src/traits/backend.rs index 1393fc71d6..8129a14fcf 100644 --- a/compiler/rustc_codegen_ssa/src/traits/backend.rs +++ b/compiler/rustc_codegen_ssa/src/traits/backend.rs @@ -6,17 +6,18 @@ use crate::{CodegenResults, ModuleCodegen}; use rustc_ast::expand::allocator::AllocatorKind; use rustc_data_structures::fx::FxHashMap; use rustc_errors::ErrorReported; +use rustc_metadata::EncodedMetadata; use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; -use rustc_middle::middle::cstore::{EncodedMetadata, MetadataLoaderDyn}; -use rustc_middle::ty::layout::{HasTyCtxt, TyAndLayout}; +use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, LayoutOf, TyAndLayout}; use rustc_middle::ty::query::Providers; use rustc_middle::ty::{Ty, TyCtxt}; use rustc_session::{ config::{self, OutputFilenames, PrintRequest}, + cstore::MetadataLoaderDyn, Session, }; use rustc_span::symbol::Symbol; -use rustc_target::abi::LayoutOf; +use rustc_target::abi::call::FnAbi; use rustc_target::spec::Target; pub use rustc_data_structures::sync::MetadataRef; @@ -42,14 +43,16 @@ pub trait Backend<'tcx>: Sized + BackendTypes + HasTyCtxt<'tcx> - + LayoutOf<'tcx, Ty = Ty<'tcx>, TyAndLayout = TyAndLayout<'tcx>> + + LayoutOf<'tcx, LayoutOfResult = TyAndLayout<'tcx>> + + FnAbiOf<'tcx, FnAbiOfResult = &'tcx FnAbi<'tcx, Ty<'tcx>>> { } impl<'tcx, T> Backend<'tcx> for T where Self: BackendTypes + HasTyCtxt<'tcx> - + LayoutOf<'tcx, Ty = Ty<'tcx>, TyAndLayout = TyAndLayout<'tcx>> + + LayoutOf<'tcx, LayoutOfResult = TyAndLayout<'tcx>> + + FnAbiOf<'tcx, FnAbiOfResult = &'tcx FnAbi<'tcx, Ty<'tcx>>> { } @@ -120,7 +123,8 @@ pub trait ExtraBackendMethods: CodegenBackend + WriteBackendMethods + Sized + Se fn codegen_allocator<'tcx>( &self, tcx: TyCtxt<'tcx>, - mods: &mut Self::Module, + module_llvm: &mut Self::Module, + module_name: &str, kind: AllocatorKind, has_alloc_error_handler: bool, ); diff --git a/compiler/rustc_codegen_ssa/src/traits/builder.rs b/compiler/rustc_codegen_ssa/src/traits/builder.rs index afb8ee3c40..e7da96f0ad 100644 --- a/compiler/rustc_codegen_ssa/src/traits/builder.rs +++ b/compiler/rustc_codegen_ssa/src/traits/builder.rs @@ -16,11 +16,9 @@ use crate::MemFlags; use rustc_middle::ty::layout::{HasParamEnv, TyAndLayout}; use rustc_middle::ty::Ty; use rustc_span::Span; -use rustc_target::abi::{Abi, Align, Scalar, Size}; +use rustc_target::abi::{Abi, Align, Scalar, Size, WrappingRange}; use rustc_target::spec::HasTargetSpec; -use std::ops::Range; - #[derive(Copy, Clone)] pub enum OverflowOp { Add, @@ -126,13 +124,13 @@ pub trait BuilderMethods<'a, 'tcx>: fn from_immediate(&mut self, val: Self::Value) -> Self::Value; fn to_immediate(&mut self, val: Self::Value, layout: TyAndLayout<'_>) -> Self::Value { - if let Abi::Scalar(ref scalar) = layout.abi { + if let Abi::Scalar(scalar) = layout.abi { self.to_immediate_scalar(val, scalar) } else { val } } - fn to_immediate_scalar(&mut self, val: Self::Value, scalar: &Scalar) -> Self::Value; + fn to_immediate_scalar(&mut self, val: Self::Value, scalar: Scalar) -> Self::Value; fn alloca(&mut self, ty: Self::Type, align: Align) -> Self::Value; fn dynamic_alloca(&mut self, ty: Self::Type, align: Align) -> Self::Value; @@ -158,7 +156,7 @@ pub trait BuilderMethods<'a, 'tcx>: dest: PlaceRef<'tcx, Self::Value>, ) -> Self; - fn range_metadata(&mut self, load: Self::Value, range: Range); + fn range_metadata(&mut self, load: Self::Value, range: WrappingRange); fn nonnull_metadata(&mut self, load: Self::Value); fn store(&mut self, val: Self::Value, ptr: Self::Value, align: Align) -> Self::Value; diff --git a/compiler/rustc_codegen_ssa/src/traits/consts.rs b/compiler/rustc_codegen_ssa/src/traits/consts.rs index 20f6618712..5260b7cc33 100644 --- a/compiler/rustc_codegen_ssa/src/traits/consts.rs +++ b/compiler/rustc_codegen_ssa/src/traits/consts.rs @@ -28,7 +28,7 @@ pub trait ConstMethods<'tcx>: BackendTypes { fn const_data_from_alloc(&self, alloc: &Allocation) -> Self::Value; - fn scalar_to_backend(&self, cv: Scalar, layout: &abi::Scalar, llty: Self::Type) -> Self::Value; + fn scalar_to_backend(&self, cv: Scalar, layout: abi::Scalar, llty: Self::Type) -> Self::Value; fn from_const_alloc( &self, layout: TyAndLayout<'tcx>, diff --git a/compiler/rustc_codegen_ssa/src/traits/debuginfo.rs b/compiler/rustc_codegen_ssa/src/traits/debuginfo.rs index 3e66d711d2..e700afc448 100644 --- a/compiler/rustc_codegen_ssa/src/traits/debuginfo.rs +++ b/compiler/rustc_codegen_ssa/src/traits/debuginfo.rs @@ -1,13 +1,18 @@ use super::BackendTypes; use crate::mir::debuginfo::{FunctionDebugContext, VariableKind}; use rustc_middle::mir; -use rustc_middle::ty::{Instance, Ty}; +use rustc_middle::ty::{Instance, PolyExistentialTraitRef, Ty}; use rustc_span::{SourceFile, Span, Symbol}; use rustc_target::abi::call::FnAbi; use rustc_target::abi::Size; pub trait DebugInfoMethods<'tcx>: BackendTypes { - fn create_vtable_metadata(&self, ty: Ty<'tcx>, vtable: Self::Value); + fn create_vtable_metadata( + &self, + ty: Ty<'tcx>, + trait_ref: Option>, + vtable: Self::Value, + ); /// Creates the function-specific debug context. /// diff --git a/compiler/rustc_const_eval/Cargo.toml b/compiler/rustc_const_eval/Cargo.toml new file mode 100644 index 0000000000..4ed908a383 --- /dev/null +++ b/compiler/rustc_const_eval/Cargo.toml @@ -0,0 +1,26 @@ +[package] +name = "rustc_const_eval" +version = "0.0.0" +edition = "2021" + +[lib] +doctest = false + +[dependencies] +tracing = "0.1" +rustc_apfloat = { path = "../rustc_apfloat" } +rustc_ast = { path = "../rustc_ast" } +rustc_attr = { path = "../rustc_attr" } +rustc_data_structures = { path = "../rustc_data_structures" } +rustc_errors = { path = "../rustc_errors" } +rustc_hir = { path = "../rustc_hir" } +rustc_index = { path = "../rustc_index" } +rustc_infer = { path = "../rustc_infer" } +rustc_macros = { path = "../rustc_macros" } +rustc_middle = { path = "../rustc_middle" } +rustc_mir_dataflow = { path = "../rustc_mir_dataflow" } +rustc_query_system = { path = "../rustc_query_system" } +rustc_session = { path = "../rustc_session" } +rustc_target = { path = "../rustc_target" } +rustc_trait_selection = { path = "../rustc_trait_selection" } +rustc_span = { path = "../rustc_span" } diff --git a/compiler/rustc_mir/src/const_eval/error.rs b/compiler/rustc_const_eval/src/const_eval/error.rs similarity index 100% rename from compiler/rustc_mir/src/const_eval/error.rs rename to compiler/rustc_const_eval/src/const_eval/error.rs diff --git a/compiler/rustc_mir/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs similarity index 98% rename from compiler/rustc_mir/src/const_eval/eval_queries.rs rename to compiler/rustc_const_eval/src/const_eval/eval_queries.rs index dc6a6b0b9f..57af0ff071 100644 --- a/compiler/rustc_mir/src/const_eval/eval_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs @@ -5,17 +5,18 @@ use crate::interpret::{ Immediate, InternKind, InterpCx, InterpResult, MPlaceTy, MemoryKind, OpTy, RefTracking, Scalar, ScalarMaybeUninit, StackPopCleanup, }; -use crate::util::pretty::display_allocation; use rustc_errors::ErrorReported; use rustc_hir::def::DefKind; use rustc_middle::mir; use rustc_middle::mir::interpret::ErrorHandled; +use rustc_middle::mir::pretty::display_allocation; use rustc_middle::traits::Reveal; +use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::{self, subst::Subst, TyCtxt}; use rustc_span::source_map::Span; -use rustc_target::abi::{Abi, LayoutOf}; +use rustc_target::abi::Abi; use std::borrow::Cow; use std::convert::TryInto; @@ -50,10 +51,11 @@ fn eval_body_using_ecx<'mir, 'tcx>( assert!(!layout.is_unsized()); let ret = ecx.allocate(layout, MemoryKind::Stack)?; - let name = - with_no_trimmed_paths(|| ty::tls::with(|tcx| tcx.def_path_str(cid.instance.def_id()))); - let prom = cid.promoted.map_or_else(String::new, |p| format!("::promoted[{:?}]", p)); - trace!("eval_body_using_ecx: pushing stack frame for global: {}{}", name, prom); + trace!( + "eval_body_using_ecx: pushing stack frame for global: {}{}", + with_no_trimmed_paths(|| ty::tls::with(|tcx| tcx.def_path_str(cid.instance.def_id()))), + cid.promoted.map_or_else(String::new, |p| format!("::promoted[{:?}]", p)) + ); ecx.push_stack_frame( cid.instance, diff --git a/compiler/rustc_mir/src/const_eval/fn_queries.rs b/compiler/rustc_const_eval/src/const_eval/fn_queries.rs similarity index 66% rename from compiler/rustc_mir/src/const_eval/fn_queries.rs rename to compiler/rustc_const_eval/src/const_eval/fn_queries.rs index 40419a4d20..df4cc295fa 100644 --- a/compiler/rustc_mir/src/const_eval/fn_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/fn_queries.rs @@ -1,28 +1,11 @@ use rustc_hir as hir; -use rustc_hir::def_id::{DefId, LocalDefId}; +use rustc_hir::def_id::DefId; use rustc_middle::hir::map::blocks::FnLikeNode; use rustc_middle::ty::query::Providers; use rustc_middle::ty::TyCtxt; use rustc_span::symbol::Symbol; use rustc_target::spec::abi::Abi; -/// Whether the `def_id` counts as const fn in your current crate, considering all active -/// feature gates -pub fn is_const_fn(tcx: TyCtxt<'_>, def_id: DefId) -> bool { - tcx.is_const_fn_raw(def_id) - && match is_unstable_const_fn(tcx, def_id) { - Some(feature_name) => { - // has a `rustc_const_unstable` attribute, check whether the user enabled the - // corresponding feature gate. - tcx.features().declared_lib_features.iter().any(|&(sym, _)| sym == feature_name) - } - // functions without const stability are either stable user written - // const fn or the user is using feature gates and we thus don't - // care what they do - None => true, - } -} - /// Whether the `def_id` is an unstable const fn and what feature gate is necessary to enable it pub fn is_unstable_const_fn(tcx: TyCtxt<'_>, def_id: DefId) -> Option { if tcx.is_const_fn_raw(def_id) { @@ -34,8 +17,14 @@ pub fn is_unstable_const_fn(tcx: TyCtxt<'_>, def_id: DefId) -> Option { } pub fn is_parent_const_impl_raw(tcx: TyCtxt<'_>, hir_id: hir::HirId) -> bool { - let parent_id = tcx.hir().get_parent_did(hir_id); - if !parent_id.is_top_level_module() { is_const_impl_raw(tcx, parent_id) } else { false } + let parent_id = tcx.hir().get_parent_node(hir_id); + matches!( + tcx.hir().get(parent_id), + hir::Node::Item(hir::Item { + kind: hir::ItemKind::Impl(hir::Impl { constness: hir::Constness::Const, .. }), + .. + }) + ) } /// Checks whether the function has a `const` modifier or, in case it is an intrinsic, whether @@ -70,21 +59,8 @@ fn is_const_fn_raw(tcx: TyCtxt<'_>, def_id: DefId) -> bool { } } -/// Checks whether the given item is an `impl` that has a `const` modifier. -fn is_const_impl_raw(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool { - let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); - let node = tcx.hir().get(hir_id); - matches!( - node, - hir::Node::Item(hir::Item { - kind: hir::ItemKind::Impl(hir::Impl { constness: hir::Constness::Const, .. }), - .. - }) - ) -} - fn is_promotable_const_fn(tcx: TyCtxt<'_>, def_id: DefId) -> bool { - is_const_fn(tcx, def_id) + tcx.is_const_fn(def_id) && match tcx.lookup_const_stability(def_id) { Some(stab) => { if cfg!(debug_assertions) && stab.promotable { @@ -103,10 +79,5 @@ fn is_promotable_const_fn(tcx: TyCtxt<'_>, def_id: DefId) -> bool { } pub fn provide(providers: &mut Providers) { - *providers = Providers { - is_const_fn_raw, - is_const_impl_raw: |tcx, def_id| is_const_impl_raw(tcx, def_id.expect_local()), - is_promotable_const_fn, - ..*providers - }; + *providers = Providers { is_const_fn_raw, is_promotable_const_fn, ..*providers }; } diff --git a/compiler/rustc_mir/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs similarity index 89% rename from compiler/rustc_mir/src/const_eval/machine.rs rename to compiler/rustc_const_eval/src/const_eval/machine.rs index 8a90686b90..202c9cad8e 100644 --- a/compiler/rustc_mir/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -26,22 +26,48 @@ impl<'mir, 'tcx> InterpCx<'mir, 'tcx, CompileTimeInterpreter<'mir, 'tcx>> { /// "Intercept" a function call to a panic-related function /// because we have something special to do for it. /// If this returns successfully (`Ok`), the function should just be evaluated normally. - fn hook_panic_fn( + fn hook_special_const_fn( &mut self, instance: ty::Instance<'tcx>, args: &[OpTy<'tcx>], + is_const_fn: bool, ) -> InterpResult<'tcx, Option>> { // The list of functions we handle here must be in sync with - // `is_lang_panic_fn` in `transform/check_consts/mod.rs`. + // `is_lang_special_const_fn` in `transform/check_consts/mod.rs`. let def_id = instance.def_id(); + + if is_const_fn { + if Some(def_id) == self.tcx.lang_items().const_eval_select() { + // redirect to const_eval_select_ct + if let Some(const_eval_select) = self.tcx.lang_items().const_eval_select_ct() { + return Ok(Some( + ty::Instance::resolve( + *self.tcx, + ty::ParamEnv::reveal_all(), + const_eval_select, + instance.substs, + ) + .unwrap() + .unwrap(), + )); + } + } + return Ok(None); + } + if Some(def_id) == self.tcx.lang_items().panic_fn() || Some(def_id) == self.tcx.lang_items().panic_str() + || Some(def_id) == self.tcx.lang_items().panic_display() || Some(def_id) == self.tcx.lang_items().begin_panic_fn() { - // &str + // &str or &&str assert!(args.len() == 1); - let msg_place = self.deref_operand(&args[0])?; + let mut msg_place = self.deref_operand(&args[0])?; + while msg_place.layout.ty.is_ref() { + msg_place = self.deref_operand(&msg_place.into())?; + } + let msg = Symbol::intern(self.read_str(&msg_place)?); let span = self.find_closest_untracked_caller_location(); let (file, line, col) = self.location_triple_for_span(span); @@ -250,31 +276,31 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, // Only check non-glue functions if let ty::InstanceDef::Item(def) = instance.def { + let mut is_const_fn = true; + // Execution might have wandered off into other crates, so we cannot do a stability- // sensitive check here. But we can at least rule out functions that are not const // at all. if !ecx.tcx.is_const_fn_raw(def.did) { // allow calling functions marked with #[default_method_body_is_const]. if !ecx.tcx.has_attr(def.did, sym::default_method_body_is_const) { - // Some functions we support even if they are non-const -- but avoid testing - // that for const fn! - if let Some(new_instance) = ecx.hook_panic_fn(instance, args)? { - // We call another const fn instead. - return Self::find_mir_or_eval_fn( - ecx, - new_instance, - _abi, - args, - _ret, - _unwind, - ); - } else { - // We certainly do *not* want to actually call the fn - // though, so be sure we return here. - throw_unsup_format!("calling non-const function `{}`", instance) - } + is_const_fn = false; } } + + // Some functions we support even if they are non-const -- but avoid testing + // that for const fn! + // `const_eval_select` is a const fn because it must use const trait bounds. + if let Some(new_instance) = ecx.hook_special_const_fn(instance, args, is_const_fn)? { + // We call another const fn instead. + return Self::find_mir_or_eval_fn(ecx, new_instance, _abi, args, _ret, _unwind); + } + + if !is_const_fn { + // We certainly do *not* want to actually call the fn + // though, so be sure we return here. + throw_unsup_format!("calling non-const function `{}`", instance) + } } // This is a const fn. Call it. Ok(Some(ecx.load_mir(instance.def, None)?)) diff --git a/compiler/rustc_mir/src/const_eval/mod.rs b/compiler/rustc_const_eval/src/const_eval/mod.rs similarity index 100% rename from compiler/rustc_mir/src/const_eval/mod.rs rename to compiler/rustc_const_eval/src/const_eval/mod.rs diff --git a/compiler/rustc_mir/src/interpret/cast.rs b/compiler/rustc_const_eval/src/interpret/cast.rs similarity index 99% rename from compiler/rustc_mir/src/interpret/cast.rs rename to compiler/rustc_const_eval/src/interpret/cast.rs index 6f18009cf4..4c4b0bd2d1 100644 --- a/compiler/rustc_mir/src/interpret/cast.rs +++ b/compiler/rustc_const_eval/src/interpret/cast.rs @@ -5,9 +5,9 @@ use rustc_apfloat::{Float, FloatConvert}; use rustc_middle::mir::interpret::{InterpResult, PointerArithmetic, Scalar}; use rustc_middle::mir::CastKind; use rustc_middle::ty::adjustment::PointerCast; -use rustc_middle::ty::layout::{IntegerExt, TyAndLayout}; +use rustc_middle::ty::layout::{IntegerExt, LayoutOf, TyAndLayout}; use rustc_middle::ty::{self, FloatTy, Ty, TypeAndMut}; -use rustc_target::abi::{Integer, LayoutOf, Variants}; +use rustc_target::abi::{Integer, Variants}; use super::{ util::ensure_monomorphic_enough, FnVal, ImmTy, Immediate, InterpCx, Machine, OpTy, PlaceTy, diff --git a/compiler/rustc_mir/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs similarity index 97% rename from compiler/rustc_mir/src/interpret/eval_context.rs rename to compiler/rustc_const_eval/src/interpret/eval_context.rs index c6003d87f3..cf084faade 100644 --- a/compiler/rustc_mir/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs @@ -6,23 +6,23 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_hir::{self as hir, def_id::DefId, definitions::DefPathData}; use rustc_index::vec::IndexVec; use rustc_macros::HashStable; -use rustc_middle::ich::StableHashingContext; use rustc_middle::mir; -use rustc_middle::ty::layout::{self, TyAndLayout}; +use rustc_middle::ty::layout::{self, LayoutError, LayoutOf, LayoutOfHelpers, TyAndLayout}; use rustc_middle::ty::{ self, query::TyCtxtAt, subst::SubstsRef, ParamEnv, Ty, TyCtxt, TypeFoldable, }; +use rustc_mir_dataflow::storage::AlwaysLiveLocals; +use rustc_query_system::ich::StableHashingContext; use rustc_session::Limit; use rustc_span::{Pos, Span}; -use rustc_target::abi::{Align, HasDataLayout, LayoutOf, Size, TargetDataLayout}; +use rustc_target::abi::{Align, HasDataLayout, Size, TargetDataLayout}; use super::{ - AllocId, GlobalId, Immediate, InterpResult, MPlaceTy, Machine, MemPlace, MemPlaceMeta, Memory, - MemoryKind, Operand, Place, PlaceTy, Pointer, Provenance, Scalar, ScalarMaybeUninit, - StackPopJump, + AllocId, GlobalId, Immediate, InterpErrorInfo, InterpResult, MPlaceTy, Machine, MemPlace, + MemPlaceMeta, Memory, MemoryKind, Operand, Place, PlaceTy, Pointer, Provenance, Scalar, + ScalarMaybeUninit, StackPopJump, }; use crate::transform::validate::equal_up_to_regions; -use crate::util::storage::AlwaysLiveLocals; pub struct InterpCx<'mir, 'tcx, M: Machine<'mir, 'tcx>> { /// Stores the `Machine` instance. @@ -313,15 +313,22 @@ where } } -impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> LayoutOf<'tcx> for InterpCx<'mir, 'tcx, M> { - type Ty = Ty<'tcx>; - type TyAndLayout = InterpResult<'tcx, TyAndLayout<'tcx>>; +impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> LayoutOfHelpers<'tcx> for InterpCx<'mir, 'tcx, M> { + type LayoutOfResult = InterpResult<'tcx, TyAndLayout<'tcx>>; #[inline] - fn layout_of(&self, ty: Ty<'tcx>) -> Self::TyAndLayout { - self.tcx - .layout_of(self.param_env.and(ty)) - .map_err(|layout| err_inval!(Layout(layout)).into()) + fn layout_tcx_at_span(&self) -> Span { + self.tcx.span + } + + #[inline] + fn handle_layout_err( + &self, + err: LayoutError<'tcx>, + _: Span, + _: Ty<'tcx>, + ) -> InterpErrorInfo<'tcx> { + err_inval!(Layout(err)).into() } } diff --git a/compiler/rustc_mir/src/interpret/intern.rs b/compiler/rustc_const_eval/src/interpret/intern.rs similarity index 99% rename from compiler/rustc_mir/src/interpret/intern.rs rename to compiler/rustc_const_eval/src/interpret/intern.rs index f2457d11d9..84e7940839 100644 --- a/compiler/rustc_mir/src/interpret/intern.rs +++ b/compiler/rustc_const_eval/src/interpret/intern.rs @@ -420,7 +420,7 @@ impl<'mir, 'tcx: 'mir, M: super::intern::CompileTimeMachine<'mir, 'tcx, !>> /// A helper function that allocates memory for the layout given and gives you access to mutate /// it. Once your own mutation code is done, the backing `Allocation` is removed from the /// current `Memory` and returned. - pub(crate) fn intern_with_temp_alloc( + pub fn intern_with_temp_alloc( &mut self, layout: TyAndLayout<'tcx>, f: impl FnOnce( diff --git a/compiler/rustc_mir/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs similarity index 96% rename from compiler/rustc_mir/src/interpret/intrinsics.rs rename to compiler/rustc_const_eval/src/interpret/intrinsics.rs index bfab886b6e..698742fe98 100644 --- a/compiler/rustc_mir/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -11,10 +11,11 @@ use rustc_middle::mir::{ BinOp, }; use rustc_middle::ty; +use rustc_middle::ty::layout::LayoutOf as _; use rustc_middle::ty::subst::SubstsRef; use rustc_middle::ty::{Ty, TyCtxt}; use rustc_span::symbol::{sym, Symbol}; -use rustc_target::abi::{Abi, Align, LayoutOf as _, Primitive, Size}; +use rustc_target::abi::{Abi, Align, Primitive, Size}; use super::{ util::ensure_monomorphic_enough, CheckInAllocMsg, ImmTy, InterpCx, Machine, OpTy, PlaceTy, @@ -61,15 +62,10 @@ crate fn eval_nullary_intrinsic<'tcx>( ensure_monomorphic_enough(tcx, tp_ty)?; ConstValue::from_bool(tp_ty.needs_drop(tcx, param_env)) } - sym::min_align_of | sym::pref_align_of => { + sym::pref_align_of => { // Correctly handles non-monomorphic calls, so there is no need for ensure_monomorphic_enough. let layout = tcx.layout_of(param_env.and(tp_ty)).map_err(|e| err_inval!(Layout(e)))?; - let n = match name { - sym::pref_align_of => layout.align.pref.bytes(), - sym::min_align_of => layout.align.abi.bytes(), - _ => bug!(), - }; - ConstValue::from_machine_usize(n, &tcx) + ConstValue::from_machine_usize(layout.align.pref.bytes(), &tcx) } sym::type_id => { ensure_monomorphic_enough(tcx, tp_ty)?; @@ -159,17 +155,14 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { self.write_scalar(Scalar::from_machine_usize(result, self), dest)?; } - sym::min_align_of - | sym::pref_align_of + sym::pref_align_of | sym::needs_drop | sym::type_id | sym::type_name | sym::variant_count => { let gid = GlobalId { instance, promoted: None }; let ty = match intrinsic_name { - sym::min_align_of | sym::pref_align_of | sym::variant_count => { - self.tcx.types.usize - } + sym::pref_align_of | sym::variant_count => self.tcx.types.usize, sym::needs_drop => self.tcx.types.bool, sym::type_id => self.tcx.types.u64, sym::type_name => self.tcx.mk_static_str(), @@ -193,7 +186,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let val = self.read_scalar(&args[0])?.check_init()?; let bits = val.to_bits(layout_of.size)?; let kind = match layout_of.abi { - Abi::Scalar(ref scalar) => scalar.value, + Abi::Scalar(scalar) => scalar.value, _ => span_bug!( self.cur_span(), "{} called on invalid type {:?}", @@ -233,7 +226,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { &r, )?; let val = if overflowed { - let num_bits = l.layout.size.bits(); + let size = l.layout.size; + let num_bits = size.bits(); if l.layout.abi.is_signed() { // For signed ints the saturated value depends on the sign of the first // term since the sign of the second term can be inferred from this and @@ -258,10 +252,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // unsigned if is_add { // max unsigned - Scalar::from_uint( - u128::MAX >> (128 - num_bits), - Size::from_bits(num_bits), - ) + Scalar::from_uint(size.unsigned_int_max(), Size::from_bits(num_bits)) } else { // underflow to 0 Scalar::from_uint(0u128, Size::from_bits(num_bits)) diff --git a/compiler/rustc_mir/src/interpret/intrinsics/caller_location.rs b/compiler/rustc_const_eval/src/interpret/intrinsics/caller_location.rs similarity index 99% rename from compiler/rustc_mir/src/interpret/intrinsics/caller_location.rs rename to compiler/rustc_const_eval/src/interpret/intrinsics/caller_location.rs index 022129b2a2..d4cbba1802 100644 --- a/compiler/rustc_mir/src/interpret/intrinsics/caller_location.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics/caller_location.rs @@ -3,9 +3,9 @@ use std::convert::TryFrom; use rustc_ast::Mutability; use rustc_hir::lang_items::LangItem; use rustc_middle::mir::TerminatorKind; +use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::subst::Subst; use rustc_span::{Span, Symbol}; -use rustc_target::abi::LayoutOf; use crate::interpret::{ intrinsics::{InterpCx, Machine}, diff --git a/compiler/rustc_mir/src/interpret/intrinsics/type_name.rs b/compiler/rustc_const_eval/src/interpret/intrinsics/type_name.rs similarity index 100% rename from compiler/rustc_mir/src/interpret/intrinsics/type_name.rs rename to compiler/rustc_const_eval/src/interpret/intrinsics/type_name.rs diff --git a/compiler/rustc_mir/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs similarity index 100% rename from compiler/rustc_mir/src/interpret/machine.rs rename to compiler/rustc_const_eval/src/interpret/machine.rs diff --git a/compiler/rustc_mir/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs similarity index 99% rename from compiler/rustc_mir/src/interpret/memory.rs rename to compiler/rustc_const_eval/src/interpret/memory.rs index 4d13274a12..b8b6ff9375 100644 --- a/compiler/rustc_mir/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -15,6 +15,7 @@ use std::ptr; use rustc_ast::Mutability; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_middle::mir::display_allocation; use rustc_middle::ty::{Instance, ParamEnv, TyCtxt}; use rustc_target::abi::{Align, HasDataLayout, Size, TargetDataLayout}; @@ -23,7 +24,6 @@ use super::{ InterpResult, Machine, MayLeak, Pointer, PointerArithmetic, Provenance, Scalar, ScalarMaybeUninit, }; -use crate::util::pretty; #[derive(Debug, PartialEq, Copy, Clone)] pub enum MemoryKind { @@ -851,7 +851,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> std::fmt::Debug for DumpAllocs<'a, for alloc_id in alloc.relocations().values().map(|tag| tag.get_alloc_id()) { allocs_to_print.push_back(alloc_id); } - write!(fmt, "{}", pretty::display_allocation(tcx, alloc)) + write!(fmt, "{}", display_allocation(tcx, alloc)) } let mut allocs_to_print: VecDeque<_> = self.allocs.iter().copied().collect(); diff --git a/compiler/rustc_mir/src/interpret/mod.rs b/compiler/rustc_const_eval/src/interpret/mod.rs similarity index 100% rename from compiler/rustc_mir/src/interpret/mod.rs rename to compiler/rustc_const_eval/src/interpret/mod.rs diff --git a/compiler/rustc_mir/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs similarity index 98% rename from compiler/rustc_mir/src/interpret/operand.rs rename to compiler/rustc_const_eval/src/interpret/operand.rs index 4afce2b6b8..b6682b13ed 100644 --- a/compiler/rustc_mir/src/interpret/operand.rs +++ b/compiler/rustc_const_eval/src/interpret/operand.rs @@ -7,11 +7,11 @@ use std::fmt::Write; use rustc_errors::ErrorReported; use rustc_hir::def::Namespace; use rustc_macros::HashStable; -use rustc_middle::ty::layout::{PrimitiveExt, TyAndLayout}; +use rustc_middle::ty::layout::{LayoutOf, PrimitiveExt, TyAndLayout}; use rustc_middle::ty::print::{FmtPrinter, PrettyPrinter, Printer}; use rustc_middle::ty::{ConstInt, Ty}; use rustc_middle::{mir, ty}; -use rustc_target::abi::{Abi, HasDataLayout, LayoutOf, Size, TagEncoding}; +use rustc_target::abi::{Abi, HasDataLayout, Size, TagEncoding}; use rustc_target::abi::{VariantIdx, Variants}; use super::{ @@ -274,11 +274,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let scalar = alloc.read_scalar(alloc_range(Size::ZERO, mplace.layout.size))?; Ok(Some(ImmTy { imm: scalar.into(), layout: mplace.layout })) } - Abi::ScalarPair(ref a, ref b) => { + Abi::ScalarPair(a, b) => { // We checked `ptr_align` above, so all fields will have the alignment they need. // We would anyway check against `ptr_align.restrict_for_offset(b_offset)`, // which `ptr.offset(b_offset)` cannot possibly fail to satisfy. - let (a, b) = (&a.value, &b.value); + let (a, b) = (a.value, b.value); let (a_size, b_size) = (a.size(self), b.size(self)); let b_offset = a_size.align_to(b.align(self).abi); assert!(b_offset.bytes() > 0); // we later use the offset to tell apart the fields @@ -296,7 +296,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { /// Note that for a given layout, this operation will either always fail or always /// succeed! Whether it succeeds depends on whether the layout can be represented /// in an `Immediate`, not on which data is stored there currently. - pub(crate) fn try_read_immediate( + pub fn try_read_immediate( &self, src: &OpTy<'tcx, M::PointerTag>, ) -> InterpResult<'tcx, Result, MPlaceTy<'tcx, M::PointerTag>>> { @@ -547,7 +547,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // in patterns via the `const_eval` module /// The `val` and `layout` are assumed to already be in our interpreter /// "universe" (param_env). - crate fn const_to_op( + pub fn const_to_op( &self, val: &ty::Const<'tcx>, layout: Option>, @@ -566,7 +566,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } } - crate fn mir_const_to_op( + pub fn mir_const_to_op( &self, val: &mir::ConstantKind<'tcx>, layout: Option>, @@ -618,6 +618,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } /// Read discriminant, return the runtime value as well as the variant index. + /// Can also legally be called on non-enums (e.g. through the discriminant_value intrinsic)! pub fn read_discriminant( &self, op: &OpTy<'tcx, M::PointerTag>, @@ -648,7 +649,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { }; return Ok((discr, index)); } - Variants::Multiple { ref tag, ref tag_encoding, tag_field, .. } => { + Variants::Multiple { tag, ref tag_encoding, tag_field, .. } => { (tag, tag_encoding, tag_field) } }; diff --git a/compiler/rustc_mir/src/interpret/operator.rs b/compiler/rustc_const_eval/src/interpret/operator.rs similarity index 99% rename from compiler/rustc_mir/src/interpret/operator.rs rename to compiler/rustc_const_eval/src/interpret/operator.rs index 79b493d74e..ac000b1bb5 100644 --- a/compiler/rustc_mir/src/interpret/operator.rs +++ b/compiler/rustc_const_eval/src/interpret/operator.rs @@ -3,8 +3,8 @@ use std::convert::TryFrom; use rustc_apfloat::Float; use rustc_middle::mir; use rustc_middle::mir::interpret::{InterpResult, Scalar}; -use rustc_middle::ty::{self, layout::TyAndLayout, FloatTy, Ty}; -use rustc_target::abi::LayoutOf; +use rustc_middle::ty::layout::{LayoutOf, TyAndLayout}; +use rustc_middle::ty::{self, FloatTy, Ty}; use super::{ImmTy, Immediate, InterpCx, Machine, PlaceTy}; diff --git a/compiler/rustc_mir/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs similarity index 97% rename from compiler/rustc_mir/src/interpret/place.rs rename to compiler/rustc_const_eval/src/interpret/place.rs index afad9716b3..d425b84bda 100644 --- a/compiler/rustc_mir/src/interpret/place.rs +++ b/compiler/rustc_const_eval/src/interpret/place.rs @@ -8,10 +8,10 @@ use std::hash::Hash; use rustc_ast::Mutability; use rustc_macros::HashStable; use rustc_middle::mir; -use rustc_middle::ty::layout::{PrimitiveExt, TyAndLayout}; +use rustc_middle::ty::layout::{LayoutOf, PrimitiveExt, TyAndLayout}; use rustc_middle::ty::{self, Ty}; use rustc_target::abi::{Abi, Align, FieldsShape, TagEncoding}; -use rustc_target::abi::{HasDataLayout, LayoutOf, Size, VariantIdx, Variants}; +use rustc_target::abi::{HasDataLayout, Size, VariantIdx, Variants}; use super::{ alloc_range, mir_assign_valid_types, AllocId, AllocRef, AllocRefMut, CheckInAllocMsg, @@ -752,7 +752,7 @@ where // We would anyway check against `ptr_align.restrict_for_offset(b_offset)`, // which `ptr.offset(b_offset)` cannot possibly fail to satisfy. let (a, b) = match dest.layout.abi { - Abi::ScalarPair(ref a, ref b) => (&a.value, &b.value), + Abi::ScalarPair(a, b) => (a.value, b.value), _ => span_bug!( self.cur_span(), "write_immediate_to_mplace: invalid ScalarPair layout: {:#?}", @@ -988,10 +988,23 @@ where variant_index: VariantIdx, dest: &PlaceTy<'tcx, M::PointerTag>, ) -> InterpResult<'tcx> { + // This must be an enum or generator. + match dest.layout.ty.kind() { + ty::Adt(adt, _) => assert!(adt.is_enum()), + ty::Generator(..) => {} + _ => span_bug!( + self.cur_span(), + "write_discriminant called on non-variant-type (neither enum nor generator)" + ), + } // Layout computation excludes uninhabited variants from consideration // therefore there's no way to represent those variants in the given layout. + // Essentially, uninhabited variants do not have a tag that corresponds to their + // discriminant, so we cannot do anything here. + // When evaluating we will always error before even getting here, but ConstProp 'executes' + // dead code, so we cannot ICE here. if dest.layout.for_variant(self, variant_index).abi.is_uninhabited() { - throw_ub!(Unreachable); + throw_ub!(UninhabitedEnumVariantWritten) } match dest.layout.variants { @@ -1000,7 +1013,7 @@ where } Variants::Multiple { tag_encoding: TagEncoding::Direct, - tag: ref tag_layout, + tag: tag_layout, tag_field, .. } => { @@ -1022,7 +1035,7 @@ where Variants::Multiple { tag_encoding: TagEncoding::Niche { dataful_variant, ref niche_variants, niche_start }, - tag: ref tag_layout, + tag: tag_layout, tag_field, .. } => { diff --git a/compiler/rustc_mir/src/interpret/step.rs b/compiler/rustc_const_eval/src/interpret/step.rs similarity index 90% rename from compiler/rustc_mir/src/interpret/step.rs rename to compiler/rustc_const_eval/src/interpret/step.rs index f2a8a067df..e6037d561d 100644 --- a/compiler/rustc_mir/src/interpret/step.rs +++ b/compiler/rustc_const_eval/src/interpret/step.rs @@ -4,7 +4,7 @@ use rustc_middle::mir; use rustc_middle::mir::interpret::{InterpResult, Scalar}; -use rustc_target::abi::LayoutOf; +use rustc_middle::ty::layout::LayoutOf; use super::{InterpCx, Machine}; @@ -76,7 +76,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { /// Runs the interpretation logic for the given `mir::Statement` at the current frame and /// statement counter. This also moves the statement counter forward. - crate fn statement(&mut self, stmt: &mir::Statement<'tcx>) -> InterpResult<'tcx> { + pub fn statement(&mut self, stmt: &mir::Statement<'tcx>) -> InterpResult<'tcx> { info!("{:?}", stmt); use rustc_middle::mir::StatementKind::*; @@ -197,12 +197,17 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } Aggregate(ref kind, ref operands) => { + // active_field_index is for union initialization. let (dest, active_field_index) = match **kind { mir::AggregateKind::Adt(adt_def, variant_index, _, _, active_field_index) => { self.write_discriminant(variant_index, &dest)?; if adt_def.is_enum() { - (self.place_downcast(&dest, variant_index)?, active_field_index) + assert!(active_field_index.is_none()); + (self.place_downcast(&dest, variant_index)?, None) } else { + if active_field_index.is_some() { + assert_eq!(operands.len(), 1); + } (dest, active_field_index) } } @@ -211,12 +216,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { for (i, operand) in operands.iter().enumerate() { let op = self.eval_operand(operand, None)?; - // Ignore zero-sized fields. - if !op.layout.is_zst() { - let field_index = active_field_index.unwrap_or(i); - let field_dest = self.place_field(&dest, field_index)?; - self.copy_op(&op, &field_dest)?; - } + let field_index = active_field_index.unwrap_or(i); + let field_dest = self.place_field(&dest, field_index)?; + self.copy_op(&op, &field_dest)?; } } @@ -253,7 +255,6 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } Len(place) => { - // FIXME(CTFE): don't allow computing the length of arrays in const eval let src = self.eval_place(place)?; let mplace = self.force_allocation(&src)?; let len = mplace.len(self)?; @@ -270,18 +271,29 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { M::box_alloc(self, &dest)?; } - NullaryOp(mir::NullOp::SizeOf, ty) => { + NullaryOp(null_op, ty) => { let ty = self.subst_from_current_frame_and_normalize_erasing_regions(ty); let layout = self.layout_of(ty)?; if layout.is_unsized() { // FIXME: This should be a span_bug (#80742) self.tcx.sess.delay_span_bug( self.frame().current_span(), - &format!("SizeOf nullary MIR operator called for unsized type {}", ty), + &format!("Nullary MIR operator called for unsized type {}", ty), ); throw_inval!(SizeOfUnsizedType(ty)); } - self.write_scalar(Scalar::from_machine_usize(layout.size.bytes(), self), &dest)?; + let val = match null_op { + mir::NullOp::SizeOf => layout.size.bytes(), + mir::NullOp::AlignOf => layout.align.abi.bytes(), + mir::NullOp::Box => unreachable!(), + }; + self.write_scalar(Scalar::from_machine_usize(val, self), &dest)?; + } + + ShallowInitBox(ref operand, _) => { + let src = self.eval_operand(operand, None)?; + let v = self.read_immediate(&src)?; + self.write_immediate(*v, &dest)?; } Cast(cast_kind, ref operand, cast_ty) => { diff --git a/compiler/rustc_mir/src/interpret/terminator.rs b/compiler/rustc_const_eval/src/interpret/terminator.rs similarity index 97% rename from compiler/rustc_mir/src/interpret/terminator.rs rename to compiler/rustc_const_eval/src/interpret/terminator.rs index 63496045e0..8d3544d434 100644 --- a/compiler/rustc_mir/src/interpret/terminator.rs +++ b/compiler/rustc_const_eval/src/interpret/terminator.rs @@ -2,13 +2,13 @@ use std::borrow::Cow; use std::convert::TryFrom; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; -use rustc_middle::ty::layout::{self, TyAndLayout}; +use rustc_middle::ty::layout::{self, LayoutOf as _, TyAndLayout}; use rustc_middle::ty::Instance; use rustc_middle::{ mir, ty::{self, Ty}, }; -use rustc_target::abi::{self, LayoutOf as _}; +use rustc_target::abi; use rustc_target::spec::abi::Abi; use super::{ @@ -187,17 +187,14 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { return false; } // Compare layout - match (&caller.abi, &callee.abi) { + match (caller.abi, callee.abi) { // Different valid ranges are okay (once we enforce validity, // that will take care to make it UB to leave the range, just // like for transmute). - (abi::Abi::Scalar(ref caller), abi::Abi::Scalar(ref callee)) => { - caller.value == callee.value + (abi::Abi::Scalar(caller), abi::Abi::Scalar(callee)) => caller.value == callee.value, + (abi::Abi::ScalarPair(caller1, caller2), abi::Abi::ScalarPair(callee1, callee2)) => { + caller1.value == callee1.value && caller2.value == callee2.value } - ( - abi::Abi::ScalarPair(ref caller1, ref caller2), - abi::Abi::ScalarPair(ref callee1, ref callee2), - ) => caller1.value == callee1.value && caller2.value == callee2.value, // Be conservative _ => false, } @@ -234,7 +231,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } /// Call this function -- pushing the stack frame and initializing the arguments. - fn eval_fn_call( + pub(crate) fn eval_fn_call( &mut self, fn_val: FnVal<'tcx, M::ExtraFnVal>, caller_abi: Abi, diff --git a/compiler/rustc_mir/src/interpret/traits.rs b/compiler/rustc_const_eval/src/interpret/traits.rs similarity index 100% rename from compiler/rustc_mir/src/interpret/traits.rs rename to compiler/rustc_const_eval/src/interpret/traits.rs diff --git a/compiler/rustc_mir/src/interpret/util.rs b/compiler/rustc_const_eval/src/interpret/util.rs similarity index 96% rename from compiler/rustc_mir/src/interpret/util.rs rename to compiler/rustc_const_eval/src/interpret/util.rs index eb0fdebb66..a16388d5de 100644 --- a/compiler/rustc_mir/src/interpret/util.rs +++ b/compiler/rustc_const_eval/src/interpret/util.rs @@ -35,7 +35,8 @@ where ty::Closure(def_id, substs) | ty::Generator(def_id, substs, ..) | ty::FnDef(def_id, substs) => { - let unused_params = self.tcx.unused_generic_params(def_id); + let instance = ty::InstanceDef::Item(ty::WithOptConstParam::unknown(def_id)); + let unused_params = self.tcx.unused_generic_params(instance); for (index, subst) in substs.into_iter().enumerate() { let index = index .try_into() diff --git a/compiler/rustc_mir/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs similarity index 97% rename from compiler/rustc_mir/src/interpret/validity.rs rename to compiler/rustc_const_eval/src/interpret/validity.rs index 2bb2f88725..fc69770bf6 100644 --- a/compiler/rustc_mir/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -12,11 +12,9 @@ use rustc_data_structures::fx::FxHashSet; use rustc_hir as hir; use rustc_middle::mir::interpret::InterpError; use rustc_middle::ty; -use rustc_middle::ty::layout::TyAndLayout; +use rustc_middle::ty::layout::{LayoutOf, TyAndLayout}; use rustc_span::symbol::{sym, Symbol}; -use rustc_target::abi::{ - Abi, LayoutOf, Scalar as ScalarAbi, Size, VariantIdx, Variants, WrappingRange, -}; +use rustc_target::abi::{Abi, Scalar as ScalarAbi, Size, VariantIdx, Variants, WrappingRange}; use std::hash::Hash; @@ -79,7 +77,7 @@ macro_rules! throw_validation_failure { /// macro_rules! try_validation { ($e:expr, $where:expr, - $( $( $p:pat )|+ => { $( $what_fmt:expr ),+ } $( expected { $( $expected_fmt:expr ),+ } )? ),+ $(,)? + $( $( $p:pat_param )|+ => { $( $what_fmt:expr ),+ } $( expected { $( $expected_fmt:expr ),+ } )? ),+ $(,)? ) => {{ match $e { Ok(x) => x, @@ -620,40 +618,38 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' fn visit_scalar( &mut self, op: &OpTy<'tcx, M::PointerTag>, - scalar_layout: &ScalarAbi, + scalar_layout: ScalarAbi, ) -> InterpResult<'tcx> { - let value = self.read_scalar(op)?; - let valid_range = scalar_layout.valid_range.clone(); - let WrappingRange { start: lo, end: hi } = valid_range; - // Determine the allowed range - // `max_hi` is as big as the size fits - let max_hi = u128::MAX >> (128 - op.layout.size.bits()); - assert!(hi <= max_hi); - // We could also write `(hi + 1) % (max_hi + 1) == lo` but `max_hi + 1` overflows for `u128` - if (lo == 0 && hi == max_hi) || (hi + 1 == lo) { + if scalar_layout.valid_range.is_full_for(op.layout.size) { // Nothing to check return Ok(()); } - // At least one value is excluded. Get the bits. + // At least one value is excluded. + let valid_range = scalar_layout.valid_range; + let WrappingRange { start, end } = valid_range; + let max_value = op.layout.size.unsigned_int_max(); + assert!(end <= max_value); + // Determine the allowed range + let value = self.read_scalar(op)?; let value = try_validation!( value.check_init(), self.path, err_ub!(InvalidUninitBytes(None)) => { "{}", value } - expected { "something {}", wrapping_range_format(valid_range, max_hi) }, + expected { "something {}", wrapping_range_format(valid_range, max_value) }, ); let bits = match value.try_to_int() { Err(_) => { // So this is a pointer then, and casting to an int failed. // Can only happen during CTFE. let ptr = self.ecx.scalar_to_ptr(value); - if lo == 1 && hi == max_hi { + if start == 1 && end == max_value { // Only null is the niche. So make sure the ptr is NOT null. if self.ecx.memory.ptr_may_be_null(ptr) { throw_validation_failure!(self.path, { "a potentially null pointer" } expected { "something that cannot possibly fail to be {}", - wrapping_range_format(valid_range, max_hi) + wrapping_range_format(valid_range, max_value) } ) } @@ -665,7 +661,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' { "a pointer" } expected { "something that cannot possibly fail to be {}", - wrapping_range_format(valid_range, max_hi) + wrapping_range_format(valid_range, max_value) } ) } @@ -678,7 +674,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' } else { throw_validation_failure!(self.path, { "{}", bits } - expected { "something {}", wrapping_range_format(valid_range, max_hi) } + expected { "something {}", wrapping_range_format(valid_range, max_value) } ) } } @@ -788,7 +784,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M> { "a value of uninhabited type {:?}", op.layout.ty } ); } - Abi::Scalar(ref scalar_layout) => { + Abi::Scalar(scalar_layout) => { self.visit_scalar(op, scalar_layout)?; } Abi::ScalarPair { .. } | Abi::Vector { .. } => { diff --git a/compiler/rustc_mir/src/interpret/visitor.rs b/compiler/rustc_const_eval/src/interpret/visitor.rs similarity index 100% rename from compiler/rustc_mir/src/interpret/visitor.rs rename to compiler/rustc_const_eval/src/interpret/visitor.rs diff --git a/compiler/rustc_mir/src/lib.rs b/compiler/rustc_const_eval/src/lib.rs similarity index 66% rename from compiler/rustc_mir/src/lib.rs rename to compiler/rustc_const_eval/src/lib.rs index e439a247c7..7ce40b319a 100644 --- a/compiler/rustc_mir/src/lib.rs +++ b/compiler/rustc_const_eval/src/lib.rs @@ -4,32 +4,24 @@ Rust MIR: a lowered representation of Rust. */ -#![feature(nll)] -#![feature(in_band_lifetimes)] -#![feature(array_windows)] #![feature(assert_matches)] -#![cfg_attr(bootstrap, feature(bindings_after_at))] #![feature(bool_to_option)] #![feature(box_patterns)] +#![feature(control_flow_enum)] #![feature(crate_visibility_modifier)] #![feature(decl_macro)] #![feature(exact_size_is_empty)] -#![feature(format_args_capture)] +#![feature(in_band_lifetimes)] #![feature(iter_zip)] -#![feature(never_type)] #![feature(map_try_insert)] #![feature(min_specialization)] #![feature(slice_ptr_get)] -#![feature(trusted_len)] -#![feature(try_blocks)] -#![feature(associated_type_defaults)] -#![feature(stmt_expr_attributes)] -#![feature(trait_alias)] #![feature(option_get_or_insert_default)] -#![feature(once_cell)] -#![feature(control_flow_enum)] -#![feature(try_reserve)] -#![feature(try_reserve_kind)] +#![feature(never_type)] +#![feature(trait_alias)] +#![feature(trusted_len)] +#![feature(trusted_step)] +#![feature(try_blocks)] #![recursion_limit = "256"] #[macro_use] @@ -37,32 +29,18 @@ extern crate tracing; #[macro_use] extern crate rustc_middle; -mod borrow_check; pub mod const_eval; -pub mod dataflow; pub mod interpret; -pub mod monomorphize; -mod shim; pub mod transform; pub mod util; -// A public API provided for the Rust compiler consumers. -pub use self::borrow_check::consumers; - use rustc_middle::ty::query::Providers; pub fn provide(providers: &mut Providers) { - borrow_check::provide(providers); const_eval::provide(providers); - shim::provide(providers); - transform::provide(providers); - monomorphize::partitioning::provide(providers); - monomorphize::polymorphize::provide(providers); providers.eval_to_const_value_raw = const_eval::eval_to_const_value_raw_provider; providers.eval_to_allocation_raw = const_eval::eval_to_allocation_raw_provider; providers.const_caller_location = const_eval::const_caller_location; - providers.mir_callgraph_reachable = transform::inline::cycle::mir_callgraph_reachable; - providers.mir_inliner_callees = transform::inline::cycle::mir_inliner_callees; providers.destructure_const = |tcx, param_env_and_value| { let (param_env, value) = param_env_and_value.into_parts(); const_eval::destructure_const(tcx, param_env, value) diff --git a/compiler/rustc_mir/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs similarity index 95% rename from compiler/rustc_mir/src/transform/check_consts/check.rs rename to compiler/rustc_const_eval/src/transform/check_consts/check.rs index 0c38127682..d704c4335c 100644 --- a/compiler/rustc_mir/src/transform/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs @@ -12,6 +12,8 @@ use rustc_middle::ty::cast::CastTy; use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts}; use rustc_middle::ty::{self, adjustment::PointerCast, Instance, InstanceDef, Ty, TyCtxt}; use rustc_middle::ty::{Binder, TraitPredicate, TraitRef}; +use rustc_mir_dataflow::impls::MaybeMutBorrowedLocals; +use rustc_mir_dataflow::{self, Analysis}; use rustc_span::{sym, Span, Symbol}; use rustc_trait_selection::traits::error_reporting::InferCtxtExt; use rustc_trait_selection::traits::{self, SelectionContext, TraitEngine}; @@ -20,26 +22,24 @@ use std::mem; use std::ops::Deref; use super::ops::{self, NonConstOp, Status}; -use super::qualifs::{self, CustomEq, HasMutInterior, NeedsDrop}; +use super::qualifs::{self, CustomEq, HasMutInterior, NeedsNonConstDrop}; use super::resolver::FlowSensitiveAnalysis; -use super::{is_lang_panic_fn, ConstCx, Qualif}; +use super::{is_lang_panic_fn, is_lang_special_const_fn, ConstCx, Qualif}; use crate::const_eval::is_unstable_const_fn; -use crate::dataflow::impls::MaybeMutBorrowedLocals; -use crate::dataflow::{self, Analysis}; // We are using `MaybeMutBorrowedLocals` as a proxy for whether an item may have been mutated // through a pointer prior to the given point. This is okay even though `MaybeMutBorrowedLocals` // kills locals upon `StorageDead` because a local will never be used after a `StorageDead`. type IndirectlyMutableResults<'mir, 'tcx> = - dataflow::ResultsCursor<'mir, 'tcx, MaybeMutBorrowedLocals<'mir, 'tcx>>; + rustc_mir_dataflow::ResultsCursor<'mir, 'tcx, MaybeMutBorrowedLocals<'mir, 'tcx>>; type QualifResults<'mir, 'tcx, Q> = - dataflow::ResultsCursor<'mir, 'tcx, FlowSensitiveAnalysis<'mir, 'mir, 'tcx, Q>>; + rustc_mir_dataflow::ResultsCursor<'mir, 'tcx, FlowSensitiveAnalysis<'mir, 'mir, 'tcx, Q>>; #[derive(Default)] pub struct Qualifs<'mir, 'tcx> { has_mut_interior: Option>, - needs_drop: Option>, + needs_drop: Option>, indirectly_mutable: Option>, } @@ -80,14 +80,14 @@ impl Qualifs<'mir, 'tcx> { location: Location, ) -> bool { let ty = ccx.body.local_decls[local].ty; - if !NeedsDrop::in_any_value_of_ty(ccx, ty) { + if !NeedsNonConstDrop::in_any_value_of_ty(ccx, ty) { return false; } let needs_drop = self.needs_drop.get_or_insert_with(|| { let ConstCx { tcx, body, .. } = *ccx; - FlowSensitiveAnalysis::new(NeedsDrop, ccx) + FlowSensitiveAnalysis::new(NeedsNonConstDrop, ccx) .into_engine(tcx, &body) .iterate_to_fixpoint() .into_results_cursor(&body) @@ -259,7 +259,9 @@ impl Checker<'mir, 'tcx> { self.check_local_or_return_ty(return_ty.skip_binder(), RETURN_PLACE); } - self.visit_body(&body); + if !tcx.has_attr(def_id.to_def_id(), sym::rustc_do_not_const_check) { + self.visit_body(&body); + } // Ensure that the end result is `Sync` in a non-thread local `static`. let should_check_for_sync = self.const_kind() @@ -384,11 +386,11 @@ impl Checker<'mir, 'tcx> { match pred.skip_binder() { ty::ExistentialPredicate::AutoTrait(_) | ty::ExistentialPredicate::Projection(_) => { - self.check_op(ops::ty::TraitBound(kind)) + self.check_op(ops::ty::DynTrait(kind)) } ty::ExistentialPredicate::Trait(trait_ref) => { if Some(trait_ref.def_id) != self.tcx.lang_items().sized_trait() { - self.check_op(ops::ty::TraitBound(kind)) + self.check_op(ops::ty::DynTrait(kind)) } } } @@ -648,8 +650,9 @@ impl Visitor<'tcx> for Checker<'mir, 'tcx> { } } - Rvalue::NullaryOp(NullOp::SizeOf, _) => {} + Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf, _) => {} Rvalue::NullaryOp(NullOp::Box, _) => self.check_op(ops::HeapAllocation), + Rvalue::ShallowInitBox(_, _) => {} Rvalue::UnaryOp(_, ref operand) => { let ty = operand.ty(self.body, self.tcx); @@ -885,8 +888,10 @@ impl Visitor<'tcx> for Checker<'mir, 'tcx> { } // At this point, we are calling a function, `callee`, whose `DefId` is known... - if is_lang_panic_fn(tcx, callee) { - self.check_op(ops::Panic); + if is_lang_special_const_fn(tcx, callee) { + // `begin_panic` and `panic_display` are generic functions that accept + // types other than str. Check to enforce that only str can be used in + // const-eval. // const-eval of the `begin_panic` fn assumes the argument is `&str` if Some(callee) == tcx.lang_items().begin_panic_fn() { @@ -896,6 +901,23 @@ impl Visitor<'tcx> for Checker<'mir, 'tcx> { } } + // const-eval of the `panic_display` fn assumes the argument is `&&str` + if Some(callee) == tcx.lang_items().panic_display() { + match args[0].ty(&self.ccx.body.local_decls, tcx).kind() { + ty::Ref(_, ty, _) if matches!(ty.kind(), ty::Ref(_, ty, _) if ty.is_str()) => + {} + _ => self.check_op(ops::PanicNonStr), + } + } + + if is_lang_panic_fn(tcx, callee) { + // run stability check on non-panic special const fns. + return; + } + } + + if Some(callee) == tcx.lang_items().exchange_malloc_fn() { + self.check_op(ops::HeapAllocation); return; } @@ -988,12 +1010,12 @@ impl Visitor<'tcx> for Checker<'mir, 'tcx> { let mut err_span = self.span; - // Check to see if the type of this place can ever have a drop impl. If not, this - // `Drop` terminator is frivolous. - let ty_needs_drop = - dropped_place.ty(self.body, self.tcx).ty.needs_drop(self.tcx, self.param_env); + let ty_needs_non_const_drop = qualifs::NeedsNonConstDrop::in_any_value_of_ty( + self.ccx, + dropped_place.ty(self.body, self.tcx).ty, + ); - if !ty_needs_drop { + if !ty_needs_non_const_drop { return; } diff --git a/compiler/rustc_mir/src/transform/check_consts/mod.rs b/compiler/rustc_const_eval/src/transform/check_consts/mod.rs similarity index 92% rename from compiler/rustc_mir/src/transform/check_consts/mod.rs rename to compiler/rustc_const_eval/src/transform/check_consts/mod.rs index a5cb0f4e14..0a852282f8 100644 --- a/compiler/rustc_mir/src/transform/check_consts/mod.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/mod.rs @@ -74,16 +74,23 @@ impl ConstCx<'mir, 'tcx> { /// Returns `true` if this `DefId` points to one of the official `panic` lang items. pub fn is_lang_panic_fn(tcx: TyCtxt<'tcx>, def_id: DefId) -> bool { - // We can allow calls to these functions because `hook_panic_fn` in - // `const_eval/machine.rs` ensures the calls are handled specially. - // Keep in sync with what that function handles! Some(def_id) == tcx.lang_items().panic_fn() || Some(def_id) == tcx.lang_items().panic_str() + || Some(def_id) == tcx.lang_items().panic_display() || Some(def_id) == tcx.lang_items().begin_panic_fn() || Some(def_id) == tcx.lang_items().panic_fmt() || Some(def_id) == tcx.lang_items().begin_panic_fmt() } +/// Returns `true` if this `DefId` points to one of the lang items that will be handled differently +/// in const_eval. +pub fn is_lang_special_const_fn(tcx: TyCtxt<'tcx>, def_id: DefId) -> bool { + // We can allow calls to these functions because `hook_special_const_fn` in + // `const_eval/machine.rs` ensures the calls are handled specially. + // Keep in sync with what that function handles! + is_lang_panic_fn(tcx, def_id) || Some(def_id) == tcx.lang_items().const_eval_select() +} + pub fn rustc_allow_const_fn_unstable( tcx: TyCtxt<'tcx>, def_id: DefId, diff --git a/compiler/rustc_mir/src/transform/check_consts/ops.rs b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs similarity index 92% rename from compiler/rustc_mir/src/transform/check_consts/ops.rs rename to compiler/rustc_const_eval/src/transform/check_consts/ops.rs index 8923d989b2..230d023efb 100644 --- a/compiler/rustc_mir/src/transform/check_consts/ops.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs @@ -102,7 +102,7 @@ impl NonConstOp for FnCallUnstable { ); if ccx.is_const_stable_const_fn() { - err.help("Const-stable functions can only call other const-stable functions"); + err.help("const-stable functions can only call other const-stable functions"); } else if ccx.tcx.sess.is_nightly_build() { if let Some(feature) = feature { err.help(&format!( @@ -368,23 +368,6 @@ impl NonConstOp for MutDeref { } } -#[derive(Debug)] -pub struct Panic; -impl NonConstOp for Panic { - fn status_in_item(&self, _: &ConstCx<'_, '_>) -> Status { - Status::Unstable(sym::const_panic) - } - - fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { - feature_err( - &ccx.tcx.sess.parse_sess, - sym::const_panic, - span, - &format!("panicking in {}s is unstable", ccx.const_kind()), - ) - } -} - /// A call to a `panic()` lang item where the first argument is _not_ a `&str`. #[derive(Debug)] pub struct PanicNonStr; @@ -407,7 +390,7 @@ impl NonConstOp for RawPtrComparison { let mut err = ccx .tcx .sess - .struct_span_err(span, "pointers cannot be reliably compared during const eval."); + .struct_span_err(span, "pointers cannot be reliably compared during const eval"); err.note( "see issue #53020 \ for more information", @@ -443,7 +426,7 @@ impl NonConstOp for RawPtrToIntCast { let mut err = ccx .tcx .sess - .struct_span_err(span, "pointers cannot be cast to integers during const eval."); + .struct_span_err(span, "pointers cannot be cast to integers during const eval"); err.note("at compile-time, pointers do not have an integer value"); err.note( "avoiding this restriction via `transmute`, `union`, or raw pointers leads to compile-time undefined behavior", @@ -599,12 +582,60 @@ pub mod ty { } fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { - feature_err( + let mut err = feature_err( &ccx.tcx.sess.parse_sess, sym::const_fn_trait_bound, span, "trait bounds other than `Sized` on const fn parameters are unstable", - ) + ); + + match ccx.fn_sig() { + Some(fn_sig) if !fn_sig.span.contains(span) => { + err.span_label(fn_sig.span, "function declared as const here"); + } + _ => {} + } + + err + } + } + + #[derive(Debug)] + pub struct DynTrait(pub mir::LocalKind); + impl NonConstOp for DynTrait { + fn importance(&self) -> DiagnosticImportance { + match self.0 { + mir::LocalKind::Var | mir::LocalKind::Temp => DiagnosticImportance::Secondary, + mir::LocalKind::ReturnPointer | mir::LocalKind::Arg => { + DiagnosticImportance::Primary + } + } + } + + fn status_in_item(&self, ccx: &ConstCx<'_, '_>) -> Status { + if ccx.const_kind() != hir::ConstContext::ConstFn { + Status::Allowed + } else { + Status::Unstable(sym::const_fn_trait_bound) + } + } + + fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { + let mut err = feature_err( + &ccx.tcx.sess.parse_sess, + sym::const_fn_trait_bound, + span, + "trait objects in const fn are unstable", + ); + + match ccx.fn_sig() { + Some(fn_sig) if !fn_sig.span.contains(span) => { + err.span_label(fn_sig.span, "function declared as const here"); + } + _ => {} + } + + err } } diff --git a/compiler/rustc_mir/src/transform/check_consts/post_drop_elaboration.rs b/compiler/rustc_const_eval/src/transform/check_consts/post_drop_elaboration.rs similarity index 90% rename from compiler/rustc_mir/src/transform/check_consts/post_drop_elaboration.rs rename to compiler/rustc_const_eval/src/transform/check_consts/post_drop_elaboration.rs index b08ce21903..1a8c8b1c78 100644 --- a/compiler/rustc_mir/src/transform/check_consts/post_drop_elaboration.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/post_drop_elaboration.rs @@ -1,11 +1,11 @@ use rustc_middle::mir::visit::Visitor; use rustc_middle::mir::{self, BasicBlock, Location}; use rustc_middle::ty::TyCtxt; -use rustc_span::Span; +use rustc_span::{symbol::sym, Span}; use super::check::Qualifs; use super::ops::{self, NonConstOp}; -use super::qualifs::{NeedsDrop, Qualif}; +use super::qualifs::{NeedsNonConstDrop, Qualif}; use super::ConstCx; /// Returns `true` if we should use the more precise live drop checker that runs after drop @@ -30,6 +30,10 @@ pub fn check_live_drops(tcx: TyCtxt<'tcx>, body: &mir::Body<'tcx>) { return; } + if tcx.has_attr(def_id.to_def_id(), sym::rustc_do_not_const_check) { + return; + } + let ccx = ConstCx { body, tcx, const_kind, param_env: tcx.param_env(def_id) }; if !checking_enabled(&ccx) { return; @@ -78,10 +82,10 @@ impl Visitor<'tcx> for CheckLiveDrops<'mir, 'tcx> { match &terminator.kind { mir::TerminatorKind::Drop { place: dropped_place, .. } => { let dropped_ty = dropped_place.ty(self.body, self.tcx).ty; - if !NeedsDrop::in_any_value_of_ty(self.ccx, dropped_ty) { - bug!( - "Drop elaboration left behind a Drop for a type that does not need dropping" - ); + if !NeedsNonConstDrop::in_any_value_of_ty(self.ccx, dropped_ty) { + // Instead of throwing a bug, we just return here. This is because we have to + // run custom `const Drop` impls. + return; } if dropped_place.is_indirect() { diff --git a/compiler/rustc_mir/src/transform/check_consts/qualifs.rs b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs similarity index 82% rename from compiler/rustc_mir/src/transform/check_consts/qualifs.rs rename to compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs index 413a9638eb..5eb7d7a91c 100644 --- a/compiler/rustc_mir/src/transform/check_consts/qualifs.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs @@ -3,10 +3,14 @@ //! See the `Qualif` trait for more info. use rustc_errors::ErrorReported; +use rustc_hir as hir; +use rustc_infer::infer::TyCtxtInferExt; use rustc_middle::mir::*; use rustc_middle::ty::{self, subst::SubstsRef, AdtDef, Ty}; use rustc_span::DUMMY_SP; -use rustc_trait_selection::traits; +use rustc_trait_selection::traits::{ + self, ImplSource, Obligation, ObligationCause, SelectionContext, +}; use super::ConstCx; @@ -17,7 +21,7 @@ pub fn in_any_value_of_ty( ) -> ConstQualifs { ConstQualifs { has_mut_interior: HasMutInterior::in_any_value_of_ty(cx, ty), - needs_drop: NeedsDrop::in_any_value_of_ty(cx, ty), + needs_drop: NeedsNonConstDrop::in_any_value_of_ty(cx, ty), custom_eq: CustomEq::in_any_value_of_ty(cx, ty), error_occured, } @@ -97,22 +101,58 @@ impl Qualif for HasMutInterior { /// This must be ruled out (a) because we cannot run `Drop` during compile-time /// as that might not be a `const fn`, and (b) because implicit promotion would /// remove side-effects that occur as part of dropping that value. -pub struct NeedsDrop; +pub struct NeedsNonConstDrop; -impl Qualif for NeedsDrop { - const ANALYSIS_NAME: &'static str = "flow_needs_drop"; +impl Qualif for NeedsNonConstDrop { + const ANALYSIS_NAME: &'static str = "flow_needs_nonconst_drop"; const IS_CLEARED_ON_MOVE: bool = true; fn in_qualifs(qualifs: &ConstQualifs) -> bool { qualifs.needs_drop } - fn in_any_value_of_ty(cx: &ConstCx<'_, 'tcx>, ty: Ty<'tcx>) -> bool { - ty.needs_drop(cx.tcx, cx.param_env) + fn in_any_value_of_ty(cx: &ConstCx<'_, 'tcx>, mut ty: Ty<'tcx>) -> bool { + // Avoid selecting for simple cases. + match ty::util::needs_drop_components(ty, &cx.tcx.data_layout).as_deref() { + Ok([]) => return false, + Err(ty::util::AlwaysRequiresDrop) => return true, + // If we've got a single component, select with that + // to increase the chance that we hit the selection cache. + Ok([t]) => ty = t, + Ok([..]) => {} + } + + let drop_trait = if let Some(did) = cx.tcx.lang_items().drop_trait() { + did + } else { + // there is no way to define a type that needs non-const drop + // without having the lang item present. + return false; + }; + let trait_ref = + ty::TraitRef { def_id: drop_trait, substs: cx.tcx.mk_substs_trait(ty, &[]) }; + let obligation = Obligation::new( + ObligationCause::dummy(), + cx.param_env, + ty::Binder::dummy(ty::TraitPredicate { + trait_ref, + constness: ty::BoundConstness::ConstIfConst, + }), + ); + + let implsrc = cx.tcx.infer_ctxt().enter(|infcx| { + let mut selcx = SelectionContext::with_constness(&infcx, hir::Constness::Const); + selcx.select(&obligation) + }); + match implsrc { + Ok(Some(ImplSource::ConstDrop(_))) + | Ok(Some(ImplSource::Param(_, ty::BoundConstness::ConstIfConst))) => false, + _ => true, + } } fn in_adt_inherently(cx: &ConstCx<'_, 'tcx>, adt: &'tcx AdtDef, _: SubstsRef<'tcx>) -> bool { - adt.has_dtor(cx.tcx) + adt.has_non_const_dtor(cx.tcx) } } @@ -166,7 +206,8 @@ where Rvalue::Use(operand) | Rvalue::Repeat(operand, _) | Rvalue::UnaryOp(_, operand) - | Rvalue::Cast(_, operand, _) => in_operand::(cx, in_local, operand), + | Rvalue::Cast(_, operand, _) + | Rvalue::ShallowInitBox(operand, _) => in_operand::(cx, in_local, operand), Rvalue::BinaryOp(_, box (lhs, rhs)) | Rvalue::CheckedBinaryOp(_, box (lhs, rhs)) => { in_operand::(cx, in_local, lhs) || in_operand::(cx, in_local, rhs) diff --git a/compiler/rustc_mir/src/transform/check_consts/resolver.rs b/compiler/rustc_const_eval/src/transform/check_consts/resolver.rs similarity index 97% rename from compiler/rustc_mir/src/transform/check_consts/resolver.rs rename to compiler/rustc_const_eval/src/transform/check_consts/resolver.rs index a00301952b..8e1b69a1d7 100644 --- a/compiler/rustc_mir/src/transform/check_consts/resolver.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/resolver.rs @@ -9,7 +9,6 @@ use rustc_middle::mir::{self, BasicBlock, Local, Location}; use std::marker::PhantomData; use super::{qualifs, ConstCx, Qualif}; -use crate::dataflow; /// A `Visitor` that propagates qualifs between locals. This defines the transfer function of /// `FlowSensitiveAnalysis`. @@ -165,7 +164,7 @@ where } } -impl dataflow::AnalysisDomain<'tcx> for FlowSensitiveAnalysis<'_, '_, 'tcx, Q> +impl rustc_mir_dataflow::AnalysisDomain<'tcx> for FlowSensitiveAnalysis<'_, '_, 'tcx, Q> where Q: Qualif, { @@ -182,7 +181,7 @@ where } } -impl dataflow::Analysis<'tcx> for FlowSensitiveAnalysis<'_, '_, 'tcx, Q> +impl rustc_mir_dataflow::Analysis<'tcx> for FlowSensitiveAnalysis<'_, '_, 'tcx, Q> where Q: Qualif, { diff --git a/compiler/rustc_const_eval/src/transform/mod.rs b/compiler/rustc_const_eval/src/transform/mod.rs new file mode 100644 index 0000000000..38c28f3493 --- /dev/null +++ b/compiler/rustc_const_eval/src/transform/mod.rs @@ -0,0 +1,5 @@ +pub mod check_consts; +pub mod promote_consts; +pub mod validate; + +pub use rustc_middle::mir::MirPass; diff --git a/compiler/rustc_mir/src/transform/promote_consts.rs b/compiler/rustc_const_eval/src/transform/promote_consts.rs similarity index 98% rename from compiler/rustc_mir/src/transform/promote_consts.rs rename to compiler/rustc_const_eval/src/transform/promote_consts.rs index 1b43670ba3..7cfe3d7f80 100644 --- a/compiler/rustc_mir/src/transform/promote_consts.rs +++ b/compiler/rustc_const_eval/src/transform/promote_consts.rs @@ -26,8 +26,7 @@ use rustc_index::vec::{Idx, IndexVec}; use std::cell::Cell; use std::{cmp, iter, mem}; -use crate::const_eval::{is_const_fn, is_unstable_const_fn}; -use crate::transform::check_consts::{is_lang_panic_fn, qualifs, ConstCx}; +use crate::transform::check_consts::{is_lang_special_const_fn, qualifs, ConstCx}; use crate::transform::MirPass; /// A `MirPass` for promotion. @@ -231,7 +230,7 @@ impl<'tcx> Validator<'_, 'tcx> { // We cannot promote things that need dropping, since the promoted value // would not get dropped. - if self.qualif_local::(place.local) { + if self.qualif_local::(place.local) { return Err(Unpromotable); } @@ -520,8 +519,11 @@ impl<'tcx> Validator<'_, 'tcx> { Rvalue::NullaryOp(op, _) => match op { NullOp::Box => return Err(Unpromotable), NullOp::SizeOf => {} + NullOp::AlignOf => {} }, + Rvalue::ShallowInitBox(_, _) => return Err(Unpromotable), + Rvalue::UnaryOp(op, operand) => { match op { // These operations can never fail. @@ -655,9 +657,7 @@ impl<'tcx> Validator<'_, 'tcx> { let is_const_fn = match *fn_ty.kind() { ty::FnDef(def_id, _) => { - is_const_fn(self.tcx, def_id) - || is_unstable_const_fn(self.tcx, def_id).is_some() - || is_lang_panic_fn(self.tcx, def_id) + self.tcx.is_const_fn_raw(def_id) || is_lang_special_const_fn(self.tcx, def_id) } _ => false, }; @@ -1058,7 +1058,7 @@ pub fn promote_candidates<'tcx>( /// This function returns `true` if the function being called in the array /// repeat expression is a `const` function. -crate fn is_const_fn_in_array_repeat_expression<'tcx>( +pub fn is_const_fn_in_array_repeat_expression<'tcx>( ccx: &ConstCx<'_, 'tcx>, place: &Place<'tcx>, body: &Body<'tcx>, @@ -1078,7 +1078,7 @@ crate fn is_const_fn_in_array_repeat_expression<'tcx>( if let ty::FnDef(def_id, _) = *literal.ty().kind() { if let Some((destination_place, _)) = destination { if destination_place == place { - if is_const_fn(ccx.tcx, def_id) { + if ccx.tcx.is_const_fn(def_id) { return true; } } diff --git a/compiler/rustc_mir/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs similarity index 98% rename from compiler/rustc_mir/src/transform/validate.rs rename to compiler/rustc_const_eval/src/transform/validate.rs index 835789069b..b09b2227f3 100644 --- a/compiler/rustc_mir/src/transform/validate.rs +++ b/compiler/rustc_const_eval/src/transform/validate.rs @@ -1,9 +1,5 @@ //! Validates the MIR to ensure that invariants are upheld. -use crate::dataflow::impls::MaybeStorageLive; -use crate::dataflow::{Analysis, ResultsCursor}; -use crate::util::storage::AlwaysLiveLocals; - use super::MirPass; use rustc_index::bit_set::BitSet; use rustc_infer::infer::TyCtxtInferExt; @@ -13,10 +9,13 @@ use rustc_middle::mir::visit::{PlaceContext, Visitor}; use rustc_middle::mir::{ AggregateKind, BasicBlock, Body, BorrowKind, Local, Location, MirPhase, Operand, PlaceElem, PlaceRef, ProjectionElem, Rvalue, SourceScope, Statement, StatementKind, Terminator, - TerminatorKind, + TerminatorKind, START_BLOCK, }; use rustc_middle::ty::fold::BottomUpFolder; use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt, TypeFoldable}; +use rustc_mir_dataflow::impls::MaybeStorageLive; +use rustc_mir_dataflow::storage::AlwaysLiveLocals; +use rustc_mir_dataflow::{Analysis, ResultsCursor}; use rustc_target::abi::Size; #[derive(Copy, Clone, Debug)] @@ -131,6 +130,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } fn check_edge(&self, location: Location, bb: BasicBlock, edge_kind: EdgeKind) { + if bb == START_BLOCK { + self.fail(location, "start block must not have predecessors") + } if let Some(bb) = self.body.basic_blocks().get(bb) { let src = self.body.basic_blocks().get(location.block).unwrap(); match (src.is_cleanup, bb.is_cleanup, edge_kind) { diff --git a/compiler/rustc_mir/src/util/aggregate.rs b/compiler/rustc_const_eval/src/util/aggregate.rs similarity index 100% rename from compiler/rustc_mir/src/util/aggregate.rs rename to compiler/rustc_const_eval/src/util/aggregate.rs diff --git a/compiler/rustc_mir/src/util/alignment.rs b/compiler/rustc_const_eval/src/util/alignment.rs similarity index 100% rename from compiler/rustc_mir/src/util/alignment.rs rename to compiler/rustc_const_eval/src/util/alignment.rs diff --git a/compiler/rustc_mir/src/util/collect_writes.rs b/compiler/rustc_const_eval/src/util/collect_writes.rs similarity index 97% rename from compiler/rustc_mir/src/util/collect_writes.rs rename to compiler/rustc_const_eval/src/util/collect_writes.rs index ecf3b08a96..9c56fd722b 100644 --- a/compiler/rustc_mir/src/util/collect_writes.rs +++ b/compiler/rustc_const_eval/src/util/collect_writes.rs @@ -2,7 +2,7 @@ use rustc_middle::mir::visit::PlaceContext; use rustc_middle::mir::visit::Visitor; use rustc_middle::mir::{Body, Local, Location}; -crate trait FindAssignments { +pub trait FindAssignments { // Finds all statements that assign directly to local (i.e., X = ...) // and returns their locations. fn find_assignments(&self, local: Local) -> Vec; diff --git a/compiler/rustc_mir/src/util/find_self_call.rs b/compiler/rustc_const_eval/src/util/find_self_call.rs similarity index 100% rename from compiler/rustc_mir/src/util/find_self_call.rs rename to compiler/rustc_const_eval/src/util/find_self_call.rs diff --git a/compiler/rustc_const_eval/src/util/mod.rs b/compiler/rustc_const_eval/src/util/mod.rs new file mode 100644 index 0000000000..4a406f8bfd --- /dev/null +++ b/compiler/rustc_const_eval/src/util/mod.rs @@ -0,0 +1,8 @@ +pub mod aggregate; +mod alignment; +pub mod collect_writes; +mod find_self_call; + +pub use self::aggregate::expand_aggregate; +pub use self::alignment::is_disaligned; +pub use self::find_self_call::find_self_call; diff --git a/compiler/rustc_data_structures/Cargo.toml b/compiler/rustc_data_structures/Cargo.toml index bc13ca26e2..4996257012 100644 --- a/compiler/rustc_data_structures/Cargo.toml +++ b/compiler/rustc_data_structures/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustc_data_structures" version = "0.0.0" -edition = "2018" +edition = "2021" [lib] doctest = false diff --git a/compiler/rustc_data_structures/src/base_n.rs b/compiler/rustc_data_structures/src/base_n.rs index 3c7bea2712..81e2501ecb 100644 --- a/compiler/rustc_data_structures/src/base_n.rs +++ b/compiler/rustc_data_structures/src/base_n.rs @@ -14,7 +14,7 @@ const BASE_64: &[u8; MAX_BASE as usize] = #[inline] pub fn push_str(mut n: u128, base: usize, output: &mut String) { - debug_assert!(base >= 2 && base <= MAX_BASE); + debug_assert!((2..=MAX_BASE).contains(&base)); let mut s = [0u8; 128]; let mut index = 0; diff --git a/compiler/rustc_data_structures/src/graph/implementation/mod.rs b/compiler/rustc_data_structures/src/graph/implementation/mod.rs index 1aa7ac024d..9ff401c3c7 100644 --- a/compiler/rustc_data_structures/src/graph/implementation/mod.rs +++ b/compiler/rustc_data_structures/src/graph/implementation/mod.rs @@ -206,17 +206,11 @@ impl Graph { AdjacentEdges { graph: self, direction, next: first_edge } } - pub fn successor_nodes<'a>( - &'a self, - source: NodeIndex, - ) -> impl Iterator + 'a { + pub fn successor_nodes(&self, source: NodeIndex) -> impl Iterator + '_ { self.outgoing_edges(source).targets() } - pub fn predecessor_nodes<'a>( - &'a self, - target: NodeIndex, - ) -> impl Iterator + 'a { + pub fn predecessor_nodes(&self, target: NodeIndex) -> impl Iterator + '_ { self.incoming_edges(target).sources() } diff --git a/compiler/rustc_data_structures/src/graph/iterate/mod.rs b/compiler/rustc_data_structures/src/graph/iterate/mod.rs index 09b91083a6..1c6979dc48 100644 --- a/compiler/rustc_data_structures/src/graph/iterate/mod.rs +++ b/compiler/rustc_data_structures/src/graph/iterate/mod.rs @@ -48,7 +48,7 @@ fn post_order_walk( let node = frame.node; visited[node] = true; - while let Some(successor) = frame.iter.next() { + for successor in frame.iter.by_ref() { if !visited[successor] { stack.push(PostOrderFrame { node: successor, iter: graph.successors(successor) }); continue 'recurse; @@ -83,8 +83,58 @@ impl DepthFirstSearch<'graph, G> where G: ?Sized + DirectedGraph + WithNumNodes + WithSuccessors, { - pub fn new(graph: &'graph G, start_node: G::Node) -> Self { - Self { graph, stack: vec![start_node], visited: BitSet::new_empty(graph.num_nodes()) } + pub fn new(graph: &'graph G) -> Self { + Self { graph, stack: vec![], visited: BitSet::new_empty(graph.num_nodes()) } + } + + /// Version of `push_start_node` that is convenient for chained + /// use. + pub fn with_start_node(mut self, start_node: G::Node) -> Self { + self.push_start_node(start_node); + self + } + + /// Pushes another start node onto the stack. If the node + /// has not already been visited, then you will be able to + /// walk its successors (and so forth) after the current + /// contents of the stack are drained. If multiple start nodes + /// are added into the walk, then their mutual successors + /// will all be walked. You can use this method once the + /// iterator has been completely drained to add additional + /// start nodes. + pub fn push_start_node(&mut self, start_node: G::Node) { + if self.visited.insert(start_node) { + self.stack.push(start_node); + } + } + + /// Searches all nodes reachable from the current start nodes. + /// This is equivalent to just invoke `next` repeatedly until + /// you get a `None` result. + pub fn complete_search(&mut self) { + for _ in self {} + } + + /// Returns true if node has been visited thus far. + /// A node is considered "visited" once it is pushed + /// onto the internal stack; it may not yet have been yielded + /// from the iterator. This method is best used after + /// the iterator is completely drained. + pub fn visited(&self, node: G::Node) -> bool { + self.visited.contains(node) + } +} + +impl std::fmt::Debug for DepthFirstSearch<'_, G> +where + G: ?Sized + DirectedGraph + WithNumNodes + WithSuccessors, +{ + fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let mut f = fmt.debug_set(); + for n in self.visited.iter() { + f.entry(&n); + } + f.finish() } } diff --git a/compiler/rustc_data_structures/src/graph/iterate/tests.rs b/compiler/rustc_data_structures/src/graph/iterate/tests.rs index 0e038e88b2..c498c28933 100644 --- a/compiler/rustc_data_structures/src/graph/iterate/tests.rs +++ b/compiler/rustc_data_structures/src/graph/iterate/tests.rs @@ -20,3 +20,19 @@ fn is_cyclic() { assert!(!is_cyclic(&diamond_acyclic)); assert!(is_cyclic(&diamond_cyclic)); } + +#[test] +fn dfs() { + let graph = TestGraph::new(0, &[(0, 1), (0, 2), (1, 3), (2, 3), (3, 0)]); + + let result: Vec = DepthFirstSearch::new(&graph).with_start_node(0).collect(); + assert_eq!(result, vec![0, 2, 3, 1]); +} + +#[test] +fn dfs_debug() { + let graph = TestGraph::new(0, &[(0, 1), (0, 2), (1, 3), (2, 3), (3, 0)]); + let mut dfs = DepthFirstSearch::new(&graph).with_start_node(0); + dfs.complete_search(); + assert_eq!(format!("{{0, 1, 2, 3}}"), format!("{:?}", dfs)); +} diff --git a/compiler/rustc_data_structures/src/graph/mod.rs b/compiler/rustc_data_structures/src/graph/mod.rs index dff2285562..3560df6e5e 100644 --- a/compiler/rustc_data_structures/src/graph/mod.rs +++ b/compiler/rustc_data_structures/src/graph/mod.rs @@ -32,7 +32,7 @@ where where Self: WithNumNodes, { - iterate::DepthFirstSearch::new(self, from) + iterate::DepthFirstSearch::new(self).with_start_node(from) } } diff --git a/compiler/rustc_data_structures/src/graph/scc/mod.rs b/compiler/rustc_data_structures/src/graph/scc/mod.rs index e2cbb09ce5..b84f28b6a9 100644 --- a/compiler/rustc_data_structures/src/graph/scc/mod.rs +++ b/compiler/rustc_data_structures/src/graph/scc/mod.rs @@ -3,7 +3,7 @@ //! Also computes as the resulting DAG if each SCC is replaced with a //! node in the graph. This uses [Tarjan's algorithm]( //! https://en.wikipedia.org/wiki/Tarjan%27s_strongly_connected_components_algorithm) -//! that completes in *O(n)* time. +//! that completes in *O*(*n*) time. use crate::fx::FxHashSet; use crate::graph::vec_graph::VecGraph; @@ -405,6 +405,7 @@ where /// Call this method when `inspect_node` has returned `None`. Having the /// caller decide avoids mutual recursion between the two methods and allows /// us to maintain an allocated stack for nodes on the path between calls. + #[instrument(skip(self, initial), level = "debug")] fn walk_unvisited_node(&mut self, initial: G::Node) -> WalkReturn { struct VisitingNodeFrame { node: G::Node, @@ -451,7 +452,7 @@ where Some(iter) => iter, None => { // This None marks that we still have the initialize this node's frame. - debug!("walk_unvisited_node(depth = {:?}, node = {:?})", depth, node); + debug!(?depth, ?node); debug_assert!(matches!(self.node_states[node], NodeState::NotVisited)); @@ -478,10 +479,7 @@ where return_value.take().into_iter().map(|walk| (*successor_node, Some(walk))); let successor_walk = successors.by_ref().map(|successor_node| { - debug!( - "walk_unvisited_node: node = {:?} successor_ode = {:?}", - node, successor_node - ); + debug!(?node, ?successor_node); (successor_node, self.inspect_node(successor_node)) }); @@ -491,10 +489,7 @@ where // Track the minimum depth we can reach. assert!(successor_min_depth <= depth); if successor_min_depth < *min_depth { - debug!( - "walk_unvisited_node: node = {:?} successor_min_depth = {:?}", - node, successor_min_depth - ); + debug!(?node, ?successor_min_depth); *min_depth = successor_min_depth; *min_cycle_root = successor_node; } @@ -503,16 +498,13 @@ where Some(WalkReturn::Complete { scc_index: successor_scc_index }) => { // Push the completed SCC indices onto // the `successors_stack` for later. - debug!( - "walk_unvisited_node: node = {:?} successor_scc_index = {:?}", - node, successor_scc_index - ); + debug!(?node, ?successor_scc_index); successors_stack.push(successor_scc_index); } None => { let depth = depth + 1; - debug!("walk_node(depth = {:?}, node = {:?})", depth, successor_node); + debug!(?depth, ?successor_node); // Remember which node the return value will come from. frame.successor_node = successor_node; // Start a new stack frame the step into it. diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs index 18bc2f896f..94e115ed49 100644 --- a/compiler/rustc_data_structures/src/lib.rs +++ b/compiler/rustc_data_structures/src/lib.rs @@ -7,22 +7,20 @@ //! This API is completely unstable and subject to change. #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] -#![feature(allow_internal_unstable)] #![feature(array_windows)] #![feature(associated_type_bounds)] #![feature(auto_traits)] #![feature(bool_to_option)] -#![feature(const_panic)] +#![cfg_attr(bootstrap, feature(const_panic))] #![feature(control_flow_enum)] #![feature(core_intrinsics)] #![feature(extend_one)] #![feature(hash_raw_entry)] #![feature(in_band_lifetimes)] -#![feature(iter_map_while)] #![feature(maybe_uninit_uninit_array)] #![feature(min_specialization)] -#![cfg_attr(bootstrap, feature(min_type_alias_impl_trait))] -#![cfg_attr(not(bootstrap), feature(type_alias_impl_trait))] +#![feature(never_type)] +#![feature(type_alias_impl_trait)] #![feature(new_uninit)] #![feature(nll)] #![feature(once_cell)] diff --git a/compiler/rustc_data_structures/src/obligation_forest/mod.rs b/compiler/rustc_data_structures/src/obligation_forest/mod.rs index 25b7a84b3a..caf515b0d1 100644 --- a/compiler/rustc_data_structures/src/obligation_forest/mod.rs +++ b/compiler/rustc_data_structures/src/obligation_forest/mod.rs @@ -390,7 +390,7 @@ impl ObligationForest { .map(|(index, _node)| Error { error: error.clone(), backtrace: self.error_at(index) }) .collect(); - self.compress(|_| assert!(false)); + self.compress(|_| unreachable!()); errors } @@ -612,7 +612,7 @@ impl ObligationForest { fn compress(&mut self, mut outcome_cb: impl FnMut(&O)) { let orig_nodes_len = self.nodes.len(); let mut node_rewrites: Vec<_> = std::mem::take(&mut self.reused_node_vec); - debug_assert!(node_rewrites.is_empty()); + assert!(node_rewrites.is_empty()); node_rewrites.extend(0..orig_nodes_len); let mut dead_nodes = 0; @@ -623,13 +623,13 @@ impl ObligationForest { // self.nodes[0..index - dead_nodes] are the first remaining nodes // self.nodes[index - dead_nodes..index] are all dead // self.nodes[index..] are unchanged - for index in 0..orig_nodes_len { + for (index, node_rewrite) in node_rewrites.iter_mut().enumerate() { let node = &self.nodes[index]; match node.state.get() { NodeState::Pending | NodeState::Waiting => { if dead_nodes > 0 { self.nodes.swap(index, index - dead_nodes); - node_rewrites[index] -= dead_nodes; + *node_rewrite -= dead_nodes; } } NodeState::Done => { @@ -646,7 +646,7 @@ impl ObligationForest { } // Extract the success stories. outcome_cb(&node.obligation); - node_rewrites[index] = orig_nodes_len; + *node_rewrite = orig_nodes_len; dead_nodes += 1; } NodeState::Error => { @@ -655,7 +655,7 @@ impl ObligationForest { // check against. self.active_cache.remove(&node.obligation.as_cache_key()); self.insert_into_error_cache(index); - node_rewrites[index] = orig_nodes_len; + *node_rewrite = orig_nodes_len; dead_nodes += 1; } NodeState::Success => unreachable!(), diff --git a/compiler/rustc_data_structures/src/sharded.rs b/compiler/rustc_data_structures/src/sharded.rs index 14db71cb8f..417c61242a 100644 --- a/compiler/rustc_data_structures/src/sharded.rs +++ b/compiler/rustc_data_structures/src/sharded.rs @@ -1,6 +1,5 @@ use crate::fx::{FxHashMap, FxHasher}; use crate::sync::{Lock, LockGuard}; -use smallvec::SmallVec; use std::borrow::Borrow; use std::collections::hash_map::RawEntryMut; use std::hash::{Hash, Hasher}; @@ -37,24 +36,7 @@ impl Default for Sharded { impl Sharded { #[inline] pub fn new(mut value: impl FnMut() -> T) -> Self { - // Create a vector of the values we want - let mut values: SmallVec<[_; SHARDS]> = - (0..SHARDS).map(|_| CacheAligned(Lock::new(value()))).collect(); - - // Create an uninitialized array - let mut shards: mem::MaybeUninit<[CacheAligned>; SHARDS]> = - mem::MaybeUninit::uninit(); - - unsafe { - // Copy the values into our array - let first = shards.as_mut_ptr() as *mut CacheAligned>; - values.as_ptr().copy_to_nonoverlapping(first, SHARDS); - - // Ignore the content of the vector - values.set_len(0); - - Sharded { shards: shards.assume_init() } - } + Sharded { shards: [(); SHARDS].map(|()| CacheAligned(Lock::new(value()))) } } /// The shard is selected by hashing `val` with `FxHasher`. diff --git a/compiler/rustc_data_structures/src/sorted_map.rs b/compiler/rustc_data_structures/src/sorted_map.rs index 9a28f8f4e2..e80db0845a 100644 --- a/compiler/rustc_data_structures/src/sorted_map.rs +++ b/compiler/rustc_data_structures/src/sorted_map.rs @@ -9,7 +9,7 @@ mod index_map; pub use index_map::SortedIndexMultiMap; /// `SortedMap` is a data structure with similar characteristics as BTreeMap but -/// slightly different trade-offs: lookup, insertion, and removal are O(log(N)) +/// slightly different trade-offs: lookup, insertion, and removal are *O*(log(*n*)) /// and elements can be iterated in order cheaply. /// /// `SortedMap` can be faster than a `BTreeMap` for small sizes (<50) since it @@ -205,10 +205,10 @@ impl SortedMap { R: RangeBounds, { let start = match range.start_bound() { - Bound::Included(ref k) => match self.lookup_index_for(k) { + Bound::Included(k) => match self.lookup_index_for(k) { Ok(index) | Err(index) => index, }, - Bound::Excluded(ref k) => match self.lookup_index_for(k) { + Bound::Excluded(k) => match self.lookup_index_for(k) { Ok(index) => index + 1, Err(index) => index, }, @@ -216,11 +216,11 @@ impl SortedMap { }; let end = match range.end_bound() { - Bound::Included(ref k) => match self.lookup_index_for(k) { + Bound::Included(k) => match self.lookup_index_for(k) { Ok(index) => index + 1, Err(index) => index, }, - Bound::Excluded(ref k) => match self.lookup_index_for(k) { + Bound::Excluded(k) => match self.lookup_index_for(k) { Ok(index) | Err(index) => index, }, Bound::Unbounded => self.data.len(), 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 e92db9ea12..1395bb16e8 100644 --- a/compiler/rustc_data_structures/src/sorted_map/index_map.rs +++ b/compiler/rustc_data_structures/src/sorted_map/index_map.rs @@ -75,7 +75,7 @@ impl SortedIndexMultiMap { /// /// If there are multiple items that are equivalent to `key`, they will be yielded in /// insertion order. - pub fn get_by_key(&'a self, key: K) -> impl 'a + Iterator { + pub fn get_by_key(&self, key: K) -> impl Iterator { self.get_by_key_enumerated(key).map(|(_, v)| v) } @@ -84,7 +84,7 @@ 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(&'a self, key: K) -> impl '_ + Iterator { + pub fn get_by_key_enumerated(&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 e249886e9b..d4274e99f1 100644 --- a/compiler/rustc_data_structures/src/sso/map.rs +++ b/compiler/rustc_data_structures/src/sso/map.rs @@ -31,7 +31,7 @@ const SSO_ARRAY_SIZE: usize = 8; // // Missing HashMap API: // all hasher-related -// try_reserve (unstable) +// try_reserve // shrink_to (unstable) // drain_filter (unstable) // into_keys/into_values (unstable) @@ -257,11 +257,7 @@ impl SsoHashMap { pub fn remove(&mut self, key: &K) -> Option { match self { SsoHashMap::Array(array) => { - if let Some(index) = array.iter().position(|(k, _v)| k == key) { - Some(array.swap_remove(index).1) - } else { - None - } + array.iter().position(|(k, _v)| k == key).map(|index| array.swap_remove(index).1) } SsoHashMap::Map(map) => map.remove(key), } @@ -272,11 +268,7 @@ impl SsoHashMap { pub fn remove_entry(&mut self, key: &K) -> Option<(K, V)> { match self { SsoHashMap::Array(array) => { - if let Some(index) = array.iter().position(|(k, _v)| k == key) { - Some(array.swap_remove(index)) - } else { - None - } + array.iter().position(|(k, _v)| k == key).map(|index| array.swap_remove(index)) } SsoHashMap::Map(map) => map.remove_entry(key), } @@ -423,14 +415,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: &'a (K, V)) -> (&'a K, &'a V) { +fn adapt_array_ref_it(pair: &(K, V)) -> (&K, &V) { let (a, b) = pair; (a, b) } /// adapts Item of array mut reference iterator to Item of hashmap mut reference iterator. #[inline(always)] -fn adapt_array_mut_it(pair: &'a mut (K, V)) -> (&'a K, &'a mut V) { +fn adapt_array_mut_it(pair: &mut (K, V)) -> (&K, &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 23cff0206c..f71522d371 100644 --- a/compiler/rustc_data_structures/src/sso/set.rs +++ b/compiler/rustc_data_structures/src/sso/set.rs @@ -13,7 +13,7 @@ use super::map::SsoHashMap; // // Missing HashSet API: // all hasher-related -// try_reserve (unstable) +// try_reserve // shrink_to (unstable) // drain_filter (unstable) // replace @@ -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(&'a self) -> impl Iterator { + pub fn iter(&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 18b352cf3b..2e992e7622 100644 --- a/compiler/rustc_data_structures/src/stable_hasher.rs +++ b/compiler/rustc_data_structures/src/stable_hasher.rs @@ -209,6 +209,12 @@ impl_stable_hash_via_hash!(i128); impl_stable_hash_via_hash!(char); impl_stable_hash_via_hash!(()); +impl HashStable for ! { + fn hash_stable(&self, _ctx: &mut CTX, _hasher: &mut StableHasher) { + unreachable!() + } +} + impl HashStable for ::std::num::NonZeroU32 { fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { self.get().hash_stable(ctx, hasher) @@ -223,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 = unsafe { ::std::mem::transmute(*self) }; + let val: u32 = self.to_bits(); val.hash_stable(ctx, hasher); } } impl HashStable for f64 { fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { - let val: u64 = unsafe { ::std::mem::transmute(*self) }; + let val: u64 = self.to_bits(); val.hash_stable(ctx, hasher); } } diff --git a/compiler/rustc_data_structures/src/stack.rs b/compiler/rustc_data_structures/src/stack.rs index a4964b7aa0..ba22c7f9b9 100644 --- a/compiler/rustc_data_structures/src/stack.rs +++ b/compiler/rustc_data_structures/src/stack.rs @@ -5,6 +5,7 @@ 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/steal.rs b/compiler/rustc_data_structures/src/steal.rs index 30f659c2f7..a3ece65504 100644 --- a/compiler/rustc_data_structures/src/steal.rs +++ b/compiler/rustc_data_structures/src/steal.rs @@ -33,10 +33,11 @@ impl Steal { #[track_caller] pub fn borrow(&self) -> MappedReadGuard<'_, T> { - ReadGuard::map(self.value.borrow(), |opt| match *opt { - None => panic!("attempted to read from stolen value"), - Some(ref v) => v, - }) + let borrow = self.value.borrow(); + if borrow.is_none() { + panic!("attempted to read from stolen value: {}", std::any::type_name::()); + } + ReadGuard::map(borrow, |opt| opt.as_ref().unwrap()) } #[track_caller] diff --git a/compiler/rustc_data_structures/src/thin_vec.rs b/compiler/rustc_data_structures/src/thin_vec.rs index 00e3047349..b5d2d24736 100644 --- a/compiler/rustc_data_structures/src/thin_vec.rs +++ b/compiler/rustc_data_structures/src/thin_vec.rs @@ -2,7 +2,7 @@ use crate::stable_hasher::{HashStable, StableHasher}; use std::iter::FromIterator; -/// A vector type optimized for cases where this size is usually 0 (cf. `SmallVector`). +/// A vector type optimized for cases where this size is usually 0 (cf. `SmallVec`). /// The `Option>` wrapping allows us to represent a zero sized vector with `None`, /// which uses only a single (null) pointer. #[derive(Clone, Encodable, Decodable, Debug)] diff --git a/compiler/rustc_data_structures/src/tiny_list.rs b/compiler/rustc_data_structures/src/tiny_list.rs index 9b07f86846..9e605ea2d9 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(ref e) = elem { + while let Some(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 1cf030d852..ce60d40b24 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: &'a Ls, -) -> impl Iterator + 'a + links: &Ls, +) -> impl Iterator + '_ where Ls: Links, { diff --git a/compiler/rustc_driver/Cargo.toml b/compiler/rustc_driver/Cargo.toml index 57159962a9..ce3a3f5a3a 100644 --- a/compiler/rustc_driver/Cargo.toml +++ b/compiler/rustc_driver/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustc_driver" version = "0.0.0" -edition = "2018" +edition = "2021" [lib] crate-type = ["dylib"] @@ -9,7 +9,7 @@ crate-type = ["dylib"] [dependencies] libc = "0.2" atty = "0.2" -tracing = { version = "0.1.25" } +tracing = { version = "0.1.28" } tracing-subscriber = { version = "0.2.16", default-features = false, features = ["fmt", "env-filter", "smallvec", "parking_lot", "ansi"] } tracing-tree = "0.1.9" rustc_middle = { path = "../rustc_middle" } @@ -22,7 +22,7 @@ rustc_feature = { path = "../rustc_feature" } rustc_hir = { path = "../rustc_hir" } rustc_hir_pretty = { path = "../rustc_hir_pretty" } rustc_metadata = { path = "../rustc_metadata" } -rustc_mir = { path = "../rustc_mir" } +rustc_const_eval = { path = "../rustc_const_eval" } rustc_parse = { path = "../rustc_parse" } rustc_plugin_impl = { path = "../rustc_plugin_impl" } rustc_save_analysis = { path = "../rustc_save_analysis" } diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs index 53053327d0..9a57ec9914 100644 --- a/compiler/rustc_driver/src/lib.rs +++ b/compiler/rustc_driver/src/lib.rs @@ -25,12 +25,12 @@ use rustc_interface::util::{self, collect_crate_types, get_codegen_backend}; use rustc_interface::{interface, Queries}; use rustc_lint::LintStore; use rustc_metadata::locator; -use rustc_middle::middle::cstore::MetadataLoader; use rustc_save_analysis as save; use rustc_save_analysis::DumpHandler; use rustc_serialize::json::{self, ToJson}; use rustc_session::config::{nightly_options, CG_OPTIONS, DB_OPTIONS}; use rustc_session::config::{ErrorOutputType, Input, OutputType, PrintRequest, TrimmedDefPaths}; +use rustc_session::cstore::MetadataLoader; use rustc_session::getopts; use rustc_session::lint::{Lint, LintId}; use rustc_session::{config, DiagnosticOutput, Session}; @@ -128,7 +128,7 @@ impl Callbacks for TimePassesCallbacks { } pub fn diagnostics_registry() -> Registry { - Registry::new(&rustc_error_codes::DIAGNOSTICS) + Registry::new(rustc_error_codes::DIAGNOSTICS) } /// This is the primary entry point for rustc. @@ -265,8 +265,8 @@ fn run_compiler( &***compiler.codegen_backend(), compiler.session(), None, - &compiler.output_dir(), - &compiler.output_file(), + compiler.output_dir(), + compiler.output_file(), ); if should_stop == Compilation::Stop { @@ -330,7 +330,7 @@ fn run_compiler( let krate = queries.parse()?.take(); pretty::print_after_parsing( sess, - &compiler.input(), + compiler.input(), &krate, *ppm, compiler.output_file().as_ref().map(|p| &**p), @@ -356,7 +356,7 @@ fn run_compiler( // Lint plugins are registered; now we can process command line flags. if sess.opts.describe_lints { - describe_lints(&sess, &lint_store, true); + describe_lints(sess, lint_store, true); return early_exit(); } } @@ -388,7 +388,7 @@ fn run_compiler( save::process_crate( tcx, &crate_name, - &compiler.input(), + compiler.input(), None, DumpHandler::new( compiler.output_dir().as_ref().map(|p| &**p), @@ -598,7 +598,7 @@ impl RustcDefaultCalls { if let Input::File(file) = compiler.input() { // FIXME: #![crate_type] and #![crate_name] support not implemented yet sess.init_crate_types(collect_crate_types(sess, &[])); - let outputs = compiler.build_output_filenames(&sess, &[]); + let outputs = compiler.build_output_filenames(sess, &[]); let rlink_data = fs::read_to_string(file).unwrap_or_else(|err| { sess.fatal(&format!("failed to read rlink file: {}", err)); }); @@ -606,7 +606,7 @@ impl RustcDefaultCalls { json::decode(&rlink_data).unwrap_or_else(|err| { sess.fatal(&format!("failed to decode rlink: {}", err)); }); - let result = compiler.codegen_backend().link(&sess, codegen_results, &outputs); + let result = compiler.codegen_backend().link(sess, codegen_results, &outputs); abort_on_err(result, sess); } else { sess.fatal("rlink must be a file") @@ -677,10 +677,7 @@ impl RustcDefaultCalls { println!("{}", targets.join("\n")); } Sysroot => println!("{}", sess.sysroot.display()), - TargetLibdir => println!( - "{}", - sess.target_tlib_path.as_ref().unwrap_or(&sess.host_tlib_path).dir.display() - ), + TargetLibdir => println!("{}", sess.target_tlib_path.dir.display()), TargetSpec => println!("{}", sess.target.to_json().pretty()), FileNames | CrateName => { let input = input.unwrap_or_else(|| { @@ -897,9 +894,9 @@ Available lint options: }; println!("Lint groups provided by rustc:\n"); - println!(" {} {}", padded("name"), "sub-lints"); - println!(" {} {}", padded("----"), "---------"); - println!(" {} {}", padded("warnings"), "all lints that are set to issue warnings"); + println!(" {} sub-lints", padded("name")); + println!(" {} ---------", padded("----")); + println!(" {} all lints that are set to issue warnings", padded("warnings")); let print_lint_groups = |lints: Vec<(&'static str, Vec)>| { for (name, to) in lints { @@ -1220,7 +1217,7 @@ pub fn report_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str) { } for note in &xs { - handler.note_without_error(¬e); + handler.note_without_error(note); } // If backtraces are enabled, also print the query stack @@ -1256,12 +1253,16 @@ pub fn init_rustc_env_logger() { /// tracing crate version. In contrast to `init_rustc_env_logger` it allows you to choose an env var /// other than `RUSTC_LOG`. pub fn init_env_logger(env: &str) { - // Don't register a dispatcher if there's no filter to print anything - match std::env::var(env) { - Err(_) => return, - Ok(s) if s.is_empty() => return, - Ok(_) => {} - } + use tracing_subscriber::{ + filter::{self, EnvFilter, LevelFilter}, + layer::SubscriberExt, + }; + + let filter = match std::env::var(env) { + Ok(env) => EnvFilter::new(env), + _ => EnvFilter::default().add_directive(filter::Directive::from(LevelFilter::WARN)), + }; + let color_logs = match std::env::var(String::from(env) + "_COLOR") { Ok(value) => match value.as_ref() { "always" => true, @@ -1281,7 +1282,7 @@ pub fn init_env_logger(env: &str) { "non-Unicode log color value: expected one of always, never, or auto", ), }; - let filter = tracing_subscriber::EnvFilter::from_env(env); + let layer = tracing_tree::HierarchicalLayer::default() .with_writer(io::stderr) .with_indent_lines(true) @@ -1291,7 +1292,6 @@ pub fn init_env_logger(env: &str) { #[cfg(parallel_compiler)] let layer = layer.with_thread_ids(true).with_thread_names(true); - use tracing_subscriber::layer::SubscriberExt; let subscriber = tracing_subscriber::Registry::default().with(filter).with(layer); tracing::subscriber::set_global_default(subscriber).unwrap(); } @@ -1329,7 +1329,7 @@ mod signal_handler { std::alloc::alloc(std::alloc::Layout::from_size_align(ALT_STACK_SIZE, 1).unwrap()) as *mut libc::c_void; alt_stack.ss_size = ALT_STACK_SIZE; - libc::sigaltstack(&mut alt_stack, std::ptr::null_mut()); + libc::sigaltstack(&alt_stack, std::ptr::null_mut()); let mut sa: libc::sigaction = std::mem::zeroed(); sa.sa_sigaction = print_stack_trace as libc::sighandler_t; diff --git a/compiler/rustc_driver/src/pretty.rs b/compiler/rustc_driver/src/pretty.rs index 579ba43b6d..8e8bea9525 100644 --- a/compiler/rustc_driver/src/pretty.rs +++ b/compiler/rustc_driver/src/pretty.rs @@ -6,8 +6,8 @@ use rustc_errors::ErrorReported; use rustc_hir as hir; use rustc_hir_pretty as pprust_hir; use rustc_middle::hir::map as hir_map; +use rustc_middle::mir::{write_mir_graphviz, write_mir_pretty}; use rustc_middle::ty::{self, TyCtxt}; -use rustc_mir::util::{write_mir_graphviz, write_mir_pretty}; use rustc_session::config::{Input, PpAstTreeMode, PpHirMode, PpMode, PpSourceMode}; use rustc_session::Session; use rustc_span::symbol::Ident; @@ -88,7 +88,7 @@ trait PrinterSupport: pprust::PpAnn { /// Produces the pretty-print annotation object. /// /// (Rust does not yet support upcasting from a trait object to - /// an object for one of its super-traits.) + /// an object for one of its supertraits.) fn pp_ann(&self) -> &dyn pprust::PpAnn; } @@ -104,7 +104,7 @@ trait HirPrinterSupport<'hir>: pprust_hir::PpAnn { /// Produces the pretty-print annotation object. /// /// (Rust does not yet support upcasting from a trait object to - /// an object for one of its super-traits.) + /// an object for one of its supertraits.) fn pp_ann(&self) -> &dyn pprust_hir::PpAnn; } @@ -296,7 +296,7 @@ struct TypedAnnotation<'tcx> { impl<'tcx> HirPrinterSupport<'tcx> for TypedAnnotation<'tcx> { fn sess(&self) -> &Session { - &self.tcx.sess + self.tcx.sess } fn hir_map(&self) -> Option> { @@ -347,8 +347,7 @@ impl<'tcx> pprust_hir::PpAnn for TypedAnnotation<'tcx> { fn get_source(input: &Input, sess: &Session) -> (String, FileName) { let src_name = input.source_name(); let src = String::clone( - &sess - .source_map() + sess.source_map() .get_source_file(&src_name) .expect("get_source_file") .src @@ -489,7 +488,7 @@ fn print_with_analysis( let mut out = String::new(); abort_on_err(rustc_typeck::check_crate(tcx), tcx.sess); debug!("pretty printing THIR tree"); - for did in tcx.body_owners() { + for did in tcx.hir().body_owners() { let _ = writeln!( out, "{:?}:\n{}\n", diff --git a/compiler/rustc_error_codes/Cargo.toml b/compiler/rustc_error_codes/Cargo.toml index 270e530189..7d5f3e4672 100644 --- a/compiler/rustc_error_codes/Cargo.toml +++ b/compiler/rustc_error_codes/Cargo.toml @@ -1,4 +1,4 @@ [package] name = "rustc_error_codes" version = "0.0.0" -edition = "2018" +edition = "2021" diff --git a/compiler/rustc_error_codes/src/error_codes.rs b/compiler/rustc_error_codes/src/error_codes.rs index 45d91c2047..724e3f7fed 100644 --- a/compiler/rustc_error_codes/src/error_codes.rs +++ b/compiler/rustc_error_codes/src/error_codes.rs @@ -92,6 +92,7 @@ E0164: include_str!("./error_codes/E0164.md"), E0165: include_str!("./error_codes/E0165.md"), E0170: include_str!("./error_codes/E0170.md"), E0178: include_str!("./error_codes/E0178.md"), +E0183: include_str!("./error_codes/E0183.md"), E0184: include_str!("./error_codes/E0184.md"), E0185: include_str!("./error_codes/E0185.md"), E0186: include_str!("./error_codes/E0186.md"), @@ -237,11 +238,13 @@ E0455: include_str!("./error_codes/E0455.md"), E0458: include_str!("./error_codes/E0458.md"), E0459: include_str!("./error_codes/E0459.md"), E0463: include_str!("./error_codes/E0463.md"), +E0464: include_str!("./error_codes/E0464.md"), E0466: include_str!("./error_codes/E0466.md"), E0468: include_str!("./error_codes/E0468.md"), E0469: include_str!("./error_codes/E0469.md"), E0477: include_str!("./error_codes/E0477.md"), E0478: include_str!("./error_codes/E0478.md"), +E0482: include_str!("./error_codes/E0482.md"), E0491: include_str!("./error_codes/E0491.md"), E0492: include_str!("./error_codes/E0492.md"), E0493: include_str!("./error_codes/E0493.md"), @@ -511,7 +514,6 @@ E0785: include_str!("./error_codes/E0785.md"), // E0173, // manual implementations of unboxed closure traits are experimental // E0174, // E0182, // merged into E0229 - E0183, // E0187, // cannot infer the kind of the closure // E0188, // can not cast an immutable reference to a mutable pointer // E0189, // deprecated: can only cast a boxed pointer to a boxed object @@ -586,7 +588,6 @@ E0785: include_str!("./error_codes/E0785.md"), E0460, // found possibly newer version of crate `..` E0461, // couldn't find crate `..` with expected target triple .. E0462, // found staticlib `..` instead of rlib or dylib - E0464, // multiple matching crates for `..` E0465, // multiple .. candidates for `..` found // E0467, removed // E0470, removed @@ -599,7 +600,6 @@ E0785: include_str!("./error_codes/E0785.md"), // E0479, // the type `..` (provided as the value of a type parameter) is... // E0480, // lifetime of method receiver does not outlive the method call // E0481, // lifetime of function argument does not outlive the function call - E0482, // lifetime of return value does not outlive the function call // E0483, // lifetime of operand does not outlive the operation // E0484, // reference is not valid at the time of borrow // E0485, // automatically reference is not valid at the time of borrow diff --git a/compiler/rustc_error_codes/src/error_codes/E0071.md b/compiler/rustc_error_codes/src/error_codes/E0071.md index bc2c03a022..a6d6d19762 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0071.md +++ b/compiler/rustc_error_codes/src/error_codes/E0071.md @@ -15,13 +15,13 @@ form of initializer was used. For example, the code above can be fixed to: ``` -enum Foo { - FirstValue(i32) -} - -fn main() { - let u = Foo::FirstValue(0i32); - - let t = 4; -} +type U32 = u32; +let t: U32 = 4; +``` + +or: + +``` +struct U32 { value: u32 } +let t = U32 { value: 4 }; ``` diff --git a/compiler/rustc_error_codes/src/error_codes/E0183.md b/compiler/rustc_error_codes/src/error_codes/E0183.md new file mode 100644 index 0000000000..7e1d08daae --- /dev/null +++ b/compiler/rustc_error_codes/src/error_codes/E0183.md @@ -0,0 +1,39 @@ +Manual implemetation of a `Fn*` trait. + +Erroneous code example: + +```compile_fail,E0183 +struct MyClosure { + foo: i32 +} + +impl FnOnce<()> for MyClosure { // error + type Output = (); + extern "rust-call" fn call_once(self, args: ()) -> Self::Output { + println!("{}", self.foo); + } +} +``` + +Manually implementing `Fn`, `FnMut` or `FnOnce` is unstable +and requires `#![feature(fn_traits, unboxed_closures)]`. + +``` +#![feature(fn_traits, unboxed_closures)] + +struct MyClosure { + foo: i32 +} + +impl FnOnce<()> for MyClosure { // ok! + type Output = (); + extern "rust-call" fn call_once(self, args: ()) -> Self::Output { + println!("{}", self.foo); + } +} +``` + +The argumements must be a tuple representing the argument list. +For more info, see the [tracking issue][iss29625]: + +[iss29625]: https://github.com/rust-lang/rust/issues/29625 diff --git a/compiler/rustc_error_codes/src/error_codes/E0222.md b/compiler/rustc_error_codes/src/error_codes/E0222.md index fbf1b8d703..f929f219af 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0222.md +++ b/compiler/rustc_error_codes/src/error_codes/E0222.md @@ -16,9 +16,9 @@ pub trait BoxCar : Box + Vehicle {} fn dent_object(c: dyn BoxCar) {} // Invalid constraint ``` -In this example, `BoxCar` has two super-traits: `Vehicle` and `Box`. Both of +In this example, `BoxCar` has two supertraits: `Vehicle` and `Box`. Both of these traits define an associated type `Color`. `BoxCar` inherits two types -with that name from both super-traits. Because of this, we need to use the +with that name from both supertraits. Because of this, we need to use the fully qualified path syntax to refer to the appropriate `Color` associated type, either `::Color` or `::Color`, but this syntax is not allowed to be used in a function signature. diff --git a/compiler/rustc_error_codes/src/error_codes/E0439.md b/compiler/rustc_error_codes/src/error_codes/E0439.md index 3e663df866..24268aef22 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0439.md +++ b/compiler/rustc_error_codes/src/error_codes/E0439.md @@ -1,8 +1,10 @@ +#### Note: this error code is no longer emitted by the compiler. + The length of the platform-intrinsic function `simd_shuffle` wasn't specified. Erroneous code example: -```compile_fail,E0439 +```ignore (no longer emitted) #![feature(platform_intrinsics)] extern "platform-intrinsic" { diff --git a/compiler/rustc_error_codes/src/error_codes/E0464.md b/compiler/rustc_error_codes/src/error_codes/E0464.md new file mode 100644 index 0000000000..9108d856c9 --- /dev/null +++ b/compiler/rustc_error_codes/src/error_codes/E0464.md @@ -0,0 +1,6 @@ +The compiler found multiple library files with the requested crate name. + +This error can occur in several different cases -- for example, when using +`extern crate` or passing `--extern` options without crate paths. It can also be +caused by caching issues with the build directory, in which case `cargo clean` +may help. diff --git a/compiler/rustc_error_codes/src/error_codes/E0482.md b/compiler/rustc_error_codes/src/error_codes/E0482.md new file mode 100644 index 0000000000..58ebf43cc9 --- /dev/null +++ b/compiler/rustc_error_codes/src/error_codes/E0482.md @@ -0,0 +1,73 @@ +A lifetime of a returned value does not outlive the function call. + +Erroneous code example: + +```compile_fail,E0482 +fn prefix<'a>( + words: impl Iterator +) -> impl Iterator { // error! + words.map(|v| format!("foo-{}", v)) +} +``` + +To fix this error, make the lifetime of the returned value explicit: + +``` +fn prefix<'a>( + words: impl Iterator + 'a +) -> impl Iterator + 'a { // ok! + words.map(|v| format!("foo-{}", v)) +} +``` + +The [`impl Trait`] feature in this example uses an implicit `'static` lifetime +restriction in the returned type. However the type implementing the `Iterator` +passed to the function lives just as long as `'a`, which is not long enough. + +The solution involves adding lifetime bound to both function argument and +the return value to make sure that the values inside the iterator +are not dropped when the function goes out of the scope. + +An alternative solution would be to guarantee that the `Item` references +in the iterator are alive for the whole lifetime of the program. + +``` +fn prefix( + words: impl Iterator +) -> impl Iterator { // ok! + words.map(|v| format!("foo-{}", v)) +} +``` + +A similar lifetime problem might arise when returning closures: + +```compile_fail,E0482 +fn foo( + x: &mut Vec +) -> impl FnMut(&mut Vec) -> &[i32] { // error! + |y| { + y.append(x); + y + } +} +``` + +Analogically, a solution here is to use explicit return lifetime +and move the ownership of the variable to the closure. + +``` +fn foo<'a>( + x: &'a mut Vec +) -> impl FnMut(&mut Vec) -> &[i32] + 'a { // ok! + move |y| { + y.append(x); + y + } +} +``` + +To better understand the lifetime treatment in the [`impl Trait`], +please see the [RFC 1951]. + +[`impl Trait`]: https://doc.rust-lang.org/reference/types/impl-trait.html +[RFC 1951]: https://rust-lang.github.io/rfcs/1951-expand-impl-trait.html diff --git a/compiler/rustc_errors/Cargo.toml b/compiler/rustc_errors/Cargo.toml index c74fd60e53..4846dc4360 100644 --- a/compiler/rustc_errors/Cargo.toml +++ b/compiler/rustc_errors/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustc_errors" version = "0.0.0" -edition = "2018" +edition = "2021" [lib] doctest = false diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index 8199c44ee2..41a73268f4 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -9,9 +9,10 @@ use rustc_lint_defs::Applicability; use rustc_serialize::json::Json; use rustc_span::{MultiSpan, Span, DUMMY_SP}; use std::fmt; +use std::hash::{Hash, Hasher}; #[must_use] -#[derive(Clone, Debug, PartialEq, Hash, Encodable, Decodable)] +#[derive(Clone, Debug, Encodable, Decodable)] pub struct Diagnostic { pub level: Level, pub message: Vec<(String, Style)>, @@ -24,6 +25,10 @@ pub struct Diagnostic { /// as a sort key to sort a buffer of diagnostics. By default, it is the primary span of /// `span` if there is one. Otherwise, it is `DUMMY_SP`. pub sort_span: Span, + + /// If diagnostic is from Lint, custom hash function ignores notes + /// otherwise hash is based on the all the fields + pub is_lint: bool, } #[derive(Clone, Debug, PartialEq, Eq, Hash, Encodable, Decodable)] @@ -69,6 +74,10 @@ impl DiagnosticStyledString { pub fn highlighted>(t: S) -> DiagnosticStyledString { DiagnosticStyledString(vec![StringPart::Highlighted(t.into())]) } + + pub fn content(&self) -> String { + self.0.iter().map(|x| x.content()).collect::() + } } #[derive(Debug, PartialEq, Eq)] @@ -77,6 +86,14 @@ pub enum StringPart { Highlighted(String), } +impl StringPart { + pub fn content(&self) -> &str { + match self { + &StringPart::Normal(ref s) | &StringPart::Highlighted(ref s) => s, + } + } +} + impl Diagnostic { pub fn new(level: Level, message: &str) -> Self { Diagnostic::new_with_code(level, None, message) @@ -91,6 +108,7 @@ impl Diagnostic { children: vec![], suggestions: vec![], sort_span: DUMMY_SP, + is_lint: false, } } @@ -298,6 +316,21 @@ impl Diagnostic { ) } + /// Show a suggestion that has multiple parts to it, always as it's own subdiagnostic. + /// In other words, multiple changes need to be applied as part of this suggestion. + pub fn multipart_suggestion_verbose( + &mut self, + msg: &str, + suggestion: Vec<(Span, String)>, + applicability: Applicability, + ) -> &mut Self { + self.multipart_suggestion_with_style( + msg, + suggestion, + applicability, + SuggestionStyle::ShowAlways, + ) + } /// [`Diagnostic::multipart_suggestion()`] but you can set the [`SuggestionStyle`]. pub fn multipart_suggestion_with_style( &mut self, @@ -558,6 +591,11 @@ impl Diagnostic { self } + pub fn set_is_lint(&mut self) -> &mut Self { + self.is_lint = true; + self + } + pub fn code(&mut self, s: DiagnosticId) -> &mut Self { self.code = Some(s); self @@ -617,6 +655,42 @@ impl Diagnostic { let sub = SubDiagnostic { level, message, span, render_span }; self.children.push(sub); } + + /// Fields used for Hash, and PartialEq trait + fn keys( + &self, + ) -> ( + &Level, + &Vec<(String, Style)>, + &Option, + &MultiSpan, + &Vec, + Option<&Vec>, + ) { + ( + &self.level, + &self.message, + &self.code, + &self.span, + &self.suggestions, + (if self.is_lint { None } else { Some(&self.children) }), + ) + } +} + +impl Hash for Diagnostic { + fn hash(&self, state: &mut H) + where + H: Hasher, + { + self.keys().hash(state); + } +} + +impl PartialEq for Diagnostic { + fn eq(&self, other: &Self) -> bool { + self.keys() == other.keys() + } } impl SubDiagnostic { diff --git a/compiler/rustc_errors/src/diagnostic_builder.rs b/compiler/rustc_errors/src/diagnostic_builder.rs index d35b292480..6f84b0d400 100644 --- a/compiler/rustc_errors/src/diagnostic_builder.rs +++ b/compiler/rustc_errors/src/diagnostic_builder.rs @@ -242,6 +242,7 @@ impl<'a> DiagnosticBuilder<'a> { sp: S, msg: &str, ) -> &mut Self); + forward!(pub fn set_is_lint(&mut self,) -> &mut Self); /// See [`Diagnostic::multipart_suggestion()`]. pub fn multipart_suggestion( @@ -257,6 +258,20 @@ impl<'a> DiagnosticBuilder<'a> { self } + /// See [`Diagnostic::multipart_suggestion()`]. + pub fn multipart_suggestion_verbose( + &mut self, + msg: &str, + suggestion: Vec<(Span, String)>, + applicability: Applicability, + ) -> &mut Self { + if !self.0.allow_suggestions { + return self; + } + self.0.diagnostic.multipart_suggestion_verbose(msg, suggestion, applicability); + self + } + /// See [`Diagnostic::tool_only_multipart_suggestion()`]. pub fn tool_only_multipart_suggestion( &mut self, diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index 29f352ae58..7fa29bd33c 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -2054,8 +2054,26 @@ fn num_decimal_digits(num: usize) -> usize { MAX_DIGITS } +// 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{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. + ('\u{202E}', ""), + ('\u{2066}', ""), + ('\u{2067}', ""), + ('\u{2068}', ""), + ('\u{202C}', ""), + ('\u{2069}', ""), +]; + fn replace_tabs(str: &str) -> String { - str.replace('\t', " ") + let mut s = str.to_string(); + for (c, replacement) in OUTPUT_REPLACEMENTS { + s = s.replace(*c, replacement); + } + s } fn draw_col_separator(buffer: &mut StyledBuffer, line: usize, col: usize) { @@ -2308,7 +2326,7 @@ pub fn is_case_difference(sm: &SourceMap, suggested: &str, sp: Span) -> bool { let found = match sm.span_to_snippet(sp) { Ok(snippet) => snippet, Err(e) => { - warn!("Invalid span {:?}. Err={:?}", sp, e); + warn!(error = ?e, "Invalid span {:?}", sp); return false; } }; diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 02b6179f89..9b2094adb1 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -9,14 +9,15 @@ #![feature(format_args_capture)] #![feature(iter_zip)] #![feature(nll)] -#![cfg_attr(bootstrap, allow(incomplete_features))] // if_let_guard #[macro_use] extern crate rustc_macros; +#[macro_use] +extern crate tracing; + pub use emitter::ColorConfig; -use tracing::debug; use Level::*; use emitter::{is_case_difference, Emitter, EmitterWriter}; @@ -340,7 +341,7 @@ impl CodeSuggestion { }); buf.push_str(&part.snippet); let cur_hi = sm.lookup_char_pos(part.span.hi()); - if prev_hi.line == cur_lo.line { + if prev_hi.line == cur_lo.line && cur_hi.line == cur_lo.line { // Account for the difference between the width of the current code and the // snippet being suggested, so that the *later* suggestions are correctly // aligned on the screen. @@ -1029,15 +1030,13 @@ impl HandlerInner { let mut error_codes = self .emitted_diagnostic_codes .iter() - .filter_map(|x| { - match &x { + .filter_map(|x| match &x { DiagnosticId::Error(s) - if let Ok(Some(_explanation)) = registry.try_find_description(s) => + if registry.try_find_description(s).map_or(false, |o| o.is_some()) => { Some(s.clone()) } _ => None, - } }) .collect::>(); if !error_codes.is_empty() { diff --git a/compiler/rustc_expand/Cargo.toml b/compiler/rustc_expand/Cargo.toml index 1be9321e4f..45237ab2e9 100644 --- a/compiler/rustc_expand/Cargo.toml +++ b/compiler/rustc_expand/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustc_expand" version = "0.0.0" -edition = "2018" +edition = "2021" build = false [lib] diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index 35df8aae4b..b630bc1f47 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -10,12 +10,12 @@ use rustc_ast::{self as ast, AstLike, Attribute, Item, NodeId, PatKind}; use rustc_attr::{self as attr, Deprecation, Stability}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::{self, Lrc}; -use rustc_errors::{DiagnosticBuilder, ErrorReported}; +use rustc_errors::{Applicability, DiagnosticBuilder, ErrorReported}; use rustc_lint_defs::builtin::PROC_MACRO_BACK_COMPAT; use rustc_lint_defs::BuiltinLintDiagnostics; use rustc_parse::{self, nt_to_tokenstream, parser, MACRO_ARGUMENTS}; use rustc_session::{parse::ParseSess, Limit, Session}; -use rustc_span::def_id::{CrateNum, DefId}; +use rustc_span::def_id::{CrateNum, DefId, LocalDefId}; use rustc_span::edition::Edition; use rustc_span::hygiene::{AstPass, ExpnData, ExpnKind, LocalExpnId}; use rustc_span::source_map::SourceMap; @@ -843,6 +843,7 @@ pub type DeriveResolutions = Vec<(ast::Path, Annotatable, Option NodeId; + fn invocation_parent(&self, id: LocalExpnId) -> LocalDefId; fn resolve_dollar_crates(&mut self); fn visit_ast_fragment_with_placeholders( @@ -1136,13 +1137,15 @@ impl<'a> ExtCtxt<'a> { } /// Extracts a string literal from the macro expanded version of `expr`, -/// emitting `err_msg` if `expr` is not a string literal. This does not stop -/// compilation on error, merely emits a non-fatal error and returns `None`. +/// returning a diagnostic error of `err_msg` if `expr` is not a string literal. +/// The returned bool indicates whether an applicable suggestion has already been +/// added to the diagnostic to avoid emitting multiple suggestions. `Err(None)` +/// indicates that an ast error was encountered. pub fn expr_to_spanned_string<'a>( cx: &'a mut ExtCtxt<'_>, expr: P, err_msg: &str, -) -> Result<(Symbol, ast::StrStyle, Span), Option>> { +) -> Result<(Symbol, ast::StrStyle, Span), Option<(DiagnosticBuilder<'a>, bool)>> { // Perform eager expansion on the expression. // We want to be able to handle e.g., `concat!("foo", "bar")`. let expr = cx.expander().fully_expand_fragment(AstFragment::Expr(expr)).make_expr(); @@ -1150,14 +1153,27 @@ pub fn expr_to_spanned_string<'a>( Err(match expr.kind { ast::ExprKind::Lit(ref l) => match l.kind { ast::LitKind::Str(s, style) => return Ok((s, style, expr.span)), + ast::LitKind::ByteStr(_) => { + let mut err = cx.struct_span_err(l.span, err_msg); + err.span_suggestion( + expr.span.shrink_to_lo(), + "consider removing the leading `b`", + String::new(), + Applicability::MaybeIncorrect, + ); + Some((err, true)) + } ast::LitKind::Err(_) => None, - _ => Some(cx.struct_span_err(l.span, err_msg)), + _ => Some((cx.struct_span_err(l.span, err_msg), false)), }, ast::ExprKind::Err => None, - _ => Some(cx.struct_span_err(expr.span, err_msg)), + _ => Some((cx.struct_span_err(expr.span, err_msg), false)), }) } +/// Extracts a string literal from the macro expanded version of `expr`, +/// emitting `err_msg` if `expr` is not a string literal. This does not stop +/// compilation on error, merely emits a non-fatal error and returns `None`. pub fn expr_to_string( cx: &mut ExtCtxt<'_>, expr: P, @@ -1165,7 +1181,7 @@ pub fn expr_to_string( ) -> Option<(Symbol, ast::StrStyle)> { expr_to_spanned_string(cx, expr, err_msg) .map_err(|err| { - err.map(|mut err| { + err.map(|(mut err, _)| { err.emit(); }) }) diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs index 38c099fa4f..1b12352096 100644 --- a/compiler/rustc_expand/src/config.rs +++ b/compiler/rustc_expand/src/config.rs @@ -171,7 +171,7 @@ fn get_features( } if let Some(allowed) = sess.opts.debugging_opts.allow_features.as_ref() { - if allowed.iter().find(|&f| name.as_str() == *f).is_none() { + if allowed.iter().all(|f| name.as_str() != *f) { struct_span_err!( span_handler, mi.span(), diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index 48ad7be3e9..f548e2848a 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -588,7 +588,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { // Resolve `$crate`s in the fragment for pretty-printing. self.cx.resolver.resolve_dollar_crates(); - let invocations = { + let mut invocations = { let mut collector = InvocationCollector { // Non-derive macro invocations cannot see the results of cfg expansion - they // will either be removed along with the item, or invoked before the cfg/cfg_attr @@ -613,6 +613,19 @@ impl<'a, 'b> MacroExpander<'a, 'b> { self.cx .resolver .visit_ast_fragment_with_placeholders(self.cx.current_expansion.id, &fragment); + + if self.cx.sess.opts.debugging_opts.incremental_relative_spans { + for (invoc, _) in invocations.iter_mut() { + let expn_id = invoc.expansion_data.id; + let parent_def = self.cx.resolver.invocation_parent(expn_id); + let span = match &mut invoc.kind { + InvocationKind::Bang { ref mut span, .. } => span, + InvocationKind::Attr { attr, .. } => &mut attr.span, + InvocationKind::Derive { path, .. } => &mut path.span, + }; + *span = span.with_parent(Some(parent_def)); + } + } } (fragment, invocations) @@ -620,14 +633,18 @@ impl<'a, 'b> MacroExpander<'a, 'b> { fn error_recursion_limit_reached(&mut self) { let expn_data = self.cx.current_expansion.id.expn_data(); - let suggested_limit = self.cx.ecfg.recursion_limit * 2; + let suggested_limit = match self.cx.ecfg.recursion_limit { + Limit(0) => Limit(2), + limit => limit * 2, + }; self.cx .struct_span_err( expn_data.call_site, &format!("recursion limit reached while expanding `{}`", expn_data.kind.descr()), ) .help(&format!( - "consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate (`{}`)", + "consider increasing the recursion limit by adding a \ + `#![recursion_limit = \"{}\"]` attribute to your crate (`{}`)", suggested_limit, self.cx.ecfg.crate_name, )) .emit(); @@ -1007,12 +1024,10 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { placeholder(fragment_kind, NodeId::placeholder_from_expn_id(expn_id), vis) } - fn collect_bang( - &mut self, - mac: ast::MacCall, - span: Span, - kind: AstFragmentKind, - ) -> AstFragment { + fn collect_bang(&mut self, mac: ast::MacCall, kind: AstFragmentKind) -> AstFragment { + // cache the macro call span so that it can be + // easily adjusted for incremental compilation + let span = mac.span(); self.collect(kind, InvocationKind::Bang { mac, span }) } @@ -1070,25 +1085,19 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { let MacCallStmt { mac, style, attrs, .. } = mac.into_inner(); Ok((style == MacStmtStyle::Semicolon, mac, attrs.into())) } - StmtKind::Item(ref item) if matches!(item.kind, ItemKind::MacCall(..)) => { - match stmt.kind { - StmtKind::Item(item) => match item.into_inner() { - ast::Item { kind: ItemKind::MacCall(mac), attrs, .. } => { - Ok((mac.args.need_semicolon(), mac, attrs)) - } - _ => unreachable!(), - }, + StmtKind::Item(item) if matches!(item.kind, ItemKind::MacCall(..)) => { + match item.into_inner() { + ast::Item { kind: ItemKind::MacCall(mac), attrs, .. } => { + Ok((mac.args.need_semicolon(), mac, attrs)) + } _ => unreachable!(), } } - StmtKind::Semi(ref expr) if matches!(expr.kind, ast::ExprKind::MacCall(..)) => { - match stmt.kind { - StmtKind::Semi(expr) => match expr.into_inner() { - ast::Expr { kind: ast::ExprKind::MacCall(mac), attrs, .. } => { - Ok((mac.args.need_semicolon(), mac, attrs.into())) - } - _ => unreachable!(), - }, + StmtKind::Semi(expr) if matches!(expr.kind, ast::ExprKind::MacCall(..)) => { + match expr.into_inner() { + ast::Expr { kind: ast::ExprKind::MacCall(mac), attrs, .. } => { + Ok((mac.args.need_semicolon(), mac, attrs.into())) + } _ => unreachable!(), } } @@ -1205,7 +1214,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { if let ast::ExprKind::MacCall(mac) = expr.kind { self.check_attributes(&expr.attrs, &mac); - self.collect_bang(mac, expr.span, AstFragmentKind::Expr).make_expr().into_inner() + self.collect_bang(mac, AstFragmentKind::Expr).make_expr().into_inner() } else { assign_id!(self, &mut expr.id, || { ensure_sufficient_stack(|| noop_visit_expr(&mut expr, self)); @@ -1301,7 +1310,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { if let ast::ExprKind::MacCall(mac) = expr.kind { self.check_attributes(&expr.attrs, &mac); - self.collect_bang(mac, expr.span, AstFragmentKind::OptExpr) + self.collect_bang(mac, AstFragmentKind::OptExpr) .make_opt_expr() .map(|expr| expr.into_inner()) } else { @@ -1322,9 +1331,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { } visit_clobber(pat, |mut pat| match mem::replace(&mut pat.kind, PatKind::Wild) { - PatKind::MacCall(mac) => { - self.collect_bang(mac, pat.span, AstFragmentKind::Pat).make_pat() - } + PatKind::MacCall(mac) => self.collect_bang(mac, AstFragmentKind::Pat).make_pat(), _ => unreachable!(), }); } @@ -1343,12 +1350,10 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { .make_stmts(); } - let span = stmt.span; match self.take_stmt_bang(stmt) { Ok((add_semicolon, mac, attrs)) => { self.check_attributes(&attrs, &mac); - let mut stmts = - self.collect_bang(mac, span, AstFragmentKind::Stmts).make_stmts(); + let mut stmts = self.collect_bang(mac, AstFragmentKind::Stmts).make_stmts(); // If this is a macro invocation with a semicolon, then apply that // semicolon to the final statement produced by expansion. @@ -1416,7 +1421,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { item.attrs = attrs; item.and_then(|item| match item.kind { ItemKind::MacCall(mac) => { - self.collect_bang(mac, span, AstFragmentKind::Items).make_items() + self.collect_bang(mac, AstFragmentKind::Items).make_items() } _ => unreachable!(), }) @@ -1525,9 +1530,9 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { ast::AssocItemKind::MacCall(ref mac) => { self.check_attributes(&item.attrs, &mac); item.and_then(|item| match item.kind { - ast::AssocItemKind::MacCall(mac) => self - .collect_bang(mac, item.span, AstFragmentKind::TraitItems) - .make_trait_items(), + ast::AssocItemKind::MacCall(mac) => { + self.collect_bang(mac, AstFragmentKind::TraitItems).make_trait_items() + } _ => unreachable!(), }) } @@ -1550,9 +1555,9 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { ast::AssocItemKind::MacCall(ref mac) => { self.check_attributes(&item.attrs, &mac); item.and_then(|item| match item.kind { - ast::AssocItemKind::MacCall(mac) => self - .collect_bang(mac, item.span, AstFragmentKind::ImplItems) - .make_impl_items(), + ast::AssocItemKind::MacCall(mac) => { + self.collect_bang(mac, AstFragmentKind::ImplItems).make_impl_items() + } _ => unreachable!(), }) } @@ -1569,9 +1574,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { }; visit_clobber(ty, |mut ty| match mem::replace(&mut ty.kind, ast::TyKind::Err) { - ast::TyKind::MacCall(mac) => { - self.collect_bang(mac, ty.span, AstFragmentKind::Ty).make_ty() - } + ast::TyKind::MacCall(mac) => self.collect_bang(mac, AstFragmentKind::Ty).make_ty(), _ => unreachable!(), }); } @@ -1596,9 +1599,9 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { ast::ForeignItemKind::MacCall(ref mac) => { self.check_attributes(&foreign_item.attrs, &mac); foreign_item.and_then(|item| match item.kind { - ast::ForeignItemKind::MacCall(mac) => self - .collect_bang(mac, item.span, AstFragmentKind::ForeignItems) - .make_foreign_items(), + ast::ForeignItemKind::MacCall(mac) => { + self.collect_bang(mac, AstFragmentKind::ForeignItems).make_foreign_items() + } _ => unreachable!(), }) } diff --git a/compiler/rustc_expand/src/lib.rs b/compiler/rustc_expand/src/lib.rs index c6dc66e99f..6dfeb047ec 100644 --- a/compiler/rustc_expand/src/lib.rs +++ b/compiler/rustc_expand/src/lib.rs @@ -1,4 +1,3 @@ -#![cfg_attr(bootstrap, feature(bindings_after_at))] #![feature(crate_visibility_modifier)] #![feature(decl_macro)] #![feature(destructuring_assignment)] @@ -9,7 +8,6 @@ #![feature(proc_macro_internals)] #![feature(proc_macro_span)] #![feature(try_blocks)] -#![cfg_attr(bootstrap, allow(incomplete_features))] // if_let_guard #![recursion_limit = "256"] #[macro_use] diff --git a/compiler/rustc_expand/src/mbe/quoted.rs b/compiler/rustc_expand/src/mbe/quoted.rs index fb7479eafc..363cc72b52 100644 --- a/compiler/rustc_expand/src/mbe/quoted.rs +++ b/compiler/rustc_expand/src/mbe/quoted.rs @@ -72,7 +72,7 @@ pub(super) fn parse( // this with just `span.edition()`. A // `SyntaxContext::root()` from the current crate will // have the edition of the current crate, and a - // `SyntaxxContext::root()` from a foreign crate will + // `SyntaxContext::root()` from a foreign crate will // have the edition of that crate (which we manually // retrieve via the `edition` parameter). if span.ctxt() == SyntaxContext::root() { diff --git a/compiler/rustc_expand/src/module.rs b/compiler/rustc_expand/src/module.rs index 60d653ac8b..1c0b2a9b48 100644 --- a/compiler/rustc_expand/src/module.rs +++ b/compiler/rustc_expand/src/module.rs @@ -3,6 +3,7 @@ use rustc_ast::ptr::P; use rustc_ast::{token, Attribute, Inline, Item}; use rustc_errors::{struct_span_err, DiagnosticBuilder}; use rustc_parse::new_parser_from_file; +use rustc_parse::validate_attr; use rustc_session::parse::ParseSess; use rustc_session::Session; use rustc_span::symbol::{sym, Ident}; @@ -168,7 +169,25 @@ fn mod_file_path_from_attr( dir_path: &Path, ) -> Option { // Extract path string from first `#[path = "path_string"]` attribute. - let path_string = sess.first_attr_value_str_by_name(attrs, sym::path)?.as_str(); + let first_path = attrs.iter().find(|at| at.has_name(sym::path))?; + let path_string = match first_path.value_str() { + Some(s) => s.as_str(), + None => { + // This check is here mainly to catch attempting to use a macro, + // such as #[path = concat!(...)]. This isn't currently supported + // because otherwise the InvocationCollector would need to defer + // loading a module until the #[path] attribute was expanded, and + // it doesn't support that (and would likely add a bit of + // complexity). Usually bad forms are checked in AstValidator (via + // `check_builtin_attribute`), but by the time that runs the macro + // is expanded, and it doesn't give an error. + validate_attr::emit_fatal_malformed_builtin_attribute( + &sess.parse_sess, + first_path, + sym::path, + ); + } + }; // On windows, the base path might have the form // `\\?\foo\bar` in which case it does not tolerate diff --git a/compiler/rustc_expand/src/proc_macro_server.rs b/compiler/rustc_expand/src/proc_macro_server.rs index 55700f7b0d..5cb9719876 100644 --- a/compiler/rustc_expand/src/proc_macro_server.rs +++ b/compiler/rustc_expand/src/proc_macro_server.rs @@ -577,7 +577,7 @@ impl server::Literal for Rustc<'_> { } // Synthesize a new symbol that includes the minus sign. - let symbol = Symbol::intern(&s[..1 + lit.symbol.len()]); + let symbol = Symbol::intern(&s[..1 + lit.symbol.as_str().len()]); lit = token::Lit::new(lit.kind, symbol, lit.suffix); } @@ -745,7 +745,7 @@ impl server::Span for Rustc<'_> { self.sess.source_map().lookup_char_pos(span.lo()).file } fn parent(&mut self, span: Self::Span) -> Option { - span.parent() + span.parent_callsite() } fn source(&mut self, span: Self::Span) -> Self::Span { span.source_callsite() @@ -758,6 +758,12 @@ impl server::Span for Rustc<'_> { 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 { + span.shrink_to_lo() + } + fn after(&mut self, span: Self::Span) -> Self::Span { + 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()); diff --git a/compiler/rustc_feature/Cargo.toml b/compiler/rustc_feature/Cargo.toml index ee381e3425..3d8d0db20d 100644 --- a/compiler/rustc_feature/Cargo.toml +++ b/compiler/rustc_feature/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustc_feature" version = "0.0.0" -edition = "2018" +edition = "2021" [lib] doctest = false diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs index f557a4c97c..0d7a2afb63 100644 --- a/compiler/rustc_feature/src/accepted.rs +++ b/compiler/rustc_feature/src/accepted.rs @@ -16,7 +16,6 @@ macro_rules! declare_features { since: $ver, issue: to_nonzero($issue), edition: None, - description: concat!($($doc,)*), } ),+ ]; @@ -294,6 +293,10 @@ declare_features! ( (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), // ------------------------------------------------------------------------- // feature-group-end: accepted features diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index 743c40ce05..0ba764021e 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -37,7 +37,6 @@ macro_rules! declare_features { since: $ver, issue: to_nonzero($issue), edition: $edition, - description: concat!($($doc,)*), } ),+]; @@ -426,9 +425,6 @@ declare_features! ( /// Allows using the `amdgpu-kernel` ABI. (active, abi_amdgpu_kernel, "1.29.0", Some(51575), None), - /// Allows panicking during const eval (producing compile-time errors). - (active, const_panic, "1.30.0", Some(51999), None), - /// Allows `#[marker]` on certain traits allowing overlapping implementations. (active, marker_trait_attr, "1.30.0", Some(29864), None), @@ -596,9 +592,6 @@ declare_features! ( /// Lessens the requirements for structs to implement `Unsize`. (active, relaxed_struct_unsize, "1.51.0", Some(81793), None), - /// Allows macro attributes to observe output of `#[derive]`. - (active, macro_attributes_in_derive_output, "1.51.0", Some(81119), None), - /// Allows associated types in inherent impls. (incomplete, inherent_associated_types, "1.52.0", Some(8995), None), @@ -679,6 +672,21 @@ declare_features! ( /// 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), + // ------------------------------------------------------------------------- // 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 e2aa54a59b..85b0db468d 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -202,6 +202,10 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ 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")), + gated!( + must_not_suspend, Normal, template!(Word, NameValueStr: "reason"), must_not_suspend, + experimental!(must_not_suspend) + ), // FIXME(#14407) ungated!( deprecated, Normal, @@ -453,6 +457,9 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ ), // Enumerates "identity-like" conversion methods to suggest on type mismatch. rustc_attr!(rustc_conversion_suggestion, Normal, template!(Word), 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), // ========================================================================== // Internal attributes, Const related: @@ -460,6 +467,8 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ rustc_attr!(rustc_promotable, Normal, template!(Word), IMPL_DETAIL), rustc_attr!(rustc_legacy_const_generics, Normal, template!(List: "N"), 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), // ========================================================================== // Internal attributes, Layout related: diff --git a/compiler/rustc_feature/src/lib.rs b/compiler/rustc_feature/src/lib.rs index cf102aa16e..b25aab21e4 100644 --- a/compiler/rustc_feature/src/lib.rs +++ b/compiler/rustc_feature/src/lib.rs @@ -51,7 +51,6 @@ pub struct Feature { pub since: &'static str, issue: Option, pub edition: Option, - description: &'static str, } #[derive(Copy, Clone, Debug)] diff --git a/compiler/rustc_feature/src/removed.rs b/compiler/rustc_feature/src/removed.rs index 8e498a5446..7b9b68268e 100644 --- a/compiler/rustc_feature/src/removed.rs +++ b/compiler/rustc_feature/src/removed.rs @@ -16,7 +16,6 @@ macro_rules! declare_features { since: $ver, issue: to_nonzero($issue), edition: None, - description: concat!($($doc,)*), } ),+ ]; @@ -34,7 +33,6 @@ macro_rules! declare_features { since: $ver, issue: to_nonzero($issue), edition: None, - description: concat!($($doc,)*), } ),+ ]; @@ -104,7 +102,7 @@ declare_features! ( (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)]`")), + 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")), diff --git a/compiler/rustc_fs_util/Cargo.toml b/compiler/rustc_fs_util/Cargo.toml index c417e978b3..34c3fe2a00 100644 --- a/compiler/rustc_fs_util/Cargo.toml +++ b/compiler/rustc_fs_util/Cargo.toml @@ -1,4 +1,4 @@ [package] name = "rustc_fs_util" version = "0.0.0" -edition = "2018" +edition = "2021" diff --git a/compiler/rustc_graphviz/Cargo.toml b/compiler/rustc_graphviz/Cargo.toml index 87c41ae171..d657fdb1a7 100644 --- a/compiler/rustc_graphviz/Cargo.toml +++ b/compiler/rustc_graphviz/Cargo.toml @@ -1,4 +1,4 @@ [package] name = "rustc_graphviz" version = "0.0.0" -edition = "2018" +edition = "2021" diff --git a/compiler/rustc_graphviz/src/lib.rs b/compiler/rustc_graphviz/src/lib.rs index 27390fd2e4..e69289b71f 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/Cargo.toml b/compiler/rustc_hir/Cargo.toml index c92551c293..41c63440ba 100644 --- a/compiler/rustc_hir/Cargo.toml +++ b/compiler/rustc_hir/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustc_hir" version = "0.0.0" -edition = "2018" +edition = "2021" [lib] doctest = false @@ -17,3 +17,4 @@ rustc_serialize = { path = "../rustc_serialize" } rustc_ast = { path = "../rustc_ast" } tracing = "0.1" smallvec = { version = "1.6.1", features = ["union", "may_dangle"] } +odht = { version = "0.3.1", features = ["nightly"] } diff --git a/compiler/rustc_hir/src/arena.rs b/compiler/rustc_hir/src/arena.rs index 3e8b98e9f5..f07e52e04d 100644 --- a/compiler/rustc_hir/src/arena.rs +++ b/compiler/rustc_hir/src/arena.rs @@ -28,9 +28,9 @@ macro_rules! arena_types { [] 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<$tcx>, + [few] foreign_item_ref: rustc_hir::ForeignItemRef, [] impl_item: rustc_hir::ImplItem<$tcx>, - [] impl_item_ref: rustc_hir::ImplItemRef<$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>, diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs index 853415c417..cb668eb35e 100644 --- a/compiler/rustc_hir/src/def.rs +++ b/compiler/rustc_hir/src/def.rs @@ -598,6 +598,11 @@ impl Res { } } + #[track_caller] + pub fn expect_non_local(self) -> Res { + self.map_id(|_| panic!("unexpected `Res::Local`")) + } + pub fn macro_kind(self) -> Option { match self { Res::Def(DefKind::Macro(kind), _) => Some(kind), diff --git a/compiler/rustc_hir/src/def_path_hash_map.rs b/compiler/rustc_hir/src/def_path_hash_map.rs new file mode 100644 index 0000000000..8bfb47af26 --- /dev/null +++ b/compiler/rustc_hir/src/def_path_hash_map.rs @@ -0,0 +1,37 @@ +use rustc_data_structures::fingerprint::Fingerprint; +use rustc_span::def_id::{DefIndex, DefPathHash}; + +#[derive(Clone, Default)] +pub struct Config; + +impl odht::Config for Config { + type Key = DefPathHash; + type Value = DefIndex; + + type EncodedKey = [u8; 16]; + type EncodedValue = [u8; 4]; + + type H = odht::UnHashFn; + + #[inline] + fn encode_key(k: &DefPathHash) -> [u8; 16] { + k.0.to_le_bytes() + } + + #[inline] + fn encode_value(v: &DefIndex) -> [u8; 4] { + v.as_u32().to_le_bytes() + } + + #[inline] + fn decode_key(k: &[u8; 16]) -> DefPathHash { + DefPathHash(Fingerprint::from_le_bytes(*k)) + } + + #[inline] + fn decode_value(v: &[u8; 4]) -> DefIndex { + DefIndex::from_u32(u32::from_le_bytes(*v)) + } +} + +pub type DefPathHashMap = odht::HashTableOwned; diff --git a/compiler/rustc_hir/src/definitions.rs b/compiler/rustc_hir/src/definitions.rs index 30a367052c..ca29351455 100644 --- a/compiler/rustc_hir/src/definitions.rs +++ b/compiler/rustc_hir/src/definitions.rs @@ -6,14 +6,15 @@ pub use crate::def_id::DefPathHash; use crate::def_id::{CrateNum, DefIndex, LocalDefId, StableCrateId, CRATE_DEF_INDEX, LOCAL_CRATE}; +use crate::def_path_hash_map::DefPathHashMap; use crate::hir; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::stable_hasher::StableHasher; -use rustc_data_structures::unhash::UnhashMap; use rustc_index::vec::IndexVec; use rustc_span::hygiene::ExpnId; use rustc_span::symbol::{kw, sym, Symbol}; +use rustc_span::Span; use std::fmt::{self, Write}; use std::hash::Hash; @@ -27,7 +28,7 @@ use tracing::debug; pub struct DefPathTable { index_to_key: IndexVec, def_path_hashes: IndexVec, - def_path_hash_to_index: UnhashMap, + def_path_hash_to_index: DefPathHashMap, } impl DefPathTable { @@ -43,7 +44,7 @@ impl DefPathTable { // Check for hash collisions of DefPathHashes. These should be // exceedingly rare. - if let Some(existing) = self.def_path_hash_to_index.insert(def_path_hash, index) { + if let Some(existing) = self.def_path_hash_to_index.insert(&def_path_hash, &index) { let def_path1 = DefPath::make(LOCAL_CRATE, existing, |idx| self.def_key(idx)); let def_path2 = DefPath::make(LOCAL_CRATE, index, |idx| self.def_key(idx)); @@ -86,7 +87,7 @@ impl DefPathTable { pub fn enumerated_keys_and_path_hashes( &self, - ) -> impl Iterator + '_ { + ) -> impl Iterator + ExactSizeIterator + '_ { self.index_to_key .iter_enumerated() .map(move |(index, key)| (index, key, &self.def_path_hashes[index])) @@ -107,6 +108,11 @@ pub struct Definitions { /// Item with a given `LocalDefId` was defined during macro expansion with ID `ExpnId`. expansions_that_defined: FxHashMap, + + def_id_to_span: IndexVec, + + /// The [StableCrateId] of the local crate. + stable_crate_id: StableCrateId, } /// A unique identifier that we can use to lookup a definition @@ -324,7 +330,7 @@ impl Definitions { } /// Adds a root definition (no parent) and a few other reserved definitions. - pub fn new(stable_crate_id: StableCrateId) -> Definitions { + pub fn new(stable_crate_id: StableCrateId, crate_span: Span) -> Definitions { let key = DefKey { parent: None, disambiguated_data: DisambiguatedDefPathData { @@ -341,11 +347,19 @@ impl Definitions { let root = LocalDefId { local_def_index: table.allocate(key, def_path_hash) }; assert_eq!(root.local_def_index, CRATE_DEF_INDEX); + let mut def_id_to_span = IndexVec::new(); + // A relative span's parent must be an absolute span. + debug_assert_eq!(crate_span.data_untracked().parent, None); + let _root = def_id_to_span.push(crate_span); + debug_assert_eq!(_root, root); + Definitions { table, def_id_to_hir_id: Default::default(), hir_id_to_def_id: Default::default(), expansions_that_defined: Default::default(), + def_id_to_span, + stable_crate_id, } } @@ -361,6 +375,7 @@ impl Definitions { data: DefPathData, expn_id: ExpnId, mut next_disambiguator: impl FnMut(LocalDefId, DefPathData) -> u32, + span: Span, ) -> LocalDefId { debug!("create_def(parent={:?}, data={:?}, expn_id={:?})", parent, data, expn_id); @@ -385,6 +400,11 @@ impl Definitions { self.expansions_that_defined.insert(def_id, expn_id); } + // A relative span's parent must be an absolute span. + debug_assert_eq!(span.data_untracked().parent, None); + let _id = self.def_id_to_span.push(span); + debug_assert_eq!(_id, def_id); + def_id } @@ -412,16 +432,28 @@ impl Definitions { self.expansions_that_defined.get(&id).copied().unwrap_or_else(ExpnId::root) } + /// Retrieves the span of the given `DefId` if `DefId` is in the local crate. + #[inline] + pub fn def_span(&self, def_id: LocalDefId) -> Span { + self.def_id_to_span[def_id] + } + pub fn iter_local_def_id(&self) -> impl Iterator + '_ { self.def_id_to_hir_id.iter_enumerated().map(|(k, _)| k) } #[inline(always)] - pub fn local_def_path_hash_to_def_id(&self, hash: DefPathHash) -> Option { + pub fn local_def_path_hash_to_def_id(&self, hash: DefPathHash) -> LocalDefId { + debug_assert!(hash.stable_crate_id() == self.stable_crate_id); self.table .def_path_hash_to_index .get(&hash) - .map(|&local_def_index| LocalDefId { local_def_index }) + .map(|local_def_index| LocalDefId { local_def_index }) + .unwrap() + } + + pub fn def_path_hash_to_def_index_map(&self) -> &DefPathHashMap { + &self.table.def_path_hash_to_index } } diff --git a/compiler/rustc_hir/src/diagnostic_items.rs b/compiler/rustc_hir/src/diagnostic_items.rs new file mode 100644 index 0000000000..243014b002 --- /dev/null +++ b/compiler/rustc_hir/src/diagnostic_items.rs @@ -0,0 +1,17 @@ +use crate::def_id::DefId; +use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; +use rustc_span::Symbol; + +#[derive(Debug, Default)] +pub struct DiagnosticItems { + pub id_to_name: FxHashMap, + pub name_to_id: FxHashMap, +} + +impl HashStable for DiagnosticItems { + #[inline] + fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { + self.name_to_id.hash_stable(ctx, hasher); + } +} diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 21fe894c6f..11d0178e93 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -1,7 +1,7 @@ use crate::def::{CtorKind, DefKind, Res}; use crate::def_id::{DefId, CRATE_DEF_ID}; crate use crate::hir_id::{HirId, ItemLocalId}; -use crate::{itemlikevisit, LangItem}; +use crate::LangItem; use rustc_ast::util::parser::ExprPrecedence; use rustc_ast::{self as ast, CrateSugar, LlvmAsmDialect}; @@ -10,7 +10,6 @@ pub use rustc_ast::{BorrowKind, ImplPolarity, IsAuto}; pub use rustc_ast::{CaptureBy, Movability, Mutability}; use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece}; use rustc_data_structures::fx::FxHashMap; -use rustc_data_structures::sync::{par_for_each_in, Send, Sync}; use rustc_index::vec::IndexVec; use rustc_macros::HashStable_Generic; use rustc_span::source_map::Spanned; @@ -21,7 +20,7 @@ use rustc_target::asm::InlineAsmRegOrRegClass; use rustc_target::spec::abi::Abi; use smallvec::SmallVec; -use std::collections::{BTreeMap, BTreeSet}; +use std::collections::BTreeMap; use std::fmt; #[derive(Copy, Clone, Encodable, HashStable_Generic)] @@ -384,6 +383,16 @@ impl GenericArgs<'_> { self.args.iter().any(|arg| matches!(arg, GenericArg::Type(_))) } + pub fn has_err(&self) -> bool { + self.args.iter().any(|arg| match arg { + GenericArg::Type(ty) => matches!(ty.kind, TyKind::Err), + _ => false, + }) || self.bindings.iter().any(|arg| match arg.kind { + TypeBindingKind::Equality { ty } => matches!(ty.kind, TyKind::Err), + _ => false, + }) + } + #[inline] pub fn num_type_params(&self) -> usize { self.args.iter().filter(|arg| matches!(arg, GenericArg::Type(_))).count() @@ -441,10 +450,12 @@ pub enum GenericBound<'hir> { Trait(PolyTraitRef<'hir>, TraitBoundModifier), // FIXME(davidtwco): Introduce `PolyTraitRef::LangItem` LangItemTrait(LangItem, Span, HirId, &'hir GenericArgs<'hir>), - Unsized(Span), Outlives(Lifetime), } +#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] +rustc_data_structures::static_assert_size!(GenericBound<'_>, 48); + impl GenericBound<'_> { pub fn trait_ref(&self) -> Option<&TraitRef<'_>> { match self { @@ -458,7 +469,6 @@ impl GenericBound<'_> { GenericBound::Trait(t, ..) => t.span, GenericBound::LangItemTrait(_, span, ..) => *span, GenericBound::Outlives(l) => l.span, - GenericBound::Unsized(span) => *span, } } } @@ -652,16 +662,6 @@ pub struct WhereEqPredicate<'hir> { pub rhs_ty: &'hir Ty<'hir>, } -#[derive(Default, Encodable, Debug, HashStable_Generic)] -pub struct ModuleItems { - // Use BTreeSets here so items are in the same order as in the - // list of all items in Crate - pub items: BTreeSet, - pub trait_items: BTreeSet, - pub impl_items: BTreeSet, - pub foreign_items: BTreeSet, -} - /// The top-level data structure that stores the entire contents of /// the crate currently being compiled. /// @@ -673,10 +673,6 @@ pub struct Crate<'hir> { pub owners: IndexVec>>, pub bodies: BTreeMap>, - /// A list of modules written out in the order in which they - /// appear in the crate. This includes the main crate module. - pub modules: BTreeMap, - /// Map indicating what traits are in scope for places where this /// is relevant; generated by resolve. pub trait_map: FxHashMap>>, @@ -711,52 +707,6 @@ impl Crate<'hir> { } } -impl Crate<'_> { - /// Visits all items in the crate in some deterministic (but - /// unspecified) order. If you just need to process every item, - /// but don't care about nesting, this method is the best choice. - /// - /// If you do care about nesting -- usually because your algorithm - /// follows lexical scoping rules -- then you want a different - /// approach. You should override `visit_nested_item` in your - /// visitor and then call `intravisit::walk_crate` instead. - pub fn visit_all_item_likes<'hir, V>(&'hir self, visitor: &mut V) - where - V: itemlikevisit::ItemLikeVisitor<'hir>, - { - for owner in self.owners.iter().filter_map(Option::as_ref) { - match owner { - OwnerNode::Item(item) => visitor.visit_item(item), - OwnerNode::ForeignItem(item) => visitor.visit_foreign_item(item), - OwnerNode::ImplItem(item) => visitor.visit_impl_item(item), - OwnerNode::TraitItem(item) => visitor.visit_trait_item(item), - OwnerNode::Crate(_) => {} - } - } - } - - /// A parallel version of `visit_all_item_likes`. - pub fn par_visit_all_item_likes<'hir, V>(&'hir self, visitor: &V) - where - V: itemlikevisit::ParItemLikeVisitor<'hir> + Sync + Send, - { - par_for_each_in(&self.owners.raw, |owner| match owner { - 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), - Some(OwnerNode::TraitItem(item)) => visitor.visit_trait_item(item), - Some(OwnerNode::Crate(_)) | None => {} - }) - } - - pub fn items<'hir>(&'hir self) -> impl Iterator> + 'hir { - self.owners.iter().filter_map(|owner| match owner { - Some(OwnerNode::Item(item)) => Some(*item), - _ => None, - }) - } -} - /// A block of statements `{ .. }`, which may have a label (in this case the /// `targeted_by_break` field will be `true`) and may be `unsafe` by means of /// the `rules` being anything but `DefaultBlock`. @@ -2285,8 +2235,7 @@ pub enum TyKind<'hir> { /// /// Type parameters may be stored in each `PathSegment`. Path(QPath<'hir>), - /// An opaque type definition itself. This is currently only used for the - /// `opaque type Foo: Trait` item that `impl Trait` in desugars to. + /// An opaque type definition itself. This is only used for `impl Trait`. /// /// The generic argument list contains the lifetimes (and in the future /// possibly parameters) that are actually bound on the `impl Trait`. @@ -2343,6 +2292,13 @@ impl<'hir> InlineAsmOperand<'hir> { Self::Const { .. } | Self::Sym { .. } => None, } } + + pub fn is_clobber(&self) -> bool { + matches!( + self, + InlineAsmOperand::Out { reg: InlineAsmRegOrRegClass::Reg(_), late: _, expr: None } + ) + } } #[derive(Debug, HashStable_Generic)] @@ -2758,7 +2714,7 @@ pub enum ItemKind<'hir> { /// A module. Mod(Mod<'hir>), /// An external module, e.g. `extern { .. }`. - ForeignMod { abi: Abi, items: &'hir [ForeignItemRef<'hir>] }, + ForeignMod { abi: Abi, items: &'hir [ForeignItemRef] }, /// Module-level inline assembly (from `global_asm!`). GlobalAsm(&'hir InlineAsm<'hir>), /// A type alias, e.g., `type Foo = Bar`. @@ -2795,7 +2751,7 @@ pub struct Impl<'hir> { pub of_trait: Option>, pub self_ty: &'hir Ty<'hir>, - pub items: &'hir [ImplItemRef<'hir>], + pub items: &'hir [ImplItemRef], } impl ItemKind<'_> { @@ -2859,13 +2815,12 @@ pub struct TraitItemRef { /// passes to find the impl they want without loading the ID (which /// means fewer edges in the incremental compilation graph). #[derive(Debug, HashStable_Generic)] -pub struct ImplItemRef<'hir> { +pub struct ImplItemRef { pub id: ImplItemId, #[stable_hasher(project(name))] pub ident: Ident, pub kind: AssocItemKind, pub span: Span, - pub vis: Visibility<'hir>, pub defaultness: Defaultness, } @@ -2899,12 +2854,11 @@ impl ForeignItemId { /// passes to find the impl they want without loading the ID (which /// means fewer edges in the incremental compilation graph). #[derive(Debug, HashStable_Generic)] -pub struct ForeignItemRef<'hir> { +pub struct ForeignItemRef { pub id: ForeignItemId, #[stable_hasher(project(name))] pub ident: Ident, pub span: Span, - pub vis: Visibility<'hir>, } #[derive(Debug)] @@ -3233,12 +3187,7 @@ impl<'hir> Node<'hir> { } } - /// Returns `Constness::Const` when this node is a const fn/impl/item, - /// - /// HACK(fee1-dead): or an associated type in a trait. This works because - /// only typeck cares about const trait predicates, so although the predicates - /// query would return const predicates when it does not need to be const, - /// it wouldn't have any effect. + /// Returns `Constness::Const` when this node is a const fn/impl/item. pub fn constness_for_typeck(&self) -> Constness { match self { Node::Item(Item { @@ -3257,7 +3206,6 @@ impl<'hir> Node<'hir> { Node::Item(Item { kind: ItemKind::Const(..), .. }) | Node::TraitItem(TraitItem { kind: TraitItemKind::Const(..), .. }) - | Node::TraitItem(TraitItem { kind: TraitItemKind::Type(..), .. }) | Node::ImplItem(ImplItem { kind: ImplItemKind::Const(..), .. }) => Constness::Const, _ => Constness::NotConst, diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index f4fbfd2692..1ac2625dd4 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -32,7 +32,6 @@ //! example generator inference, and possibly also HIR borrowck. use crate::hir::*; -use crate::hir_id::CRATE_HIR_ID; use crate::itemlikevisit::{ItemLikeVisitor, ParItemLikeVisitor}; use rustc_ast::walk_list; use rustc_ast::{Attribute, Label}; @@ -393,10 +392,10 @@ pub trait Visitor<'v>: Sized { fn visit_impl_item(&mut self, ii: &'v ImplItem<'v>) { walk_impl_item(self, ii) } - fn visit_foreign_item_ref(&mut self, ii: &'v ForeignItemRef<'v>) { + fn visit_foreign_item_ref(&mut self, ii: &'v ForeignItemRef) { walk_foreign_item_ref(self, ii) } - fn visit_impl_item_ref(&mut self, ii: &'v ImplItemRef<'v>) { + fn visit_impl_item_ref(&mut self, ii: &'v ImplItemRef) { walk_impl_item_ref(self, ii) } fn visit_trait_ref(&mut self, t: &'v TraitRef<'v>) { @@ -477,17 +476,6 @@ pub trait Visitor<'v>: Sized { } } -/// Walks the contents of a crate. See also `Crate::visit_all_items`. -pub fn walk_crate<'v, V: Visitor<'v>>(visitor: &mut V, krate: &'v Crate<'v>) { - let top_mod = krate.module(); - visitor.visit_mod(top_mod, top_mod.inner, CRATE_HIR_ID); - for (&id, attrs) in krate.attrs.iter() { - for a in *attrs { - visitor.visit_attribute(id, a) - } - } -} - pub fn walk_mod<'v, V: Visitor<'v>>(visitor: &mut V, module: &'v Mod<'v>, mod_hir_id: HirId) { visitor.visit_id(mod_hir_id); for &item_id in module.item_ids { @@ -883,7 +871,6 @@ pub fn walk_param_bound<'v, V: Visitor<'v>>(visitor: &mut V, bound: &'v GenericB visitor.visit_generic_args(span, args); } GenericBound::Outlives(ref lifetime) => visitor.visit_lifetime(lifetime), - GenericBound::Unsized(_) => {} } } @@ -1055,22 +1042,20 @@ pub fn walk_impl_item<'v, V: Visitor<'v>>(visitor: &mut V, impl_item: &'v ImplIt pub fn walk_foreign_item_ref<'v, V: Visitor<'v>>( visitor: &mut V, - foreign_item_ref: &'v ForeignItemRef<'v>, + foreign_item_ref: &'v ForeignItemRef, ) { // N.B., deliberately force a compilation error if/when new fields are added. - let ForeignItemRef { id, ident, span: _, ref vis } = *foreign_item_ref; + let ForeignItemRef { id, ident, span: _ } = *foreign_item_ref; visitor.visit_nested_foreign_item(id); visitor.visit_ident(ident); - visitor.visit_vis(vis); } -pub fn walk_impl_item_ref<'v, V: Visitor<'v>>(visitor: &mut V, impl_item_ref: &'v ImplItemRef<'v>) { +pub fn walk_impl_item_ref<'v, V: Visitor<'v>>(visitor: &mut V, impl_item_ref: &'v ImplItemRef) { // N.B., deliberately force a compilation error if/when new fields are added. - let ImplItemRef { id, ident, ref kind, span: _, ref vis, ref defaultness } = *impl_item_ref; + let ImplItemRef { id, ident, ref kind, span: _, ref defaultness } = *impl_item_ref; visitor.visit_nested_impl_item(id); visitor.visit_ident(ident); visitor.visit_associated_item_kind(kind); - visitor.visit_vis(vis); visitor.visit_defaultness(defaultness); } diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs index b85ed0cb4b..f35353dbfb 100644 --- a/compiler/rustc_hir/src/lang_items.rs +++ b/compiler/rustc_hir/src/lang_items.rs @@ -283,6 +283,7 @@ language_item_table! { // a weak lang item, but do not have it defined. Panic, sym::panic, panic_fn, Target::Fn, GenericRequirement::None; 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; @@ -298,8 +299,10 @@ language_item_table! { DropInPlace, sym::drop_in_place, drop_in_place_fn, Target::Fn, GenericRequirement::Minimum(1); Oom, sym::oom, oom, Target::Fn, GenericRequirement::None; AllocLayout, sym::alloc_layout, alloc_layout, Target::Struct, GenericRequirement::None; + ConstEvalSelect, sym::const_eval_select, const_eval_select, Target::Fn, GenericRequirement::Exact(4); + ConstConstEvalSelect, sym::const_eval_select_ct,const_eval_select_ct, Target::Fn, GenericRequirement::Exact(4); - Start, sym::start, start_fn, Target::Fn, GenericRequirement::None; + Start, sym::start, start_fn, Target::Fn, GenericRequirement::Exact(1); EhPersonality, sym::eh_personality, eh_personality, Target::Fn, GenericRequirement::None; EhCatchTypeinfo, sym::eh_catch_typeinfo, eh_catch_typeinfo, Target::Static, GenericRequirement::None; diff --git a/compiler/rustc_hir/src/lib.rs b/compiler/rustc_hir/src/lib.rs index 4257527383..f5ea044e24 100644 --- a/compiler/rustc_hir/src/lib.rs +++ b/compiler/rustc_hir/src/lib.rs @@ -16,7 +16,9 @@ extern crate rustc_data_structures; mod arena; pub mod def; +pub mod def_path_hash_map; pub mod definitions; +pub mod diagnostic_items; pub use rustc_span::def_id; mod hir; pub mod hir_id; diff --git a/compiler/rustc_hir/src/stable_hash_impls.rs b/compiler/rustc_hir/src/stable_hash_impls.rs index 422a106487..9d5ef279dd 100644 --- a/compiler/rustc_hir/src/stable_hash_impls.rs +++ b/compiler/rustc_hir/src/stable_hash_impls.rs @@ -33,6 +33,25 @@ impl ToStableHashKey for HirId { } } +impl ToStableHashKey for ItemLocalId { + type KeyType = ItemLocalId; + + #[inline] + fn to_stable_hash_key(&self, _: &HirCtx) -> ItemLocalId { + *self + } +} + +impl ToStableHashKey for BodyId { + type KeyType = (DefPathHash, ItemLocalId); + + #[inline] + fn to_stable_hash_key(&self, hcx: &HirCtx) -> (DefPathHash, ItemLocalId) { + let BodyId { hir_id } = *self; + hir_id.to_stable_hash_key(hcx) + } +} + impl ToStableHashKey for ItemId { type KeyType = DefPathHash; diff --git a/compiler/rustc_hir_pretty/Cargo.toml b/compiler/rustc_hir_pretty/Cargo.toml index c7510b7ec1..46a8e7deee 100644 --- a/compiler/rustc_hir_pretty/Cargo.toml +++ b/compiler/rustc_hir_pretty/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustc_hir_pretty" version = "0.0.0" -edition = "2018" +edition = "2021" [lib] doctest = false diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 42e51f4bb4..9196344cb3 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -51,19 +51,6 @@ pub struct NoAnn; impl PpAnn for NoAnn {} pub const NO_ANN: &dyn PpAnn = &NoAnn; -impl PpAnn for hir::Crate<'_> { - fn nested(&self, state: &mut State<'_>, nested: Nested) { - match nested { - Nested::Item(id) => state.print_item(self.item(id)), - Nested::TraitItem(id) => state.print_trait_item(self.trait_item(id)), - Nested::ImplItem(id) => state.print_impl_item(self.impl_item(id)), - Nested::ForeignItem(id) => state.print_foreign_item(self.foreign_item(id)), - Nested::Body(id) => state.print_expr(&self.body(id).value), - Nested::BodyParamPat(id, i) => state.print_pat(&self.body(id).params[i].pat), - } - } -} - /// Identical to the `PpAnn` implementation for `hir::Crate`, /// except it avoids creating a dependency on the whole crate. impl PpAnn for &dyn rustc_hir::intravisit::Map<'_> { @@ -1036,7 +1023,7 @@ impl<'a> State<'a> { self.maybe_print_comment(st.span.lo()); match st.kind { hir::StmtKind::Local(ref loc) => { - self.print_local(loc.init.as_deref(), |this| this.print_local_decl(&loc)); + self.print_local(loc.init, |this| this.print_local_decl(&loc)); } hir::StmtKind::Item(item) => self.ann.nested(self, Nested::Item(item)), hir::StmtKind::Expr(ref expr) => { @@ -2232,9 +2219,6 @@ impl<'a> State<'a> { GenericBound::Outlives(lt) => { self.print_lifetime(lt); } - GenericBound::Unsized(_) => { - self.s.word("?Sized"); - } } } } diff --git a/compiler/rustc_incremental/Cargo.toml b/compiler/rustc_incremental/Cargo.toml index 9156243a10..dece752c19 100644 --- a/compiler/rustc_incremental/Cargo.toml +++ b/compiler/rustc_incremental/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustc_incremental" version = "0.0.0" -edition = "2018" +edition = "2021" [lib] doctest = false diff --git a/compiler/rustc_incremental/src/assert_dep_graph.rs b/compiler/rustc_incremental/src/assert_dep_graph.rs index 0a558eb055..d42e2f7a99 100644 --- a/compiler/rustc_incremental/src/assert_dep_graph.rs +++ b/compiler/rustc_incremental/src/assert_dep_graph.rs @@ -74,7 +74,7 @@ pub fn assert_dep_graph(tcx: TyCtxt<'_>) { let mut visitor = IfThisChanged { tcx, if_this_changed: vec![], then_this_would_need: vec![] }; visitor.process_attrs(hir::CRATE_HIR_ID); - tcx.hir().krate().visit_all_item_likes(&mut visitor.as_deep_visitor()); + tcx.hir().visit_all_item_likes(&mut visitor.as_deep_visitor()); (visitor.if_this_changed, visitor.then_this_would_need) }; diff --git a/compiler/rustc_incremental/src/persist/dirty_clean.rs b/compiler/rustc_incremental/src/persist/dirty_clean.rs index c4dc0fbadc..55286384de 100644 --- a/compiler/rustc_incremental/src/persist/dirty_clean.rs +++ b/compiler/rustc_incremental/src/persist/dirty_clean.rs @@ -137,12 +137,11 @@ pub fn check_dirty_clean_annotations(tcx: TyCtxt<'_>) { } tcx.dep_graph.with_ignore(|| { - let krate = tcx.hir().krate(); let mut dirty_clean_visitor = DirtyCleanVisitor { tcx, checked_attrs: Default::default() }; - krate.visit_all_item_likes(&mut dirty_clean_visitor); + tcx.hir().visit_all_item_likes(&mut dirty_clean_visitor); let mut all_attrs = FindAllAttrs { tcx, found_attrs: vec![] }; - intravisit::walk_crate(&mut all_attrs, krate); + tcx.hir().walk_attributes(&mut all_attrs); // Note that we cannot use the existing "unused attribute"-infrastructure // here, since that is running before codegen. This is also the reason why diff --git a/compiler/rustc_incremental/src/persist/file_format.rs b/compiler/rustc_incremental/src/persist/file_format.rs index b821ed6cff..572a4fc697 100644 --- a/compiler/rustc_incremental/src/persist/file_format.rs +++ b/compiler/rustc_incremental/src/persist/file_format.rs @@ -12,10 +12,12 @@ use std::env; use std::fs; use std::io::{self, Read}; -use std::path::Path; +use std::path::{Path, PathBuf}; +use rustc_data_structures::memmap::Mmap; use rustc_serialize::opaque::{FileEncodeResult, FileEncoder}; use rustc_serialize::Encoder; +use rustc_session::Session; /// The first few bytes of files generated by incremental compilation. const FILE_MAGIC: &[u8] = b"RSIC"; @@ -28,7 +30,7 @@ const HEADER_FORMAT_VERSION: u16 = 0; /// the Git commit hash. const RUSTC_VERSION: Option<&str> = option_env!("CFG_VERSION"); -pub fn write_file_header(stream: &mut FileEncoder, nightly_build: bool) -> FileEncodeResult { +pub(crate) fn write_file_header(stream: &mut FileEncoder, nightly_build: bool) -> FileEncodeResult { stream.emit_raw_bytes(FILE_MAGIC)?; stream.emit_raw_bytes(&[ (HEADER_FORMAT_VERSION >> 0) as u8, @@ -41,6 +43,61 @@ pub fn write_file_header(stream: &mut FileEncoder, nightly_build: bool) -> FileE stream.emit_raw_bytes(rustc_version.as_bytes()) } +pub(crate) fn save_in(sess: &Session, path_buf: PathBuf, name: &str, encode: F) +where + F: FnOnce(&mut FileEncoder) -> FileEncodeResult, +{ + debug!("save: storing data in {}", path_buf.display()); + + // Delete the old file, if any. + // Note: It's important that we actually delete the old file and not just + // truncate and overwrite it, since it might be a shared hard-link, the + // underlying data of which we don't want to modify. + // + // We have to ensure we have dropped the memory maps to this file + // before performing this removal. + match fs::remove_file(&path_buf) { + Ok(()) => { + debug!("save: remove old file"); + } + Err(err) if err.kind() == io::ErrorKind::NotFound => (), + Err(err) => { + sess.err(&format!( + "unable to delete old {} at `{}`: {}", + name, + path_buf.display(), + err + )); + return; + } + } + + let mut encoder = match FileEncoder::new(&path_buf) { + Ok(encoder) => encoder, + Err(err) => { + sess.err(&format!("failed to create {} at `{}`: {}", name, path_buf.display(), err)); + return; + } + }; + + if let Err(err) = write_file_header(&mut encoder, sess.is_nightly_build()) { + sess.err(&format!("failed to write {} header to `{}`: {}", name, path_buf.display(), err)); + return; + } + + if let Err(err) = encode(&mut encoder) { + sess.err(&format!("failed to write {} to `{}`: {}", name, path_buf.display(), err)); + return; + } + + if let Err(err) = encoder.flush() { + sess.err(&format!("failed to flush {} to `{}`: {}", name, path_buf.display(), err)); + return; + } + + debug!("save: data written to disk successfully"); +} + /// Reads the contents of a file with a file header as defined in this module. /// /// - Returns `Ok(Some(data, pos))` if the file existed and was generated by a @@ -54,14 +111,21 @@ pub fn read_file( report_incremental_info: bool, path: &Path, nightly_build: bool, -) -> io::Result, usize)>> { - let data = match fs::read(path) { - Ok(data) => data, +) -> io::Result> { + let file = match fs::File::open(path) { + Ok(file) => file, Err(err) if err.kind() == io::ErrorKind::NotFound => return Ok(None), Err(err) => return Err(err), }; + // SAFETY: This process must not modify nor remove the backing file while the memory map lives. + // For the dep-graph and the work product index, it is as soon as the decoding is done. + // For the query result cache, the memory map is dropped in save_dep_graph before calling + // save_in and trying to remove the backing file. + // + // There is no way to prevent another process from modifying this file. + let mmap = unsafe { Mmap::map(file) }?; - let mut file = io::Cursor::new(data); + let mut file = io::Cursor::new(&*mmap); // Check FILE_MAGIC { @@ -103,7 +167,7 @@ pub fn read_file( } let post_header_start_pos = file.position() as usize; - Ok(Some((file.into_inner(), post_header_start_pos))) + Ok(Some((mmap, post_header_start_pos))) } fn report_format_mismatch(report_incremental_info: bool, file: &Path, message: &str) { diff --git a/compiler/rustc_incremental/src/persist/load.rs b/compiler/rustc_incremental/src/persist/load.rs index 437d559644..4d38556e5d 100644 --- a/compiler/rustc_incremental/src/persist/load.rs +++ b/compiler/rustc_incremental/src/persist/load.rs @@ -1,6 +1,7 @@ //! Code to save/load the dep-graph from files. use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::memmap::Mmap; use rustc_middle::dep_graph::{SerializedDepGraph, WorkProduct, WorkProductId}; use rustc_middle::ty::OnDiskCache; use rustc_serialize::opaque::Decoder; @@ -48,7 +49,7 @@ fn load_data( report_incremental_info: bool, path: &Path, nightly_build: bool, -) -> LoadResult<(Vec, usize)> { +) -> LoadResult<(Mmap, usize)> { match file_format::read_file(report_incremental_info, path, nightly_build) { Ok(Some(data_and_pos)) => LoadResult::Ok { data: data_and_pos }, Ok(None) => { diff --git a/compiler/rustc_incremental/src/persist/save.rs b/compiler/rustc_incremental/src/persist/save.rs index a8455854eb..6c683058b1 100644 --- a/compiler/rustc_incremental/src/persist/save.rs +++ b/compiler/rustc_incremental/src/persist/save.rs @@ -6,8 +6,6 @@ use rustc_serialize::opaque::{FileEncodeResult, FileEncoder}; use rustc_serialize::Encodable as RustcEncodable; use rustc_session::Session; use std::fs; -use std::io; -use std::path::PathBuf; use super::data::*; use super::dirty_clean; @@ -44,7 +42,14 @@ pub fn save_dep_graph(tcx: TyCtxt<'_>) { join( move || { sess.time("incr_comp_persist_result_cache", || { - save_in(sess, query_cache_path, "query cache", |e| encode_query_cache(tcx, e)); + // Drop the memory map so that we can remove the file and write to it. + if let Some(odc) = &tcx.on_disk_cache { + odc.drop_serialized_data(tcx); + } + + file_format::save_in(sess, query_cache_path, "query cache", |e| { + encode_query_cache(tcx, e) + }); }); }, move || { @@ -86,7 +91,9 @@ pub fn save_work_product_index( debug!("save_work_product_index()"); dep_graph.assert_ignored(); let path = work_products_path(sess); - save_in(sess, path, "work product index", |e| encode_work_product_index(&new_work_products, e)); + file_format::save_in(sess, path, "work product index", |e| { + encode_work_product_index(&new_work_products, e) + }); // We also need to clean out old work-products, as not all of them are // deleted during invalidation. Some object files don't change their @@ -113,58 +120,6 @@ pub fn save_work_product_index( }); } -pub(crate) fn save_in(sess: &Session, path_buf: PathBuf, name: &str, encode: F) -where - F: FnOnce(&mut FileEncoder) -> FileEncodeResult, -{ - debug!("save: storing data in {}", path_buf.display()); - - // Delete the old file, if any. - // Note: It's important that we actually delete the old file and not just - // truncate and overwrite it, since it might be a shared hard-link, the - // underlying data of which we don't want to modify - match fs::remove_file(&path_buf) { - Ok(()) => { - debug!("save: remove old file"); - } - Err(err) if err.kind() == io::ErrorKind::NotFound => (), - Err(err) => { - sess.err(&format!( - "unable to delete old {} at `{}`: {}", - name, - path_buf.display(), - err - )); - return; - } - } - - let mut encoder = match FileEncoder::new(&path_buf) { - Ok(encoder) => encoder, - Err(err) => { - sess.err(&format!("failed to create {} at `{}`: {}", name, path_buf.display(), err)); - return; - } - }; - - if let Err(err) = file_format::write_file_header(&mut encoder, sess.is_nightly_build()) { - sess.err(&format!("failed to write {} header to `{}`: {}", name, path_buf.display(), err)); - return; - } - - if let Err(err) = encode(&mut encoder) { - sess.err(&format!("failed to write {} to `{}`: {}", name, path_buf.display(), err)); - return; - } - - if let Err(err) = encoder.flush() { - sess.err(&format!("failed to flush {} to `{}`: {}", name, path_buf.display(), err)); - return; - } - - debug!("save: data written to disk successfully"); -} - fn encode_work_product_index( work_products: &FxHashMap, encoder: &mut FileEncoder, diff --git a/compiler/rustc_index/Cargo.toml b/compiler/rustc_index/Cargo.toml index e1a2b61976..b984a1321e 100644 --- a/compiler/rustc_index/Cargo.toml +++ b/compiler/rustc_index/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustc_index" version = "0.0.0" -edition = "2018" +edition = "2021" [lib] doctest = false diff --git a/compiler/rustc_index/src/bit_set.rs b/compiler/rustc_index/src/bit_set.rs index aeb3f9970a..573124c8ec 100644 --- a/compiler/rustc_index/src/bit_set.rs +++ b/compiler/rustc_index/src/bit_set.rs @@ -841,7 +841,7 @@ impl GrowableBitSet { #[inline] pub fn contains(&self, elem: T) -> bool { let (word_index, mask) = word_index_and_mask(elem); - if let Some(word) = self.bit_set.words.get(word_index) { (word & mask) != 0 } else { false } + self.bit_set.words.get(word_index).map_or(false, |word| (word & mask) != 0) } } @@ -990,9 +990,8 @@ impl BitMatrix { pub fn insert_all_into_row(&mut self, row: R) { assert!(row.index() < self.num_rows); let (start, end) = self.range(row); - let words = &mut self.words[..]; - for index in start..end { - words[index] = !0; + for word in self.words[start..end].iter_mut() { + *word = !0; } self.clear_excess_bits(row); } @@ -1072,13 +1071,9 @@ impl SparseBitMatrix { } fn ensure_row(&mut self, row: R) -> &mut HybridBitSet { - // Instantiate any missing rows up to and including row `row` with an - // empty HybridBitSet. - self.rows.ensure_contains_elem(row, || None); - + // Instantiate any missing rows up to and including row `row` with an empty HybridBitSet. // Then replace row `row` with a full HybridBitSet if necessary. - let num_columns = self.num_columns; - self.rows[row].get_or_insert_with(|| HybridBitSet::new_empty(num_columns)) + self.rows.get_or_insert_with(row, || HybridBitSet::new_empty(self.num_columns)) } /// Sets the cell at `(row, column)` to true. Put another way, insert @@ -1148,7 +1143,7 @@ impl SparseBitMatrix { /// Iterates through all the columns set to true in a given row of /// the matrix. - pub fn iter<'a>(&'a self, row: R) -> impl Iterator + 'a { + pub fn iter(&self, row: R) -> impl Iterator + '_ { self.row(row).into_iter().flat_map(|r| r.iter()) } diff --git a/compiler/rustc_index/src/lib.rs b/compiler/rustc_index/src/lib.rs index 0093fa5e56..a72a27e07b 100644 --- a/compiler/rustc_index/src/lib.rs +++ b/compiler/rustc_index/src/lib.rs @@ -2,9 +2,8 @@ #![feature(bench_black_box)] #![feature(extend_one)] #![feature(iter_zip)] -#![feature(unboxed_closures)] +#![feature(min_specialization)] #![feature(test)] -#![feature(fn_traits)] pub mod bit_set; pub mod vec; diff --git a/compiler/rustc_index/src/vec.rs b/compiler/rustc_index/src/vec.rs index 246fa28d98..69578e85f2 100644 --- a/compiler/rustc_index/src/vec.rs +++ b/compiler/rustc_index/src/vec.rs @@ -3,9 +3,9 @@ use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; use std::fmt; use std::fmt::Debug; use std::hash::Hash; -use std::iter::{self, FromIterator}; +use std::iter::FromIterator; use std::marker::PhantomData; -use std::ops::{Index, IndexMut, Range, RangeBounds}; +use std::ops::{Index, IndexMut, RangeBounds}; use std::slice; use std::vec; @@ -124,7 +124,9 @@ macro_rules! newtype_index { #[inline] $v const fn from_usize(value: usize) -> Self { - // FIXME: replace with `assert!(value <= ($max as usize));` once `const_panic` is stable + #[cfg(not(bootstrap))] + assert!(value <= ($max as usize)); + #[cfg(bootstrap)] [()][(value > ($max as usize)) as usize]; unsafe { Self::from_u32_unchecked(value as u32) @@ -133,7 +135,9 @@ macro_rules! newtype_index { #[inline] $v const fn from_u32(value: u32) -> Self { - // FIXME: replace with `assert!(value <= $max);` once `const_panic` is stable + #[cfg(not(bootstrap))] + assert!(value <= $max); + #[cfg(bootstrap)] [()][(value > $max) as usize]; unsafe { Self::from_u32_unchecked(value) @@ -518,8 +522,6 @@ impl fmt::Debug for IndexVec { } } -pub type Enumerated = iter::Map, IntoIdx>; - impl IndexVec { #[inline] pub fn new() -> Self { @@ -596,8 +598,10 @@ impl IndexVec { } #[inline] - pub fn into_iter_enumerated(self) -> Enumerated> { - self.raw.into_iter().enumerate().map(IntoIdx { _marker: PhantomData }) + pub fn into_iter_enumerated( + self, + ) -> impl DoubleEndedIterator + ExactSizeIterator { + self.raw.into_iter().enumerate().map(|(n, t)| (I::new(n), t)) } #[inline] @@ -606,13 +610,15 @@ impl IndexVec { } #[inline] - pub fn iter_enumerated(&self) -> Enumerated> { - self.raw.iter().enumerate().map(IntoIdx { _marker: PhantomData }) + pub fn iter_enumerated( + &self, + ) -> impl DoubleEndedIterator + ExactSizeIterator + '_ { + self.raw.iter().enumerate().map(|(n, t)| (I::new(n), t)) } #[inline] - pub fn indices(&self) -> iter::Map, IntoIdx> { - (0..self.len()).map(IntoIdx { _marker: PhantomData }) + pub fn indices(&self) -> impl DoubleEndedIterator + ExactSizeIterator + 'static { + (0..self.len()).map(|n| I::new(n)) } #[inline] @@ -621,24 +627,23 @@ impl IndexVec { } #[inline] - pub fn iter_enumerated_mut(&mut self) -> Enumerated> { - self.raw.iter_mut().enumerate().map(IntoIdx { _marker: PhantomData }) + pub fn iter_enumerated_mut( + &mut self, + ) -> impl DoubleEndedIterator + ExactSizeIterator + '_ { + self.raw.iter_mut().enumerate().map(|(n, t)| (I::new(n), t)) } #[inline] - pub fn drain<'a, R: RangeBounds>( - &'a mut self, - range: R, - ) -> impl Iterator + 'a { + pub fn drain>(&mut self, range: R) -> impl Iterator + '_ { self.raw.drain(range) } #[inline] - pub fn drain_enumerated<'a, R: RangeBounds>( - &'a mut self, + pub fn drain_enumerated>( + &mut self, range: R, - ) -> impl Iterator + 'a { - self.raw.drain(range).enumerate().map(IntoIdx { _marker: PhantomData }) + ) -> impl Iterator + '_ { + self.raw.drain(range).enumerate().map(|(n, t)| (I::new(n), t)) } #[inline] @@ -720,6 +725,27 @@ impl IndexVec { } } +/// `IndexVec` is often used as a map, so it provides some map-like APIs. +impl IndexVec> { + #[inline] + pub fn insert(&mut self, index: I, value: T) -> Option { + self.ensure_contains_elem(index, || None); + self[index].replace(value) + } + + #[inline] + pub fn get_or_insert_with(&mut self, index: I, value: impl FnOnce() -> T) -> &mut T { + self.ensure_contains_elem(index, || None); + self[index].get_or_insert_with(value) + } + + #[inline] + pub fn remove(&mut self, index: I) -> Option { + self.ensure_contains_elem(index, || None); + self[index].take() + } +} + impl IndexVec { #[inline] pub fn resize(&mut self, new_len: usize, value: T) { @@ -817,36 +843,5 @@ impl<'a, I: Idx, T> IntoIterator for &'a mut IndexVec { } } -pub struct IntoIdx { - _marker: PhantomData, -} -impl FnOnce<((usize, T),)> for IntoIdx { - type Output = (I, T); - - extern "rust-call" fn call_once(self, ((n, t),): ((usize, T),)) -> Self::Output { - (I::new(n), t) - } -} - -impl FnMut<((usize, T),)> for IntoIdx { - extern "rust-call" fn call_mut(&mut self, ((n, t),): ((usize, T),)) -> Self::Output { - (I::new(n), t) - } -} - -impl FnOnce<(usize,)> for IntoIdx { - type Output = I; - - extern "rust-call" fn call_once(self, (n,): (usize,)) -> Self::Output { - I::new(n) - } -} - -impl FnMut<(usize,)> for IntoIdx { - extern "rust-call" fn call_mut(&mut self, (n,): (usize,)) -> Self::Output { - I::new(n) - } -} - #[cfg(test)] mod tests; diff --git a/compiler/rustc_infer/Cargo.toml b/compiler/rustc_infer/Cargo.toml index 15649bb678..f87ea43b1a 100644 --- a/compiler/rustc_infer/Cargo.toml +++ b/compiler/rustc_infer/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustc_infer" version = "0.0.0" -edition = "2018" +edition = "2021" [lib] doctest = false diff --git a/compiler/rustc_infer/src/infer/at.rs b/compiler/rustc_infer/src/infer/at.rs index 11ee8fb17a..cff848eeb6 100644 --- a/compiler/rustc_infer/src/infer/at.rs +++ b/compiler/rustc_infer/src/infer/at.rs @@ -187,11 +187,11 @@ impl<'a, 'tcx> At<'a, 'tcx> { impl<'a, 'tcx> Trace<'a, 'tcx> { /// Makes `a <: b` where `a` may or may not be expected (if /// `a_is_expected` is true, then `a` is expected). + #[instrument(skip(self), level = "debug")] pub fn sub(self, a: T, b: T) -> InferResult<'tcx, ()> where T: Relate<'tcx>, { - debug!("sub({:?} <: {:?})", a, b); let Trace { at, trace, a_is_expected } = self; at.infcx.commit_if_ok(|_| { let mut fields = at.infcx.combine_fields(trace, at.param_env); @@ -204,11 +204,11 @@ impl<'a, 'tcx> Trace<'a, 'tcx> { /// Makes `a == b`; the expectation is set by the call to /// `trace()`. + #[instrument(skip(self), level = "debug")] pub fn eq(self, a: T, b: T) -> InferResult<'tcx, ()> where T: Relate<'tcx>, { - debug!("eq({:?} == {:?})", a, b); let Trace { at, trace, a_is_expected } = self; at.infcx.commit_if_ok(|_| { let mut fields = at.infcx.combine_fields(trace, at.param_env); @@ -219,11 +219,11 @@ impl<'a, 'tcx> Trace<'a, 'tcx> { }) } + #[instrument(skip(self), level = "debug")] pub fn lub(self, a: T, b: T) -> InferResult<'tcx, T> where T: Relate<'tcx>, { - debug!("lub({:?} \\/ {:?})", a, b); let Trace { at, trace, a_is_expected } = self; at.infcx.commit_if_ok(|_| { let mut fields = at.infcx.combine_fields(trace, at.param_env); @@ -234,11 +234,11 @@ impl<'a, 'tcx> Trace<'a, 'tcx> { }) } + #[instrument(skip(self), level = "debug")] pub fn glb(self, a: T, b: T) -> InferResult<'tcx, T> where T: Relate<'tcx>, { - debug!("glb({:?} /\\ {:?})", a, b); let Trace { at, trace, a_is_expected } = self; at.infcx.commit_if_ok(|_| { let mut fields = at.infcx.combine_fields(trace, at.param_env); diff --git a/compiler/rustc_infer/src/infer/canonical/query_response.rs b/compiler/rustc_infer/src/infer/canonical/query_response.rs index 6a97a6c43c..2296cc6129 100644 --- a/compiler/rustc_infer/src/infer/canonical/query_response.rs +++ b/compiler/rustc_infer/src/infer/canonical/query_response.rs @@ -49,6 +49,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { /// the same thing happens, but the resulting query is marked as ambiguous. /// - Finally, if any of the obligations result in a hard error, /// then `Err(NoSolution)` is returned. + #[instrument(skip(self, inference_vars, answer, fulfill_cx), level = "trace")] pub fn make_canonicalized_query_response( &self, inference_vars: CanonicalVarValues<'tcx>, @@ -62,7 +63,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { let query_response = self.make_query_response(inference_vars, answer, fulfill_cx)?; let canonical_result = self.canonicalize_response(query_response); - debug!("make_canonicalized_query_response: canonical_result = {:#?}", canonical_result); + debug!("canonical_result = {:#?}", canonical_result); Ok(self.tcx.arena.alloc(canonical_result)) } @@ -94,6 +95,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { /// Helper for `make_canonicalized_query_response` that does /// everything up until the final canonicalization. + #[instrument(skip(self, fulfill_cx), level = "debug")] fn make_query_response( &self, inference_vars: CanonicalVarValues<'tcx>, @@ -105,13 +107,6 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { { let tcx = self.tcx; - debug!( - "make_query_response(\ - inference_vars={:?}, \ - answer={:?})", - inference_vars, answer, - ); - // Select everything, returning errors. let true_errors = fulfill_cx.select_where_possible(self).err().unwrap_or_else(Vec::new); debug!("true_errors = {:#?}", true_errors); @@ -669,8 +664,10 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for QueryTypeRelatingDelegate<'_, 'tcx> { self.obligations.push(Obligation { cause: self.cause.clone(), param_env: self.param_env, - predicate: ty::PredicateKind::RegionOutlives(ty::OutlivesPredicate(sup, sub)) - .to_predicate(self.infcx.tcx), + predicate: ty::Binder::dummy(ty::PredicateKind::RegionOutlives(ty::OutlivesPredicate( + sup, sub, + ))) + .to_predicate(self.infcx.tcx), recursion_depth: 0, }); } diff --git a/compiler/rustc_infer/src/infer/combine.rs b/compiler/rustc_infer/src/infer/combine.rs index a0ee212bed..3f54247ece 100644 --- a/compiler/rustc_infer/src/infer/combine.rs +++ b/compiler/rustc_infer/src/infer/combine.rs @@ -22,6 +22,7 @@ // is also useful to track which value is the "expected" value in // terms of error reporting. +use super::equate::Equate; use super::glb::Glb; use super::lub::Lub; use super::sub::Sub; @@ -29,7 +30,6 @@ use super::type_variable::TypeVariableValue; use super::unify_key::replace_if_possible; use super::unify_key::{ConstVarValue, ConstVariableValue}; use super::unify_key::{ConstVariableOrigin, ConstVariableOriginKind}; -use super::{equate::Equate, type_variable::Diverging}; use super::{InferCtxt, MiscVariable, TypeTrace}; use crate::traits::{Obligation, PredicateObligations}; @@ -360,7 +360,8 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> { self.obligations.push(Obligation::new( self.trace.cause.clone(), self.param_env, - ty::PredicateKind::WellFormed(b_ty.into()).to_predicate(self.infcx.tcx), + ty::Binder::dummy(ty::PredicateKind::WellFormed(b_ty.into())) + .to_predicate(self.infcx.tcx), )); } @@ -463,7 +464,7 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> { self.obligations.push(Obligation::new( self.trace.cause.clone(), self.param_env, - predicate.to_predicate(self.tcx()), + ty::Binder::dummy(predicate).to_predicate(self.tcx()), )); } } @@ -645,7 +646,7 @@ impl TypeRelation<'tcx> for Generalizer<'_, 'tcx> { .inner .borrow_mut() .type_variables() - .new_var(self.for_universe, Diverging::NotDiverging, origin); + .new_var(self.for_universe, origin); let u = self.tcx().mk_ty_var(new_var_id); // Record that we replaced `vid` with `new_var_id` as part of a generalization @@ -885,11 +886,12 @@ impl TypeRelation<'tcx> for ConstInferUnifier<'_, 'tcx> { let origin = *self.infcx.inner.borrow_mut().type_variables().var_origin(vid); - let new_var_id = self.infcx.inner.borrow_mut().type_variables().new_var( - self.for_universe, - Diverging::NotDiverging, - origin, - ); + let new_var_id = self + .infcx + .inner + .borrow_mut() + .type_variables() + .new_var(self.for_universe, origin); let u = self.tcx().mk_ty_var(new_var_id); debug!( "ConstInferUnifier: replacing original vid={:?} with new={:?}", diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 32150c7f4c..126c25f0c3 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -7,7 +7,7 @@ //! inference graph arose so that we can explain to the user what gave //! rise to a particular error. //! -//! The basis of the system are the "origin" types. An "origin" is the +//! The system is based around a set of "origin" types. An "origin" is the //! reason that a constraint or inference variable arose. There are //! different "origin" enums for different kinds of constraints/variables //! (e.g., `TypeOrigin`, `RegionVariableOrigin`). An origin always has @@ -116,7 +116,7 @@ pub(super) fn note_and_explain_region( emit_msg_span(err, prefix, description, span, suffix); } -pub(super) fn note_and_explain_free_region( +fn explain_free_region( tcx: TyCtxt<'tcx>, err: &mut DiagnosticBuilder<'_>, prefix: &str, @@ -125,7 +125,7 @@ pub(super) fn note_and_explain_free_region( ) { let (description, span) = msg_span_from_free_region(tcx, region, None); - emit_msg_span(err, prefix, description, span, suffix); + label_msg_span(err, prefix, description, span, suffix); } fn msg_span_from_free_region( @@ -135,7 +135,8 @@ fn msg_span_from_free_region( ) -> (String, Option) { match *region { ty::ReEarlyBound(_) | ty::ReFree(_) => { - msg_span_from_early_bound_and_free_regions(tcx, region) + let (msg, span) = msg_span_from_early_bound_and_free_regions(tcx, region); + (msg, Some(span)) } ty::ReStatic => ("the static lifetime".to_owned(), alt_span), ty::ReEmpty(ty::UniverseIndex::ROOT) => ("an empty lifetime".to_owned(), alt_span), @@ -147,20 +148,12 @@ fn msg_span_from_free_region( fn msg_span_from_early_bound_and_free_regions( tcx: TyCtxt<'tcx>, region: ty::Region<'tcx>, -) -> (String, Option) { +) -> (String, Span) { let sm = tcx.sess.source_map(); let scope = region.free_region_binding_scope(tcx); let node = tcx.hir().local_def_id_to_hir_id(scope.expect_local()); - let tag = match tcx.hir().find(node) { - Some(Node::Block(_) | Node::Expr(_)) => "body", - Some(Node::Item(it)) => item_scope_tag(&it), - Some(Node::TraitItem(it)) => trait_item_scope_tag(&it), - Some(Node::ImplItem(it)) => impl_item_scope_tag(&it), - Some(Node::ForeignItem(it)) => foreign_item_scope_tag(&it), - _ => unreachable!(), - }; - let (prefix, span) = match *region { + match *region { ty::ReEarlyBound(ref br) => { let mut sp = sm.guess_head_span(tcx.hir().span(node)); if let Some(param) = @@ -168,7 +161,7 @@ fn msg_span_from_early_bound_and_free_regions( { sp = param.span; } - (format!("the lifetime `{}` as defined on", br.name), sp) + (format!("the lifetime `{}` as defined here", br.name), sp) } ty::ReFree(ty::FreeRegion { bound_region: ty::BoundRegionKind::BrNamed(_, name), .. @@ -179,28 +172,26 @@ fn msg_span_from_early_bound_and_free_regions( { sp = param.span; } - (format!("the lifetime `{}` as defined on", name), sp) + (format!("the lifetime `{}` as defined here", name), sp) } ty::ReFree(ref fr) => match fr.bound_region { ty::BrAnon(idx) => { if let Some((ty, _)) = find_anon_type(tcx, region, &fr.bound_region) { - ("the anonymous lifetime defined on".to_string(), ty.span) + ("the anonymous lifetime defined here".to_string(), ty.span) } else { ( - format!("the anonymous lifetime #{} defined on", idx + 1), + format!("the anonymous lifetime #{} defined here", idx + 1), tcx.hir().span(node), ) } } _ => ( - format!("the lifetime `{}` as defined on", region), + format!("the lifetime `{}` as defined here", region), sm.guess_head_span(tcx.hir().span(node)), ), }, _ => bug!(), - }; - let (msg, opt_span) = explain_span(tcx, tag, span); - (format!("{} {}", prefix, msg), opt_span) + } } fn emit_msg_span( @@ -219,44 +210,22 @@ fn emit_msg_span( } } -fn item_scope_tag(item: &hir::Item<'_>) -> &'static str { - match item.kind { - hir::ItemKind::Impl { .. } => "impl", - hir::ItemKind::Struct(..) => "struct", - hir::ItemKind::Union(..) => "union", - hir::ItemKind::Enum(..) => "enum", - hir::ItemKind::Trait(..) => "trait", - hir::ItemKind::Fn(..) => "function body", - _ => "item", - } -} +fn label_msg_span( + err: &mut DiagnosticBuilder<'_>, + prefix: &str, + description: String, + span: Option, + suffix: &str, +) { + let message = format!("{}{}{}", prefix, description, suffix); -fn trait_item_scope_tag(item: &hir::TraitItem<'_>) -> &'static str { - match item.kind { - hir::TraitItemKind::Fn(..) => "method body", - hir::TraitItemKind::Const(..) | hir::TraitItemKind::Type(..) => "associated item", + if let Some(span) = span { + err.span_label(span, &message); + } else { + err.note(&message); } } -fn impl_item_scope_tag(item: &hir::ImplItem<'_>) -> &'static str { - match item.kind { - hir::ImplItemKind::Fn(..) => "method body", - hir::ImplItemKind::Const(..) | hir::ImplItemKind::TyAlias(..) => "associated item", - } -} - -fn foreign_item_scope_tag(item: &hir::ForeignItem<'_>) -> &'static str { - match item.kind { - hir::ForeignItemKind::Fn(..) => "method body", - hir::ForeignItemKind::Static(..) | hir::ForeignItemKind::Type => "associated item", - } -} - -fn explain_span(tcx: TyCtxt<'tcx>, heading: &str, span: Span) -> (String, Option) { - let lo = tcx.sess.source_map().lookup_char_pos(span.lo()); - (format!("the {} at {}:{}", heading, lo.line, lo.col.to_usize() + 1), Some(span)) -} - pub fn unexpected_hidden_region_diagnostic( tcx: TyCtxt<'tcx>, span: Span, @@ -291,13 +260,25 @@ pub fn unexpected_hidden_region_diagnostic( // // (*) if not, the `tainted_by_errors` field would be set to // `Some(ErrorReported)` in any case, so we wouldn't be here at all. - note_and_explain_free_region( + explain_free_region( tcx, &mut err, &format!("hidden type `{}` captures ", hidden_ty), hidden_region, "", ); + if let Some(reg_info) = tcx.is_suitable_region(hidden_region) { + let fn_returns = tcx.return_type_impl_or_dyn_traits(reg_info.def_id); + nice_region_error::suggest_new_region_bound( + tcx, + &mut err, + fn_returns, + hidden_region.to_string(), + None, + format!("captures {}", hidden_region), + None, + ) + } } _ => { // Ugh. This is a painful case: the hidden region is not one @@ -609,6 +590,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { err: &mut DiagnosticBuilder<'tcx>, cause: &ObligationCause<'tcx>, exp_found: Option>>, + terr: &TypeError<'tcx>, ) { match cause.code { ObligationCauseCode::Pattern { origin_expr: true, span: Some(span), root_ty } => { @@ -785,7 +767,15 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { err.help("try adding a diverging expression, such as `return` or `panic!(..)`"); err.help("...or use `match` instead of `let...else`"); } - _ => (), + _ => { + if let ObligationCauseCode::BindingObligation(_, binding_span) = + cause.code.peel_derives() + { + if matches!(terr, TypeError::RegionsPlaceholderMismatch) { + err.span_note(*binding_span, "the lifetime requirement is introduced here"); + } + } + } } } @@ -1724,7 +1714,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { // It reads better to have the error origin as the final // thing. - self.note_error_origin(diag, cause, exp_found); + self.note_error_origin(diag, cause, exp_found, terr); } pub fn get_impl_future_output_ty(&self, ty: Ty<'tcx>) -> Option> { @@ -1971,6 +1961,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { trace: TypeTrace<'tcx>, terr: &TypeError<'tcx>, ) -> DiagnosticBuilder<'tcx> { + use crate::traits::ObligationCauseCode::MatchExpressionArm; + debug!("report_and_explain_type_error(trace={:?}, terr={:?})", trace, terr); let span = trace.cause.span(self.tcx); @@ -2013,6 +2005,19 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { _ => {} } } + if let MatchExpressionArm(box MatchExpressionArmCause { source, .. }) = + trace.cause.code + { + if let hir::MatchSource::TryDesugar = source { + if let Some((expected_ty, found_ty)) = self.values_str(trace.values) { + err.note(&format!( + "`?` operator cannot convert from `{}` to `{}`", + found_ty.content(), + expected_ty.content(), + )); + } + } + } err } FailureCode::Error0644(failure_str) => { @@ -2036,14 +2041,24 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { expected: exp_found.expected.print_only_trait_path(), found: exp_found.found.print_only_trait_path(), }; - self.expected_found_str(pretty_exp_found) + match self.expected_found_str(pretty_exp_found) { + Some((expected, found)) if expected == found => { + self.expected_found_str(exp_found) + } + ret => ret, + } } infer::PolyTraitRefs(exp_found) => { let pretty_exp_found = ty::error::ExpectedFound { expected: exp_found.expected.print_only_trait_path(), found: exp_found.found.print_only_trait_path(), }; - self.expected_found_str(pretty_exp_found) + match self.expected_found_str(pretty_exp_found) { + Some((expected, found)) if expected == found => { + self.expected_found_str(exp_found) + } + ret => ret, + } } } } @@ -2345,7 +2360,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { ); err.span_suggestion( generics.where_clause.tail_span_for_suggestion(), - "consider adding a where clause".into(), + "consider adding a where clause", suggestion, Applicability::MaybeIncorrect, ); @@ -2509,7 +2524,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { /// within `?` desugaring. pub fn is_try_conversion(&self, span: Span, trait_def_id: DefId) -> bool { span.is_desugaring(DesugaringKind::QuestionMark) - && self.tcx.is_diagnostic_item(sym::from_trait, trait_def_id) + && self.tcx.is_diagnostic_item(sym::From, trait_def_id) } } @@ -2585,9 +2600,7 @@ impl<'tcx> ObligationCauseExt<'tcx> for ObligationCause<'tcx> { CompareImplTypeObligation { .. } => Error0308("type not compatible with trait"), MatchExpressionArm(box MatchExpressionArmCause { source, .. }) => { Error0308(match source { - hir::MatchSource::TryDesugar => { - "try expression alternatives have incompatible types" - } + hir::MatchSource::TryDesugar => "`?` operator has incompatible types", _ => "`match` arms have incompatible types", }) } diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs index c60a7149e4..35c8786dcd 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs @@ -29,11 +29,17 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { SubregionOrigin::Subtype(box TypeTrace { ref cause, .. }) => cause, _ => return None, }; - let (parent, impl_def_id) = match &cause.code { + // If we added a "points at argument expression" obligation, we remove it here, we care + // about the original obligation only. + let code = match &cause.code { + ObligationCauseCode::FunctionArgumentObligation { parent_code, .. } => &*parent_code, + _ => &cause.code, + }; + let (parent, impl_def_id) = match code { ObligationCauseCode::MatchImpl(parent, impl_def_id) => (parent, impl_def_id), _ => return None, }; - let binding_span = match **parent { + let binding_span = match parent.code { ObligationCauseCode::BindingObligation(_def_id, binding_span) => binding_span, _ => return None, }; diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mod.rs index 3f27bf67b5..6a33097700 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mod.rs @@ -14,6 +14,8 @@ mod static_impl_trait; mod trait_impl_difference; mod util; +pub use static_impl_trait::suggest_new_region_bound; + impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { pub fn try_report_nice_region_error(&self, error: &RegionResolutionError<'tcx>) -> bool { NiceRegionError::new(self, error.clone()).try_report().is_some() 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 81059fbcb1..7fba6a823d 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 @@ -189,7 +189,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { } if let SubregionOrigin::Subtype(box TypeTrace { cause, .. }) = &sub_origin { let code = match &cause.code { - ObligationCauseCode::MatchImpl(parent, ..) => &**parent, + ObligationCauseCode::MatchImpl(parent, ..) => &parent.code, _ => &cause.code, }; if let ObligationCauseCode::ItemObligation(item_def_id) = *code { @@ -217,128 +217,159 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { )); } - debug!("try_report_static_impl_trait: fn_return={:?}", fn_returns); - // FIXME: account for the need of parens in `&(dyn Trait + '_)` - let consider = "consider changing the"; - let declare = "to declare that the"; let arg = match param.param.pat.simple_ident() { Some(simple_ident) => format!("argument `{}`", simple_ident), None => "the argument".to_string(), }; - let explicit = format!("you can add an explicit `{}` lifetime bound", lifetime_name); - let explicit_static = format!("explicit `'static` bound to the lifetime of {}", arg); let captures = format!("captures data from {}", arg); - let add_static_bound = "alternatively, add an explicit `'static` bound to this reference"; - let plus_lt = format!(" + {}", lifetime_name); - for fn_return in fn_returns { - if fn_return.span.desugaring_kind().is_some() { - // Skip `async` desugaring `impl Future`. - continue; - } - 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 { - err.emit(); - return Some(ErrorReported); - }; + suggest_new_region_bound( + tcx, + &mut err, + fn_returns, + lifetime_name, + Some(arg), + captures, + Some((param.param_ty_span, param.param_ty.to_string())), + ); - if let Some(span) = opaque - .bounds - .iter() - .filter_map(|arg| match arg { - GenericBound::Outlives(Lifetime { - name: LifetimeName::Static, - span, - .. - }) => Some(*span), - _ => None, - }) - .next() - { + err.emit(); + Some(ErrorReported) + } +} + +pub fn suggest_new_region_bound( + tcx: TyCtxt<'tcx>, + err: &mut DiagnosticBuilder<'_>, + fn_returns: Vec<&rustc_hir::Ty<'_>>, + lifetime_name: String, + arg: Option, + captures: String, + param: Option<(Span, String)>, +) { + debug!("try_report_static_impl_trait: fn_return={:?}", fn_returns); + // FIXME: account for the need of parens in `&(dyn Trait + '_)` + let consider = "consider changing the"; + let declare = "to declare that the"; + let explicit = format!("you can add an explicit `{}` lifetime bound", lifetime_name); + let explicit_static = + arg.map(|arg| format!("explicit `'static` bound to the lifetime of {}", arg)); + let add_static_bound = "alternatively, add an explicit `'static` bound to this reference"; + let plus_lt = format!(" + {}", lifetime_name); + for fn_return in fn_returns { + if fn_return.span.desugaring_kind().is_some() { + // Skip `async` desugaring `impl Future`. + continue; + } + 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 { + return; + }; + + if let Some(span) = opaque + .bounds + .iter() + .filter_map(|arg| match arg { + GenericBound::Outlives(Lifetime { + name: LifetimeName::Static, + span, + .. + }) => Some(*span), + _ => None, + }) + .next() + { + if let Some(explicit_static) = &explicit_static { err.span_suggestion_verbose( span, &format!("{} `impl Trait`'s {}", consider, explicit_static), lifetime_name.clone(), Applicability::MaybeIncorrect, ); + } + if let Some((param_span, param_ty)) = param.clone() { err.span_suggestion_verbose( - param.param_ty_span, + param_span, add_static_bound, - param.param_ty.to_string(), - Applicability::MaybeIncorrect, - ); - } else if opaque - .bounds - .iter() - .filter_map(|arg| match arg { - GenericBound::Outlives(Lifetime { name, span, .. }) - if name.ident().to_string() == lifetime_name => - { - Some(*span) - } - _ => None, - }) - .next() - .is_some() - { - } else { - err.span_suggestion_verbose( - fn_return.span.shrink_to_hi(), - &format!( - "{declare} `impl Trait` {captures}, {explicit}", - declare = declare, - captures = captures, - explicit = explicit, - ), - plus_lt.clone(), + param_ty, Applicability::MaybeIncorrect, ); } + } else if opaque + .bounds + .iter() + .filter_map(|arg| match arg { + GenericBound::Outlives(Lifetime { name, span, .. }) + if name.ident().to_string() == lifetime_name => + { + Some(*span) + } + _ => None, + }) + .next() + .is_some() + { + } else { + err.span_suggestion_verbose( + fn_return.span.shrink_to_hi(), + &format!( + "{declare} `impl Trait` {captures}, {explicit}", + declare = declare, + captures = captures, + explicit = explicit, + ), + plus_lt.clone(), + Applicability::MaybeIncorrect, + ); } - TyKind::TraitObject(_, lt, _) => match lt.name { - LifetimeName::ImplicitObjectLifetimeDefault => { - err.span_suggestion_verbose( - fn_return.span.shrink_to_hi(), - &format!( - "{declare} trait object {captures}, {explicit}", - declare = declare, - captures = captures, - explicit = explicit, - ), - plus_lt.clone(), - Applicability::MaybeIncorrect, - ); - } - name if name.ident().to_string() != lifetime_name => { - // With this check we avoid suggesting redundant bounds. This - // would happen if there are nested impl/dyn traits and only - // one of them has the bound we'd suggest already there, like - // in `impl Foo + '_`. + } + TyKind::TraitObject(_, lt, _) => match lt.name { + LifetimeName::ImplicitObjectLifetimeDefault => { + err.span_suggestion_verbose( + fn_return.span.shrink_to_hi(), + &format!( + "{declare} trait object {captures}, {explicit}", + declare = declare, + captures = captures, + explicit = explicit, + ), + plus_lt.clone(), + Applicability::MaybeIncorrect, + ); + } + name if name.ident().to_string() != lifetime_name => { + // With this check we avoid suggesting redundant bounds. This + // would happen if there are nested impl/dyn traits and only + // one of them has the bound we'd suggest already there, like + // in `impl Foo + '_`. + if let Some(explicit_static) = &explicit_static { err.span_suggestion_verbose( lt.span, &format!("{} trait object's {}", consider, explicit_static), lifetime_name.clone(), Applicability::MaybeIncorrect, ); + } + if let Some((param_span, param_ty)) = param.clone() { err.span_suggestion_verbose( - param.param_ty_span, + param_span, add_static_bound, - param.param_ty.to_string(), + param_ty, Applicability::MaybeIncorrect, ); } - _ => {} - }, + } _ => {} - } + }, + _ => {} } - err.emit(); - Some(ErrorReported) } +} +impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { fn get_impl_ident_and_self_ty_from_trait( &self, def_id: DefId, 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 61c8113d05..ea9d0eae17 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 @@ -2,7 +2,7 @@ use crate::infer::error_reporting::nice_region_error::NiceRegionError; use crate::infer::lexical_region_resolve::RegionResolutionError; -use crate::infer::{Subtype, ValuePairs}; +use crate::infer::{SubregionOrigin, Subtype, ValuePairs}; use crate::traits::ObligationCauseCode::CompareImplMethodObligation; use rustc_errors::ErrorReported; use rustc_hir as hir; @@ -11,44 +11,55 @@ 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_span::{MultiSpan, Span}; +use rustc_span::{MultiSpan, Span, Symbol}; 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 { - if let Some(ref error) = self.error { - debug!("try_report_impl_not_conforming_to_trait {:?}", error); - if let RegionResolutionError::SubSupConflict( - _, - var_origin, - sub_origin, - _sub, - sup_origin, - _sup, - ) = error.clone() - { - if let (&Subtype(ref sup_trace), &Subtype(ref sub_trace)) = - (&sup_origin, &sub_origin) + let error = self.error.as_ref()?; + debug!("try_report_impl_not_conforming_to_trait {:?}", error); + if let RegionResolutionError::SubSupConflict( + _, + var_origin, + sub_origin, + _sub, + sup_origin, + _sup, + ) = error.clone() + { + if let (&Subtype(ref sup_trace), &Subtype(ref sub_trace)) = (&sup_origin, &sub_origin) { + if let ( + ValuePairs::Types(sub_expected_found), + ValuePairs::Types(sup_expected_found), + CompareImplMethodObligation { trait_item_def_id, .. }, + ) = (&sub_trace.values, &sup_trace.values, &sub_trace.cause.code) { - if let ( - ValuePairs::Types(sub_expected_found), - ValuePairs::Types(sup_expected_found), - CompareImplMethodObligation { trait_item_def_id, .. }, - ) = (&sub_trace.values, &sup_trace.values, &sub_trace.cause.code) - { - if sup_expected_found == sub_expected_found { - self.emit_err( - var_origin.span(), - sub_expected_found.expected, - sub_expected_found.found, - *trait_item_def_id, - ); - return Some(ErrorReported); - } + if sup_expected_found == sub_expected_found { + self.emit_err( + var_origin.span(), + sub_expected_found.expected, + sub_expected_found.found, + *trait_item_def_id, + ); + return Some(ErrorReported); } } } } + if let RegionResolutionError::ConcreteFailure(origin, _, _) + | RegionResolutionError::GenericBoundFailure(origin, _, _) = error.clone() + { + 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); + return Some(ErrorReported); + } + } None } @@ -107,6 +118,25 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { } err.emit(); } + + fn emit_associated_type_err( + &self, + span: Span, + item_name: Symbol, + impl_item_def_id: DefId, + trait_item_def_id: DefId, + ) { + let impl_sp = self.tcx().def_span(impl_item_def_id); + let trait_sp = self.tcx().def_span(trait_item_def_id); + let mut err = self + .tcx() + .sess + .struct_span_err(span, &format!("`impl` associated type signature for `{}` doesn't match `trait` associated type signature", item_name)); + err.span_label(impl_sp, "found"); + err.span_label(trait_sp, "expected"); + + err.emit(); + } } struct TypeParamSpanVisitor<'tcx> { diff --git a/compiler/rustc_infer/src/infer/error_reporting/note.rs b/compiler/rustc_infer/src/infer/error_reporting/note.rs index 4bc59a4baf..5f99a23f86 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/note.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/note.rs @@ -99,6 +99,12 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { "...so that the definition in impl matches the definition from the trait", ); } + infer::CompareImplTypeObligation { span, .. } => { + label_or_note( + span, + "...so that the definition in impl matches the definition from the trait", + ); + } } } @@ -356,6 +362,18 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { 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), + ), } } diff --git a/compiler/rustc_infer/src/infer/fudge.rs b/compiler/rustc_infer/src/infer/fudge.rs index c292b2bdb3..773753a036 100644 --- a/compiler/rustc_infer/src/infer/fudge.rs +++ b/compiler/rustc_infer/src/infer/fudge.rs @@ -94,13 +94,12 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { /// the actual types (`?T`, `Option`) -- and remember that /// after the snapshot is popped, the variable `?T` is no longer /// unified. + #[instrument(skip(self, f), level = "debug")] pub fn fudge_inference_if_ok(&self, f: F) -> Result where F: FnOnce() -> Result, T: TypeFoldable<'tcx>, { - debug!("fudge_inference_if_ok()"); - let variable_lengths = self.variable_lengths(); let (mut fudger, value) = self.probe(|_| { match f() { @@ -187,7 +186,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for InferenceFudger<'a, 'tcx> { if self.type_vars.0.contains(&vid) { // This variable was created during the fudging. // Recreate it with a fresh variable here. - let idx = (vid.index - self.type_vars.0.start.index) as usize; + let idx = (vid.as_usize() - self.type_vars.0.start.as_usize()) as usize; let origin = self.type_vars.1[idx]; self.infcx.next_ty_var(origin) } else { diff --git a/compiler/rustc_infer/src/infer/higher_ranked/mod.rs b/compiler/rustc_infer/src/infer/higher_ranked/mod.rs index d460222df8..ae85e55da6 100644 --- a/compiler/rustc_infer/src/infer/higher_ranked/mod.rs +++ b/compiler/rustc_infer/src/infer/higher_ranked/mod.rs @@ -9,6 +9,7 @@ use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation}; use rustc_middle::ty::{self, Binder, TypeFoldable}; impl<'a, 'tcx> CombineFields<'a, 'tcx> { + #[instrument(skip(self), level = "debug")] pub fn higher_ranked_sub( &mut self, a: Binder<'tcx, T>, @@ -18,8 +19,6 @@ impl<'a, 'tcx> CombineFields<'a, 'tcx> { where T: Relate<'tcx>, { - debug!("higher_ranked_sub(a={:?}, b={:?})", a, b); - // Rather than checking the subtype relationship between `a` and `b` // as-is, we need to do some extra work here in order to make sure // that function subtyping works correctly with respect to regions diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index bc98a3aa3f..18836d5a68 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -46,7 +46,7 @@ use self::region_constraints::{GenericKind, RegionConstraintData, VarInfos, Veri use self::region_constraints::{ RegionConstraintCollector, RegionConstraintStorage, RegionSnapshot, }; -use self::type_variable::{Diverging, TypeVariableOrigin, TypeVariableOriginKind}; +use self::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; pub mod at; pub mod canonical; @@ -64,6 +64,7 @@ mod lub; pub mod nll_relate; pub mod opaque_types; pub mod outlives; +mod projection; pub mod region_constraints; pub mod resolve; mod sub; @@ -427,6 +428,15 @@ pub enum SubregionOrigin<'tcx> { 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, + }, } // `SubregionOrigin` is used a lot. Make sure it doesn't unintentionally get bigger. @@ -692,17 +702,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { t.fold_with(&mut self.freshener()) } - /// Returns whether `ty` is a diverging type variable or not. - /// (If `ty` is not a type variable at all, returns not diverging.) - /// - /// No attempt is made to resolve `ty`. - pub fn type_var_diverges(&'a self, ty: Ty<'_>) -> Diverging { - match *ty.kind() { - ty::Infer(ty::TyVar(vid)) => self.inner.borrow_mut().type_variables().var_diverges(vid), - _ => Diverging::NotDiverging, - } - } - /// Returns the origin of the type variable identified by `vid`, or `None` /// if this is not a type variable. /// @@ -808,8 +807,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } } + #[instrument(skip(self, snapshot), level = "debug")] fn rollback_to(&self, cause: &str, snapshot: CombinedSnapshot<'a, 'tcx>) { - debug!("rollback_to(cause={})", cause); let CombinedSnapshot { undo_snapshot, region_constraints_snapshot, @@ -826,8 +825,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { inner.unwrap_region_constraints().rollback_to(region_constraints_snapshot); } + #[instrument(skip(self, snapshot), level = "debug")] fn commit_from(&self, snapshot: CombinedSnapshot<'a, 'tcx>) { - debug!("commit_from()"); let CombinedSnapshot { undo_snapshot, region_constraints_snapshot: _, @@ -842,11 +841,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } /// Executes `f` and commit the bindings. + #[instrument(skip(self, f), level = "debug")] pub fn commit_unconditionally(&self, f: F) -> R where F: FnOnce(&CombinedSnapshot<'a, 'tcx>) -> R, { - debug!("commit_unconditionally()"); let snapshot = self.start_snapshot(); let r = f(&snapshot); self.commit_from(snapshot); @@ -854,11 +853,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } /// Execute `f` and commit the bindings if closure `f` returns `Ok(_)`. + #[instrument(skip(self, f), level = "debug")] pub fn commit_if_ok(&self, f: F) -> Result where F: FnOnce(&CombinedSnapshot<'a, 'tcx>) -> Result, { - debug!("commit_if_ok()"); let snapshot = self.start_snapshot(); let r = f(&snapshot); debug!("commit_if_ok() -- r.is_ok() = {}", r.is_ok()); @@ -874,11 +873,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } /// Execute `f` then unroll any bindings it creates. + #[instrument(skip(self, f), level = "debug")] pub fn probe(&self, f: F) -> R where F: FnOnce(&CombinedSnapshot<'a, 'tcx>) -> R, { - debug!("probe()"); let snapshot = self.start_snapshot(); let r = f(&snapshot); self.rollback_to("probe", snapshot); @@ -886,11 +885,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } /// If `should_skip` is true, then execute `f` then unroll any bindings it creates. + #[instrument(skip(self, f), level = "debug")] pub fn probe_maybe_skip_leak_check(&self, should_skip: bool, f: F) -> R where F: FnOnce(&CombinedSnapshot<'a, 'tcx>) -> R, { - debug!("probe()"); let snapshot = self.start_snapshot(); let was_skip_leak_check = self.skip_leak_check.get(); if should_skip { @@ -947,18 +946,19 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { }) } + #[instrument(skip(self), level = "debug")] pub fn sub_regions( &self, origin: SubregionOrigin<'tcx>, a: ty::Region<'tcx>, b: ty::Region<'tcx>, ) { - debug!("sub_regions({:?} <: {:?})", a, b); self.inner.borrow_mut().unwrap_region_constraints().make_subregion(origin, a, b); } /// Require that the region `r` be equal to one of the regions in /// the set `regions`. + #[instrument(skip(self), level = "debug")] pub fn member_constraint( &self, opaque_type_def_id: DefId, @@ -967,7 +967,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { region: ty::Region<'tcx>, in_regions: &Lrc>>, ) { - debug!("member_constraint({:?} <: {:?})", region, in_regions); self.inner.borrow_mut().unwrap_region_constraints().member_constraint( opaque_type_def_id, definition_span, @@ -1061,12 +1060,17 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { }) } - pub fn next_ty_var_id(&self, diverging: Diverging, origin: TypeVariableOrigin) -> TyVid { - self.inner.borrow_mut().type_variables().new_var(self.universe(), diverging, origin) + /// Number of type variables created so far. + pub fn num_ty_vars(&self) -> usize { + self.inner.borrow_mut().type_variables().num_vars() + } + + pub fn next_ty_var_id(&self, origin: TypeVariableOrigin) -> TyVid { + self.inner.borrow_mut().type_variables().new_var(self.universe(), origin) } pub fn next_ty_var(&self, origin: TypeVariableOrigin) -> Ty<'tcx> { - self.tcx.mk_ty_var(self.next_ty_var_id(Diverging::NotDiverging, origin)) + self.tcx.mk_ty_var(self.next_ty_var_id(origin)) } pub fn next_ty_var_in_universe( @@ -1074,18 +1078,10 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { origin: TypeVariableOrigin, universe: ty::UniverseIndex, ) -> Ty<'tcx> { - let vid = self.inner.borrow_mut().type_variables().new_var( - universe, - Diverging::NotDiverging, - origin, - ); + let vid = self.inner.borrow_mut().type_variables().new_var(universe, origin); self.tcx.mk_ty_var(vid) } - pub fn next_diverging_ty_var(&self, origin: TypeVariableOrigin) -> Ty<'tcx> { - self.tcx.mk_ty_var(self.next_ty_var_id(Diverging::Diverges, origin)) - } - pub fn next_const_var( &self, ty: Ty<'tcx>, @@ -1197,7 +1193,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { // as the substitutions for the default, `(T, U)`. let ty_var_id = self.inner.borrow_mut().type_variables().new_var( self.universe(), - Diverging::NotDiverging, TypeVariableOrigin { kind: TypeVariableOriginKind::TypeParameterDefinition( param.name, @@ -1810,6 +1805,7 @@ impl<'tcx> SubregionOrigin<'tcx> { ReferenceOutlivesReferent(_, a) => a, CallReturn(a) => a, CompareImplMethodObligation { span, .. } => span, + CompareImplTypeObligation { span, .. } => span, } } @@ -1833,6 +1829,17 @@ impl<'tcx> SubregionOrigin<'tcx> { 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, + }, + _ => default(), } } diff --git a/compiler/rustc_infer/src/infer/nll_relate/mod.rs b/compiler/rustc_infer/src/infer/nll_relate/mod.rs index c211d8e94a..29a9cbc7a9 100644 --- a/compiler/rustc_infer/src/infer/nll_relate/mod.rs +++ b/compiler/rustc_infer/src/infer/nll_relate/mod.rs @@ -22,7 +22,6 @@ //! constituents) use crate::infer::combine::ConstEquateRelation; -use crate::infer::type_variable::Diverging; use crate::infer::InferCtxt; use crate::infer::{ConstVarValue, ConstVariableValue}; use rustc_data_structures::fx::FxHashMap; @@ -508,6 +507,7 @@ where true } + #[instrument(skip(self, info), level = "trace")] fn relate_with_variance>( &mut self, variance: ty::Variance, @@ -515,23 +515,22 @@ where a: T, b: T, ) -> RelateResult<'tcx, T> { - debug!("relate_with_variance(variance={:?}, a={:?}, b={:?})", variance, a, b); - let old_ambient_variance = self.ambient_variance; self.ambient_variance = self.ambient_variance.xform(variance); - self.ambient_variance_info = self.ambient_variance_info.clone().xform(info); + self.ambient_variance_info = self.ambient_variance_info.xform(info); - debug!("relate_with_variance: ambient_variance = {:?}", self.ambient_variance); + debug!(?self.ambient_variance); let r = self.relate(a, b)?; self.ambient_variance = old_ambient_variance; - debug!("relate_with_variance: r={:?}", r); + debug!(?r); Ok(r) } + #[instrument(skip(self), level = "debug")] fn tys(&mut self, a: Ty<'tcx>, mut b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> { let a = self.infcx.shallow_resolve(a); @@ -574,7 +573,7 @@ where } _ => { - debug!("tys(a={:?}, b={:?}, variance={:?})", a, b, self.ambient_variance); + debug!(?a, ?b, ?self.ambient_variance); // Will also handle unification of `IntVar` and `FloatVar`. self.infcx.super_combine_tys(self, a, b) @@ -582,27 +581,28 @@ where } } + #[instrument(skip(self), level = "trace")] fn regions( &mut self, a: ty::Region<'tcx>, b: ty::Region<'tcx>, ) -> RelateResult<'tcx, ty::Region<'tcx>> { - debug!("regions(a={:?}, b={:?}, variance={:?})", a, b, self.ambient_variance); + debug!(?self.ambient_variance); let v_a = self.replace_bound_region(a, ty::INNERMOST, &self.a_scopes); let v_b = self.replace_bound_region(b, ty::INNERMOST, &self.b_scopes); - debug!("regions: v_a = {:?}", v_a); - debug!("regions: v_b = {:?}", v_b); + debug!(?v_a); + debug!(?v_b); if self.ambient_covariance() { // Covariance: a <= b. Hence, `b: a`. - self.push_outlives(v_b, v_a, self.ambient_variance_info.clone()); + self.push_outlives(v_b, v_a, self.ambient_variance_info); } if self.ambient_contravariance() { // Contravariant: b <= a. Hence, `a: b`. - self.push_outlives(v_a, v_b, self.ambient_variance_info.clone()); + self.push_outlives(v_a, v_b, self.ambient_variance_info); } Ok(a) @@ -629,6 +629,7 @@ where } } + #[instrument(skip(self), level = "trace")] fn binders( &mut self, a: ty::Binder<'tcx, T>, @@ -656,7 +657,7 @@ where // - Instantiate binders on `b` universally, yielding a universe U1. // - Instantiate binders on `a` existentially in U1. - debug!("binders({:?}: {:?}, ambient_variance={:?})", a, b, self.ambient_variance); + debug!(?self.ambient_variance); if let (Some(a), Some(b)) = (a.no_bound_vars(), b.no_bound_vars()) { // Fast path for the common case. @@ -674,8 +675,8 @@ where let b_scope = self.create_scope(b, UniversallyQuantified(true)); let a_scope = self.create_scope(a, UniversallyQuantified(false)); - debug!("binders: a_scope = {:?} (existential)", a_scope); - debug!("binders: b_scope = {:?} (universal)", b_scope); + debug!(?a_scope, "(existential)"); + debug!(?b_scope, "(universal)"); self.b_scopes.push(b_scope); self.a_scopes.push(a_scope); @@ -718,8 +719,8 @@ where let a_scope = self.create_scope(a, UniversallyQuantified(true)); let b_scope = self.create_scope(b, UniversallyQuantified(false)); - debug!("binders: a_scope = {:?} (universal)", a_scope); - debug!("binders: b_scope = {:?} (existential)", b_scope); + debug!(?a_scope, "(universal)"); + debug!(?b_scope, "(existential)"); self.a_scopes.push(a_scope); self.b_scopes.push(b_scope); @@ -927,8 +928,7 @@ where // Replacing with a new variable in the universe `self.universe`, // it will be unified later with the original type variable in // the universe `_universe`. - let new_var_id = - variables.new_var(self.universe, Diverging::NotDiverging, origin); + let new_var_id = variables.new_var(self.universe, origin); let u = self.tcx().mk_ty_var(new_var_id); debug!("generalize: replacing original vid={:?} with new={:?}", vid, u); diff --git a/compiler/rustc_middle/src/ty/outlives.rs b/compiler/rustc_infer/src/infer/outlives/components.rs similarity index 94% rename from compiler/rustc_middle/src/ty/outlives.rs rename to compiler/rustc_infer/src/infer/outlives/components.rs index ef4ad998f1..98f926e9d7 100644 --- a/compiler/rustc_middle/src/ty/outlives.rs +++ b/compiler/rustc_infer/src/infer/outlives/components.rs @@ -2,10 +2,10 @@ // refers to rules defined in RFC 1214 (`OutlivesFooBar`), so see that // RFC for reference. -use crate::ty::subst::{GenericArg, GenericArgKind}; -use crate::ty::{self, Ty, TyCtxt, TypeFoldable}; use rustc_data_structures::sso::SsoHashSet; -use smallvec::SmallVec; +use rustc_middle::ty::subst::{GenericArg, GenericArgKind}; +use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable}; +use smallvec::{smallvec, SmallVec}; #[derive(Debug)] pub enum Component<'tcx> { @@ -47,14 +47,16 @@ pub enum Component<'tcx> { EscapingProjection(Vec>), } -impl<'tcx> TyCtxt<'tcx> { - /// Push onto `out` all the things that must outlive `'a` for the condition - /// `ty0: 'a` to hold. Note that `ty0` must be a **fully resolved type**. - pub fn push_outlives_components(self, ty0: Ty<'tcx>, out: &mut SmallVec<[Component<'tcx>; 4]>) { - let mut visited = SsoHashSet::new(); - compute_components(self, ty0, out, &mut visited); - debug!("components({:?}) = {:?}", ty0, out); - } +/// Push onto `out` all the things that must outlive `'a` for the condition +/// `ty0: 'a` to hold. Note that `ty0` must be a **fully resolved type**. +pub fn push_outlives_components( + tcx: TyCtxt<'tcx>, + ty0: Ty<'tcx>, + out: &mut SmallVec<[Component<'tcx>; 4]>, +) { + let mut visited = SsoHashSet::new(); + compute_components(tcx, ty0, out, &mut visited); + debug!("components({:?}) = {:?}", ty0, out); } fn compute_components( diff --git a/compiler/rustc_infer/src/infer/outlives/mod.rs b/compiler/rustc_infer/src/infer/outlives/mod.rs index 4dd5e8ba54..03d6c45a65 100644 --- a/compiler/rustc_infer/src/infer/outlives/mod.rs +++ b/compiler/rustc_infer/src/infer/outlives/mod.rs @@ -1,5 +1,6 @@ //! Various code related to computing outlives relations. +pub mod components; pub mod env; pub mod obligations; pub mod verify; diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs index 437083c68d..91a22ecc5a 100644 --- a/compiler/rustc_infer/src/infer/outlives/obligations.rs +++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs @@ -1,5 +1,5 @@ //! Code that handles "type-outlives" constraints like `T: 'a`. This -//! is based on the `push_outlives_components` function defined on the tcx, +//! is based on the `push_outlives_components` function defined in rustc_infer, //! but it adds a bit of heuristics on top, in particular to deal with //! associated types and projections. //! @@ -59,13 +59,13 @@ //! might later infer `?U` to something like `&'b u32`, which would //! imply that `'b: 'a`. +use crate::infer::outlives::components::{push_outlives_components, Component}; use crate::infer::outlives::env::RegionBoundPairs; use crate::infer::outlives::verify::VerifyBoundCx; use crate::infer::{ self, GenericKind, InferCtxt, RegionObligation, SubregionOrigin, UndoLog, VerifyBound, }; use crate::traits::{ObligationCause, ObligationCauseCode}; -use rustc_middle::ty::outlives::Component; use rustc_middle::ty::subst::GenericArgKind; use rustc_middle::ty::{self, Region, Ty, TyCtxt, TypeFoldable}; @@ -271,7 +271,7 @@ where assert!(!ty.has_escaping_bound_vars()); let mut components = smallvec![]; - self.tcx.push_outlives_components(ty, &mut components); + push_outlives_components(self.tcx, ty, &mut components); self.components_must_outlive(origin, &components, region); } diff --git a/compiler/rustc_infer/src/infer/projection.rs b/compiler/rustc_infer/src/infer/projection.rs new file mode 100644 index 0000000000..9b53ab72b0 --- /dev/null +++ b/compiler/rustc_infer/src/infer/projection.rs @@ -0,0 +1,39 @@ +use rustc_middle::traits::ObligationCause; +use rustc_middle::ty::{self, ToPredicate, Ty}; + +use crate::traits::{Obligation, PredicateObligation}; + +use super::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; +use super::InferCtxt; + +impl<'a, 'tcx> InferCtxt<'a, 'tcx> { + /// Instead of normalizing an associated type projection, + /// this function generates an inference variable and registers + /// an obligation that this inference variable must be the result + /// of the given projection. This allows us to proceed with projections + /// while they cannot be resolved yet due to missing information or + /// simply due to the lack of access to the trait resolution machinery. + pub fn infer_projection( + &self, + param_env: ty::ParamEnv<'tcx>, + projection_ty: ty::ProjectionTy<'tcx>, + cause: ObligationCause<'tcx>, + recursion_depth: usize, + obligations: &mut Vec>, + ) -> Ty<'tcx> { + let def_id = projection_ty.item_def_id; + let ty_var = self.next_ty_var(TypeVariableOrigin { + kind: TypeVariableOriginKind::NormalizeProjectionType, + span: self.tcx.def_span(def_id), + }); + let projection = ty::Binder::dummy(ty::ProjectionPredicate { projection_ty, ty: ty_var }); + let obligation = Obligation::with_depth( + cause, + recursion_depth, + param_env, + projection.to_predicate(self.tcx), + ); + obligations.push(obligation); + ty_var + } +} diff --git a/compiler/rustc_infer/src/infer/region_constraints/mod.rs b/compiler/rustc_infer/src/infer/region_constraints/mod.rs index af31ab0923..df4fdb3a98 100644 --- a/compiler/rustc_infer/src/infer/region_constraints/mod.rs +++ b/compiler/rustc_infer/src/infer/region_constraints/mod.rs @@ -540,6 +540,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> { }); } + #[instrument(skip(self, origin), level = "debug")] pub fn make_subregion( &mut self, origin: SubregionOrigin<'tcx>, @@ -547,10 +548,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> { sup: Region<'tcx>, ) { // cannot add constraints once regions are resolved - debug!( - "RegionConstraintCollector: make_subregion({:?}, {:?}) due to {:?}", - sub, sup, origin - ); + debug!("origin = {:#?}", origin); match (sub, sup) { (&ReLateBound(..), _) | (_, &ReLateBound(..)) => { diff --git a/compiler/rustc_infer/src/infer/sub.rs b/compiler/rustc_infer/src/infer/sub.rs index 1692d8ee52..8ef0d132cf 100644 --- a/compiler/rustc_infer/src/infer/sub.rs +++ b/compiler/rustc_infer/src/infer/sub.rs @@ -97,11 +97,11 @@ impl TypeRelation<'tcx> for Sub<'combine, 'infcx, 'tcx> { self.fields.obligations.push(Obligation::new( self.fields.trace.cause.clone(), self.fields.param_env, - ty::PredicateKind::Subtype(ty::SubtypePredicate { + ty::Binder::dummy(ty::PredicateKind::Subtype(ty::SubtypePredicate { a_is_expected: self.a_is_expected, a, b, - }) + })) .to_predicate(self.tcx()), )); diff --git a/compiler/rustc_infer/src/infer/type_variable.rs b/compiler/rustc_infer/src/infer/type_variable.rs index d2b0bdaf97..82970f214f 100644 --- a/compiler/rustc_infer/src/infer/type_variable.rs +++ b/compiler/rustc_infer/src/infer/type_variable.rs @@ -129,19 +129,16 @@ pub enum TypeVariableOriginKind { SubstitutionPlaceholder, AutoDeref, AdjustmentType, - DivergingFn, + + /// In type check, when we are type checking a function that + /// returns `-> dyn Foo`, we substitute a type variable for the + /// return type for diagnostic purposes. + DynReturnFn, LatticeVariable, } pub(crate) struct TypeVariableData { origin: TypeVariableOrigin, - diverging: Diverging, -} - -#[derive(Copy, Clone, Debug)] -pub enum Diverging { - NotDiverging, - Diverges, } #[derive(Copy, Clone, Debug)] @@ -191,20 +188,12 @@ impl<'tcx> TypeVariableStorage<'tcx> { } impl<'tcx> TypeVariableTable<'_, 'tcx> { - /// Returns the diverges flag given when `vid` was created. - /// - /// Note that this function does not return care whether - /// `vid` has been unified with something else or not. - pub fn var_diverges(&self, vid: ty::TyVid) -> Diverging { - self.storage.values.get(vid.index as usize).diverging - } - /// Returns the origin that was given when `vid` was created. /// /// Note that this function does not return care whether /// `vid` has been unified with something else or not. pub fn var_origin(&self, vid: ty::TyVid) -> &TypeVariableOrigin { - &self.storage.values.get(vid.index as usize).origin + &self.storage.values.get(vid.as_usize()).origin } /// Records that `a == b`, depending on `dir`. @@ -260,7 +249,6 @@ impl<'tcx> TypeVariableTable<'_, 'tcx> { pub fn new_var( &mut self, universe: ty::UniverseIndex, - diverging: Diverging, origin: TypeVariableOrigin, ) -> ty::TyVid { let eq_key = self.eq_relations().new_key(TypeVariableValue::Unknown { universe }); @@ -268,13 +256,10 @@ impl<'tcx> TypeVariableTable<'_, 'tcx> { let sub_key = self.sub_relations().new_key(()); assert_eq!(eq_key.vid, sub_key); - let index = self.values().push(TypeVariableData { origin, diverging }); - assert_eq!(eq_key.vid.index, index as u32); + let index = self.values().push(TypeVariableData { origin }); + assert_eq!(eq_key.vid.as_u32(), index as u32); - debug!( - "new_var(index={:?}, universe={:?}, diverging={:?}, origin={:?}", - eq_key.vid, universe, diverging, origin, - ); + debug!("new_var(index={:?}, universe={:?}, origin={:?}", eq_key.vid, universe, origin,); eq_key.vid } @@ -357,11 +342,11 @@ impl<'tcx> TypeVariableTable<'_, 'tcx> { &mut self, value_count: usize, ) -> (Range, Vec) { - let range = TyVid { index: value_count as u32 }..TyVid { index: self.num_vars() as u32 }; + let range = TyVid::from_usize(value_count)..TyVid::from_usize(self.num_vars()); ( range.start..range.end, - (range.start.index..range.end.index) - .map(|index| self.storage.values.get(index as usize).origin) + (range.start.as_usize()..range.end.as_usize()) + .map(|index| self.storage.values.get(index).origin) .collect(), ) } @@ -371,7 +356,7 @@ impl<'tcx> TypeVariableTable<'_, 'tcx> { pub fn unsolved_variables(&mut self) -> Vec { (0..self.storage.values.len()) .filter_map(|i| { - let vid = ty::TyVid { index: i as u32 }; + let vid = ty::TyVid::from_usize(i); match self.probe(vid) { TypeVariableValue::Unknown { .. } => Some(vid), TypeVariableValue::Known { .. } => None, @@ -415,6 +400,7 @@ pub(crate) struct TyVidEqKey<'tcx> { } impl<'tcx> From for TyVidEqKey<'tcx> { + #[inline] // make this function eligible for inlining - it is quite hot. fn from(vid: ty::TyVid) -> Self { TyVidEqKey { vid, phantom: PhantomData } } @@ -424,10 +410,10 @@ impl<'tcx> ut::UnifyKey for TyVidEqKey<'tcx> { type Value = TypeVariableValue<'tcx>; #[inline(always)] fn index(&self) -> u32 { - self.vid.index + self.vid.as_u32() } fn from_index(i: u32) -> Self { - TyVidEqKey::from(ty::TyVid { index: i }) + TyVidEqKey::from(ty::TyVid::from_u32(i)) } fn tag() -> &'static str { "TyVidEqKey" diff --git a/compiler/rustc_infer/src/traits/engine.rs b/compiler/rustc_infer/src/traits/engine.rs index 42333dc29b..dce4a87b04 100644 --- a/compiler/rustc_infer/src/traits/engine.rs +++ b/compiler/rustc_infer/src/traits/engine.rs @@ -1,5 +1,6 @@ use crate::infer::InferCtxt; use crate::traits::Obligation; +use rustc_data_structures::fx::FxHashMap; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_middle::ty::{self, ToPredicate, Ty, WithConstness}; @@ -34,7 +35,7 @@ pub trait TraitEngine<'tcx>: 'tcx { cause, recursion_depth: 0, param_env, - predicate: trait_ref.without_const().to_predicate(infcx.tcx), + predicate: ty::Binder::dummy(trait_ref).without_const().to_predicate(infcx.tcx), }, ); } @@ -73,6 +74,8 @@ pub trait TraitEngine<'tcx>: 'tcx { } fn pending_obligations(&self) -> Vec>; + + fn relationships(&mut self) -> &mut FxHashMap; } pub trait TraitEngineExt<'tcx> { diff --git a/compiler/rustc_infer/src/traits/error_reporting/mod.rs b/compiler/rustc_infer/src/traits/error_reporting/mod.rs index d0bd508bc2..9dbfa3a850 100644 --- a/compiler/rustc_infer/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/traits/error_reporting/mod.rs @@ -83,10 +83,6 @@ pub fn report_object_safety_error( messages.push(msg.clone()); } } - if trait_span.is_some() { - // Only provide the help if its a local trait, otherwise it's not actionable. - violation.solution(&mut err); - } } } let has_multi_span = !multi_span.is_empty(); @@ -104,5 +100,13 @@ pub fn report_object_safety_error( to be resolvable dynamically; for more information visit \ ", ); + if trait_span.is_some() { + let mut reported_violations: Vec<_> = reported_violations.into_iter().collect(); + reported_violations.sort(); + for violation in reported_violations { + // Only provide the help if its a local trait, otherwise it's not actionable. + violation.solution(&mut err); + } + } err } diff --git a/compiler/rustc_infer/src/traits/mod.rs b/compiler/rustc_infer/src/traits/mod.rs index b450c39894..e1d6982f16 100644 --- a/compiler/rustc_infer/src/traits/mod.rs +++ b/compiler/rustc_infer/src/traits/mod.rs @@ -66,10 +66,6 @@ pub type Selection<'tcx> = ImplSource<'tcx, PredicateObligation<'tcx>>; pub struct FulfillmentError<'tcx> { pub obligation: PredicateObligation<'tcx>, pub code: FulfillmentErrorCode<'tcx>, - /// Diagnostics only: we opportunistically change the `code.span` when we encounter an - /// obligation error caused by a call argument. When this is the case, we also signal that in - /// this field to ensure accuracy of suggestions. - pub points_at_arg_span: bool, /// Diagnostics only: the 'root' obligation which resulted in /// the failure to process `obligation`. This is the obligation /// that was initially passed to `register_predicate_obligation` @@ -128,7 +124,7 @@ impl<'tcx> FulfillmentError<'tcx> { code: FulfillmentErrorCode<'tcx>, root_obligation: PredicateObligation<'tcx>, ) -> FulfillmentError<'tcx> { - FulfillmentError { obligation, code, points_at_arg_span: false, root_obligation } + FulfillmentError { obligation, code, root_obligation } } } diff --git a/compiler/rustc_infer/src/traits/project.rs b/compiler/rustc_infer/src/traits/project.rs index 33bddf1ded..e2c13d20a9 100644 --- a/compiler/rustc_infer/src/traits/project.rs +++ b/compiler/rustc_infer/src/traits/project.rs @@ -153,47 +153,6 @@ impl<'tcx> ProjectionCache<'_, 'tcx> { assert!(!fresh_key, "never started projecting `{:?}`", key); } - /// Mark the relevant projection cache key as having its derived obligations - /// complete, so they won't have to be re-computed (this is OK to do in a - /// snapshot - if the snapshot is rolled back, the obligations will be - /// marked as incomplete again). - pub fn complete(&mut self, key: ProjectionCacheKey<'tcx>) { - let mut map = self.map(); - let ty = match map.get(&key) { - Some(&ProjectionCacheEntry::NormalizedTy(ref ty)) => { - debug!("ProjectionCacheEntry::complete({:?}) - completing {:?}", key, ty); - ty.value - } - ref value => { - // Type inference could "strand behind" old cache entries. Leave - // them alone for now. - debug!("ProjectionCacheEntry::complete({:?}) - ignoring {:?}", key, value); - return; - } - }; - - map.insert( - key, - ProjectionCacheEntry::NormalizedTy(Normalized { value: ty, obligations: vec![] }), - ); - } - - /// A specialized version of `complete` for when the key's value is known - /// to be a NormalizedTy. - pub fn complete_normalized(&mut self, key: ProjectionCacheKey<'tcx>, ty: &NormalizedTy<'tcx>) { - // We want to insert `ty` with no obligations. If the existing value - // already has no obligations (as is common) we don't insert anything. - if !ty.obligations.is_empty() { - self.map().insert( - key, - ProjectionCacheEntry::NormalizedTy(Normalized { - value: ty.value, - obligations: vec![], - }), - ); - } - } - /// Indicates that trying to normalize `key` resulted in /// ambiguity. No point in trying it again then until we gain more /// type information (in which case, the "fully resolved" key will diff --git a/compiler/rustc_infer/src/traits/util.rs b/compiler/rustc_infer/src/traits/util.rs index 3a25cb6689..c839f824d1 100644 --- a/compiler/rustc_infer/src/traits/util.rs +++ b/compiler/rustc_infer/src/traits/util.rs @@ -1,8 +1,8 @@ use smallvec::smallvec; +use crate::infer::outlives::components::{push_outlives_components, Component}; use crate::traits::{Obligation, ObligationCause, PredicateObligation}; use rustc_data_structures::fx::{FxHashSet, FxIndexSet}; -use rustc_middle::ty::outlives::Component; use rustc_middle::ty::{self, ToPredicate, TyCtxt, WithConstness}; use rustc_span::symbol::Ident; @@ -200,7 +200,7 @@ impl Elaborator<'tcx> { let visited = &mut self.visited; let mut components = smallvec![]; - tcx.push_outlives_components(ty_max, &mut components); + push_outlives_components(tcx, ty_max, &mut components); self.stack.extend( components .into_iter() @@ -231,6 +231,7 @@ impl Elaborator<'tcx> { None } }) + .map(ty::Binder::dummy) .map(|predicate_kind| predicate_kind.to_predicate(tcx)) .filter(|&predicate| visited.insert(predicate)) .map(|predicate| { diff --git a/compiler/rustc_interface/Cargo.toml b/compiler/rustc_interface/Cargo.toml index dad5b256e4..07af2201f5 100644 --- a/compiler/rustc_interface/Cargo.toml +++ b/compiler/rustc_interface/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustc_interface" version = "0.0.0" -edition = "2018" +edition = "2021" [lib] doctest = false @@ -14,6 +14,7 @@ rayon = { version = "0.3.1", package = "rustc-rayon" } smallvec = { version = "1.6.1", features = ["union", "may_dangle"] } rustc_ast = { path = "../rustc_ast" } rustc_attr = { path = "../rustc_attr" } +rustc_borrowck = { path = "../rustc_borrowck" } rustc_builtin_macros = { path = "../rustc_builtin_macros" } rustc_expand = { path = "../rustc_expand" } rustc_parse = { path = "../rustc_parse" } @@ -31,8 +32,10 @@ rustc_symbol_mangling = { path = "../rustc_symbol_mangling" } rustc_codegen_llvm = { path = "../rustc_codegen_llvm", optional = true } rustc_hir = { path = "../rustc_hir" } rustc_metadata = { path = "../rustc_metadata" } -rustc_mir = { path = "../rustc_mir" } +rustc_const_eval = { path = "../rustc_const_eval" } rustc_mir_build = { path = "../rustc_mir_build" } +rustc_mir_transform = { path = "../rustc_mir_transform" } +rustc_monomorphize = { path = "../rustc_monomorphize" } rustc_passes = { path = "../rustc_passes" } rustc_typeck = { path = "../rustc_typeck" } rustc_lint = { path = "../rustc_lint" } diff --git a/compiler/rustc_interface/src/callbacks.rs b/compiler/rustc_interface/src/callbacks.rs index 3b852b8ccf..3c7908fae7 100644 --- a/compiler/rustc_interface/src/callbacks.rs +++ b/compiler/rustc_interface/src/callbacks.rs @@ -25,13 +25,23 @@ fn span_debug(span: rustc_span::Span, f: &mut fmt::Formatter<'_>) -> fmt::Result }) } +fn track_span_parent(def_id: rustc_span::def_id::LocalDefId) { + tls::with_opt(|tcx| { + if let Some(tcx) = tcx { + let _span = tcx.source_span(def_id); + // Sanity check: relative span's parent must be an absolute span. + debug_assert_eq!(_span.data_untracked().parent, None); + } + }) +} + /// This is a callback from `rustc_ast` as it cannot access the implicit state /// in `rustc_middle` otherwise. It is used to when diagnostic messages are /// emitted and stores them in the current query, if there is one. fn track_diagnostic(diagnostic: &Diagnostic) { tls::with_context_opt(|icx| { if let Some(icx) = icx { - if let Some(ref diagnostics) = icx.diagnostics { + if let Some(diagnostics) = icx.diagnostics { let mut diagnostics = diagnostics.lock(); diagnostics.extend(Some(diagnostic.clone())); } @@ -56,6 +66,7 @@ fn def_id_debug(def_id: rustc_hir::def_id::DefId, f: &mut fmt::Formatter<'_>) -> /// TyCtxt in. pub fn setup_callbacks() { rustc_span::SPAN_DEBUG.swap(&(span_debug as fn(_, &mut fmt::Formatter<'_>) -> _)); + rustc_span::SPAN_TRACK.swap(&(track_span_parent as fn(_))); rustc_hir::def_id::DEF_ID_DEBUG.swap(&(def_id_debug as fn(_, &mut fmt::Formatter<'_>) -> _)); TRACK_DIAGNOSTICS.swap(&(track_diagnostic as fn(&_))); } diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs index 8393826aa1..0861bd290d 100644 --- a/compiler/rustc_interface/src/interface.rs +++ b/compiler/rustc_interface/src/interface.rs @@ -65,13 +65,7 @@ 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, attrs, sess) } } diff --git a/compiler/rustc_interface/src/lib.rs b/compiler/rustc_interface/src/lib.rs index c7424b9e2a..2fc3759968 100644 --- a/compiler/rustc_interface/src/lib.rs +++ b/compiler/rustc_interface/src/lib.rs @@ -1,6 +1,7 @@ #![feature(bool_to_option)] #![feature(box_patterns)] #![feature(internal_output_capture)] +#![feature(thread_spawn_unchecked)] #![feature(nll)] #![feature(once_cell)] #![recursion_limit = "256"] diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 7127ec57c0..bcfa0ef352 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -4,10 +4,11 @@ use crate::util; use rustc_ast::mut_visit::MutVisitor; use rustc_ast::{self as ast, visit}; +use rustc_borrowck as mir_borrowck; use rustc_codegen_ssa::back::link::emit_metadata; use rustc_codegen_ssa::traits::CodegenBackend; use rustc_data_structures::parallel; -use rustc_data_structures::sync::{par_iter, Lrc, OnceCell, ParallelIterator, WorkerLocal}; +use rustc_data_structures::sync::{Lrc, OnceCell, WorkerLocal}; use rustc_data_structures::temp_dir::MaybeTempDir; use rustc_errors::{ErrorReported, PResult}; use rustc_expand::base::ExtCtxt; @@ -15,26 +16,25 @@ use rustc_hir::def_id::{StableCrateId, LOCAL_CRATE}; use rustc_hir::Crate; use rustc_lint::LintStore; 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::middle; -use rustc_middle::middle::cstore::{MetadataLoader, MetadataLoaderDyn}; use rustc_middle::ty::query::Providers; use rustc_middle::ty::{self, GlobalCtxt, ResolverOutputs, TyCtxt}; -use rustc_mir as mir; use rustc_mir_build as mir_build; -use rustc_parse::{parse_crate_from_file, parse_crate_from_source_str}; +use rustc_parse::{parse_crate_from_file, parse_crate_from_source_str, validate_attr}; use rustc_passes::{self, hir_stats, layout_test}; use rustc_plugin_impl as plugin; use rustc_query_impl::{OnDiskCache, Queries as TcxQueries}; use rustc_resolve::{Resolver, ResolverArenas}; use rustc_serialize::json; use rustc_session::config::{CrateType, Input, OutputFilenames, OutputType, PpMode, PpSourceMode}; +use rustc_session::cstore::{MetadataLoader, MetadataLoaderDyn}; use rustc_session::lint; use rustc_session::output::{filename_for_input, filename_for_metadata}; use rustc_session::search_paths::PathKind; -use rustc_session::Session; -use rustc_span::symbol::{Ident, Symbol}; +use rustc_session::{Limit, Session}; +use rustc_span::symbol::{sym, Ident, Symbol}; use rustc_span::FileName; use rustc_trait_selection::traits; use rustc_typeck as typeck; @@ -169,7 +169,7 @@ pub fn create_resolver( ) -> BoxedResolver { tracing::trace!("create_resolver"); BoxedResolver::new(sess, move |sess, resolver_arenas| { - Resolver::new(sess, &krate, &crate_name, metadata_loader, &resolver_arenas) + Resolver::new(sess, krate, crate_name, metadata_loader, resolver_arenas) }) } @@ -179,7 +179,7 @@ pub fn register_plugins<'a>( register_lints: impl Fn(&Session, &mut LintStore), mut krate: ast::Crate, crate_name: &str, -) -> Result<(ast::Crate, Lrc)> { +) -> Result<(ast::Crate, LintStore)> { krate = sess.time("attributes_injection", || { rustc_builtin_macros::cmdline_attrs::inject( krate, @@ -201,7 +201,7 @@ pub fn register_plugins<'a>( sess.opts.cg.metadata.clone(), ); sess.stable_crate_id.set(stable_crate_id).expect("not yet initialized"); - rustc_incremental::prepare_session_directory(sess, &crate_name, stable_crate_id)?; + rustc_incremental::prepare_session_directory(sess, crate_name, stable_crate_id)?; if sess.opts.incremental.is_some() { sess.time("incr_comp_garbage_collect_session_directories", || { @@ -219,7 +219,7 @@ pub fn register_plugins<'a>( sess.opts.debugging_opts.no_interleave_lints, sess.unstable_options(), ); - register_lints(&sess, &mut lint_store); + register_lints(sess, &mut lint_store); let registrars = sess.time("plugin_loading", || plugin::load::load_plugins(sess, metadata_loader, &krate)); @@ -230,9 +230,6 @@ pub fn register_plugins<'a>( } }); - let lint_store = Lrc::new(lint_store); - sess.init_lint_store(lint_store.clone()); - Ok((krate, lint_store)) } @@ -240,13 +237,15 @@ fn pre_expansion_lint( sess: &Session, lint_store: &LintStore, krate: &ast::Crate, + crate_attrs: &[ast::Attribute], crate_name: &str, ) { sess.prof.generic_activity_with_arg("pre_AST_expansion_lint_checks", crate_name).run(|| { rustc_lint::check_ast_crate( sess, lint_store, - &krate, + krate, + crate_attrs, true, None, rustc_lint::BuiltinCombinedPreExpansionLintPass::new(), @@ -266,15 +265,15 @@ pub fn configure_and_expand( resolver: &mut Resolver<'_>, ) -> Result { tracing::trace!("configure_and_expand"); - pre_expansion_lint(sess, lint_store, &krate, crate_name); + pre_expansion_lint(sess, lint_store, &krate, &krate.attrs, crate_name); rustc_builtin_macros::register_builtin_macros(resolver); krate = sess.time("crate_injection", || { let alt_std_name = sess.opts.alt_std_name.as_ref().map(|s| Symbol::intern(s)); - rustc_builtin_macros::standard_library_imports::inject(krate, resolver, &sess, alt_std_name) + rustc_builtin_macros::standard_library_imports::inject(krate, resolver, sess, alt_std_name) }); - util::check_attr_crate_type(&sess, &krate.attrs, &mut resolver.lint_buffer()); + util::check_attr_crate_type(sess, &krate.attrs, &mut resolver.lint_buffer()); // Expand all macros krate = sess.time("macro_expand_crate", || { @@ -311,10 +310,9 @@ pub fn configure_and_expand( // Create the config for macro expansion let features = sess.features_untracked(); - let recursion_limit = - rustc_middle::middle::limits::get_recursion_limit(&krate.attrs, &sess); + let recursion_limit = get_recursion_limit(&krate.attrs, sess); let cfg = rustc_expand::expand::ExpansionConfig { - features: Some(&features), + features: Some(features), recursion_limit, trace_mac: sess.opts.debugging_opts.trace_macros, should_test: sess.opts.test, @@ -323,12 +321,13 @@ pub fn configure_and_expand( ..rustc_expand::expand::ExpansionConfig::default(crate_name.to_string()) }; + let crate_attrs = krate.attrs.clone(); let extern_mod_loaded = |ident: Ident, attrs, items, span| { let krate = ast::Crate { attrs, items, span }; - pre_expansion_lint(sess, lint_store, &krate, &ident.name.as_str()); + pre_expansion_lint(sess, lint_store, &krate, &crate_attrs, &ident.name.as_str()); (krate.attrs, krate.items) }; - let mut ecx = ExtCtxt::new(&sess, cfg, resolver, Some(&extern_mod_loaded)); + let mut ecx = ExtCtxt::new(sess, cfg, resolver, Some(&extern_mod_loaded)); // Expand macros now! let krate = sess.time("expand_crate", || ecx.monotonic_expander().expand_crate(krate)); @@ -370,7 +369,7 @@ pub fn configure_and_expand( })?; sess.time("maybe_building_test_harness", || { - rustc_builtin_macros::test_harness::inject(&sess, resolver, &mut krate) + rustc_builtin_macros::test_harness::inject(sess, resolver, &mut krate) }); if let Some(PpMode::Source(PpSourceMode::EveryBodyLoops)) = sess.opts.pretty { @@ -393,8 +392,8 @@ pub fn configure_and_expand( // start passing '--crate-type proc-macro' if has_proc_macro_decls && sess.opts.actually_rustdoc && !is_proc_macro_crate { let mut msg = sess.diagnostic().struct_warn( - &"Trying to document proc macro crate \ - without passing '--crate-type proc-macro to rustdoc", + "Trying to document proc macro crate \ + without passing '--crate-type proc-macro to rustdoc", ); msg.warn("The generated documentation may be incorrect"); @@ -404,7 +403,7 @@ pub fn configure_and_expand( let num_crate_types = crate_types.len(); let is_test_crate = sess.opts.test; rustc_builtin_macros::proc_macro_harness::inject( - &sess, + sess, resolver, krate, is_proc_macro_crate, @@ -438,12 +437,18 @@ pub fn configure_and_expand( }); // Add all buffered lints from the `ParseSess` to the `Session`. - sess.parse_sess.buffered_lints.with_lock(|buffered_lints| { - info!("{} parse sess buffered_lints", buffered_lints.len()); - for early_lint in buffered_lints.drain(..) { - resolver.lint_buffer().add_early_lint(early_lint); - } - }); + // The ReplaceBodyWithLoop pass may have deleted some AST nodes, potentially + // causing a delay_span_bug later if a buffered lint refers to such a deleted + // AST node (issue #87308). Since everybody_loops is for pretty-printing only, + // anyway, we simply skip all buffered lints here. + if !matches!(sess.opts.pretty, Some(PpMode::Source(PpSourceMode::EveryBodyLoops))) { + sess.parse_sess.buffered_lints.with_lock(|buffered_lints| { + info!("{} parse sess buffered_lints", buffered_lints.len()); + for early_lint in buffered_lints.drain(..) { + resolver.lint_buffer().add_early_lint(early_lint); + } + }); + } Ok(krate) } @@ -464,15 +469,12 @@ pub fn lower_to_hir<'res, 'tcx>( arena, ); - if sess.opts.debugging_opts.hir_stats { - hir_stats::print_hir_stats(&hir_crate); - } - sess.time("early_lint_checks", || { rustc_lint::check_ast_crate( sess, lint_store, &krate, + &krate.attrs, false, Some(std::mem::take(resolver.lint_buffer())), rustc_lint::BuiltinCombinedEarlyLintPass::new(), @@ -695,7 +697,7 @@ pub fn prepare_outputs( ); let output_paths = - generated_output_paths(sess, &outputs, compiler.output_file.is_some(), &crate_name); + generated_output_paths(sess, &outputs, compiler.output_file.is_some(), crate_name); // Ensure the source file isn't accidentally overwritten during compilation. if let Some(ref input_path) = compiler.input_path { @@ -741,9 +743,12 @@ pub static DEFAULT_QUERY_PROVIDERS: SyncLazy = SyncLazy::new(|| { let providers = &mut Providers::default(); providers.analysis = analysis; proc_macro_decls::provide(providers); + rustc_const_eval::provide(providers); rustc_middle::hir::provide(providers); - mir::provide(providers); + mir_borrowck::provide(providers); mir_build::provide(providers); + rustc_mir_transform::provide(providers); + rustc_monomorphize::provide(providers); rustc_privacy::provide(providers); typeck::provide(providers); ty::provide(providers); @@ -833,7 +838,7 @@ pub fn create_global_ctxt<'tcx>( dep_graph, queries.on_disk_cache.as_ref().map(OnDiskCache::as_dyn), queries.as_dyn(), - &crate_name, + crate_name, outputs, ) }) @@ -862,7 +867,7 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> { CStore::from_tcx(tcx).report_unused_deps(tcx); }, { - par_iter(&tcx.hir().krate().modules).for_each(|(&module, _)| { + tcx.hir().par_for_each_module(|module| { tcx.ensure().check_mod_loops(module); tcx.ensure().check_mod_attrs(module); tcx.ensure().check_mod_naked_functions(module); @@ -887,14 +892,12 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> { parallel!( { sess.time("match_checking", || { - tcx.par_body_owners(|def_id| { - tcx.ensure().check_match(def_id.to_def_id()); - }); + tcx.hir().par_body_owners(|def_id| tcx.ensure().check_match(def_id.to_def_id())) }); }, { sess.time("liveness_and_intrinsic_checking", || { - par_iter(&tcx.hir().krate().modules).for_each(|(&module, _)| { + tcx.hir().par_for_each_module(|module| { // this must run before MIR dump, because // "not all control paths return a value" is reported here. // @@ -908,14 +911,14 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> { }); sess.time("MIR_borrow_checking", || { - tcx.par_body_owners(|def_id| tcx.ensure().mir_borrowck(def_id)); + tcx.hir().par_body_owners(|def_id| tcx.ensure().mir_borrowck(def_id)); }); sess.time("MIR_effect_checking", || { - for def_id in tcx.body_owners() { + for def_id in tcx.hir().body_owners() { tcx.ensure().thir_check_unsafety(def_id); if !tcx.sess.opts.debugging_opts.thir_unsafeck { - mir::transform::check_unsafety::check_unsafety(tcx, def_id); + rustc_mir_transform::check_unsafety::check_unsafety(tcx, def_id); } if tcx.hir().body_const_context(def_id).is_some() { @@ -964,7 +967,7 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> { }, { sess.time("privacy_checking_modules", || { - par_iter(&tcx.hir().krate().modules).for_each(|(&module, _)| { + tcx.hir().par_for_each_module(|module| { tcx.ensure().check_mod_privacy(module); }); }); @@ -978,7 +981,7 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> { fn encode_and_write_metadata( tcx: TyCtxt<'_>, outputs: &OutputFilenames, -) -> (middle::cstore::EncodedMetadata, bool) { +) -> (EncodedMetadata, bool) { #[derive(PartialEq, Eq, PartialOrd, Ord)] enum MetadataKind { None, @@ -1001,8 +1004,8 @@ fn encode_and_write_metadata( .unwrap_or(MetadataKind::None); let metadata = match metadata_kind { - MetadataKind::None => middle::cstore::EncodedMetadata::new(), - MetadataKind::Uncompressed | MetadataKind::Compressed => tcx.encode_metadata(), + MetadataKind::None => EncodedMetadata::new(), + MetadataKind::Uncompressed | MetadataKind::Compressed => encode_metadata(tcx), }; let _prof_timer = tcx.sess.prof.generic_activity("write_crate_metadata"); @@ -1021,7 +1024,7 @@ fn encode_and_write_metadata( .tempdir_in(out_filename.parent().unwrap()) .unwrap_or_else(|err| tcx.sess.fatal(&format!("couldn't create a temp dir: {}", err))); let metadata_tmpdir = MaybeTempDir::new(metadata_tmpdir, tcx.sess.opts.cg.save_temps); - let metadata_filename = emit_metadata(tcx.sess, &metadata.raw_data, &metadata_tmpdir); + let metadata_filename = emit_metadata(tcx.sess, metadata.raw_data(), &metadata_tmpdir); if let Err(e) = util::non_durable_rename(&metadata_filename, &out_filename) { tcx.sess.fatal(&format!("failed to write {}: {}", out_filename.display(), e)); } @@ -1063,7 +1066,7 @@ pub fn start_codegen<'tcx>( info!("Post-codegen\n{:?}", tcx.debug_stats()); if tcx.sess.opts.output_types.contains_key(&OutputType::Mir) { - if let Err(e) = mir::transform::dump_mir::emit_mir(tcx, outputs) { + if let Err(e) = rustc_mir_transform::dump_mir::emit_mir(tcx, outputs) { tcx.sess.err(&format!("could not emit MIR: {}", e)); tcx.sess.abort_if_errors(); } @@ -1071,3 +1074,24 @@ pub fn start_codegen<'tcx>( codegen } + +fn get_recursion_limit(krate_attrs: &[ast::Attribute], sess: &Session) -> Limit { + if let Some(attr) = krate_attrs + .iter() + .find(|attr| attr.has_name(sym::recursion_limit) && attr.value_str().is_none()) + { + // This is here mainly to check for using a macro, such as + // #![recursion_limit = foo!()]. That is not supported since that + // would require expanding this while in the middle of expansion, + // which needs to know the limit before expanding. Otherwise, + // validation would normally be caught in AstValidator (via + // `check_builtin_attribute`), but by the time that runs the macro + // is expanded, and it doesn't give an error. + validate_attr::emit_fatal_malformed_builtin_attribute( + &sess.parse_sess, + attr, + sym::recursion_limit, + ); + } + rustc_middle::middle::limits::get_recursion_limit(krate_attrs, sess) +} diff --git a/compiler/rustc_interface/src/proc_macro_decls.rs b/compiler/rustc_interface/src/proc_macro_decls.rs index 88cf6275eb..c0316ce58d 100644 --- a/compiler/rustc_interface/src/proc_macro_decls.rs +++ b/compiler/rustc_interface/src/proc_macro_decls.rs @@ -7,7 +7,7 @@ use rustc_span::symbol::sym; fn proc_macro_decls_static(tcx: TyCtxt<'_>, (): ()) -> Option { let mut finder = Finder { tcx, decls: None }; - tcx.hir().krate().visit_all_item_likes(&mut finder); + tcx.hir().visit_all_item_likes(&mut finder); finder.decls.map(|id| tcx.hir().local_def_id(id)) } diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs index 2f540395b2..f188ad3560 100644 --- a/compiler/rustc_interface/src/queries.rs +++ b/compiler/rustc_interface/src/queries.rs @@ -110,7 +110,7 @@ impl<'tcx> Queries<'tcx> { &self.compiler.sess } fn codegen_backend(&self) -> &Lrc> { - &self.compiler.codegen_backend() + self.compiler.codegen_backend() } fn dep_graph_future(&self) -> Result<&Query>> { @@ -135,7 +135,7 @@ impl<'tcx> Queries<'tcx> { let krate = self.parse()?.take(); let empty: &(dyn Fn(&Session, &mut LintStore) + Sync + Send) = &|_, _| {}; - let result = passes::register_plugins( + let (krate, lint_store) = passes::register_plugins( self.session(), &*self.codegen_backend().metadata_loader(), self.compiler.register_lints.as_deref().unwrap_or_else(|| empty), @@ -150,7 +150,7 @@ impl<'tcx> Queries<'tcx> { // called, which happens within passes::register_plugins(). self.dep_graph_future().ok(); - Ok(result) + Ok((krate, Lrc::new(lint_store))) }) } @@ -181,7 +181,7 @@ impl<'tcx> Queries<'tcx> { &crate_name, ); let krate = resolver.access(|resolver| { - passes::configure_and_expand(&sess, &lint_store, krate, &crate_name, resolver) + passes::configure_and_expand(sess, &lint_store, krate, &crate_name, resolver) })?; Ok((Rc::new(krate), Rc::new(RefCell::new(resolver)), lint_store)) }) @@ -343,7 +343,7 @@ impl Linker { let sess = &self.sess; let dep_graph = self.dep_graph; sess.time("serialize_work_products", || { - rustc_incremental::save_work_product_index(&sess, &dep_graph, work_products) + rustc_incremental::save_work_product_index(sess, &dep_graph, work_products) }); let prof = self.sess.prof.clone(); @@ -386,7 +386,7 @@ impl Compiler { F: for<'tcx> FnOnce(&'tcx Queries<'tcx>) -> T, { let mut _timer = None; - let queries = Queries::new(&self); + let queries = Queries::new(self); let ret = f(&queries); // NOTE: intentionally does not compute the global context if it hasn't been built yet, diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index afab919bc3..844e5ab56a 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -715,6 +715,7 @@ fn test_debugging_options_tracking_hash() { tracked!(chalk, true); tracked!(codegen_backend, Some("abc".to_string())); tracked!(crate_attr, vec!["abc".to_string()]); + tracked!(debug_info_for_profiling, true); tracked!(debug_macros, true); tracked!(dep_info_omit_d_target, true); tracked!(dual_proc_macros, true); @@ -743,6 +744,7 @@ fn test_debugging_options_tracking_hash() { 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!(plt, Some(true)); tracked!(polonius, true); @@ -751,8 +753,10 @@ fn test_debugging_options_tracking_hash() { tracked!(profile, true); tracked!(profile_emit, Some(PathBuf::from("abc"))); tracked!(profiler_runtime, "abc".to_string()); + tracked!(profile_sample_use, Some(PathBuf::from("abc"))); 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); diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index a5f0c01477..cffb087af1 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -10,6 +10,7 @@ use rustc_errors::registry::Registry; use rustc_metadata::dynamic_lib::DynamicLibrary; #[cfg(parallel_compiler)] use rustc_middle::ty::tls; +use rustc_parse::validate_attr; #[cfg(parallel_compiler)] use rustc_query_impl::QueryCtxt; use rustc_resolve::{self, Resolver}; @@ -115,24 +116,11 @@ fn get_stack_size() -> Option { /// for `'static` bounds. #[cfg(not(parallel_compiler))] pub fn scoped_thread R + Send, R: Send>(cfg: thread::Builder, f: F) -> R { - struct Ptr(*mut ()); - unsafe impl Send for Ptr {} - unsafe impl Sync for Ptr {} - - let mut f = Some(f); - let run = Ptr(&mut f as *mut _ as *mut ()); - let mut result = None; - let result_ptr = Ptr(&mut result as *mut _ as *mut ()); - - let thread = cfg.spawn(move || { - let run = unsafe { (*(run.0 as *mut Option)).take().unwrap() }; - let result = unsafe { &mut *(result_ptr.0 as *mut Option) }; - *result = Some(run()); - }); - - match thread.unwrap().join() { - Ok(()) => result.unwrap(), - Err(p) => panic::resume_unwind(p), + // SAFETY: join() is called immediately, so any closure captures are still + // alive. + match unsafe { cfg.spawn_unchecked(f) }.unwrap().join() { + Ok(v) => v, + Err(e) => panic::resume_unwind(e), } } @@ -414,7 +402,7 @@ pub fn get_codegen_sysroot( .iter() .chain(sysroot_candidates.iter()) .map(|sysroot| { - filesearch::make_target_lib_path(&sysroot, &target).with_file_name("codegen-backends") + filesearch::make_target_lib_path(sysroot, target).with_file_name("codegen-backends") }) .find(|f| { info!("codegen backend candidate: {}", f.display()); @@ -488,7 +476,7 @@ pub fn get_codegen_sysroot( } pub(crate) fn check_attr_crate_type( - _sess: &Session, + sess: &Session, attrs: &[ast::Attribute], lint_buffer: &mut LintBuffer, ) { @@ -528,6 +516,19 @@ pub(crate) fn check_attr_crate_type( ); } } + } else { + // This is here mainly to check for using a macro, such as + // #![crate_type = foo!()]. That is not supported since the + // crate type needs to be known very early in compilation long + // before expansion. Otherwise, validation would normally be + // caught in AstValidator (via `check_builtin_attribute`), but + // by the time that runs the macro is expanded, and it doesn't + // give an error. + validate_attr::emit_fatal_malformed_builtin_attribute( + &sess.parse_sess, + a, + sym::crate_type, + ); } } } @@ -618,7 +619,7 @@ pub fn build_output_filenames( .opts .crate_name .clone() - .or_else(|| rustc_attr::find_crate_name(&sess, attrs).map(|n| n.to_string())) + .or_else(|| rustc_attr::find_crate_name(sess, attrs).map(|n| n.to_string())) .unwrap_or_else(|| input.filestem().to_owned()); OutputFilenames::new( diff --git a/compiler/rustc_lexer/Cargo.toml b/compiler/rustc_lexer/Cargo.toml index 7e05fe545c..60c146f457 100644 --- a/compiler/rustc_lexer/Cargo.toml +++ b/compiler/rustc_lexer/Cargo.toml @@ -2,7 +2,7 @@ name = "rustc_lexer" version = "0.1.0" license = "MIT OR Apache-2.0" -edition = "2018" +edition = "2021" repository = "https://github.com/rust-lang/rust/" description = """ diff --git a/compiler/rustc_lexer/src/unescape.rs b/compiler/rustc_lexer/src/unescape.rs index b970c9e491..804dc657f2 100644 --- a/compiler/rustc_lexer/src/unescape.rs +++ b/compiler/rustc_lexer/src/unescape.rs @@ -68,11 +68,10 @@ pub enum EscapeError { impl EscapeError { /// Returns true for actual errors, as opposed to warnings. pub fn is_fatal(&self) -> bool { - match self { - EscapeError::UnskippedWhitespaceWarning => false, - EscapeError::MultipleSkippedLinesWarning => false, - _ => true, - } + !matches!( + self, + EscapeError::UnskippedWhitespaceWarning | EscapeError::MultipleSkippedLinesWarning + ) } } @@ -330,7 +329,7 @@ where callback(start..end, Err(EscapeError::MultipleSkippedLinesWarning)); } let tail = &tail[first_non_space..]; - if let Some(c) = tail.chars().nth(0) { + if let Some(c) = tail.chars().next() { // 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/Cargo.toml b/compiler/rustc_lint/Cargo.toml index 8294d5878f..414fcbeb9e 100644 --- a/compiler/rustc_lint/Cargo.toml +++ b/compiler/rustc_lint/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustc_lint" version = "0.0.0" -edition = "2018" +edition = "2021" [dependencies] if_chain = "1.0" diff --git a/compiler/rustc_lint/src/array_into_iter.rs b/compiler/rustc_lint/src/array_into_iter.rs index 5ac42c50c7..d147148ac7 100644 --- a/compiler/rustc_lint/src/array_into_iter.rs +++ b/compiler/rustc_lint/src/array_into_iter.rs @@ -13,7 +13,7 @@ declare_lint! { /// /// ### Example /// - /// ```rust + /// ```rust,edition2018 /// # #![allow(unused)] /// [1, 2, 3].into_iter().for_each(|n| { *n; }); /// ``` @@ -124,7 +124,7 @@ impl<'tcx> LateLintPass<'tcx> for ArrayIntoIter { let mut diag = lint.build(&format!( "this method call resolves to `<&{} as IntoIterator>::into_iter` \ (due to backwards compatibility), \ - but will resolve to <{} as IntoIterator>::into_iter in Rust 2021.", + but will resolve to <{} as IntoIterator>::into_iter in Rust 2021", target, target, )); diag.span_suggestion( diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 88b9e92119..57c1c8f3ec 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -41,16 +41,17 @@ use rustc_hir::{ForeignItemKind, GenericParamKind, PatKind}; use rustc_hir::{HirId, Node}; use rustc_index::vec::Idx; use rustc_middle::lint::LintDiagnosticBuilder; +use rustc_middle::ty::layout::{LayoutError, LayoutOf}; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::subst::{GenericArgKind, Subst}; use rustc_middle::ty::Instance; -use rustc_middle::ty::{self, layout::LayoutError, Ty, TyCtxt}; +use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_session::lint::{BuiltinLintDiagnostics, FutureIncompatibilityReason}; use rustc_span::edition::Edition; use rustc_span::source_map::Spanned; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{BytePos, InnerSpan, MultiSpan, Span}; -use rustc_target::abi::{LayoutOf, VariantIdx}; +use rustc_target::abi::VariantIdx; use rustc_trait_selection::traits::misc::can_type_implement_copy; use crate::nonstandard_style::{method_context, MethodLateContext}; @@ -583,8 +584,14 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc { self.doc_hidden_stack.pop().expect("empty doc_hidden_stack"); } - fn check_crate(&mut self, cx: &LateContext<'_>, krate: &hir::Crate<'_>) { - self.check_missing_docs_attrs(cx, CRATE_DEF_ID, krate.module().inner, "the", "crate"); + fn check_crate(&mut self, cx: &LateContext<'_>) { + self.check_missing_docs_attrs( + cx, + CRATE_DEF_ID, + cx.tcx.def_span(CRATE_DEF_ID), + "the", + "crate", + ); } fn check_item(&mut self, cx: &LateContext<'_>, it: &hir::Item<'_>) { @@ -805,7 +812,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDebugImplementations { _ => return, } - let debug = match cx.tcx.get_diagnostic_item(sym::debug_trait) { + let debug = match cx.tcx.get_diagnostic_item(sym::Debug) { Some(debug) => debug, None => return, }; @@ -911,7 +918,7 @@ impl EarlyLintPass for AnonymousParameters { lint.build( "anonymous parameters are deprecated and will be \ - removed in the next edition.", + removed in the next edition", ) .span_suggestion( arg.pat.span, @@ -1622,9 +1629,9 @@ impl<'tcx> LateLintPass<'tcx> for TrivialConstraints { let predicates = cx.tcx.predicates_of(item.def_id); for &(predicate, span) in predicates.predicates { let predicate_kind_name = match predicate.kind().skip_binder() { - Trait(..) => "Trait", + Trait(..) => "trait", TypeOutlives(..) | - RegionOutlives(..) => "Lifetime", + RegionOutlives(..) => "lifetime", // Ignore projections, as they can only be global // if the trait bound is global @@ -1685,7 +1692,7 @@ declare_lint! { /// /// ### Example /// - /// ```rust + /// ```rust,edition2018 /// let x = 123; /// match x { /// 0...100 => {} @@ -2471,14 +2478,11 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue { // Find calls to `mem::{uninitialized,zeroed}` methods. if let hir::ExprKind::Path(ref qpath) = path_expr.kind { let def_id = cx.qpath_res(qpath, path_expr.hir_id).opt_def_id()?; - - if cx.tcx.is_diagnostic_item(sym::mem_zeroed, def_id) { - return Some(InitKind::Zeroed); - } else if cx.tcx.is_diagnostic_item(sym::mem_uninitialized, def_id) { - return Some(InitKind::Uninit); - } else if cx.tcx.is_diagnostic_item(sym::transmute, def_id) && is_zero(&args[0]) - { - return Some(InitKind::Zeroed); + match cx.tcx.get_diagnostic_name(def_id) { + Some(sym::mem_zeroed) => return Some(InitKind::Zeroed), + Some(sym::mem_uninitialized) => return Some(InitKind::Uninit), + Some(sym::transmute) if is_zero(&args[0]) => return Some(InitKind::Zeroed), + _ => {} } } } else if let hir::ExprKind::MethodCall(_, _, ref args, _) = expr.kind { @@ -2490,11 +2494,10 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue { if let hir::ExprKind::Call(ref path_expr, _) = args[0].kind { if let hir::ExprKind::Path(ref qpath) = path_expr.kind { let def_id = cx.qpath_res(qpath, path_expr.hir_id).opt_def_id()?; - - if cx.tcx.is_diagnostic_item(sym::maybe_uninit_zeroed, def_id) { - return Some(InitKind::Zeroed); - } else if cx.tcx.is_diagnostic_item(sym::maybe_uninit_uninit, def_id) { - return Some(InitKind::Uninit); + match cx.tcx.get_diagnostic_name(def_id) { + Some(sym::maybe_uninit_zeroed) => return Some(InitKind::Zeroed), + Some(sym::maybe_uninit_uninit) => return Some(InitKind::Uninit), + _ => {} } } } @@ -3084,8 +3087,10 @@ impl<'tcx> LateLintPass<'tcx> for DerefNullPtr { rustc_hir::ExprKind::Call(ref path, _) => { if let rustc_hir::ExprKind::Path(ref qpath) = path.kind { if let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id() { - return cx.tcx.is_diagnostic_item(sym::ptr_null, def_id) - || cx.tcx.is_diagnostic_item(sym::ptr_null_mut, def_id); + return matches!( + cx.tcx.get_diagnostic_name(def_id), + Some(sym::ptr_null | sym::ptr_null_mut) + ); } } } diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index 7dbc3d6043..6fd0a5b95f 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -16,6 +16,7 @@ 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 rustc_ast as ast; @@ -31,17 +32,16 @@ use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData}; use rustc_middle::lint::LintDiagnosticBuilder; use rustc_middle::middle::privacy::AccessLevels; use rustc_middle::middle::stability; -use rustc_middle::ty::layout::{LayoutError, TyAndLayout}; +use rustc_middle::ty::layout::{LayoutError, LayoutOfHelpers, TyAndLayout}; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::{self, print::Printer, subst::GenericArg, Ty, TyCtxt}; use rustc_serialize::json::Json; use rustc_session::lint::{BuiltinLintDiagnostics, ExternDepSpec}; use rustc_session::lint::{FutureIncompatibleInfo, Level, Lint, LintBuffer, LintId}; use rustc_session::Session; -use rustc_session::SessionLintStore; use rustc_span::lev_distance::find_best_match_for_name; -use rustc_span::{symbol::Symbol, MultiSpan, Span, DUMMY_SP}; -use rustc_target::abi::{self, LayoutOf}; +use rustc_span::{symbol::Symbol, BytePos, MultiSpan, Span, DUMMY_SP}; +use rustc_target::abi; use tracing::debug; use std::cell::Cell; @@ -75,20 +75,6 @@ pub struct LintStore { lint_groups: FxHashMap<&'static str, LintGroup>, } -impl SessionLintStore for LintStore { - fn name_to_lint(&self, lint_name: &str) -> LintId { - let lints = self - .find_lints(lint_name) - .unwrap_or_else(|_| panic!("Failed to find lint with name `{}`", lint_name)); - - if let &[lint] = lints.as_slice() { - return lint; - } else { - panic!("Found mutliple lints with name `{}`: {:?}", lint_name, lints); - } - } -} - /// The target of the `by_name` map, which accounts for renaming/deprecation. #[derive(Debug)] enum TargetLint { @@ -612,6 +598,42 @@ pub trait LintContext: Sized { // Now, set up surrounding context. let sess = self.sess(); match diagnostic { + BuiltinLintDiagnostics::UnicodeTextFlow(span, content) => { + let spans: Vec<_> = content + .char_indices() + .filter_map(|(i, c)| { + UNICODE_TEXT_FLOW_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))) + }) + }) + .collect(); + let (an, s) = match spans.len() { + 1 => ("an ", ""), + _ => ("", "s"), + }; + db.span_label(span, &format!( + "this comment contains {}invisible unicode text flow control codepoint{}", + an, + s, + )); + for (c, span) in &spans { + db.span_label(*span, format!("{:?}", c)); + } + db.note( + "these kind of unicode codepoints change the way text flows on \ + applications that support them, but can cause confusion because they \ + change the order of characters on the screen", + ); + if !spans.is_empty() { + db.multipart_suggestion_with_style( + "if their presence wasn't intentional, you can remove them", + spans.into_iter().map(|(_, span)| (span, "".to_string())).collect(), + Applicability::MachineApplicable, + SuggestionStyle::HideCodeAlways, + ); + } + }, BuiltinLintDiagnostics::Normal => (), BuiltinLintDiagnostics::BareTraitObject(span, is_global) => { let (sugg, app) = match sess.source_map().span_to_snippet(span) { @@ -805,6 +827,7 @@ impl<'a> EarlyContext<'a> { sess: &'a Session, lint_store: &'a LintStore, krate: &'a ast::Crate, + crate_attrs: &'a [ast::Attribute], buffered: LintBuffer, warn_about_weird_lints: bool, ) -> EarlyContext<'a> { @@ -812,7 +835,7 @@ impl<'a> EarlyContext<'a> { sess, krate, lint_store, - builder: LintLevelsBuilder::new(sess, warn_about_weird_lints, lint_store, &krate.attrs), + builder: LintLevelsBuilder::new(sess, warn_about_weird_lints, lint_store, crate_attrs), buffered, } } @@ -1080,12 +1103,12 @@ impl<'tcx> ty::layout::HasParamEnv<'tcx> for LateContext<'tcx> { } } -impl<'tcx> LayoutOf<'tcx> for LateContext<'tcx> { - type Ty = Ty<'tcx>; - type TyAndLayout = Result, LayoutError<'tcx>>; +impl<'tcx> LayoutOfHelpers<'tcx> for LateContext<'tcx> { + type LayoutOfResult = Result, LayoutError<'tcx>>; - fn layout_of(&self, ty: Ty<'tcx>) -> Self::TyAndLayout { - self.tcx.layout_of(self.param_env.and(ty)) + #[inline] + fn handle_layout_err(&self, err: LayoutError<'tcx>, _: Span, _: Ty<'tcx>) -> LayoutError<'tcx> { + err } } diff --git a/compiler/rustc_lint/src/early.rs b/compiler/rustc_lint/src/early.rs index 7a8b731da5..0bba66d383 100644 --- a/compiler/rustc_lint/src/early.rs +++ b/compiler/rustc_lint/src/early.rs @@ -329,12 +329,20 @@ fn early_lint_crate( sess: &Session, lint_store: &LintStore, krate: &ast::Crate, + crate_attrs: &[ast::Attribute], pass: T, buffered: LintBuffer, warn_about_weird_lints: bool, ) -> LintBuffer { let mut cx = EarlyContextAndPass { - context: EarlyContext::new(sess, lint_store, krate, buffered, warn_about_weird_lints), + context: EarlyContext::new( + sess, + lint_store, + krate, + crate_attrs, + buffered, + warn_about_weird_lints, + ), pass, }; @@ -355,6 +363,7 @@ pub fn check_ast_crate( sess: &Session, lint_store: &LintStore, krate: &ast::Crate, + crate_attrs: &[ast::Attribute], pre_expansion: bool, lint_buffer: Option, builtin_lints: T, @@ -365,14 +374,22 @@ pub fn check_ast_crate( let mut buffered = lint_buffer.unwrap_or_default(); if !sess.opts.debugging_opts.no_interleave_lints { - buffered = - early_lint_crate(sess, lint_store, krate, builtin_lints, buffered, pre_expansion); + buffered = early_lint_crate( + sess, + lint_store, + krate, + crate_attrs, + builtin_lints, + buffered, + pre_expansion, + ); if !passes.is_empty() { buffered = early_lint_crate( sess, lint_store, krate, + crate_attrs, EarlyLintPassObjects { lints: &mut passes[..] }, buffered, false, @@ -386,6 +403,7 @@ pub fn check_ast_crate( sess, lint_store, krate, + crate_attrs, EarlyLintPassObjects { lints: slice::from_mut(pass) }, buffered, pre_expansion && i == 0, diff --git a/compiler/rustc_lint/src/enum_intrinsics_non_enums.rs b/compiler/rustc_lint/src/enum_intrinsics_non_enums.rs new file mode 100644 index 0000000000..876245747f --- /dev/null +++ b/compiler/rustc_lint/src/enum_intrinsics_non_enums.rs @@ -0,0 +1,106 @@ +use crate::{context::LintContext, LateContext, LateLintPass}; +use rustc_hir as hir; +use rustc_middle::ty::{fold::TypeFoldable, Ty}; +use rustc_span::{symbol::sym, Span}; + +declare_lint! { + /// The `enum_intrinsics_non_enums` lint detects calls to + /// intrinsic functions that require an enum ([`core::mem::discriminant`], + /// [`core::mem::variant_count`]), but are called with a non-enum type. + /// + /// [`core::mem::discriminant`]: https://doc.rust-lang.org/core/mem/fn.discriminant.html + /// [`core::mem::variant_count`]: https://doc.rust-lang.org/core/mem/fn.variant_count.html + /// + /// ### Example + /// + /// ```rust,compile_fail + /// #![deny(enum_intrinsics_non_enums)] + /// core::mem::discriminant::(&123); + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// In order to accept any enum, the `mem::discriminant` and + /// `mem::variant_count` functions are generic over a type `T`. + /// This makes it technically possible for `T` to be a non-enum, + /// in which case the return value is unspecified. + /// + /// This lint prevents such incorrect usage of these functions. + ENUM_INTRINSICS_NON_ENUMS, + Deny, + "detects calls to `core::mem::discriminant` and `core::mem::variant_count` with non-enum types" +} + +declare_lint_pass!(EnumIntrinsicsNonEnums => [ENUM_INTRINSICS_NON_ENUMS]); + +/// Returns `true` if we know for sure that the given type is not an enum. Note that for cases where +/// the type is generic, we can't be certain if it will be an enum so we have to assume that it is. +fn is_non_enum(t: Ty<'_>) -> bool { + !t.is_enum() && !t.potentially_needs_subst() +} + +fn enforce_mem_discriminant( + cx: &LateContext<'_>, + func_expr: &hir::Expr<'_>, + expr_span: Span, + args_span: Span, +) { + let ty_param = cx.typeck_results().node_substs(func_expr.hir_id).type_at(0); + if is_non_enum(ty_param) { + cx.struct_span_lint(ENUM_INTRINSICS_NON_ENUMS, expr_span, |builder| { + builder + .build( + "the return value of `mem::discriminant` is \ + unspecified when called with a non-enum type", + ) + .span_note( + args_span, + &format!( + "the argument to `discriminant` should be a \ + reference to an enum, but it was passed \ + a reference to a `{}`, which is not an enum.", + ty_param, + ), + ) + .emit(); + }); + } +} + +fn enforce_mem_variant_count(cx: &LateContext<'_>, func_expr: &hir::Expr<'_>, span: Span) { + let ty_param = cx.typeck_results().node_substs(func_expr.hir_id).type_at(0); + if is_non_enum(ty_param) { + cx.struct_span_lint(ENUM_INTRINSICS_NON_ENUMS, span, |builder| { + builder + .build( + "the return value of `mem::variant_count` is \ + unspecified when called with a non-enum type", + ) + .note(&format!( + "the type parameter of `variant_count` should \ + be an enum, but it was instantiated with \ + the type `{}`, which is not an enum.", + ty_param, + )) + .emit(); + }); + } +} + +impl<'tcx> LateLintPass<'tcx> for EnumIntrinsicsNonEnums { + fn check_expr(&mut self, cx: &LateContext<'_>, expr: &hir::Expr<'_>) { + if let hir::ExprKind::Call(ref func, ref args) = expr.kind { + if let hir::ExprKind::Path(ref qpath) = func.kind { + if let Some(def_id) = cx.qpath_res(qpath, func.hir_id).opt_def_id() { + if cx.tcx.is_diagnostic_item(sym::mem_discriminant, def_id) { + enforce_mem_discriminant(cx, func, expr.span, args[0].span); + } else if cx.tcx.is_diagnostic_item(sym::mem_variant_count, def_id) { + enforce_mem_variant_count(cx, func, expr.span); + } + } + } + } + } +} diff --git a/compiler/rustc_lint/src/hidden_unicode_codepoints.rs b/compiler/rustc_lint/src/hidden_unicode_codepoints.rs new file mode 100644 index 0000000000..1bcdcb806f --- /dev/null +++ b/compiler/rustc_lint/src/hidden_unicode_codepoints.rs @@ -0,0 +1,161 @@ +use crate::{EarlyContext, EarlyLintPass, LintContext}; +use rustc_ast as ast; +use rustc_errors::{Applicability, SuggestionStyle}; +use rustc_span::{BytePos, Span, Symbol}; + +declare_lint! { + /// The `text_direction_codepoint_in_literal` lint detects Unicode codepoints that change the + /// visual representation of text on screen in a way that does not correspond to their on + /// memory representation. + /// + /// ### Explanation + /// + /// The unicode characters `\u{202A}`, `\u{202B}`, `\u{202D}`, `\u{202E}`, `\u{2066}`, + /// `\u{2067}`, `\u{2068}`, `\u{202C}` and `\u{2069}` make the flow of text on screen change + /// its direction on software that supports these codepoints. This makes the text "abc" display + /// as "cba" on screen. By leveraging software that supports these, people can write specially + /// crafted literals that make the surrounding code seem like it's performing one action, when + /// in reality it is performing another. Because of this, we proactively lint against their + /// presence to avoid surprises. + /// + /// ### Example + /// + /// ```rust,compile_fail + /// #![deny(text_direction_codepoint_in_literal)] + /// fn main() { + /// println!("{:?}", '‮'); + /// } + /// ``` + /// + /// {{produces}} + /// + pub TEXT_DIRECTION_CODEPOINT_IN_LITERAL, + Deny, + "detect special Unicode codepoints that affect the visual representation of text on screen, \ + changing the direction in which text flows", +} + +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, + cx: &EarlyContext<'_>, + text: Symbol, + span: Span, + padding: u32, + point_at_inner_spans: bool, + label: &str, + ) { + // Obtain the `Span`s for each of the forbidden chars. + let spans: Vec<_> = text + .as_str() + .char_indices() + .filter_map(|(i, c)| { + UNICODE_TEXT_FLOW_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))) + }) + }) + .collect(); + + cx.struct_span_lint(TEXT_DIRECTION_CODEPOINT_IN_LITERAL, span, |lint| { + let mut err = lint.build(&format!( + "unicode codepoint changing visible direction of text present in {}", + label + )); + let (an, s) = match spans.len() { + 1 => ("an ", ""), + _ => ("", "s"), + }; + err.span_label( + span, + &format!( + "this {} contains {}invisible unicode text flow control codepoint{}", + label, an, s, + ), + ); + if point_at_inner_spans { + for (c, span) in &spans { + err.span_label(*span, format!("{:?}", c)); + } + } + err.note( + "these kind of unicode codepoints change the way text flows on applications that \ + support them, but can cause confusion because they change the order of \ + characters on the screen", + ); + if point_at_inner_spans && !spans.is_empty() { + err.multipart_suggestion_with_style( + "if their presence wasn't intentional, you can remove them", + spans.iter().map(|(_, span)| (*span, "".to_string())).collect(), + Applicability::MachineApplicable, + SuggestionStyle::HideCodeAlways, + ); + err.multipart_suggestion( + "if you want to keep them but make them visible in your source code, you can \ + escape them", + spans + .into_iter() + .map(|(c, span)| { + let c = format!("{:?}", c); + (span, c[1..c.len() - 1].to_string()) + }) + .collect(), + Applicability::MachineApplicable, + ); + } else { + // FIXME: in other suggestions we've reversed the inner spans of doc comments. We + // should do the same here to provide the same good suggestions as we do for + // literals above. + err.note("if their presence wasn't intentional, you can remove them"); + err.note(&format!( + "if you want to keep them but make them visible in your source code, you can \ + escape them: {}", + spans + .into_iter() + .map(|(c, _)| { format!("{:?}", c) }) + .collect::>() + .join(", "), + )); + } + err.emit(); + }); + } +} +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) { + self.lint_text_direction_codepoint(cx, comment, attr.span, 0, false, "doc comment"); + } + } + } + + fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &ast::Expr) { + // byte strings are already handled well enough by `EscapeError::NonAsciiCharInByteString` + 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) { + return; + } + let padding = match kind { + // account for `"` or `'` + ast::LitKind::Str(_, ast::StrStyle::Cooked) | ast::LitKind::Char(_) => 1, + // account for `r###"` + ast::LitKind::Str(_, ast::StrStyle::Raw(val)) => *val as u32 + 2, + _ => return, + }; + (text, span, padding) + } + _ => return, + }; + self.lint_text_direction_codepoint(cx, text, *span, padding, true, "literal"); + } +} diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs index 8a4a708943..50a0d211a3 100644 --- a/compiler/rustc_lint/src/internal.rs +++ b/compiler/rustc_lint/src/internal.rs @@ -33,12 +33,10 @@ impl LateLintPass<'_> for DefaultHashTypes { // don't lint imports, only actual usages return; } - let replace = if cx.tcx.is_diagnostic_item(sym::hashmap_type, def_id) { - "FxHashMap" - } else if cx.tcx.is_diagnostic_item(sym::hashset_type, def_id) { - "FxHashSet" - } else { - return; + let replace = match cx.tcx.get_diagnostic_name(def_id) { + Some(sym::HashMap) => "FxHashMap", + Some(sym::HashSet) => "FxHashSet", + _ => return, }; cx.struct_span_lint(DEFAULT_HASH_TYPES, path.span, |lint| { let msg = format!( @@ -174,26 +172,29 @@ 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(_, did) => { - if cx.tcx.is_diagnostic_item(sym::Ty, did) { - return Some(format!("Ty{}", gen_args(path.segments.last().unwrap()))); - } else if cx.tcx.is_diagnostic_item(sym::TyCtxt, did) { - return Some(format!("TyCtxt{}", gen_args(path.segments.last().unwrap()))); + 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 cx.tcx.is_diagnostic_item(sym::Ty, adt.did) { + 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!("Ty<{}>", substs[0])); - } else if cx.tcx.is_diagnostic_item(sym::TyCtxt, adt.did) { - return Some(format!("TyCtxt<{}>", substs[0])); + return Some(format!("{}<{}>", name, substs[0])); } } } diff --git a/compiler/rustc_lint/src/late.rs b/compiler/rustc_lint/src/late.rs index 30400da86b..773e5751f1 100644 --- a/compiler/rustc_lint/src/late.rs +++ b/compiler/rustc_lint/src/late.rs @@ -16,7 +16,7 @@ use crate::{passes::LateLintPassObject, LateContext, LateLintPass, LintStore}; use rustc_ast as ast; -use rustc_data_structures::sync::{join, par_iter, ParallelIterator}; +use rustc_data_structures::sync::join; use rustc_hir as hir; use rustc_hir::def_id::LocalDefId; use rustc_hir::intravisit as hir_visit; @@ -430,8 +430,6 @@ pub fn late_lint_mod<'tcx, T: LateLintPass<'tcx>>( fn late_lint_pass_crate<'tcx, T: LateLintPass<'tcx>>(tcx: TyCtxt<'tcx>, pass: T) { let access_levels = &tcx.privacy_access_levels(()); - let krate = tcx.hir().krate(); - let context = LateContext { tcx, enclosing_body: None, @@ -450,11 +448,10 @@ fn late_lint_pass_crate<'tcx, T: LateLintPass<'tcx>>(tcx: TyCtxt<'tcx>, pass: T) cx.with_lint_attrs(hir::CRATE_HIR_ID, |cx| { // since the root module isn't visited as an item (because it isn't an // item), warn for it here. - lint_callback!(cx, check_crate, krate); - - hir_visit::walk_crate(cx, krate); - - lint_callback!(cx, check_crate_post, krate); + lint_callback!(cx, check_crate,); + tcx.hir().walk_toplevel_module(cx); + tcx.hir().walk_attributes(cx); + lint_callback!(cx, check_crate_post,); }) } @@ -502,9 +499,7 @@ pub fn check_crate<'tcx, T: LateLintPass<'tcx>>( || { tcx.sess.time("module_lints", || { // Run per-module lints - par_iter(&tcx.hir().krate().modules).for_each(|(&module, _)| { - tcx.ensure().lint_mod(module); - }); + tcx.hir().par_for_each_module(|module| tcx.ensure().lint_mod(module)); }); }, ); diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs index 90bf34ee86..b6d66eb12d 100644 --- a/compiler/rustc_lint/src/levels.rs +++ b/compiler/rustc_lint/src/levels.rs @@ -1,7 +1,6 @@ use crate::context::{CheckLintNameResult, LintStore}; use crate::late::unerased_lint_store; use rustc_ast as ast; -use rustc_ast::unwrap_or; use rustc_ast_pretty::pprust; use rustc_data_structures::fx::FxHashMap; use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder}; @@ -37,7 +36,7 @@ fn lint_levels(tcx: TyCtxt<'_>, (): ()) -> LintLevelMap { let push = builder.levels.push(tcx.hir().attrs(hir::CRATE_HIR_ID), &store, true); builder.levels.register_id(hir::CRATE_HIR_ID); - intravisit::walk_crate(&mut builder, krate); + tcx.hir().walk_toplevel_module(&mut builder); builder.levels.pop(push); builder.levels.build_map() @@ -233,7 +232,10 @@ impl<'s> LintLevelsBuilder<'s> { Some(lvl) => lvl, }; - let mut metas = unwrap_or!(attr.meta_item_list(), continue); + let mut metas = match attr.meta_item_list() { + Some(x) => x, + None => continue, + }; if metas.is_empty() { // FIXME (#55112): issue unused-attributes lint for `#[level()]` diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index ef4bda666b..f6514ddca9 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -26,7 +26,6 @@ //! This API is completely unstable and subject to change. #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] -#![cfg_attr(test, feature(test))] #![feature(array_windows)] #![feature(bool_to_option)] #![feature(box_patterns)] @@ -48,6 +47,8 @@ mod array_into_iter; pub mod builtin; mod context; mod early; +mod enum_intrinsics_non_enums; +pub mod hidden_unicode_codepoints; mod internal; mod late; mod levels; @@ -77,6 +78,8 @@ use rustc_span::Span; use array_into_iter::ArrayIntoIter; use builtin::*; +use enum_intrinsics_non_enums::EnumIntrinsicsNonEnums; +use hidden_unicode_codepoints::*; use internal::*; use methods::*; use non_ascii_idents::*; @@ -128,6 +131,7 @@ macro_rules! early_lint_passes { DeprecatedAttr: DeprecatedAttr::new(), WhileTrue: WhileTrue, NonAsciiIdents: NonAsciiIdents, + HiddenUnicodeCodepoints: HiddenUnicodeCodepoints, IncompleteFeatures: IncompleteFeatures, RedundantSemicolons: RedundantSemicolons, UnusedDocComment: UnusedDocComment, @@ -169,6 +173,7 @@ macro_rules! late_lint_passes { TemporaryCStringAsPtr: TemporaryCStringAsPtr, NonPanicFmt: NonPanicFmt, NoopMethodCall: NoopMethodCall, + EnumIntrinsicsNonEnums: EnumIntrinsicsNonEnums, InvalidAtomicOrdering: InvalidAtomicOrdering, NamedAsmLabels: NamedAsmLabels, ] diff --git a/compiler/rustc_lint/src/methods.rs b/compiler/rustc_lint/src/methods.rs index 8732845af0..5558947de0 100644 --- a/compiler/rustc_lint/src/methods.rs +++ b/compiler/rustc_lint/src/methods.rs @@ -84,7 +84,7 @@ fn lint_cstring_as_ptr( ) { let source_type = cx.typeck_results().expr_ty(source); if let ty::Adt(def, substs) = source_type.kind() { - if cx.tcx.is_diagnostic_item(sym::result_type, def.did) { + if cx.tcx.is_diagnostic_item(sym::Result, def.did) { if let ty::Adt(adt, _) = substs.type_at(0).kind() { if cx.tcx.is_diagnostic_item(sym::cstring_type, adt.did) { cx.struct_span_lint(TEMPORARY_CSTRING_AS_PTR, as_ptr_span, |diag| { diff --git a/compiler/rustc_lint/src/non_ascii_idents.rs b/compiler/rustc_lint/src/non_ascii_idents.rs index 301e607fc5..9b4ee148df 100644 --- a/compiler/rustc_lint/src/non_ascii_idents.rs +++ b/compiler/rustc_lint/src/non_ascii_idents.rs @@ -331,9 +331,9 @@ impl EarlyLintPass for NonAsciiIdents { for ((sp, ch_list), script_set) in lint_reports { cx.struct_span_lint(MIXED_SCRIPT_CONFUSABLES, sp, |lint| { let message = format!( - "The usage of Script Group `{}` in this crate consists solely of mixed script confusables", + "the usage of Script Group `{}` in this crate consists solely of mixed script confusables", script_set); - let mut note = "The usage includes ".to_string(); + let mut note = "the usage includes ".to_string(); for (idx, ch) in ch_list.into_iter().enumerate() { if idx != 0 { note += ", "; @@ -341,8 +341,7 @@ impl EarlyLintPass for NonAsciiIdents { let char_info = format!("'{}' (U+{:04X})", ch, ch as u32); note += &char_info; } - note += "."; - lint.build(&message).note(¬e).note("Please recheck to make sure their usages are indeed what you want.").emit() + lint.build(&message).note(¬e).note("please recheck to make sure their usages are indeed what you want").emit() }); } } diff --git a/compiler/rustc_lint/src/non_fmt_panic.rs b/compiler/rustc_lint/src/non_fmt_panic.rs index 33a6edafa2..f2ad72f97e 100644 --- a/compiler/rustc_lint/src/non_fmt_panic.rs +++ b/compiler/rustc_lint/src/non_fmt_panic.rs @@ -18,7 +18,7 @@ declare_lint! { /// /// ### Example /// - /// ```rust,no_run + /// ```rust,no_run,edition2018 /// panic!("{}"); /// panic!(123); /// ``` @@ -54,9 +54,10 @@ impl<'tcx> LateLintPass<'tcx> for NonPanicFmt { || Some(def_id) == cx.tcx.lang_items().panic_str() { if let Some(id) = f.span.ctxt().outer_expn_data().macro_def_id { - if cx.tcx.is_diagnostic_item(sym::std_panic_2015_macro, id) - || cx.tcx.is_diagnostic_item(sym::core_panic_2015_macro, id) - { + if matches!( + cx.tcx.get_diagnostic_name(id), + Some(sym::core_panic_2015_macro | sym::std_panic_2015_macro) + ) { check_panic(cx, f, arg); } } @@ -130,14 +131,14 @@ fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tc ty::Ref(_, r, _) if *r.kind() == ty::Str, ) || matches!( ty.ty_adt_def(), - Some(ty_def) if cx.tcx.is_diagnostic_item(sym::string_type, ty_def.did), + Some(ty_def) if cx.tcx.is_diagnostic_item(sym::String, ty_def.did), ); let (suggest_display, suggest_debug) = cx.tcx.infer_ctxt().enter(|infcx| { - let display = is_str || cx.tcx.get_diagnostic_item(sym::display_trait).map(|t| { + let display = is_str || cx.tcx.get_diagnostic_item(sym::Display).map(|t| { infcx.type_implements_trait(t, ty, InternalSubsts::empty(), cx.param_env).may_apply() }) == Some(true); - let debug = !display && cx.tcx.get_diagnostic_item(sym::debug_trait).map(|t| { + let debug = !display && cx.tcx.get_diagnostic_item(sym::Debug).map(|t| { infcx.type_implements_trait(t, ty, InternalSubsts::empty(), cx.param_env).may_apply() }) == Some(true); (display, debug) @@ -229,8 +230,7 @@ fn check_panic_str<'tcx>( Err(_) => (None, None), }; - let mut fmt_parser = - Parser::new(fmt.as_ref(), style, snippet.clone(), false, ParseMode::Format); + let mut fmt_parser = Parser::new(fmt, style, snippet.clone(), false, ParseMode::Format); let n_arguments = (&mut fmt_parser).filter(|a| matches!(a, Piece::NextArgument(_))).count(); if n_arguments > 0 && fmt_parser.errors.is_empty() { diff --git a/compiler/rustc_lint/src/nonstandard_style.rs b/compiler/rustc_lint/src/nonstandard_style.rs index 03344973bb..bcddc4f3d7 100644 --- a/compiler/rustc_lint/src/nonstandard_style.rs +++ b/compiler/rustc_lint/src/nonstandard_style.rs @@ -437,12 +437,13 @@ impl<'tcx> LateLintPass<'tcx> for NonSnakeCase { if let hir::Node::Pat(parent_pat) = cx.tcx.hir().get(cx.tcx.hir().get_parent_node(hid)) { if let PatKind::Struct(_, field_pats, _) = &parent_pat.kind { - for field in field_pats.iter() { - if field.ident != ident { - // Only check if a new name has been introduced, to avoid warning - // on both the struct definition and this pattern. - self.check_snake_case(cx, "variable", &ident); - } + if field_pats + .iter() + .any(|field| !field.is_shorthand && field.pat.hir_id == p.hir_id) + { + // Only check if a new name has been introduced, to avoid warning + // on both the struct definition and this pattern. + self.check_snake_case(cx, "variable", &ident); } return; } diff --git a/compiler/rustc_lint/src/noop_method_call.rs b/compiler/rustc_lint/src/noop_method_call.rs index c14f16b6d1..d2c970468a 100644 --- a/compiler/rustc_lint/src/noop_method_call.rs +++ b/compiler/rustc_lint/src/noop_method_call.rs @@ -51,9 +51,10 @@ impl<'tcx> LateLintPass<'tcx> for NoopMethodCall { Some((DefKind::AssocFn, did)) => match cx.tcx.trait_of_item(did) { // Check that we're dealing with a trait method for one of the traits we care about. Some(trait_id) - if [sym::Clone, sym::Deref, sym::Borrow] - .iter() - .any(|s| cx.tcx.is_diagnostic_item(*s, trait_id)) => + if matches!( + cx.tcx.get_diagnostic_name(trait_id), + Some(sym::Borrow | sym::Clone | sym::Deref) + ) => { (trait_id, did) } diff --git a/compiler/rustc_lint/src/passes.rs b/compiler/rustc_lint/src/passes.rs index 2d047ac7a0..b1b4229b1f 100644 --- a/compiler/rustc_lint/src/passes.rs +++ b/compiler/rustc_lint/src/passes.rs @@ -16,8 +16,8 @@ macro_rules! late_lint_methods { fn check_body(a: &$hir hir::Body<$hir>); fn check_body_post(a: &$hir hir::Body<$hir>); fn check_name(a: Span, b: Symbol); - fn check_crate(a: &$hir hir::Crate<$hir>); - fn check_crate_post(a: &$hir hir::Crate<$hir>); + fn check_crate(); + fn check_crate_post(); fn check_mod(a: &$hir hir::Mod<$hir>, b: Span, c: hir::HirId); fn check_mod_post(a: &$hir hir::Mod<$hir>, b: Span, c: hir::HirId); fn check_foreign_item(a: &$hir hir::ForeignItem<$hir>); diff --git a/compiler/rustc_lint/src/traits.rs b/compiler/rustc_lint/src/traits.rs index edb158dd37..5435ff1396 100644 --- a/compiler/rustc_lint/src/traits.rs +++ b/compiler/rustc_lint/src/traits.rs @@ -86,6 +86,7 @@ declare_lint_pass!( impl<'tcx> LateLintPass<'tcx> for DropTraitConstraints { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) { + use rustc_middle::ty; use rustc_middle::ty::PredicateKind::*; let predicates = cx.tcx.explicit_predicates_of(item.def_id); @@ -94,6 +95,10 @@ impl<'tcx> LateLintPass<'tcx> for DropTraitConstraints { Trait(trait_predicate) => trait_predicate, _ => continue, }; + if trait_predicate.constness == ty::BoundConstness::ConstIfConst { + // `~const Drop` definitely have meanings so avoid linting here. + continue; + } let def_id = trait_predicate.trait_ref.def_id; if cx.tcx.lang_items().drop_trait() == Some(def_id) { // Explicitly allow `impl Drop`, a drop-guards-as-Voldemort-type pattern. diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index 5d25578163..708cd56e06 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -6,14 +6,14 @@ use rustc_errors::Applicability; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::{is_range_literal, Expr, ExprKind, Node}; -use rustc_middle::ty::layout::{IntegerExt, SizeSkeleton}; +use rustc_middle::ty::layout::{IntegerExt, LayoutOf, SizeSkeleton}; use rustc_middle::ty::subst::SubstsRef; use rustc_middle::ty::{self, AdtKind, DefIdTree, Ty, TyCtxt, TypeFoldable}; use rustc_span::source_map; use rustc_span::symbol::sym; use rustc_span::{Span, Symbol, DUMMY_SP}; use rustc_target::abi::Abi; -use rustc_target::abi::{Integer, LayoutOf, TagEncoding, Variants}; +use rustc_target::abi::{Integer, TagEncoding, Variants}; use rustc_target::spec::abi::Abi as SpecAbi; use if_chain::if_chain; @@ -851,12 +851,18 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { use FfiResult::*; if def.repr.transparent() { - // Can assume that only one field is not a ZST, so only check + // Can assume that at most one field is not a ZST, so only check // that field's type for FFI-safety. if let Some(field) = transparent_newtype_field(self.cx.tcx, variant) { self.check_field_type_for_ffi(cache, field, substs) } else { - bug!("malformed transparent type"); + // All fields are ZSTs; this means that the type should behave + // like (), which is FFI-unsafe + FfiUnsafe { + ty, + reason: "this struct contains only zero-sized fields".into(), + help: None, + } } } else { // We can't completely trust repr(C) markings; make sure the fields are @@ -1050,6 +1056,15 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { FfiSafe } + ty::RawPtr(ty::TypeAndMut { ty, .. }) + if match ty.kind() { + ty::Tuple(tuple) => tuple.is_empty(), + _ => false, + } => + { + FfiSafe + } + ty::RawPtr(ty::TypeAndMut { ty, .. }) | ty::Ref(_, ty, _) => { self.check_type_for_ffi(cache, ty) } @@ -1327,10 +1342,7 @@ impl<'tcx> LateLintPass<'tcx> for VariantSizeDifferences { }; let (variants, tag) = match layout.variants { Variants::Multiple { - tag_encoding: TagEncoding::Direct, - ref tag, - ref variants, - .. + tag_encoding: TagEncoding::Direct, tag, ref variants, .. } => (variants, tag), _ => return, }; @@ -1529,8 +1541,7 @@ impl InvalidAtomicOrdering { if let ExprKind::Call(ref func, ref args) = expr.kind; if let ExprKind::Path(ref func_qpath) = func.kind; if let Some(def_id) = cx.qpath_res(func_qpath, func.hir_id).opt_def_id(); - if cx.tcx.is_diagnostic_item(sym::fence, def_id) || - cx.tcx.is_diagnostic_item(sym::compiler_fence, def_id); + if matches!(cx.tcx.get_diagnostic_name(def_id), Some(sym::fence | sym::compiler_fence)); if let ExprKind::Path(ref ordering_qpath) = &args[0].kind; if let Some(ordering_def_id) = cx.qpath_res(ordering_qpath, args[0].hir_id).opt_def_id(); if Self::matches_ordering(cx, ordering_def_id, &[sym::Relaxed]); diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index f04ac8dd94..48b955e41a 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -3,7 +3,6 @@ use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext} use rustc_ast as ast; use rustc_ast::util::{classify, parser}; use rustc_ast::{ExprKind, StmtKind}; -use rustc_ast_pretty::pprust; use rustc_errors::{pluralize, Applicability}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; @@ -12,7 +11,7 @@ use rustc_middle::ty::adjustment; use rustc_middle::ty::{self, Ty}; use rustc_span::symbol::Symbol; use rustc_span::symbol::{kw, sym}; -use rustc_span::{BytePos, Span, DUMMY_SP}; +use rustc_span::{BytePos, MultiSpan, Span, DUMMY_SP}; declare_lint! { /// The `unused_must_use` lint detects unused result of a type flagged as @@ -461,13 +460,16 @@ trait UnusedDelimLint { let lhs_needs_parens = { let mut innermost = inner; loop { - if let ExprKind::Binary(_, lhs, _rhs) = &innermost.kind { - innermost = lhs; - if !classify::expr_requires_semi_to_be_stmt(innermost) { - break true; - } - } else { - break false; + innermost = match &innermost.kind { + ExprKind::Binary(_, lhs, _rhs) => lhs, + ExprKind::Call(fn_, _params) => fn_, + ExprKind::Cast(expr, _ty) => expr, + ExprKind::Type(expr, _ty) => expr, + ExprKind::Index(base, _subscript) => base, + _ => break false, + }; + if !classify::expr_requires_semi_to_be_stmt(innermost) { + break true; } } }; @@ -488,77 +490,60 @@ trait UnusedDelimLint { left_pos: Option, right_pos: Option, ) { - let expr_text = if let Ok(snippet) = cx.sess().source_map().span_to_snippet(value.span) { - snippet - } else { - pprust::expr_to_string(value) + let spans = match value.kind { + ast::ExprKind::Block(ref block, None) if block.stmts.len() > 0 => { + let start = block.stmts[0].span; + let end = block.stmts[block.stmts.len() - 1].span; + if value.span.from_expansion() || start.from_expansion() || end.from_expansion() { + ( + value.span.with_hi(value.span.lo() + BytePos(1)), + value.span.with_lo(value.span.hi() - BytePos(1)), + ) + } else { + (value.span.with_hi(start.lo()), value.span.with_lo(end.hi())) + } + } + ast::ExprKind::Paren(ref expr) => { + if value.span.from_expansion() || expr.span.from_expansion() { + ( + value.span.with_hi(value.span.lo() + BytePos(1)), + value.span.with_lo(value.span.hi() - BytePos(1)), + ) + } else { + (value.span.with_hi(expr.span.lo()), value.span.with_lo(expr.span.hi())) + } + } + _ => return, }; let keep_space = ( left_pos.map_or(false, |s| s >= value.span.lo()), right_pos.map_or(false, |s| s <= value.span.hi()), ); - self.emit_unused_delims(cx, value.span, &expr_text, ctx.into(), keep_space); + self.emit_unused_delims(cx, spans, ctx.into(), keep_space); } fn emit_unused_delims( &self, cx: &EarlyContext<'_>, - span: Span, - pattern: &str, + spans: (Span, Span), msg: &str, keep_space: (bool, bool), ) { // FIXME(flip1995): Quick and dirty fix for #70814. This should be fixed in rustdoc // properly. - if span == DUMMY_SP { + if spans.0 == DUMMY_SP || spans.1 == DUMMY_SP { return; } - cx.struct_span_lint(self.lint(), span, |lint| { + cx.struct_span_lint(self.lint(), MultiSpan::from(vec![spans.0, spans.1]), |lint| { let span_msg = format!("unnecessary {} around {}", Self::DELIM_STR, msg); let mut err = lint.build(&span_msg); - let mut ate_left_paren = false; - let mut ate_right_paren = false; - let parens_removed = pattern - .trim_matches(|c| match c { - '(' | '{' => { - if ate_left_paren { - false - } else { - ate_left_paren = true; - true - } - } - ')' | '}' => { - if ate_right_paren { - false - } else { - ate_right_paren = true; - true - } - } - _ => false, - }) - .trim(); - - let replace = { - let mut replace = if keep_space.0 { - let mut s = String::from(" "); - s.push_str(parens_removed); - s - } else { - String::from(parens_removed) - }; - - if keep_space.1 { - replace.push(' '); - } - replace - }; - + let replacement = vec![ + (spans.0, if keep_space.0 { " ".into() } else { "".into() }), + (spans.1, if keep_space.1 { " ".into() } else { "".into() }), + ]; let suggestion = format!("remove these {}", Self::DELIM_STR); - - err.span_suggestion_short(span, &suggestion, replace, Applicability::MachineApplicable); + err.multipart_suggestion(&suggestion, replacement, Applicability::MachineApplicable); err.emit(); }); } @@ -767,14 +752,15 @@ impl UnusedParens { // Otherwise proceed with linting. _ => {} } - - let pattern_text = - if let Ok(snippet) = cx.sess().source_map().span_to_snippet(value.span) { - snippet - } else { - pprust::pat_to_string(value) - }; - self.emit_unused_delims(cx, value.span, &pattern_text, "pattern", (false, false)); + let spans = if value.span.from_expansion() || inner.span.from_expansion() { + ( + value.span.with_hi(value.span.lo() + BytePos(1)), + value.span.with_lo(value.span.hi() - BytePos(1)), + ) + } else { + (value.span.with_hi(inner.span.lo()), value.span.with_lo(inner.span.hi())) + }; + self.emit_unused_delims(cx, spans, "pattern", (false, false)); } } } @@ -867,14 +853,15 @@ impl EarlyLintPass for UnusedParens { ); } _ => { - let pattern_text = - if let Ok(snippet) = cx.sess().source_map().span_to_snippet(ty.span) { - snippet - } else { - pprust::ty_to_string(ty) - }; - - self.emit_unused_delims(cx, ty.span, &pattern_text, "type", (false, false)); + let spans = if ty.span.from_expansion() || r.span.from_expansion() { + ( + ty.span.with_hi(ty.span.lo() + BytePos(1)), + ty.span.with_lo(ty.span.hi() - BytePos(1)), + ) + } else { + (ty.span.with_hi(r.span.lo()), ty.span.with_lo(r.span.hi())) + }; + self.emit_unused_delims(cx, spans, "type", (false, false)); } } } diff --git a/compiler/rustc_lint_defs/Cargo.toml b/compiler/rustc_lint_defs/Cargo.toml index f9ada5cc95..798d50819e 100644 --- a/compiler/rustc_lint_defs/Cargo.toml +++ b/compiler/rustc_lint_defs/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustc_lint_defs" version = "0.0.0" -edition = "2018" +edition = "2021" [dependencies] rustc_ast = { path = "../rustc_ast" } diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 8fb678e2d2..8f4f54d026 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -6,6 +6,7 @@ use crate::{declare_lint, declare_lint_pass, FutureIncompatibilityReason}; use rustc_span::edition::Edition; +use rustc_span::symbol::sym; declare_lint! { /// The `forbidden_lint_groups` lint detects violations of @@ -314,6 +315,46 @@ declare_lint! { "imports that are never used" } +declare_lint! { + /// The `must_not_suspend` lint guards against values that shouldn't be held across suspend points + /// (`.await`) + /// + /// ### Example + /// + /// ```rust + /// #![feature(must_not_suspend)] + /// #![warn(must_not_suspend)] + /// + /// #[must_not_suspend] + /// struct SyncThing {} + /// + /// async fn yield_now() {} + /// + /// pub async fn uhoh() { + /// let guard = SyncThing {}; + /// yield_now().await; + /// } + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// The `must_not_suspend` lint detects values that are marked with the `#[must_not_suspend]` + /// attribute being held across suspend points. A "suspend" point is usually a `.await` in an async + /// function. + /// + /// This attribute can be used to mark values that are semantically incorrect across suspends + /// (like certain types of timers), values that have async alternatives, and values that + /// regularly cause problems with the `Send`-ness of async fn's returned futures (like + /// `MutexGuard`'s) + /// + pub MUST_NOT_SUSPEND, + Allow, + "use of a `#[must_not_suspend]` value across a yield point", + @feature_gate = rustc_span::symbol::sym::must_not_suspend; +} + declare_lint! { /// The `unused_extern_crates` lint guards against `extern crate` items /// that are never used. @@ -1584,7 +1625,7 @@ declare_lint! { /// /// ### Example /// - /// ```rust + /// ```rust,edition2018 /// trait Trait { } /// /// fn takes_trait_object(_: Box) { @@ -1922,6 +1963,7 @@ declare_lint! { "detects proc macro derives using inaccessible names from parent modules", @future_incompatible = FutureIncompatibleInfo { reference: "issue #83583 ", + reason: FutureIncompatibilityReason::FutureReleaseErrorReportNow, }; } @@ -2993,6 +3035,7 @@ declare_lint_pass! { CENUM_IMPL_DROP_CAST, CONST_EVALUATABLE_UNCHECKED, INEFFECTIVE_UNSTABLE_TRAIT_IMPL, + MUST_NOT_SUSPEND, UNINHABITED_STATIC, FUNCTION_ITEM_REFERENCES, USELESS_DEPRECATED, @@ -3010,6 +3053,9 @@ declare_lint_pass! { UNSUPPORTED_CALLING_CONVENTIONS, BREAK_WITH_LABEL_AND_LOOP, UNUSED_ATTRIBUTES, + NON_EXHAUSTIVE_OMITTED_PATTERNS, + TEXT_DIRECTION_CODEPOINT_IN_COMMENT, + DEREF_INTO_DYN_SUPERTRAIT, ] } @@ -3312,7 +3358,7 @@ declare_lint! { /// /// ### Example /// - /// ```rust,compile_fail + /// ```rust,edition2018,compile_fail /// #![deny(rust_2021_prefixes_incompatible_syntax)] /// /// macro_rules! m { @@ -3332,6 +3378,8 @@ declare_lint! { /// /// This lint suggests to add whitespace between the `z` and `"hey"` tokens /// to keep them separated in Rust 2021. + // Allow this lint -- rustdoc doesn't yet support threading edition into this lint's parser. + #[allow(rustdoc::invalid_rust_codeblocks)] pub RUST_2021_PREFIXES_INCOMPATIBLE_SYNTAX, Allow, "identifiers that will be parsed as a prefix in Rust 2021", @@ -3416,3 +3464,132 @@ declare_lint! { Warn, "`break` expression with label and unlabeled loop as value expression" } + +declare_lint! { + /// The `non_exhaustive_omitted_patterns` lint detects when a wildcard (`_` or `..`) in a + /// pattern for a `#[non_exhaustive]` struct or enum is reachable. + /// + /// ### Example + /// + /// ```rust,ignore (needs separate crate) + /// // crate A + /// #[non_exhaustive] + /// pub enum Bar { + /// A, + /// B, // added variant in non breaking change + /// } + /// + /// // in crate B + /// #![feature(non_exhaustive_omitted_patterns_lint)] + /// + /// match Bar::A { + /// Bar::A => {}, + /// #[warn(non_exhaustive_omitted_patterns)] + /// _ => {}, + /// } + /// ``` + /// + /// This will produce: + /// + /// ```text + /// warning: reachable patterns not covered of non exhaustive enum + /// --> $DIR/reachable-patterns.rs:70:9 + /// | + /// LL | _ => {} + /// | ^ pattern `B` not covered + /// | + /// note: the lint level is defined here + /// --> $DIR/reachable-patterns.rs:69:16 + /// | + /// LL | #[warn(non_exhaustive_omitted_patterns)] + /// | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + /// = help: ensure that all possible cases are being handled by adding the suggested match arms + /// = note: the matched value is of type `Bar` and the `non_exhaustive_omitted_patterns` attribute was found + /// ``` + /// + /// ### Explanation + /// + /// Structs and enums tagged with `#[non_exhaustive]` force the user to add a + /// (potentially redundant) wildcard when pattern-matching, to allow for future + /// addition of fields or variants. The `non_exhaustive_omitted_patterns` lint + /// detects when such a wildcard happens to actually catch some fields/variants. + /// In other words, when the match without the wildcard would not be exhaustive. + /// This lets the user be informed if new fields/variants were added. + pub NON_EXHAUSTIVE_OMITTED_PATTERNS, + Allow, + "detect when patterns of types marked `non_exhaustive` are missed", + @feature_gate = sym::non_exhaustive_omitted_patterns_lint; +} + +declare_lint! { + /// The `text_direction_codepoint_in_comment` lint detects Unicode codepoints in comments that + /// change the visual representation of text on screen in a way that does not correspond to + /// their on memory representation. + /// + /// ### Example + /// + /// ```rust,compile_fail + /// #![deny(text_direction_codepoint_in_comment)] + /// fn main() { + /// println!("{:?}"); // '‮'); + /// } + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// Unicode allows changing the visual flow of text on screen in order to support scripts that + /// are written right-to-left, but a specially crafted comment can make code that will be + /// compiled appear to be part of a comment, depending on the software used to read the code. + /// To avoid potential problems or confusion, such as in CVE-2021-42574, by default we deny + /// their use. + pub TEXT_DIRECTION_CODEPOINT_IN_COMMENT, + Deny, + "invisible directionality-changing codepoints in comment" +} + +declare_lint! { + /// The `deref_into_dyn_supertrait` lint is output whenever there is a use of the + /// `Deref` implementation with a `dyn SuperTrait` type as `Output`. + /// + /// These implementations will become shadowed when the `trait_upcasting` feature is stablized. + /// The `deref` functions will no longer be called implicitly, so there might be behavior change. + /// + /// ### Example + /// + /// ```rust,compile_fail + /// #![deny(deref_into_dyn_supertrait)] + /// #![allow(dead_code)] + /// + /// use core::ops::Deref; + /// + /// trait A {} + /// trait B: A {} + /// impl<'a> Deref for dyn 'a + B { + /// type Target = dyn A; + /// fn deref(&self) -> &Self::Target { + /// todo!() + /// } + /// } + /// + /// fn take_a(_: &dyn A) { } + /// + /// fn take_b(b: &dyn B) { + /// take_a(b); + /// } + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// The dyn upcasting coercion feature adds new coercion rules, taking priority + /// over certain other coercion rules, which will cause some behavior change. + pub DEREF_INTO_DYN_SUPERTRAIT, + Warn, + "`Deref` implementation usage with a supertrait trait object for output might be shadowed in the future", + @future_incompatible = FutureIncompatibleInfo { + reference: "issue #89460 ", + }; +} diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index f89d531b5e..feac2a7cfa 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -306,6 +306,7 @@ pub enum BuiltinLintDiagnostics { TrailingMacro(bool, Ident), BreakWithLabelAndLoop(Span), NamedAsmLabel(String), + UnicodeTextFlow(Span, String), } /// Lints that are buffered up early on in the `Session` before the diff --git a/compiler/rustc_llvm/Cargo.toml b/compiler/rustc_llvm/Cargo.toml index 2f0f3dd9ec..d8dfcc84e6 100644 --- a/compiler/rustc_llvm/Cargo.toml +++ b/compiler/rustc_llvm/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustc_llvm" version = "0.0.0" -edition = "2018" +edition = "2021" [features] static-libstdcpp = [] diff --git a/compiler/rustc_llvm/build.rs b/compiler/rustc_llvm/build.rs index 964b7cace9..36a6d2cc33 100644 --- a/compiler/rustc_llvm/build.rs +++ b/compiler/rustc_llvm/build.rs @@ -76,6 +76,7 @@ fn main() { "aarch64", "amdgpu", "avr", + "m68k", "mips", "powerpc", "systemz", diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp index b3f86f3295..87f423fb2d 100644 --- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp @@ -25,6 +25,7 @@ #include "llvm/Transforms/IPO/PassManagerBuilder.h" #include "llvm/Transforms/IPO/AlwaysInliner.h" #include "llvm/Transforms/IPO/FunctionImport.h" +#include "llvm/Transforms/Utils/AddDiscriminators.h" #include "llvm/Transforms/Utils/FunctionImportUtils.h" #include "llvm/LTO/LTO.h" #include "llvm-c/Transforms/PassManagerBuilder.h" @@ -39,6 +40,7 @@ #include "llvm/Transforms/Instrumentation/HWAddressSanitizer.h" #include "llvm/Transforms/Utils/CanonicalizeAliases.h" #include "llvm/Transforms/Utils/NameAnonGlobals.h" +#include "llvm/Transforms/Utils.h" using namespace llvm; @@ -201,6 +203,12 @@ void LLVMRustAddLastExtensionPasses( #define SUBTARGET_AVR #endif +#ifdef LLVM_COMPONENT_M68k +#define SUBTARGET_M68K SUBTARGET(M68k) +#else +#define SUBTARGET_M68K +#endif + #ifdef LLVM_COMPONENT_MIPS #define SUBTARGET_MIPS SUBTARGET(Mips) #else @@ -248,6 +256,7 @@ void LLVMRustAddLastExtensionPasses( SUBTARGET_ARM \ SUBTARGET_AARCH64 \ SUBTARGET_AVR \ + SUBTARGET_M68K \ SUBTARGET_MIPS \ SUBTARGET_PPC \ SUBTARGET_SYSTEMZ \ @@ -516,7 +525,7 @@ extern "C" void LLVMRustDisposeTargetMachine(LLVMTargetMachineRef TM) { extern "C" void LLVMRustConfigurePassManagerBuilder( LLVMPassManagerBuilderRef PMBR, LLVMRustCodeGenOptLevel OptLevel, bool MergeFunctions, bool SLPVectorize, bool LoopVectorize, bool PrepareForThinLTO, - const char* PGOGenPath, const char* PGOUsePath) { + const char* PGOGenPath, const char* PGOUsePath, const char* PGOSampleUsePath) { unwrap(PMBR)->MergeFunctions = MergeFunctions; unwrap(PMBR)->SLPVectorize = SLPVectorize; unwrap(PMBR)->OptLevel = fromRust(OptLevel); @@ -524,13 +533,14 @@ extern "C" void LLVMRustConfigurePassManagerBuilder( unwrap(PMBR)->PrepareForThinLTO = PrepareForThinLTO; if (PGOGenPath) { - assert(!PGOUsePath); + assert(!PGOUsePath && !PGOSampleUsePath); unwrap(PMBR)->EnablePGOInstrGen = true; unwrap(PMBR)->PGOInstrGen = PGOGenPath; - } - if (PGOUsePath) { - assert(!PGOGenPath); + } else if (PGOUsePath) { + assert(!PGOSampleUsePath); unwrap(PMBR)->PGOInstrUse = PGOUsePath; + } else if (PGOSampleUsePath) { + unwrap(PMBR)->PGOSampleUse = PGOSampleUsePath; } } @@ -752,6 +762,7 @@ LLVMRustOptimizeWithNewPassManager( LLVMRustSanitizerOptions *SanitizerOptions, const char *PGOGenPath, const char *PGOUsePath, bool InstrumentCoverage, bool InstrumentGCOV, + const char *PGOSampleUsePath, bool DebugInfoForProfiling, void* LlvmSelfProfiler, LLVMRustSelfProfileBeforePassCallback BeforePassCallback, LLVMRustSelfProfileAfterPassCallback AfterPassCallback, @@ -790,11 +801,19 @@ LLVMRustOptimizeWithNewPassManager( Optional PGOOpt; if (PGOGenPath) { - assert(!PGOUsePath); - PGOOpt = PGOOptions(PGOGenPath, "", "", PGOOptions::IRInstr); + assert(!PGOUsePath && !PGOSampleUsePath); + PGOOpt = PGOOptions(PGOGenPath, "", "", PGOOptions::IRInstr, + PGOOptions::NoCSAction, DebugInfoForProfiling); } else if (PGOUsePath) { - assert(!PGOGenPath); - PGOOpt = PGOOptions(PGOUsePath, "", "", PGOOptions::IRUse); + assert(!PGOSampleUsePath); + PGOOpt = PGOOptions(PGOUsePath, "", "", PGOOptions::IRUse, + PGOOptions::NoCSAction, DebugInfoForProfiling); + } else if (PGOSampleUsePath) { + PGOOpt = PGOOptions(PGOSampleUsePath, "", "", PGOOptions::SampleUse, + PGOOptions::NoCSAction, DebugInfoForProfiling); + } else if (DebugInfoForProfiling) { + PGOOpt = PGOOptions("", "", "", PGOOptions::NoAction, + PGOOptions::NoCSAction, DebugInfoForProfiling); } #if LLVM_VERSION_GE(12, 0) && !LLVM_VERSION_GE(13,0) @@ -875,7 +894,11 @@ LLVMRustOptimizeWithNewPassManager( #if LLVM_VERSION_GE(11, 0) OptimizerLastEPCallbacks.push_back( [Options](ModulePassManager &MPM, OptimizationLevel Level) { +#if LLVM_VERSION_GE(14, 0) + MPM.addPass(ModuleMemorySanitizerPass(Options)); +#else MPM.addPass(MemorySanitizerPass(Options)); +#endif MPM.addPass(createModuleToFunctionPassAdaptor(MemorySanitizerPass(Options))); } ); @@ -897,7 +920,11 @@ LLVMRustOptimizeWithNewPassManager( #if LLVM_VERSION_GE(11, 0) OptimizerLastEPCallbacks.push_back( [](ModulePassManager &MPM, OptimizationLevel Level) { +#if LLVM_VERSION_GE(14, 0) + MPM.addPass(ModuleThreadSanitizerPass()); +#else MPM.addPass(ThreadSanitizerPass()); +#endif MPM.addPass(createModuleToFunctionPassAdaptor(ThreadSanitizerPass())); } ); @@ -989,7 +1016,10 @@ LLVMRustOptimizeWithNewPassManager( #endif bool NeedThinLTOBufferPasses = UseThinLTOBuffers; if (!NoPrepopulatePasses) { - if (OptLevel == OptimizationLevel::O0) { + // The pre-link pipelines don't support O0 and require using budilO0DefaultPipeline() instead. + // 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); @@ -1554,7 +1584,11 @@ extern "C" bool LLVMRustPrepareThinLTOResolveWeak(const LLVMRustThinLTOData *Data, LLVMModuleRef M) { Module &Mod = *unwrap(M); const auto &DefinedGlobals = Data->ModuleToDefinedGVSummaries.lookup(Mod.getModuleIdentifier()); +#if LLVM_VERSION_GE(14, 0) + thinLTOFinalizeInModule(Mod, DefinedGlobals, /*PropagateAttrs=*/true); +#else thinLTOResolvePrevailingInModule(Mod, DefinedGlobals); +#endif return true; } @@ -1732,7 +1766,7 @@ LLVMRustGetBitcodeSliceFromObjectData(const char *data, // Rewrite all `DICompileUnit` pointers to the `DICompileUnit` specified. See // the comment in `back/lto.rs` for why this exists. extern "C" void -LLVMRustThinLTOGetDICompileUnit(LLVMModuleRef Mod, +LLVMRustLTOGetDICompileUnit(LLVMModuleRef Mod, DICompileUnit **A, DICompileUnit **B) { Module *M = unwrap(Mod); @@ -1750,7 +1784,7 @@ LLVMRustThinLTOGetDICompileUnit(LLVMModuleRef Mod, // Rewrite all `DICompileUnit` pointers to the `DICompileUnit` specified. See // the comment in `back/lto.rs` for why this exists. extern "C" void -LLVMRustThinLTOPatchDICompileUnit(LLVMModuleRef Mod, DICompileUnit *Unit) { +LLVMRustLTOPatchDICompileUnit(LLVMModuleRef Mod, DICompileUnit *Unit) { Module *M = unwrap(Mod); // If the original source module didn't have a `DICompileUnit` then try to diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp index 4f07a0c67c..b7b0524e2a 100644 --- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp @@ -54,7 +54,11 @@ static LLVM_THREAD_LOCAL char *LastError; // // Notably it exits the process with code 101, unlike LLVM's default of 1. static void FatalErrorHandler(void *UserData, +#if LLVM_VERSION_LT(14, 0) const std::string& Reason, +#else + const char* Reason, +#endif bool GenCrashDiag) { // Do the same thing that the default error handler does. std::cerr << "LLVM ERROR: " << Reason << std::endl; @@ -203,56 +207,57 @@ static Attribute::AttrKind fromRust(LLVMRustAttribute Kind) { report_fatal_error("bad AttributeKind"); } +template static inline void AddAttribute(T *t, unsigned Index, Attribute Attr) { +#if LLVM_VERSION_LT(14, 0) + t->addAttribute(Index, Attr); +#else + t->addAttributeAtIndex(Index, Attr); +#endif +} + extern "C" void LLVMRustAddCallSiteAttribute(LLVMValueRef Instr, unsigned Index, LLVMRustAttribute RustAttr) { CallBase *Call = unwrap(Instr); Attribute Attr = Attribute::get(Call->getContext(), fromRust(RustAttr)); - Call->addAttribute(Index, Attr); + AddAttribute(Call, Index, Attr); } extern "C" void LLVMRustAddCallSiteAttrString(LLVMValueRef Instr, unsigned Index, const char *Name) { CallBase *Call = unwrap(Instr); Attribute Attr = Attribute::get(Call->getContext(), Name); - Call->addAttribute(Index, Attr); + AddAttribute(Call, Index, Attr); } - extern "C" void LLVMRustAddAlignmentCallSiteAttr(LLVMValueRef Instr, unsigned Index, uint32_t Bytes) { CallBase *Call = unwrap(Instr); - AttrBuilder B; - B.addAlignmentAttr(Bytes); - Call->setAttributes(Call->getAttributes().addAttributes( - Call->getContext(), Index, B)); + Attribute Attr = Attribute::getWithAlignment(Call->getContext(), Align(Bytes)); + AddAttribute(Call, Index, Attr); } extern "C" void LLVMRustAddDereferenceableCallSiteAttr(LLVMValueRef Instr, unsigned Index, uint64_t Bytes) { CallBase *Call = unwrap(Instr); - AttrBuilder B; - B.addDereferenceableAttr(Bytes); - Call->setAttributes(Call->getAttributes().addAttributes( - Call->getContext(), Index, B)); + Attribute Attr = Attribute::getWithDereferenceableBytes(Call->getContext(), Bytes); + AddAttribute(Call, Index, Attr); } extern "C" void LLVMRustAddDereferenceableOrNullCallSiteAttr(LLVMValueRef Instr, unsigned Index, uint64_t Bytes) { CallBase *Call = unwrap(Instr); - AttrBuilder B; - B.addDereferenceableOrNullAttr(Bytes); - Call->setAttributes(Call->getAttributes().addAttributes( - Call->getContext(), Index, B)); + Attribute Attr = Attribute::getWithDereferenceableOrNullBytes(Call->getContext(), Bytes); + AddAttribute(Call, Index, Attr); } extern "C" void LLVMRustAddByValCallSiteAttr(LLVMValueRef Instr, unsigned Index, LLVMTypeRef Ty) { CallBase *Call = unwrap(Instr); Attribute Attr = Attribute::getWithByValType(Call->getContext(), unwrap(Ty)); - Call->addAttribute(Index, Attr); + AddAttribute(Call, Index, Attr); } extern "C" void LLVMRustAddStructRetCallSiteAttr(LLVMValueRef Instr, unsigned Index, @@ -263,28 +268,28 @@ extern "C" void LLVMRustAddStructRetCallSiteAttr(LLVMValueRef Instr, unsigned In #else Attribute Attr = Attribute::get(Call->getContext(), Attribute::StructRet); #endif - Call->addAttribute(Index, Attr); + AddAttribute(Call, Index, Attr); } extern "C" void LLVMRustAddFunctionAttribute(LLVMValueRef Fn, unsigned Index, LLVMRustAttribute RustAttr) { Function *A = unwrap(Fn); Attribute Attr = Attribute::get(A->getContext(), fromRust(RustAttr)); - A->addAttribute(Index, Attr); + AddAttribute(A, Index, Attr); } extern "C" void LLVMRustAddAlignmentAttr(LLVMValueRef Fn, unsigned Index, uint32_t Bytes) { Function *A = unwrap(Fn); - A->addAttribute(Index, Attribute::getWithAlignment( + AddAttribute(A, Index, Attribute::getWithAlignment( A->getContext(), llvm::Align(Bytes))); } extern "C" void LLVMRustAddDereferenceableAttr(LLVMValueRef Fn, unsigned Index, uint64_t Bytes) { Function *A = unwrap(Fn); - A->addAttribute(Index, Attribute::getWithDereferenceableBytes(A->getContext(), + AddAttribute(A, Index, Attribute::getWithDereferenceableBytes(A->getContext(), Bytes)); } @@ -292,7 +297,7 @@ extern "C" void LLVMRustAddDereferenceableOrNullAttr(LLVMValueRef Fn, unsigned Index, uint64_t Bytes) { Function *A = unwrap(Fn); - A->addAttribute(Index, Attribute::getWithDereferenceableOrNullBytes( + AddAttribute(A, Index, Attribute::getWithDereferenceableOrNullBytes( A->getContext(), Bytes)); } @@ -300,7 +305,7 @@ extern "C" void LLVMRustAddByValAttr(LLVMValueRef Fn, unsigned Index, LLVMTypeRef Ty) { Function *F = unwrap(Fn); Attribute Attr = Attribute::getWithByValType(F->getContext(), unwrap(Ty)); - F->addAttribute(Index, Attr); + AddAttribute(F, Index, Attr); } extern "C" void LLVMRustAddStructRetAttr(LLVMValueRef Fn, unsigned Index, @@ -311,7 +316,7 @@ extern "C" void LLVMRustAddStructRetAttr(LLVMValueRef Fn, unsigned Index, #else Attribute Attr = Attribute::get(F->getContext(), Attribute::StructRet); #endif - F->addAttribute(Index, Attr); + AddAttribute(F, Index, Attr); } extern "C" void LLVMRustAddFunctionAttrStringValue(LLVMValueRef Fn, @@ -319,7 +324,7 @@ extern "C" void LLVMRustAddFunctionAttrStringValue(LLVMValueRef Fn, const char *Name, const char *Value) { Function *F = unwrap(Fn); - F->addAttribute(Index, Attribute::get( + AddAttribute(F, Index, Attribute::get( F->getContext(), StringRef(Name), StringRef(Value))); } @@ -330,7 +335,12 @@ extern "C" void LLVMRustRemoveFunctionAttributes(LLVMValueRef Fn, Attribute Attr = Attribute::get(F->getContext(), fromRust(RustAttr)); AttrBuilder B(Attr); auto PAL = F->getAttributes(); - auto PALNew = PAL.removeAttributes(F->getContext(), Index, B); + AttributeList PALNew; +#if LLVM_VERSION_LT(14, 0) + PALNew = PAL.removeAttributes(F->getContext(), Index, B); +#else + PALNew = PAL.removeAttributesAtIndex(F->getContext(), Index, B); +#endif F->setAttributes(PALNew); } @@ -1743,10 +1753,11 @@ LLVMRustBuildMaxNum(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS) { } // This struct contains all necessary info about a symbol exported from a DLL. -// At the moment, it's just the symbol's name, but we use a separate struct to -// make it easier to add other information like ordinal later. struct LLVMRustCOFFShortExport { const char* name; + bool ordinal_present; + // The value of `ordinal` is only meaningful if `ordinal_present` is true. + uint16_t ordinal; }; // Machine must be a COFF machine type, as defined in PE specs. @@ -1762,13 +1773,15 @@ extern "C" LLVMRustResult LLVMRustWriteImportLibrary( ConvertedExports.reserve(NumExports); for (size_t i = 0; i < NumExports; ++i) { + bool ordinal_present = Exports[i].ordinal_present; + uint16_t ordinal = ordinal_present ? Exports[i].ordinal : 0; ConvertedExports.push_back(llvm::object::COFFShortExport{ Exports[i].name, // Name std::string{}, // ExtName std::string{}, // SymbolName std::string{}, // AliasTarget - 0, // Ordinal - false, // Noname + ordinal, // Ordinal + ordinal_present, // Noname false, // Data false, // Private false // Constant diff --git a/compiler/rustc_llvm/src/lib.rs b/compiler/rustc_llvm/src/lib.rs index 122627eb50..6493bd91ca 100644 --- a/compiler/rustc_llvm/src/lib.rs +++ b/compiler/rustc_llvm/src/lib.rs @@ -17,6 +17,10 @@ impl RustString { pub fn len(&self) -> usize { self.bytes.borrow().len() } + + pub fn is_empty(&self) -> bool { + self.bytes.borrow().is_empty() + } } /// Appending to a Rust string -- used by RawRustStringOstream. @@ -90,6 +94,14 @@ pub fn initialize_available_targets() { LLVMInitializeAVRAsmPrinter, LLVMInitializeAVRAsmParser ); + init_target!( + llvm_component = "m68k", + LLVMInitializeM68kTargetInfo, + LLVMInitializeM68kTarget, + LLVMInitializeM68kTargetMC, + LLVMInitializeM68kAsmPrinter, + LLVMInitializeM68kAsmParser + ); init_target!( llvm_component = "mips", LLVMInitializeMipsTargetInfo, diff --git a/compiler/rustc_macros/Cargo.toml b/compiler/rustc_macros/Cargo.toml index e4dddbab06..a9192be4d6 100644 --- a/compiler/rustc_macros/Cargo.toml +++ b/compiler/rustc_macros/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustc_macros" version = "0.1.0" -edition = "2018" +edition = "2021" [lib] proc-macro = true diff --git a/compiler/rustc_macros/src/hash_stable.rs b/compiler/rustc_macros/src/hash_stable.rs index b916113a0e..63bdcea87f 100644 --- a/compiler/rustc_macros/src/hash_stable.rs +++ b/compiler/rustc_macros/src/hash_stable.rs @@ -24,11 +24,9 @@ fn parse_attributes(field: &syn::Field) -> Attributes { } if meta.path().is_ident("project") { if let Meta::List(list) = meta { - if let Some(nested) = list.nested.iter().next() { - if let NestedMeta::Meta(meta) = nested { - attrs.project = meta.path().get_ident().cloned(); - any_attr = true; - } + if let Some(NestedMeta::Meta(meta)) = list.nested.iter().next() { + attrs.project = meta.path().get_ident().cloned(); + any_attr = true; } } } @@ -116,14 +114,14 @@ pub fn hash_stable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::To s.bound_impl( quote!( ::rustc_data_structures::stable_hasher::HashStable< - ::rustc_middle::ich::StableHashingContext<'__ctx>, + ::rustc_query_system::ich::StableHashingContext<'__ctx>, > ), quote! { #[inline] fn hash_stable( &self, - __hcx: &mut ::rustc_middle::ich::StableHashingContext<'__ctx>, + __hcx: &mut ::rustc_query_system::ich::StableHashingContext<'__ctx>, __hasher: &mut ::rustc_data_structures::stable_hasher::StableHasher) { #discriminant match *self { #body } diff --git a/compiler/rustc_macros/src/query.rs b/compiler/rustc_macros/src/query.rs index 7ad36973f4..005017185c 100644 --- a/compiler/rustc_macros/src/query.rs +++ b/compiler/rustc_macros/src/query.rs @@ -455,28 +455,28 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream { // Pass on the fatal_cycle modifier if let Some(fatal_cycle) = &modifiers.fatal_cycle { - attributes.push(quote! { #fatal_cycle }); + attributes.push(quote! { (#fatal_cycle) }); }; // Pass on the storage modifier if let Some(ref ty) = modifiers.storage { let span = ty.span(); - attributes.push(quote_spanned! {span=> storage(#ty) }); + attributes.push(quote_spanned! {span=> (storage #ty) }); }; // Pass on the cycle_delay_bug modifier if let Some(cycle_delay_bug) = &modifiers.cycle_delay_bug { - attributes.push(quote! { #cycle_delay_bug }); + attributes.push(quote! { (#cycle_delay_bug) }); }; // Pass on the no_hash modifier if let Some(no_hash) = &modifiers.no_hash { - attributes.push(quote! { #no_hash }); + attributes.push(quote! { (#no_hash) }); }; // Pass on the anon modifier if let Some(anon) = &modifiers.anon { - attributes.push(quote! { #anon }); + attributes.push(quote! { (#anon) }); }; // Pass on the eval_always modifier if let Some(eval_always) = &modifiers.eval_always { - attributes.push(quote! { #eval_always }); + attributes.push(quote! { (#eval_always) }); }; // This uses the span of the query definition for the commas, diff --git a/compiler/rustc_macros/src/session_diagnostic.rs b/compiler/rustc_macros/src/session_diagnostic.rs index 8a0fce209b..c8959dc86a 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); } @@ -448,7 +448,7 @@ impl<'a> SessionDiagnosticDeriveBuilder<'a> { span_idx = Some(syn::Index::from(idx)); } else { throw_span_err!( - info.span.clone().unwrap(), + info.span.unwrap(), "type of field annotated with `#[suggestion(...)]` contains more than one Span" ); } @@ -460,7 +460,7 @@ impl<'a> SessionDiagnosticDeriveBuilder<'a> { applicability_idx = Some(syn::Index::from(idx)); } else { throw_span_err!( - info.span.clone().unwrap(), + info.span.unwrap(), "type of field annotated with `#[suggestion(...)]` contains more than one Applicability" ); } @@ -479,7 +479,7 @@ impl<'a> SessionDiagnosticDeriveBuilder<'a> { return Ok((span, applicability)); } throw_span_err!( - info.span.clone().unwrap(), + info.span.unwrap(), "wrong types for suggestion", |diag| { diag.help("#[suggestion(...)] on a tuple field must be applied to fields of type (Span, Applicability)") @@ -487,7 +487,7 @@ impl<'a> SessionDiagnosticDeriveBuilder<'a> { ); } _ => throw_span_err!( - info.span.clone().unwrap(), + info.span.unwrap(), "wrong field type for suggestion", |diag| { diag.help("#[suggestion(...)] should be applied to fields of type Span or (Span, Applicability)") diff --git a/compiler/rustc_macros/src/symbols.rs b/compiler/rustc_macros/src/symbols.rs index 85e990bde8..1b245f2a75 100644 --- a/compiler/rustc_macros/src/symbols.rs +++ b/compiler/rustc_macros/src/symbols.rs @@ -215,7 +215,7 @@ fn symbols_with_errors(input: TokenStream) -> (TokenStream, Vec) { } impl Interner { - pub fn fresh() -> Self { + pub(crate) fn fresh() -> Self { Interner::prefill(&[ #prefill_stream ]) diff --git a/compiler/rustc_metadata/Cargo.toml b/compiler/rustc_metadata/Cargo.toml index 7c79aa5e00..dec77d996f 100644 --- a/compiler/rustc_metadata/Cargo.toml +++ b/compiler/rustc_metadata/Cargo.toml @@ -1,13 +1,14 @@ [package] name = "rustc_metadata" version = "0.0.0" -edition = "2018" +edition = "2021" [lib] doctest = false [dependencies] libc = "0.2" +odht = { version = "0.3.1", features = ["nightly"] } snap = "1" tracing = "0.1" smallvec = { version = "1.6.1", features = ["union", "may_dangle"] } diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index 394cb83893..95b74fd530 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -13,11 +13,11 @@ use rustc_expand::base::SyntaxExtension; use rustc_hir::def_id::{CrateNum, LocalDefId, StableCrateId, LOCAL_CRATE}; use rustc_hir::definitions::Definitions; use rustc_index::vec::IndexVec; -use rustc_middle::middle::cstore::{CrateDepKind, CrateSource, ExternCrate}; -use rustc_middle::middle::cstore::{ExternCrateSource, MetadataLoaderDyn}; use rustc_middle::ty::TyCtxt; use rustc_serialize::json::ToJson; use rustc_session::config::{self, CrateType, ExternLocation}; +use rustc_session::cstore::{CrateDepKind, CrateSource, ExternCrate}; +use rustc_session::cstore::{ExternCrateSource, MetadataLoaderDyn}; use rustc_session::lint::{self, BuiltinLintDiagnostics, ExternDepSpec}; use rustc_session::output::validate_crate_name; use rustc_session::search_paths::PathKind; @@ -45,7 +45,7 @@ pub struct CStore { /// This map is used to verify we get no hash conflicts between /// `StableCrateId` values. - stable_crate_ids: FxHashMap, + pub(crate) stable_crate_ids: FxHashMap, /// Unused externs of the crate unused_externs: Vec, @@ -450,6 +450,7 @@ impl<'a> CrateLoader<'a> { &self, locator: &mut CrateLocator<'b>, path_kind: PathKind, + host_hash: Option, ) -> Result)>, CrateError> where 'a: 'b, @@ -459,7 +460,7 @@ impl<'a> CrateLoader<'a> { let mut proc_macro_locator = locator.clone(); // Try to load a proc macro - proc_macro_locator.is_proc_macro = Some(true); + proc_macro_locator.is_proc_macro = true; // Load the proc macro crate for the target let (locator, target_result) = if self.sess.opts.debugging_opts.dual_proc_macros { @@ -471,7 +472,7 @@ impl<'a> CrateLoader<'a> { Some(LoadResult::Loaded(library)) => Some(LoadResult::Loaded(library)), None => return Ok(None), }; - locator.hash = locator.host_hash; + locator.hash = host_hash; // Use the locator when looking for the host proc macro crate, as that is required // so we want it to affect the error message (locator, result) @@ -482,7 +483,7 @@ impl<'a> CrateLoader<'a> { // Load the proc macro crate for the host locator.reset(); - locator.is_proc_macro = Some(true); + locator.is_proc_macro = true; locator.target = &self.sess.host; locator.triple = TargetTriple::from_triple(config::host_triple()); locator.filesearch = self.sess.host_filesearch(path_kind); @@ -510,12 +511,9 @@ impl<'a> CrateLoader<'a> { name: Symbol, span: Span, dep_kind: CrateDepKind, - dep: Option<(&'b CratePaths, &'b CrateDep)>, ) -> CrateNum { - if dep.is_none() { - self.used_extern_options.insert(name); - } - self.maybe_resolve_crate(name, dep_kind, dep).unwrap_or_else(|err| { + self.used_extern_options.insert(name); + self.maybe_resolve_crate(name, dep_kind, None).unwrap_or_else(|err| { let missing_core = self.maybe_resolve_crate(sym::core, CrateDepKind::Explicit, None).is_err(); err.report(&self.sess, span, missing_core) @@ -551,21 +549,18 @@ impl<'a> CrateLoader<'a> { &*self.metadata_loader, name, hash, - host_hash, extra_filename, false, // is_host path_kind, - root, - Some(false), // is_proc_macro ); match self.load(&mut locator)? { Some(res) => (res, None), None => { dep_kind = CrateDepKind::MacrosOnly; - match self.load_proc_macro(&mut locator, path_kind)? { + match self.load_proc_macro(&mut locator, path_kind, host_hash)? { Some(res) => res, - None => return Err(locator.into_error()), + None => return Err(locator.into_error(root.cloned())), } } } @@ -605,7 +600,7 @@ impl<'a> CrateLoader<'a> { // FIXME: why is this condition necessary? It was adding in #33625 but I // don't know why and the original author doesn't remember ... let can_reuse_cratenum = - locator.triple == self.sess.opts.target_triple || locator.is_proc_macro == Some(true); + locator.triple == self.sess.opts.target_triple || locator.is_proc_macro; Ok(Some(if can_reuse_cratenum { let mut result = LoadResult::Loaded(library); self.cstore.iter_crate_data(|cnum, data| { @@ -755,7 +750,7 @@ impl<'a> CrateLoader<'a> { }; info!("panic runtime not found -- loading {}", name); - let cnum = self.resolve_crate(name, DUMMY_SP, CrateDepKind::Implicit, None); + let cnum = self.resolve_crate(name, DUMMY_SP, CrateDepKind::Implicit); let data = self.cstore.get_crate_data(cnum); // Sanity check the loaded crate to ensure it is indeed a panic runtime @@ -795,7 +790,7 @@ impl<'a> CrateLoader<'a> { ); } - let cnum = self.resolve_crate(name, DUMMY_SP, CrateDepKind::Implicit, None); + let cnum = self.resolve_crate(name, DUMMY_SP, CrateDepKind::Implicit); let data = self.cstore.get_crate_data(cnum); // Sanity check the loaded crate to ensure it is indeed a profiler runtime @@ -883,7 +878,7 @@ impl<'a> CrateLoader<'a> { "no global memory allocator found but one is \ required; link to std or \ add `#[global_allocator]` to a static item \ - that implements the GlobalAlloc trait.", + that implements the GlobalAlloc trait", ); } self.cstore.allocator_kind = Some(AllocatorKind::Default); @@ -1015,7 +1010,7 @@ impl<'a> CrateLoader<'a> { CrateDepKind::Explicit }; - let cnum = self.resolve_crate(name, item.span, dep_kind, None); + let cnum = self.resolve_crate(name, item.span, dep_kind); let path_len = definitions.def_path(def_id).data.len(); self.update_extern_crate( @@ -1034,7 +1029,7 @@ impl<'a> CrateLoader<'a> { } pub fn process_path_extern(&mut self, name: Symbol, span: Span) -> CrateNum { - let cnum = self.resolve_crate(name, span, CrateDepKind::Explicit, None); + let cnum = self.resolve_crate(name, span, CrateDepKind::Explicit); self.update_extern_crate( cnum, diff --git a/compiler/rustc_metadata/src/dependency_format.rs b/compiler/rustc_metadata/src/dependency_format.rs index 2d4deb1d8d..ddc3e10fa4 100644 --- a/compiler/rustc_metadata/src/dependency_format.rs +++ b/compiler/rustc_metadata/src/dependency_format.rs @@ -11,10 +11,10 @@ //! should be used when linking each output type requested in this session. This //! generally follows this set of rules: //! -//! 1. Each library must appear exactly once in the output. -//! 2. Each rlib contains only one library (it's just an object file) -//! 3. Each dylib can contain more than one library (due to static linking), -//! and can also bring in many dynamic dependencies. +//! 1. Each library must appear exactly once in the output. +//! 2. Each rlib contains only one library (it's just an object file) +//! 3. Each dylib can contain more than one library (due to static linking), +//! and can also bring in many dynamic dependencies. //! //! With these constraints in mind, it's generally a very difficult problem to //! find a solution that's not "all rlibs" or "all dylibs". I have suspicions @@ -22,24 +22,24 @@ //! //! The current selection algorithm below looks mostly similar to: //! -//! 1. If static linking is required, then require all upstream dependencies -//! to be available as rlibs. If not, generate an error. -//! 2. If static linking is requested (generating an executable), then -//! attempt to use all upstream dependencies as rlibs. If any are not -//! found, bail out and continue to step 3. -//! 3. Static linking has failed, at least one library must be dynamically -//! linked. Apply a heuristic by greedily maximizing the number of -//! dynamically linked libraries. -//! 4. Each upstream dependency available as a dynamic library is -//! registered. The dependencies all propagate, adding to a map. It is -//! possible for a dylib to add a static library as a dependency, but it -//! is illegal for two dylibs to add the same static library as a -//! dependency. The same dylib can be added twice. Additionally, it is -//! illegal to add a static dependency when it was previously found as a -//! dylib (and vice versa) -//! 5. After all dynamic dependencies have been traversed, re-traverse the -//! remaining dependencies and add them statically (if they haven't been -//! added already). +//! 1. If static linking is required, then require all upstream dependencies +//! to be available as rlibs. If not, generate an error. +//! 2. If static linking is requested (generating an executable), then +//! attempt to use all upstream dependencies as rlibs. If any are not +//! found, bail out and continue to step 3. +//! 3. Static linking has failed, at least one library must be dynamically +//! linked. Apply a heuristic by greedily maximizing the number of +//! dynamically linked libraries. +//! 4. Each upstream dependency available as a dynamic library is +//! registered. The dependencies all propagate, adding to a map. It is +//! possible for a dylib to add a static library as a dependency, but it +//! is illegal for two dylibs to add the same static library as a +//! dependency. The same dylib can be added twice. Additionally, it is +//! illegal to add a static dependency when it was previously found as a +//! dylib (and vice versa) +//! 5. After all dynamic dependencies have been traversed, re-traverse the +//! remaining dependencies and add them statically (if they haven't been +//! added already). //! //! While not perfect, this algorithm should help support use-cases such as leaf //! dependencies being static while the larger tree of inner dependencies are @@ -55,11 +55,11 @@ use crate::creader::CStore; use rustc_data_structures::fx::FxHashMap; use rustc_hir::def_id::CrateNum; -use rustc_middle::middle::cstore::CrateDepKind; -use rustc_middle::middle::cstore::LinkagePreference::{self, RequireDynamic, RequireStatic}; use rustc_middle::middle::dependency_format::{Dependencies, DependencyList, Linkage}; use rustc_middle::ty::TyCtxt; use rustc_session::config::CrateType; +use rustc_session::cstore::CrateDepKind; +use rustc_session::cstore::LinkagePreference::{self, RequireDynamic, RequireStatic}; use rustc_target::spec::PanicStrategy; crate fn calculate(tcx: TyCtxt<'_>) -> Dependencies { @@ -277,7 +277,7 @@ fn attempt_static(tcx: TyCtxt<'_>) -> Option { let all_crates_available_as_rlib = tcx .crates(()) .iter() - .cloned() + .copied() .filter_map(|cnum| { if tcx.dep_kind(cnum).macros_only() { return None; @@ -291,10 +291,11 @@ fn attempt_static(tcx: TyCtxt<'_>) -> Option { // All crates are available in an rlib format, so we're just going to link // everything in explicitly so long as it's actually required. - let last_crate = tcx.crates(()).len(); - let mut ret = (1..last_crate + 1) - .map(|cnum| { - if tcx.dep_kind(CrateNum::new(cnum)) == CrateDepKind::Explicit { + let mut ret = tcx + .crates(()) + .iter() + .map(|&cnum| { + if tcx.dep_kind(cnum) == CrateDepKind::Explicit { Linkage::Static } else { Linkage::NotLinked @@ -400,21 +401,35 @@ fn verify_ok(tcx: TyCtxt<'_>, list: &[Linkage]) { continue; } let cnum = CrateNum::new(i + 1); - let found_strategy = tcx.panic_strategy(cnum); - let is_compiler_builtins = tcx.is_compiler_builtins(cnum); - if is_compiler_builtins || desired_strategy == found_strategy { + if tcx.is_compiler_builtins(cnum) { continue; } - sess.err(&format!( - "the crate `{}` is compiled with the \ + let found_strategy = tcx.panic_strategy(cnum); + if desired_strategy != found_strategy { + sess.err(&format!( + "the crate `{}` is compiled with the \ panic strategy `{}` which is \ incompatible with this crate's \ strategy of `{}`", - tcx.crate_name(cnum), - found_strategy.desc(), - desired_strategy.desc() - )); + tcx.crate_name(cnum), + found_strategy.desc(), + desired_strategy.desc() + )); + } + + let found_drop_strategy = tcx.panic_in_drop_strategy(cnum); + if tcx.sess.opts.debugging_opts.panic_in_drop != found_drop_strategy { + sess.err(&format!( + "the crate `{}` is compiled with the \ + panic-in-drop strategy `{}` which is \ + incompatible with this crate's \ + strategy of `{}`", + tcx.crate_name(cnum), + found_drop_strategy.desc(), + tcx.sess.opts.debugging_opts.panic_in_drop.desc() + )); + } } } } diff --git a/compiler/rustc_metadata/src/foreign_modules.rs b/compiler/rustc_metadata/src/foreign_modules.rs index 3d3071c18f..5b42f48a7d 100644 --- a/compiler/rustc_metadata/src/foreign_modules.rs +++ b/compiler/rustc_metadata/src/foreign_modules.rs @@ -1,11 +1,11 @@ use rustc_hir as hir; use rustc_hir::itemlikevisit::ItemLikeVisitor; -use rustc_middle::middle::cstore::ForeignModule; use rustc_middle::ty::TyCtxt; +use rustc_session::cstore::ForeignModule; crate fn collect(tcx: TyCtxt<'_>) -> Vec { let mut collector = Collector { modules: Vec::new() }; - tcx.hir().krate().visit_all_item_likes(&mut collector); + tcx.hir().visit_all_item_likes(&mut collector); collector.modules } diff --git a/compiler/rustc_metadata/src/lib.rs b/compiler/rustc_metadata/src/lib.rs index 2c9bad7e5c..644b849a9f 100644 --- a/compiler/rustc_metadata/src/lib.rs +++ b/compiler/rustc_metadata/src/lib.rs @@ -30,4 +30,4 @@ pub mod creader; pub mod dynamic_lib; pub mod locator; -pub use rmeta::METADATA_HEADER; +pub use rmeta::{encode_metadata, EncodedMetadata, METADATA_HEADER}; diff --git a/compiler/rustc_metadata/src/locator.rs b/compiler/rustc_metadata/src/locator.rs index 8d1bf6f55d..bbd30c9327 100644 --- a/compiler/rustc_metadata/src/locator.rs +++ b/compiler/rustc_metadata/src/locator.rs @@ -221,8 +221,8 @@ use rustc_data_structures::owning_ref::OwningRef; use rustc_data_structures::svh::Svh; use rustc_data_structures::sync::MetadataRef; use rustc_errors::struct_span_err; -use rustc_middle::middle::cstore::{CrateSource, MetadataLoader}; use rustc_session::config::{self, CrateType}; +use rustc_session::cstore::{CrateSource, MetadataLoader}; use rustc_session::filesearch::{FileDoesntMatch, FileMatches, FileSearch}; use rustc_session::search_paths::PathKind; use rustc_session::utils::CanonicalizedPath; @@ -232,6 +232,7 @@ use rustc_span::Span; use rustc_target::spec::{Target, TargetTriple}; use snap::read::FrameDecoder; +use std::fmt::Write as _; use std::io::{Read, Result as IoResult, Write}; use std::path::{Path, PathBuf}; use std::{cmp, fmt, fs}; @@ -240,27 +241,22 @@ use tracing::{debug, info, warn}; #[derive(Clone)] crate struct CrateLocator<'a> { // Immutable per-session configuration. - sess: &'a Session, + only_needs_metadata: bool, + sysroot: &'a Path, metadata_loader: &'a dyn MetadataLoader, // Immutable per-search configuration. crate_name: Symbol, exact_paths: Vec, pub hash: Option, - pub host_hash: Option, extra_filename: Option<&'a str>, pub target: &'a Target, pub triple: TargetTriple, pub filesearch: FileSearch<'a>, - root: Option<&'a CratePaths>, - pub is_proc_macro: Option, + pub is_proc_macro: bool, // Mutable in-progress state or output. - rejected_via_hash: Vec, - rejected_via_triple: Vec, - rejected_via_kind: Vec, - rejected_via_version: Vec, - rejected_via_filename: Vec, + crate_rejections: CrateRejections, } #[derive(Clone)] @@ -298,15 +294,22 @@ impl<'a> CrateLocator<'a> { metadata_loader: &'a dyn MetadataLoader, crate_name: Symbol, hash: Option, - host_hash: Option, extra_filename: Option<&'a str>, is_host: bool, path_kind: PathKind, - root: Option<&'a CratePaths>, - is_proc_macro: Option, ) -> CrateLocator<'a> { + // The all loop is because `--crate-type=rlib --crate-type=rlib` is + // legal and produces both inside this type. + let is_rlib = sess.crate_types().iter().all(|c| *c == CrateType::Rlib); + let needs_object_code = sess.opts.output_types.should_codegen(); + // If we're producing an rlib, then we don't need object code. + // Or, if we're not producing object code, then we don't need it either + // (e.g., if we're a cdylib but emitting just metadata). + let only_needs_metadata = is_rlib || !needs_object_code; + CrateLocator { - sess, + only_needs_metadata, + sysroot: &sess.sysroot, metadata_loader, crate_name, exact_paths: if hash.is_none() { @@ -324,7 +327,6 @@ impl<'a> CrateLocator<'a> { Vec::new() }, hash, - host_hash, extra_filename, target: if is_host { &sess.host } else { &sess.target }, triple: if is_host { @@ -337,22 +339,17 @@ impl<'a> CrateLocator<'a> { } else { sess.target_filesearch(path_kind) }, - root, - is_proc_macro, - rejected_via_hash: Vec::new(), - rejected_via_triple: Vec::new(), - rejected_via_kind: Vec::new(), - rejected_via_version: Vec::new(), - rejected_via_filename: Vec::new(), + is_proc_macro: false, + crate_rejections: CrateRejections::default(), } } crate fn reset(&mut self) { - self.rejected_via_hash.clear(); - self.rejected_via_triple.clear(); - self.rejected_via_kind.clear(); - self.rejected_via_version.clear(); - self.rejected_via_filename.clear(); + self.crate_rejections.via_hash.clear(); + self.crate_rejections.via_triple.clear(); + self.crate_rejections.via_kind.clear(); + self.crate_rejections.via_version.clear(); + self.crate_rejections.via_filename.clear(); } crate fn maybe_load_library_crate(&mut self) -> Result, CrateError> { @@ -435,7 +432,7 @@ impl<'a> CrateLocator<'a> { }; FileMatches }); - self.rejected_via_kind.extend(staticlibs); + self.crate_rejections.via_kind.extend(staticlibs); // We have now collected all known libraries into a set of candidates // keyed of the filename hash listed. For each filename, we also have a @@ -480,18 +477,11 @@ impl<'a> CrateLocator<'a> { } fn needs_crate_flavor(&self, flavor: CrateFlavor) -> bool { - if flavor == CrateFlavor::Dylib && self.is_proc_macro == Some(true) { + if flavor == CrateFlavor::Dylib && self.is_proc_macro { return true; } - // The all loop is because `--crate-type=rlib --crate-type=rlib` is - // legal and produces both inside this type. - let is_rlib = self.sess.crate_types().iter().all(|c| *c == CrateType::Rlib); - let needs_object_code = self.sess.opts.output_types.should_codegen(); - // If we're producing an rlib, then we don't need object code. - // Or, if we're not producing object code, then we don't need it either - // (e.g., if we're a cdylib but emitting just metadata). - if is_rlib || !needs_object_code { + if self.only_needs_metadata { flavor == CrateFlavor::Rmeta } else { // we need all flavors (perhaps not true, but what we do for now) @@ -539,6 +529,15 @@ impl<'a> CrateLocator<'a> { let mut err_data: Option> = None; for (lib, kind) in m { info!("{} reading metadata from: {}", flavor, lib.display()); + if flavor == CrateFlavor::Rmeta && lib.metadata().map_or(false, |m| m.len() == 0) { + // Empty files will cause get_metadata_section to fail. Rmeta + // files can be empty, for example with binaries (which can + // often appear with `cargo check` when checking a library as + // a unittest). We don't want to emit a user-visible warning + // in this case as it is not a real problem. + debug!("skipping empty file"); + continue; + } let (hash, metadata) = match get_metadata_section(self.target, flavor, &lib, self.metadata_loader) { Ok(blob) => { @@ -591,7 +590,7 @@ impl<'a> CrateLocator<'a> { // candidates are all canonicalized, so we canonicalize the sysroot // as well. if let Some((prev, _)) = &ret { - let sysroot = &self.sess.sysroot; + let sysroot = self.sysroot; let sysroot = sysroot.canonicalize().unwrap_or_else(|_| sysroot.to_path_buf()); if prev.starts_with(&sysroot) { continue; @@ -613,21 +612,20 @@ impl<'a> CrateLocator<'a> { let found_version = metadata.get_rustc_version(); if found_version != rustc_version { info!("Rejecting via version: expected {} got {}", rustc_version, found_version); - self.rejected_via_version + self.crate_rejections + .via_version .push(CrateMismatch { path: libpath.to_path_buf(), got: found_version }); return None; } let root = metadata.get_root(); - if let Some(expected_is_proc_macro) = self.is_proc_macro { - let is_proc_macro = root.is_proc_macro_crate(); - if is_proc_macro != expected_is_proc_macro { - info!( - "Rejecting via proc macro: expected {} got {}", - expected_is_proc_macro, is_proc_macro - ); - return None; - } + if root.is_proc_macro_crate() != self.is_proc_macro { + info!( + "Rejecting via proc macro: expected {} got {}", + self.is_proc_macro, + root.is_proc_macro_crate(), + ); + return None; } if self.exact_paths.is_empty() && self.crate_name != root.name() { @@ -637,7 +635,7 @@ impl<'a> CrateLocator<'a> { if root.triple() != &self.triple { info!("Rejecting via crate triple: expected {} got {}", self.triple, root.triple()); - self.rejected_via_triple.push(CrateMismatch { + self.crate_rejections.via_triple.push(CrateMismatch { path: libpath.to_path_buf(), got: root.triple().to_string(), }); @@ -648,7 +646,8 @@ impl<'a> CrateLocator<'a> { if let Some(expected_hash) = self.hash { if hash != expected_hash { info!("Rejecting via hash: expected {} got {}", expected_hash, hash); - self.rejected_via_hash + self.crate_rejections + .via_hash .push(CrateMismatch { path: libpath.to_path_buf(), got: hash.to_string() }); return None; } @@ -702,7 +701,8 @@ impl<'a> CrateLocator<'a> { dylibs.insert(loc_canon, PathKind::ExternFlag); } } else { - self.rejected_via_filename + self.crate_rejections + .via_filename .push(CrateMismatch { path: loc.original().clone(), got: String::new() }); } } @@ -711,18 +711,14 @@ impl<'a> CrateLocator<'a> { Ok(self.extract_lib(rlibs, rmetas, dylibs)?.map(|(_, lib)| lib)) } - crate fn into_error(self) -> CrateError { + crate fn into_error(self, root: Option) -> CrateError { CrateError::LocatorCombined(CombinedLocatorError { crate_name: self.crate_name, - root: self.root.cloned(), + root, triple: self.triple, dll_prefix: self.target.dll_prefix.clone(), dll_suffix: self.target.dll_suffix.clone(), - rejected_via_hash: self.rejected_via_hash, - rejected_via_triple: self.rejected_via_triple, - rejected_via_kind: self.rejected_via_kind, - rejected_via_version: self.rejected_via_version, - rejected_via_filename: self.rejected_via_filename, + crate_rejections: self.crate_rejections, }) } } @@ -754,7 +750,9 @@ fn get_metadata_section( // Header is okay -> inflate the actual metadata let compressed_bytes = &buf[header_len..]; debug!("inflating {} bytes of compressed metadata", compressed_bytes.len()); - let mut inflated = Vec::new(); + // Assume the decompressed data will be at least the size of the compressed data, so we + // don't have to grow the buffer as much. + let mut inflated = Vec::with_capacity(compressed_bytes.len()); match FrameDecoder::new(compressed_bytes).read_to_end(&mut inflated) { Ok(_) => rustc_erase_owner!(OwningRef::new(inflated).map_owner_box()), Err(_) => { @@ -806,12 +804,9 @@ fn find_plugin_registrar_impl<'a>( metadata_loader, name, None, // hash - None, // host_hash None, // extra_filename true, // is_host PathKind::Crate, - None, // root - None, // is_proc_macro ); match locator.maybe_load_library_crate()? { @@ -819,7 +814,7 @@ fn find_plugin_registrar_impl<'a>( Some(dylib) => Ok(dylib.0), None => Err(CrateError::NonDylibPlugin(name)), }, - None => Err(locator.into_error()), + None => Err(locator.into_error(None)), } } @@ -852,6 +847,15 @@ struct CrateMismatch { got: String, } +#[derive(Clone, Default)] +struct CrateRejections { + via_hash: Vec, + via_triple: Vec, + via_kind: Vec, + via_version: Vec, + via_filename: Vec, +} + /// Candidate rejection reasons collected during crate search. /// If no candidate is accepted, then these reasons are presented to the user, /// otherwise they are ignored. @@ -861,11 +865,7 @@ crate struct CombinedLocatorError { triple: TargetTriple, dll_prefix: String, dll_suffix: String, - rejected_via_hash: Vec, - rejected_via_triple: Vec, - rejected_via_kind: Vec, - rejected_via_version: Vec, - rejected_via_filename: Vec, + crate_rejections: CrateRejections, } crate enum CrateError { @@ -920,23 +920,30 @@ impl CrateError { "multiple matching crates for `{}`", crate_name ); + let mut libraries: Vec<_> = libraries.into_values().collect(); + // Make ordering of candidates deterministic. + // This has to `clone()` to work around lifetime restrictions with `sort_by_key()`. + // `sort_by()` could be used instead, but this is in the error path, + // so the performance shouldn't matter. + libraries.sort_by_cached_key(|lib| lib.source.paths().next().unwrap().clone()); let candidates = libraries .iter() - .filter_map(|(_, lib)| { + .map(|lib| { let crate_name = &lib.metadata.get_root().name().as_str(); - match (&lib.source.dylib, &lib.source.rlib) { - (Some((pd, _)), Some((pr, _))) => Some(format!( - "\ncrate `{}`: {}\n{:>padding$}", - crate_name, - pd.display(), - pr.display(), - padding = 8 + crate_name.len() - )), - (Some((p, _)), None) | (None, Some((p, _))) => { - Some(format!("\ncrate `{}`: {}", crate_name, p.display())) - } - (None, None) => None, + let mut paths = lib.source.paths(); + + // This `unwrap()` should be okay because there has to be at least one + // source file. `CrateSource`'s docs confirm that too. + let mut s = format!( + "\ncrate `{}`: {}", + crate_name, + paths.next().unwrap().display() + ); + let padding = 8 + crate_name.len(); + for path in paths { + write!(s, "\n{:>padding$}", path.display(), padding = padding).unwrap(); } + s }) .collect::(); err.note(&format!("candidates:{}", candidates)); @@ -974,7 +981,7 @@ impl CrateError { Some(r) => format!(" which `{}` depends on", r.name), }; let mut msg = "the following crate versions were found:".to_string(); - let mut err = if !locator.rejected_via_hash.is_empty() { + let mut err = if !locator.crate_rejections.via_hash.is_empty() { let mut err = struct_span_err!( sess, span, @@ -984,7 +991,7 @@ impl CrateError { add, ); err.note("perhaps that crate needs to be recompiled?"); - let mismatches = locator.rejected_via_hash.iter(); + let mismatches = locator.crate_rejections.via_hash.iter(); for CrateMismatch { path, .. } in mismatches { msg.push_str(&format!("\ncrate `{}`: {}", crate_name, path.display())); } @@ -995,7 +1002,7 @@ impl CrateError { } err.note(&msg); err - } else if !locator.rejected_via_triple.is_empty() { + } else if !locator.crate_rejections.via_triple.is_empty() { let mut err = struct_span_err!( sess, span, @@ -1005,7 +1012,7 @@ impl CrateError { locator.triple, add, ); - let mismatches = locator.rejected_via_triple.iter(); + let mismatches = locator.crate_rejections.via_triple.iter(); for CrateMismatch { path, got } in mismatches { msg.push_str(&format!( "\ncrate `{}`, target triple {}: {}", @@ -1016,7 +1023,7 @@ impl CrateError { } err.note(&msg); err - } else if !locator.rejected_via_kind.is_empty() { + } else if !locator.crate_rejections.via_kind.is_empty() { let mut err = struct_span_err!( sess, span, @@ -1026,13 +1033,13 @@ impl CrateError { add, ); err.help("please recompile that crate using --crate-type lib"); - let mismatches = locator.rejected_via_kind.iter(); + let mismatches = locator.crate_rejections.via_kind.iter(); for CrateMismatch { path, .. } in mismatches { msg.push_str(&format!("\ncrate `{}`: {}", crate_name, path.display())); } err.note(&msg); err - } else if !locator.rejected_via_version.is_empty() { + } else if !locator.crate_rejections.via_version.is_empty() { let mut err = struct_span_err!( sess, span, @@ -1042,10 +1049,11 @@ impl CrateError { add, ); err.help(&format!( - "please recompile that crate using this compiler ({})", + "please recompile that crate using this compiler ({}) \ + (consider running `cargo clean` first)", rustc_version(), )); - let mismatches = locator.rejected_via_version.iter(); + let mismatches = locator.crate_rejections.via_version.iter(); for CrateMismatch { path, got } in mismatches { msg.push_str(&format!( "\ncrate `{}` compiled by {}: {}", @@ -1107,13 +1115,18 @@ impl CrateError { == Symbol::intern(&sess.opts.debugging_opts.profiler_runtime) { err.note(&"the compiler may have been built without the profiler runtime"); + } else if crate_name.as_str().starts_with("rustc_") { + err.help( + "maybe you need to install the missing components with: \ + `rustup component add rust-src rustc-dev llvm-tools-preview`", + ); } err.span_label(span, "can't find crate"); err }; - if !locator.rejected_via_filename.is_empty() { - let mismatches = locator.rejected_via_filename.iter(); + if !locator.crate_rejections.via_filename.is_empty() { + let mismatches = locator.crate_rejections.via_filename.iter(); for CrateMismatch { path, .. } in mismatches { err.note(&format!( "extern location for {} is of an unknown type: {}", diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs index 5f0d8c46f2..2431b819a3 100644 --- a/compiler/rustc_metadata/src/native_libs.rs +++ b/compiler/rustc_metadata/src/native_libs.rs @@ -3,8 +3,8 @@ use rustc_data_structures::fx::FxHashSet; use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_hir::itemlikevisit::ItemLikeVisitor; -use rustc_middle::middle::cstore::{DllCallingConvention, DllImport, NativeLib}; use rustc_middle::ty::{List, ParamEnv, ParamEnvAnd, Ty, TyCtxt}; +use rustc_session::cstore::{DllCallingConvention, DllImport, NativeLib}; use rustc_session::parse::feature_err; use rustc_session::utils::NativeLibKind; use rustc_session::Session; @@ -14,7 +14,7 @@ use rustc_target::spec::abi::Abi; crate fn collect(tcx: TyCtxt<'_>) -> Vec { let mut collector = Collector { tcx, libs: Vec::new() }; - tcx.hir().krate().visit_all_item_likes(&mut collector); + tcx.hir().visit_all_item_likes(&mut collector); collector.process_command_line(); collector.libs } @@ -319,13 +319,13 @@ impl Collector<'tcx> { self.tcx.sess.err(&format!( "renaming of the library `{}` was specified, \ however this crate contains no `#[link(...)]` \ - attributes referencing this library.", + attributes referencing this library", lib.name )); } else if !renames.insert(&lib.name) { self.tcx.sess.err(&format!( "multiple renamings were \ - specified for library `{}` .", + specified for library `{}`", lib.name )); } @@ -363,7 +363,7 @@ impl Collector<'tcx> { .collect::>(); if existing.is_empty() { // Add if not found - let new_name = passed_lib.new_name.as_ref().map(|s| &**s); // &Option -> Option<&str> + let new_name: Option<&str> = passed_lib.new_name.as_deref(); let lib = NativeLib { name: Some(Symbol::intern(new_name.unwrap_or(&passed_lib.name))), kind: passed_lib.kind, @@ -382,7 +382,7 @@ impl Collector<'tcx> { } } - fn i686_arg_list_size(&self, item: &hir::ForeignItemRef<'_>) -> usize { + fn i686_arg_list_size(&self, item: &hir::ForeignItemRef) -> usize { let argument_types: &List> = self.tcx.erase_late_bound_regions( self.tcx .type_of(item.id.def_id) @@ -406,7 +406,7 @@ impl Collector<'tcx> { .sum() } - fn build_dll_import(&self, abi: Abi, item: &hir::ForeignItemRef<'_>) -> DllImport { + fn build_dll_import(&self, abi: Abi, item: &hir::ForeignItemRef) -> DllImport { let calling_convention = if self.tcx.sess.target.arch == "x86" { match abi { Abi::C { .. } | Abi::Cdecl => DllCallingConvention::C, @@ -433,6 +433,12 @@ impl Collector<'tcx> { } } }; - DllImport { name: item.ident.name, ordinal: None, calling_convention, span: item.span } + + DllImport { + name: item.ident.name, + ordinal: self.tcx.codegen_fn_attrs(item.id.def_id).link_ordinal, + calling_convention, + span: item.span, + } } } diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index dd44e0cb1f..89bb5797a8 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -18,17 +18,20 @@ use rustc_hir as hir; use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res}; use rustc_hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE}; use rustc_hir::definitions::{DefKey, DefPath, DefPathData, DefPathHash}; +use rustc_hir::diagnostic_items::DiagnosticItems; use rustc_hir::lang_items; use rustc_index::vec::{Idx, IndexVec}; use rustc_middle::hir::exports::Export; -use rustc_middle::middle::cstore::{CrateSource, ExternCrate}; -use rustc_middle::middle::cstore::{ForeignModule, LinkagePreference, NativeLib}; use rustc_middle::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel}; use rustc_middle::mir::interpret::{AllocDecodingSession, AllocDecodingState}; use rustc_middle::mir::{self, Body, Promoted}; +use rustc_middle::thir; use rustc_middle::ty::codec::TyDecoder; use rustc_middle::ty::{self, Ty, TyCtxt, Visibility}; use rustc_serialize::{opaque, Decodable, Decoder}; +use rustc_session::cstore::{ + CrateSource, ExternCrate, ForeignModule, LinkagePreference, NativeLib, +}; use rustc_session::Session; use rustc_span::hygiene::{ExpnIndex, MacroKind}; use rustc_span::source_map::{respan, Spanned}; @@ -47,7 +50,26 @@ use rustc_span::hygiene::HygieneDecodeContext; mod cstore_impl; -crate struct MetadataBlob(MetadataRef); +/// A reference to the raw binary version of crate metadata. +/// A `MetadataBlob` internally is just a reference counted pointer to +/// the actual data, so cloning it is cheap. +#[derive(Clone)] +crate struct MetadataBlob(Lrc); + +// This is needed so we can create an OwningRef into the blob. +// The data behind a `MetadataBlob` has a stable address because it is +// contained within an Rc/Arc. +unsafe impl rustc_data_structures::owning_ref::StableAddress for MetadataBlob {} + +// This is needed so we can create an OwningRef into the blob. +impl std::ops::Deref for MetadataBlob { + type Target = [u8]; + + #[inline] + fn deref(&self) -> &[u8] { + &self.0[..] + } +} // A map from external crate numbers (as decoded from some crate file) to // local crate numbers (as generated during this session). Each external @@ -75,10 +97,8 @@ crate struct CrateMetadata { raw_proc_macros: Option<&'static [ProcMacro]>, /// Source maps for code from the crate. source_map_import_info: OnceCell>, - /// For every definition in this crate, maps its `DefPathHash` to its - /// `DefIndex`. See `raw_def_id_to_def_id` for more details about how - /// this is used. - def_path_hash_map: OnceCell>, + /// For every definition in this crate, maps its `DefPathHash` to its `DefIndex`. + def_path_hash_map: DefPathHashMapRef<'static>, /// Likewise for ExpnHash. expn_hash_map: OnceCell>, /// Used for decoding interpret::AllocIds in a cached & thread-safe manner. @@ -133,6 +153,7 @@ struct ImportedSourceFile { pub(super) struct DecodeContext<'a, 'tcx> { opaque: opaque::Decoder<'a>, cdata: Option>, + blob: &'a MetadataBlob, sess: Option<&'tcx Session>, tcx: Option>, @@ -147,7 +168,8 @@ pub(super) struct DecodeContext<'a, 'tcx> { /// Abstract over the various ways one can create metadata decoders. pub(super) trait Metadata<'a, 'tcx>: Copy { - fn raw_bytes(self) -> &'a [u8]; + fn blob(self) -> &'a MetadataBlob; + fn cdata(self) -> Option> { None } @@ -161,8 +183,9 @@ pub(super) trait Metadata<'a, 'tcx>: Copy { fn decoder(self, pos: usize) -> DecodeContext<'a, 'tcx> { let tcx = self.tcx(); DecodeContext { - opaque: opaque::Decoder::new(self.raw_bytes(), pos), + opaque: opaque::Decoder::new(self.blob(), pos), cdata: self.cdata(), + blob: self.blob(), sess: self.sess().or(tcx.map(|tcx| tcx.sess)), tcx, last_source_file_index: 0, @@ -175,17 +198,19 @@ pub(super) trait Metadata<'a, 'tcx>: Copy { } impl<'a, 'tcx> Metadata<'a, 'tcx> for &'a MetadataBlob { - fn raw_bytes(self) -> &'a [u8] { - &self.0 + #[inline] + fn blob(self) -> &'a MetadataBlob { + self } } impl<'a, 'tcx> Metadata<'a, 'tcx> for (&'a MetadataBlob, &'tcx Session) { - fn raw_bytes(self) -> &'a [u8] { - let (blob, _) = self; - &blob.0 + #[inline] + fn blob(self) -> &'a MetadataBlob { + self.0 } + #[inline] fn sess(self) -> Option<&'tcx Session> { let (_, sess) = self; Some(sess) @@ -193,33 +218,41 @@ impl<'a, 'tcx> Metadata<'a, 'tcx> for (&'a MetadataBlob, &'tcx Session) { } impl<'a, 'tcx> Metadata<'a, 'tcx> for &'a CrateMetadataRef<'a> { - fn raw_bytes(self) -> &'a [u8] { - self.blob.raw_bytes() + #[inline] + fn blob(self) -> &'a MetadataBlob { + &self.blob } + #[inline] fn cdata(self) -> Option> { Some(*self) } } impl<'a, 'tcx> Metadata<'a, 'tcx> for (&'a CrateMetadataRef<'a>, &'tcx Session) { - fn raw_bytes(self) -> &'a [u8] { - self.0.raw_bytes() + #[inline] + fn blob(self) -> &'a MetadataBlob { + &self.0.blob } + #[inline] fn cdata(self) -> Option> { Some(*self.0) } + #[inline] fn sess(self) -> Option<&'tcx Session> { Some(&self.1) } } impl<'a, 'tcx> Metadata<'a, 'tcx> for (&'a CrateMetadataRef<'a>, TyCtxt<'tcx>) { - fn raw_bytes(self) -> &'a [u8] { - self.0.raw_bytes() + #[inline] + fn blob(self) -> &'a MetadataBlob { + &self.0.blob } + #[inline] fn cdata(self) -> Option> { Some(*self.0) } + #[inline] fn tcx(self) -> Option> { Some(self.1) } @@ -245,12 +278,21 @@ impl<'a: 'x, 'tcx: 'x, 'x, T: Decodable>> Lazy<[T]> { } impl<'a, 'tcx> DecodeContext<'a, 'tcx> { + #[inline] fn tcx(&self) -> TyCtxt<'tcx> { - self.tcx.expect("missing TyCtxt in DecodeContext") + debug_assert!(self.tcx.is_some(), "missing TyCtxt in DecodeContext"); + self.tcx.unwrap() } - fn cdata(&self) -> CrateMetadataRef<'a> { - self.cdata.expect("missing CrateMetadata in DecodeContext") + #[inline] + pub fn blob(&self) -> &'a MetadataBlob { + self.blob + } + + #[inline] + pub fn cdata(&self) -> CrateMetadataRef<'a> { + debug_assert!(self.cdata.is_some(), "missing CrateMetadata in DecodeContext"); + self.cdata.unwrap() } fn map_encoded_cnum_to_current(&self, cnum: CrateNum) -> CrateNum { @@ -275,6 +317,11 @@ impl<'a, 'tcx> DecodeContext<'a, 'tcx> { self.lazy_state = LazyState::Previous(NonZeroUsize::new(position + min_size).unwrap()); Ok(Lazy::from_position_and_meta(NonZeroUsize::new(position).unwrap(), meta)) } + + #[inline] + pub fn read_raw_bytes(&mut self, len: usize) -> &'a [u8] { + self.opaque.read_raw_bytes(len) + } } impl<'a, 'tcx> TyDecoder<'tcx> for DecodeContext<'a, 'tcx> { @@ -536,11 +583,12 @@ impl<'a, 'tcx> Decodable> for Span { let hi = (hi + source_file.translated_source_file.start_pos) - source_file.original_start_pos; - Ok(Span::new(lo, hi, ctxt)) + // Do not try to decode parent for foreign spans. + Ok(Span::new(lo, hi, ctxt, None)) } } -impl<'a, 'tcx> Decodable> for &'tcx [mir::abstract_const::Node<'tcx>] { +impl<'a, 'tcx> Decodable> for &'tcx [thir::abstract_const::Node<'tcx>] { fn decode(d: &mut DecodeContext<'a, 'tcx>) -> Result { ty::codec::RefDecodable::decode(d) } @@ -584,11 +632,11 @@ implement_ty_decoder!(DecodeContext<'a, 'tcx>); impl MetadataBlob { crate fn new(metadata_ref: MetadataRef) -> MetadataBlob { - MetadataBlob(metadata_ref) + MetadataBlob(Lrc::new(metadata_ref)) } crate fn is_compatible(&self) -> bool { - self.raw_bytes().starts_with(METADATA_HEADER) + self.blob().starts_with(METADATA_HEADER) } crate fn get_rustc_version(&self) -> String { @@ -597,7 +645,7 @@ impl MetadataBlob { } crate fn get_root(&self) -> CrateRoot<'tcx> { - let slice = self.raw_bytes(); + let slice = &self.blob()[..]; let offset = METADATA_HEADER.len(); let pos = (((slice[offset + 0] as u32) << 24) | ((slice[offset + 1] as u32) << 16) @@ -1005,24 +1053,28 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { } /// Iterates over the diagnostic items in the given crate. - fn get_diagnostic_items(&self) -> FxHashMap { + fn get_diagnostic_items(&self) -> DiagnosticItems { if self.root.is_proc_macro_crate() { // Proc macro crates do not export any diagnostic-items to the target. Default::default() } else { - self.root + let mut id_to_name = FxHashMap::default(); + let name_to_id = self + .root .diagnostic_items .decode(self) - .map(|(name, def_index)| (name, self.local_def_id(def_index))) - .collect() + .map(|(name, def_index)| { + let id = self.local_def_id(def_index); + id_to_name.insert(id, name); + (name, id) + }) + .collect(); + DiagnosticItems { id_to_name, name_to_id } } } /// Iterates over each child of the given item. - fn each_child_of_item(&self, id: DefIndex, mut callback: F, sess: &Session) - where - F: FnMut(Export), - { + fn each_child_of_item(&self, id: DefIndex, mut callback: impl FnMut(Export), sess: &Session) { if let Some(data) = &self.root.proc_macro_data { /* If we are loading as a proc macro, we want to return the view of this crate * as a proc macro crate. @@ -1198,14 +1250,14 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { .decode((self, tcx)) } - fn get_mir_abstract_const( + fn get_thir_abstract_const( &self, tcx: TyCtxt<'tcx>, id: DefIndex, - ) -> Result]>, ErrorReported> { + ) -> Result]>, ErrorReported> { self.root .tables - .mir_abstract_consts + .thir_abstract_consts .get(self, id) .map_or(Ok(None), |v| Ok(Some(v.decode((self, tcx))))) } @@ -1553,58 +1605,6 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { .or_insert_with(|| self.root.tables.def_keys.get(self, index).unwrap().decode(self)) } - /// Finds the corresponding `DefId` for the provided `DefPathHash`, if it exists. - /// This is used by incremental compilation to map a serialized `DefPathHash` to - /// its `DefId` in the current session. - /// Normally, only one 'main' crate will change between incremental compilation sessions: - /// all dependencies will be completely unchanged. In this case, we can avoid - /// decoding every `DefPathHash` in the crate, since the `DefIndex` from the previous - /// session will still be valid. If our 'guess' is wrong (the `DefIndex` no longer exists, - /// or has a different `DefPathHash`, then we need to decode all `DefPathHashes` to determine - /// the correct mapping). - fn def_path_hash_to_def_id( - &self, - krate: CrateNum, - index_guess: u32, - hash: DefPathHash, - ) -> Option { - let def_index_guess = DefIndex::from_u32(index_guess); - let old_hash = self - .root - .tables - .def_path_hashes - .get(self, def_index_guess) - .map(|lazy| lazy.decode(self)); - - // Fast path: the definition and its index is unchanged from the - // previous compilation session. There is no need to decode anything - // else - if old_hash == Some(hash) { - return Some(DefId { krate, index: def_index_guess }); - } - - let is_proc_macro = self.is_proc_macro_crate(); - - // Slow path: We need to find out the new `DefIndex` of the provided - // `DefPathHash`, if its still exists. This requires decoding every `DefPathHash` - // stored in this crate. - let map = self.cdata.def_path_hash_map.get_or_init(|| { - let end_id = self.root.tables.def_path_hashes.size() as u32; - let mut map = UnhashMap::with_capacity_and_hasher(end_id as usize, Default::default()); - for i in 0..end_id { - let def_index = DefIndex::from_u32(i); - // There may be gaps in the encoded table if we're decoding a proc-macro crate - if let Some(hash) = self.root.tables.def_path_hashes.get(self, def_index) { - map.insert(hash.decode(self), def_index); - } else if !is_proc_macro { - panic!("Missing def_path_hashes entry for {:?}", def_index); - } - } - map - }); - map.get(&hash).map(|index| DefId { krate, index: *index }) - } - // Returns the path leading to the thing with this `id`. fn def_path(&self, id: DefIndex) -> DefPath { debug!("def_path(cnum={:?}, id={:?})", self.cnum, id); @@ -1627,7 +1627,12 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { self.def_path_hash_unlocked(index, &mut def_path_hashes) } - fn expn_hash_to_expn_id(&self, index_guess: u32, hash: ExpnHash) -> ExpnId { + #[inline] + fn def_path_hash_to_def_index(&self, hash: DefPathHash) -> DefIndex { + self.def_path_hash_map.def_path_hash_to_def_index(&hash) + } + + fn expn_hash_to_expn_id(&self, sess: &Session, index_guess: u32, hash: ExpnHash) -> ExpnId { debug_assert_eq!(ExpnId::from_hash(hash), None); let index_guess = ExpnIndex::from_u32(index_guess); let old_hash = self.root.expn_hashes.get(self, index_guess).map(|lazy| lazy.decode(self)); @@ -1649,8 +1654,6 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { let i = ExpnIndex::from_u32(i); if let Some(hash) = self.root.expn_hashes.get(self, i) { map.insert(hash.decode(self), i); - } else { - panic!("Missing expn_hash entry for {:?}", i); } } map @@ -1658,7 +1661,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { map[&hash] }; - let data = self.root.expn_data.get(self, index).unwrap().decode(self); + let data = self.root.expn_data.get(self, index).unwrap().decode((self, sess)); rustc_span::hygiene::register_expn_id(self.cnum, index, data, hash) } @@ -1893,13 +1896,18 @@ impl CrateMetadata { let alloc_decoding_state = AllocDecodingState::new(root.interpret_alloc_index.decode(&blob).collect()); let dependencies = Lock::new(cnum_map.iter().cloned().collect()); + + // Pre-decode the DefPathHash->DefIndex table. This is a cheap operation + // that does not copy any data. It just does some data verification. + let def_path_hash_map = root.def_path_hash_map.decode(&blob); + CrateMetadata { blob, root, trait_impls, raw_proc_macros, source_map_import_info: OnceCell::new(), - def_path_hash_map: Default::default(), + def_path_hash_map, expn_hash_map: Default::default(), alloc_decoding_state, cnum, diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index 41839c5802..e12f049a90 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -1,21 +1,18 @@ use crate::creader::{CStore, LoadedMacro}; use crate::foreign_modules; use crate::native_libs; -use crate::rmeta::encoder; use rustc_ast as ast; use rustc_data_structures::stable_map::FxHashMap; -use rustc_hir as hir; use rustc_hir::def::{CtorKind, DefKind}; use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, CRATE_DEF_INDEX, LOCAL_CRATE}; use rustc_hir::definitions::{DefKey, DefPath, DefPathHash}; use rustc_middle::hir::exports::Export; -use rustc_middle::middle::cstore::ForeignModule; -use rustc_middle::middle::cstore::{CrateSource, CrateStore, EncodedMetadata}; use rustc_middle::middle::exported_symbols::ExportedSymbol; use rustc_middle::middle::stability::DeprecationEntry; use rustc_middle::ty::query::Providers; use rustc_middle::ty::{self, TyCtxt, Visibility}; +use rustc_session::cstore::{CrateSource, CrateStore, ForeignModule}; use rustc_session::utils::NativeLibKind; use rustc_session::{Session, StableCrateId}; use rustc_span::hygiene::{ExpnHash, ExpnId}; @@ -86,6 +83,12 @@ impl IntoArgs for (CrateNum, DefId) { } } +impl IntoArgs for ty::InstanceDef<'tcx> { + fn into_args(self) -> (DefId, DefId) { + (self.def_id(), self.def_id()) + } +} + provide! { <'tcx> tcx, def_id, other, cdata, type_of => { cdata.get_type(def_id.index, tcx) } generics_of => { cdata.get_generics(def_id.index, tcx.sess) } @@ -117,7 +120,7 @@ provide! { <'tcx> tcx, def_id, other, cdata, optimized_mir => { tcx.arena.alloc(cdata.get_optimized_mir(tcx, def_id.index)) } mir_for_ctfe => { tcx.arena.alloc(cdata.get_mir_for_ctfe(tcx, def_id.index)) } promoted_mir => { tcx.arena.alloc(cdata.get_promoted_mir(tcx, def_id.index)) } - mir_abstract_const => { cdata.get_mir_abstract_const(tcx, def_id.index) } + thir_abstract_const => { cdata.get_thir_abstract_const(tcx, def_id.index) } unused_generic_params => { cdata.get_unused_generic_params(def_id.index) } const_param_default => { tcx.mk_const(cdata.get_const_param_default(tcx, def_id.index)) } mir_const_qualif => { cdata.mir_const_qualif(def_id.index) } @@ -160,6 +163,7 @@ provide! { <'tcx> tcx, def_id, other, cdata, has_panic_handler => { cdata.root.has_panic_handler } is_profiler_runtime => { cdata.root.profiler_runtime } panic_strategy => { cdata.root.panic_strategy } + panic_in_drop_strategy => { cdata.root.panic_in_drop_strategy } extern_crate => { let r = *cdata.extern_crate.lock(); r.map(|c| &*tcx.arena.alloc(c)) @@ -304,17 +308,7 @@ pub fn provide(providers: &mut Providers) { // traversal, but not globally minimal across all crates. let bfs_queue = &mut VecDeque::new(); - // Preferring shortest paths alone does not guarantee a - // deterministic result; so sort by crate num to avoid - // hashtable iteration non-determinism. This only makes - // things as deterministic as crate-nums assignment is, - // which is to say, its not deterministic in general. But - // we believe that libstd is consistently assigned crate - // num 1, so it should be enough to resolve #46112. - let mut crates: Vec = (*tcx.crates(())).to_owned(); - crates.sort(); - - for &cnum in crates.iter() { + for &cnum in tcx.crates(()) { // Ignore crates without a corresponding local `extern crate` item. if tcx.missing_extern_crate_item(cnum) { continue; @@ -323,37 +317,32 @@ pub fn provide(providers: &mut Providers) { bfs_queue.push_back(DefId { krate: cnum, index: CRATE_DEF_INDEX }); } - // (restrict scope of mutable-borrow of `visible_parent_map`) - { - let visible_parent_map = &mut visible_parent_map; - let mut add_child = - |bfs_queue: &mut VecDeque<_>, child: &Export, parent: DefId| { - if child.vis != ty::Visibility::Public { - return; - } + let mut add_child = |bfs_queue: &mut VecDeque<_>, child: &Export, parent: DefId| { + if child.vis != ty::Visibility::Public { + return; + } - if let Some(child) = child.res.opt_def_id() { - match visible_parent_map.entry(child) { - Entry::Occupied(mut entry) => { - // If `child` is defined in crate `cnum`, ensure - // that it is mapped to a parent in `cnum`. - if child.is_local() && entry.get().is_local() { - entry.insert(parent); - } - } - Entry::Vacant(entry) => { - entry.insert(parent); - bfs_queue.push_back(child); - } + if let Some(child) = child.res.opt_def_id() { + match visible_parent_map.entry(child) { + Entry::Occupied(mut entry) => { + // If `child` is defined in crate `cnum`, ensure + // that it is mapped to a parent in `cnum`. + if child.is_local() && entry.get().is_local() { + entry.insert(parent); } } - }; - - while let Some(def) = bfs_queue.pop_front() { - for child in tcx.item_children(def).iter() { - add_child(bfs_queue, child, def); + Entry::Vacant(entry) => { + entry.insert(parent); + bfs_queue.push_back(child); + } } } + }; + + while let Some(def) = bfs_queue.pop_front() { + for child in tcx.item_children(def).iter() { + add_child(bfs_queue, child, def); + } } visible_parent_map @@ -393,11 +382,7 @@ impl CStore { self.get_crate_data(def.krate).get_visibility(def.index) } - pub fn item_children_untracked( - &self, - def_id: DefId, - sess: &Session, - ) -> Vec> { + pub fn item_children_untracked(&self, def_id: DefId, sess: &Session) -> Vec { let mut result = vec![]; self.get_crate_data(def_id.krate).each_child_of_item( def_id.index, @@ -503,6 +488,10 @@ impl CrateStore for CStore { self.get_crate_data(cnum).root.stable_crate_id } + fn stable_crate_id_to_crate_num(&self, stable_crate_id: StableCrateId) -> CrateNum { + self.stable_crate_ids[&stable_crate_id] + } + /// Returns the `DefKey` for a given `DefId`. This indicates the /// parent `DefId` as well as some idea of what kind of data the /// `DefId` refers to. @@ -518,21 +507,18 @@ impl CrateStore for CStore { self.get_crate_data(def.krate).def_path_hash(def.index) } - // See `CrateMetadataRef::def_path_hash_to_def_id` for more details - fn def_path_hash_to_def_id( + fn def_path_hash_to_def_id(&self, cnum: CrateNum, hash: DefPathHash) -> DefId { + let def_index = self.get_crate_data(cnum).def_path_hash_to_def_index(hash); + DefId { krate: cnum, index: def_index } + } + + fn expn_hash_to_expn_id( &self, + sess: &Session, cnum: CrateNum, index_guess: u32, - hash: DefPathHash, - ) -> Option { - self.get_crate_data(cnum).def_path_hash_to_def_id(cnum, index_guess, hash) - } - - fn expn_hash_to_expn_id(&self, cnum: CrateNum, index_guess: u32, hash: ExpnHash) -> ExpnId { - self.get_crate_data(cnum).expn_hash_to_expn_id(index_guess, hash) - } - - fn encode_metadata(&self, tcx: TyCtxt<'_>) -> EncodedMetadata { - encoder::encode_metadata(tcx) + hash: ExpnHash, + ) -> ExpnId { + self.get_crate_data(cnum).expn_hash_to_expn_id(sess, index_guess, hash) } } diff --git a/compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs b/compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs new file mode 100644 index 0000000000..d6435bb649 --- /dev/null +++ b/compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs @@ -0,0 +1,58 @@ +use crate::rmeta::DecodeContext; +use crate::rmeta::EncodeContext; +use crate::rmeta::MetadataBlob; +use rustc_data_structures::owning_ref::OwningRef; +use rustc_hir::def_path_hash_map::{Config as HashMapConfig, DefPathHashMap}; +use rustc_serialize::{opaque, Decodable, Decoder, Encodable, Encoder}; +use rustc_span::def_id::{DefIndex, DefPathHash}; + +crate enum DefPathHashMapRef<'tcx> { + OwnedFromMetadata(odht::HashTable>), + BorrowedFromTcx(&'tcx DefPathHashMap), +} + +impl DefPathHashMapRef<'tcx> { + #[inline] + pub fn def_path_hash_to_def_index(&self, def_path_hash: &DefPathHash) -> DefIndex { + match *self { + DefPathHashMapRef::OwnedFromMetadata(ref map) => map.get(def_path_hash).unwrap(), + DefPathHashMapRef::BorrowedFromTcx(_) => { + panic!("DefPathHashMap::BorrowedFromTcx variant only exists for serialization") + } + } + } +} + +impl<'a, 'tcx> Encodable> for DefPathHashMapRef<'tcx> { + fn encode(&self, e: &mut EncodeContext<'a, 'tcx>) -> opaque::EncodeResult { + match *self { + DefPathHashMapRef::BorrowedFromTcx(def_path_hash_map) => { + let bytes = def_path_hash_map.raw_bytes(); + e.emit_usize(bytes.len())?; + e.emit_raw_bytes(bytes) + } + DefPathHashMapRef::OwnedFromMetadata(_) => { + panic!("DefPathHashMap::OwnedFromMetadata variant only exists for deserialization") + } + } + } +} + +impl<'a, 'tcx> Decodable> for DefPathHashMapRef<'static> { + fn decode(d: &mut DecodeContext<'a, 'tcx>) -> Result, String> { + // Import TyDecoder so we can access the DecodeContext::position() method + use crate::rustc_middle::ty::codec::TyDecoder; + + let len = d.read_usize()?; + let pos = d.position(); + let o = OwningRef::new(d.blob().clone()).map(|x| &x[pos..pos + len]); + + // Although we already have the data we need via the OwningRef, we still need + // to advance the DecodeContext's position so it's in a valid state after + // the method. We use read_raw_bytes() for that. + let _ = d.read_raw_bytes(len); + + let inner = odht::HashTable::from_raw_bytes(o).map_err(|e| format!("{}", e))?; + Ok(DefPathHashMapRef::OwnedFromMetadata(inner)) + } +} diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index d8b9a47997..20f7b059b5 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1,3 +1,4 @@ +use crate::rmeta::def_path_hash_map::DefPathHashMapRef; use crate::rmeta::table::{FixedSizeEncoding, TableBuilder}; use crate::rmeta::*; @@ -17,17 +18,18 @@ use rustc_hir::{AnonConst, GenericParamKind}; use rustc_index::bit_set::GrowableBitSet; use rustc_index::vec::Idx; use rustc_middle::hir::map::Map; -use rustc_middle::middle::cstore::{EncodedMetadata, ForeignModule, LinkagePreference, NativeLib}; use rustc_middle::middle::dependency_format::Linkage; use rustc_middle::middle::exported_symbols::{ metadata_symbol_name, ExportedSymbol, SymbolExportLevel, }; use rustc_middle::mir::interpret; +use rustc_middle::thir; use rustc_middle::traits::specialization_graph; use rustc_middle::ty::codec::TyEncoder; use rustc_middle::ty::{self, SymbolName, Ty, TyCtxt}; use rustc_serialize::{opaque, Encodable, Encoder}; use rustc_session::config::CrateType; +use rustc_session::cstore::{ForeignModule, LinkagePreference, NativeLib}; use rustc_span::symbol::{sym, Ident, Symbol}; use rustc_span::{self, ExternalSource, FileName, SourceFile, Span, SyntaxContext}; use rustc_span::{ @@ -344,7 +346,7 @@ impl<'a, 'tcx> TyEncoder<'tcx> for EncodeContext<'a, 'tcx> { } } -impl<'a, 'tcx> Encodable> for &'tcx [mir::abstract_const::Node<'tcx>] { +impl<'a, 'tcx> Encodable> for &'tcx [thir::abstract_const::Node<'tcx>] { fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) -> opaque::EncodeResult { (**self).encode(s) } @@ -438,8 +440,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } fn encode_info_for_items(&mut self) { - let krate = self.tcx.hir().krate(); - self.encode_info_for_mod(CRATE_DEF_ID, krate.module()); + self.encode_info_for_mod(CRATE_DEF_ID, self.tcx.hir().root_module()); // Proc-macro crates only export proc-macro items, which are looked // up using `proc_macro_data` @@ -447,7 +448,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { return; } - krate.visit_all_item_likes(&mut self.as_deep_visitor()); + self.tcx.hir().visit_all_item_likes(&mut self.as_deep_visitor()); } fn encode_def_path_table(&mut self) { @@ -471,6 +472,12 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } } + fn encode_def_path_hash_map(&mut self) -> Lazy> { + self.lazy(DefPathHashMapRef::BorrowedFromTcx( + self.tcx.resolutions(()).definitions.def_path_hash_to_def_index_map(), + )) + } + fn encode_source_map(&mut self) -> Lazy<[rustc_span::SourceFile]> { let source_map = self.tcx.sess.source_map(); let all_source_files = source_map.files(); @@ -674,6 +681,10 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let (syntax_contexts, expn_data, expn_hashes) = self.encode_hygiene(); let hygiene_bytes = self.position() - i; + i = self.position(); + let def_path_hash_map = self.encode_def_path_hash_map(); + let def_path_hash_map_bytes = self.position() - i; + // Encode source_map. This needs to be done last, // since encoding `Span`s tells us which `SourceFiles` we actually // need to encode. @@ -691,6 +702,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { hash: tcx.crate_hash(LOCAL_CRATE), stable_crate_id: tcx.def_path_hash(LOCAL_CRATE.as_def_id()).stable_crate_id(), panic_strategy: tcx.sess.panic_strategy(), + panic_in_drop_strategy: tcx.sess.opts.debugging_opts.panic_in_drop, edition: tcx.sess.edition(), has_global_allocator: tcx.has_global_allocator(LOCAL_CRATE), has_panic_handler: tcx.has_panic_handler(LOCAL_CRATE), @@ -720,6 +732,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { syntax_contexts, expn_data, expn_hashes, + def_path_hash_map, }); let total_bytes = self.position(); @@ -742,6 +755,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { eprintln!(" impl bytes: {}", impl_bytes); eprintln!(" exp. symbols bytes: {}", exported_symbols_bytes); eprintln!(" def-path table bytes: {}", def_path_table_bytes); + eprintln!(" def-path hashes bytes: {}", def_path_hash_map_bytes); eprintln!(" proc-macro-data-bytes: {}", proc_macro_data_bytes); eprintln!(" mir bytes: {}", mir_bytes); eprintln!(" item bytes: {}", item_bytes); @@ -1065,14 +1079,7 @@ impl EncodeContext<'a, 'tcx> { // items - we encode information about proc-macros later on. let reexports = if !self.is_proc_macro { match tcx.module_exports(local_def_id) { - Some(exports) => { - let hir = self.tcx.hir(); - self.lazy( - exports - .iter() - .map(|export| export.map_id(|id| hir.local_def_id_to_hir_id(id))), - ) - } + Some(exports) => self.lazy(exports), _ => Lazy::empty(), } } else { @@ -1304,14 +1311,17 @@ impl EncodeContext<'a, 'tcx> { if encode_const { record!(self.tables.mir_for_ctfe[def_id.to_def_id()] <- self.tcx.mir_for_ctfe(def_id)); - let abstract_const = self.tcx.mir_abstract_const(def_id); + // FIXME(generic_const_exprs): this feels wrong to have in `encode_mir` + let abstract_const = self.tcx.thir_abstract_const(def_id); if let Ok(Some(abstract_const)) = abstract_const { - record!(self.tables.mir_abstract_consts[def_id.to_def_id()] <- abstract_const); + record!(self.tables.thir_abstract_consts[def_id.to_def_id()] <- abstract_const); } } record!(self.tables.promoted_mir[def_id.to_def_id()] <- self.tcx.promoted_mir(def_id)); - let unused = self.tcx.unused_generic_params(def_id); + let instance = + ty::InstanceDef::Item(ty::WithOptConstParam::unknown(def_id.to_def_id())); + let unused = self.tcx.unused_generic_params(instance); if !unused.is_empty() { record!(self.tables.unused_generic_params[def_id.to_def_id()] <- unused); } @@ -1699,9 +1709,10 @@ impl EncodeContext<'a, 'tcx> { fn encode_crate_deps(&mut self) -> Lazy<[CrateDep]> { empty_proc_macro!(self); - let crates = self.tcx.crates(()); - let mut deps = crates + let deps = self + .tcx + .crates(()) .iter() .map(|&cnum| { let dep = CrateDep { @@ -1715,8 +1726,6 @@ impl EncodeContext<'a, 'tcx> { }) .collect::>(); - deps.sort_by_key(|&(cnum, _)| cnum); - { // Sanity-check the crate numbers let mut expected_cnum = 1; @@ -1743,7 +1752,7 @@ impl EncodeContext<'a, 'tcx> { fn encode_diagnostic_items(&mut self) -> Lazy<[(Symbol, DefIndex)]> { empty_proc_macro!(self); let tcx = self.tcx; - let diagnostic_items = tcx.diagnostic_items(LOCAL_CRATE); + let diagnostic_items = &tcx.diagnostic_items(LOCAL_CRATE).name_to_id; self.lazy(diagnostic_items.iter().map(|(&name, def_id)| (name, def_id.index))) } @@ -1774,7 +1783,7 @@ impl EncodeContext<'a, 'tcx> { debug!("EncodeContext::encode_impls()"); let tcx = self.tcx; let mut visitor = ImplVisitor { tcx, impls: FxHashMap::default() }; - tcx.hir().krate().visit_all_item_likes(&mut visitor); + tcx.hir().visit_all_item_likes(&mut visitor); let mut all_impls: Vec<_> = visitor.impls.into_iter().collect(); @@ -2093,7 +2102,26 @@ fn prefetch_mir(tcx: TyCtxt<'_>) { // will allow us to slice the metadata to the precise length that we just // generated regardless of trailing bytes that end up in it. -pub(super) fn encode_metadata(tcx: TyCtxt<'_>) -> EncodedMetadata { +#[derive(Encodable, Decodable)] +pub struct EncodedMetadata { + raw_data: Vec, +} + +impl EncodedMetadata { + #[inline] + pub fn new() -> EncodedMetadata { + EncodedMetadata { raw_data: Vec::new() } + } + + #[inline] + pub fn raw_data(&self) -> &[u8] { + &self.raw_data[..] + } +} + +pub fn encode_metadata(tcx: TyCtxt<'_>) -> EncodedMetadata { + let _prof_timer = tcx.prof.verbose_generic_activity("generate_crate_metadata"); + // Since encoding metadata is not in a query, and nothing is cached, // there's no need to do dep-graph tracking for any of it. tcx.dep_graph.assert_ignored(); diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index a487753f46..42855e9d9d 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -1,4 +1,5 @@ use decoder::Metadata; +use def_path_hash_map::DefPathHashMapRef; use table::{Table, TableBuilder}; use rustc_ast::{self as ast, MacroDef}; @@ -12,12 +13,13 @@ use rustc_hir::definitions::DefKey; use rustc_hir::lang_items; use rustc_index::{bit_set::FiniteBitSet, vec::IndexVec}; use rustc_middle::hir::exports::Export; -use rustc_middle::middle::cstore::{CrateDepKind, ForeignModule, LinkagePreference, NativeLib}; use rustc_middle::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel}; use rustc_middle::mir; +use rustc_middle::thir; use rustc_middle::ty::{self, ReprOptions, Ty}; use rustc_serialize::opaque::Encoder; use rustc_session::config::SymbolManglingVersion; +use rustc_session::cstore::{CrateDepKind, ForeignModule, LinkagePreference, NativeLib}; use rustc_span::edition::Edition; use rustc_span::hygiene::{ExpnIndex, MacroKind}; use rustc_span::symbol::{Ident, Symbol}; @@ -31,9 +33,11 @@ use decoder::DecodeContext; pub use decoder::{provide, provide_extern}; crate use decoder::{CrateMetadata, CrateNumMap, MetadataBlob}; use encoder::EncodeContext; +pub use encoder::{encode_metadata, EncodedMetadata}; use rustc_span::hygiene::SyntaxContextData; mod decoder; +mod def_path_hash_map; mod encoder; mod table; @@ -204,6 +208,7 @@ crate struct CrateRoot<'tcx> { hash: Svh, stable_crate_id: StableCrateId, panic_strategy: PanicStrategy, + panic_in_drop_strategy: PanicStrategy, edition: Edition, has_global_allocator: bool, has_panic_handler: bool, @@ -229,6 +234,8 @@ crate struct CrateRoot<'tcx> { expn_data: ExpnDataTable, expn_hashes: ExpnHashTable, + def_path_hash_map: Lazy>, + source_map: Lazy<[rustc_span::SourceFile]>, compiler_builtins: bool, @@ -305,7 +312,7 @@ define_tables! { mir: Table)>, mir_for_ctfe: Table)>, promoted_mir: Table>)>, - mir_abstract_consts: Table])>, + thir_abstract_consts: Table])>, const_defaults: Table>>, unused_generic_params: Table>>, // `def_keys` and `def_path_hashes` represent a lazy version of a @@ -359,7 +366,7 @@ struct RenderedConst(String); #[derive(MetadataEncodable, MetadataDecodable)] struct ModData { - reexports: Lazy<[Export]>, + reexports: Lazy<[Export]>, expansion: ExpnId, } diff --git a/compiler/rustc_metadata/src/rmeta/table.rs b/compiler/rustc_metadata/src/rmeta/table.rs index 62c0ce1584..4dfefda490 100644 --- a/compiler/rustc_metadata/src/rmeta/table.rs +++ b/compiler/rustc_metadata/src/rmeta/table.rs @@ -199,7 +199,7 @@ where debug!("Table::lookup: index={:?} len={:?}", i, self.meta); let start = self.position.get(); - let bytes = &metadata.raw_bytes()[start..start + self.meta]; + let bytes = &metadata.blob()[start..start + self.meta]; >::maybe_read_from_bytes_at(bytes, i.index())? } diff --git a/compiler/rustc_middle/Cargo.toml b/compiler/rustc_middle/Cargo.toml index 2403ce2d24..d06c593d39 100644 --- a/compiler/rustc_middle/Cargo.toml +++ b/compiler/rustc_middle/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustc_middle" version = "0.0.0" -edition = "2018" +edition = "2021" [lib] doctest = false @@ -9,6 +9,8 @@ doctest = false [dependencies] rustc_arena = { path = "../rustc_arena" } bitflags = "1.2.1" +either = "1.5.0" +gsgdt = "0.1.2" tracing = "0.1" rustc-rayon-core = "0.3.1" polonius-engine = "0.13.0" @@ -21,6 +23,7 @@ rustc_macros = { path = "../rustc_macros" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_query_system = { path = "../rustc_query_system" } rustc_errors = { path = "../rustc_errors" } +rustc_graphviz = { path = "../rustc_graphviz" } rustc_index = { path = "../rustc_index" } rustc_serialize = { path = "../rustc_serialize" } rustc_ast = { path = "../rustc_ast" } @@ -29,3 +32,5 @@ chalk-ir = "0.55.0" smallvec = { version = "1.6.1", features = ["union", "may_dangle"] } rustc_session = { path = "../rustc_session" } rustc_type_ir = { path = "../rustc_type_ir" } +rand = "0.8.4" +rand_xoshiro = "0.6.0" diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs index 59db2c6636..962aea448b 100644 --- a/compiler/rustc_middle/src/arena.rs +++ b/compiler/rustc_middle/src/arena.rs @@ -11,7 +11,8 @@ macro_rules! arena_types { ($macro:path, $tcx:lifetime) => ( $macro!([ - [] layouts: rustc_target::abi::Layout, + [] layout: rustc_target::abi::Layout, + [] 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>, @@ -78,8 +79,8 @@ macro_rules! arena_types { >, [few] all_traits: Vec, [few] privacy_access_levels: rustc_middle::middle::privacy::AccessLevels, - [few] foreign_module: rustc_middle::middle::cstore::ForeignModule, - [few] foreign_modules: Vec, + [few] foreign_module: rustc_session::cstore::ForeignModule, + [few] 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>, diff --git a/compiler/rustc_middle/src/dep_graph/dep_node.rs b/compiler/rustc_middle/src/dep_graph/dep_node.rs index 8476929eae..23d475a595 100644 --- a/compiler/rustc_middle/src/dep_graph/dep_node.rs +++ b/compiler/rustc_middle/src/dep_graph/dep_node.rs @@ -63,6 +63,7 @@ use rustc_data_structures::fingerprint::Fingerprint; use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, CRATE_DEF_INDEX}; use rustc_hir::definitions::DefPathHash; use rustc_hir::HirId; +use rustc_query_system::dep_graph::FingerprintStyle; use rustc_span::symbol::Symbol; use std::hash::Hash; @@ -89,9 +90,9 @@ pub struct DepKindStruct { /// 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::can_reconstruct_query_key + // FIXME: Make this a simple boolean once DepNodeParams::fingerprint_style // can be made a specialized associated const. - can_reconstruct_query_key: fn() -> bool, + fingerprint_style: fn() -> FingerprintStyle, } impl std::ops::Deref for DepKind { @@ -103,14 +104,14 @@ impl std::ops::Deref for DepKind { impl DepKind { #[inline(always)] - pub fn can_reconstruct_query_key(&self) -> bool { + pub fn fingerprint_style(&self) -> FingerprintStyle { // Only fetch the DepKindStruct once. let data: &DepKindStruct = &**self; if data.is_anon { - return false; + return FingerprintStyle::Opaque; } - (data.can_reconstruct_query_key)() + (data.fingerprint_style)() } } @@ -140,17 +141,18 @@ macro_rules! is_eval_always_attr { } macro_rules! contains_anon_attr { - ($($attr:ident $(($($attr_args:tt)*))* ),*) => ({$(is_anon_attr!($attr) | )* false}); + ($(($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}); + ($(($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 { @@ -158,7 +160,7 @@ pub mod dep_kind { is_anon: false, is_eval_always: false, - can_reconstruct_query_key: || true, + fingerprint_style: || FingerprintStyle::Unit, }; pub const TraitSelect: DepKindStruct = DepKindStruct { @@ -166,7 +168,7 @@ pub mod dep_kind { is_anon: true, is_eval_always: false, - can_reconstruct_query_key: || true, + fingerprint_style: || FingerprintStyle::Unit, }; pub const CompileCodegenUnit: DepKindStruct = DepKindStruct { @@ -174,7 +176,7 @@ pub mod dep_kind { is_anon: false, is_eval_always: false, - can_reconstruct_query_key: || false, + fingerprint_style: || FingerprintStyle::Opaque, }; pub const CompileMonoItem: DepKindStruct = DepKindStruct { @@ -182,7 +184,7 @@ pub mod dep_kind { is_anon: false, is_eval_always: false, - can_reconstruct_query_key: || false, + fingerprint_style: || FingerprintStyle::Opaque, }; macro_rules! define_query_dep_kinds { @@ -196,16 +198,16 @@ pub mod dep_kind { const is_eval_always: bool = contains_eval_always_attr!($($attrs)*); #[inline(always)] - fn can_reconstruct_query_key() -> bool { + fn fingerprint_style() -> rustc_query_system::dep_graph::FingerprintStyle { as DepNodeParams>> - ::can_reconstruct_query_key() + ::fingerprint_style() } DepKindStruct { has_params, is_anon, is_eval_always, - can_reconstruct_query_key, + fingerprint_style, } };)* ); @@ -320,7 +322,7 @@ impl DepNodeExt for DepNode { /// 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.can_reconstruct_query_key() && kind.has_params); + debug_assert!(kind.fingerprint_style() == FingerprintStyle::DefPathHash); DepNode { kind, hash: def_path_hash.0.into() } } @@ -335,8 +337,12 @@ 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.can_reconstruct_query_key() { - tcx.on_disk_cache.as_ref()?.def_path_hash_to_def_id(tcx, DefPathHash(self.hash.into())) + 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())), + ) } else { None } @@ -346,14 +352,16 @@ impl DepNodeExt for DepNode { fn from_label_string(label: &str, def_path_hash: DefPathHash) -> Result { let kind = dep_kind_from_label_string(label)?; - if !kind.can_reconstruct_query_key() { - return Err(()); - } - - if kind.has_params { - Ok(DepNode::from_def_path_hash(def_path_hash, kind)) - } else { - Ok(DepNode::new_no_params(kind)) + match kind.fingerprint_style() { + FingerprintStyle::Opaque => Err(()), + FingerprintStyle::Unit => { + if !kind.has_params { + Ok(DepNode::new_no_params(kind)) + } else { + Err(()) + } + } + FingerprintStyle::DefPathHash => Ok(DepNode::from_def_path_hash(def_path_hash, kind)), } } @@ -365,8 +373,8 @@ impl DepNodeExt for DepNode { impl<'tcx> DepNodeParams> for () { #[inline(always)] - fn can_reconstruct_query_key() -> bool { - true + fn fingerprint_style() -> FingerprintStyle { + FingerprintStyle::Unit } fn to_fingerprint(&self, _: TyCtxt<'tcx>) -> Fingerprint { @@ -380,22 +388,12 @@ impl<'tcx> DepNodeParams> for () { impl<'tcx> DepNodeParams> for DefId { #[inline(always)] - fn can_reconstruct_query_key() -> bool { - true + fn fingerprint_style() -> FingerprintStyle { + FingerprintStyle::DefPathHash } fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint { - let hash = tcx.def_path_hash(*self); - // If this is a foreign `DefId`, store its current value - // in the incremental cache. When we decode the cache, - // we will use the old DefIndex as an initial guess for - // a lookup into the crate metadata. - if !self.is_local() { - if let Some(cache) = &tcx.on_disk_cache { - cache.store_foreign_def_id_hash(*self, hash); - } - } - hash.0 + tcx.def_path_hash(*self).0 } fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String { @@ -409,8 +407,8 @@ impl<'tcx> DepNodeParams> for DefId { impl<'tcx> DepNodeParams> for LocalDefId { #[inline(always)] - fn can_reconstruct_query_key() -> bool { - true + fn fingerprint_style() -> FingerprintStyle { + FingerprintStyle::DefPathHash } fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint { @@ -428,8 +426,8 @@ impl<'tcx> DepNodeParams> for LocalDefId { impl<'tcx> DepNodeParams> for CrateNum { #[inline(always)] - fn can_reconstruct_query_key() -> bool { - true + fn fingerprint_style() -> FingerprintStyle { + FingerprintStyle::DefPathHash } fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint { @@ -448,8 +446,8 @@ impl<'tcx> DepNodeParams> for CrateNum { impl<'tcx> DepNodeParams> for (DefId, DefId) { #[inline(always)] - fn can_reconstruct_query_key() -> bool { - false + fn fingerprint_style() -> FingerprintStyle { + FingerprintStyle::Opaque } // We actually would not need to specialize the implementation of this @@ -473,8 +471,8 @@ impl<'tcx> DepNodeParams> for (DefId, DefId) { impl<'tcx> DepNodeParams> for HirId { #[inline(always)] - fn can_reconstruct_query_key() -> bool { - false + fn fingerprint_style() -> FingerprintStyle { + FingerprintStyle::Opaque } // We actually would not need to specialize the implementation of this diff --git a/compiler/rustc_middle/src/dep_graph/mod.rs b/compiler/rustc_middle/src/dep_graph/mod.rs index aa61219ad7..cda9963907 100644 --- a/compiler/rustc_middle/src/dep_graph/mod.rs +++ b/compiler/rustc_middle/src/dep_graph/mod.rs @@ -1,7 +1,7 @@ -use crate::ich::StableHashingContext; use crate::ty::{self, TyCtxt}; use rustc_data_structures::profiling::SelfProfilerRef; use rustc_data_structures::sync::Lock; +use rustc_query_system::ich::StableHashingContext; use rustc_session::Session; #[macro_use] @@ -25,8 +25,8 @@ impl rustc_query_system::dep_graph::DepKind for DepKind { const NULL: Self = DepKind::Null; #[inline(always)] - fn can_reconstruct_query_key(&self) -> bool { - DepKind::can_reconstruct_query_key(self) + fn fingerprint_style(&self) -> rustc_query_system::dep_graph::FingerprintStyle { + DepKind::fingerprint_style(self) } #[inline(always)] @@ -90,15 +90,9 @@ impl rustc_query_system::dep_graph::DepKind for DepKind { impl<'tcx> DepContext for TyCtxt<'tcx> { type DepKind = DepKind; - type StableHashingContext = StableHashingContext<'tcx>; - fn register_reused_dep_node(&self, dep_node: &DepNode) { - if let Some(cache) = self.on_disk_cache.as_ref() { - cache.register_reused_dep_node(*self, dep_node) - } - } - - fn create_stable_hashing_context(&self) -> Self::StableHashingContext { + #[inline] + fn create_stable_hashing_context(&self) -> StableHashingContext<'_> { TyCtxt::create_stable_hashing_context(*self) } diff --git a/compiler/rustc_middle/src/hir/exports.rs b/compiler/rustc_middle/src/hir/exports.rs index be9e38aca6..f37b976fba 100644 --- a/compiler/rustc_middle/src/hir/exports.rs +++ b/compiler/rustc_middle/src/hir/exports.rs @@ -11,23 +11,18 @@ use std::fmt::Debug; /// This is the replacement export map. It maps a module to all of the exports /// within. -pub type ExportMap = FxHashMap>>; +pub type ExportMap = FxHashMap>; #[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, HashStable)] -pub struct Export { +pub struct Export { /// The name of the target. pub ident: Ident, /// The resolution of the target. - pub res: Res, + /// Local variables cannot be exported, so this `Res` doesn't need the ID parameter. + pub res: Res, /// The span of the target. pub span: Span, /// The visibility of the export. /// We include non-`pub` exports for hygienic macros that get used from extern crates. pub vis: ty::Visibility, } - -impl Export { - pub fn map_id(self, map: impl FnMut(Id) -> R) -> Export { - Export { ident: self.ident, res: self.res.map_id(map), span: self.span, vis: self.vis } - } -} diff --git a/compiler/rustc_middle/src/hir/map/collector.rs b/compiler/rustc_middle/src/hir/map/collector.rs index 1351b4950f..efebf73224 100644 --- a/compiler/rustc_middle/src/hir/map/collector.rs +++ b/compiler/rustc_middle/src/hir/map/collector.rs @@ -1,7 +1,6 @@ use crate::arena::Arena; use crate::hir::map::Map; use crate::hir::{IndexedHir, OwnerNodes, ParentedNode}; -use crate::ich::StableHashingContext; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; @@ -12,6 +11,7 @@ use rustc_hir::definitions; use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc_hir::*; use rustc_index::vec::{Idx, IndexVec}; +use rustc_query_system::ich::StableHashingContext; use rustc_session::Session; use rustc_span::source_map::SourceMap; use rustc_span::{Span, DUMMY_SP}; @@ -62,13 +62,6 @@ fn hash_body( stable_hasher.finish() } -/// Represents an entry and its parent `HirId`. -#[derive(Copy, Clone, Debug)] -pub struct Entry<'hir> { - parent: HirId, - node: Node<'hir>, -} - impl<'a, 'hir> NodeCollector<'a, 'hir> { pub(super) fn root( sess: &'a Session, @@ -420,18 +413,18 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { self.visit_nested_trait_item(id); } - fn visit_impl_item_ref(&mut self, ii: &'hir ImplItemRef<'hir>) { + fn visit_impl_item_ref(&mut self, ii: &'hir ImplItemRef) { // Do not visit the duplicate information in ImplItemRef. We want to // map the actual nodes, not the duplicate ones in the *Ref. - let ImplItemRef { id, ident: _, kind: _, span: _, vis: _, defaultness: _ } = *ii; + let ImplItemRef { id, ident: _, kind: _, span: _, defaultness: _ } = *ii; self.visit_nested_impl_item(id); } - fn visit_foreign_item_ref(&mut self, fi: &'hir ForeignItemRef<'hir>) { + fn visit_foreign_item_ref(&mut self, fi: &'hir ForeignItemRef) { // Do not visit the duplicate information in ForeignItemRef. We want to // map the actual nodes, not the duplicate ones in the *Ref. - let ForeignItemRef { id, ident: _, span: _, vis: _ } = *fi; + let ForeignItemRef { id, ident: _, span: _ } = *fi; self.visit_nested_foreign_item(id); } diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index 62d0374fb5..e6f56b0be9 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -1,15 +1,16 @@ use self::collector::NodeCollector; -use crate::hir::{AttributeMap, IndexedHir, Owner}; +use crate::hir::{AttributeMap, IndexedHir, ModuleItems, Owner}; use crate::ty::TyCtxt; use rustc_ast as ast; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::svh::Svh; +use rustc_data_structures::sync::{par_for_each_in, Send, Sync}; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE}; +use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, CRATE_DEF_ID, LOCAL_CRATE}; use rustc_hir::definitions::{DefKey, DefPath, DefPathHash}; -use rustc_hir::intravisit; +use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::itemlikevisit::ItemLikeVisitor; use rustc_hir::*; use rustc_index::vec::Idx; @@ -19,6 +20,7 @@ use rustc_span::source_map::Spanned; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::Span; use rustc_target::spec::abi::Abi; +use std::collections::VecDeque; pub mod blocks; mod collector; @@ -82,12 +84,12 @@ pub struct Map<'hir> { /// An iterator that walks up the ancestor tree of a given `HirId`. /// Constructed using `tcx.hir().parent_iter(hir_id)`. -pub struct ParentHirIterator<'map, 'hir> { +pub struct ParentHirIterator<'hir> { current_id: HirId, - map: &'map Map<'hir>, + map: Map<'hir>, } -impl<'hir> Iterator for ParentHirIterator<'_, 'hir> { +impl<'hir> Iterator for ParentHirIterator<'hir> { type Item = (HirId, Node<'hir>); fn next(&mut self) -> Option { @@ -114,12 +116,12 @@ impl<'hir> Iterator for ParentHirIterator<'_, 'hir> { /// An iterator that walks up the ancestor tree of a given `HirId`. /// Constructed using `tcx.hir().parent_owner_iter(hir_id)`. -pub struct ParentOwnerIterator<'map, 'hir> { +pub struct ParentOwnerIterator<'hir> { current_id: HirId, - map: &'map Map<'hir>, + map: Map<'hir>, } -impl<'hir> Iterator for ParentOwnerIterator<'_, 'hir> { +impl<'hir> Iterator for ParentOwnerIterator<'hir> { type Item = (HirId, OwnerNode<'hir>); fn next(&mut self) -> Option { @@ -155,6 +157,21 @@ impl<'hir> Map<'hir> { self.tcx.hir_crate(()) } + pub fn root_module(&self) -> &'hir Mod<'hir> { + match self.tcx.hir_owner(CRATE_DEF_ID).map(|o| o.node) { + Some(OwnerNode::Crate(item)) => item, + _ => bug!(), + } + } + + 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), + _ => None, + }) + } + pub fn def_key(&self, def_id: LocalDefId) -> DefKey { // Accessing the DefKey is ok, since it is part of DefPathHash. self.tcx.untracked_resolutions.definitions.def_key(def_id) @@ -206,11 +223,6 @@ impl<'hir> Map<'hir> { } pub fn opt_def_kind(&self, local_def_id: LocalDefId) -> Option { - // FIXME(eddyb) support `find` on the crate root. - if local_def_id.to_def_id().index == CRATE_DEF_INDEX { - return Some(DefKind::Mod); - } - let hir_id = self.local_def_id_to_hir_id(local_def_id); let def_kind = match self.find(hir_id)? { Node::Item(item) => match item.kind { @@ -479,6 +491,17 @@ impl<'hir> Map<'hir> { Some(ccx) } + /// Returns an iterator of the `DefId`s for all body-owners in this + /// 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)) + } + + 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))); + } + pub fn ty_param_owner(&self, id: HirId) -> HirId { match self.get(id) { Node::Item(&Item { kind: ItemKind::Trait(..) | ItemKind::TraitAlias(..), .. }) => id, @@ -519,38 +542,125 @@ impl<'hir> Map<'hir> { } } + /// Walks the contents of a crate. See also `Crate::visit_all_items`. + pub fn walk_toplevel_module(self, visitor: &mut impl Visitor<'hir>) { + let (top_mod, span, hir_id) = self.get_module(CRATE_DEF_ID); + visitor.visit_mod(top_mod, span, hir_id); + } + + /// 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) + } + } + } + + /// Visits all items in the crate in some deterministic (but + /// unspecified) order. If you just need to process every item, + /// but don't care about nesting, this method is the best choice. + /// + /// If you do care about nesting -- usually because your algorithm + /// follows lexical scoping rules -- then you want a different + /// approach. You should override `visit_nested_item` in your + /// visitor and then call `intravisit::walk_crate` instead. + pub fn visit_all_item_likes(&self, visitor: &mut V) + where + V: itemlikevisit::ItemLikeVisitor<'hir>, + { + let krate = self.krate(); + for owner in krate.owners.iter().filter_map(Option::as_ref) { + match owner { + OwnerNode::Item(item) => visitor.visit_item(item), + OwnerNode::ForeignItem(item) => visitor.visit_foreign_item(item), + OwnerNode::ImplItem(item) => visitor.visit_impl_item(item), + OwnerNode::TraitItem(item) => visitor.visit_trait_item(item), + OwnerNode::Crate(_) => {} + } + } + } + + /// A parallel version of `visit_all_item_likes`. + pub fn par_visit_all_item_likes(&self, visitor: &V) + where + V: itemlikevisit::ParItemLikeVisitor<'hir> + Sync + Send, + { + let krate = self.krate(); + par_for_each_in(&krate.owners.raw, |owner| match owner.as_ref() { + 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), + Some(OwnerNode::TraitItem(item)) => visitor.visit_trait_item(item), + Some(OwnerNode::Crate(_)) | None => {} + }) + } + pub fn visit_item_likes_in_module(&self, module: LocalDefId, visitor: &mut V) where V: ItemLikeVisitor<'hir>, { let module = self.tcx.hir_module_items(module); - for id in &module.items { + for id in module.items.iter() { visitor.visit_item(self.item(*id)); } - for id in &module.trait_items { + for id in module.trait_items.iter() { visitor.visit_trait_item(self.trait_item(*id)); } - for id in &module.impl_items { + for id in module.impl_items.iter() { visitor.visit_impl_item(self.impl_item(*id)); } - for id in &module.foreign_items { + for id in module.foreign_items.iter() { visitor.visit_foreign_item(self.foreign_item(*id)); } } + pub fn for_each_module(&self, f: impl Fn(LocalDefId)) { + let mut queue = VecDeque::new(); + queue.push_back(CRATE_DEF_ID); + + while let Some(id) = queue.pop_front() { + f(id); + let items = self.tcx.hir_module_items(id); + queue.extend(items.submodules.iter().copied()) + } + } + + #[cfg(not(parallel_compiler))] + #[inline] + pub fn par_for_each_module(&self, f: impl Fn(LocalDefId)) { + self.for_each_module(f) + } + + #[cfg(parallel_compiler)] + pub fn par_for_each_module(&self, f: impl Fn(LocalDefId) + Sync) { + use rustc_data_structures::sync::{par_iter, ParallelIterator}; + par_iter_submodules(self.tcx, CRATE_DEF_ID, &f); + + fn par_iter_submodules(tcx: TyCtxt<'_>, module: LocalDefId, f: &F) + where + F: Fn(LocalDefId) + Sync, + { + (*f)(module); + let items = tcx.hir_module_items(module); + par_iter(&items.submodules[..]).for_each(|&sm| par_iter_submodules(tcx, sm, f)); + } + } + /// Returns an iterator for the nodes in the ancestor tree of the `current_id` /// until the crate root is reached. Prefer this over your own loop using `get_parent_node`. - pub fn parent_iter(&self, current_id: HirId) -> ParentHirIterator<'_, 'hir> { + pub fn parent_iter(self, current_id: HirId) -> ParentHirIterator<'hir> { ParentHirIterator { current_id, map: self } } /// Returns an iterator for the nodes in the ancestor tree of the `current_id` /// until the crate root is reached. Prefer this over your own loop using `get_parent_node`. - pub fn parent_owner_iter(&self, current_id: HirId) -> ParentOwnerIterator<'_, 'hir> { + pub fn parent_owner_iter(self, current_id: HirId) -> ParentOwnerIterator<'hir> { ParentOwnerIterator { current_id, map: self } } @@ -934,7 +1044,8 @@ pub(super) fn index_hir<'tcx>(tcx: TyCtxt<'tcx>, (): ()) -> &'tcx IndexedHir<'tc &tcx.untracked_resolutions.definitions, hcx, ); - intravisit::walk_crate(&mut collector, tcx.untracked_crate); + 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) @@ -952,22 +1063,12 @@ pub(super) fn crate_hash(tcx: TyCtxt<'_>, crate_num: CrateNum) -> Svh { .iter_enumerated() .filter_map(|(def_id, hod)| { let def_path_hash = tcx.untracked_resolutions.definitions.def_path_hash(def_id); - let mut hasher = StableHasher::new(); - hod.as_ref()?.hash_stable(&mut hcx, &mut hasher); - AttributeMap { map: &tcx.untracked_crate.attrs, prefix: def_id } - .hash_stable(&mut hcx, &mut hasher); - Some((def_path_hash, hasher.finish())) + let hash = hod.as_ref()?.hash; + Some((def_path_hash, hash, def_id)) }) .collect(); hir_body_nodes.sort_unstable_by_key(|bn| bn.0); - let node_hashes = hir_body_nodes.iter().fold( - Fingerprint::ZERO, - |combined_fingerprint, &(def_path_hash, fingerprint)| { - combined_fingerprint.combine(def_path_hash.0.combine(fingerprint)) - }, - ); - let upstream_crates = upstream_crates(tcx); // We hash the final, remapped names of all local source files so we @@ -987,7 +1088,17 @@ pub(super) fn crate_hash(tcx: TyCtxt<'_>, crate_num: CrateNum) -> Svh { source_file_names.sort_unstable(); let mut stable_hasher = StableHasher::new(); - node_hashes.hash_stable(&mut hcx, &mut stable_hasher); + 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); + } + } upstream_crates.hash_stable(&mut hcx, &mut stable_hasher); source_file_names.hash_stable(&mut hcx, &mut stable_hasher); tcx.sess.opts.dep_tracking_hash(true).hash_stable(&mut hcx, &mut stable_hasher); @@ -1101,3 +1212,69 @@ fn hir_id_to_string(map: &Map<'_>, id: HirId) -> String { None => format!("unknown node{}", id_str), } } + +pub(super) fn hir_module_items(tcx: TyCtxt<'_>, module_id: LocalDefId) -> ModuleItems { + let mut collector = ModuleCollector { + tcx, + submodules: Vec::default(), + items: Vec::default(), + trait_items: Vec::default(), + impl_items: Vec::default(), + foreign_items: Vec::default(), + }; + + let (hir_mod, span, hir_id) = tcx.hir().get_module(module_id); + collector.visit_mod(hir_mod, span, hir_id); + + let ModuleCollector { submodules, items, trait_items, impl_items, foreign_items, .. } = + collector; + return ModuleItems { + submodules: submodules.into_boxed_slice(), + items: items.into_boxed_slice(), + trait_items: trait_items.into_boxed_slice(), + impl_items: impl_items.into_boxed_slice(), + foreign_items: foreign_items.into_boxed_slice(), + }; + + struct ModuleCollector<'tcx> { + tcx: TyCtxt<'tcx>, + submodules: Vec, + items: Vec, + trait_items: Vec, + impl_items: Vec, + foreign_items: Vec, + } + + impl<'hir> Visitor<'hir> for ModuleCollector<'hir> { + type Map = Map<'hir>; + + fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap { + intravisit::NestedVisitorMap::All(self.tcx.hir()) + } + + fn visit_item(&mut self, item: &'hir Item<'hir>) { + self.items.push(item.item_id()); + if let ItemKind::Mod(..) = item.kind { + // If this declares another module, do not recurse inside it. + self.submodules.push(item.def_id); + } else { + intravisit::walk_item(self, item) + } + } + + fn visit_trait_item(&mut self, item: &'hir TraitItem<'hir>) { + self.trait_items.push(item.trait_item_id()); + intravisit::walk_trait_item(self, item) + } + + fn visit_impl_item(&mut self, item: &'hir ImplItem<'hir>) { + self.impl_items.push(item.impl_item_id()); + intravisit::walk_impl_item(self, item) + } + + fn visit_foreign_item(&mut self, item: &'hir ForeignItem<'hir>) { + self.foreign_items.push(item.foreign_item_id()); + intravisit::walk_foreign_item(self, item) + } + } +} diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs index 34aee4f1b3..5016c5ce95 100644 --- a/compiler/rustc_middle/src/hir/mod.rs +++ b/compiler/rustc_middle/src/hir/mod.rs @@ -6,7 +6,6 @@ pub mod exports; pub mod map; pub mod place; -use crate::ich::StableHashingContext; use crate::ty::query::Providers; use crate::ty::TyCtxt; use rustc_ast::Attribute; @@ -16,6 +15,7 @@ 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; @@ -121,6 +121,17 @@ impl<'tcx> AttributeMap<'tcx> { } } +/// Gather the LocalDefId for each item-like within a module, including items contained within +/// bodies. The Ids are in visitor order. This is used to partition a pass between modules. +#[derive(Debug, HashStable)] +pub struct ModuleItems { + submodules: Box<[LocalDefId]>, + items: Box<[ItemId]>, + trait_items: Box<[TraitItemId]>, + impl_items: Box<[ImplItemId]>, + foreign_items: Box<[ForeignItemId]>, +} + impl<'tcx> TyCtxt<'tcx> { #[inline(always)] pub fn hir(self) -> map::Map<'tcx> { @@ -140,7 +151,7 @@ pub fn provide(providers: &mut Providers) { providers.hir_crate = |tcx, ()| tcx.untracked_crate; providers.index_hir = map::index_hir; providers.crate_hash = map::crate_hash; - providers.hir_module_items = |tcx, id| &tcx.untracked_crate.modules[&id]; + 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; @@ -153,6 +164,7 @@ pub fn provide(providers: &mut Providers) { index.parenting.get(&id).copied().unwrap_or(CRATE_HIR_ID) }; providers.hir_attrs = |tcx, id| AttributeMap { map: &tcx.untracked_crate.attrs, prefix: id }; + 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| { let hir = tcx.hir(); diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs index 573fa913d6..e41f5add45 100644 --- a/compiler/rustc_middle/src/lib.rs +++ b/compiler/rustc_middle/src/lib.rs @@ -8,7 +8,7 @@ //! - **MIR.** The "mid-level (M) intermediate representation (IR)" is //! defined in the `mir` module. This module contains only the //! *definition* of the MIR; the passes that transform and operate -//! on MIR are found in `rustc_mir` crate. +//! on MIR are found in `rustc_const_eval` crate. //! - **Types.** The internal representation of types used in rustc is //! defined in the `ty` module. This includes the **type context** //! (or `tcx`), which is the central context during most of @@ -31,7 +31,9 @@ #![feature(box_patterns)] #![feature(core_intrinsics)] #![feature(discriminant_kind)] +#![feature(exhaustive_patterns)] #![feature(if_let_guard)] +#![feature(map_first_last)] #![feature(never_type)] #![feature(extern_types)] #![feature(new_uninit)] @@ -39,21 +41,19 @@ #![feature(once_cell)] #![feature(min_specialization)] #![feature(trusted_len)] -#![feature(test)] #![feature(in_band_lifetimes)] #![feature(crate_visibility_modifier)] #![feature(associated_type_bounds)] #![feature(rustc_attrs)] #![feature(half_open_range_patterns)] -#![feature(exclusive_range_pattern)] #![feature(control_flow_enum)] #![feature(associated_type_defaults)] #![feature(iter_zip)] #![feature(thread_local_const_init)] -#![feature(try_reserve)] +#![feature(trusted_step)] +#![feature(try_blocks)] #![feature(try_reserve_kind)] #![feature(nonzero_ops)] -#![cfg_attr(bootstrap, allow(incomplete_features))] // if_let_guard #![recursion_limit = "512"] #[macro_use] @@ -81,7 +81,6 @@ pub mod arena; #[macro_use] pub mod dep_graph; pub mod hir; -pub mod ich; pub mod infer; pub mod lint; pub mod middle; diff --git a/compiler/rustc_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs index 6ad6887723..1eba2994ed 100644 --- a/compiler/rustc_middle/src/lint.rs +++ b/compiler/rustc_middle/src/lint.rs @@ -1,11 +1,11 @@ use std::cmp; -use crate::ich::StableHashingContext; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_errors::{DiagnosticBuilder, DiagnosticId}; use rustc_hir::HirId; use rustc_index::vec::IndexVec; +use rustc_query_system::ich::StableHashingContext; use rustc_session::lint::{ builtin::{self, FORBIDDEN_LINT_GROUPS}, FutureIncompatibilityReason, Level, Lint, LintId, @@ -192,6 +192,7 @@ impl<'a> LintDiagnosticBuilder<'a> { /// Return the inner DiagnosticBuilder, first setting the primary message to `msg`. pub fn build(mut self, msg: &str) -> DiagnosticBuilder<'a> { self.0.set_primary_message(msg); + self.0.set_is_lint(); self.0 } @@ -388,9 +389,9 @@ pub fn struct_lint_level<'s, 'd>( pub fn in_external_macro(sess: &Session, span: Span) -> bool { let expn_data = span.ctxt().outer_expn_data(); match expn_data.kind { - ExpnKind::Inlined | ExpnKind::Root | ExpnKind::Desugaring(DesugaringKind::ForLoop(_)) => { - false - } + ExpnKind::Inlined + | ExpnKind::Root + | 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/codegen_fn_attrs.rs b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs index b2705c7693..b054d21ada 100644 --- a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs +++ b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs @@ -22,7 +22,7 @@ pub struct CodegenFnAttrs { /// imported function has in the dynamic library. Note that this must not /// be set when `link_name` is set. This is for foreign items with the /// "raw-dylib" kind. - pub link_ordinal: Option, + pub link_ordinal: Option, /// The `#[target_feature(enable = "...")]` attribute and the enabled /// features (only enabled features are supported right now). pub target_features: Vec, diff --git a/compiler/rustc_middle/src/middle/mod.rs b/compiler/rustc_middle/src/middle/mod.rs index b370ec152e..80a5407131 100644 --- a/compiler/rustc_middle/src/middle/mod.rs +++ b/compiler/rustc_middle/src/middle/mod.rs @@ -1,5 +1,4 @@ pub mod codegen_fn_attrs; -pub mod cstore; pub mod dependency_format; pub mod exported_symbols; pub mod lang_items; diff --git a/compiler/rustc_middle/src/middle/privacy.rs b/compiler/rustc_middle/src/middle/privacy.rs index a11ca74b25..f33bd3438b 100644 --- a/compiler/rustc_middle/src/middle/privacy.rs +++ b/compiler/rustc_middle/src/middle/privacy.rs @@ -3,7 +3,9 @@ //! which are available for use externally when compiled as a library. use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_macros::HashStable; +use rustc_query_system::ich::{NodeIdHashingMode, StableHashingContext}; use rustc_span::def_id::LocalDefId; use std::hash::Hash; @@ -53,3 +55,12 @@ impl Default for AccessLevels { AccessLevels { map: Default::default() } } } + +impl<'a> HashStable> for AccessLevels { + fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { + hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| { + let AccessLevels { ref map } = *self; + map.hash_stable(hcx, hasher); + }); + } +} diff --git a/compiler/rustc_middle/src/middle/region.rs b/compiler/rustc_middle/src/middle/region.rs index bd4e83a42e..605e0bc2e6 100644 --- a/compiler/rustc_middle/src/middle/region.rs +++ b/compiler/rustc_middle/src/middle/region.rs @@ -6,10 +6,10 @@ //! //! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/borrow_check.html -use crate::ich::{NodeIdHashingMode, StableHashingContext}; use crate::ty::TyCtxt; use rustc_hir as hir; use rustc_hir::Node; +use rustc_query_system::ich::{NodeIdHashingMode, StableHashingContext}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; @@ -257,7 +257,8 @@ pub struct ScopeTree { /// ``` /// /// With the HIR tree (calls numbered for expository purposes) - /// ``` + /// + /// ```text /// Call#0(foo, [Call#1(f), Yield(y), Call#2(bar, Call#3(g))]) /// ``` /// diff --git a/compiler/rustc_middle/src/middle/stability.rs b/compiler/rustc_middle/src/middle/stability.rs index f0b4b6b5a0..597622b2eb 100644 --- a/compiler/rustc_middle/src/middle/stability.rs +++ b/compiler/rustc_middle/src/middle/stability.rs @@ -15,12 +15,11 @@ use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, CRATE_DEF_INDEX}; use rustc_hir::{self, HirId}; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_session::lint::builtin::{DEPRECATED, DEPRECATED_IN_FUTURE, SOFT_UNSTABLE}; -use rustc_session::lint::{BuiltinLintDiagnostics, Lint, LintBuffer}; +use rustc_session::lint::{BuiltinLintDiagnostics, Level, Lint, LintBuffer}; use rustc_session::parse::feature_err_issue; use rustc_session::{DiagnosticMessageId, Session}; use rustc_span::symbol::{sym, Symbol}; use rustc_span::{MultiSpan, Span}; - use std::num::NonZeroU32; #[derive(PartialEq, Clone, Copy, Debug)] @@ -125,7 +124,11 @@ pub fn report_unstable( /// Checks whether an item marked with `deprecated(since="X")` is currently /// deprecated (i.e., whether X is not greater than the current rustc version). -pub fn deprecation_in_effect(is_since_rustc_version: bool, since: Option<&str>) -> bool { +pub fn deprecation_in_effect(depr: &Deprecation) -> bool { + let is_since_rustc_version = depr.is_since_rustc_version; + let since = depr.since.map(Symbol::as_str); + let since = since.as_deref(); + fn parse_version(ver: &str) -> Vec { // We ignore non-integer components of the version (e.g., "nightly"). ver.split(|c| c == '.' || c == '-').flat_map(|s| s.parse()).collect() @@ -175,33 +178,50 @@ pub fn deprecation_suggestion( } } -pub fn deprecation_message(depr: &Deprecation, kind: &str, path: &str) -> (String, &'static Lint) { - let since = depr.since.map(Symbol::as_str); - let (message, lint) = if deprecation_in_effect(depr.is_since_rustc_version, since.as_deref()) { - (format!("use of deprecated {} `{}`", kind, path), DEPRECATED) +fn deprecation_lint(is_in_effect: bool) -> &'static Lint { + if is_in_effect { DEPRECATED } else { DEPRECATED_IN_FUTURE } +} + +fn deprecation_message( + is_in_effect: bool, + since: Option, + note: Option, + kind: &str, + path: &str, +) -> String { + let message = if is_in_effect { + format!("use of deprecated {} `{}`", kind, path) } else { - ( - if since.as_deref() == Some("TBD") { - format!( - "use of {} `{}` that will be deprecated in a future Rust version", - kind, path - ) - } else { - format!( - "use of {} `{}` that will be deprecated in future version {}", - kind, - path, - since.unwrap() - ) - }, - DEPRECATED_IN_FUTURE, - ) + let since = since.map(Symbol::as_str); + + if since.as_deref() == Some("TBD") { + format!("use of {} `{}` that will be deprecated in a future Rust version", kind, path) + } else { + format!( + "use of {} `{}` that will be deprecated in future version {}", + kind, + path, + since.unwrap() + ) + } }; - let message = match depr.note { + + match note { Some(reason) => format!("{}: {}", message, reason), None => message, - }; - (message, lint) + } +} + +pub fn deprecation_message_and_lint( + depr: &Deprecation, + kind: &str, + path: &str, +) -> (String, &'static Lint) { + let is_in_effect = deprecation_in_effect(depr); + ( + deprecation_message(is_in_effect, depr.since, depr.note, kind, path), + deprecation_lint(is_in_effect), + ) } pub fn early_report_deprecation( @@ -303,20 +323,34 @@ impl<'tcx> TyCtxt<'tcx> { // // #[rustc_deprecated] however wants to emit down the whole // hierarchy. - if !skip || depr_entry.attr.is_since_rustc_version { - let path = &with_no_trimmed_paths(|| self.def_path_str(def_id)); - let kind = self.def_kind(def_id).descr(def_id); - let (message, lint) = deprecation_message(&depr_entry.attr, kind, path); - late_report_deprecation( - self, - &message, - depr_entry.attr.suggestion, - lint, - span, - method_span, - id, - def_id, - ); + let depr_attr = &depr_entry.attr; + if !skip || depr_attr.is_since_rustc_version { + // Calculating message for lint involves calling `self.def_path_str`. + // Which by default to calculate visible path will invoke expensive `visible_parent_map` query. + // So we skip message calculation altogether, if lint is allowed. + let is_in_effect = deprecation_in_effect(depr_attr); + let lint = deprecation_lint(is_in_effect); + if self.lint_level_at_node(lint, id).0 != Level::Allow { + let def_path = &with_no_trimmed_paths(|| self.def_path_str(def_id)); + let def_kind = self.def_kind(def_id).descr(def_id); + + late_report_deprecation( + self, + &deprecation_message( + is_in_effect, + depr_attr.since, + depr_attr.note, + def_kind, + def_path, + ), + depr_attr.suggestion, + lint, + span, + method_span, + id, + def_id, + ); + } } }; } diff --git a/compiler/rustc_middle/src/mir/abstract_const.rs b/compiler/rustc_middle/src/mir/abstract_const.rs deleted file mode 100644 index 1ef1024114..0000000000 --- a/compiler/rustc_middle/src/mir/abstract_const.rs +++ /dev/null @@ -1,38 +0,0 @@ -//! A subset of a mir body used for const evaluatability checking. -use crate::mir::{self, CastKind}; -use crate::ty::{self, Ty}; - -rustc_index::newtype_index! { - /// An index into an `AbstractConst`. - pub struct NodeId { - derive [HashStable] - DEBUG_FORMAT = "n{}", - } -} - -/// A node of an `AbstractConst`. -#[derive(Debug, Clone, Copy, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)] -pub enum Node<'tcx> { - Leaf(&'tcx ty::Const<'tcx>), - Binop(mir::BinOp, NodeId, NodeId), - UnaryOp(mir::UnOp, NodeId), - FunctionCall(NodeId, &'tcx [NodeId]), - Cast(CastKind, NodeId, Ty<'tcx>), -} - -#[derive(Debug, Copy, Clone, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)] -pub enum NotConstEvaluatable { - Error(rustc_errors::ErrorReported), - MentionsInfer, - MentionsParam, -} - -impl From for NotConstEvaluatable { - fn from(e: rustc_errors::ErrorReported) -> NotConstEvaluatable { - NotConstEvaluatable::Error(e) - } -} - -TrivialTypeFoldableAndLiftImpls! { - NotConstEvaluatable, -} diff --git a/compiler/rustc_mir/src/util/generic_graph.rs b/compiler/rustc_middle/src/mir/generic_graph.rs similarity index 100% rename from compiler/rustc_mir/src/util/generic_graph.rs rename to compiler/rustc_middle/src/mir/generic_graph.rs diff --git a/compiler/rustc_mir/src/util/generic_graphviz.rs b/compiler/rustc_middle/src/mir/generic_graphviz.rs similarity index 100% rename from compiler/rustc_mir/src/util/generic_graphviz.rs rename to compiler/rustc_middle/src/mir/generic_graphviz.rs diff --git a/compiler/rustc_mir/src/util/graphviz.rs b/compiler/rustc_middle/src/mir/graphviz.rs similarity index 100% rename from compiler/rustc_mir/src/util/graphviz.rs rename to compiler/rustc_middle/src/mir/graphviz.rs diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs index b6358f9929..a36c9b6ed7 100644 --- a/compiler/rustc_middle/src/mir/interpret/allocation.rs +++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs @@ -1004,13 +1004,13 @@ impl Allocation { /// Checks that a range of bytes is initialized. If not, returns the `InvalidUninitBytes` /// error which will report the first range of bytes which is uninitialized. fn check_init(&self, range: AllocRange) -> AllocResult { - self.is_init(range).or_else(|idx_range| { - Err(AllocError::InvalidUninitBytes(Some(UninitBytesAccess { + self.is_init(range).map_err(|idx_range| { + AllocError::InvalidUninitBytes(Some(UninitBytesAccess { access_offset: range.start, access_size: range.size, uninit_offset: idx_range.start, uninit_size: idx_range.end - idx_range.start, // `Size` subtraction - }))) + })) }) } diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs index 5d17bb9b15..9472a287e5 100644 --- a/compiler/rustc_middle/src/mir/interpret/error.rs +++ b/compiler/rustc_middle/src/mir/interpret/error.rs @@ -287,6 +287,8 @@ pub enum UndefinedBehaviorInfo<'tcx> { target_size: u64, data_size: u64, }, + /// A discriminant of an uninhabited enum variant is written. + UninhabitedEnumVariantWritten, } impl fmt::Display for UndefinedBehaviorInfo<'_> { @@ -391,6 +393,9 @@ impl fmt::Display for UndefinedBehaviorInfo<'_> { "scalar size mismatch: expected {} bytes but got {} bytes instead", target_size, data_size ), + UninhabitedEnumVariantWritten => { + write!(f, "writing discriminant of an uninhabited enum") + } } } } diff --git a/compiler/rustc_middle/src/mir/interpret/pointer.rs b/compiler/rustc_middle/src/mir/interpret/pointer.rs index 3eee45a923..c9dc5a0f3b 100644 --- a/compiler/rustc_middle/src/mir/interpret/pointer.rs +++ b/compiler/rustc_middle/src/mir/interpret/pointer.rs @@ -3,7 +3,7 @@ use super::{AllocId, InterpResult}; use rustc_macros::HashStable; use rustc_target::abi::{HasDataLayout, Size}; -use std::convert::TryFrom; +use std::convert::{TryFrom, TryInto}; use std::fmt; //////////////////////////////////////////////////////////////////////////////// @@ -20,29 +20,27 @@ pub trait PointerArithmetic: HasDataLayout { #[inline] fn machine_usize_max(&self) -> u64 { - let max_usize_plus_1 = 1u128 << self.pointer_size().bits(); - u64::try_from(max_usize_plus_1 - 1).unwrap() + self.pointer_size().unsigned_int_max().try_into().unwrap() } #[inline] fn machine_isize_min(&self) -> i64 { - let max_isize_plus_1 = 1i128 << (self.pointer_size().bits() - 1); - i64::try_from(-max_isize_plus_1).unwrap() + self.pointer_size().signed_int_min().try_into().unwrap() } #[inline] fn machine_isize_max(&self) -> i64 { - let max_isize_plus_1 = 1u128 << (self.pointer_size().bits() - 1); - i64::try_from(max_isize_plus_1 - 1).unwrap() + self.pointer_size().signed_int_max().try_into().unwrap() } #[inline] fn machine_usize_to_isize(&self, val: u64) -> i64 { let val = val as i64; - // Now clamp into the machine_isize range. + // Now wrap-around into the machine_isize range. if val > self.machine_isize_max() { // This can only happen the the ptr size is < 64, so we know max_usize_plus_1 fits into // i64. + debug_assert!(self.pointer_size().bits() < 64); let max_usize_plus_1 = 1u128 << self.pointer_size().bits(); val - i64::try_from(max_usize_plus_1).unwrap() } else { diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 83f6e79d5f..971556d446 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -40,13 +40,18 @@ use self::graph_cyclic_cache::GraphIsCyclicCache; use self::predecessors::{PredecessorCache, Predecessors}; pub use self::query::*; -pub mod abstract_const; pub mod coverage; +mod generic_graph; +pub mod generic_graphviz; mod graph_cyclic_cache; +pub mod graphviz; pub mod interpret; pub mod mono; +pub mod patch; mod predecessors; +pub mod pretty; mod query; +pub mod spanview; pub mod tcx; pub mod terminator; pub use terminator::*; @@ -54,6 +59,12 @@ pub mod traversal; mod type_foldable; pub mod visit; +pub use self::generic_graph::graphviz_safe_def_name; +pub use self::graphviz::write_mir_graphviz; +pub use self::pretty::{ + create_dump_file, display_allocation, dump_enabled, dump_mir, write_mir_pretty, PassWhere, +}; + /// Types for locals pub type LocalDecls<'tcx> = IndexVec>; @@ -75,6 +86,22 @@ impl<'tcx> HasLocalDecls<'tcx> for Body<'tcx> { } } +/// A streamlined trait that you can implement to create a pass; the +/// pass will be named after the type, and it will consist of a main +/// loop that goes over each available MIR and applies `run_pass`. +pub trait MirPass<'tcx> { + fn name(&self) -> Cow<'_, str> { + let name = std::any::type_name::(); + if let Some(tail) = name.rfind(':') { + Cow::from(&name[tail + 1..]) + } else { + Cow::from(name) + } + } + + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>); +} + /// The various "big phases" that MIR goes through. /// /// These phases all describe dialects of MIR. Since all MIR uses the same datastructures, the @@ -776,8 +803,8 @@ pub enum ImplicitSelfKind { TrivialTypeFoldableAndLiftImpls! { BindingForm<'tcx>, } mod binding_form_impl { - use crate::ich::StableHashingContext; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; + use rustc_query_system::ich::StableHashingContext; impl<'a, 'tcx> HashStable> for super::BindingForm<'tcx> { fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { @@ -965,6 +992,9 @@ pub enum LocalInfo<'tcx> { StaticRef { def_id: DefId, is_thread_local: bool }, /// A temporary created that references the const with the given `DefId` ConstRef { def_id: DefId }, + /// A temporary created during the creation of an aggregate + /// (e.g. a temporary for `foo` in `MyStruct { my_field: foo }`) + AggregateTemp, } impl<'tcx> LocalDecl<'tcx> { @@ -1142,7 +1172,7 @@ rustc_index::newtype_index! { /// [CFG]: https://rustc-dev-guide.rust-lang.org/appendix/background.html#cfg /// [data-flow analyses]: /// https://rustc-dev-guide.rust-lang.org/appendix/background.html#what-is-a-dataflow-analysis - /// [`CriticalCallEdges`]: ../../rustc_mir/transform/add_call_guards/enum.AddCallGuards.html#variant.CriticalCallEdges + /// [`CriticalCallEdges`]: ../../rustc_const_eval/transform/add_call_guards/enum.AddCallGuards.html#variant.CriticalCallEdges /// [guide-mir]: https://rustc-dev-guide.rust-lang.org/mir/ pub struct BasicBlock { derive [HashStable] @@ -1708,7 +1738,7 @@ pub struct Place<'tcx> { pub projection: &'tcx List>, } -#[cfg(target_arch = "x86_64")] +#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] static_assert_size!(Place<'_>, 16); #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] @@ -2034,7 +2064,7 @@ pub enum Operand<'tcx> { Constant(Box>), } -#[cfg(target_arch = "x86_64")] +#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] static_assert_size!(Operand<'_>, 24); impl<'tcx> Debug for Operand<'tcx> { @@ -2170,9 +2200,15 @@ pub enum Rvalue<'tcx> { /// that `Foo` has a destructor. These rvalues can be optimized /// away after type-checking and before lowering. Aggregate(Box>, Vec>), + + /// Transmutes a `*mut u8` into shallow-initialized `Box`. + /// + /// This is different a normal transmute because dataflow analysis will treat the box + /// as initialized but its content as uninitialized. + ShallowInitBox(Operand<'tcx>, Ty<'tcx>), } -#[cfg(target_arch = "x86_64")] +#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] static_assert_size!(Rvalue<'_>, 40); #[derive(Clone, Copy, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)] @@ -2198,7 +2234,7 @@ pub enum AggregateKind<'tcx> { Generator(DefId, SubstsRef<'tcx>, hir::Movability), } -#[cfg(target_arch = "x86_64")] +#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] static_assert_size!(AggregateKind<'_>, 48); #[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Eq, TyEncodable, TyDecodable, Hash, HashStable)] @@ -2250,6 +2286,8 @@ impl BinOp { pub enum NullOp { /// Returns the size of a value of that type SizeOf, + /// Returns the minimum alignment of a type + AlignOf, /// Creates a new uninitialized box for a value of that type Box, } @@ -2418,6 +2456,10 @@ impl<'tcx> Debug for Rvalue<'tcx> { }), } } + + ShallowInitBox(ref place, ref ty) => { + write!(fmt, "ShallowInitBox({:?}, {:?})", place, ty) + } } } } diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs index 776cf002c1..06b4232004 100644 --- a/compiler/rustc_middle/src/mir/mono.rs +++ b/compiler/rustc_middle/src/mir/mono.rs @@ -1,5 +1,4 @@ use crate::dep_graph::{DepNode, WorkProduct, WorkProductId}; -use crate::ich::{NodeIdHashingMode, StableHashingContext}; use crate::ty::{subst::InternalSubsts, Instance, InstanceDef, SymbolName, TyCtxt}; use rustc_attr::InlineAttr; use rustc_data_structures::base_n; @@ -8,6 +7,7 @@ use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; use rustc_hir::{HirId, ItemId}; +use rustc_query_system::ich::{NodeIdHashingMode, StableHashingContext}; use rustc_session::config::OptLevel; use rustc_span::source_map::Span; use rustc_span::symbol::Symbol; @@ -47,6 +47,14 @@ pub enum MonoItem<'tcx> { } impl<'tcx> MonoItem<'tcx> { + /// Returns `true` if the mono item is user-defined (i.e. not compiler-generated, like shims). + pub fn is_user_defined(&self) -> bool { + match *self { + MonoItem::Fn(instance) => matches!(instance.def, InstanceDef::Item(..)), + MonoItem::Static(..) | MonoItem::GlobalAsm(..) => true, + } + } + pub fn size_estimate(&self, tcx: TyCtxt<'tcx>) -> usize { match *self { MonoItem::Fn(instance) => { diff --git a/compiler/rustc_mir/src/util/patch.rs b/compiler/rustc_middle/src/mir/patch.rs similarity index 100% rename from compiler/rustc_mir/src/util/patch.rs rename to compiler/rustc_middle/src/mir/patch.rs diff --git a/compiler/rustc_mir/src/util/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs similarity index 99% rename from compiler/rustc_mir/src/util/pretty.rs rename to compiler/rustc_middle/src/mir/pretty.rs index 92591db668..db98cb7634 100644 --- a/compiler/rustc_mir/src/util/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -7,7 +7,6 @@ use std::path::{Path, PathBuf}; use super::graphviz::write_mir_fn_graphviz; use super::spanview::write_mir_fn_spanview; -use crate::transform::MirSource; use either::Either; use rustc_data_structures::fx::FxHashMap; use rustc_hir::def_id::DefId; @@ -16,6 +15,7 @@ use rustc_middle::mir::interpret::{ read_target_uint, AllocId, Allocation, ConstValue, GlobalAlloc, Pointer, Provenance, }; use rustc_middle::mir::visit::Visitor; +use rustc_middle::mir::MirSource; use rustc_middle::mir::*; use rustc_middle::ty::{self, TyCtxt, TyS, TypeFoldable, TypeVisitor}; use rustc_target::abi::Size; @@ -250,7 +250,7 @@ fn create_dump_file_with_basename( /// bit of MIR-related data. Used by `mir-dump`, but also by other /// bits of code (e.g., NLL inference) that dump graphviz data or /// other things, and hence takes the extension as an argument. -pub(crate) fn create_dump_file( +pub fn create_dump_file( tcx: TyCtxt<'_>, extension: &str, pass_num: Option<&dyn Display>, diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs index 4fb737f463..d5541d7890 100644 --- a/compiler/rustc_middle/src/mir/query.rs +++ b/compiler/rustc_middle/src/mir/query.rs @@ -1,6 +1,6 @@ //! Values computed by queries that use MIR. -use crate::mir::{abstract_const, Body, Promoted}; +use crate::mir::{Body, Promoted}; use crate::ty::{self, Ty, TyCtxt}; use rustc_data_structures::sync::Lrc; use rustc_data_structures::vec_map::VecMap; @@ -219,7 +219,7 @@ pub struct BorrowCheckResult<'tcx> { /// The result of the `mir_const_qualif` query. /// /// Each field (except `error_occured`) corresponds to an implementer of the `Qualif` trait in -/// `rustc_mir/src/transform/check_consts/qualifs.rs`. See that file for more information on each +/// `rustc_const_eval/src/transform/check_consts/qualifs.rs`. See that file for more information on each /// `Qualif`. #[derive(Clone, Copy, Debug, Default, TyEncodable, TyDecodable, HashStable)] pub struct ConstQualifs { @@ -309,11 +309,14 @@ pub struct ClosureOutlivesRequirement<'tcx> { pub category: ConstraintCategory, } +// Make sure this enum doesn't unintentionally grow +rustc_data_structures::static_assert_size!(ConstraintCategory, 12); + /// Outlives-constraints can be categorized to determine whether and why they /// are interesting (for error reporting). Order of variants indicates sort /// order of the category, thereby influencing diagnostic output. /// -/// See also `rustc_mir::borrow_check::constraints`. +/// See also `rustc_const_eval::borrow_check::constraints`. #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)] #[derive(TyEncodable, TyDecodable, HashStable)] pub enum ConstraintCategory { @@ -332,17 +335,20 @@ pub enum ConstraintCategory { CopyBound, SizedBound, Assignment, + /// A constraint that came from a usage of a variable (e.g. in an ADT expression + /// like `Foo { field: my_val }`) + Usage, OpaqueType, ClosureUpvar(hir::HirId), + /// A constraint from a user-written predicate + /// with the provided span, written on the item + /// with the given `DefId` + Predicate(Span), + /// A "boring" constraint (caused by the given location) is one that /// the user probably doesn't want to see described in diagnostics, /// because it is kind of an artifact of the type system setup. - /// Example: `x = Foo { field: y }` technically creates - /// intermediate regions representing the "type of `Foo { field: y - /// }`", and data flows from `y` into those variables, but they - /// are not very interesting. The assignment into `x` on the other - /// hand might be. Boring, // Boring and applicable everywhere. BoringNoLocation, @@ -431,16 +437,4 @@ impl<'tcx> TyCtxt<'tcx> { self.mir_for_ctfe(def.did) } } - - #[inline] - pub fn mir_abstract_const_opt_const_arg( - self, - def: ty::WithOptConstParam, - ) -> Result]>, ErrorReported> { - if let Some((did, param_did)) = def.as_const_arg() { - self.mir_abstract_const_of_const_arg((did, param_did)) - } else { - self.mir_abstract_const(def.did) - } - } } diff --git a/compiler/rustc_mir/src/util/spanview.rs b/compiler/rustc_middle/src/mir/spanview.rs similarity index 100% rename from compiler/rustc_mir/src/util/spanview.rs rename to compiler/rustc_middle/src/mir/spanview.rs diff --git a/compiler/rustc_middle/src/mir/tcx.rs b/compiler/rustc_middle/src/mir/tcx.rs index 74d303cee5..c3c5ebe705 100644 --- a/compiler/rustc_middle/src/mir/tcx.rs +++ b/compiler/rustc_middle/src/mir/tcx.rs @@ -196,7 +196,7 @@ impl<'tcx> Rvalue<'tcx> { Rvalue::UnaryOp(UnOp::Not | UnOp::Neg, ref operand) => operand.ty(local_decls, tcx), Rvalue::Discriminant(ref place) => place.ty(local_decls, tcx).ty.discriminant_ty(tcx), Rvalue::NullaryOp(NullOp::Box, t) => tcx.mk_box(t), - Rvalue::NullaryOp(NullOp::SizeOf, _) => tcx.types.usize, + Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf, _) => tcx.types.usize, Rvalue::Aggregate(ref ak, ref ops) => match **ak { AggregateKind::Array(ty) => tcx.mk_array(ty, ops.len() as u64), AggregateKind::Tuple => tcx.mk_tup(ops.iter().map(|op| op.ty(local_decls, tcx))), @@ -206,6 +206,7 @@ impl<'tcx> Rvalue<'tcx> { tcx.mk_generator(did, substs, movability) } }, + Rvalue::ShallowInitBox(_, ty) => tcx.mk_box(ty), } } @@ -214,7 +215,9 @@ impl<'tcx> Rvalue<'tcx> { /// whether its only shallowly initialized (`Rvalue::Box`). pub fn initialization_state(&self) -> RvalueInitializationState { match *self { - Rvalue::NullaryOp(NullOp::Box, _) => RvalueInitializationState::Shallow, + Rvalue::NullaryOp(NullOp::Box, _) | Rvalue::ShallowInitBox(_, _) => { + RvalueInitializationState::Shallow + } _ => RvalueInitializationState::Deep, } } diff --git a/compiler/rustc_middle/src/mir/type_foldable.rs b/compiler/rustc_middle/src/mir/type_foldable.rs index b2d4a22194..b7201f7acf 100644 --- a/compiler/rustc_middle/src/mir/type_foldable.rs +++ b/compiler/rustc_middle/src/mir/type_foldable.rs @@ -210,6 +210,7 @@ impl<'tcx> TypeFoldable<'tcx> for Rvalue<'tcx> { }); Aggregate(kind, fields.fold_with(folder)) } + ShallowInitBox(op, ty) => ShallowInitBox(op.fold_with(folder), ty.fold_with(folder)), } } @@ -255,6 +256,10 @@ impl<'tcx> TypeFoldable<'tcx> for Rvalue<'tcx> { } fields.visit_with(visitor) } + ShallowInitBox(ref op, ty) => { + op.visit_with(visitor)?; + ty.visit_with(visitor) + } } } } diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs index af7f779652..fda7ebe1a4 100644 --- a/compiler/rustc_middle/src/mir/visit.rs +++ b/compiler/rustc_middle/src/mir/visit.rs @@ -348,7 +348,7 @@ macro_rules! make_mir_visitor { ty::InstanceDef::VtableShim(_def_id) | ty::InstanceDef::ReifyShim(_def_id) | ty::InstanceDef::Virtual(_def_id, _) | - ty::InstanceDef::ClosureOnceShim { call_once: _def_id } | + ty::InstanceDef::ClosureOnceShim { call_once: _def_id, track_caller: _ } | ty::InstanceDef::DropGlue(_def_id, None) => {} ty::InstanceDef::FnPtrShim(_def_id, ty) | @@ -753,6 +753,11 @@ macro_rules! make_mir_visitor { self.visit_operand(operand, location); } } + + Rvalue::ShallowInitBox(operand, ty) => { + self.visit_operand(operand, location); + self.visit_ty(ty, TyContext::Location(location)); + } } } diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index ed32bb16d4..4145cbd424 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -20,6 +20,14 @@ rustc_queries! { desc { "get the resolver outputs" } } + /// Return the span for a definition. + /// Contrary to `def_span` below, this query returns the full absolute span of the definition. + /// This span is meant for dep-tracking rather than diagnostics. It should not be used outside + /// of rustc_middle::hir::source_map. + query source_span(key: LocalDefId) -> Span { + desc { "get the source span" } + } + /// Represents crate as a whole (as distinct from the top-level crate module). /// If you call `hir_crate` (e.g., indirectly by calling `tcx.hir().krate()`), /// we will have to assume that any change means that you need to be recompiled. @@ -44,8 +52,8 @@ rustc_queries! { /// /// This can be conveniently accessed by `tcx.hir().visit_item_likes_in_module`. /// Avoid calling this query directly. - query hir_module_items(key: LocalDefId) -> &'tcx hir::ModuleItems { - eval_always + query hir_module_items(key: LocalDefId) -> rustc_middle::hir::ModuleItems { + storage(ArenaCacheSelector<'tcx>) desc { |tcx| "HIR module items in `{}`", tcx.def_path_str(key.to_def_id()) } } @@ -295,17 +303,17 @@ rustc_queries! { } /// Try to build an abstract representation of the given constant. - query mir_abstract_const( + query thir_abstract_const( key: DefId - ) -> Result]>, ErrorReported> { + ) -> Result]>, ErrorReported> { desc { |tcx| "building an abstract representation for {}", tcx.def_path_str(key), } } /// Try to build an abstract representation of the given constant. - query mir_abstract_const_of_const_arg( + query thir_abstract_const_of_const_arg( key: (LocalDefId, DefId) - ) -> Result]>, ErrorReported> { + ) -> Result]>, ErrorReported> { desc { |tcx| "building an abstract representation for the const argument {}", @@ -544,14 +552,6 @@ rustc_queries! { desc { |tcx| "checking if item is const fn: `{}`", tcx.def_path_str(key) } } - /// Returns `true` if this is a const `impl`. **Do not call this function manually.** - /// - /// This query caches the base data for the `is_const_impl` helper function, which also - /// takes into account stability attributes (e.g., `#[rustc_const_unstable]`). - query is_const_impl_raw(key: DefId) -> bool { - desc { |tcx| "checking if item is const impl: `{}`", tcx.def_path_str(key) } - } - query asyncness(key: DefId) -> hir::IsAsync { desc { |tcx| "checking if the function is async: `{}`", tcx.def_path_str(key) } } @@ -599,7 +599,7 @@ rustc_queries! { desc { "computing the inferred outlives predicates for items in this crate" } } - /// Maps from an impl/trait `DefId to a list of the `DefId`s of its items. + /// 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) } } @@ -996,6 +996,12 @@ rustc_queries! { desc { |tcx| "checking if item has mir available: `{}`", tcx.def_path_str(key) } } + query own_existential_vtable_entries( + key: ty::PolyExistentialTraitRef<'tcx> + ) -> &'tcx [DefId] { + desc { |tcx| "finding all existential vtable entries for trait {}", tcx.def_path_str(key.def_id()) } + } + query vtable_entries(key: ty::PolyTraitRef<'tcx>) -> &'tcx [ty::VtblEntry<'tcx>] { desc { |tcx| "finding all vtable entries for trait {}", tcx.def_path_str(key.def_id()) } @@ -1129,6 +1135,27 @@ rustc_queries! { desc { "computing layout of `{}`", key.value } } + /// Compute a `FnAbi` suitable for indirect calls, i.e. to `fn` pointers. + /// + /// NB: this doesn't handle virtual calls - those should use `fn_abi_of_instance` + /// instead, where the instance is an `InstanceDef::Virtual`. + query fn_abi_of_fn_ptr( + key: ty::ParamEnvAnd<'tcx, (ty::PolyFnSig<'tcx>, &'tcx ty::List>)> + ) -> Result<&'tcx abi::call::FnAbi<'tcx, Ty<'tcx>>, ty::layout::FnAbiError<'tcx>> { + desc { "computing call ABI of `{}` function pointers", key.value.0 } + } + + /// Compute a `FnAbi` suitable for declaring/defining an `fn` instance, and for + /// direct calls to an `fn`. + /// + /// NB: that includes virtual calls, which are represented by "direct calls" + /// to an `InstanceDef::Virtual` instance (of `::fn`). + query fn_abi_of_instance( + key: ty::ParamEnvAnd<'tcx, (ty::Instance<'tcx>, &'tcx ty::List>)> + ) -> Result<&'tcx abi::call::FnAbi<'tcx, Ty<'tcx>>, ty::layout::FnAbiError<'tcx>> { + desc { "computing call ABI of `{}`", key.value.0 } + } + query dylib_dependency_formats(_: CrateNum) -> &'tcx [(CrateNum, LinkagePreference)] { desc { "dylib dependency formats of crate" } @@ -1160,6 +1187,10 @@ rustc_queries! { fatal_cycle desc { "query a crate's configured panic strategy" } } + query panic_in_drop_strategy(_: CrateNum) -> PanicStrategy { + fatal_cycle + desc { "query a crate's configured panic-in-drop strategy" } + } query is_no_builtins(_: CrateNum) -> bool { fatal_cycle desc { "test whether a crate has `#![no_builtins]`" } @@ -1182,7 +1213,7 @@ rustc_queries! { desc { "traits in scope at a block" } } - query module_exports(def_id: LocalDefId) -> Option<&'tcx [Export]> { + query module_exports(def_id: LocalDefId) -> Option<&'tcx [Export]> { desc { |tcx| "looking up items exported by `{}`", tcx.def_path_str(def_id.to_def_id()) } } @@ -1394,7 +1425,7 @@ rustc_queries! { eval_always desc { "fetching what a crate is named" } } - query item_children(def_id: DefId) -> &'tcx [Export] { + query item_children(def_id: DefId) -> &'tcx [Export] { desc { |tcx| "collecting child items of `{}`", tcx.def_path_str(def_id) } } query extern_mod_stmt_cnum(def_id: LocalDefId) -> Option { @@ -1418,7 +1449,7 @@ rustc_queries! { } /// Returns all diagnostic items defined in all crates. - query all_diagnostic_items(_: ()) -> FxHashMap { + query all_diagnostic_items(_: ()) -> rustc_hir::diagnostic_items::DiagnosticItems { storage(ArenaCacheSelector<'tcx>) eval_always desc { "calculating the diagnostic items map" } @@ -1430,7 +1461,7 @@ rustc_queries! { } /// Returns the diagnostic items defined in a crate. - query diagnostic_items(_: CrateNum) -> FxHashMap { + query diagnostic_items(_: CrateNum) -> rustc_hir::diagnostic_items::DiagnosticItems { storage(ArenaCacheSelector<'tcx>) desc { "calculating the diagnostic items map in a crate" } } @@ -1527,11 +1558,11 @@ rustc_queries! { query codegen_unit(_: Symbol) -> &'tcx CodegenUnit<'tcx> { desc { "codegen_unit" } } - query unused_generic_params(key: DefId) -> FiniteBitSet { - cache_on_disk_if { key.is_local() } + query unused_generic_params(key: ty::InstanceDef<'tcx>) -> FiniteBitSet { + cache_on_disk_if { key.def_id().is_local() } desc { |tcx| "determining which generic parameters are unused by `{}`", - tcx.def_path_str(key) + tcx.def_path_str(key.def_id()) } } query backend_optimization_level(_: ()) -> OptLevel { diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index 91a64e163e..8d6fd1e729 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -33,6 +33,9 @@ use rustc_target::asm::InlineAsmRegOrRegClass; use std::fmt; use std::ops::Index; +pub mod abstract_const; +pub mod visit; + newtype_index! { /// An index to an [`Arm`] stored in [`Thir::arms`] #[derive(HashStable)] diff --git a/compiler/rustc_middle/src/thir/abstract_const.rs b/compiler/rustc_middle/src/thir/abstract_const.rs new file mode 100644 index 0000000000..f80beadd6e --- /dev/null +++ b/compiler/rustc_middle/src/thir/abstract_const.rs @@ -0,0 +1,61 @@ +//! A subset of a mir body used for const evaluatability checking. +use crate::mir; +use crate::ty::{self, Ty, TyCtxt}; +use rustc_errors::ErrorReported; + +rustc_index::newtype_index! { + /// An index into an `AbstractConst`. + pub struct NodeId { + derive [HashStable] + DEBUG_FORMAT = "n{}", + } +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)] +pub enum CastKind { + /// thir::ExprKind::As + As, + /// thir::ExprKind::Use + Use, +} + +/// A node of an `AbstractConst`. +#[derive(Debug, Clone, Copy, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)] +pub enum Node<'tcx> { + Leaf(&'tcx ty::Const<'tcx>), + Binop(mir::BinOp, NodeId, NodeId), + UnaryOp(mir::UnOp, NodeId), + FunctionCall(NodeId, &'tcx [NodeId]), + Cast(CastKind, NodeId, Ty<'tcx>), +} + +#[derive(Debug, Copy, Clone, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)] +pub enum NotConstEvaluatable { + Error(ErrorReported), + MentionsInfer, + MentionsParam, +} + +impl From for NotConstEvaluatable { + fn from(e: ErrorReported) -> NotConstEvaluatable { + NotConstEvaluatable::Error(e) + } +} + +TrivialTypeFoldableAndLiftImpls! { + NotConstEvaluatable, +} + +impl<'tcx> TyCtxt<'tcx> { + #[inline] + pub fn thir_abstract_const_opt_const_arg( + self, + def: ty::WithOptConstParam, + ) -> Result]>, ErrorReported> { + if let Some((did, param_did)) = def.as_const_arg() { + self.thir_abstract_const_of_const_arg((did, param_did)) + } else { + self.thir_abstract_const(def.did) + } + } +} diff --git a/compiler/rustc_mir_build/src/thir/visit.rs b/compiler/rustc_middle/src/thir/visit.rs similarity index 98% rename from compiler/rustc_mir_build/src/thir/visit.rs rename to compiler/rustc_middle/src/thir/visit.rs index 51c371b872..7fc15e02fc 100644 --- a/compiler/rustc_mir_build/src/thir/visit.rs +++ b/compiler/rustc_middle/src/thir/visit.rs @@ -1,4 +1,6 @@ -use rustc_middle::thir::{self, *}; +use super::{ + Arm, Block, Expr, ExprKind, Guard, InlineAsmOperand, Pat, PatKind, Stmt, StmtKind, Thir, +}; use rustc_middle::ty::Const; pub trait Visitor<'a, 'tcx: 'a>: Sized { @@ -101,7 +103,7 @@ pub fn walk_expr<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, expr: &Exp visitor.visit_expr(&visitor.thir()[field]); } } - Adt(box thir::Adt { + Adt(box crate::thir::Adt { ref fields, ref base, adt_def: _, diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index 74edb17fe3..b089ae22d6 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -9,7 +9,7 @@ pub mod specialization_graph; mod structural_impls; use crate::infer::canonical::Canonical; -use crate::mir::abstract_const::NotConstEvaluatable; +use crate::thir::abstract_const::NotConstEvaluatable; use crate::ty::subst::SubstsRef; use crate::ty::{self, AdtKind, Ty, TyCtxt}; @@ -253,6 +253,15 @@ pub enum ObligationCauseCode<'tcx> { DerivedObligation(DerivedObligationCause<'tcx>), + FunctionArgumentObligation { + /// The node of the relevant argument in the function call. + arg_hir_id: hir::HirId, + /// The node of the function call. + call_hir_id: hir::HirId, + /// The obligation introduced by this argument. + parent_code: Lrc>, + }, + /// Error derived when matching traits/impls; see ObligationCause for more details CompareImplConstObligation, @@ -340,7 +349,7 @@ pub enum ObligationCauseCode<'tcx> { WellFormed(Option), /// From `match_impl`. The cause for us having to match an impl, and the DefId we are matching against. - MatchImpl(Lrc>, DefId), + MatchImpl(ObligationCause<'tcx>, DefId), } /// The 'location' at which we try to perform HIR-based wf checking. @@ -368,11 +377,12 @@ impl ObligationCauseCode<'_> { // Return the base obligation, ignoring derived obligations. pub fn peel_derives(&self) -> &Self { let mut base_cause = self; - while let BuiltinDerivedObligation(cause) - | ImplDerivedObligation(cause) - | DerivedObligation(cause) = base_cause + while let BuiltinDerivedObligation(DerivedObligationCause { parent_code, .. }) + | ImplDerivedObligation(DerivedObligationCause { parent_code, .. }) + | DerivedObligation(DerivedObligationCause { parent_code, .. }) + | FunctionArgumentObligation { parent_code, .. } = base_cause { - base_cause = &cause.parent_code; + base_cause = &parent_code; } base_cause } @@ -439,6 +449,7 @@ pub enum SelectionError<'tcx> { TraitNotObjectSafe(DefId), NotConstEvaluatable(NotConstEvaluatable), Overflow, + ErrorReporting, } /// When performing resolution, it is typically the case that there @@ -529,6 +540,9 @@ pub enum ImplSource<'tcx, N> { /// ImplSource for a trait alias. TraitAlias(ImplSourceTraitAliasData<'tcx, N>), + + /// ImplSource for a `const Drop` implementation. + ConstDrop(ImplSourceConstDropData), } impl<'tcx, N> ImplSource<'tcx, N> { @@ -543,7 +557,8 @@ impl<'tcx, N> ImplSource<'tcx, N> { ImplSource::Object(d) => d.nested, ImplSource::FnPointer(d) => d.nested, ImplSource::DiscriminantKind(ImplSourceDiscriminantKindData) - | ImplSource::Pointee(ImplSourcePointeeData) => Vec::new(), + | ImplSource::Pointee(ImplSourcePointeeData) + | ImplSource::ConstDrop(ImplSourceConstDropData) => Vec::new(), ImplSource::TraitAlias(d) => d.nested, ImplSource::TraitUpcasting(d) => d.nested, } @@ -560,7 +575,8 @@ impl<'tcx, N> ImplSource<'tcx, N> { ImplSource::Object(d) => &d.nested[..], ImplSource::FnPointer(d) => &d.nested[..], ImplSource::DiscriminantKind(ImplSourceDiscriminantKindData) - | ImplSource::Pointee(ImplSourcePointeeData) => &[], + | ImplSource::Pointee(ImplSourcePointeeData) + | ImplSource::ConstDrop(ImplSourceConstDropData) => &[], ImplSource::TraitAlias(d) => &d.nested[..], ImplSource::TraitUpcasting(d) => &d.nested[..], } @@ -621,6 +637,9 @@ impl<'tcx, N> ImplSource<'tcx, N> { nested: d.nested.into_iter().map(f).collect(), }) } + ImplSource::ConstDrop(ImplSourceConstDropData) => { + ImplSource::ConstDrop(ImplSourceConstDropData) + } } } } @@ -712,6 +731,9 @@ pub struct ImplSourceDiscriminantKindData; #[derive(Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, HashStable)] pub struct ImplSourcePointeeData; +#[derive(Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, HashStable)] +pub struct ImplSourceConstDropData; + #[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, TypeFoldable, Lift)] pub struct ImplSourceTraitAliasData<'tcx, N> { pub alias_def_id: DefId, @@ -719,7 +741,7 @@ pub struct ImplSourceTraitAliasData<'tcx, N> { pub nested: Vec, } -#[derive(Clone, Debug, PartialEq, Eq, Hash, HashStable)] +#[derive(Clone, Debug, PartialEq, Eq, Hash, HashStable, PartialOrd, Ord)] pub enum ObjectSafetyViolation { /// `Self: Sized` declared on the trait. SizedSelf(SmallVec<[Span; 1]>), @@ -868,7 +890,7 @@ impl ObjectSafetyViolation { } /// Reasons a method might not be object-safe. -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable, PartialOrd, Ord)] pub enum MethodViolationCode { /// e.g., `fn foo()` StaticMethod(Option<(&'static str, Span)>, Span, bool /* has args */), diff --git a/compiler/rustc_middle/src/traits/query.rs b/compiler/rustc_middle/src/traits/query.rs index b0ab0c9ae5..cb35a4005f 100644 --- a/compiler/rustc_middle/src/traits/query.rs +++ b/compiler/rustc_middle/src/traits/query.rs @@ -5,7 +5,6 @@ //! The providers for the queries defined here can be found in //! `rustc_traits`. -use crate::ich::StableHashingContext; use crate::infer::canonical::{Canonical, QueryResponse}; use crate::ty::error::TypeError; use crate::ty::subst::GenericArg; @@ -14,6 +13,7 @@ use crate::ty::{self, Ty, TyCtxt}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::sync::Lrc; use rustc_errors::struct_span_err; +use rustc_query_system::ich::StableHashingContext; use rustc_span::source_map::Span; use std::iter::FromIterator; use std::mem; diff --git a/compiler/rustc_middle/src/traits/select.rs b/compiler/rustc_middle/src/traits/select.rs index 62996bf4cb..6720493cd3 100644 --- a/compiler/rustc_middle/src/traits/select.rs +++ b/compiler/rustc_middle/src/traits/select.rs @@ -120,7 +120,9 @@ pub enum SelectionCandidate<'tcx> { /// Implementation of a `Fn`-family trait by one of the anonymous /// types generated for a fn pointer type (e.g., `fn(int) -> int`) - FnPointerCandidate, + FnPointerCandidate { + is_const: bool, + }, /// Builtin implementation of `DiscriminantKind`. DiscriminantKindCandidate, @@ -143,6 +145,9 @@ pub enum SelectionCandidate<'tcx> { BuiltinObjectCandidate, BuiltinUnsizeCandidate, + + /// Implementation of `const Drop`. + ConstDropCandidate, } /// The result of trait evaluation. The order is important @@ -256,12 +261,18 @@ impl EvaluationResult { } } -/// Indicates that trait evaluation caused overflow. +/// Indicates that trait evaluation caused overflow and in which pass. #[derive(Copy, Clone, Debug, PartialEq, Eq, HashStable)] -pub struct OverflowError; +pub enum OverflowError { + Canonical, + ErrorReporting, +} impl<'tcx> From for SelectionError<'tcx> { - fn from(OverflowError: OverflowError) -> SelectionError<'tcx> { - SelectionError::Overflow + fn from(overflow_error: OverflowError) -> SelectionError<'tcx> { + match overflow_error { + OverflowError::Canonical => SelectionError::Overflow, + OverflowError::ErrorReporting => SelectionError::ErrorReporting, + } } } diff --git a/compiler/rustc_middle/src/traits/specialization_graph.rs b/compiler/rustc_middle/src/traits/specialization_graph.rs index cb60bfa4c5..ab47c2a763 100644 --- a/compiler/rustc_middle/src/traits/specialization_graph.rs +++ b/compiler/rustc_middle/src/traits/specialization_graph.rs @@ -1,9 +1,7 @@ -use crate::ich::{self, StableHashingContext}; use crate::ty::fast_reject::SimplifiedType; use crate::ty::fold::TypeFoldable; use crate::ty::{self, TyCtxt}; -use rustc_data_structures::fx::FxHashMap; -use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; +use rustc_data_structures::fx::FxIndexMap; use rustc_errors::ErrorReported; use rustc_hir::def_id::{DefId, DefIdMap}; use rustc_span::symbol::Ident; @@ -50,19 +48,19 @@ impl Graph { /// Children of a given impl, grouped into blanket/non-blanket varieties as is /// done in `TraitDef`. -#[derive(Default, TyEncodable, TyDecodable, Debug)] +#[derive(Default, TyEncodable, TyDecodable, Debug, HashStable)] pub struct Children { // Impls of a trait (or specializations of a given impl). To allow for // quicker lookup, the impls are indexed by a simplified version of their // `Self` type: impls with a simplifiable `Self` are stored in - // `nonblanket_impls` keyed by it, while all other impls are stored in + // `non_blanket_impls` keyed by it, while all other impls are stored in // `blanket_impls`. // // A similar division is used within `TraitDef`, but the lists there collect // together *all* the impls for a trait, and are populated prior to building // the specialization graph. /// Impls of the trait. - pub nonblanket_impls: FxHashMap>, + pub non_blanket_impls: FxIndexMap>, /// Blanket impls associated with the trait. pub blanket_impls: Vec, @@ -235,11 +233,3 @@ pub fn ancestors( }) } } - -impl<'a> HashStable> for Children { - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { - let Children { ref nonblanket_impls, ref blanket_impls } = *self; - - ich::hash_stable_trait_impls(hcx, hasher, blanket_impls, nonblanket_impls); - } -} diff --git a/compiler/rustc_middle/src/traits/structural_impls.rs b/compiler/rustc_middle/src/traits/structural_impls.rs index aa16e14fed..6032004e60 100644 --- a/compiler/rustc_middle/src/traits/structural_impls.rs +++ b/compiler/rustc_middle/src/traits/structural_impls.rs @@ -32,6 +32,8 @@ impl<'tcx, N: fmt::Debug> fmt::Debug for traits::ImplSource<'tcx, N> { super::ImplSource::TraitAlias(ref d) => write!(f, "{:?}", d), super::ImplSource::TraitUpcasting(ref d) => write!(f, "{:?}", d), + + super::ImplSource::ConstDrop(ref d) => write!(f, "{:?}", d), } } } @@ -125,4 +127,5 @@ TrivialTypeFoldableAndLiftImpls! { super::IfExpressionCause, super::ImplSourceDiscriminantKindData, super::ImplSourcePointeeData, + super::ImplSourceConstDropData, } diff --git a/compiler/rustc_middle/src/ty/adt.rs b/compiler/rustc_middle/src/ty/adt.rs index 27927bcca7..44f741c5df 100644 --- a/compiler/rustc_middle/src/ty/adt.rs +++ b/compiler/rustc_middle/src/ty/adt.rs @@ -1,4 +1,3 @@ -use crate::ich::StableHashingContext; use crate::mir::interpret::ErrorHandled; use crate::ty; use crate::ty::util::{Discr, IntTypeExt}; @@ -7,9 +6,11 @@ use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_errors::ErrorReported; +use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::DefId; use rustc_index::vec::{Idx, IndexVec}; +use rustc_query_system::ich::StableHashingContext; use rustc_serialize::{self, Encodable, Encoder}; use rustc_session::DataTypeKind; use rustc_span::symbol::sym; @@ -288,6 +289,10 @@ impl<'tcx> AdtDef { self.destructor(tcx).is_some() } + pub fn has_non_const_dtor(&self, tcx: TyCtxt<'tcx>) -> bool { + matches!(self.destructor(tcx), Some(Destructor { constness: hir::Constness::NotConst, .. })) + } + /// Asserts this is a struct or union and returns its unique variant. pub fn non_enum_variant(&self) -> &VariantDef { assert!(self.is_struct() || self.is_union()); diff --git a/compiler/rustc_middle/src/ty/codec.rs b/compiler/rustc_middle/src/ty/codec.rs index 4edb6a327b..434008ecb1 100644 --- a/compiler/rustc_middle/src/ty/codec.rs +++ b/compiler/rustc_middle/src/ty/codec.rs @@ -1,10 +1,10 @@ -// This module contains some shared code for encoding and decoding various -// things from the `ty` module, and in particular implements support for -// "shorthands" which allow to have pointers back into the already encoded -// stream instead of re-encoding the same thing twice. -// -// The functionality in here is shared between persisting to crate metadata and -// persisting to incr. comp. caches. +//! This module contains some shared code for encoding and decoding various +//! things from the `ty` module, and in particular implements support for +//! "shorthands" which allow to have pointers back into the already encoded +//! stream instead of re-encoding the same thing twice. +//! +//! The functionality in here is shared between persisting to crate metadata and +//! persisting to incr. comp. caches. use crate::arena::ArenaAllocatable; use crate::infer::canonical::{CanonicalVarInfo, CanonicalVarInfos}; @@ -12,6 +12,7 @@ use crate::mir::{ self, interpret::{AllocId, Allocation}, }; +use crate::thir; use crate::ty::subst::SubstsRef; use crate::ty::{self, List, Ty, TyCtxt}; use rustc_data_structures::fx::FxHashMap; @@ -362,7 +363,7 @@ impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for [(ty::Predicate<'tcx>, } } -impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for [mir::abstract_const::Node<'tcx>] { +impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for [thir::abstract_const::Node<'tcx>] { fn decode(decoder: &mut D) -> Result<&'tcx Self, D::Error> { Ok(decoder.tcx().arena.alloc_from_iter( (0..decoder.read_usize()?) @@ -372,7 +373,7 @@ impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for [mir::abstract_const::N } } -impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for [mir::abstract_const::NodeId] { +impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for [thir::abstract_const::NodeId] { fn decode(decoder: &mut D) -> Result<&'tcx Self, D::Error> { Ok(decoder.tcx().arena.alloc_from_iter( (0..decoder.read_usize()?) diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 4def27e42d..83d7c307bd 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1,13 +1,11 @@ //! Type context book-keeping. use crate::arena::Arena; -use crate::dep_graph::{DepGraph, DepNode}; +use crate::dep_graph::DepGraph; use crate::hir::place::Place as HirPlace; -use crate::ich::{NodeIdHashingMode, StableHashingContext}; use crate::infer::canonical::{Canonical, CanonicalVarInfo, CanonicalVarInfos}; use crate::lint::{struct_lint_level, LintDiagnosticBuilder, LintLevelSource}; use crate::middle; -use crate::middle::cstore::EncodedMetadata; use crate::middle::resolve_lifetime::{self, LifetimeScopeForPath, ObjectLifetimeDefault}; use crate::middle::stability; use crate::mir::interpret::{self, Allocation, ConstValue, Scalar}; @@ -27,6 +25,7 @@ use crate::ty::{ use rustc_ast as ast; use rustc_attr as attr; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::memmap::Mmap; use rustc_data_structures::profiling::SelfProfilerRef; use rustc_data_structures::sharded::{IntoPointer, ShardedHashMap}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; @@ -45,6 +44,7 @@ use rustc_hir::{ use rustc_index::vec::{Idx, IndexVec}; use rustc_macros::HashStable; use rustc_middle::mir::FakeReadCause; +use rustc_query_system::ich::{NodeIdHashingMode, StableHashingContext}; use rustc_serialize::opaque::{FileEncodeResult, FileEncoder}; use rustc_session::config::{BorrowckMode, CrateType, OutputFilenames}; use rustc_session::lint::{Level, Lint}; @@ -71,7 +71,7 @@ use std::sync::Arc; pub trait OnDiskCache<'tcx>: rustc_data_structures::sync::Sync { /// Creates a new `OnDiskCache` instance from the serialized data in `data`. - fn new(sess: &'tcx Session, data: Vec, start_pos: usize) -> Self + fn new(sess: &'tcx Session, data: Mmap, start_pos: usize) -> Self where Self: Sized; @@ -82,23 +82,9 @@ pub trait OnDiskCache<'tcx>: rustc_data_structures::sync::Sync { /// Converts a `DefPathHash` to its corresponding `DefId` in the current compilation /// session, if it still exists. This is used during incremental compilation to /// turn a deserialized `DefPathHash` into its current `DefId`. - fn def_path_hash_to_def_id( - &self, - tcx: TyCtxt<'tcx>, - def_path_hash: DefPathHash, - ) -> Option; + fn def_path_hash_to_def_id(&self, tcx: TyCtxt<'tcx>, def_path_hash: DefPathHash) -> DefId; - /// If the given `dep_node`'s hash still exists in the current compilation, - /// and its current `DefId` is foreign, calls `store_foreign_def_id` with it. - /// - /// Normally, `store_foreign_def_id_hash` can be called directly by - /// the dependency graph when we construct a `DepNode`. However, - /// when we re-use a deserialized `DepNode` from the previous compilation - /// session, we only have the `DefPathHash` available. This method is used - /// to that any `DepNode` that we re-use has a `DefPathHash` -> `RawId` written - /// out for usage in the next compilation session. - fn register_reused_dep_node(&self, tcx: TyCtxt<'tcx>, dep_node: &DepNode); - fn store_foreign_def_id_hash(&self, def_id: DefId, hash: DefPathHash); + fn drop_serialized_data(&self, tcx: TyCtxt<'tcx>); fn serialize(&self, tcx: TyCtxt<'tcx>, encoder: &mut FileEncoder) -> FileEncodeResult; } @@ -115,8 +101,8 @@ pub struct CtxtInterners<'tcx> { /// The arena that types, regions, etc. are allocated from. arena: &'tcx WorkerLocal>, - /// Specifically use a speedy hash algorithm for these hash sets, since - /// they're accessed quite often. + // Specifically use a speedy hash algorithm for these hash sets, since + // they're accessed quite often. type_: InternedSet<'tcx, TyS<'tcx>>, type_list: InternedSet<'tcx, List>>, substs: InternedSet<'tcx, InternalSubsts<'tcx>>, @@ -129,9 +115,9 @@ pub struct CtxtInterners<'tcx> { projs: InternedSet<'tcx, List>, place_elems: InternedSet<'tcx, List>>, const_: InternedSet<'tcx, Const<'tcx>>, - /// Const allocations. - allocation: InternedSet<'tcx, Allocation>, + const_allocation: InternedSet<'tcx, Allocation>, bound_variable_kinds: InternedSet<'tcx, List>, + layout: InternedSet<'tcx, Layout>, } impl<'tcx> CtxtInterners<'tcx> { @@ -149,8 +135,9 @@ impl<'tcx> CtxtInterners<'tcx> { projs: Default::default(), place_elems: Default::default(), const_: Default::default(), - allocation: Default::default(), + const_allocation: Default::default(), bound_variable_kinds: Default::default(), + layout: Default::default(), } } @@ -1059,8 +1046,6 @@ pub struct GlobalCtxt<'tcx> { /// Stores memory for globals (statics/consts). pub(crate) alloc_map: Lock>, - layout_interner: ShardedHashMap<&'tcx Layout, ()>, - output_filenames: Arc, } @@ -1101,13 +1086,6 @@ impl<'tcx> TyCtxt<'tcx> { self.arena.alloc(ty::AdtDef::new(self, did, kind, variants, repr)) } - pub fn intern_const_alloc(self, alloc: Allocation) -> &'tcx Allocation { - self.interners - .allocation - .intern(alloc, |alloc| Interned(self.interners.arena.alloc(alloc))) - .0 - } - /// Allocates a read-only byte or string literal for `mir::interpret`. pub fn allocate_bytes(self, bytes: &[u8]) -> interpret::AllocId { // Create an allocation that just contains these bytes. @@ -1116,20 +1094,19 @@ impl<'tcx> TyCtxt<'tcx> { self.create_memory_alloc(alloc) } + // FIXME(eddyb) move to `direct_interners!`. pub fn intern_stability(self, stab: attr::Stability) -> &'tcx attr::Stability { self.stability_interner.intern(stab, |stab| self.arena.alloc(stab)) } + // FIXME(eddyb) move to `direct_interners!`. pub fn intern_const_stability(self, stab: attr::ConstStability) -> &'tcx attr::ConstStability { self.const_stability_interner.intern(stab, |stab| self.arena.alloc(stab)) } - pub fn intern_layout(self, layout: Layout) -> &'tcx Layout { - self.layout_interner.intern(layout, |layout| self.arena.alloc(layout)) - } - /// Returns a range of the start/end indices specified with the /// `rustc_layout_scalar_valid_range` attribute. + // FIXME(eddyb) this is an awkward spot for this method, maybe move it? pub fn layout_scalar_valid_range(self, def_id: DefId) -> (Bound, Bound) { let attrs = self.get_attrs(def_id); let get = |name| { @@ -1204,7 +1181,6 @@ impl<'tcx> TyCtxt<'tcx> { evaluation_cache: Default::default(), crate_name: Symbol::intern(crate_name), data_layout, - layout_interner: Default::default(), stability_interner: Default::default(), const_stability_interner: Default::default(), alloc_map: Lock::new(interpret::AllocMap::new()), @@ -1251,12 +1227,17 @@ impl<'tcx> TyCtxt<'tcx> { /// Obtain the given diagnostic item's `DefId`. Use `is_diagnostic_item` if you just want to /// compare against another `DefId`, since `is_diagnostic_item` is cheaper. pub fn get_diagnostic_item(self, name: Symbol) -> Option { - self.all_diagnostic_items(()).get(&name).copied() + self.all_diagnostic_items(()).name_to_id.get(&name).copied() + } + + /// Obtain the diagnostic item's name + pub fn get_diagnostic_name(self, id: DefId) -> Option { + self.diagnostic_items(id.krate).id_to_name.get(&id).copied() } /// Check whether the diagnostic item with the given `name` has the given `DefId`. pub fn is_diagnostic_item(self, name: Symbol, did: DefId) -> bool { - self.diagnostic_items(did.krate).get(&name) == Some(&did) + self.diagnostic_items(did.krate).name_to_id.get(&name) == Some(&did) } pub fn stability(self) -> &'tcx stability::Index<'tcx> { @@ -1309,6 +1290,17 @@ impl<'tcx> TyCtxt<'tcx> { } } + /// Maps a StableCrateId to the corresponding CrateNum. This method assumes + /// that the crate in question has already been loaded by the CrateStore. + #[inline] + pub fn stable_crate_id_to_crate_num(self, stable_crate_id: StableCrateId) -> CrateNum { + if stable_crate_id == self.sess.local_stable_crate_id() { + LOCAL_CRATE + } else { + self.untracked_resolutions.cstore.stable_crate_id_to_crate_num(stable_crate_id) + } + } + 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!() @@ -1331,11 +1323,6 @@ impl<'tcx> TyCtxt<'tcx> { ) } - pub fn encode_metadata(self) -> EncodedMetadata { - let _prof_timer = self.prof.verbose_generic_activity("generate_crate_metadata"); - self.untracked_resolutions.cstore.encode_metadata(self) - } - /// Note that this is *untracked* and should only be used within the query /// system if the result is otherwise tracked through queries pub fn cstore_untracked(self) -> &'tcx ty::CrateStoreDyn { @@ -1663,7 +1650,7 @@ macro_rules! nop_list_lift { nop_lift! {type_; Ty<'a> => Ty<'tcx>} nop_lift! {region; Region<'a> => Region<'tcx>} nop_lift! {const_; &'a Const<'a> => &'tcx Const<'tcx>} -nop_lift! {allocation; &'a Allocation => &'tcx Allocation} +nop_lift! {const_allocation; &'a Allocation => &'tcx Allocation} nop_lift! {predicate; &'a PredicateInner<'a> => &'tcx PredicateInner<'tcx>} nop_list_lift! {type_list; Ty<'a> => Ty<'tcx>} @@ -1955,8 +1942,12 @@ impl<'tcx> TyCtxt<'tcx> { "Const Stability interner: #{}", self.0.const_stability_interner.len() )?; - writeln!(fmt, "Allocation interner: #{}", self.0.interners.allocation.len())?; - writeln!(fmt, "Layout interner: #{}", self.0.layout_interner.len())?; + writeln!( + fmt, + "Const Allocation interner: #{}", + self.0.interners.const_allocation.len() + )?; + writeln!(fmt, "Layout interner: #{}", self.0.interners.layout.len())?; Ok(()) } @@ -2044,38 +2035,6 @@ impl<'tcx, T> Borrow<[T]> for Interned<'tcx, List> { } } -impl<'tcx> Borrow for Interned<'tcx, RegionKind> { - fn borrow(&self) -> &RegionKind { - &self.0 - } -} - -impl<'tcx> Borrow> for Interned<'tcx, Const<'tcx>> { - fn borrow<'a>(&'a self) -> &'a Const<'tcx> { - &self.0 - } -} - -impl<'tcx> Borrow for Interned<'tcx, Allocation> { - fn borrow<'a>(&'a self) -> &'a Allocation { - &self.0 - } -} - -impl<'tcx> PartialEq for Interned<'tcx, Allocation> { - fn eq(&self, other: &Self) -> bool { - self.0 == other.0 - } -} - -impl<'tcx> Eq for Interned<'tcx, Allocation> {} - -impl<'tcx> Hash for Interned<'tcx, Allocation> { - fn hash(&self, s: &mut H) { - self.0.hash(s) - } -} - macro_rules! direct_interners { ($($name:ident: $method:ident($ty:ty),)+) => { $(impl<'tcx> PartialEq for Interned<'tcx, $ty> { @@ -2092,9 +2051,15 @@ macro_rules! direct_interners { } } + impl<'tcx> Borrow<$ty> for Interned<'tcx, $ty> { + fn borrow<'a>(&'a self) -> &'a $ty { + &self.0 + } + } + impl<'tcx> TyCtxt<'tcx> { pub fn $method(self, v: $ty) -> &'tcx $ty { - self.interners.$name.intern_ref(&v, || { + self.interners.$name.intern(v, |v| { Interned(self.interners.arena.alloc(v)) }).0 } @@ -2105,6 +2070,8 @@ macro_rules! direct_interners { direct_interners! { region: mk_region(RegionKind), const_: mk_const(Const<'tcx>), + const_allocation: intern_const_alloc(Allocation), + layout: intern_layout(Layout), } macro_rules! slice_interners { @@ -2150,7 +2117,7 @@ impl<'tcx> TyCtxt<'tcx> { }) } - /// Computes the def-ids of the transitive super-traits of `trait_def_id`. This (intentionally) + /// Computes the def-ids of the transitive supertraits of `trait_def_id`. This (intentionally) /// does not compute the full elaborated super-predicates but just the set of def-ids. It is used /// to identify which traits may define a given associated type to help avoid cycle errors. /// Returns a `DefId` iterator. @@ -2734,6 +2701,29 @@ impl<'tcx> TyCtxt<'tcx> { pub fn lifetime_scope(self, id: HirId) -> Option { self.lifetime_scope_map(id.owner).and_then(|mut map| map.remove(&id.local_id)) } + + /// Whether the `def_id` counts as const fn in the current crate, considering all active + /// feature gates + pub fn is_const_fn(self, def_id: DefId) -> bool { + if self.is_const_fn_raw(def_id) { + match self.lookup_const_stability(def_id) { + Some(stability) if stability.level.is_unstable() => { + // has a `rustc_const_unstable` attribute, check whether the user enabled the + // corresponding feature gate. + self.features() + .declared_lib_features + .iter() + .any(|&(sym, _)| sym == stability.feature) + } + // functions without const stability are either stable user written + // const fn or the user is using feature gates and we thus don't + // care what they do + _ => true, + } + } else { + false + } + } } impl TyCtxtAt<'tcx> { diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs index 4cfb104bee..092eae0fc5 100644 --- a/compiler/rustc_middle/src/ty/diagnostics.rs +++ b/compiler/rustc_middle/src/ty/diagnostics.rs @@ -2,7 +2,6 @@ use crate::ty::TyKind::*; use crate::ty::{InferTy, TyCtxt, TyS}; -use rustc_data_structures::fx::FxHashSet; use rustc_errors::{Applicability, DiagnosticBuilder}; use rustc_hir as hir; use rustc_hir::def_id::DefId; @@ -114,10 +113,8 @@ fn suggest_removing_unsized_bound( def_id: Option, ) { // See if there's a `?Sized` bound that can be removed to suggest that. - // First look at the `where` clause because we can have `where T: ?Sized`, but that - // `?Sized` bound is *also* included in the `GenericParam` as a bound, which breaks - // the spans. Hence the somewhat involved logic that follows. - let mut where_unsized_bounds = FxHashSet::default(); + // First look at the `where` clause because we can have `where T: ?Sized`, + // then look at params. for (where_pos, predicate) in generics.where_clause.predicates.iter().enumerate() { match predicate { WherePredicate::BoundPredicate(WhereBoundPredicate { @@ -140,7 +137,6 @@ fn suggest_removing_unsized_bound( }) if segment.ident.as_str() == param_name => { for (pos, bound) in bounds.iter().enumerate() { match bound { - hir::GenericBound::Unsized(_) => {} hir::GenericBound::Trait(poly, hir::TraitBoundModifier::Maybe) if poly.trait_ref.trait_def_id() == def_id => {} _ => continue, @@ -173,7 +169,6 @@ fn suggest_removing_unsized_bound( // ^^^^^^^^^ (_, pos, _, _) => bounds[pos - 1].span().shrink_to_hi().to(bound.span()), }; - where_unsized_bounds.insert(bound.span()); err.span_suggestion_verbose( sp, "consider removing the `?Sized` bound to make the \ @@ -189,8 +184,7 @@ fn suggest_removing_unsized_bound( for (pos, bound) in param.bounds.iter().enumerate() { match bound { hir::GenericBound::Trait(poly, hir::TraitBoundModifier::Maybe) - if poly.trait_ref.trait_def_id() == def_id - && !where_unsized_bounds.contains(&bound.span()) => + if poly.trait_ref.trait_def_id() == def_id => { let sp = match (param.bounds.len(), pos) { // T: ?Sized, diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs index 796ca650bd..08b4d3aecd 100644 --- a/compiler/rustc_middle/src/ty/error.rs +++ b/compiler/rustc_middle/src/ty/error.rs @@ -964,7 +964,7 @@ fn foo(&self) -> Self::T { String::new() } { let (span, sugg) = if has_params { let pos = span.hi() - BytePos(1); - let span = Span::new(pos, pos, span.ctxt()); + let span = Span::new(pos, pos, span.ctxt(), span.parent()); (span, format!(", {} = {}", assoc.ident, ty)) } else { let item_args = self.format_generic_args(assoc_substs); diff --git a/compiler/rustc_middle/src/ty/fast_reject.rs b/compiler/rustc_middle/src/ty/fast_reject.rs index 94d75a469d..11ee942b83 100644 --- a/compiler/rustc_middle/src/ty/fast_reject.rs +++ b/compiler/rustc_middle/src/ty/fast_reject.rs @@ -1,7 +1,7 @@ -use crate::ich::StableHashingContext; use crate::ty::{self, Ty, TyCtxt}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_hir::def_id::DefId; +use rustc_query_system::ich::StableHashingContext; use std::fmt::Debug; use std::hash::Hash; use std::mem; diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs index a04b0a7ef6..e16491dcc9 100644 --- a/compiler/rustc_middle/src/ty/fold.rs +++ b/compiler/rustc_middle/src/ty/fold.rs @@ -79,6 +79,7 @@ pub trait TypeFoldable<'tcx>: fmt::Debug + Clone { == Some(FoundFlags) } + #[instrument(level = "trace")] fn has_type_flags(&self, flags: TypeFlags) -> bool { self.visit_with(&mut HasTypeFlagsVisitor { tcx: None, flags }).break_value() == Some(FoundFlags) @@ -476,21 +477,16 @@ impl<'a, 'tcx> TypeFolder<'tcx> for RegionFolder<'a, 'tcx> { t } + #[instrument(skip(self), level = "debug")] fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { match *r { ty::ReLateBound(debruijn, _) if debruijn < self.current_index => { - debug!( - "RegionFolder.fold_region({:?}) skipped bound region (current index={:?})", - r, self.current_index - ); + debug!(?self.current_index, "skipped bound region"); *self.skipped_regions = true; r } _ => { - debug!( - "RegionFolder.fold_region({:?}) folding free region (current_index={:?})", - r, self.current_index - ); + debug!(?self.current_index, "folding free region"); (self.fold_region_fn)(r, self.current_index) } } @@ -1125,6 +1121,12 @@ struct HasTypeFlagsVisitor<'tcx> { flags: ty::TypeFlags, } +impl std::fmt::Debug for HasTypeFlagsVisitor<'tcx> { + fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + self.flags.fmt(fmt) + } +} + impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor<'tcx> { type BreakTy = FoundFlags; fn tcx_for_anon_const_substs(&self) -> Option> { @@ -1132,9 +1134,10 @@ impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor<'tcx> { } #[inline] + #[instrument(level = "trace")] fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { let flags = t.flags(); - debug!("HasTypeFlagsVisitor: t={:?} flags={:?} self.flags={:?}", t, flags, self.flags); + trace!(t.flags=?t.flags()); if flags.intersects(self.flags) { ControlFlow::Break(FoundFlags) } else { @@ -1146,9 +1149,10 @@ impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor<'tcx> { } #[inline] + #[instrument(skip(self), level = "trace")] fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow { let flags = r.type_flags(); - debug!("HasTypeFlagsVisitor: r={:?} r.flags={:?} self.flags={:?}", r, flags, self.flags); + trace!(r.flags=?flags); if flags.intersects(self.flags) { ControlFlow::Break(FoundFlags) } else { @@ -1157,9 +1161,10 @@ impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor<'tcx> { } #[inline] + #[instrument(level = "trace")] fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> ControlFlow { let flags = FlagComputation::for_const(c); - debug!("HasTypeFlagsVisitor: c={:?} c.flags={:?} self.flags={:?}", c, flags, self.flags); + trace!(r.flags=?flags); if flags.intersects(self.flags) { ControlFlow::Break(FoundFlags) } else { @@ -1171,9 +1176,10 @@ impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor<'tcx> { } #[inline] + #[instrument(level = "trace")] fn visit_unevaluated_const(&mut self, uv: ty::Unevaluated<'tcx>) -> ControlFlow { let flags = FlagComputation::for_unevaluated_const(uv); - debug!("HasTypeFlagsVisitor: uv={:?} uv.flags={:?} self.flags={:?}", uv, flags, self.flags); + trace!(r.flags=?flags); if flags.intersects(self.flags) { ControlFlow::Break(FoundFlags) } else { @@ -1185,12 +1191,10 @@ impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor<'tcx> { } #[inline] + #[instrument(level = "trace")] fn visit_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> ControlFlow { let flags = predicate.inner.flags; - debug!( - "HasTypeFlagsVisitor: predicate={:?} flags={:?} self.flags={:?}", - predicate, flags, self.flags - ); + trace!(predicate.flags=?flags); if flags.intersects(self.flags) { ControlFlow::Break(FoundFlags) } else { diff --git a/compiler/rustc_middle/src/ich/impls_ty.rs b/compiler/rustc_middle/src/ty/impls_ty.rs similarity index 78% rename from compiler/rustc_middle/src/ich/impls_ty.rs rename to compiler/rustc_middle/src/ty/impls_ty.rs index 8e53e4ba94..9f47ed89f1 100644 --- a/compiler/rustc_middle/src/ich/impls_ty.rs +++ b/compiler/rustc_middle/src/ty/impls_ty.rs @@ -1,13 +1,13 @@ //! This module contains `HashStable` implementations for various data types //! from `rustc_middle::ty` in no particular order. -use crate::ich::{NodeIdHashingMode, StableHashingContext}; use crate::middle::region; use crate::mir; use crate::ty; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey}; +use rustc_query_system::ich::StableHashingContext; use std::cell::RefCell; use std::mem; @@ -90,7 +90,10 @@ impl<'a> HashStable> for ty::RegionKind { ty::ReFree(ref free_region) => { free_region.hash_stable(hcx, hasher); } - ty::ReVar(..) | ty::RePlaceholder(..) => { + ty::RePlaceholder(p) => { + p.hash_stable(hcx, hasher); + } + ty::ReVar(..) => { bug!("StableHasher: unexpected region {:?}", *self) } } @@ -160,37 +163,3 @@ impl<'a> ToStableHashKey> for region::Scope { *self } } - -impl<'a> HashStable> for ty::TyVid { - fn hash_stable(&self, _hcx: &mut StableHashingContext<'a>, _hasher: &mut StableHasher) { - // `TyVid` values are confined to an inference context and hence - // should not be hashed. - bug!("ty::TyKind::hash_stable() - can't hash a TyVid {:?}.", *self) - } -} - -impl<'a> HashStable> for ty::IntVid { - fn hash_stable(&self, _hcx: &mut StableHashingContext<'a>, _hasher: &mut StableHasher) { - // `IntVid` values are confined to an inference context and hence - // should not be hashed. - bug!("ty::TyKind::hash_stable() - can't hash an IntVid {:?}.", *self) - } -} - -impl<'a> HashStable> for ty::FloatVid { - fn hash_stable(&self, _hcx: &mut StableHashingContext<'a>, _hasher: &mut StableHasher) { - // `FloatVid` values are confined to an inference context and hence - // should not be hashed. - bug!("ty::TyKind::hash_stable() - can't hash a FloatVid {:?}.", *self) - } -} - -impl<'a> HashStable> for crate::middle::privacy::AccessLevels { - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { - hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| { - let crate::middle::privacy::AccessLevels { ref map } = *self; - - map.hash_stable(hcx, hasher); - }); - } -} diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index 261a19f862..4b38105e44 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -77,7 +77,7 @@ pub enum InstanceDef<'tcx> { /// `<[FnMut closure] as FnOnce>::call_once`. /// /// The `DefId` is the ID of the `call_once` method in `FnOnce`. - ClosureOnceShim { call_once: DefId }, + ClosureOnceShim { call_once: DefId, track_caller: bool }, /// `core::ptr::drop_in_place::`. /// @@ -146,12 +146,28 @@ impl<'tcx> InstanceDef<'tcx> { | InstanceDef::FnPtrShim(def_id, _) | InstanceDef::Virtual(def_id, _) | InstanceDef::Intrinsic(def_id) - | InstanceDef::ClosureOnceShim { call_once: def_id } + | InstanceDef::ClosureOnceShim { call_once: def_id, track_caller: _ } | InstanceDef::DropGlue(def_id, _) | InstanceDef::CloneShim(def_id, _) => def_id, } } + /// Returns the `DefId` of instances which might not require codegen locally. + pub fn def_id_if_not_guaranteed_local_codegen(self) -> Option { + match self { + ty::InstanceDef::Item(def) => Some(def.did), + ty::InstanceDef::DropGlue(def_id, Some(_)) => Some(def_id), + InstanceDef::VtableShim(..) + | InstanceDef::ReifyShim(..) + | InstanceDef::FnPtrShim(..) + | InstanceDef::Virtual(..) + | InstanceDef::Intrinsic(..) + | InstanceDef::ClosureOnceShim { .. } + | InstanceDef::DropGlue(..) + | InstanceDef::CloneShim(..) => None, + } + } + #[inline] pub fn with_opt_param(self) -> ty::WithOptConstParam { match self { @@ -161,7 +177,7 @@ impl<'tcx> InstanceDef<'tcx> { | InstanceDef::FnPtrShim(def_id, _) | InstanceDef::Virtual(def_id, _) | InstanceDef::Intrinsic(def_id) - | InstanceDef::ClosureOnceShim { call_once: def_id } + | InstanceDef::ClosureOnceShim { call_once: def_id, track_caller: _ } | InstanceDef::DropGlue(def_id, _) | InstanceDef::CloneShim(def_id, _) => ty::WithOptConstParam::unknown(def_id), } @@ -231,6 +247,7 @@ impl<'tcx> InstanceDef<'tcx> { | InstanceDef::Virtual(def_id, _) => { tcx.codegen_fn_attrs(def_id).flags.contains(CodegenFnAttrFlags::TRACK_CALLER) } + InstanceDef::ClosureOnceShim { call_once: _, track_caller } => track_caller, _ => false, } } @@ -381,6 +398,8 @@ impl<'tcx> Instance<'tcx> { substs: SubstsRef<'tcx>, ) -> Option> { debug!("resolve(def_id={:?}, substs={:?})", def_id, substs); + // Use either `resolve_closure` or `resolve_for_vtable` + assert!(!tcx.is_closure(def_id), "Called `resolve_for_fn_ptr` on closure: {:?}", def_id); Instance::resolve(tcx, param_env, def_id, substs).ok().flatten().map(|mut resolved| { match resolved.def { InstanceDef::Item(def) if resolved.def.requires_caller_location(tcx) => { @@ -442,10 +461,20 @@ impl<'tcx> Instance<'tcx> { }) ) { - debug!( - " => vtable fn pointer created for function with #[track_caller]" - ); - resolved.def = InstanceDef::ReifyShim(def.did); + if tcx.is_closure(def.did) { + debug!(" => vtable fn pointer created for closure with #[track_caller]: {:?} for method {:?} {:?}", + def.did, def_id, substs); + + // Create a shim for the `FnOnce/FnMut/Fn` method we are calling + // - unlike functions, invoking a closure always goes through a + // trait. + resolved = Instance { def: InstanceDef::ReifyShim(def_id), substs }; + } else { + debug!( + " => vtable fn pointer created for function with #[track_caller]: {:?}", def.did + ); + resolved.def = InstanceDef::ReifyShim(def.did); + } } } InstanceDef::Virtual(def_id, _) => { @@ -493,7 +522,9 @@ impl<'tcx> Instance<'tcx> { .find(|it| it.kind == ty::AssocKind::Fn) .unwrap() .def_id; - let def = ty::InstanceDef::ClosureOnceShim { call_once }; + let track_caller = + tcx.codegen_fn_attrs(closure_did).flags.contains(CodegenFnAttrFlags::TRACK_CALLER); + let def = ty::InstanceDef::ClosureOnceShim { call_once, track_caller }; let self_ty = tcx.mk_closure(closure_did, substs); @@ -552,29 +583,26 @@ impl<'tcx> Instance<'tcx> { return self; } - if let InstanceDef::Item(def) = self.def { - let polymorphized_substs = polymorphize(tcx, def.did, self.substs); - debug!("polymorphize: self={:?} polymorphized_substs={:?}", self, polymorphized_substs); - Self { def: self.def, substs: polymorphized_substs } - } else { - self - } + let polymorphized_substs = polymorphize(tcx, self.def, self.substs); + debug!("polymorphize: self={:?} polymorphized_substs={:?}", self, polymorphized_substs); + Self { def: self.def, substs: polymorphized_substs } } } fn polymorphize<'tcx>( tcx: TyCtxt<'tcx>, - def_id: DefId, + instance: ty::InstanceDef<'tcx>, substs: SubstsRef<'tcx>, ) -> SubstsRef<'tcx> { - debug!("polymorphize({:?}, {:?})", def_id, substs); - let unused = tcx.unused_generic_params(def_id); + debug!("polymorphize({:?}, {:?})", instance, substs); + let unused = tcx.unused_generic_params(instance); debug!("polymorphize: unused={:?}", unused); // If this is a closure or generator then we need to handle the case where another closure // from the function is captured as an upvar and hasn't been polymorphized. In this case, // the unpolymorphized upvar closure would result in a polymorphized closure producing // multiple mono items (and eventually symbol clashes). + let def_id = instance.def_id(); let upvars_ty = if tcx.is_closure(def_id) { Some(substs.as_closure().tupled_upvars_ty()) } else if tcx.type_of(def_id).is_generator() { @@ -598,7 +626,11 @@ fn polymorphize<'tcx>( debug!("fold_ty: ty={:?}", ty); match ty.kind { ty::Closure(def_id, substs) => { - let polymorphized_substs = polymorphize(self.tcx, def_id, substs); + let polymorphized_substs = polymorphize( + self.tcx, + ty::InstanceDef::Item(ty::WithOptConstParam::unknown(def_id)), + substs, + ); if substs == polymorphized_substs { ty } else { @@ -606,7 +638,11 @@ fn polymorphize<'tcx>( } } ty::Generator(def_id, substs, movability) => { - let polymorphized_substs = polymorphize(self.tcx, def_id, substs); + let polymorphized_substs = polymorphize( + self.tcx, + ty::InstanceDef::Item(ty::WithOptConstParam::unknown(def_id)), + substs, + ); if substs == polymorphized_substs { ty } else { diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 5e5902abe6..d0c7379c2d 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -1,32 +1,36 @@ -use crate::ich::StableHashingContext; use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags; use crate::mir::{GeneratorLayout, GeneratorSavedLocal}; use crate::ty::subst::Subst; use crate::ty::{self, subst::SubstsRef, ReprOptions, Ty, TyCtxt, TypeFoldable}; - use rustc_ast as ast; use rustc_attr as attr; -use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_hir as hir; use rustc_hir::lang_items::LangItem; use rustc_index::bit_set::BitSet; use rustc_index::vec::{Idx, IndexVec}; use rustc_session::{config::OptLevel, DataTypeKind, FieldInfo, SizeKind, VariantInfo}; use rustc_span::symbol::{Ident, Symbol}; -use rustc_span::DUMMY_SP; +use rustc_span::{Span, DUMMY_SP}; use rustc_target::abi::call::{ ArgAbi, ArgAttribute, ArgAttributes, ArgExtension, Conv, FnAbi, PassMode, Reg, RegKind, }; use rustc_target::abi::*; -use rustc_target::spec::{abi::Abi as SpecAbi, HasTargetSpec, PanicStrategy}; +use rustc_target::spec::{abi::Abi as SpecAbi, HasTargetSpec, PanicStrategy, Target}; use std::cmp; use std::fmt; use std::iter; -use std::mem; use std::num::NonZeroUsize; use std::ops::Bound; +use rand::{seq::SliceRandom, SeedableRng}; +use rand_xoshiro::Xoshiro128StarStar; + +pub fn provide(providers: &mut ty::query::Providers) { + *providers = + ty::query::Providers { layout_of, fn_abi_of_fn_ptr, fn_abi_of_instance, ..*providers }; +} + pub trait IntegerExt { fn to_ty<'tcx>(&self, tcx: TyCtxt<'tcx>, signed: bool) -> Ty<'tcx>; fn from_attr(cx: &C, ity: attr::IntType) -> Integer; @@ -191,7 +195,7 @@ pub const FAT_PTR_EXTRA: usize = 1; /// * Cranelift stores the base-2 log of the lane count in a 4 bit integer. pub const MAX_SIMD_LANES: u64 = 1 << 0xF; -#[derive(Copy, Clone, Debug, TyEncodable, TyDecodable)] +#[derive(Copy, Clone, Debug, HashStable, TyEncodable, TyDecodable)] pub enum LayoutError<'tcx> { Unknown(Ty<'tcx>), SizeOverflow(Ty<'tcx>), @@ -248,10 +252,6 @@ fn layout_of<'tcx>( }) } -pub fn provide(providers: &mut ty::query::Providers) { - *providers = ty::query::Providers { layout_of, ..*providers }; -} - pub struct LayoutCx<'tcx, C> { pub tcx: C, pub param_env: ty::ParamEnv<'tcx>, @@ -290,9 +290,9 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { // HACK(nox): We iter on `b` and then `a` because `max_by_key` // returns the last maximum. - let largest_niche = Niche::from_scalar(dl, b_offset, b.clone()) + let largest_niche = Niche::from_scalar(dl, b_offset, b) .into_iter() - .chain(Niche::from_scalar(dl, Size::ZERO, a.clone())) + .chain(Niche::from_scalar(dl, Size::ZERO, a)) .max_by_key(|niche| niche.available(dl)); Layout { @@ -326,6 +326,10 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { let mut inverse_memory_index: Vec = (0..fields.len() as u32).collect(); + // `ReprOptions.layout_seed` is a deterministic seed that we can use to + // randomize field ordering with + let mut rng = Xoshiro128StarStar::seed_from_u64(repr.field_shuffle_seed); + let optimize = !repr.inhibit_struct_field_reordering_opt(); if optimize { let end = @@ -334,20 +338,35 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { let field_align = |f: &TyAndLayout<'_>| { if let Some(pack) = pack { f.align.abi.min(pack) } else { f.align.abi } }; - match kind { - StructKind::AlwaysSized | StructKind::MaybeUnsized => { - optimizing.sort_by_key(|&x| { - // Place ZSTs first to avoid "interesting offsets", - // especially with only one or two non-ZST fields. - let f = &fields[x as usize]; - (!f.is_zst(), cmp::Reverse(field_align(f))) - }); - } - StructKind::Prefixed(..) => { - // Sort in ascending alignment so that the layout stay optimal - // regardless of the prefix - optimizing.sort_by_key(|&x| field_align(&fields[x as usize])); + + // If `-Z randomize-layout` was enabled for the type definition we can shuffle + // the field ordering to try and catch some code making assumptions about layouts + // we don't guarantee + if repr.can_randomize_type_layout() { + // Shuffle the ordering of the fields + optimizing.shuffle(&mut rng); + + // Otherwise we just leave things alone and actually optimize the type's fields + } else { + match kind { + StructKind::AlwaysSized | StructKind::MaybeUnsized => { + optimizing.sort_by_key(|&x| { + // Place ZSTs first to avoid "interesting offsets", + // especially with only one or two non-ZST fields. + let f = &fields[x as usize]; + (!f.is_zst(), cmp::Reverse(field_align(f))) + }); + } + + StructKind::Prefixed(..) => { + // Sort in ascending alignment so that the layout stays optimal + // regardless of the prefix + optimizing.sort_by_key(|&x| field_align(&fields[x as usize])); + } } + + // FIXME(Kixiron): We can always shuffle fields within a given alignment class + // regardless of the status of `-Z randomize-layout` } } @@ -401,7 +420,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { offsets[i as usize] = offset; if !repr.hide_niche() { - if let Some(mut niche) = field.largest_niche.clone() { + if let Some(mut niche) = field.largest_niche { let available = niche.available(dl); if available > largest_niche_available { largest_niche_available = available; @@ -449,12 +468,12 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { // For plain scalars, or vectors of them, we can't unpack // newtypes for `#[repr(C)]`, as that affects C ABIs. Abi::Scalar(_) | Abi::Vector { .. } if optimize => { - abi = field.abi.clone(); + abi = field.abi; } // But scalar pairs are Rust-specific and get // treated as aggregates by C ABIs anyway. Abi::ScalarPair(..) => { - abi = field.abi.clone(); + abi = field.abi; } _ => {} } @@ -463,14 +482,14 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { // Two non-ZST fields, and they're both scalars. ( - Some((i, &TyAndLayout { layout: &Layout { abi: Abi::Scalar(ref a), .. }, .. })), - Some((j, &TyAndLayout { layout: &Layout { abi: Abi::Scalar(ref b), .. }, .. })), + Some((i, &TyAndLayout { layout: &Layout { abi: Abi::Scalar(a), .. }, .. })), + Some((j, &TyAndLayout { layout: &Layout { abi: Abi::Scalar(b), .. }, .. })), None, ) => { // Order by the memory placement, not source order. let ((i, a), (j, b)) = if offsets[i] < offsets[j] { ((i, a), (j, b)) } else { ((j, b), (i, a)) }; - let pair = self.scalar_pair(a.clone(), b.clone()); + let pair = self.scalar_pair(a, b); let pair_offsets = match pair.fields { FieldsShape::Arbitrary { ref offsets, ref memory_index } => { assert_eq!(memory_index, &[0, 1]); @@ -512,9 +531,9 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { let param_env = self.param_env; let dl = self.data_layout(); let scalar_unit = |value: Primitive| { - let bits = value.size(dl).bits(); - assert!(bits <= 128); - Scalar { value, valid_range: WrappingRange { start: 0, end: (!0 >> (128 - bits)) } } + let size = value.size(dl); + assert!(size.bits() <= 128); + Scalar { value, valid_range: WrappingRange { start: 0, end: size.unsigned_int_max() } } }; let scalar = |value: Primitive| tcx.intern_layout(Layout::scalar(self, scalar_unit(value))); @@ -609,7 +628,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { Abi::Aggregate { sized: true } }; - let largest_niche = if count != 0 { element.largest_niche.clone() } else { None }; + let largest_niche = if count != 0 { element.largest_niche } else { None }; tcx.intern_layout(Layout { variants: Variants::Single { index: VariantIdx::new(0) }, @@ -768,8 +787,8 @@ 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(ref scalar) = e_ly.abi { - scalar.clone() + let e_abi = if let Abi::Scalar(scalar) = e_ly.abi { + scalar } else { // This error isn't caught in typeck, e.g., if // the element type of the vector is generic. @@ -796,7 +815,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { variants: Variants::Single { index: VariantIdx::new(0) }, fields, abi: Abi::Vector { element: e_abi, count: e_len }, - largest_niche: e_ly.largest_niche.clone(), + largest_niche: e_ly.largest_niche, size, align, }) @@ -843,13 +862,13 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { // If all non-ZST fields have the same ABI, forward this ABI if optimize && !field.is_zst() { // Normalize scalar_unit to the maximal valid range - let field_abi = match &field.abi { + let field_abi = match field.abi { Abi::Scalar(x) => Abi::Scalar(scalar_unit(x.value)), Abi::ScalarPair(x, y) => { Abi::ScalarPair(scalar_unit(x.value), scalar_unit(y.value)) } Abi::Vector { element: x, count } => { - Abi::Vector { element: scalar_unit(x.value), count: *count } + Abi::Vector { element: scalar_unit(x.value), count } } Abi::Uninhabited | Abi::Aggregate { .. } => { Abi::Aggregate { sized: true } @@ -967,10 +986,10 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { let niche = if def.repr.hide_niche() { None } else { - Niche::from_scalar(dl, Size::ZERO, scalar.clone()) + Niche::from_scalar(dl, Size::ZERO, *scalar) }; if let Some(niche) = niche { - match &st.largest_niche { + match st.largest_niche { Some(largest_niche) => { // Replace the existing niche even if they're equal, // because this one is at a lower offset. @@ -1045,7 +1064,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { let niche_candidate = variants[i] .iter() .enumerate() - .filter_map(|(j, &field)| Some((j, field.largest_niche.as_ref()?))) + .filter_map(|(j, field)| Some((j, field.largest_niche?))) .max_by_key(|(_, niche)| niche.available(dl)); if let Some((field_index, niche, (niche_start, niche_scalar))) = @@ -1078,31 +1097,24 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { Abi::Uninhabited } else { match st[i].abi { - Abi::Scalar(_) => Abi::Scalar(niche_scalar.clone()), - Abi::ScalarPair(ref first, ref second) => { + Abi::Scalar(_) => Abi::Scalar(niche_scalar), + Abi::ScalarPair(first, second) => { // We need to use scalar_unit to reset the // valid range to the maximal one for that // primitive, because only the niche is // guaranteed to be initialised, not the // other primitive. if offset.bytes() == 0 { - Abi::ScalarPair( - niche_scalar.clone(), - scalar_unit(second.value), - ) + Abi::ScalarPair(niche_scalar, scalar_unit(second.value)) } else { - Abi::ScalarPair( - scalar_unit(first.value), - niche_scalar.clone(), - ) + Abi::ScalarPair(scalar_unit(first.value), niche_scalar) } } _ => Abi::Aggregate { sized: true }, } }; - let largest_niche = - Niche::from_scalar(dl, offset, niche_scalar.clone()); + let largest_niche = Niche::from_scalar(dl, offset, niche_scalar); niche_filling_layout = Some(Layout { variants: Variants::Multiple { @@ -1273,7 +1285,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { } } - let tag_mask = !0u128 >> (128 - ity.size().bits()); + let tag_mask = ity.size().unsigned_int_max(); let tag = Scalar { value: Int(ity, signed), valid_range: WrappingRange { @@ -1283,7 +1295,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { }; let mut abi = Abi::Aggregate { sized: true }; if tag.value.size(dl) == size { - abi = Abi::Scalar(tag.clone()); + abi = Abi::Scalar(tag); } else { // Try to use a ScalarPair for all tagged enums. let mut common_prim = None; @@ -1303,7 +1315,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { } }; let prim = match field.abi { - Abi::Scalar(ref scalar) => scalar.value, + Abi::Scalar(scalar) => scalar.value, _ => { common_prim = None; break; @@ -1323,7 +1335,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { } } if let Some((prim, offset)) = common_prim { - let pair = self.scalar_pair(tag.clone(), scalar_unit(prim)); + let pair = self.scalar_pair(tag, scalar_unit(prim)); let pair_offsets = match pair.fields { FieldsShape::Arbitrary { ref offsets, ref memory_index } => { assert_eq!(memory_index, &[0, 1]); @@ -1347,7 +1359,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { abi = Abi::Uninhabited; } - let largest_niche = Niche::from_scalar(dl, Size::ZERO, tag.clone()); + let largest_niche = Niche::from_scalar(dl, Size::ZERO, tag); let tagged_layout = Layout { variants: Variants::Multiple { @@ -1372,8 +1384,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { // pick the layout with the larger niche; otherwise, // pick tagged as it has simpler codegen. cmp::min_by_key(tagged_layout, niche_filling_layout, |layout| { - let niche_size = - layout.largest_niche.as_ref().map_or(0, |n| n.available(dl)); + let niche_size = layout.largest_niche.map_or(0, |n| n.available(dl)); (layout.size, cmp::Reverse(niche_size)) }) } @@ -1560,7 +1571,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { value: Primitive::Int(discr_int, false), valid_range: WrappingRange { start: 0, end: max_discr }, }; - let tag_layout = self.tcx.intern_layout(Layout::scalar(self, tag.clone())); + let tag_layout = self.tcx.intern_layout(Layout::scalar(self, tag)); let tag_layout = TyAndLayout { ty: discr_int_ty, layout: tag_layout }; let promoted_layouts = ineligible_locals @@ -1815,8 +1826,11 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { match layout.variants { Variants::Single { index } => { - debug!("print-type-size `{:#?}` variant {}", layout, adt_def.variants[index].ident); - if !adt_def.variants.is_empty() { + if !adt_def.variants.is_empty() && layout.fields != FieldsShape::Primitive { + debug!( + "print-type-size `{:#?}` variant {}", + layout, adt_def.variants[index].ident + ); let variant_def = &adt_def.variants[index]; let fields: Vec<_> = variant_def.fields.iter().map(|f| f.ident.name).collect(); record( @@ -1832,7 +1846,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { } } - Variants::Multiple { ref tag, ref tag_encoding, .. } => { + Variants::Multiple { tag, ref tag_encoding, .. } => { debug!( "print-type-size `{:#?}` adt general variants def {}", layout.ty, @@ -2023,6 +2037,12 @@ impl<'tcx> HasDataLayout for TyCtxt<'tcx> { } } +impl<'tcx> HasTargetSpec for TyCtxt<'tcx> { + fn target_spec(&self) -> &Target { + &self.sess.target + } +} + impl<'tcx> HasTyCtxt<'tcx> for TyCtxt<'tcx> { #[inline] fn tcx(&self) -> TyCtxt<'tcx> { @@ -2037,6 +2057,12 @@ impl<'tcx> HasDataLayout for ty::query::TyCtxtAt<'tcx> { } } +impl<'tcx> HasTargetSpec for ty::query::TyCtxtAt<'tcx> { + fn target_spec(&self) -> &Target { + &self.sess.target + } +} + impl<'tcx> HasTyCtxt<'tcx> for ty::query::TyCtxtAt<'tcx> { #[inline] fn tcx(&self) -> TyCtxt<'tcx> { @@ -2056,35 +2082,125 @@ impl<'tcx, T: HasDataLayout> HasDataLayout for LayoutCx<'tcx, T> { } } +impl<'tcx, T: HasTargetSpec> HasTargetSpec for LayoutCx<'tcx, T> { + fn target_spec(&self) -> &Target { + self.tcx.target_spec() + } +} + impl<'tcx, T: HasTyCtxt<'tcx>> HasTyCtxt<'tcx> for LayoutCx<'tcx, T> { fn tcx(&self) -> TyCtxt<'tcx> { self.tcx.tcx() } } -pub type TyAndLayout<'tcx> = rustc_target::abi::TyAndLayout<'tcx, Ty<'tcx>>; +pub trait MaybeResult { + type Error; -impl LayoutOf<'tcx> for LayoutCx<'tcx, TyCtxt<'tcx>> { - type Ty = Ty<'tcx>; - type TyAndLayout = Result, LayoutError<'tcx>>; + fn from(x: Result) -> Self; + fn to_result(self) -> Result; +} - /// Computes the layout of a type. Note that this implicitly - /// executes in "reveal all" mode, and will normalize the input type. - #[inline] - fn layout_of(&self, ty: Ty<'tcx>) -> Self::TyAndLayout { - self.tcx.layout_of(self.param_env.and(ty)) +impl MaybeResult for T { + type Error = !; + + fn from(Ok(x): Result) -> Self { + x + } + fn to_result(self) -> Result { + Ok(self) } } -impl LayoutOf<'tcx> for LayoutCx<'tcx, ty::query::TyCtxtAt<'tcx>> { - type Ty = Ty<'tcx>; - type TyAndLayout = Result, LayoutError<'tcx>>; +impl MaybeResult for Result { + type Error = E; + fn from(x: Result) -> Self { + x + } + fn to_result(self) -> Result { + self + } +} + +pub type TyAndLayout<'tcx> = rustc_target::abi::TyAndLayout<'tcx, Ty<'tcx>>; + +/// Trait for contexts that want to be able to compute layouts of types. +/// This automatically gives access to `LayoutOf`, through a blanket `impl`. +pub trait LayoutOfHelpers<'tcx>: HasDataLayout + HasTyCtxt<'tcx> + HasParamEnv<'tcx> { + /// The `TyAndLayout`-wrapping type (or `TyAndLayout` itself), which will be + /// returned from `layout_of` (see also `handle_layout_err`). + type LayoutOfResult: MaybeResult>; + + /// `Span` to use for `tcx.at(span)`, from `layout_of`. + // FIXME(eddyb) perhaps make this mandatory to get contexts to track it better? + #[inline] + fn layout_tcx_at_span(&self) -> Span { + DUMMY_SP + } + + /// Helper used for `layout_of`, to adapt `tcx.layout_of(...)` into a + /// `Self::LayoutOfResult` (which does not need to be a `Result<...>`). + /// + /// Most `impl`s, which propagate `LayoutError`s, should simply return `err`, + /// but this hook allows e.g. codegen to return only `TyAndLayout` from its + /// `cx.layout_of(...)`, without any `Result<...>` around it to deal with + /// (and any `LayoutError`s are turned into fatal errors or ICEs). + fn handle_layout_err( + &self, + err: LayoutError<'tcx>, + span: Span, + ty: Ty<'tcx>, + ) -> >>::Error; +} + +/// Blanket extension trait for contexts that can compute layouts of types. +pub trait LayoutOf<'tcx>: LayoutOfHelpers<'tcx> { /// Computes the layout of a type. Note that this implicitly /// executes in "reveal all" mode, and will normalize the input type. #[inline] - fn layout_of(&self, ty: Ty<'tcx>) -> Self::TyAndLayout { - self.tcx.layout_of(self.param_env.and(ty)) + fn layout_of(&self, ty: Ty<'tcx>) -> Self::LayoutOfResult { + self.spanned_layout_of(ty, DUMMY_SP) + } + + /// Computes the layout of a type, at `span`. Note that this implicitly + /// executes in "reveal all" mode, and will normalize the input type. + // FIXME(eddyb) avoid passing information like this, and instead add more + // `TyCtxt::at`-like APIs to be able to do e.g. `cx.at(span).layout_of(ty)`. + #[inline] + fn spanned_layout_of(&self, ty: Ty<'tcx>, span: Span) -> Self::LayoutOfResult { + let span = if !span.is_dummy() { span } else { self.layout_tcx_at_span() }; + let tcx = self.tcx().at(span); + + MaybeResult::from( + tcx.layout_of(self.param_env().and(ty)) + .map_err(|err| self.handle_layout_err(err, span, ty)), + ) + } +} + +impl> LayoutOf<'tcx> for C {} + +impl LayoutOfHelpers<'tcx> for LayoutCx<'tcx, TyCtxt<'tcx>> { + type LayoutOfResult = Result, LayoutError<'tcx>>; + + #[inline] + fn handle_layout_err(&self, err: LayoutError<'tcx>, _: Span, _: Ty<'tcx>) -> LayoutError<'tcx> { + err + } +} + +impl LayoutOfHelpers<'tcx> for LayoutCx<'tcx, ty::query::TyCtxtAt<'tcx>> { + type LayoutOfResult = Result, LayoutError<'tcx>>; + + #[inline] + fn layout_tcx_at_span(&self) -> Span { + self.tcx.span + } + + #[inline] + fn handle_layout_err(&self, err: LayoutError<'tcx>, _: Span, _: Ty<'tcx>) -> LayoutError<'tcx> { + err } } @@ -2156,8 +2272,8 @@ where i: usize, ) -> TyMaybeWithLayout<'tcx> { let tcx = cx.tcx(); - let tag_layout = |tag: &Scalar| -> TyAndLayout<'tcx> { - let layout = Layout::scalar(cx, tag.clone()); + let tag_layout = |tag: Scalar| -> TyAndLayout<'tcx> { + let layout = Layout::scalar(cx, tag); TyAndLayout { layout: tcx.intern_layout(layout), ty: tag.value.to_ty(tcx) } }; @@ -2245,7 +2361,7 @@ where .nth(i) .unwrap(), ), - Variants::Multiple { ref tag, tag_field, .. } => { + Variants::Multiple { tag, tag_field, .. } => { if i == tag_field { return TyMaybeWithLayout::TyAndLayout(tag_layout(tag)); } @@ -2263,7 +2379,7 @@ where } // Discriminant field for enums (where applicable). - Variants::Multiple { ref tag, .. } => { + Variants::Multiple { tag, .. } => { assert_eq!(i, 0); return TyMaybeWithLayout::TyAndLayout(tag_layout(tag)); } @@ -2443,24 +2559,12 @@ where } } -impl<'a, 'tcx> HashStable> for LayoutError<'tcx> { - #[inline] - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { - use crate::ty::layout::LayoutError::*; - mem::discriminant(self).hash_stable(hcx, hasher); - - match *self { - Unknown(t) | SizeOverflow(t) => t.hash_stable(hcx, hasher), - } - } -} - impl<'tcx> ty::Instance<'tcx> { // NOTE(eddyb) this is private to avoid using it from outside of - // `FnAbi::of_instance` - any other uses are either too high-level + // `fn_abi_of_instance` - any other uses are either too high-level // for `Instance` (e.g. typeck would use `Ty::fn_sig` instead), // or should go through `FnAbi` instead, to avoid losing any - // adjustments `FnAbi::of_instance` might be performing. + // adjustments `fn_abi_of_instance` might be performing. fn fn_sig_for_fn_abi(&self, tcx: TyCtxt<'tcx>) -> ty::PolyFnSig<'tcx> { // FIXME(davidtwco,eddyb): A `ParamEnv` should be passed through to this function. let ty = self.ty(tcx, ty::ParamEnv::reveal_all()); @@ -2557,38 +2661,6 @@ impl<'tcx> ty::Instance<'tcx> { } } -pub trait FnAbiExt<'tcx, C> -where - C: LayoutOf<'tcx, Ty = Ty<'tcx>, TyAndLayout = TyAndLayout<'tcx>> - + HasDataLayout - + HasTargetSpec - + HasTyCtxt<'tcx> - + HasParamEnv<'tcx>, -{ - /// Compute a `FnAbi` suitable for indirect calls, i.e. to `fn` pointers. - /// - /// NB: this doesn't handle virtual calls - those should use `FnAbi::of_instance` - /// instead, where the instance is an `InstanceDef::Virtual`. - fn of_fn_ptr(cx: &C, sig: ty::PolyFnSig<'tcx>, extra_args: &[Ty<'tcx>]) -> Self; - - /// Compute a `FnAbi` suitable for declaring/defining an `fn` instance, and for - /// direct calls to an `fn`. - /// - /// NB: that includes virtual calls, which are represented by "direct calls" - /// to an `InstanceDef::Virtual` instance (of `::fn`). - fn of_instance(cx: &C, instance: ty::Instance<'tcx>, extra_args: &[Ty<'tcx>]) -> Self; - - fn new_internal( - cx: &C, - sig: ty::PolyFnSig<'tcx>, - extra_args: &[Ty<'tcx>], - caller_location: Option>, - codegen_fn_attr_flags: CodegenFnAttrFlags, - make_self_ptr_thin: bool, - ) -> Self; - fn adjust_for_abi(&mut self, cx: &C, abi: SpecAbi); -} - /// Calculates whether a function's ABI can unwind or not. /// /// This takes two primary parameters: @@ -2744,52 +2816,175 @@ pub fn conv_from_spec_abi(tcx: TyCtxt<'_>, abi: SpecAbi) -> Conv { } } -impl<'tcx, C> FnAbiExt<'tcx, C> for call::FnAbi<'tcx, Ty<'tcx>> -where - C: LayoutOf<'tcx, Ty = Ty<'tcx>, TyAndLayout = TyAndLayout<'tcx>> - + HasDataLayout - + HasTargetSpec - + HasTyCtxt<'tcx> - + HasParamEnv<'tcx>, -{ - fn of_fn_ptr(cx: &C, sig: ty::PolyFnSig<'tcx>, extra_args: &[Ty<'tcx>]) -> Self { - call::FnAbi::new_internal(cx, sig, extra_args, None, CodegenFnAttrFlags::empty(), false) +/// Error produced by attempting to compute or adjust a `FnAbi`. +#[derive(Clone, Debug, HashStable)] +pub enum FnAbiError<'tcx> { + /// Error produced by a `layout_of` call, while computing `FnAbi` initially. + Layout(LayoutError<'tcx>), + + /// Error produced by attempting to adjust a `FnAbi`, for a "foreign" ABI. + AdjustForForeignAbi(call::AdjustForForeignAbiError), +} + +impl From> for FnAbiError<'tcx> { + fn from(err: LayoutError<'tcx>) -> Self { + Self::Layout(err) + } +} + +impl From for FnAbiError<'_> { + fn from(err: call::AdjustForForeignAbiError) -> Self { + Self::AdjustForForeignAbi(err) + } +} + +impl<'tcx> fmt::Display for FnAbiError<'tcx> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::Layout(err) => err.fmt(f), + Self::AdjustForForeignAbi(err) => err.fmt(f), + } + } +} + +// FIXME(eddyb) maybe use something like this for an unified `fn_abi_of`, not +// just for error handling. +#[derive(Debug)] +pub enum FnAbiRequest<'tcx> { + OfFnPtr { sig: ty::PolyFnSig<'tcx>, extra_args: &'tcx ty::List> }, + OfInstance { instance: ty::Instance<'tcx>, extra_args: &'tcx ty::List> }, +} + +/// Trait for contexts that want to be able to compute `FnAbi`s. +/// This automatically gives access to `FnAbiOf`, through a blanket `impl`. +pub trait FnAbiOfHelpers<'tcx>: LayoutOfHelpers<'tcx> { + /// The `&FnAbi`-wrapping type (or `&FnAbi` itself), which will be + /// returned from `fn_abi_of_*` (see also `handle_fn_abi_err`). + type FnAbiOfResult: MaybeResult<&'tcx FnAbi<'tcx, Ty<'tcx>>>; + + /// Helper used for `fn_abi_of_*`, to adapt `tcx.fn_abi_of_*(...)` into a + /// `Self::FnAbiOfResult` (which does not need to be a `Result<...>`). + /// + /// Most `impl`s, which propagate `FnAbiError`s, should simply return `err`, + /// but this hook allows e.g. codegen to return only `&FnAbi` from its + /// `cx.fn_abi_of_*(...)`, without any `Result<...>` around it to deal with + /// (and any `FnAbiError`s are turned into fatal errors or ICEs). + fn handle_fn_abi_err( + &self, + err: FnAbiError<'tcx>, + span: Span, + fn_abi_request: FnAbiRequest<'tcx>, + ) -> >>>::Error; +} + +/// Blanket extension trait for contexts that can compute `FnAbi`s. +pub trait FnAbiOf<'tcx>: FnAbiOfHelpers<'tcx> { + /// Compute a `FnAbi` suitable for indirect calls, i.e. to `fn` pointers. + /// + /// NB: this doesn't handle virtual calls - those should use `fn_abi_of_instance` + /// instead, where the instance is an `InstanceDef::Virtual`. + #[inline] + fn fn_abi_of_fn_ptr( + &self, + sig: ty::PolyFnSig<'tcx>, + extra_args: &'tcx ty::List>, + ) -> Self::FnAbiOfResult { + // FIXME(eddyb) get a better `span` here. + let span = self.layout_tcx_at_span(); + let tcx = self.tcx().at(span); + + MaybeResult::from(tcx.fn_abi_of_fn_ptr(self.param_env().and((sig, extra_args))).map_err( + |err| self.handle_fn_abi_err(err, span, FnAbiRequest::OfFnPtr { sig, extra_args }), + )) } - fn of_instance(cx: &C, instance: ty::Instance<'tcx>, extra_args: &[Ty<'tcx>]) -> Self { - let sig = instance.fn_sig_for_fn_abi(cx.tcx()); + /// Compute a `FnAbi` suitable for declaring/defining an `fn` instance, and for + /// direct calls to an `fn`. + /// + /// NB: that includes virtual calls, which are represented by "direct calls" + /// to an `InstanceDef::Virtual` instance (of `::fn`). + #[inline] + fn fn_abi_of_instance( + &self, + instance: ty::Instance<'tcx>, + extra_args: &'tcx ty::List>, + ) -> Self::FnAbiOfResult { + // FIXME(eddyb) get a better `span` here. + let span = self.layout_tcx_at_span(); + let tcx = self.tcx().at(span); - let caller_location = if instance.def.requires_caller_location(cx.tcx()) { - Some(cx.tcx().caller_location_ty()) - } else { - None - }; - - let attrs = cx.tcx().codegen_fn_attrs(instance.def_id()).flags; - - call::FnAbi::new_internal( - cx, - sig, - extra_args, - caller_location, - attrs, - matches!(instance.def, ty::InstanceDef::Virtual(..)), + MaybeResult::from( + tcx.fn_abi_of_instance(self.param_env().and((instance, extra_args))).map_err(|err| { + // HACK(eddyb) at least for definitions of/calls to `Instance`s, + // we can get some kind of span even if one wasn't provided. + // However, we don't do this early in order to avoid calling + // `def_span` unconditionally (which may have a perf penalty). + let span = if !span.is_dummy() { span } else { tcx.def_span(instance.def_id()) }; + self.handle_fn_abi_err(err, span, FnAbiRequest::OfInstance { instance, extra_args }) + }), ) } +} - fn new_internal( - cx: &C, +impl> FnAbiOf<'tcx> for C {} + +fn fn_abi_of_fn_ptr<'tcx>( + tcx: TyCtxt<'tcx>, + query: ty::ParamEnvAnd<'tcx, (ty::PolyFnSig<'tcx>, &'tcx ty::List>)>, +) -> Result<&'tcx FnAbi<'tcx, Ty<'tcx>>, FnAbiError<'tcx>> { + let (param_env, (sig, extra_args)) = query.into_parts(); + + LayoutCx { tcx, param_env }.fn_abi_new_uncached( + sig, + extra_args, + None, + CodegenFnAttrFlags::empty(), + false, + ) +} + +fn fn_abi_of_instance<'tcx>( + tcx: TyCtxt<'tcx>, + query: ty::ParamEnvAnd<'tcx, (ty::Instance<'tcx>, &'tcx ty::List>)>, +) -> Result<&'tcx FnAbi<'tcx, Ty<'tcx>>, FnAbiError<'tcx>> { + let (param_env, (instance, extra_args)) = query.into_parts(); + + let sig = instance.fn_sig_for_fn_abi(tcx); + + let caller_location = if instance.def.requires_caller_location(tcx) { + Some(tcx.caller_location_ty()) + } else { + None + }; + + let attrs = tcx.codegen_fn_attrs(instance.def_id()).flags; + + LayoutCx { tcx, param_env }.fn_abi_new_uncached( + sig, + extra_args, + caller_location, + attrs, + matches!(instance.def, ty::InstanceDef::Virtual(..)), + ) +} + +impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { + // FIXME(eddyb) perhaps group the signature/type-containing (or all of them?) + // arguments of this method, into a separate `struct`. + fn fn_abi_new_uncached( + &self, sig: ty::PolyFnSig<'tcx>, extra_args: &[Ty<'tcx>], caller_location: Option>, codegen_fn_attr_flags: CodegenFnAttrFlags, + // FIXME(eddyb) replace this with something typed, like an `enum`. force_thin_self_ptr: bool, - ) -> Self { - debug!("FnAbi::new_internal({:?}, {:?})", sig, extra_args); + ) -> Result<&'tcx FnAbi<'tcx, Ty<'tcx>>, FnAbiError<'tcx>> { + debug!("fn_abi_new_uncached({:?}, {:?})", sig, extra_args); - let sig = cx.tcx().normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), sig); + let sig = self.tcx.normalize_erasing_late_bound_regions(self.param_env, sig); - let conv = conv_from_spec_abi(cx.tcx(), sig.abi); + let conv = conv_from_spec_abi(self.tcx(), sig.abi); let mut inputs = sig.inputs(); let extra_args = if sig.abi == RustCall { @@ -2816,8 +3011,8 @@ where extra_args.to_vec() }; - let target = &cx.tcx().sess.target; - let target_env_gnu_like = matches!(&target.env[..], "gnu" | "musl"); + let target = &self.tcx.sess.target; + let target_env_gnu_like = matches!(&target.env[..], "gnu" | "musl" | "uclibc"); let win_x64_gnu = target.os == "windows" && target.arch == "x86_64" && target.env == "gnu"; let linux_s390x_gnu_like = target.os == "linux" && target.arch == "s390x" && target_env_gnu_like; @@ -2830,7 +3025,7 @@ where // Handle safe Rust thin and fat pointers. let adjust_for_rust_scalar = |attrs: &mut ArgAttributes, - scalar: &Scalar, + scalar: Scalar, layout: TyAndLayout<'tcx>, offset: Size, is_return: bool| { @@ -2845,11 +3040,11 @@ where return; } - if !scalar.valid_range.contains_zero() { + if !scalar.valid_range.contains(0) { attrs.set(ArgAttribute::NonNull); } - if let Some(pointee) = layout.pointee_info_at(cx, offset) { + if let Some(pointee) = layout.pointee_info_at(self, offset) { if let Some(kind) = pointee.safe { attrs.pointee_align = Some(pointee.align); @@ -2893,20 +3088,20 @@ where } }; - let arg_of = |ty: Ty<'tcx>, arg_idx: Option| { + let arg_of = |ty: Ty<'tcx>, arg_idx: Option| -> Result<_, FnAbiError<'tcx>> { let is_return = arg_idx.is_none(); - let layout = cx.layout_of(ty); + let layout = self.layout_of(ty)?; let layout = if force_thin_self_ptr && arg_idx == Some(0) { // Don't pass the vtable, it's not an argument of the virtual fn. // Instead, pass just the data pointer, but give it the type `*const/mut dyn Trait` // or `&/&mut dyn Trait` because this is special-cased elsewhere in codegen - make_thin_self_ptr(cx, layout) + make_thin_self_ptr(self, layout) } else { layout }; - let mut arg = ArgAbi::new(cx, layout, |layout, scalar, offset| { + let mut arg = ArgAbi::new(self, layout, |layout, scalar, offset| { let mut attrs = ArgAttributes::new(); adjust_for_rust_scalar(&mut attrs, scalar, *layout, offset, is_return); attrs @@ -2915,7 +3110,7 @@ where if arg.layout.is_zst() { // For some forsaken reason, x86_64-pc-windows-gnu // doesn't ignore zero-sized struct arguments. - // The same is true for {s390x,sparc64,powerpc}-unknown-linux-{gnu,musl}. + // The same is true for {s390x,sparc64,powerpc}-unknown-linux-{gnu,musl,uclibc}. if is_return || rust_abi || (!win_x64_gnu @@ -2927,11 +3122,11 @@ where } } - arg + Ok(arg) }; let mut fn_abi = FnAbi { - ret: arg_of(sig.output(), None), + ret: arg_of(sig.output(), None)?, args: inputs .iter() .cloned() @@ -2939,20 +3134,24 @@ where .chain(caller_location) .enumerate() .map(|(i, ty)| arg_of(ty, Some(i))) - .collect(), + .collect::>()?, c_variadic: sig.c_variadic, fixed_count: inputs.len(), conv, - can_unwind: fn_can_unwind(cx.tcx(), codegen_fn_attr_flags, sig.abi), + can_unwind: fn_can_unwind(self.tcx(), codegen_fn_attr_flags, sig.abi), }; - fn_abi.adjust_for_abi(cx, sig.abi); - debug!("FnAbi::new_internal = {:?}", fn_abi); - fn_abi + self.fn_abi_adjust_for_abi(&mut fn_abi, sig.abi)?; + debug!("fn_abi_new_uncached = {:?}", fn_abi); + Ok(self.tcx.arena.alloc(fn_abi)) } - fn adjust_for_abi(&mut self, cx: &C, abi: SpecAbi) { + fn fn_abi_adjust_for_abi( + &self, + fn_abi: &mut FnAbi<'tcx, Ty<'tcx>>, + abi: SpecAbi, + ) -> Result<(), FnAbiError<'tcx>> { if abi == SpecAbi::Unadjusted { - return; + return Ok(()); } if abi == SpecAbi::Rust @@ -2989,7 +3188,7 @@ where // anyway, we control all calls to it in libstd. Abi::Vector { .. } if abi != SpecAbi::PlatformIntrinsic - && cx.tcx().sess.target.simd_types_indirect => + && self.tcx.sess.target.simd_types_indirect => { arg.make_indirect(); return; @@ -3000,7 +3199,7 @@ where // Pass and return structures up to 2 pointers in size by value, matching `ScalarPair`. // LLVM will usually pass these in 2 registers, which is more efficient than by-ref. - let max_by_val_size = Pointer.size(cx) * 2; + let max_by_val_size = Pointer.size(self) * 2; let size = arg.layout.size; if arg.layout.is_unsized() || size > max_by_val_size { @@ -3012,16 +3211,15 @@ where arg.cast_to(Reg { kind: RegKind::Integer, size }); } }; - fixup(&mut self.ret); - for arg in &mut self.args { + fixup(&mut fn_abi.ret); + for arg in &mut fn_abi.args { fixup(arg); } - return; + } else { + fn_abi.adjust_for_foreign_abi(self, abi)?; } - if let Err(msg) = self.adjust_for_cabi(cx, abi) { - cx.tcx().sess.fatal(&msg); - } + Ok(()) } } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 1bb9a86110..20d07bdc48 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -20,8 +20,6 @@ pub use generics::*; pub use vtable::*; use crate::hir::exports::ExportMap; -use crate::ich::StableHashingContext; -use crate::middle::cstore::CrateStoreDyn; use crate::mir::{Body, GeneratorLayout}; use crate::traits::{self, Reveal}; use crate::ty; @@ -29,18 +27,18 @@ use crate::ty::subst::{GenericArg, InternalSubsts, Subst, SubstsRef}; use crate::ty::util::Discr; use rustc_ast as ast; use rustc_attr as attr; -use rustc_data_structures::captures::Captures; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; -use rustc_data_structures::sync::{self, par_iter, ParallelIterator}; use rustc_data_structures::tagged_ptr::CopyTaggedPtr; use rustc_hir as hir; use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res}; use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LocalDefIdMap, CRATE_DEF_INDEX}; use rustc_hir::Node; use rustc_macros::HashStable; +use rustc_query_system::ich::StableHashingContext; +use rustc_session::cstore::CrateStoreDyn; use rustc_span::symbol::{kw, Ident, Symbol}; -use rustc_span::Span; +use rustc_span::{sym, Span}; use rustc_target::abi::Align; use std::cmp::Ordering; @@ -94,7 +92,6 @@ pub mod fold; pub mod inhabitedness; pub mod layout; pub mod normalize_erasing_regions; -pub mod outlives; pub mod print; pub mod query; pub mod relate; @@ -112,6 +109,7 @@ mod context; mod diagnostics; mod erase_regions; mod generics; +mod impls_ty; mod instance; mod list; mod structural_impls; @@ -127,7 +125,7 @@ pub struct ResolverOutputs { pub extern_crate_map: FxHashMap, pub maybe_unused_trait_imports: FxHashSet, pub maybe_unused_extern_crates: Vec<(LocalDefId, Span)>, - pub export_map: ExportMap, + pub export_map: ExportMap, pub glob_map: FxHashMap>, /// Extern prelude entries. The value is `true` if the entry was introduced /// via `extern crate` item and not `--extern` option or compiler built-in. @@ -137,6 +135,9 @@ pub struct ResolverOutputs { /// A list of proc macro LocalDefIds, written out in the order in which /// they are declared in the static array generated by proc_macro_harness. pub proc_macros: Vec, + /// Mapping from ident span to path span for paths that don't exist as written, but that + /// exist under `std`. For example, wrote `str::from_utf8` instead of `std::str::from_utf8`. + pub confused_type_with_std_module: FxHashMap, } #[derive(Clone, Copy, Debug)] @@ -598,7 +599,7 @@ impl<'tcx> Predicate<'tcx> { // where both `'x` and `'b` would have a DB index of 1. // The substitution from the input trait-ref is therefore going to be // `'a => 'x` (where `'x` has a DB index of 1). - // - The super-trait-ref is `for<'b> Bar1<'a,'b>`, where `'a` is an + // - The supertrait-ref is `for<'b> Bar1<'a,'b>`, where `'a` is an // early-bound parameter and `'b' is a late-bound parameter with a // DB index of 1. // - If we replace `'a` with `'x` from the input, it too will have @@ -766,12 +767,6 @@ pub trait ToPolyTraitRef<'tcx> { fn to_poly_trait_ref(&self) -> PolyTraitRef<'tcx>; } -impl<'tcx> ToPolyTraitRef<'tcx> for TraitRef<'tcx> { - fn to_poly_trait_ref(&self) -> PolyTraitRef<'tcx> { - ty::Binder::dummy(*self) - } -} - impl<'tcx> ToPolyTraitRef<'tcx> for PolyTraitPredicate<'tcx> { fn to_poly_trait_ref(&self) -> PolyTraitRef<'tcx> { self.map_bound_ref(|trait_pred| trait_pred.trait_ref) @@ -789,23 +784,6 @@ impl ToPredicate<'tcx> for Binder<'tcx, PredicateKind<'tcx>> { } } -impl ToPredicate<'tcx> for PredicateKind<'tcx> { - #[inline(always)] - fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { - tcx.mk_predicate(Binder::dummy(self)) - } -} - -impl<'tcx> ToPredicate<'tcx> for ConstnessAnd> { - fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { - PredicateKind::Trait(ty::TraitPredicate { - trait_ref: self.value, - constness: self.constness, - }) - .to_predicate(tcx) - } -} - impl<'tcx> ToPredicate<'tcx> for ConstnessAnd> { fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { self.value @@ -1374,6 +1352,8 @@ where pub struct Destructor { /// The `DefId` of the destructor method pub did: DefId, + /// The constness of the destructor method + pub constness: hir::Constness, } bitflags! { @@ -1509,6 +1489,9 @@ bitflags! { const IS_LINEAR = 1 << 3; // If true, don't expose any niche to type's context. const HIDE_NICHE = 1 << 4; + // If true, the type's layout can be randomized using + // the seed stored in `ReprOptions.layout_seed` + const RANDOMIZE_LAYOUT = 1 << 5; // Any of these flags being set prevent field reordering optimisation. const IS_UNOPTIMISABLE = ReprFlags::IS_C.bits | ReprFlags::IS_SIMD.bits | @@ -1523,6 +1506,14 @@ pub struct ReprOptions { pub align: Option, pub pack: Option, pub flags: ReprFlags, + /// The seed to be used for randomizing a type's layout + /// + /// Note: This could technically be a `[u8; 16]` (a `u128`) which would + /// be the "most accurate" hash as it'd encompass the item and crate + /// hash without loss, but it does pay the price of being larger. + /// Everything's a tradeoff, a `u64` seed should be sufficient for our + /// purposes (primarily `-Z randomize-layout`) + pub field_shuffle_seed: u64, } impl ReprOptions { @@ -1531,6 +1522,11 @@ impl ReprOptions { let mut size = None; let mut max_align: Option = None; let mut min_pack: Option = None; + + // Generate a deterministically-derived seed from the item's path hash + // to allow for cross-crate compilation to actually work + let field_shuffle_seed = tcx.def_path_hash(did).0.to_smaller_hash(); + for attr in tcx.get_attrs(did).iter() { for r in attr::find_repr_attrs(&tcx.sess, attr) { flags.insert(match r { @@ -1559,33 +1555,45 @@ impl ReprOptions { } } + // If `-Z randomize-layout` was enabled for the type definition then we can + // consider performing layout randomization + if tcx.sess.opts.debugging_opts.randomize_layout { + flags.insert(ReprFlags::RANDOMIZE_LAYOUT); + } + // This is here instead of layout because the choice must make it into metadata. if !tcx.consider_optimizing(|| format!("Reorder fields of {:?}", tcx.def_path_str(did))) { flags.insert(ReprFlags::IS_LINEAR); } - ReprOptions { int: size, align: max_align, pack: min_pack, flags } + + Self { int: size, align: max_align, pack: min_pack, flags, field_shuffle_seed } } #[inline] pub fn simd(&self) -> bool { self.flags.contains(ReprFlags::IS_SIMD) } + #[inline] pub fn c(&self) -> bool { self.flags.contains(ReprFlags::IS_C) } + #[inline] pub fn packed(&self) -> bool { self.pack.is_some() } + #[inline] pub fn transparent(&self) -> bool { self.flags.contains(ReprFlags::IS_TRANSPARENT) } + #[inline] pub fn linear(&self) -> bool { self.flags.contains(ReprFlags::IS_LINEAR) } + #[inline] pub fn hide_niche(&self) -> bool { self.flags.contains(ReprFlags::HIDE_NICHE) @@ -1612,9 +1620,17 @@ impl ReprOptions { return true; } } + self.flags.intersects(ReprFlags::IS_UNOPTIMISABLE) || self.int.is_some() } + /// Returns `true` if this type is valid for reordering and `-Z randomize-layout` + /// was enabled for its declaration crate + pub fn can_randomize_type_layout(&self) -> bool { + !self.inhibit_struct_field_reordering_opt() + && self.flags.contains(ReprFlags::RANDOMIZE_LAYOUT) + } + /// Returns `true` if this `#[repr()]` should inhibit union ABI optimisations. pub fn inhibit_union_abi_opt(&self) -> bool { self.c() @@ -1622,8 +1638,8 @@ impl ReprOptions { } impl<'tcx> FieldDef { - /// Returns the type of this field. The `subst` is typically obtained - /// via the second field of `TyKind::AdtDef`. + /// Returns the type of this field. The resulting type is not normalized. The `subst` is + /// typically obtained via the second field of `TyKind::AdtDef`. pub fn ty(&self, tcx: TyCtxt<'tcx>, subst: SubstsRef<'tcx>) -> Ty<'tcx> { tcx.type_of(self.did).subst(tcx, subst) } @@ -1678,18 +1694,6 @@ impl<'tcx> TyCtxt<'tcx> { self.typeck(self.hir().body_owner_def_id(body)) } - /// Returns an iterator of the `DefId`s for all body-owners in this - /// 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 + Captures<'tcx> + 'tcx { - self.hir().krate().bodies.keys().map(move |&body_id| self.hir().body_owner_def_id(body_id)) - } - - pub fn par_body_owners(self, f: F) { - par_iter(&self.hir().krate().bodies) - .for_each(|(&body_id, _)| f(self.hir().body_owner_def_id(body_id))); - } - pub fn provided_trait_methods(self, id: DefId) -> impl 'tcx + Iterator { self.associated_items(id) .in_definition_order() @@ -1895,6 +1899,14 @@ impl<'tcx> TyCtxt<'tcx> { self.sess.contains_name(&self.get_attrs(did), attr) } + /// Determines whether an item is annotated with `doc(hidden)`. + pub fn is_doc_hidden(self, did: DefId) -> bool { + self.get_attrs(did) + .iter() + .filter_map(|attr| if attr.has_name(sym::doc) { attr.meta_item_list() } else { None }) + .any(|items| items.iter().any(|item| item.has_name(sym::hidden))) + } + /// Returns `true` if this is an `auto trait`. pub fn trait_is_auto(self, trait_def_id: DefId) -> bool { self.trait_def(trait_def_id).has_auto_impl @@ -2086,3 +2098,16 @@ impl<'tcx> fmt::Debug for SymbolName<'tcx> { fmt::Display::fmt(&self.name, fmt) } } + +#[derive(Debug, Default, Copy, Clone)] +pub struct FoundRelationships { + /// This is true if we identified that this Ty (`?T`) is found in a `?T: Foo` + /// obligation, where: + /// + /// * `Foo` is not `Sized` + /// * `(): Foo` may be satisfied + pub self_in_trait: bool, + /// This is true if we identified that this Ty (`?T`) is found in a `<_ as + /// _>::AssocType = ?T` + pub output: bool, +} diff --git a/compiler/rustc_middle/src/ty/print/mod.rs b/compiler/rustc_middle/src/ty/print/mod.rs index 13e2122a61..308b4d2fef 100644 --- a/compiler/rustc_middle/src/ty/print/mod.rs +++ b/compiler/rustc_middle/src/ty/print/mod.rs @@ -98,14 +98,14 @@ pub trait Printer<'tcx>: Sized { // Defaults (should not be overridden): + #[instrument(skip(self), level = "debug")] fn default_print_def_path( self, def_id: DefId, substs: &'tcx [GenericArg<'tcx>], ) -> Result { - debug!("default_print_def_path: def_id={:?}, substs={:?}", def_id, substs); let key = self.tcx().def_key(def_id); - debug!("default_print_def_path: key={:?}", key); + debug!(?key); match key.disambiguated_data.data { DefPathData::CrateRoot => { diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 18b52badd0..2610a76b28 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -1,4 +1,3 @@ -use crate::middle::cstore::{ExternCrate, ExternCrateSource}; use crate::mir::interpret::{AllocRange, ConstValue, GlobalAlloc, Pointer, Provenance, Scalar}; use crate::ty::subst::{GenericArg, GenericArgKind, Subst}; use crate::ty::{self, ConstInt, DefIdTree, ParamConst, ScalarInt, Ty, TyCtxt, TypeFoldable}; @@ -11,6 +10,7 @@ use rustc_hir::def_id::{DefId, DefIdSet, CRATE_DEF_INDEX, LOCAL_CRATE}; use rustc_hir::definitions::{DefPathData, DefPathDataName, DisambiguatedDefPathData}; use rustc_hir::ItemKind; use rustc_session::config::TrimmedDefPaths; +use rustc_session::cstore::{ExternCrate, ExternCrateSource}; use rustc_span::symbol::{kw, Ident, Symbol}; use rustc_target::abi::Size; use rustc_target::spec::abi::Abi; @@ -59,6 +59,7 @@ thread_local! { static SHOULD_PREFIX_WITH_CRATE: Cell = const { Cell::new(false) }; static NO_TRIMMED_PATH: Cell = const { Cell::new(false) }; static NO_QUERIES: Cell = const { Cell::new(false) }; + static NO_VISIBLE_PATH: Cell = const { Cell::new(false) }; } /// Avoids running any queries during any prints that occur @@ -112,6 +113,16 @@ pub fn with_no_trimmed_paths R, R>(f: F) -> R { }) } +/// Prevent selection of visible paths. `Display` impl of DefId will prefer visible (public) reexports of types as paths. +pub fn with_no_visible_paths R, R>(f: F) -> R { + NO_VISIBLE_PATH.with(|flag| { + let old = flag.replace(true); + let result = f(); + flag.set(old); + result + }) +} + /// The "region highlights" are used to control region printing during /// specific error messages. When a "region highlight" is enabled, it /// gives an alternate way to print specific regions. For now, we @@ -268,6 +279,10 @@ pub trait PrettyPrinter<'tcx>: /// from at least one local module, and returns `true`. If the crate defining `def_id` is /// declared with an `extern crate`, the path is guaranteed to use the `extern crate`. fn try_print_visible_def_path(self, def_id: DefId) -> Result<(Self, bool), Self::Error> { + if NO_VISIBLE_PATH.with(|flag| flag.get()) { + return Ok((self, false)); + } + let mut callers = Vec::new(); self.try_print_visible_def_path_recur(def_id, &mut callers) } @@ -2018,12 +2033,11 @@ impl FmtPrinter<'_, 'tcx, F> { Ok(inner) } + #[instrument(skip(self), level = "debug")] fn prepare_late_bound_region_info(&mut self, value: &ty::Binder<'tcx, T>) where T: TypeFoldable<'tcx>, { - debug!("prepare_late_bound_region_info(value: {:?})", value); - struct LateBoundRegionNameCollector<'a, 'tcx> { tcx: TyCtxt<'tcx>, used_region_names: &'a mut FxHashSet, @@ -2037,8 +2051,9 @@ impl FmtPrinter<'_, 'tcx, F> { Some(self.tcx) } + #[instrument(skip(self), level = "trace")] fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow { - debug!("LateBoundRegionNameCollector::visit_region(r: {:?}, address: {:p})", r, &r); + trace!("address: {:p}", r); if let ty::ReLateBound(_, ty::BoundRegion { kind: ty::BrNamed(_, name), .. }) = *r { self.used_region_names.insert(name); } else if let ty::RePlaceholder(ty::PlaceholderRegion { @@ -2053,8 +2068,8 @@ impl FmtPrinter<'_, 'tcx, F> { // We collect types in order to prevent really large types from compiling for // a really long time. See issue #83150 for why this is necessary. + #[instrument(skip(self), level = "trace")] fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow { - debug!("LateBoundRegionNameCollector::visit_ty(ty: {:?}", ty); let not_previously_inserted = self.type_collector.insert(ty); if not_previously_inserted { ty.super_visit_with(self) @@ -2156,10 +2171,26 @@ impl fmt::Debug for TraitRefPrintOnlyTraitPath<'tcx> { } } +/// Wrapper type for `ty::TraitRef` which opts-in to pretty printing only +/// the trait name. That is, it will print `Trait` instead of +/// `>`. +#[derive(Copy, Clone, TypeFoldable, Lift)] +pub struct TraitRefPrintOnlyTraitName<'tcx>(ty::TraitRef<'tcx>); + +impl fmt::Debug for TraitRefPrintOnlyTraitName<'tcx> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(self, f) + } +} + impl ty::TraitRef<'tcx> { pub fn print_only_trait_path(self) -> TraitRefPrintOnlyTraitPath<'tcx> { TraitRefPrintOnlyTraitPath(self) } + + pub fn print_only_trait_name(self) -> TraitRefPrintOnlyTraitName<'tcx> { + TraitRefPrintOnlyTraitName(self) + } } impl ty::Binder<'tcx, ty::TraitRef<'tcx>> { @@ -2179,6 +2210,7 @@ forward_display_to_print! { ty::Binder<'tcx, ty::TraitRef<'tcx>>, ty::Binder<'tcx, ty::ExistentialTraitRef<'tcx>>, ty::Binder<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, + ty::Binder<'tcx, TraitRefPrintOnlyTraitName<'tcx>>, ty::Binder<'tcx, ty::FnSig<'tcx>>, ty::Binder<'tcx, ty::TraitPredicate<'tcx>>, ty::Binder<'tcx, ty::SubtypePredicate<'tcx>>, @@ -2241,6 +2273,10 @@ define_print_and_forward_display! { p!(print_def_path(self.0.def_id, self.0.substs)); } + TraitRefPrintOnlyTraitName<'tcx> { + p!(print_def_path(self.0.def_id, &[])); + } + ty::ParamTy { p!(write("{}", self.name)) } @@ -2326,7 +2362,7 @@ define_print_and_forward_display! { fn for_each_def(tcx: TyCtxt<'_>, mut collect_fn: impl for<'b> FnMut(&'b Ident, Namespace, DefId)) { // Iterate all local crate items no matter where they are defined. let hir = tcx.hir(); - for item in hir.krate().items() { + for item in hir.items() { if item.ident.name.as_str().is_empty() || matches!(item.kind, ItemKind::Use(_, _)) { continue; } @@ -2394,7 +2430,7 @@ fn for_each_def(tcx: TyCtxt<'_>, mut collect_fn: impl for<'b> FnMut(&'b Ident, N /// /// The implementation uses similar import discovery logic to that of 'use' suggestions. fn trimmed_def_paths(tcx: TyCtxt<'_>, (): ()) -> FxHashMap { - let mut map = FxHashMap::default(); + let mut map: FxHashMap = FxHashMap::default(); if let TrimmedDefPaths::GoodPath = tcx.sess.opts.trimmed_def_paths { // For good paths causing this bug, the `rustc_middle::ty::print::with_no_trimmed_paths` @@ -2432,8 +2468,29 @@ fn trimmed_def_paths(tcx: TyCtxt<'_>, (): ()) -> FxHashMap { }); for ((_, symbol), opt_def_id) in unique_symbols_rev.drain() { + use std::collections::hash_map::Entry::{Occupied, Vacant}; + if let Some(def_id) = opt_def_id { - map.insert(def_id, symbol); + match map.entry(def_id) { + Occupied(mut v) => { + // A single DefId can be known under multiple names (e.g., + // with a `pub use ... as ...;`). We need to ensure that the + // name placed in this map is chosen deterministically, so + // if we find multiple names (`symbol`) resolving to the + // same `def_id`, we prefer the lexicographically smallest + // name. + // + // Any stable ordering would be fine here though. + if *v.get() != symbol { + if v.get().as_str() > symbol.as_str() { + v.insert(symbol); + } + } + } + Vacant(v) => { + v.insert(symbol); + } + } } } diff --git a/compiler/rustc_middle/src/ty/query.rs b/compiler/rustc_middle/src/ty/query.rs index 15a8888ee6..b1bc073ca9 100644 --- a/compiler/rustc_middle/src/ty/query.rs +++ b/compiler/rustc_middle/src/ty/query.rs @@ -3,8 +3,6 @@ use crate::hir::exports::Export; use crate::infer::canonical::{self, Canonical}; use crate::lint::LintLevelMap; use crate::middle::codegen_fn_attrs::CodegenFnAttrs; -use crate::middle::cstore::{CrateDepKind, CrateSource}; -use crate::middle::cstore::{ExternCrate, ForeignModule, LinkagePreference, NativeLib}; use crate::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel}; use crate::middle::lib_features::LibFeatures; use crate::middle::privacy::AccessLevels; @@ -46,8 +44,11 @@ use rustc_hir::lang_items::{LangItem, LanguageItems}; use rustc_hir::{Crate, ItemLocalId, TraitCandidate}; use rustc_index::{bit_set::FiniteBitSet, vec::IndexVec}; use rustc_session::config::{EntryFnType, OptLevel, OutputFilenames, SymbolManglingVersion}; +use rustc_session::cstore::{CrateDepKind, CrateSource}; +use rustc_session::cstore::{ExternCrate, ForeignModule, LinkagePreference, NativeLib}; use rustc_session::utils::NativeLibKind; use rustc_session::Limits; +use rustc_target::abi; use rustc_target::spec::PanicStrategy; use rustc_ast as ast; @@ -110,11 +111,11 @@ macro_rules! query_storage { ([][$K:ty, $V:ty]) => { >::Cache }; - ([storage($ty:ty) $($rest:tt)*][$K:ty, $V:ty]) => { + ([(storage $ty:ty) $($rest:tt)*][$K:ty, $V:ty]) => { <$ty as CacheSelector<$K, $V>>::Cache }; - ([$other:ident $(($($other_args:tt)*))* $(, $($modifiers:tt)*)*][$($args:tt)*]) => { - query_storage!([$($($modifiers)*)*][$($args)*]) + ([$other:tt $($modifiers:tt)*][$($args:tt)*]) => { + query_storage!([$($modifiers)*][$($args)*]) }; } diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs index 9d1be212f5..2c78653801 100644 --- a/compiler/rustc_middle/src/ty/relate.rs +++ b/compiler/rustc_middle/src/ty/relate.rs @@ -639,6 +639,15 @@ fn check_const_value_eq>( get_slice_bytes(&tcx, a_val) == get_slice_bytes(&tcx, b_val) } + (ConstValue::ByRef { alloc: alloc_a, .. }, ConstValue::ByRef { alloc: alloc_b, .. }) + if a.ty.is_ref() || b.ty.is_ref() => + { + if a.ty.is_ref() && b.ty.is_ref() { + alloc_a == alloc_b + } else { + false + } + } (ConstValue::ByRef { .. }, ConstValue::ByRef { .. }) => { let a_destructured = tcx.destructure_const(relation.param_env().and(a)); let b_destructured = tcx.destructure_const(relation.param_env().and(b)); diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index 89ad99d9f0..8f343ba9fe 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -638,8 +638,8 @@ impl<'a, 'tcx> Lift<'tcx> for ty::InstanceDef<'a> { Some(ty::InstanceDef::FnPtrShim(def_id, tcx.lift(ty)?)) } ty::InstanceDef::Virtual(def_id, n) => Some(ty::InstanceDef::Virtual(def_id, n)), - ty::InstanceDef::ClosureOnceShim { call_once } => { - Some(ty::InstanceDef::ClosureOnceShim { call_once }) + ty::InstanceDef::ClosureOnceShim { call_once, track_caller } => { + Some(ty::InstanceDef::ClosureOnceShim { call_once, track_caller }) } ty::InstanceDef::DropGlue(def_id, ty) => { Some(ty::InstanceDef::DropGlue(def_id, tcx.lift(ty)?)) @@ -824,8 +824,8 @@ impl<'tcx> TypeFoldable<'tcx> for ty::instance::Instance<'tcx> { Intrinsic(did) => Intrinsic(did.fold_with(folder)), FnPtrShim(did, ty) => FnPtrShim(did.fold_with(folder), ty.fold_with(folder)), Virtual(did, i) => Virtual(did.fold_with(folder), i), - ClosureOnceShim { call_once } => { - ClosureOnceShim { call_once: call_once.fold_with(folder) } + ClosureOnceShim { call_once, track_caller } => { + ClosureOnceShim { call_once: call_once.fold_with(folder), track_caller } } DropGlue(did, ty) => DropGlue(did.fold_with(folder), ty.fold_with(folder)), CloneShim(did, ty) => CloneShim(did.fold_with(folder), ty.fold_with(folder)), @@ -849,7 +849,7 @@ impl<'tcx> TypeFoldable<'tcx> for ty::instance::Instance<'tcx> { did.visit_with(visitor)?; ty.visit_with(visitor) } - ClosureOnceShim { call_once } => call_once.visit_with(visitor), + ClosureOnceShim { call_once, track_caller: _ } => call_once.visit_with(visitor), } } } diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 65dd61b632..d3094b3e6f 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -643,7 +643,7 @@ impl<'tcx> GeneratorSubsts<'tcx> { } /// This returns the types of the MIR locals which had to be stored across suspension points. - /// It is calculated in rustc_mir::transform::generator::StateTransform. + /// It is calculated in rustc_const_eval::transform::generator::StateTransform. /// All the types here must be in the tuple in GeneratorInterior. /// /// The locals are grouped by their variant number. Note that some locals may @@ -844,8 +844,11 @@ impl<'tcx> TraitRef<'tcx> { /// Returns a `TraitRef` of the form `P0: Foo` where `Pi` /// are the parameters defined on trait. - pub fn identity(tcx: TyCtxt<'tcx>, def_id: DefId) -> TraitRef<'tcx> { - TraitRef { def_id, substs: InternalSubsts::identity_for_item(tcx, def_id) } + pub fn identity(tcx: TyCtxt<'tcx>, def_id: DefId) -> Binder<'tcx, TraitRef<'tcx>> { + ty::Binder::dummy(TraitRef { + def_id, + substs: InternalSubsts::identity_for_item(tcx, def_id), + }) } #[inline] @@ -1268,7 +1271,7 @@ pub type Region<'tcx> = &'tcx RegionKind; /// Representation of regions. Note that the NLL checker uses a distinct /// representation of regions. For this reason, it internally replaces all the /// regions with inference variables -- the index of the variable is then used -/// to index into internal NLL data structures. See `rustc_mir::borrow_check` +/// to index into internal NLL data structures. See `rustc_const_eval::borrow_check` /// module for more information. /// /// ## The Region lattice within a given function @@ -1672,6 +1675,14 @@ impl<'tcx> TyS<'tcx> { matches!(self.kind(), Infer(TyVar(_))) } + #[inline] + pub fn ty_vid(&self) -> Option { + match self.kind() { + &Infer(TyVar(vid)) => Some(vid), + _ => None, + } + } + #[inline] pub fn is_ty_infer(&self) -> bool { matches!(self.kind(), Infer(_)) diff --git a/compiler/rustc_middle/src/ty/trait_def.rs b/compiler/rustc_middle/src/ty/trait_def.rs index ae86f51e6a..25a310b12d 100644 --- a/compiler/rustc_middle/src/ty/trait_def.rs +++ b/compiler/rustc_middle/src/ty/trait_def.rs @@ -1,4 +1,3 @@ -use crate::ich::{self, StableHashingContext}; use crate::traits::specialization_graph; use crate::ty::fast_reject; use crate::ty::fold::TypeFoldable; @@ -7,8 +6,7 @@ use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::definitions::DefPathHash; -use rustc_data_structures::fx::FxHashMap; -use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; +use rustc_data_structures::fx::FxIndexMap; use rustc_errors::ErrorReported; use rustc_macros::HashStable; @@ -66,11 +64,11 @@ pub enum TraitSpecializationKind { AlwaysApplicable, } -#[derive(Default, Debug)] +#[derive(Default, Debug, HashStable)] pub struct TraitImpls { blanket_impls: Vec, /// Impls indexed by their simplified self type, for fast lookup. - non_blanket_impls: FxHashMap>, + non_blanket_impls: FxIndexMap>, } impl TraitImpls { @@ -249,11 +247,3 @@ pub(super) fn trait_impls_of_provider(tcx: TyCtxt<'_>, trait_id: DefId) -> Trait impls } - -impl<'a> HashStable> for TraitImpls { - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { - let TraitImpls { ref blanket_impls, ref non_blanket_impls } = *self; - - ich::hash_stable_trait_impls(hcx, hasher, blanket_impls, non_blanket_impls); - } -} diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 1b8e94260b..2c884813d2 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -1,6 +1,5 @@ //! Miscellaneous type-system utilities that are too small to deserve their own modules. -use crate::ich::NodeIdHashingMode; use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags; use crate::ty::fold::TypeFolder; use crate::ty::layout::IntegerExt; @@ -18,6 +17,7 @@ use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; use rustc_macros::HashStable; +use rustc_query_system::ich::NodeIdHashingMode; use rustc_span::DUMMY_SP; use rustc_target::abi::{Integer, Size, TargetDataLayout}; use smallvec::SmallVec; @@ -45,18 +45,6 @@ impl<'tcx> fmt::Display for Discr<'tcx> { } } -fn signed_min(size: Size) -> i128 { - size.sign_extend(1_u128 << (size.bits() - 1)) as i128 -} - -fn signed_max(size: Size) -> i128 { - i128::MAX >> (128 - size.bits()) -} - -fn unsigned_max(size: Size) -> u128 { - u128::MAX >> (128 - size.bits()) -} - fn int_size_and_signed<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> (Size, bool) { let (int, signed) = match *ty.kind() { Int(ity) => (Integer::from_int_ty(&tcx, ity), true), @@ -74,8 +62,8 @@ impl<'tcx> Discr<'tcx> { pub fn checked_add(self, tcx: TyCtxt<'tcx>, n: u128) -> (Self, bool) { let (size, signed) = int_size_and_signed(tcx, self.ty); let (val, oflo) = if signed { - let min = signed_min(size); - let max = signed_max(size); + let min = size.signed_int_min(); + let max = size.signed_int_max(); let val = size.sign_extend(self.val) as i128; assert!(n < (i128::MAX as u128)); let n = n as i128; @@ -86,7 +74,7 @@ impl<'tcx> Discr<'tcx> { let val = size.truncate(val); (val, oflo) } else { - let max = unsigned_max(size); + let max = size.unsigned_int_max(); let val = self.val; let oflo = val > max - n; let val = if oflo { n - (max - val) - 1 } else { val + n }; @@ -336,16 +324,16 @@ impl<'tcx> TyCtxt<'tcx> { self.ensure().coherent_trait(drop_trait); let ty = self.type_of(adt_did); - let dtor_did = self.find_map_relevant_impl(drop_trait, ty, |impl_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 validate(self, impl_did).is_ok() { - return Some(item.def_id); + return Some((item.def_id, self.impl_constness(impl_did))); } } None - }); + })?; - Some(ty::Destructor { did: dtor_did? }) + Some(ty::Destructor { did, constness }) } /// Returns the set of types that are required to be alive in @@ -528,6 +516,7 @@ impl<'tcx> TyCtxt<'tcx> { } /// Expands the given impl trait type, stopping if the type is recursive. + #[instrument(skip(self), level = "debug")] pub fn try_expand_impl_trait_type( self, def_id: DefId, @@ -544,6 +533,7 @@ impl<'tcx> TyCtxt<'tcx> { }; let expanded_type = visitor.expand_opaque_ty(def_id, substs).unwrap(); + trace!(?expanded_type); if visitor.found_recursion { Err(expanded_type) } else { Ok(expanded_type) } } } @@ -621,7 +611,8 @@ impl<'tcx> ty::TyS<'tcx> { let val = match self.kind() { ty::Int(_) | ty::Uint(_) => { let (size, signed) = int_size_and_signed(tcx, self); - let val = if signed { signed_max(size) as u128 } else { unsigned_max(size) }; + let val = + if signed { size.signed_int_max() as u128 } else { size.unsigned_int_max() }; Some(val) } ty::Char => Some(std::char::MAX as u128), @@ -640,7 +631,7 @@ impl<'tcx> ty::TyS<'tcx> { let val = match self.kind() { ty::Int(_) | ty::Uint(_) => { let (size, signed) = int_size_and_signed(tcx, self); - let val = if signed { size.truncate(signed_min(size) as u128) } else { 0 }; + let val = if signed { size.truncate(size.signed_int_min() as u128) } else { 0 }; Some(val) } ty::Char => Some(0), diff --git a/compiler/rustc_mir/src/borrow_check/type_check/relate_tys.rs b/compiler/rustc_mir/src/borrow_check/type_check/relate_tys.rs deleted file mode 100644 index 971c4daa6b..0000000000 --- a/compiler/rustc_mir/src/borrow_check/type_check/relate_tys.rs +++ /dev/null @@ -1,134 +0,0 @@ -use rustc_infer::infer::nll_relate::{NormalizationStrategy, TypeRelating, TypeRelatingDelegate}; -use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin}; -use rustc_middle::mir::ConstraintCategory; -use rustc_middle::ty::relate::TypeRelation; -use rustc_middle::ty::{self, Const, Ty}; -use rustc_trait_selection::traits::query::Fallible; - -use crate::borrow_check::constraints::OutlivesConstraint; -use crate::borrow_check::diagnostics::UniverseInfo; -use crate::borrow_check::type_check::{BorrowCheckContext, Locations}; - -/// Adds sufficient constraints to ensure that `a R b` where `R` depends on `v`: -/// -/// - "Covariant" `a <: b` -/// - "Invariant" `a == b` -/// - "Contravariant" `a :> b` -/// -/// N.B., the type `a` is permitted to have unresolved inference -/// variables, but not the type `b`. -pub(super) fn relate_types<'tcx>( - infcx: &InferCtxt<'_, 'tcx>, - param_env: ty::ParamEnv<'tcx>, - a: Ty<'tcx>, - v: ty::Variance, - b: Ty<'tcx>, - locations: Locations, - category: ConstraintCategory, - borrowck_context: &mut BorrowCheckContext<'_, 'tcx>, -) -> Fallible<()> { - debug!("relate_types(a={:?}, v={:?}, b={:?}, locations={:?})", a, v, b, locations); - TypeRelating::new( - infcx, - NllTypeRelatingDelegate::new( - infcx, - borrowck_context, - param_env, - locations, - category, - UniverseInfo::relate(a, b), - ), - v, - ) - .relate(a, b)?; - Ok(()) -} - -struct NllTypeRelatingDelegate<'me, 'bccx, 'tcx> { - infcx: &'me InferCtxt<'me, 'tcx>, - borrowck_context: &'me mut BorrowCheckContext<'bccx, 'tcx>, - - param_env: ty::ParamEnv<'tcx>, - - /// Where (and why) is this relation taking place? - locations: Locations, - - /// What category do we assign the resulting `'a: 'b` relationships? - category: ConstraintCategory, - - /// Information so that error reporting knows what types we are relating - /// when reporting a bound region error. - universe_info: UniverseInfo<'tcx>, -} - -impl NllTypeRelatingDelegate<'me, 'bccx, 'tcx> { - fn new( - infcx: &'me InferCtxt<'me, 'tcx>, - borrowck_context: &'me mut BorrowCheckContext<'bccx, 'tcx>, - param_env: ty::ParamEnv<'tcx>, - locations: Locations, - category: ConstraintCategory, - universe_info: UniverseInfo<'tcx>, - ) -> Self { - Self { infcx, borrowck_context, param_env, locations, category, universe_info } - } -} - -impl TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx> { - fn param_env(&self) -> ty::ParamEnv<'tcx> { - self.param_env - } - - fn create_next_universe(&mut self) -> ty::UniverseIndex { - let info_universe = - self.borrowck_context.constraints.universe_causes.push(self.universe_info.clone()); - let universe = self.infcx.create_next_universe(); - assert_eq!(info_universe, universe); - universe - } - - fn next_existential_region_var(&mut self, from_forall: bool) -> ty::Region<'tcx> { - let origin = NllRegionVariableOrigin::Existential { from_forall }; - self.infcx.next_nll_region_var(origin) - } - - fn next_placeholder_region(&mut self, placeholder: ty::PlaceholderRegion) -> ty::Region<'tcx> { - self.borrowck_context.constraints.placeholder_region(self.infcx, placeholder) - } - - fn generalize_existential(&mut self, universe: ty::UniverseIndex) -> ty::Region<'tcx> { - self.infcx.next_nll_region_var_in_universe( - NllRegionVariableOrigin::Existential { from_forall: false }, - universe, - ) - } - - fn push_outlives( - &mut self, - sup: ty::Region<'tcx>, - sub: ty::Region<'tcx>, - info: ty::VarianceDiagInfo<'tcx>, - ) { - let sub = self.borrowck_context.universal_regions.to_region_vid(sub); - let sup = self.borrowck_context.universal_regions.to_region_vid(sup); - self.borrowck_context.constraints.outlives_constraints.push(OutlivesConstraint { - sup, - sub, - locations: self.locations, - category: self.category, - variance_info: info, - }); - } - - // We don't have to worry about the equality of consts during borrow checking - // as consts always have a static lifetime. - fn const_equate(&mut self, _a: &'tcx Const<'tcx>, _b: &'tcx Const<'tcx>) {} - - fn normalization() -> NormalizationStrategy { - NormalizationStrategy::Eager - } - - fn forbid_inference_vars() -> bool { - true - } -} diff --git a/compiler/rustc_mir/src/dataflow/mod.rs b/compiler/rustc_mir/src/dataflow/mod.rs deleted file mode 100644 index 8a426cc101..0000000000 --- a/compiler/rustc_mir/src/dataflow/mod.rs +++ /dev/null @@ -1,49 +0,0 @@ -use rustc_ast::{self as ast, MetaItem}; -use rustc_middle::ty; -use rustc_session::Session; -use rustc_span::symbol::{sym, Symbol}; - -pub(crate) use self::drop_flag_effects::*; -pub use self::framework::{ - fmt, graphviz, lattice, visit_results, Analysis, AnalysisDomain, Backward, BorrowckFlowState, - BorrowckResults, Engine, Forward, GenKill, GenKillAnalysis, JoinSemiLattice, Results, - ResultsCursor, ResultsRefCursor, ResultsVisitor, SwitchIntEdgeEffects, -}; - -use self::move_paths::MoveData; - -pub mod drop_flag_effects; -mod framework; -pub mod impls; -pub mod move_paths; - -pub(crate) mod indexes { - pub(crate) use super::{ - impls::borrows::BorrowIndex, - move_paths::{InitIndex, MoveOutIndex, MovePathIndex}, - }; -} - -pub struct MoveDataParamEnv<'tcx> { - pub(crate) move_data: MoveData<'tcx>, - pub(crate) param_env: ty::ParamEnv<'tcx>, -} - -pub(crate) fn has_rustc_mir_with( - _sess: &Session, - attrs: &[ast::Attribute], - name: Symbol, -) -> Option { - for attr in attrs { - if attr.has_name(sym::rustc_mir) { - let items = attr.meta_item_list(); - for item in items.iter().flat_map(|l| l.iter()) { - match item.meta_item() { - Some(mi) if mi.has_name(name) => return Some(mi.clone()), - _ => continue, - } - } - } - } - None -} diff --git a/compiler/rustc_mir/src/util/mod.rs b/compiler/rustc_mir/src/util/mod.rs deleted file mode 100644 index 3e466b5060..0000000000 --- a/compiler/rustc_mir/src/util/mod.rs +++ /dev/null @@ -1,21 +0,0 @@ -pub mod aggregate; -pub mod borrowck_errors; -pub mod elaborate_drops; -pub mod patch; -pub mod storage; - -mod alignment; -pub mod collect_writes; -mod find_self_call; -mod generic_graph; -pub(crate) mod generic_graphviz; -mod graphviz; -pub(crate) mod pretty; -pub(crate) mod spanview; - -pub use self::aggregate::expand_aggregate; -pub use self::alignment::is_disaligned; -pub use self::find_self_call::find_self_call; -pub use self::generic_graph::graphviz_safe_def_name; -pub use self::graphviz::write_mir_graphviz; -pub use self::pretty::{dump_enabled, dump_mir, write_mir_fn, write_mir_pretty, PassWhere}; diff --git a/compiler/rustc_mir_build/Cargo.toml b/compiler/rustc_mir_build/Cargo.toml index e9fbc1b186..998b80a36c 100644 --- a/compiler/rustc_mir_build/Cargo.toml +++ b/compiler/rustc_mir_build/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustc_mir_build" version = "0.0.0" -edition = "2018" +edition = "2021" [lib] doctest = false diff --git a/compiler/rustc_mir_build/src/build/expr/as_operand.rs b/compiler/rustc_mir_build/src/build/expr/as_operand.rs index bbb2f89fda..b627b0763a 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_operand.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_operand.rs @@ -20,7 +20,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { expr: &Expr<'tcx>, ) -> BlockAnd> { let local_scope = self.local_scope(); - self.as_operand(block, Some(local_scope), expr) + self.as_operand(block, Some(local_scope), expr, None) } /// Returns an operand suitable for use until the end of the current scope expression and @@ -85,6 +85,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { /// temporary `tmp = x`, so that we capture the value of `x` at /// this time. /// + /// If we end up needing to create a temporary, then we will use + /// `local_info` as its `LocalInfo`, unless `as_temporary` + /// has already assigned it a non-`None` `LocalInfo`. + /// Normally, you should use `None` for `local_info` + /// /// The operand is known to be live until the end of `scope`. /// /// Like `as_local_call_operand`, except that the argument will @@ -94,15 +99,16 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { mut block: BasicBlock, scope: Option, expr: &Expr<'tcx>, + local_info: Option>>, ) -> BlockAnd> { - debug!("as_operand(block={:?}, expr={:?})", block, expr); + debug!("as_operand(block={:?}, expr={:?} local_info={:?})", block, expr, local_info); let this = self; if let ExprKind::Scope { region_scope, lint_level, value } = expr.kind { let source_info = this.source_info(expr.span); let region_scope = (region_scope, source_info); return this.in_scope(region_scope, lint_level, |this| { - this.as_operand(block, scope, &this.thir[value]) + this.as_operand(block, scope, &this.thir[value], local_info) }); } @@ -115,6 +121,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } Category::Place | Category::Rvalue(..) => { let operand = unpack!(block = this.as_temp(block, scope, expr, Mutability::Mut)); + if this.local_decls[operand].local_info.is_none() { + this.local_decls[operand].local_info = local_info; + } block.and(Operand::Move(Place::from(operand))) } } @@ -167,6 +176,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } } - this.as_operand(block, scope, expr) + this.as_operand(block, scope, expr, None) } } diff --git a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs index 68de1af613..9a86d465f9 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs @@ -5,6 +5,7 @@ use rustc_index::vec::Idx; use crate::build::expr::as_place::PlaceBase; use crate::build::expr::category::{Category, RvalueFunc}; use crate::build::{BlockAnd, BlockAndExtension, Builder}; +use rustc_hir::lang_items::LangItem; use rustc_middle::middle::region; use rustc_middle::mir::AssertKind; use rustc_middle::mir::Place; @@ -52,16 +53,16 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } ExprKind::Repeat { value, count } => { let value_operand = - unpack!(block = this.as_operand(block, scope, &this.thir[value])); + unpack!(block = this.as_operand(block, scope, &this.thir[value], None)); block.and(Rvalue::Repeat(value_operand, count)) } ExprKind::Binary { op, lhs, rhs } => { - let lhs = unpack!(block = this.as_operand(block, scope, &this.thir[lhs])); - let rhs = unpack!(block = this.as_operand(block, scope, &this.thir[rhs])); + let lhs = unpack!(block = this.as_operand(block, scope, &this.thir[lhs], None)); + let rhs = unpack!(block = this.as_operand(block, scope, &this.thir[rhs], None)); this.build_binary_op(block, op, expr_span, expr.ty, lhs, rhs) } ExprKind::Unary { op, arg } => { - let arg = unpack!(block = this.as_operand(block, scope, &this.thir[arg])); + let arg = unpack!(block = this.as_operand(block, scope, &this.thir[arg], None)); // Check for -MIN on signed integers if this.check_overflow && op == UnOp::Neg && expr.ty.is_signed() { let bool_ty = this.tcx.types.bool; @@ -88,6 +89,56 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } ExprKind::Box { value } => { let value = &this.thir[value]; + let tcx = this.tcx; + + // `exchange_malloc` is unsafe but box is safe, so need a new scope. + let synth_scope = this.new_source_scope( + expr_span, + LintLevel::Inherited, + Some(Safety::BuiltinUnsafe), + ); + let synth_info = SourceInfo { span: expr_span, scope: synth_scope }; + + let size = this.temp(tcx.types.usize, expr_span); + this.cfg.push_assign( + block, + synth_info, + size, + Rvalue::NullaryOp(NullOp::SizeOf, value.ty), + ); + + let align = this.temp(tcx.types.usize, expr_span); + this.cfg.push_assign( + block, + synth_info, + align, + Rvalue::NullaryOp(NullOp::AlignOf, value.ty), + ); + + // malloc some memory of suitable size and align: + let exchange_malloc = Operand::function_handle( + tcx, + tcx.require_lang_item(LangItem::ExchangeMalloc, Some(expr_span)), + ty::List::empty(), + expr_span, + ); + let storage = this.temp(tcx.mk_mut_ptr(tcx.types.u8), expr_span); + let success = this.cfg.start_new_block(); + this.cfg.terminate( + block, + synth_info, + TerminatorKind::Call { + func: exchange_malloc, + args: vec![Operand::Move(size), Operand::Move(align)], + destination: Some((storage, success)), + cleanup: None, + from_hir_call: false, + fn_span: expr_span, + }, + ); + this.diverge_from(block); + block = success; + // The `Box` temporary created here is not a part of the HIR, // and therefore is not considered during generator auto-trait // determination. See the comment about `box` at `yield_in_scope`. @@ -101,8 +152,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { this.schedule_drop_storage_and_value(expr_span, scope, result); } - // malloc some memory of suitable type (thus far, uninitialized): - let box_ = Rvalue::NullaryOp(NullOp::Box, value.ty); + // Transmute `*mut u8` to the box (thus far, uninitialized): + let box_ = Rvalue::ShallowInitBox(Operand::Move(storage), value.ty); this.cfg.push_assign(block, source_info, Place::from(result), box_); // initialize the box contents: @@ -116,11 +167,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { block.and(Rvalue::Use(Operand::Move(Place::from(result)))) } ExprKind::Cast { source } => { - let source = unpack!(block = this.as_operand(block, scope, &this.thir[source])); + let source = + unpack!(block = this.as_operand(block, scope, &this.thir[source], None)); block.and(Rvalue::Cast(CastKind::Misc, source, expr.ty)) } ExprKind::Pointer { cast, source } => { - let source = unpack!(block = this.as_operand(block, scope, &this.thir[source])); + let source = + unpack!(block = this.as_operand(block, scope, &this.thir[source], None)); block.and(Rvalue::Cast(CastKind::Pointer(cast), source, expr.ty)) } ExprKind::Array { ref fields } => { @@ -155,7 +208,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let fields: Vec<_> = fields .into_iter() .copied() - .map(|f| unpack!(block = this.as_operand(block, scope, &this.thir[f]))) + .map(|f| unpack!(block = this.as_operand(block, scope, &this.thir[f], None))) .collect(); block.and(Rvalue::Aggregate(Box::new(AggregateKind::Array(el_ty)), fields)) @@ -166,7 +219,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let fields: Vec<_> = fields .into_iter() .copied() - .map(|f| unpack!(block = this.as_operand(block, scope, &this.thir[f]))) + .map(|f| unpack!(block = this.as_operand(block, scope, &this.thir[f], None))) .collect(); block.and(Rvalue::Aggregate(Box::new(AggregateKind::Tuple), fields)) @@ -242,7 +295,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { &this.thir[arg], ) ), - _ => unpack!(block = this.as_operand(block, scope, upvar)), + _ => { + unpack!(block = this.as_operand(block, scope, upvar, None)) + } } } } @@ -304,7 +359,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { Category::of(&expr.kind), Some(Category::Rvalue(RvalueFunc::AsRvalue)) )); - let operand = unpack!(block = this.as_operand(block, scope, expr)); + let operand = unpack!(block = this.as_operand(block, scope, expr, None)); block.and(Rvalue::Use(operand)) } } @@ -494,9 +549,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // Helper to get a `-1` value of the appropriate type fn neg_1_literal(&mut self, span: Span, ty: Ty<'tcx>) -> Operand<'tcx> { let param_ty = ty::ParamEnv::empty().and(ty); - let bits = self.tcx.layout_of(param_ty).unwrap().size.bits(); - let n = (!0u128) >> (128 - bits); - let literal = ty::Const::from_bits(self.tcx, n, param_ty); + let size = self.tcx.layout_of(param_ty).unwrap().size; + let literal = ty::Const::from_bits(self.tcx, size.unsigned_int_max(), param_ty); self.literal_operand(span, literal) } diff --git a/compiler/rustc_mir_build/src/build/expr/into.rs b/compiler/rustc_mir_build/src/build/expr/into.rs index e30e758e63..53868f2855 100644 --- a/compiler/rustc_mir_build/src/build/expr/into.rs +++ b/compiler/rustc_mir_build/src/build/expr/into.rs @@ -326,10 +326,16 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let fields_map: FxHashMap<_, _> = fields .into_iter() .map(|f| { + let local_info = Box::new(LocalInfo::AggregateTemp); ( f.name, unpack!( - block = this.as_operand(block, Some(scope), &this.thir[f.expr]) + block = this.as_operand( + block, + Some(scope), + &this.thir[f.expr], + Some(local_info) + ) ), ) }) @@ -443,8 +449,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { }) .collect(); - let destination = this.cfg.start_new_block(); + if !options.contains(InlineAsmOptions::NORETURN) { + this.cfg.push_assign_unit(block, source_info, destination, this.tcx); + } + let destination_block = this.cfg.start_new_block(); this.cfg.terminate( block, source_info, @@ -456,11 +465,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { destination: if options.contains(InlineAsmOptions::NORETURN) { None } else { - Some(destination) + Some(destination_block) }, }, ); - destination.unit() + destination_block.unit() } // These cases don't actually need a destination @@ -508,7 +517,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { ExprKind::Yield { value } => { let scope = this.local_scope(); - let value = unpack!(block = this.as_operand(block, Some(scope), &this.thir[value])); + let value = + unpack!(block = this.as_operand(block, Some(scope), &this.thir[value], None)); let resume = this.cfg.start_new_block(); this.cfg.terminate( block, diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs index ba94e15444..4df073c40e 100644 --- a/compiler/rustc_mir_build/src/build/matches/mod.rs +++ b/compiler/rustc_mir_build/src/build/matches/mod.rs @@ -900,10 +900,7 @@ fn traverse_candidate<'pat, 'tcx: 'pat, C, T, I>( struct Binding<'tcx> { span: Span, source: Place<'tcx>, - name: Symbol, var_id: HirId, - var_ty: Ty<'tcx>, - mutability: Mutability, binding_mode: BindingMode, } @@ -2063,7 +2060,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { source_info.span, ascription.source, ascription.user_ty, ); - let user_ty = ascription.user_ty.clone().user_ty( + let user_ty = ascription.user_ty.user_ty( &mut self.canonical_user_type_annotations, ascription.source.ty(&self.local_decls, self.tcx).ty, source_info.span, diff --git a/compiler/rustc_mir_build/src/build/matches/simplify.rs b/compiler/rustc_mir_build/src/build/matches/simplify.rs index 1feb8b0d7a..4ce26cc8df 100644 --- a/compiler/rustc_mir_build/src/build/matches/simplify.rs +++ b/compiler/rustc_mir_build/src/build/matches/simplify.rs @@ -176,17 +176,22 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { Ok(()) } - PatKind::Binding { name, mutability, mode, var, ty, ref subpattern, is_primary: _ } => { + PatKind::Binding { + name: _, + mutability: _, + mode, + var, + ty: _, + ref subpattern, + is_primary: _, + } => { if let Ok(place_resolved) = match_pair.place.clone().try_upvars_resolved(self.tcx, self.typeck_results) { candidate.bindings.push(Binding { - name, - mutability, span: match_pair.pattern.span, source: place_resolved.into_place(self.tcx, self.typeck_results), var_id: var, - var_ty: ty, binding_mode: mode, }); } diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs index 0a760a740d..4108ad5047 100644 --- a/compiler/rustc_mir_build/src/build/mod.rs +++ b/compiler/rustc_mir_build/src/build/mod.rs @@ -44,13 +44,18 @@ fn mir_build(tcx: TyCtxt<'_>, def: ty::WithOptConstParam) -> Body<'_ let body_owner_kind = tcx.hir().body_owner_kind(id); let typeck_results = tcx.typeck_opt_const_arg(def); - // Ensure unsafeck is ran before we steal the THIR. + // Ensure unsafeck and abstract const building is ran before we steal the THIR. + // We can't use `ensure()` for `thir_abstract_const` as it doesn't compute the query + // if inputs are green. This can cause ICEs when calling `thir_abstract_const` after + // THIR has been stolen if we haven't computed this query yet. match def { ty::WithOptConstParam { did, const_param_did: Some(const_param_did) } => { - tcx.ensure().thir_check_unsafety_for_const_arg((did, const_param_did)) + tcx.ensure().thir_check_unsafety_for_const_arg((did, const_param_did)); + drop(tcx.thir_abstract_const_of_const_arg((did, const_param_did))); } ty::WithOptConstParam { did, const_param_did: None } => { - tcx.ensure().thir_check_unsafety(did) + tcx.ensure().thir_check_unsafety(did); + drop(tcx.thir_abstract_const(did)); } } diff --git a/compiler/rustc_mir_build/src/build/scope.rs b/compiler/rustc_mir_build/src/build/scope.rs index bd8d14fcd0..b74208edaf 100644 --- a/compiler/rustc_mir_build/src/build/scope.rs +++ b/compiler/rustc_mir_build/src/build/scope.rs @@ -118,9 +118,6 @@ struct Scope { /// the region span of this scope within source code. region_scope: region::Scope, - /// the span of that region_scope - region_scope_span: Span, - /// set of places to drop when exiting this scope. This starts /// out empty but grows as variables are declared during the /// building process. This is a stack, so we always drop from the @@ -420,7 +417,6 @@ impl<'tcx> Scopes<'tcx> { self.scopes.push(Scope { source_scope: vis_scope, region_scope: region_scope.0, - region_scope_span: region_scope.1.span, drops: vec![], moved_locals: vec![], cached_unwind_block: None, diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index 05a5fcef16..0e82b18720 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -1,5 +1,5 @@ use crate::build::ExprCategory; -use crate::thir::visit::{self, Visitor}; +use rustc_middle::thir::visit::{self, Visitor}; use rustc_errors::struct_span_err; use rustc_hir as hir; diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index 66005be05d..17296a95bc 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -39,10 +39,17 @@ impl<'tcx> Cx<'tcx> { let mut expr = self.make_mirror_unadjusted(hir_expr); + let adjustment_span = match self.adjustment_span { + Some((hir_id, span)) if hir_id == hir_expr.hir_id => Some(span), + _ => None, + }; + // Now apply adjustments, if any. for adjustment in self.typeck_results.expr_adjustments(hir_expr) { debug!("make_mirror: expr={:?} applying adjustment={:?}", expr, adjustment); - expr = self.apply_adjustment(hir_expr, expr, adjustment); + let span = expr.span; + expr = + self.apply_adjustment(hir_expr, expr, adjustment, adjustment_span.unwrap_or(span)); } // Next, wrap this up in the expr's scope. @@ -82,8 +89,9 @@ impl<'tcx> Cx<'tcx> { hir_expr: &'tcx hir::Expr<'tcx>, mut expr: Expr<'tcx>, adjustment: &Adjustment<'tcx>, + mut span: Span, ) -> Expr<'tcx> { - let Expr { temp_lifetime, mut span, .. } = expr; + let Expr { temp_lifetime, .. } = expr; // Adjust the span from the block, to the last expression of the // block. This is a better span when returning a mutable reference @@ -150,6 +158,7 @@ impl<'tcx> Cx<'tcx> { fn make_mirror_unadjusted(&mut self, expr: &'tcx hir::Expr<'tcx>) -> Expr<'tcx> { let expr_ty = self.typeck_results().expr_ty(expr); + let expr_span = expr.span; let temp_lifetime = self.region_scope_tree.temporary_scope(expr.hir_id.local_id); let kind = match expr.kind { @@ -157,7 +166,13 @@ impl<'tcx> Cx<'tcx> { hir::ExprKind::MethodCall(_, method_span, ref args, fn_span) => { // Rewrite a.b(c) into UFCS form like Trait::b(a, c) let expr = self.method_callee(expr, method_span, None); + // When we apply adjustments to the receiver, use the span of + // the overall method call for better diagnostics. args[0] + // is guaranteed to exist, since a method call always has a receiver. + let old_adjustment_span = self.adjustment_span.replace((args[0].hir_id, expr_span)); + tracing::info!("Using method span: {:?}", expr.span); let args = self.mirror_exprs(args); + self.adjustment_span = old_adjustment_span; ExprKind::Call { ty: expr.ty, fun: self.thir.exprs.push(expr), diff --git a/compiler/rustc_mir_build/src/thir/cx/mod.rs b/compiler/rustc_mir_build/src/thir/cx/mod.rs index 5059dd939d..38a4676bd1 100644 --- a/compiler/rustc_mir_build/src/thir/cx/mod.rs +++ b/compiler/rustc_mir_build/src/thir/cx/mod.rs @@ -9,6 +9,7 @@ use rustc_ast as ast; use rustc_data_structures::steal::Steal; use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; +use rustc_hir::HirId; use rustc_hir::Node; use rustc_middle::middle::region; use rustc_middle::mir::interpret::{LitToConstError, LitToConstInput}; @@ -46,6 +47,14 @@ struct Cx<'tcx> { crate region_scope_tree: &'tcx region::ScopeTree, crate typeck_results: &'tcx ty::TypeckResults<'tcx>, + /// When applying adjustments to the expression + /// with the given `HirId`, use the given `Span`, + /// instead of the usual span. This is used to + /// assign the span of an overall method call + /// (e.g. `my_val.foo()`) to the adjustment expressions + /// for the receiver. + adjustment_span: Option<(HirId, Span)>, + /// The `DefId` of the owner of this body. body_owner: DefId, } @@ -60,6 +69,7 @@ impl<'tcx> Cx<'tcx> { region_scope_tree: tcx.region_scope_tree(def.did), typeck_results, body_owner: def.did.to_def_id(), + adjustment_span: None, } } diff --git a/compiler/rustc_mir_build/src/thir/mod.rs b/compiler/rustc_mir_build/src/thir/mod.rs index e5123d8ef0..ddbe1b0b69 100644 --- a/compiler/rustc_mir_build/src/thir/mod.rs +++ b/compiler/rustc_mir_build/src/thir/mod.rs @@ -11,4 +11,3 @@ crate mod cx; crate mod pattern; mod util; -pub mod visit; 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 b34c1e07be..e28fd2c508 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -1,6 +1,6 @@ +use super::deconstruct_pat::{Constructor, DeconstructedPat}; use super::usefulness::{ - compute_match_usefulness, expand_pattern, is_wildcard, MatchArm, MatchCheckCtxt, Reachability, - UsefulnessReport, + compute_match_usefulness, MatchArm, MatchCheckCtxt, Reachability, UsefulnessReport, }; use super::{PatCtxt, PatternError}; @@ -12,13 +12,12 @@ use rustc_hir::def::*; use rustc_hir::def_id::DefId; use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc_hir::{HirId, Pat}; -use rustc_middle::thir::PatKind; -use rustc_middle::ty::{self, Ty, TyCtxt}; -use rustc_session::lint::builtin::BINDINGS_WITH_VARIANT_NAME; -use rustc_session::lint::builtin::{IRREFUTABLE_LET_PATTERNS, UNREACHABLE_PATTERNS}; +use rustc_middle::ty::{self, AdtDef, Ty, TyCtxt}; +use rustc_session::lint::builtin::{ + BINDINGS_WITH_VARIANT_NAME, IRREFUTABLE_LET_PATTERNS, UNREACHABLE_PATTERNS, +}; use rustc_session::Session; use rustc_span::{DesugaringKind, ExpnKind, Span}; -use std::slice; crate fn check_match(tcx: TyCtxt<'_>, def_id: DefId) { let body_id = match def_id.as_local() { @@ -26,11 +25,12 @@ crate fn check_match(tcx: TyCtxt<'_>, def_id: DefId) { Some(id) => tcx.hir().body_owned_by(tcx.hir().local_def_id_to_hir_id(id)), }; + let pattern_arena = TypedArena::default(); let mut visitor = MatchVisitor { tcx, typeck_results: tcx.typeck_body(body_id), param_env: tcx.param_env(def_id), - pattern_arena: TypedArena::default(), + pattern_arena: &pattern_arena, }; visitor.visit_body(tcx.hir().body(body_id)); } @@ -39,14 +39,21 @@ fn create_e0004(sess: &Session, sp: Span, error_message: String) -> DiagnosticBu struct_span_err!(sess, sp, E0004, "{}", &error_message) } -struct MatchVisitor<'a, 'tcx> { +#[derive(PartialEq)] +enum RefutableFlag { + Irrefutable, + Refutable, +} +use RefutableFlag::*; + +struct MatchVisitor<'a, 'p, 'tcx> { tcx: TyCtxt<'tcx>, typeck_results: &'a ty::TypeckResults<'tcx>, param_env: ty::ParamEnv<'tcx>, - pattern_arena: TypedArena>, + pattern_arena: &'p TypedArena>, } -impl<'tcx> Visitor<'tcx> for MatchVisitor<'_, 'tcx> { +impl<'tcx> Visitor<'tcx> for MatchVisitor<'_, '_, 'tcx> { type Map = intravisit::ErasedMap<'tcx>; fn nested_visit_map(&mut self) -> NestedVisitorMap { @@ -73,13 +80,13 @@ impl<'tcx> Visitor<'tcx> for MatchVisitor<'_, 'tcx> { hir::LocalSource::AssignDesugar(_) => ("destructuring assignment binding", None), }; self.check_irrefutable(&loc.pat, msg, sp); - self.check_patterns(&loc.pat); + 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); + self.check_patterns(¶m.pat, Irrefutable); } } @@ -112,31 +119,30 @@ impl PatCtxt<'_, '_> { } } -impl<'tcx> MatchVisitor<'_, 'tcx> { - fn check_patterns(&self, pat: &Pat<'_>) { +impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> { + fn check_patterns(&self, pat: &Pat<'_>, rf: RefutableFlag) { pat.walk_always(|pat| check_borrow_conflicts_in_at_patterns(self, pat)); - check_for_bindings_named_same_as_variants(self, pat); + check_for_bindings_named_same_as_variants(self, pat, rf); } - fn lower_pattern<'p>( + fn lower_pattern( &self, cx: &mut MatchCheckCtxt<'p, 'tcx>, pat: &'tcx hir::Pat<'tcx>, have_errors: &mut bool, - ) -> (&'p super::Pat<'tcx>, Ty<'tcx>) { + ) -> &'p DeconstructedPat<'p, 'tcx> { let mut patcx = PatCtxt::new(self.tcx, self.param_env, self.typeck_results); patcx.include_lint_checks(); let pattern = patcx.lower_pattern(pat); - let pattern_ty = pattern.ty; - let pattern: &_ = cx.pattern_arena.alloc(expand_pattern(pattern)); + let pattern: &_ = cx.pattern_arena.alloc(DeconstructedPat::from_pat(cx, &pattern)); if !patcx.errors.is_empty() { *have_errors = true; patcx.report_inlining_errors(); } - (pattern, pattern_ty) + pattern } - fn new_cx(&self, hir_id: HirId) -> MatchCheckCtxt<'_, 'tcx> { + fn new_cx(&self, hir_id: HirId) -> MatchCheckCtxt<'p, 'tcx> { MatchCheckCtxt { tcx: self.tcx, param_env: self.param_env, @@ -146,10 +152,10 @@ impl<'tcx> MatchVisitor<'_, 'tcx> { } fn check_let(&mut self, pat: &'tcx hir::Pat<'tcx>, expr: &hir::Expr<'_>, span: Span) { - self.check_patterns(pat); + self.check_patterns(pat, Refutable); let mut cx = self.new_cx(expr.hir_id); - let tpat = self.lower_pattern(&mut cx, pat, &mut false).0; - check_let_reachability(&mut cx, pat.hir_id, &tpat, span); + let tpat = self.lower_pattern(&mut cx, pat, &mut false); + check_let_reachability(&mut cx, pat.hir_id, tpat, span); } fn check_match( @@ -162,11 +168,11 @@ impl<'tcx> MatchVisitor<'_, 'tcx> { for arm in arms { // Check the arm for some things unrelated to exhaustiveness. - self.check_patterns(&arm.pat); + self.check_patterns(&arm.pat, Refutable); if let Some(hir::Guard::IfLet(ref pat, _)) = arm.guard { - self.check_patterns(pat); - let tpat = self.lower_pattern(&mut cx, pat, &mut false).0; - check_let_reachability(&mut cx, pat.hir_id, &tpat, tpat.span); + self.check_patterns(pat, Refutable); + let tpat = self.lower_pattern(&mut cx, pat, &mut false); + check_let_reachability(&mut cx, pat.hir_id, tpat, tpat.span()); } } @@ -175,7 +181,7 @@ impl<'tcx> MatchVisitor<'_, 'tcx> { let arms: Vec<_> = arms .iter() .map(|hir::Arm { pat, guard, .. }| MatchArm { - pat: self.lower_pattern(&mut cx, pat, &mut have_errors).0, + pat: self.lower_pattern(&mut cx, pat, &mut have_errors), hir_id: pat.hir_id, has_guard: guard.is_some(), }) @@ -189,20 +195,16 @@ impl<'tcx> MatchVisitor<'_, 'tcx> { let scrut_ty = self.typeck_results.expr_ty_adjusted(scrut); let report = compute_match_usefulness(&cx, &arms, scrut.hir_id, scrut_ty); - report_arm_reachability(&cx, &report, |_, arm_span, arm_hir_id, catchall| { - match source { - hir::MatchSource::ForLoopDesugar | hir::MatchSource::Normal => { - unreachable_pattern(cx.tcx, arm_span, arm_hir_id, catchall); - } - // Unreachable patterns in try and await expressions occur when one of - // the arms are an uninhabited type. Which is OK. - hir::MatchSource::AwaitDesugar | hir::MatchSource::TryDesugar => {} + match source { + hir::MatchSource::ForLoopDesugar | hir::MatchSource::Normal => { + report_arm_reachability(&cx, &report) } - }); + // Unreachable patterns in try and await expressions occur when one of + // the arms are an uninhabited type. Which is OK. + hir::MatchSource::AwaitDesugar | hir::MatchSource::TryDesugar => {} + } // Check if the match is exhaustive. - // Note: An empty match isn't the same as an empty matrix for diagnostics purposes, - // since an empty matrix can occur when there are arms, if those arms all have guards. let is_empty_match = arms.is_empty(); let witnesses = report.non_exhaustiveness_witnesses; if !witnesses.is_empty() { @@ -213,7 +215,8 @@ impl<'tcx> MatchVisitor<'_, 'tcx> { fn check_irrefutable(&self, pat: &'tcx Pat<'tcx>, origin: &str, sp: Option) { let mut cx = self.new_cx(pat.hir_id); - let (pattern, pattern_ty) = self.lower_pattern(&mut cx, pat, &mut false); + let pattern = self.lower_pattern(&mut cx, pat, &mut false); + let pattern_ty = pattern.ty(); let arms = vec![MatchArm { pat: pattern, hir_id: pat.hir_id, has_guard: false }]; let report = compute_match_usefulness(&cx, &arms, pat.hir_id, pattern_ty); @@ -225,7 +228,7 @@ impl<'tcx> MatchVisitor<'_, 'tcx> { return; } - let joined_patterns = joined_uncovered_patterns(&witnesses); + let joined_patterns = joined_uncovered_patterns(&cx, &witnesses); let mut err = struct_span_err!( self.tcx.sess, pat.span, @@ -301,7 +304,11 @@ fn const_not_var( } } -fn check_for_bindings_named_same_as_variants(cx: &MatchVisitor<'_, '_>, pat: &Pat<'_>) { +fn check_for_bindings_named_same_as_variants( + cx: &MatchVisitor<'_, '_, '_>, + pat: &Pat<'_>, + rf: RefutableFlag, +) { pat.walk_always(|p| { if let hir::PatKind::Binding(_, _, ident, None) = p.kind { if let Some(ty::BindByValue(hir::Mutability::Not)) = @@ -314,25 +321,31 @@ fn check_for_bindings_named_same_as_variants(cx: &MatchVisitor<'_, '_>, pat: &Pa variant.ident == ident && variant.ctor_kind == CtorKind::Const }) { + let variant_count = edef.variants.len(); cx.tcx.struct_span_lint_hir( BINDINGS_WITH_VARIANT_NAME, p.hir_id, p.span, |lint| { let ty_path = cx.tcx.def_path_str(edef.did); - lint.build(&format!( + let mut err = lint.build(&format!( "pattern binding `{}` is named the same as one \ - of the variants of the type `{}`", + of the variants of the type `{}`", ident, ty_path - )) - .code(error_code!(E0170)) - .span_suggestion( - p.span, - "to match on the variant, qualify the path", - format!("{}::{}", ty_path, ident), - Applicability::MachineApplicable, - ) - .emit(); + )); + err.code(error_code!(E0170)); + // If this is an irrefutable pattern, and there's > 1 variant, + // then we can't actually match on this. Applying the below + // suggestion would produce code that breaks on `check_irrefutable`. + if rf == Refutable || variant_count == 1 { + err.span_suggestion( + p.span, + "to match on the variant, qualify the path", + format!("{}::{}", ty_path, ident), + Applicability::MachineApplicable, + ); + } + err.emit(); }, ) } @@ -343,12 +356,11 @@ fn check_for_bindings_named_same_as_variants(cx: &MatchVisitor<'_, '_>, pat: &Pa } /// Checks for common cases of "catchall" patterns that may not be intended as such. -fn pat_is_catchall(pat: &super::Pat<'_>) -> bool { - use PatKind::*; - match &*pat.kind { - Binding { subpattern: None, .. } => true, - Binding { subpattern: Some(s), .. } | Deref { subpattern: s } => pat_is_catchall(s), - Leaf { subpatterns: s } => s.iter().all(|p| pat_is_catchall(&p.pattern)), +fn pat_is_catchall(pat: &DeconstructedPat<'_, '_>) -> bool { + use Constructor::*; + match pat.ctor() { + Wildcard => true, + Single => pat.iter_fields().all(|pat| pat_is_catchall(pat)), _ => false, } } @@ -427,29 +439,16 @@ fn irrefutable_let_pattern(tcx: TyCtxt<'_>, id: HirId, span: Span) { fn check_let_reachability<'p, 'tcx>( cx: &mut MatchCheckCtxt<'p, 'tcx>, pat_id: HirId, - pat: &'p super::Pat<'tcx>, + pat: &'p DeconstructedPat<'p, 'tcx>, span: Span, ) { let arms = [MatchArm { pat, hir_id: pat_id, has_guard: false }]; - let report = compute_match_usefulness(&cx, &arms, pat_id, pat.ty); + let report = compute_match_usefulness(&cx, &arms, pat_id, pat.ty()); - report_arm_reachability(&cx, &report, |arm_index, arm_span, arm_hir_id, _| { - match let_source(cx.tcx, pat_id) { - LetSource::IfLet | LetSource::WhileLet => { - match arm_index { - // The arm with the user-specified pattern. - 0 => unreachable_pattern(cx.tcx, arm_span, arm_hir_id, None), - // The arm with the wildcard pattern. - 1 => irrefutable_let_pattern(cx.tcx, pat_id, arm_span), - _ => bug!(), - } - } - LetSource::IfLetGuard if arm_index == 0 => { - unreachable_pattern(cx.tcx, arm_span, arm_hir_id, None); - } - _ => {} - } - }); + // Report if the pattern is unreachable, which can only occur when the type is uninhabited. + // This also reports unreachable sub-patterns though, so we can't just replace it with an + // `is_uninhabited` check. + report_arm_reachability(&cx, &report); if report.non_exhaustiveness_witnesses.is_empty() { // The match is exhaustive, i.e. the `if let` pattern is irrefutable. @@ -458,18 +457,15 @@ fn check_let_reachability<'p, 'tcx>( } /// Report unreachable arms, if any. -fn report_arm_reachability<'p, 'tcx, F>( +fn report_arm_reachability<'p, 'tcx>( cx: &MatchCheckCtxt<'p, 'tcx>, report: &UsefulnessReport<'p, 'tcx>, - unreachable: F, -) where - F: Fn(usize, Span, HirId, Option), -{ +) { use Reachability::*; let mut catchall = None; - for (arm_index, (arm, is_useful)) in report.arm_usefulness.iter().enumerate() { + for (arm, is_useful) in report.arm_usefulness.iter() { match is_useful { - Unreachable => unreachable(arm_index, arm.pat.span, arm.hir_id, catchall), + Unreachable => unreachable_pattern(cx.tcx, arm.pat.span(), arm.hir_id, catchall), Reachable(unreachables) if unreachables.is_empty() => {} // The arm is reachable, but contains unreachable subpatterns (from or-patterns). Reachable(unreachables) => { @@ -482,7 +478,7 @@ fn report_arm_reachability<'p, 'tcx, F>( } } if !arm.has_guard && catchall.is_none() && pat_is_catchall(arm.pat) { - catchall = Some(arm.pat.span); + catchall = Some(arm.pat.span()); } } } @@ -492,7 +488,7 @@ fn non_exhaustive_match<'p, 'tcx>( cx: &MatchCheckCtxt<'p, 'tcx>, scrut_ty: Ty<'tcx>, sp: Span, - witnesses: Vec>, + witnesses: Vec>, is_empty_match: bool, ) { let non_empty_enum = match scrut_ty.kind() { @@ -509,7 +505,7 @@ fn non_exhaustive_match<'p, 'tcx>( format!("non-exhaustive patterns: type `{}` is non-empty", scrut_ty), ); } else { - let joined_patterns = joined_uncovered_patterns(&witnesses); + let joined_patterns = joined_uncovered_patterns(cx, &witnesses); err = create_e0004( cx.tcx.sess, sp, @@ -536,7 +532,7 @@ fn non_exhaustive_match<'p, 'tcx>( if (scrut_ty == cx.tcx.types.usize || scrut_ty == cx.tcx.types.isize) && !is_empty_match && witnesses.len() == 1 - && is_wildcard(&witnesses[0]) + && matches!(witnesses[0].ctor(), Constructor::NonExhaustive) { err.note(&format!( "`{}` does not have a fixed maximum value, \ @@ -559,33 +555,40 @@ fn non_exhaustive_match<'p, 'tcx>( err.emit(); } -fn joined_uncovered_patterns(witnesses: &[super::Pat<'_>]) -> String { +crate fn joined_uncovered_patterns<'p, 'tcx>( + cx: &MatchCheckCtxt<'p, 'tcx>, + witnesses: &[DeconstructedPat<'p, 'tcx>], +) -> String { const LIMIT: usize = 3; + let pat_to_str = |pat: &DeconstructedPat<'p, 'tcx>| pat.to_pat(cx).to_string(); match witnesses { [] => bug!(), - [witness] => format!("`{}`", witness), + [witness] => format!("`{}`", witness.to_pat(cx)), [head @ .., tail] if head.len() < LIMIT => { - let head: Vec<_> = head.iter().map(<_>::to_string).collect(); - format!("`{}` and `{}`", head.join("`, `"), tail) + let head: Vec<_> = head.iter().map(pat_to_str).collect(); + format!("`{}` and `{}`", head.join("`, `"), tail.to_pat(cx)) } _ => { let (head, tail) = witnesses.split_at(LIMIT); - let head: Vec<_> = head.iter().map(<_>::to_string).collect(); + let head: Vec<_> = head.iter().map(pat_to_str).collect(); format!("`{}` and {} more", head.join("`, `"), tail.len()) } } } -fn pattern_not_covered_label(witnesses: &[super::Pat<'_>], joined_patterns: &str) -> String { +crate fn pattern_not_covered_label( + witnesses: &[DeconstructedPat<'_, '_>], + joined_patterns: &str, +) -> String { format!("pattern{} {} not covered", rustc_errors::pluralize!(witnesses.len()), joined_patterns) } /// Point at the definition of non-covered `enum` variants. -fn adt_defined_here( - cx: &MatchCheckCtxt<'_, '_>, +fn adt_defined_here<'p, 'tcx>( + cx: &MatchCheckCtxt<'p, 'tcx>, err: &mut DiagnosticBuilder<'_>, - ty: Ty<'_>, - witnesses: &[super::Pat<'_>], + ty: Ty<'tcx>, + witnesses: &[DeconstructedPat<'p, 'tcx>], ) { let ty = ty.peel_refs(); if let ty::Adt(def, _) = ty.kind() { @@ -594,57 +597,42 @@ fn adt_defined_here( } if witnesses.len() < 4 { - for sp in maybe_point_at_variant(ty, &witnesses) { + for sp in maybe_point_at_variant(cx, def, witnesses.iter()) { err.span_label(sp, "not covered"); } } } } -fn maybe_point_at_variant(ty: Ty<'_>, patterns: &[super::Pat<'_>]) -> Vec { +fn maybe_point_at_variant<'a, 'p: 'a, 'tcx: 'a>( + cx: &MatchCheckCtxt<'p, 'tcx>, + def: &AdtDef, + patterns: impl Iterator>, +) -> Vec { + use Constructor::*; let mut covered = vec![]; - if let ty::Adt(def, _) = ty.kind() { - // Don't point at variants that have already been covered due to other patterns to avoid - // visual clutter. - for pattern in patterns { - use PatKind::{AscribeUserType, Deref, Leaf, Or, Variant}; - match &*pattern.kind { - AscribeUserType { subpattern, .. } | Deref { subpattern } => { - covered.extend(maybe_point_at_variant(ty, slice::from_ref(&subpattern))); + for pattern in patterns { + if let Variant(variant_index) = pattern.ctor() { + if let ty::Adt(this_def, _) = pattern.ty().kind() { + if this_def.did != def.did { + continue; } - Variant { adt_def, variant_index, subpatterns, .. } if adt_def.did == def.did => { - let sp = def.variants[*variant_index].ident.span; - if covered.contains(&sp) { - continue; - } - covered.push(sp); - - let pats = subpatterns - .iter() - .map(|field_pattern| field_pattern.pattern.clone()) - .collect::>(); - covered.extend(maybe_point_at_variant(ty, &pats)); - } - Leaf { subpatterns } => { - let pats = subpatterns - .iter() - .map(|field_pattern| field_pattern.pattern.clone()) - .collect::>(); - covered.extend(maybe_point_at_variant(ty, &pats)); - } - Or { pats } => { - let pats = pats.iter().cloned().collect::>(); - covered.extend(maybe_point_at_variant(ty, &pats)); - } - _ => {} } + let sp = def.variants[*variant_index].ident.span; + if covered.contains(&sp) { + // Don't point at variants that have already been covered due to other patterns to avoid + // visual clutter. + continue; + } + covered.push(sp); } + covered.extend(maybe_point_at_variant(cx, def, pattern.iter_fields())); } covered } /// Check if a by-value binding is by-value. That is, check if the binding's type is not `Copy`. -fn is_binding_by_move(cx: &MatchVisitor<'_, '_>, hir_id: HirId, span: Span) -> bool { +fn is_binding_by_move(cx: &MatchVisitor<'_, '_, '_>, hir_id: HirId, span: Span) -> bool { !cx.typeck_results.node_type(hir_id).is_copy_modulo_regions(cx.tcx.at(span), cx.param_env) } @@ -658,7 +646,7 @@ fn is_binding_by_move(cx: &MatchVisitor<'_, '_>, hir_id: HirId, span: Span) -> b /// - `x @ Some(ref mut? y)`. /// /// This analysis is *not* subsumed by NLL. -fn check_borrow_conflicts_in_at_patterns(cx: &MatchVisitor<'_, '_>, pat: &Pat<'_>) { +fn check_borrow_conflicts_in_at_patterns(cx: &MatchVisitor<'_, '_, '_>, pat: &Pat<'_>) { // Extract `sub` in `binding @ sub`. let (name, sub) = match &pat.kind { hir::PatKind::Binding(.., name, Some(sub)) => (*name, sub), 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 bbb5de34d1..847b89f046 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 @@ -322,16 +322,18 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> { && !self.saw_const_match_lint.get() { self.saw_const_match_lint.set(true); - let msg = format!( - "to use a constant of type `{}` in a pattern, \ - `{}` must be annotated with `#[derive(PartialEq, Eq)]`", - cv.ty, cv.ty, - ); tcx.struct_span_lint_hir( lint::builtin::INDIRECT_STRUCTURAL_MATCH, id, span, - |lint| lint.build(&msg).emit(), + |lint| { + let msg = format!( + "to use a constant of type `{}` in a pattern, \ + `{}` must be annotated with `#[derive(PartialEq, Eq)]`", + cv.ty, cv.ty, + ); + lint.build(&msg).emit() + }, ); } // Since we are behind a reference, we can just bubble the error up so we get a diff --git a/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs index ace13ea446..368e3957dd 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs @@ -46,26 +46,45 @@ use self::Constructor::*; use self::SliceKind::*; use super::compare_const_vals; -use super::usefulness::{is_wildcard, MatchCheckCtxt, PatCtxt}; +use super::usefulness::{MatchCheckCtxt, PatCtxt}; use rustc_data_structures::captures::Captures; use rustc_index::vec::Idx; use rustc_hir::{HirId, RangeEnd}; -use rustc_middle::mir::interpret::ConstValue; use rustc_middle::mir::Field; use rustc_middle::thir::{FieldPat, Pat, PatKind, PatRange}; use rustc_middle::ty::layout::IntegerExt; -use rustc_middle::ty::{self, Const, Ty, TyCtxt}; +use rustc_middle::ty::{self, Const, Ty, TyCtxt, VariantDef}; +use rustc_middle::{middle::stability::EvalResult, mir::interpret::ConstValue}; use rustc_session::lint; use rustc_span::{Span, DUMMY_SP}; use rustc_target::abi::{Integer, Size, VariantIdx}; use smallvec::{smallvec, SmallVec}; +use std::cell::Cell; use std::cmp::{self, max, min, Ordering}; +use std::fmt; use std::iter::{once, IntoIterator}; use std::ops::RangeInclusive; +/// Recursively expand this pattern into its subpatterns. Only useful for or-patterns. +fn expand_or_pat<'p, 'tcx>(pat: &'p Pat<'tcx>) -> Vec<&'p Pat<'tcx>> { + fn expand<'p, 'tcx>(pat: &'p Pat<'tcx>, vec: &mut Vec<&'p Pat<'tcx>>) { + if let PatKind::Or { pats } = pat.kind.as_ref() { + for pat in pats { + expand(pat, vec); + } + } else { + vec.push(pat) + } + } + + let mut pats = Vec::new(); + expand(pat, &mut pats); + pats +} + /// An inclusive interval, used for precise integer exhaustiveness checking. /// `IntRange`s always store a contiguous range. This means that values are /// encoded such that `0` encodes the minimum value for the integer, @@ -76,9 +95,13 @@ use std::ops::RangeInclusive; /// /// `IntRange` is never used to encode an empty range or a "range" that wraps /// around the (offset) space: i.e., `range.lo <= range.hi`. -#[derive(Clone, Debug, PartialEq, Eq)] +#[derive(Clone, PartialEq, Eq)] pub(super) struct IntRange { range: RangeInclusive, + /// Keeps the bias used for encoding the range. It depends on the type of the range and + /// possibly the pointer size of the current architecture. The algorithm ensures we never + /// compare `IntRange`s with different types/architectures. + bias: u128, } impl IntRange { @@ -131,7 +154,7 @@ impl IntRange { value.try_eval_bits(tcx, param_env, ty) })()?; let val = val ^ bias; - Some(IntRange { range: val..=val }) + Some(IntRange { range: val..=val, bias }) } else { None } @@ -155,7 +178,7 @@ impl IntRange { // This should have been caught earlier by E0030. bug!("malformed range pattern: {}..={}", lo, (hi - offset)); } - Some(IntRange { range: lo..=(hi - offset) }) + Some(IntRange { range: lo..=(hi - offset), bias }) } else { None } @@ -180,7 +203,7 @@ impl IntRange { let (lo, hi) = self.boundaries(); let (other_lo, other_hi) = other.boundaries(); if lo <= other_hi && other_lo <= hi { - Some(IntRange { range: max(lo, other_lo)..=min(hi, other_hi) }) + Some(IntRange { range: max(lo, other_lo)..=min(hi, other_hi), bias: self.bias }) } else { None } @@ -203,10 +226,11 @@ impl IntRange { (lo == other_hi || hi == other_lo) && !self.is_singleton() && !other.is_singleton() } + /// Only used for displaying the range properly. fn to_pat<'tcx>(&self, tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Pat<'tcx> { let (lo, hi) = self.boundaries(); - let bias = IntRange::signed_bias(tcx, ty); + let bias = self.bias; let (lo, hi) = (lo ^ bias, hi ^ bias); let env = ty::ParamEnv::empty().and(ty); @@ -223,10 +247,10 @@ impl IntRange { } /// Lint on likely incorrect range patterns (#63987) - pub(super) fn lint_overlapping_range_endpoints<'a, 'tcx: 'a>( + pub(super) fn lint_overlapping_range_endpoints<'a, 'p: 'a, 'tcx: 'a>( &self, - pcx: PatCtxt<'_, '_, 'tcx>, - ctors: impl Iterator, Span)>, + pcx: PatCtxt<'_, 'p, 'tcx>, + pats: impl Iterator>, column_count: usize, hir_id: HirId, ) { @@ -248,8 +272,8 @@ impl IntRange { return; } - let overlaps: Vec<_> = ctors - .filter_map(|(ctor, span)| Some((ctor.as_int_range()?, span))) + let overlaps: Vec<_> = pats + .filter_map(|pat| Some((pat.ctor().as_int_range()?, pat.span()))) .filter(|(range, _)| self.suspicious_intersection(range)) .map(|(range, span)| (self.intersection(&range).unwrap(), span)) .collect(); @@ -291,6 +315,19 @@ impl IntRange { } } +/// Note: this is often not what we want: e.g. `false` is converted into the range `0..=0` and +/// would be displayed as such. To render properly, convert to a pattern first. +impl fmt::Debug for IntRange { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let (lo, hi) = self.boundaries(); + let bias = self.bias; + let (lo, hi) = (lo ^ bias, hi ^ bias); + write!(f, "{}", lo)?; + write!(f, "{}", RangeEnd::Included)?; + write!(f, "{}", hi) + } +} + /// Represents a border between 2 integers. Because the intervals spanning borders must be able to /// cover every integer, we need to be able to represent 2^128 + 1 such borders. #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] @@ -375,13 +412,13 @@ impl SplitIntRange { // Skip duplicates. .filter(|(prev_border, border)| prev_border != border) // Finally, convert to ranges. - .map(|(prev_border, border)| { + .map(move |(prev_border, border)| { let range = match (prev_border, border) { (JustBefore(n), JustBefore(m)) if n < m => n..=(m - 1), (JustBefore(n), AfterMax) => n..=u128::MAX, _ => unreachable!(), // Ruled out by the sorting and filtering we did }; - IntRange { range } + IntRange { range, bias: self.range.bias } }) } } @@ -389,17 +426,17 @@ impl SplitIntRange { #[derive(Copy, Clone, Debug, PartialEq, Eq)] enum SliceKind { /// Patterns of length `n` (`[x, y]`). - FixedLen(u64), + FixedLen(usize), /// Patterns using the `..` notation (`[x, .., y]`). /// Captures any array constructor of `length >= i + j`. /// In the case where `array_len` is `Some(_)`, /// this indicates that we only care about the first `i` and the last `j` values of the array, /// and everything in between is a wildcard `_`. - VarLen(u64, u64), + VarLen(usize, usize), } impl SliceKind { - fn arity(self) -> u64 { + fn arity(self) -> usize { match self { FixedLen(length) => length, VarLen(prefix, suffix) => prefix + suffix, @@ -407,7 +444,7 @@ impl SliceKind { } /// Whether this pattern includes patterns of length `other_len`. - fn covers_length(self, other_len: u64) -> bool { + fn covers_length(self, other_len: usize) -> bool { match self { FixedLen(len) => len == other_len, VarLen(prefix, suffix) => prefix + suffix <= other_len, @@ -419,13 +456,13 @@ impl SliceKind { #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub(super) struct Slice { /// `None` if the matched value is a slice, `Some(n)` if it is an array of size `n`. - array_len: Option, + array_len: Option, /// The kind of pattern it is: fixed-length `[x, y]` or variable length `[x, .., y]`. kind: SliceKind, } impl Slice { - fn new(array_len: Option, kind: SliceKind) -> Self { + fn new(array_len: Option, kind: SliceKind) -> Self { let kind = match (array_len, kind) { // If the middle `..` is empty, we effectively have a fixed-length pattern. (Some(len), VarLen(prefix, suffix)) if prefix + suffix >= len => FixedLen(len), @@ -434,7 +471,7 @@ impl Slice { Slice { array_len, kind } } - fn arity(self) -> u64 { + fn arity(self) -> usize { self.kind.arity() } @@ -508,16 +545,16 @@ impl Slice { #[derive(Debug)] struct SplitVarLenSlice { /// If the type is an array, this is its size. - array_len: Option, + array_len: Option, /// The arity of the input slice. - arity: u64, + arity: usize, /// The smallest slice bigger than any slice seen. `max_slice.arity()` is the length `L` /// described above. max_slice: SliceKind, } impl SplitVarLenSlice { - fn new(prefix: u64, suffix: u64, array_len: Option) -> Self { + fn new(prefix: usize, suffix: usize, array_len: Option) -> Self { SplitVarLenSlice { array_len, arity: prefix + suffix, max_slice: VarLen(prefix, suffix) } } @@ -606,10 +643,13 @@ pub(super) enum Constructor<'tcx> { /// for those types for which we cannot list constructors explicitly, like `f64` and `str`. NonExhaustive, /// Stands for constructors that are not seen in the matrix, as explained in the documentation - /// for [`SplitWildcard`]. - Missing, + /// for [`SplitWildcard`]. The carried `bool` is used for the `non_exhaustive_omitted_patterns` + /// lint. + Missing { nonexhaustive_enum_missing_real_variants: bool }, /// Wildcard pattern. Wildcard, + /// Or-pattern. + Or, } impl<'tcx> Constructor<'tcx> { @@ -617,6 +657,10 @@ impl<'tcx> Constructor<'tcx> { matches!(self, Wildcard) } + pub(super) fn is_non_exhaustive(&self) -> bool { + matches!(self, NonExhaustive) + } + fn as_int_range(&self) -> Option<&IntRange> { match self { IntRange(range) => Some(range), @@ -631,6 +675,36 @@ impl<'tcx> Constructor<'tcx> { } } + /// Checks if the `Constructor` is a variant and `TyCtxt::eval_stability` returns + /// `EvalResult::Deny { .. }`. + /// + /// This means that the variant has a stdlib unstable feature marking it. + pub(super) fn is_unstable_variant(&self, pcx: PatCtxt<'_, '_, 'tcx>) -> bool { + if let Constructor::Variant(idx) = self { + if let ty::Adt(adt, _) = pcx.ty.kind() { + let variant_def_id = adt.variants[*idx].def_id; + // Filter variants that depend on a disabled unstable feature. + return matches!( + pcx.cx.tcx.eval_stability(variant_def_id, None, DUMMY_SP, None), + EvalResult::Deny { .. } + ); + } + } + false + } + + /// Checks if the `Constructor` is a `Constructor::Variant` with a `#[doc(hidden)]` + /// attribute. + pub(super) fn is_doc_hidden_variant(&self, pcx: PatCtxt<'_, '_, 'tcx>) -> bool { + if let Constructor::Variant(idx) = self { + if let ty::Adt(adt, _) = pcx.ty.kind() { + let variant_def_id = adt.variants[*idx].def_id; + return pcx.cx.tcx.is_doc_hidden(variant_def_id); + } + } + false + } + fn variant_index_for_adt(&self, adt: &'tcx ty::AdtDef) -> VariantIdx { match *self { Variant(idx) => idx, @@ -642,60 +716,34 @@ impl<'tcx> Constructor<'tcx> { } } - /// Determines the constructor that the given pattern can be specialized to. - pub(super) fn from_pat<'p>(cx: &MatchCheckCtxt<'p, 'tcx>, pat: &'p Pat<'tcx>) -> Self { - match pat.kind.as_ref() { - PatKind::AscribeUserType { .. } => bug!(), // Handled by `expand_pattern` - PatKind::Binding { .. } | PatKind::Wild => Wildcard, - PatKind::Leaf { .. } | PatKind::Deref { .. } => Single, - &PatKind::Variant { variant_index, .. } => Variant(variant_index), - PatKind::Constant { value } => { - if let Some(int_range) = IntRange::from_const(cx.tcx, cx.param_env, value) { - IntRange(int_range) - } else { - match pat.ty.kind() { - ty::Float(_) => FloatRange(value, value, RangeEnd::Included), - // In `expand_pattern`, we convert string literals to `&CONST` patterns with - // `CONST` a pattern of type `str`. In truth this contains a constant of type - // `&str`. - ty::Str => Str(value), - // All constants that can be structurally matched have already been expanded - // into the corresponding `Pat`s by `const_to_pat`. Constants that remain are - // opaque. - _ => Opaque, + /// The number of fields for this constructor. This must be kept in sync with + /// `Fields::wildcards`. + pub(super) fn arity(&self, pcx: PatCtxt<'_, '_, 'tcx>) -> usize { + match self { + Single | Variant(_) => match pcx.ty.kind() { + ty::Tuple(fs) => fs.len(), + ty::Ref(..) => 1, + ty::Adt(adt, ..) => { + if adt.is_box() { + // The only legal patterns of type `Box` (outside `std`) are `_` and box + // patterns. If we're here we can assume this is a box pattern. + 1 + } else { + let variant = &adt.variants[self.variant_index_for_adt(adt)]; + Fields::list_variant_nonhidden_fields(pcx.cx, pcx.ty, variant).count() } } - } - &PatKind::Range(PatRange { lo, hi, end }) => { - let ty = lo.ty; - if let Some(int_range) = IntRange::from_range( - cx.tcx, - lo.eval_bits(cx.tcx, cx.param_env, lo.ty), - hi.eval_bits(cx.tcx, cx.param_env, hi.ty), - ty, - &end, - ) { - IntRange(int_range) - } else { - FloatRange(lo, hi, end) - } - } - PatKind::Array { prefix, slice, suffix } | PatKind::Slice { prefix, slice, suffix } => { - let array_len = match pat.ty.kind() { - ty::Array(_, length) => Some(length.eval_usize(cx.tcx, cx.param_env)), - ty::Slice(_) => None, - _ => span_bug!(pat.span, "bad ty {:?} for slice pattern", pat.ty), - }; - let prefix = prefix.len() as u64; - let suffix = suffix.len() as u64; - let kind = if slice.is_some() { - VarLen(prefix, suffix) - } else { - FixedLen(prefix + suffix) - }; - Slice(Slice::new(array_len, kind)) - } - PatKind::Or { .. } => bug!("Or-pattern should have been expanded earlier on."), + _ => bug!("Unexpected type for `Single` constructor: {:?}", pcx.ty), + }, + Slice(slice) => slice.arity(), + Str(..) + | FloatRange(..) + | IntRange(..) + | NonExhaustive + | Opaque + | Missing { .. } + | Wildcard => 0, + Or => bug!("The `Or` constructor doesn't have a fixed arity"), } } @@ -756,7 +804,7 @@ impl<'tcx> Constructor<'tcx> { // Wildcards cover anything (_, Wildcard) => true, // The missing ctors are not covered by anything in the matrix except wildcards. - (Missing | Wildcard, _) => false, + (Missing { .. } | Wildcard, _) => false, (Single, Single) => true, (Variant(self_id), Variant(other_id)) => self_id == other_id, @@ -818,7 +866,7 @@ impl<'tcx> Constructor<'tcx> { match self { // If `self` is `Single`, `used_ctors` cannot contain anything else than `Single`s. Single => !used_ctors.is_empty(), - Variant(_) => used_ctors.iter().any(|c| c == self), + Variant(vid) => used_ctors.iter().any(|c| matches!(c, Variant(i) if i == vid)), IntRange(range) => used_ctors .iter() .filter_map(|c| c.as_int_range()) @@ -829,7 +877,7 @@ impl<'tcx> Constructor<'tcx> { .any(|other| slice.is_covered_by(other)), // This constructor is never covered by anything else NonExhaustive => false, - Str(..) | FloatRange(..) | Opaque | Missing | Wildcard => { + Str(..) | FloatRange(..) | Opaque | Missing { .. } | Wildcard | Or => { span_bug!(pcx.span, "found unexpected ctor in all_ctors: {:?}", self) } } @@ -880,7 +928,7 @@ impl<'tcx> SplitWildcard<'tcx> { let all_ctors = match pcx.ty.kind() { ty::Bool => smallvec![make_range(0, 1)], ty::Array(sub_ty, len) if len.try_eval_usize(cx.tcx, cx.param_env).is_some() => { - let len = len.eval_usize(cx.tcx, cx.param_env); + let len = len.eval_usize(cx.tcx, cx.param_env) as usize; if len != 0 && cx.is_uninhabited(sub_ty) { smallvec![] } else { @@ -911,30 +959,33 @@ impl<'tcx> SplitWildcard<'tcx> { // witness. let is_declared_nonexhaustive = cx.is_foreign_non_exhaustive_enum(pcx.ty); + let is_exhaustive_pat_feature = cx.tcx.features().exhaustive_patterns; + // If `exhaustive_patterns` is disabled and our scrutinee is an empty enum, we treat it // as though it had an "unknown" constructor to avoid exposing its emptiness. The // exception is if the pattern is at the top level, because we want empty matches to be // considered exhaustive. - let is_secretly_empty = def.variants.is_empty() - && !cx.tcx.features().exhaustive_patterns - && !pcx.is_top_level; + let is_secretly_empty = + def.variants.is_empty() && !is_exhaustive_pat_feature && !pcx.is_top_level; + + let mut ctors: SmallVec<[_; 1]> = def + .variants + .iter_enumerated() + .filter(|(_, v)| { + // If `exhaustive_patterns` is enabled, we exclude variants known to be + // uninhabited. + let is_uninhabited = is_exhaustive_pat_feature + && v.uninhabited_from(cx.tcx, substs, def.adt_kind(), cx.param_env) + .contains(cx.tcx, cx.module); + !is_uninhabited + }) + .map(|(idx, _)| Variant(idx)) + .collect(); if is_secretly_empty || is_declared_nonexhaustive { - smallvec![NonExhaustive] - } else if cx.tcx.features().exhaustive_patterns { - // If `exhaustive_patterns` is enabled, we exclude variants known to be - // uninhabited. - def.variants - .iter_enumerated() - .filter(|(_, v)| { - !v.uninhabited_from(cx.tcx, substs, def.adt_kind(), cx.param_env) - .contains(cx.tcx, cx.module) - }) - .map(|(idx, _)| Variant(idx)) - .collect() - } else { - def.variants.indices().map(|idx| Variant(idx)).collect() + ctors.push(NonExhaustive); } + ctors } ty::Char => { smallvec![ @@ -975,6 +1026,7 @@ impl<'tcx> SplitWildcard<'tcx> { // This type is one for which we cannot list constructors, like `str` or `f64`. _ => smallvec![NonExhaustive], }; + SplitWildcard { matrix_ctors: Vec::new(), all_ctors } } @@ -1039,7 +1091,15 @@ impl<'tcx> SplitWildcard<'tcx> { // sometimes prefer reporting the list of constructors instead of just `_`. let report_when_all_missing = pcx.is_top_level && !IntRange::is_integral(pcx.ty); let ctor = if !self.matrix_ctors.is_empty() || report_when_all_missing { - Missing + if pcx.is_non_exhaustive { + Missing { + nonexhaustive_enum_missing_real_variants: self + .iter_missing(pcx) + .any(|c| !(c.is_non_exhaustive() || c.is_unstable_variant(pcx))), + } + } else { + Missing { nonexhaustive_enum_missing_real_variants: false } + } } else { Wildcard }; @@ -1051,120 +1111,108 @@ impl<'tcx> SplitWildcard<'tcx> { } } -/// Some fields need to be explicitly hidden away in certain cases; see the comment above the -/// `Fields` struct. This struct represents such a potentially-hidden field. -#[derive(Debug, Copy, Clone)] -pub(super) enum FilteredField<'p, 'tcx> { - Kept(&'p Pat<'tcx>), - Hidden, -} - -impl<'p, 'tcx> FilteredField<'p, 'tcx> { - fn kept(self) -> Option<&'p Pat<'tcx>> { - match self { - FilteredField::Kept(p) => Some(p), - FilteredField::Hidden => None, - } - } -} - /// A value can be decomposed into a constructor applied to some fields. This struct represents /// those fields, generalized to allow patterns in each field. See also `Constructor`. -/// This is constructed from a constructor using [`Fields::wildcards()`]. /// -/// If a private or `non_exhaustive` field is uninhabited, the code mustn't observe that it is -/// uninhabited. For that, we filter these fields out of the matrix. This is handled automatically -/// in `Fields`. This filtering is uncommon in practice, because uninhabited fields are rarely used, -/// so we avoid it when possible to preserve performance. -#[derive(Debug, Clone)] -pub(super) enum Fields<'p, 'tcx> { - /// Lists of patterns that don't contain any filtered fields. - /// `Slice` and `Vec` behave the same; the difference is only to avoid allocating and - /// triple-dereferences when possible. Frankly this is premature optimization, I (Nadrieril) - /// have not measured if it really made a difference. - Slice(&'p [Pat<'tcx>]), - Vec(SmallVec<[&'p Pat<'tcx>; 2]>), - /// Patterns where some of the fields need to be hidden. For all intents and purposes we only - /// care about the non-hidden fields. We need to keep the real field index for those fields; - /// we're morally storing a `Vec<(usize, &Pat)>` but what we do is more convenient. - /// `len` counts the number of non-hidden fields - Filtered { - fields: SmallVec<[FilteredField<'p, 'tcx>; 2]>, - len: usize, - }, +/// This is constructed for a constructor using [`Fields::wildcards()`]. The idea is that +/// [`Fields::wildcards()`] constructs a list of fields where all entries are wildcards, and then +/// given a pattern we fill some of the fields with its subpatterns. +/// In the following example `Fields::wildcards` returns `[_, _, _, _]`. Then in +/// `extract_pattern_arguments` we fill some of the entries, and the result is +/// `[Some(0), _, _, _]`. +/// ```rust +/// let x: [Option; 4] = foo(); +/// match x { +/// [Some(0), ..] => {} +/// } +/// ``` +/// +/// Note that the number of fields of a constructor may not match the fields declared in the +/// original struct/variant. This happens if a private or `non_exhaustive` field is uninhabited, +/// because the code mustn't observe that it is uninhabited. In that case that field is not +/// included in `fields`. For that reason, when you have a `mir::Field` you must use +/// `index_with_declared_idx`. +#[derive(Debug, Clone, Copy)] +pub(super) struct Fields<'p, 'tcx> { + fields: &'p [DeconstructedPat<'p, 'tcx>], } impl<'p, 'tcx> Fields<'p, 'tcx> { - /// Internal use. Use `Fields::wildcards()` instead. - /// Must not be used if the pattern is a field of a struct/tuple/variant. - fn from_single_pattern(pat: &'p Pat<'tcx>) -> Self { - Fields::Slice(std::slice::from_ref(pat)) + fn empty() -> Self { + Fields { fields: &[] } + } + + fn singleton(cx: &MatchCheckCtxt<'p, 'tcx>, field: DeconstructedPat<'p, 'tcx>) -> Self { + let field: &_ = cx.pattern_arena.alloc(field); + Fields { fields: std::slice::from_ref(field) } + } + + pub(super) fn from_iter( + cx: &MatchCheckCtxt<'p, 'tcx>, + fields: impl IntoIterator>, + ) -> Self { + let fields: &[_] = cx.pattern_arena.alloc_from_iter(fields); + Fields { fields } } - /// Convenience; internal use. fn wildcards_from_tys( cx: &MatchCheckCtxt<'p, 'tcx>, tys: impl IntoIterator>, ) -> Self { - let wilds = tys.into_iter().map(Pat::wildcard_from_ty); - let pats = cx.pattern_arena.alloc_from_iter(wilds); - Fields::Slice(pats) + Fields::from_iter(cx, tys.into_iter().map(DeconstructedPat::wildcard)) } - /// Creates a new list of wildcard fields for a given constructor. - pub(super) fn wildcards(pcx: PatCtxt<'_, 'p, 'tcx>, constructor: &Constructor<'tcx>) -> Self { - let ty = pcx.ty; - let cx = pcx.cx; - let wildcard_from_ty = |ty| &*cx.pattern_arena.alloc(Pat::wildcard_from_ty(ty)); + // In the cases of either a `#[non_exhaustive]` field list or a non-public field, we hide + // uninhabited fields in order not to reveal the uninhabitedness of the whole variant. + // This lists the fields we keep along with their types. + fn list_variant_nonhidden_fields<'a>( + cx: &'a MatchCheckCtxt<'p, 'tcx>, + ty: Ty<'tcx>, + variant: &'a VariantDef, + ) -> impl Iterator)> + Captures<'a> + Captures<'p> { + let (adt, substs) = match ty.kind() { + ty::Adt(adt, substs) => (adt, substs), + _ => bug!(), + }; + // Whether we must not match the fields of this variant exhaustively. + let is_non_exhaustive = variant.is_field_list_non_exhaustive() && !adt.did.is_local(); + variant.fields.iter().enumerate().filter_map(move |(i, field)| { + let ty = field.ty(cx.tcx, substs); + // `field.ty()` doesn't normalize after substituting. + let ty = cx.tcx.normalize_erasing_regions(cx.param_env, ty); + let is_visible = adt.is_enum() || field.vis.is_accessible_from(cx.module, cx.tcx); + let is_uninhabited = cx.is_uninhabited(ty); + + if is_uninhabited && (!is_visible || is_non_exhaustive) { + None + } else { + Some((Field::new(i), ty)) + } + }) + } + + /// Creates a new list of wildcard fields for a given constructor. The result must have a + /// length of `constructor.arity()`. + pub(super) fn wildcards( + cx: &MatchCheckCtxt<'p, 'tcx>, + ty: Ty<'tcx>, + constructor: &Constructor<'tcx>, + ) -> Self { let ret = match constructor { Single | Variant(_) => match ty.kind() { - ty::Tuple(ref fs) => { - Fields::wildcards_from_tys(cx, fs.into_iter().map(|ty| ty.expect_ty())) - } - ty::Ref(_, rty, _) => Fields::from_single_pattern(wildcard_from_ty(rty)), + ty::Tuple(fs) => Fields::wildcards_from_tys(cx, fs.iter().map(|ty| ty.expect_ty())), + ty::Ref(_, rty, _) => Fields::wildcards_from_tys(cx, once(*rty)), ty::Adt(adt, substs) => { if adt.is_box() { - // Use T as the sub pattern type of Box. - Fields::from_single_pattern(wildcard_from_ty(substs.type_at(0))) + // The only legal patterns of type `Box` (outside `std`) are `_` and box + // patterns. If we're here we can assume this is a box pattern. + Fields::wildcards_from_tys(cx, once(substs.type_at(0))) } else { let variant = &adt.variants[constructor.variant_index_for_adt(adt)]; - // Whether we must not match the fields of this variant exhaustively. - let is_non_exhaustive = - variant.is_field_list_non_exhaustive() && !adt.did.is_local(); - let field_tys = variant.fields.iter().map(|field| field.ty(cx.tcx, substs)); - // In the following cases, we don't need to filter out any fields. This is - // the vast majority of real cases, since uninhabited fields are uncommon. - let has_no_hidden_fields = (adt.is_enum() && !is_non_exhaustive) - || !field_tys.clone().any(|ty| cx.is_uninhabited(ty)); - - if has_no_hidden_fields { - Fields::wildcards_from_tys(cx, field_tys) - } else { - let mut len = 0; - let fields = variant - .fields - .iter() - .map(|field| { - let ty = field.ty(cx.tcx, substs); - let is_visible = adt.is_enum() - || field.vis.is_accessible_from(cx.module, cx.tcx); - let is_uninhabited = cx.is_uninhabited(ty); - - // In the cases of either a `#[non_exhaustive]` field list - // or a non-public field, we hide uninhabited fields in - // order not to reveal the uninhabitedness of the whole - // variant. - if is_uninhabited && (!is_visible || is_non_exhaustive) { - FilteredField::Hidden - } else { - len += 1; - FilteredField::Kept(wildcard_from_ty(ty)) - } - }) - .collect(); - Fields::Filtered { fields, len } - } + let tys = Fields::list_variant_nonhidden_fields(cx, ty, variant) + .map(|(_, ty)| ty); + Fields::wildcards_from_tys(cx, tys) } } _ => bug!("Unexpected type for `Single` constructor: {:?}", ty), @@ -1176,52 +1224,249 @@ impl<'p, 'tcx> Fields<'p, 'tcx> { } _ => bug!("bad slice pattern {:?} {:?}", constructor, ty), }, - Str(..) | FloatRange(..) | IntRange(..) | NonExhaustive | Opaque | Missing - | Wildcard => Fields::Slice(&[]), + Str(..) + | FloatRange(..) + | IntRange(..) + | NonExhaustive + | Opaque + | Missing { .. } + | Wildcard => Fields::empty(), + Or => { + bug!("called `Fields::wildcards` on an `Or` ctor") + } }; debug!("Fields::wildcards({:?}, {:?}) = {:#?}", constructor, ty, ret); ret } - /// Apply a constructor to a list of patterns, yielding a new pattern. `self` - /// must have as many elements as this constructor's arity. - /// - /// This is roughly the inverse of `specialize_constructor`. - /// - /// Examples: - /// `ctor`: `Constructor::Single` - /// `ty`: `Foo(u32, u32, u32)` - /// `self`: `[10, 20, _]` - /// returns `Foo(10, 20, _)` - /// - /// `ctor`: `Constructor::Variant(Option::Some)` - /// `ty`: `Option` - /// `self`: `[false]` - /// returns `Some(false)` - pub(super) fn apply(self, pcx: PatCtxt<'_, 'p, 'tcx>, ctor: &Constructor<'tcx>) -> Pat<'tcx> { - let subpatterns_and_indices = self.patterns_and_indices(); - let mut subpatterns = subpatterns_and_indices.iter().map(|&(_, p)| p).cloned(); + /// Returns the list of patterns. + pub(super) fn iter_patterns<'a>( + &'a self, + ) -> impl Iterator> + Captures<'a> { + self.fields.iter() + } +} - let pat = match ctor { - Single | Variant(_) => match pcx.ty.kind() { - ty::Adt(..) | ty::Tuple(..) => { - // We want the real indices here. - let subpatterns = subpatterns_and_indices - .iter() - .map(|&(field, p)| FieldPat { field, pattern: p.clone() }) +/// Values and patterns can be represented as a constructor applied to some fields. This represents +/// a pattern in this form. +/// This also keeps track of whether the pattern has been found reachable during analysis. For this +/// reason we should be careful not to clone patterns for which we care about that. Use +/// `clone_and_forget_reachability` if you're sure. +pub(crate) struct DeconstructedPat<'p, 'tcx> { + ctor: Constructor<'tcx>, + fields: Fields<'p, 'tcx>, + ty: Ty<'tcx>, + span: Span, + reachable: Cell, +} + +impl<'p, 'tcx> DeconstructedPat<'p, 'tcx> { + pub(super) fn wildcard(ty: Ty<'tcx>) -> Self { + Self::new(Wildcard, Fields::empty(), ty, DUMMY_SP) + } + + pub(super) fn new( + ctor: Constructor<'tcx>, + fields: Fields<'p, 'tcx>, + ty: Ty<'tcx>, + span: Span, + ) -> Self { + DeconstructedPat { ctor, fields, ty, span, reachable: Cell::new(false) } + } + + /// Construct a pattern that matches everything that starts with this constructor. + /// For example, if `ctor` is a `Constructor::Variant` for `Option::Some`, we get the pattern + /// `Some(_)`. + pub(super) fn wild_from_ctor(pcx: PatCtxt<'_, 'p, 'tcx>, ctor: Constructor<'tcx>) -> Self { + let fields = Fields::wildcards(pcx.cx, pcx.ty, &ctor); + DeconstructedPat::new(ctor, fields, pcx.ty, DUMMY_SP) + } + + /// Clone this value. This method emphasizes that cloning loses reachability information and + /// should be done carefully. + pub(super) fn clone_and_forget_reachability(&self) -> Self { + DeconstructedPat::new(self.ctor.clone(), self.fields, self.ty, self.span) + } + + pub(crate) fn from_pat(cx: &MatchCheckCtxt<'p, 'tcx>, pat: &Pat<'tcx>) -> Self { + let mkpat = |pat| DeconstructedPat::from_pat(cx, pat); + let ctor; + let fields; + match pat.kind.as_ref() { + PatKind::AscribeUserType { subpattern, .. } => return mkpat(subpattern), + PatKind::Binding { subpattern: Some(subpat), .. } => return mkpat(subpat), + PatKind::Binding { subpattern: None, .. } | PatKind::Wild => { + ctor = Wildcard; + fields = Fields::empty(); + } + PatKind::Deref { subpattern } => { + ctor = Single; + fields = Fields::singleton(cx, mkpat(subpattern)); + } + PatKind::Leaf { subpatterns } | PatKind::Variant { subpatterns, .. } => { + match pat.ty.kind() { + ty::Tuple(fs) => { + ctor = Single; + let mut wilds: SmallVec<[_; 2]> = fs + .iter() + .map(|ty| ty.expect_ty()) + .map(DeconstructedPat::wildcard) + .collect(); + for pat in subpatterns { + wilds[pat.field.index()] = mkpat(&pat.pattern); + } + fields = Fields::from_iter(cx, wilds); + } + ty::Adt(adt, substs) if adt.is_box() => { + // The only legal patterns of type `Box` (outside `std`) are `_` and box + // patterns. If we're here we can assume this is a box pattern. + // FIXME(Nadrieril): A `Box` can in theory be matched either with `Box(_, + // _)` or a box pattern. As a hack to avoid an ICE with the former, we + // ignore other fields than the first one. This will trigger an error later + // anyway. + // See https://github.com/rust-lang/rust/issues/82772 , + // explanation: https://github.com/rust-lang/rust/pull/82789#issuecomment-796921977 + // The problem is that we can't know from the type whether we'll match + // normally or through box-patterns. We'll have to figure out a proper + // solution when we introduce generalized deref patterns. Also need to + // prevent mixing of those two options. + let pat = subpatterns.into_iter().find(|pat| pat.field.index() == 0); + let pat = if let Some(pat) = pat { + mkpat(&pat.pattern) + } else { + DeconstructedPat::wildcard(substs.type_at(0)) + }; + ctor = Single; + fields = Fields::singleton(cx, pat); + } + ty::Adt(adt, _) => { + ctor = match pat.kind.as_ref() { + PatKind::Leaf { .. } => Single, + PatKind::Variant { variant_index, .. } => Variant(*variant_index), + _ => bug!(), + }; + let variant = &adt.variants[ctor.variant_index_for_adt(adt)]; + // For each field in the variant, we store the relevant index into `self.fields` if any. + let mut field_id_to_id: Vec> = + (0..variant.fields.len()).map(|_| None).collect(); + let tys = Fields::list_variant_nonhidden_fields(cx, pat.ty, variant) + .enumerate() + .map(|(i, (field, ty))| { + field_id_to_id[field.index()] = Some(i); + ty + }); + let mut wilds: SmallVec<[_; 2]> = + tys.map(DeconstructedPat::wildcard).collect(); + for pat in subpatterns { + if let Some(i) = field_id_to_id[pat.field.index()] { + wilds[i] = mkpat(&pat.pattern); + } + } + fields = Fields::from_iter(cx, wilds); + } + _ => bug!("pattern has unexpected type: pat: {:?}, ty: {:?}", pat, pat.ty), + } + } + PatKind::Constant { value } => { + if let Some(int_range) = IntRange::from_const(cx.tcx, cx.param_env, value) { + ctor = IntRange(int_range); + fields = Fields::empty(); + } else { + match pat.ty.kind() { + ty::Float(_) => { + ctor = FloatRange(value, value, RangeEnd::Included); + fields = Fields::empty(); + } + ty::Ref(_, t, _) if t.is_str() => { + // We want a `&str` constant to behave like a `Deref` pattern, to be compatible + // with other `Deref` patterns. This could have been done in `const_to_pat`, + // but that causes issues with the rest of the matching code. + // So here, the constructor for a `"foo"` pattern is `&` (represented by + // `Single`), and has one field. That field has constructor `Str(value)` and no + // fields. + // Note: `t` is `str`, not `&str`. + let subpattern = + DeconstructedPat::new(Str(value), Fields::empty(), t, pat.span); + ctor = Single; + fields = Fields::singleton(cx, subpattern) + } + // All constants that can be structurally matched have already been expanded + // into the corresponding `Pat`s by `const_to_pat`. Constants that remain are + // opaque. + _ => { + ctor = Opaque; + fields = Fields::empty(); + } + } + } + } + &PatKind::Range(PatRange { lo, hi, end }) => { + let ty = lo.ty; + ctor = if let Some(int_range) = IntRange::from_range( + cx.tcx, + lo.eval_bits(cx.tcx, cx.param_env, lo.ty), + hi.eval_bits(cx.tcx, cx.param_env, hi.ty), + ty, + &end, + ) { + IntRange(int_range) + } else { + FloatRange(lo, hi, end) + }; + fields = Fields::empty(); + } + PatKind::Array { prefix, slice, suffix } | PatKind::Slice { prefix, slice, suffix } => { + let array_len = match pat.ty.kind() { + ty::Array(_, length) => Some(length.eval_usize(cx.tcx, cx.param_env) as usize), + ty::Slice(_) => None, + _ => span_bug!(pat.span, "bad ty {:?} for slice pattern", pat.ty), + }; + let kind = if slice.is_some() { + VarLen(prefix.len(), suffix.len()) + } else { + FixedLen(prefix.len() + suffix.len()) + }; + ctor = Slice(Slice::new(array_len, kind)); + fields = Fields::from_iter(cx, prefix.iter().chain(suffix).map(mkpat)); + } + PatKind::Or { .. } => { + ctor = Or; + let pats = expand_or_pat(pat); + fields = Fields::from_iter(cx, pats.into_iter().map(mkpat)); + } + } + DeconstructedPat::new(ctor, fields, pat.ty, pat.span) + } + + pub(crate) fn to_pat(&self, cx: &MatchCheckCtxt<'p, 'tcx>) -> Pat<'tcx> { + let is_wildcard = |pat: &Pat<'_>| { + matches!(*pat.kind, PatKind::Binding { subpattern: None, .. } | PatKind::Wild) + }; + let mut subpatterns = self.iter_fields().map(|p| p.to_pat(cx)); + let pat = match &self.ctor { + Single | Variant(_) => match self.ty.kind() { + ty::Tuple(..) => PatKind::Leaf { + subpatterns: subpatterns + .enumerate() + .map(|(i, p)| FieldPat { field: Field::new(i), pattern: p }) + .collect(), + }, + ty::Adt(adt_def, _) if adt_def.is_box() => { + // Without `box_patterns`, the only legal pattern of type `Box` is `_` (outside + // of `std`). So this branch is only reachable when the feature is enabled and + // the pattern is a box pattern. + PatKind::Deref { subpattern: subpatterns.next().unwrap() } + } + ty::Adt(adt_def, substs) => { + let variant_index = self.ctor.variant_index_for_adt(adt_def); + let variant = &adt_def.variants[variant_index]; + let subpatterns = Fields::list_variant_nonhidden_fields(cx, self.ty, variant) + .zip(subpatterns) + .map(|((field, _ty), pattern)| FieldPat { field, pattern }) .collect(); - if let ty::Adt(adt, substs) = pcx.ty.kind() { - if adt.is_enum() { - PatKind::Variant { - adt_def: adt, - substs, - variant_index: ctor.variant_index_for_adt(adt), - subpatterns, - } - } else { - PatKind::Leaf { subpatterns } - } + if adt_def.is_enum() { + PatKind::Variant { adt_def, substs, variant_index, subpatterns } } else { PatKind::Leaf { subpatterns } } @@ -1229,195 +1474,239 @@ impl<'p, 'tcx> Fields<'p, 'tcx> { // Note: given the expansion of `&str` patterns done in `expand_pattern`, we should // be careful to reconstruct the correct constant pattern here. However a string // literal pattern will never be reported as a non-exhaustiveness witness, so we - // can ignore this issue. + // ignore this issue. ty::Ref(..) => PatKind::Deref { subpattern: subpatterns.next().unwrap() }, - ty::Slice(_) | ty::Array(..) => bug!("bad slice pattern {:?} {:?}", ctor, pcx.ty), - _ => PatKind::Wild, + _ => bug!("unexpected ctor for type {:?} {:?}", self.ctor, self.ty), }, - Slice(slice) => match slice.kind { - FixedLen(_) => { - PatKind::Slice { prefix: subpatterns.collect(), slice: None, suffix: vec![] } - } - VarLen(prefix, _) => { - let mut prefix: Vec<_> = subpatterns.by_ref().take(prefix as usize).collect(); - if slice.array_len.is_some() { - // Improves diagnostics a bit: if the type is a known-size array, instead - // of reporting `[x, _, .., _, y]`, we prefer to report `[x, .., y]`. - // This is incorrect if the size is not known, since `[_, ..]` captures - // arrays of lengths `>= 1` whereas `[..]` captures any length. - while !prefix.is_empty() && is_wildcard(prefix.last().unwrap()) { - prefix.pop(); + Slice(slice) => { + match slice.kind { + FixedLen(_) => PatKind::Slice { + prefix: subpatterns.collect(), + slice: None, + suffix: vec![], + }, + VarLen(prefix, _) => { + let mut subpatterns = subpatterns.peekable(); + let mut prefix: Vec<_> = subpatterns.by_ref().take(prefix).collect(); + if slice.array_len.is_some() { + // Improves diagnostics a bit: if the type is a known-size array, instead + // of reporting `[x, _, .., _, y]`, we prefer to report `[x, .., y]`. + // This is incorrect if the size is not known, since `[_, ..]` captures + // arrays of lengths `>= 1` whereas `[..]` captures any length. + while !prefix.is_empty() && is_wildcard(prefix.last().unwrap()) { + prefix.pop(); + } + while subpatterns.peek().is_some() + && is_wildcard(subpatterns.peek().unwrap()) + { + subpatterns.next(); + } } + let suffix: Vec<_> = subpatterns.collect(); + let wild = Pat::wildcard_from_ty(self.ty); + PatKind::Slice { prefix, slice: Some(wild), suffix } } - let suffix: Vec<_> = if slice.array_len.is_some() { - // Same as above. - subpatterns.skip_while(is_wildcard).collect() - } else { - subpatterns.collect() - }; - let wild = Pat::wildcard_from_ty(pcx.ty); - PatKind::Slice { prefix, slice: Some(wild), suffix } } - }, + } &Str(value) => PatKind::Constant { value }, &FloatRange(lo, hi, end) => PatKind::Range(PatRange { lo, hi, end }), - IntRange(range) => return range.to_pat(pcx.cx.tcx, pcx.ty), - NonExhaustive => PatKind::Wild, - Wildcard => return Pat::wildcard_from_ty(pcx.ty), - Opaque => bug!("we should not try to apply an opaque constructor"), - Missing => bug!( - "trying to apply the `Missing` constructor; this should have been done in `apply_constructors`" + IntRange(range) => return range.to_pat(cx.tcx, self.ty), + Wildcard | NonExhaustive => PatKind::Wild, + Missing { .. } => bug!( + "trying to convert a `Missing` constructor into a `Pat`; this is probably a bug, + `Missing` should have been processed in `apply_constructors`" ), + Opaque | Or => { + bug!("can't convert to pattern: {:?}", self) + } }; - Pat { ty: pcx.ty, span: DUMMY_SP, kind: Box::new(pat) } + Pat { ty: self.ty, span: DUMMY_SP, kind: Box::new(pat) } } - /// Returns the number of patterns. This is the same as the arity of the constructor used to - /// construct `self`. - pub(super) fn len(&self) -> usize { - match self { - Fields::Slice(pats) => pats.len(), - Fields::Vec(pats) => pats.len(), - Fields::Filtered { len, .. } => *len, - } + pub(super) fn is_or_pat(&self) -> bool { + matches!(self.ctor, Or) } - /// Returns the list of patterns along with the corresponding field indices. - fn patterns_and_indices(&self) -> SmallVec<[(Field, &'p Pat<'tcx>); 2]> { - match self { - Fields::Slice(pats) => { - pats.iter().enumerate().map(|(i, p)| (Field::new(i), p)).collect() - } - Fields::Vec(pats) => { - pats.iter().copied().enumerate().map(|(i, p)| (Field::new(i), p)).collect() - } - Fields::Filtered { fields, .. } => { - // Indices must be relative to the full list of patterns - fields - .iter() - .enumerate() - .filter_map(|(i, p)| Some((Field::new(i), p.kept()?))) - .collect() - } - } + pub(super) fn ctor(&self) -> &Constructor<'tcx> { + &self.ctor + } + pub(super) fn ty(&self) -> Ty<'tcx> { + self.ty + } + pub(super) fn span(&self) -> Span { + self.span } - /// Returns the list of patterns. - pub(super) fn into_patterns(self) -> SmallVec<[&'p Pat<'tcx>; 2]> { - match self { - Fields::Slice(pats) => pats.iter().collect(), - Fields::Vec(pats) => pats, - Fields::Filtered { fields, .. } => fields.iter().filter_map(|p| p.kept()).collect(), - } + pub(super) fn iter_fields<'a>( + &'a self, + ) -> impl Iterator> + Captures<'a> { + self.fields.iter_patterns() } - /// Overrides some of the fields with the provided patterns. Exactly like - /// `replace_fields_indexed`, except that it takes `FieldPat`s as input. - fn replace_with_fieldpats( - &self, - new_pats: impl IntoIterator>, - ) -> Self { - self.replace_fields_indexed( - new_pats.into_iter().map(|pat| (pat.field.index(), &pat.pattern)), - ) - } - - /// Overrides some of the fields with the provided patterns. This is used when a pattern - /// defines some fields but not all, for example `Foo { field1: Some(_), .. }`: here we start - /// with a `Fields` that is just one wildcard per field of the `Foo` struct, and override the - /// entry corresponding to `field1` with the pattern `Some(_)`. This is also used for slice - /// patterns for the same reason. - fn replace_fields_indexed( - &self, - new_pats: impl IntoIterator)>, - ) -> Self { - let mut fields = self.clone(); - if let Fields::Slice(pats) = fields { - fields = Fields::Vec(pats.iter().collect()); - } - - match &mut fields { - Fields::Vec(pats) => { - for (i, pat) in new_pats { - if let Some(p) = pats.get_mut(i) { - *p = pat; - } - } - } - Fields::Filtered { fields, .. } => { - for (i, pat) in new_pats { - if let FilteredField::Kept(p) = &mut fields[i] { - *p = pat - } - } - } - Fields::Slice(_) => unreachable!(), - } - fields - } - - /// Replaces contained fields with the given list of patterns. There must be `len()` patterns - /// in `pats`. - pub(super) fn replace_fields( - &self, + /// Specialize this pattern with a constructor. + /// `other_ctor` can be different from `self.ctor`, but must be covered by it. + pub(super) fn specialize<'a>( + &'a self, cx: &MatchCheckCtxt<'p, 'tcx>, - pats: impl IntoIterator>, - ) -> Self { - let pats: &[_] = cx.pattern_arena.alloc_from_iter(pats); - - match self { - Fields::Filtered { fields, len } => { - let mut pats = pats.iter(); - let mut fields = fields.clone(); - for f in &mut fields { - if let FilteredField::Kept(p) = f { - // We take one input pattern for each `Kept` field, in order. - *p = pats.next().unwrap(); + other_ctor: &Constructor<'tcx>, + ) -> SmallVec<[&'p DeconstructedPat<'p, 'tcx>; 2]> { + match (&self.ctor, other_ctor) { + (Wildcard, _) => { + // We return a wildcard for each field of `other_ctor`. + Fields::wildcards(cx, self.ty, other_ctor).iter_patterns().collect() + } + (Slice(self_slice), Slice(other_slice)) + if self_slice.arity() != other_slice.arity() => + { + // The only tricky case: two slices of different arity. Since `self_slice` covers + // `other_slice`, `self_slice` must be `VarLen`, i.e. of the form + // `[prefix, .., suffix]`. Moreover `other_slice` is guaranteed to have a larger + // arity. So we fill the middle part with enough wildcards to reach the length of + // the new, larger slice. + match self_slice.kind { + FixedLen(_) => bug!("{:?} doesn't cover {:?}", self_slice, other_slice), + VarLen(prefix, suffix) => { + let inner_ty = match *self.ty.kind() { + ty::Slice(ty) | ty::Array(ty, _) => ty, + _ => bug!("bad slice pattern {:?} {:?}", self.ctor, self.ty), + }; + let prefix = &self.fields.fields[..prefix]; + let suffix = &self.fields.fields[self_slice.arity() - suffix..]; + let wildcard: &_ = + cx.pattern_arena.alloc(DeconstructedPat::wildcard(inner_ty)); + let extra_wildcards = other_slice.arity() - self_slice.arity(); + let extra_wildcards = (0..extra_wildcards).map(|_| wildcard); + prefix.iter().chain(extra_wildcards).chain(suffix).collect() } } - Fields::Filtered { fields, len: *len } } - _ => Fields::Slice(pats), + _ => self.fields.iter_patterns().collect(), } } - /// Replaces contained fields with the arguments of the given pattern. Only use on a pattern - /// that is compatible with the constructor used to build `self`. - /// This is meant to be used on the result of `Fields::wildcards()`. The idea is that - /// `wildcards` constructs a list of fields where all entries are wildcards, and the pattern - /// provided to this function fills some of the fields with non-wildcards. - /// In the following example `Fields::wildcards` would return `[_, _, _, _]`. If we call - /// `replace_with_pattern_arguments` on it with the pattern, the result will be `[Some(0), _, - /// _, _]`. - /// ```rust - /// let x: [Option; 4] = foo(); - /// match x { - /// [Some(0), ..] => {} - /// } - /// ``` - /// This is guaranteed to preserve the number of patterns in `self`. - pub(super) fn replace_with_pattern_arguments(&self, pat: &'p Pat<'tcx>) -> Self { - match pat.kind.as_ref() { - PatKind::Deref { subpattern } => { - assert_eq!(self.len(), 1); - Fields::from_single_pattern(subpattern) - } - PatKind::Leaf { subpatterns } | PatKind::Variant { subpatterns, .. } => { - self.replace_with_fieldpats(subpatterns) - } - PatKind::Array { prefix, suffix, .. } | PatKind::Slice { prefix, suffix, .. } => { - // Number of subpatterns for the constructor - let ctor_arity = self.len(); + /// We keep track for each pattern if it was ever reachable during the analysis. This is used + /// with `unreachable_spans` to report unreachable subpatterns arising from or patterns. + pub(super) fn set_reachable(&self) { + self.reachable.set(true) + } + pub(super) fn is_reachable(&self) -> bool { + self.reachable.get() + } - // Replace the prefix and the suffix with the given patterns, leaving wildcards in - // the middle if there was a subslice pattern `..`. - let prefix = prefix.iter().enumerate(); - let suffix = - suffix.iter().enumerate().map(|(i, p)| (ctor_arity - suffix.len() + i, p)); - self.replace_fields_indexed(prefix.chain(suffix)) + /// Report the spans of subpatterns that were not reachable, if any. + pub(super) fn unreachable_spans(&self) -> Vec { + let mut spans = Vec::new(); + self.collect_unreachable_spans(&mut spans); + spans + } + + fn collect_unreachable_spans(&self, spans: &mut Vec) { + // We don't look at subpatterns if we already reported the whole pattern as unreachable. + if !self.is_reachable() { + spans.push(self.span); + } else { + for p in self.iter_fields() { + p.collect_unreachable_spans(spans); } - _ => self.clone(), + } + } +} + +/// This is mostly copied from the `Pat` impl. This is best effort and not good enough for a +/// `Display` impl. +impl<'p, 'tcx> fmt::Debug for DeconstructedPat<'p, 'tcx> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + // Printing lists is a chore. + let mut first = true; + let mut start_or_continue = |s| { + if first { + first = false; + "" + } else { + s + } + }; + let mut start_or_comma = || start_or_continue(", "); + + match &self.ctor { + Single | Variant(_) => match self.ty.kind() { + ty::Adt(def, _) if def.is_box() => { + // Without `box_patterns`, the only legal pattern of type `Box` is `_` (outside + // of `std`). So this branch is only reachable when the feature is enabled and + // the pattern is a box pattern. + let subpattern = self.iter_fields().next().unwrap(); + write!(f, "box {:?}", subpattern) + } + ty::Adt(..) | ty::Tuple(..) => { + let variant = match self.ty.kind() { + ty::Adt(adt, _) => { + Some(&adt.variants[self.ctor.variant_index_for_adt(adt)]) + } + ty::Tuple(_) => None, + _ => unreachable!(), + }; + + if let Some(variant) = variant { + write!(f, "{}", variant.ident)?; + } + + // Without `cx`, we can't know which field corresponds to which, so we can't + // get the names of the fields. Instead we just display everything as a suple + // struct, which should be good enough. + write!(f, "(")?; + for p in self.iter_fields() { + write!(f, "{}", start_or_comma())?; + write!(f, "{:?}", p)?; + } + write!(f, ")") + } + // Note: given the expansion of `&str` patterns done in `expand_pattern`, we should + // be careful to detect strings here. However a string literal pattern will never + // be reported as a non-exhaustiveness witness, so we can ignore this issue. + ty::Ref(_, _, mutbl) => { + let subpattern = self.iter_fields().next().unwrap(); + write!(f, "&{}{:?}", mutbl.prefix_str(), subpattern) + } + _ => write!(f, "_"), + }, + Slice(slice) => { + let mut subpatterns = self.fields.iter_patterns(); + write!(f, "[")?; + match slice.kind { + FixedLen(_) => { + for p in subpatterns { + write!(f, "{}{:?}", start_or_comma(), p)?; + } + } + VarLen(prefix_len, _) => { + for p in subpatterns.by_ref().take(prefix_len) { + write!(f, "{}{:?}", start_or_comma(), p)?; + } + write!(f, "{}", start_or_comma())?; + write!(f, "..")?; + for p in subpatterns { + write!(f, "{}{:?}", start_or_comma(), p)?; + } + } + } + write!(f, "]") + } + &FloatRange(lo, hi, end) => { + write!(f, "{}", lo)?; + write!(f, "{}", end)?; + write!(f, "{}", hi) + } + IntRange(range) => write!(f, "{:?}", range), // Best-effort, will render e.g. `false` as `0..=0` + Wildcard | Missing { .. } | NonExhaustive => write!(f, "_ : {:?}", self.ty), + Or => { + for pat in self.iter_fields() { + write!(f, "{}{:?}", start_or_continue(" | "), pat)?; + } + Ok(()) + } + Str(value) => write!(f, "{}", value), + Opaque => write!(f, ""), } } } diff --git a/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs b/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs index 344006e9fb..d959d2f7f6 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs @@ -280,28 +280,26 @@ //! The details are not necessary to understand this file, so we explain them in //! [`super::deconstruct_pat`]. Splitting is done by the [`Constructor::split`] function. +use self::ArmType::*; use self::Usefulness::*; -use self::WitnessPreference::*; -use super::deconstruct_pat::{Constructor, Fields, SplitWildcard}; -use super::{PatternFoldable, PatternFolder}; +use super::check_match::{joined_uncovered_patterns, pattern_not_covered_label}; +use super::deconstruct_pat::{Constructor, DeconstructedPat, Fields, SplitWildcard}; use rustc_data_structures::captures::Captures; -use rustc_data_structures::fx::FxHashMap; use rustc_arena::TypedArena; use rustc_hir::def_id::DefId; use rustc_hir::HirId; -use rustc_middle::thir::{Pat, PatKind}; use rustc_middle::ty::{self, Ty, TyCtxt}; -use rustc_span::Span; +use rustc_session::lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS; +use rustc_span::{Span, DUMMY_SP}; use smallvec::{smallvec, SmallVec}; use std::fmt; -use std::iter::{FromIterator, IntoIterator}; -use std::lazy::OnceCell; +use std::iter::once; -crate struct MatchCheckCtxt<'a, 'tcx> { +crate struct MatchCheckCtxt<'p, 'tcx> { crate tcx: TyCtxt<'tcx>, /// The module in which the match occurs. This is necessary for /// checking inhabited-ness of types because whether a type is (visibly) @@ -310,7 +308,7 @@ crate struct MatchCheckCtxt<'a, 'tcx> { /// outside its module and should not be matchable with an empty match statement. crate module: DefId, crate param_env: ty::ParamEnv<'tcx>, - crate pattern_arena: &'a TypedArena>, + crate pattern_arena: &'p TypedArena>, } impl<'a, 'tcx> MatchCheckCtxt<'a, 'tcx> { @@ -343,6 +341,8 @@ pub(super) struct PatCtxt<'a, 'p, 'tcx> { /// Whether the current pattern is the whole pattern as found in a match arm, or if it's a /// subpattern. pub(super) is_top_level: bool, + /// Wether the current pattern is from a `non_exhaustive` enum. + pub(super) is_non_exhaustive: bool, } impl<'a, 'p, 'tcx> fmt::Debug for PatCtxt<'a, 'p, 'tcx> { @@ -351,78 +351,20 @@ impl<'a, 'p, 'tcx> fmt::Debug for PatCtxt<'a, 'p, 'tcx> { } } -crate fn expand_pattern<'tcx>(pat: Pat<'tcx>) -> Pat<'tcx> { - LiteralExpander.fold_pattern(&pat) -} - -struct LiteralExpander; - -impl<'tcx> PatternFolder<'tcx> for LiteralExpander { - fn fold_pattern(&mut self, pat: &Pat<'tcx>) -> Pat<'tcx> { - debug!("fold_pattern {:?} {:?} {:?}", pat, pat.ty.kind(), pat.kind); - match (pat.ty.kind(), pat.kind.as_ref()) { - (_, PatKind::Binding { subpattern: Some(s), .. }) => s.fold_with(self), - (_, PatKind::AscribeUserType { subpattern: s, .. }) => s.fold_with(self), - (ty::Ref(_, t, _), PatKind::Constant { .. }) if t.is_str() => { - // Treat string literal patterns as deref patterns to a `str` constant, i.e. - // `&CONST`. This expands them like other const patterns. This could have been done - // in `const_to_pat`, but that causes issues with the rest of the matching code. - let mut new_pat = pat.super_fold_with(self); - // Make a fake const pattern of type `str` (instead of `&str`). That the carried - // constant value still knows it is of type `&str`. - new_pat.ty = t; - Pat { - kind: Box::new(PatKind::Deref { subpattern: new_pat }), - span: pat.span, - ty: pat.ty, - } - } - _ => pat.super_fold_with(self), - } - } -} - -pub(super) fn is_wildcard(pat: &Pat<'_>) -> bool { - matches!(*pat.kind, PatKind::Binding { subpattern: None, .. } | PatKind::Wild) -} - -fn is_or_pat(pat: &Pat<'_>) -> bool { - matches!(*pat.kind, PatKind::Or { .. }) -} - -/// Recursively expand this pattern into its subpatterns. Only useful for or-patterns. -fn expand_or_pat<'p, 'tcx>(pat: &'p Pat<'tcx>) -> Vec<&'p Pat<'tcx>> { - fn expand<'p, 'tcx>(pat: &'p Pat<'tcx>, vec: &mut Vec<&'p Pat<'tcx>>) { - if let PatKind::Or { pats } = pat.kind.as_ref() { - for pat in pats { - expand(pat, vec); - } - } else { - vec.push(pat) - } - } - - let mut pats = Vec::new(); - expand(pat, &mut pats); - pats -} - /// A row of a matrix. Rows of len 1 are very common, which is why `SmallVec[_; 2]` /// works well. #[derive(Clone)] struct PatStack<'p, 'tcx> { - pats: SmallVec<[&'p Pat<'tcx>; 2]>, - /// Cache for the constructor of the head - head_ctor: OnceCell>, + pats: SmallVec<[&'p DeconstructedPat<'p, 'tcx>; 2]>, } impl<'p, 'tcx> PatStack<'p, 'tcx> { - fn from_pattern(pat: &'p Pat<'tcx>) -> Self { + fn from_pattern(pat: &'p DeconstructedPat<'p, 'tcx>) -> Self { Self::from_vec(smallvec![pat]) } - fn from_vec(vec: SmallVec<[&'p Pat<'tcx>; 2]>) -> Self { - PatStack { pats: vec, head_ctor: OnceCell::new() } + fn from_vec(vec: SmallVec<[&'p DeconstructedPat<'p, 'tcx>; 2]>) -> Self { + PatStack { pats: vec } } fn is_empty(&self) -> bool { @@ -433,79 +375,56 @@ impl<'p, 'tcx> PatStack<'p, 'tcx> { self.pats.len() } - fn head(&self) -> &'p Pat<'tcx> { + fn head(&self) -> &'p DeconstructedPat<'p, 'tcx> { self.pats[0] } - #[inline] - fn head_ctor<'a>(&'a self, cx: &MatchCheckCtxt<'p, 'tcx>) -> &'a Constructor<'tcx> { - self.head_ctor.get_or_init(|| Constructor::from_pat(cx, self.head())) - } - - fn iter(&self) -> impl Iterator> { + fn iter(&self) -> impl Iterator> { self.pats.iter().copied() } // Recursively expand the first pattern into its subpatterns. Only useful if the pattern is an // or-pattern. Panics if `self` is empty. fn expand_or_pat<'a>(&'a self) -> impl Iterator> + Captures<'a> { - expand_or_pat(self.head()).into_iter().map(move |pat| { + self.head().iter_fields().map(move |pat| { let mut new_patstack = PatStack::from_pattern(pat); new_patstack.pats.extend_from_slice(&self.pats[1..]); new_patstack }) } - /// This computes `S(self.head_ctor(), self)`. See top of the file for explanations. + /// This computes `S(self.head().ctor(), self)`. See top of the file for explanations. /// /// Structure patterns with a partial wild pattern (Foo { a: 42, .. }) have their missing /// fields filled with wild patterns. /// /// This is roughly the inverse of `Constructor::apply`. - fn pop_head_constructor(&self, ctor_wild_subpatterns: &Fields<'p, 'tcx>) -> PatStack<'p, 'tcx> { + fn pop_head_constructor( + &self, + cx: &MatchCheckCtxt<'p, 'tcx>, + ctor: &Constructor<'tcx>, + ) -> PatStack<'p, 'tcx> { // We pop the head pattern and push the new fields extracted from the arguments of // `self.head()`. - let mut new_fields = - ctor_wild_subpatterns.replace_with_pattern_arguments(self.head()).into_patterns(); + let mut new_fields: SmallVec<[_; 2]> = self.head().specialize(cx, ctor); new_fields.extend_from_slice(&self.pats[1..]); PatStack::from_vec(new_fields) } } -impl<'p, 'tcx> Default for PatStack<'p, 'tcx> { - fn default() -> Self { - Self::from_vec(smallvec![]) - } -} - -impl<'p, 'tcx> PartialEq for PatStack<'p, 'tcx> { - fn eq(&self, other: &Self) -> bool { - self.pats == other.pats - } -} - -impl<'p, 'tcx> FromIterator<&'p Pat<'tcx>> for PatStack<'p, 'tcx> { - fn from_iter(iter: T) -> Self - where - T: IntoIterator>, - { - Self::from_vec(iter.into_iter().collect()) - } -} - /// Pretty-printing for matrix row. impl<'p, 'tcx> fmt::Debug for PatStack<'p, 'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "+")?; for pat in self.iter() { - write!(f, " {} +", pat)?; + write!(f, " {:?} +", pat)?; } Ok(()) } } /// A 2D matrix. -#[derive(Clone, PartialEq)] +#[derive(Clone)] pub(super) struct Matrix<'p, 'tcx> { patterns: Vec>, } @@ -523,7 +442,7 @@ impl<'p, 'tcx> Matrix<'p, 'tcx> { /// Pushes a new row to the matrix. If the row starts with an or-pattern, this recursively /// expands it. fn push(&mut self, row: PatStack<'p, 'tcx>) { - if !row.is_empty() && is_or_pat(row.head()) { + if !row.is_empty() && row.head().is_or_pat() { for row in row.expand_or_pat() { self.patterns.push(row); } @@ -533,38 +452,26 @@ impl<'p, 'tcx> Matrix<'p, 'tcx> { } /// Iterate over the first component of each row - fn heads<'a>(&'a self) -> impl Iterator> + Captures<'p> { + fn heads<'a>( + &'a self, + ) -> impl Iterator> + Clone + Captures<'a> { self.patterns.iter().map(|r| r.head()) } - /// Iterate over the first constructor of each row. - pub(super) fn head_ctors<'a>( - &'a self, - cx: &'a MatchCheckCtxt<'p, 'tcx>, - ) -> impl Iterator> + Captures<'p> + Clone { - self.patterns.iter().map(move |r| r.head_ctor(cx)) - } - - /// Iterate over the first constructor and the corresponding span of each row. - pub(super) fn head_ctors_and_spans<'a>( - &'a self, - cx: &'a MatchCheckCtxt<'p, 'tcx>, - ) -> impl Iterator, Span)> + Captures<'p> { - self.patterns.iter().map(move |r| (r.head_ctor(cx), r.head().span)) - } - /// This computes `S(constructor, self)`. See top of the file for explanations. fn specialize_constructor( &self, pcx: PatCtxt<'_, 'p, 'tcx>, ctor: &Constructor<'tcx>, - ctor_wild_subpatterns: &Fields<'p, 'tcx>, ) -> Matrix<'p, 'tcx> { - self.patterns - .iter() - .filter(|r| ctor.is_covered_by(pcx, r.head_ctor(pcx.cx))) - .map(|r| r.pop_head_constructor(ctor_wild_subpatterns)) - .collect() + let mut matrix = Matrix::empty(); + for row in &self.patterns { + if ctor.is_covered_by(pcx, row.head().ctor()) { + let new_row = row.pop_head_constructor(pcx.cx, ctor); + matrix.push(new_row); + } + } + matrix } } @@ -583,7 +490,7 @@ impl<'p, 'tcx> fmt::Debug for Matrix<'p, 'tcx> { let Matrix { patterns: m, .. } = self; let pretty_printed_matrix: Vec> = - m.iter().map(|row| row.iter().map(|pat| format!("{}", pat)).collect()).collect(); + m.iter().map(|row| row.iter().map(|pat| format!("{:?}", pat)).collect()).collect(); let column_count = m.iter().map(|row| row.len()).next().unwrap_or(0); assert!(m.iter().all(|row| row.len() == column_count)); @@ -604,289 +511,41 @@ impl<'p, 'tcx> fmt::Debug for Matrix<'p, 'tcx> { } } -impl<'p, 'tcx> FromIterator> for Matrix<'p, 'tcx> { - fn from_iter(iter: T) -> Self - where - T: IntoIterator>, - { - let mut matrix = Matrix::empty(); - for x in iter { - // Using `push` ensures we correctly expand or-patterns. - matrix.push(x); - } - matrix - } -} - -/// Given a pattern or a pattern-stack, this struct captures a set of its subpatterns. We use that -/// to track reachable sub-patterns arising from or-patterns. In the absence of or-patterns this -/// will always be either `Empty` (the whole pattern is unreachable) or `Full` (the whole pattern -/// is reachable). When there are or-patterns, some subpatterns may be reachable while others -/// aren't. In this case the whole pattern still counts as reachable, but we will lint the -/// unreachable subpatterns. -/// -/// This supports a limited set of operations, so not all possible sets of subpatterns can be -/// represented. That's ok, we only want the ones that make sense for our usage. -/// -/// What we're doing is illustrated by this: -/// ``` -/// match (true, 0) { -/// (true, 0) => {} -/// (_, 1) => {} -/// (true | false, 0 | 1) => {} -/// } -/// ``` -/// When we try the alternatives of the `true | false` or-pattern, the last `0` is reachable in the -/// `false` alternative but not the `true`. So overall it is reachable. By contrast, the last `1` -/// is not reachable in either alternative, so we want to signal this to the user. -/// Therefore we take the union of sets of reachable patterns coming from different alternatives in -/// order to figure out which subpatterns are overall reachable. -/// -/// Invariant: we try to construct the smallest representation we can. In particular if -/// `self.is_empty()` we ensure that `self` is `Empty`, and same with `Full`. This is not important -/// for correctness currently. -#[derive(Debug, Clone)] -enum SubPatSet<'p, 'tcx> { - /// The empty set. This means the pattern is unreachable. - Empty, - /// The set containing the full pattern. - Full, - /// If the pattern is a pattern with a constructor or a pattern-stack, we store a set for each - /// of its subpatterns. Missing entries in the map are implicitly full, because that's the - /// common case. - Seq { subpats: FxHashMap> }, - /// If the pattern is an or-pattern, we store a set for each of its alternatives. Missing - /// entries in the map are implicitly empty. Note: we always flatten nested or-patterns. - Alt { - subpats: FxHashMap>, - /// Counts the total number of alternatives in the pattern - alt_count: usize, - /// We keep the pattern around to retrieve spans. - pat: &'p Pat<'tcx>, - }, -} - -impl<'p, 'tcx> SubPatSet<'p, 'tcx> { - fn full() -> Self { - SubPatSet::Full - } - fn empty() -> Self { - SubPatSet::Empty - } - - fn is_empty(&self) -> bool { - match self { - SubPatSet::Empty => true, - SubPatSet::Full => false, - // If any subpattern in a sequence is unreachable, the whole pattern is unreachable. - SubPatSet::Seq { subpats } => subpats.values().any(|set| set.is_empty()), - // An or-pattern is reachable if any of its alternatives is. - SubPatSet::Alt { subpats, .. } => subpats.values().all(|set| set.is_empty()), - } - } - - fn is_full(&self) -> bool { - match self { - SubPatSet::Empty => false, - SubPatSet::Full => true, - // The whole pattern is reachable only when all its alternatives are. - SubPatSet::Seq { subpats } => subpats.values().all(|sub_set| sub_set.is_full()), - // The whole or-pattern is reachable only when all its alternatives are. - SubPatSet::Alt { subpats, alt_count, .. } => { - subpats.len() == *alt_count && subpats.values().all(|set| set.is_full()) - } - } - } - - /// Union `self` with `other`, mutating `self`. - fn union(&mut self, other: Self) { - use SubPatSet::*; - // Union with full stays full; union with empty changes nothing. - if self.is_full() || other.is_empty() { - return; - } else if self.is_empty() { - *self = other; - return; - } else if other.is_full() { - *self = Full; - return; - } - - match (&mut *self, other) { - (Seq { subpats: s_set }, Seq { subpats: mut o_set }) => { - s_set.retain(|i, s_sub_set| { - // Missing entries count as full. - let o_sub_set = o_set.remove(&i).unwrap_or(Full); - s_sub_set.union(o_sub_set); - // We drop full entries. - !s_sub_set.is_full() - }); - // Everything left in `o_set` is missing from `s_set`, i.e. counts as full. Since - // unioning with full returns full, we can drop those entries. - } - (Alt { subpats: s_set, .. }, Alt { subpats: mut o_set, .. }) => { - s_set.retain(|i, s_sub_set| { - // Missing entries count as empty. - let o_sub_set = o_set.remove(&i).unwrap_or(Empty); - s_sub_set.union(o_sub_set); - // We drop empty entries. - !s_sub_set.is_empty() - }); - // Everything left in `o_set` is missing from `s_set`, i.e. counts as empty. Since - // unioning with empty changes nothing, we can take those entries as is. - s_set.extend(o_set); - } - _ => bug!(), - } - - if self.is_full() { - *self = Full; - } - } - - /// Returns a list of the spans of the unreachable subpatterns. If `self` is empty (i.e. the - /// whole pattern is unreachable) we return `None`. - fn list_unreachable_spans(&self) -> Option> { - /// Panics if `set.is_empty()`. - fn fill_spans(set: &SubPatSet<'_, '_>, spans: &mut Vec) { - match set { - SubPatSet::Empty => bug!(), - SubPatSet::Full => {} - SubPatSet::Seq { subpats } => { - for (_, sub_set) in subpats { - fill_spans(sub_set, spans); - } - } - SubPatSet::Alt { subpats, pat, alt_count, .. } => { - let expanded = expand_or_pat(pat); - for i in 0..*alt_count { - let sub_set = subpats.get(&i).unwrap_or(&SubPatSet::Empty); - if sub_set.is_empty() { - // Found an unreachable subpattern. - spans.push(expanded[i].span); - } else { - fill_spans(sub_set, spans); - } - } - } - } - } - - if self.is_empty() { - return None; - } - if self.is_full() { - // No subpatterns are unreachable. - return Some(Vec::new()); - } - let mut spans = Vec::new(); - fill_spans(self, &mut spans); - Some(spans) - } - - /// When `self` refers to a patstack that was obtained from specialization, after running - /// `unspecialize` it will refer to the original patstack before specialization. - fn unspecialize(self, arity: usize) -> Self { - use SubPatSet::*; - match self { - Full => Full, - Empty => Empty, - Seq { subpats } => { - // We gather the first `arity` subpatterns together and shift the remaining ones. - let mut new_subpats = FxHashMap::default(); - let mut new_subpats_first_col = FxHashMap::default(); - for (i, sub_set) in subpats { - if i < arity { - // The first `arity` indices are now part of the pattern in the first - // column. - new_subpats_first_col.insert(i, sub_set); - } else { - // Indices after `arity` are simply shifted - new_subpats.insert(i - arity + 1, sub_set); - } - } - // If `new_subpats_first_col` has no entries it counts as full, so we can omit it. - if !new_subpats_first_col.is_empty() { - new_subpats.insert(0, Seq { subpats: new_subpats_first_col }); - } - Seq { subpats: new_subpats } - } - Alt { .. } => bug!(), // `self` is a patstack - } - } - - /// When `self` refers to a patstack that was obtained from splitting an or-pattern, after - /// running `unspecialize` it will refer to the original patstack before splitting. - /// - /// For example: - /// ``` - /// match Some(true) { - /// Some(true) => {} - /// None | Some(true | false) => {} - /// } - /// ``` - /// Here `None` would return the full set and `Some(true | false)` would return the set - /// containing `false`. After `unsplit_or_pat`, we want the set to contain `None` and `false`. - /// This is what this function does. - fn unsplit_or_pat(mut self, alt_id: usize, alt_count: usize, pat: &'p Pat<'tcx>) -> Self { - use SubPatSet::*; - if self.is_empty() { - return Empty; - } - - // Subpatterns coming from inside the or-pattern alternative itself, e.g. in `None | Some(0 - // | 1)`. - let set_first_col = match &mut self { - Full => Full, - Seq { subpats } => subpats.remove(&0).unwrap_or(Full), - Empty => unreachable!(), - Alt { .. } => bug!(), // `self` is a patstack - }; - let mut subpats_first_col = FxHashMap::default(); - subpats_first_col.insert(alt_id, set_first_col); - let set_first_col = Alt { subpats: subpats_first_col, pat, alt_count }; - - let mut subpats = match self { - Full => FxHashMap::default(), - Seq { subpats } => subpats, - Empty => unreachable!(), - Alt { .. } => bug!(), // `self` is a patstack - }; - subpats.insert(0, set_first_col); - Seq { subpats } - } -} - /// This carries the results of computing usefulness, as described at the top of the file. When /// checking usefulness of a match branch, we use the `NoWitnesses` variant, which also keeps track /// of potential unreachable sub-patterns (in the presence of or-patterns). When checking /// exhaustiveness of a whole match, we use the `WithWitnesses` variant, which carries a list of /// witnesses of non-exhaustiveness when there are any. -/// Which variant to use is dictated by `WitnessPreference`. -#[derive(Clone, Debug)] +/// Which variant to use is dictated by `ArmType`. +#[derive(Debug)] enum Usefulness<'p, 'tcx> { - /// Carries a set of subpatterns that have been found to be reachable. If empty, this indicates - /// the whole pattern is unreachable. If not, this indicates that the pattern is reachable but - /// that some sub-patterns may be unreachable (due to or-patterns). In the absence of - /// or-patterns this will always be either `Empty` (the whole pattern is unreachable) or `Full` - /// (the whole pattern is reachable). - NoWitnesses(SubPatSet<'p, 'tcx>), + /// If we don't care about witnesses, simply remember if the pattern was useful. + NoWitnesses { useful: bool }, /// Carries a list of witnesses of non-exhaustiveness. If empty, indicates that the whole /// pattern is unreachable. - WithWitnesses(Vec>), + WithWitnesses(Vec>), } impl<'p, 'tcx> Usefulness<'p, 'tcx> { - fn new_useful(preference: WitnessPreference) -> Self { + fn new_useful(preference: ArmType) -> Self { match preference { - ConstructWitness => WithWitnesses(vec![Witness(vec![])]), - LeaveOutWitness => NoWitnesses(SubPatSet::full()), + // A single (empty) witness of reachability. + FakeExtraWildcard => WithWitnesses(vec![Witness(vec![])]), + RealArm => NoWitnesses { useful: true }, } } - fn new_not_useful(preference: WitnessPreference) -> Self { + + fn new_not_useful(preference: ArmType) -> Self { match preference { - ConstructWitness => WithWitnesses(vec![]), - LeaveOutWitness => NoWitnesses(SubPatSet::empty()), + FakeExtraWildcard => WithWitnesses(vec![]), + RealArm => NoWitnesses { useful: false }, + } + } + + fn is_useful(&self) -> bool { + match self { + Usefulness::NoWitnesses { useful } => *useful, + Usefulness::WithWitnesses(witnesses) => !witnesses.is_empty(), } } @@ -896,37 +555,14 @@ impl<'p, 'tcx> Usefulness<'p, 'tcx> { (WithWitnesses(_), WithWitnesses(o)) if o.is_empty() => {} (WithWitnesses(s), WithWitnesses(o)) if s.is_empty() => *self = WithWitnesses(o), (WithWitnesses(s), WithWitnesses(o)) => s.extend(o), - (NoWitnesses(s), NoWitnesses(o)) => s.union(o), + (NoWitnesses { useful: s_useful }, NoWitnesses { useful: o_useful }) => { + *s_useful = *s_useful || o_useful + } _ => unreachable!(), } } - /// When trying several branches and each returns a `Usefulness`, we need to combine the - /// results together. - fn merge(pref: WitnessPreference, usefulnesses: impl Iterator) -> Self { - let mut ret = Self::new_not_useful(pref); - for u in usefulnesses { - ret.extend(u); - if let NoWitnesses(subpats) = &ret { - if subpats.is_full() { - // Once we reach the full set, more unions won't change the result. - return ret; - } - } - } - ret - } - - /// After calculating the usefulness for a branch of an or-pattern, call this to make this - /// usefulness mergeable with those from the other branches. - fn unsplit_or_pat(self, alt_id: usize, alt_count: usize, pat: &'p Pat<'tcx>) -> Self { - match self { - NoWitnesses(subpats) => NoWitnesses(subpats.unsplit_or_pat(alt_id, alt_count, pat)), - WithWitnesses(_) => bug!(), - } - } - - /// After calculating usefulness after a specialization, call this to recontruct a usefulness + /// After calculating usefulness after a specialization, call this to reconstruct a usefulness /// that makes sense for the matrix pre-specialization. This new usefulness can then be merged /// with the results of specializing with the other constructors. fn apply_constructor( @@ -934,51 +570,81 @@ impl<'p, 'tcx> Usefulness<'p, 'tcx> { pcx: PatCtxt<'_, 'p, 'tcx>, matrix: &Matrix<'p, 'tcx>, // used to compute missing ctors ctor: &Constructor<'tcx>, - ctor_wild_subpatterns: &Fields<'p, 'tcx>, ) -> Self { match self { - WithWitnesses(witnesses) if witnesses.is_empty() => WithWitnesses(witnesses), + NoWitnesses { .. } => self, + WithWitnesses(ref witnesses) if witnesses.is_empty() => self, WithWitnesses(witnesses) => { - let new_witnesses = if matches!(ctor, Constructor::Missing) { - let mut split_wildcard = SplitWildcard::new(pcx); - split_wildcard.split(pcx, matrix.head_ctors(pcx.cx)); - // Construct for each missing constructor a "wild" version of this - // constructor, that matches everything that can be built with - // it. For example, if `ctor` is a `Constructor::Variant` for - // `Option::Some`, we get the pattern `Some(_)`. - let new_patterns: Vec<_> = split_wildcard - .iter_missing(pcx) - .map(|missing_ctor| { - Fields::wildcards(pcx, missing_ctor).apply(pcx, missing_ctor) - }) - .collect(); + let new_witnesses = if let Constructor::Missing { .. } = ctor { + // We got the special `Missing` constructor, so each of the missing constructors + // gives a new pattern that is not caught by the match. We list those patterns. + let new_patterns = if pcx.is_non_exhaustive { + // Here we don't want the user to try to list all variants, we want them to add + // a wildcard, so we only suggest that. + vec![DeconstructedPat::wildcard(pcx.ty)] + } else { + let mut split_wildcard = SplitWildcard::new(pcx); + split_wildcard.split(pcx, matrix.heads().map(DeconstructedPat::ctor)); + + // This lets us know if we skipped any variants because they are marked + // `doc(hidden)` or they are unstable feature gate (only stdlib types). + let mut hide_variant_show_wild = false; + // Construct for each missing constructor a "wild" version of this + // constructor, that matches everything that can be built with + // it. For example, if `ctor` is a `Constructor::Variant` for + // `Option::Some`, we get the pattern `Some(_)`. + let mut new: Vec> = split_wildcard + .iter_missing(pcx) + .filter_map(|missing_ctor| { + // Check if this variant is marked `doc(hidden)` + if missing_ctor.is_doc_hidden_variant(pcx) + || missing_ctor.is_unstable_variant(pcx) + { + hide_variant_show_wild = true; + return None; + } + Some(DeconstructedPat::wild_from_ctor(pcx, missing_ctor.clone())) + }) + .collect(); + + if hide_variant_show_wild { + new.push(DeconstructedPat::wildcard(pcx.ty)); + } + + new + }; + witnesses .into_iter() .flat_map(|witness| { new_patterns.iter().map(move |pat| { - let mut witness = witness.clone(); - witness.0.push(pat.clone()); - witness + Witness( + witness + .0 + .iter() + .chain(once(pat)) + .map(DeconstructedPat::clone_and_forget_reachability) + .collect(), + ) }) }) .collect() } else { witnesses .into_iter() - .map(|witness| witness.apply_constructor(pcx, &ctor, ctor_wild_subpatterns)) + .map(|witness| witness.apply_constructor(pcx, &ctor)) .collect() }; WithWitnesses(new_witnesses) } - NoWitnesses(subpats) => NoWitnesses(subpats.unspecialize(ctor_wild_subpatterns.len())), } } } #[derive(Copy, Clone, Debug)] -enum WitnessPreference { - ConstructWitness, - LeaveOutWitness, +enum ArmType { + FakeExtraWildcard, + RealArm, } /// A witness of non-exhaustiveness for error reporting, represented @@ -1014,12 +680,12 @@ enum WitnessPreference { /// `Witness(vec![Pair(Some(_), true)])` /// /// The final `Pair(Some(_), true)` is then the resulting witness. -#[derive(Clone, Debug)] -crate struct Witness<'tcx>(Vec>); +#[derive(Debug)] +crate struct Witness<'p, 'tcx>(Vec>); -impl<'tcx> Witness<'tcx> { +impl<'p, 'tcx> Witness<'p, 'tcx> { /// Asserts that the witness contains a single pattern, and returns it. - fn single_pattern(self) -> Pat<'tcx> { + fn single_pattern(self) -> DeconstructedPat<'p, 'tcx> { assert_eq!(self.0.len(), 1); self.0.into_iter().next().unwrap() } @@ -1037,17 +703,13 @@ impl<'tcx> Witness<'tcx> { /// /// left_ty: struct X { a: (bool, &'static str), b: usize} /// pats: [(false, "foo"), 42] => X { a: (false, "foo"), b: 42 } - fn apply_constructor<'p>( - mut self, - pcx: PatCtxt<'_, 'p, 'tcx>, - ctor: &Constructor<'tcx>, - ctor_wild_subpatterns: &Fields<'p, 'tcx>, - ) -> Self { + fn apply_constructor(mut self, pcx: PatCtxt<'_, 'p, 'tcx>, ctor: &Constructor<'tcx>) -> Self { let pat = { let len = self.0.len(); - let arity = ctor_wild_subpatterns.len(); + let arity = ctor.arity(pcx); let pats = self.0.drain((len - arity)..).rev(); - ctor_wild_subpatterns.replace_fields(pcx.cx, pats).apply(pcx, ctor) + let fields = Fields::from_iter(pcx.cx, pats); + DeconstructedPat::new(ctor.clone(), fields, pcx.ty, DUMMY_SP) }; self.0.push(pat); @@ -1056,6 +718,32 @@ impl<'tcx> Witness<'tcx> { } } +/// Report that a match of a `non_exhaustive` enum marked with `non_exhaustive_omitted_patterns` +/// is not exhaustive enough. +/// +/// NB: The partner lint for structs lives in `compiler/rustc_typeck/src/check/pat.rs`. +fn lint_non_exhaustive_omitted_patterns<'p, 'tcx>( + cx: &MatchCheckCtxt<'p, 'tcx>, + scrut_ty: Ty<'tcx>, + sp: Span, + hir_id: HirId, + witnesses: Vec>, +) { + let joined_patterns = joined_uncovered_patterns(cx, &witnesses); + cx.tcx.struct_span_lint_hir(NON_EXHAUSTIVE_OMITTED_PATTERNS, hir_id, sp, |build| { + let mut lint = build.build("some variants are not matched explicitly"); + lint.span_label(sp, pattern_not_covered_label(&witnesses, &joined_patterns)); + lint.help( + "ensure that all variants are matched explicitly by adding the suggested match arms", + ); + lint.note(&format!( + "the matched value is of type `{}` and the `non_exhaustive_omitted_patterns` attribute was found", + scrut_ty, + )); + lint.emit(); + }); +} + /// Algorithm from . /// The algorithm from the paper has been modified to correctly handle empty /// types. The changes are: @@ -1086,7 +774,7 @@ fn is_useful<'p, 'tcx>( cx: &MatchCheckCtxt<'p, 'tcx>, matrix: &Matrix<'p, 'tcx>, v: &PatStack<'p, 'tcx>, - witness_preference: WitnessPreference, + witness_preference: ArmType, hir_id: HirId, is_under_guard: bool, is_top_level: bool, @@ -1111,59 +799,96 @@ fn is_useful<'p, 'tcx>( assert!(rows.iter().all(|r| r.len() == v.len())); - // FIXME(Nadrieril): Hack to work around type normalization issues (see #72476). - let ty = matrix.heads().next().map_or(v.head().ty, |r| r.ty); - let pcx = PatCtxt { cx, ty, span: v.head().span, is_top_level }; + let ty = v.head().ty(); + let is_non_exhaustive = cx.is_foreign_non_exhaustive_enum(ty); + let pcx = PatCtxt { cx, ty, span: v.head().span(), is_top_level, is_non_exhaustive }; // If the first pattern is an or-pattern, expand it. - let ret = if is_or_pat(v.head()) { + let mut ret = Usefulness::new_not_useful(witness_preference); + if v.head().is_or_pat() { debug!("expanding or-pattern"); - let v_head = v.head(); - let vs: Vec<_> = v.expand_or_pat().collect(); - let alt_count = vs.len(); // We try each or-pattern branch in turn. let mut matrix = matrix.clone(); - let usefulnesses = vs.into_iter().enumerate().map(|(i, v)| { + for v in v.expand_or_pat() { let usefulness = 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 { // We push the already-seen patterns into the matrix in order to detect redundant // branches like `Some(_) | Some(0)`. matrix.push(v); } - usefulness.unsplit_or_pat(i, alt_count, v_head) - }); - Usefulness::merge(witness_preference, usefulnesses) + } } else { - let v_ctor = v.head_ctor(cx); + let v_ctor = v.head().ctor(); if let Constructor::IntRange(ctor_range) = &v_ctor { // Lint on likely incorrect range patterns (#63987) ctor_range.lint_overlapping_range_endpoints( pcx, - matrix.head_ctors_and_spans(cx), + matrix.heads(), matrix.column_count().unwrap_or(0), hir_id, ) } // We split the head constructor of `v`. - let split_ctors = v_ctor.split(pcx, matrix.head_ctors(cx)); + let split_ctors = v_ctor.split(pcx, matrix.heads().map(DeconstructedPat::ctor)); + let is_non_exhaustive_and_wild = is_non_exhaustive && v_ctor.is_wildcard(); // For each constructor, we compute whether there's a value that starts with it that would // witness the usefulness of `v`. let start_matrix = &matrix; - let usefulnesses = split_ctors.into_iter().map(|ctor| { + for ctor in split_ctors { debug!("specialize({:?})", ctor); // We cache the result of `Fields::wildcards` because it is used a lot. - let ctor_wild_subpatterns = Fields::wildcards(pcx, &ctor); - let spec_matrix = - start_matrix.specialize_constructor(pcx, &ctor, &ctor_wild_subpatterns); - let v = v.pop_head_constructor(&ctor_wild_subpatterns); + 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); - usefulness.apply_constructor(pcx, start_matrix, &ctor, &ctor_wild_subpatterns) - }); - Usefulness::merge(witness_preference, usefulnesses) - }; + let usefulness = usefulness.apply_constructor(pcx, start_matrix, &ctor); + + // When all the conditions are met we have a match with a `non_exhaustive` enum + // that has the potential to trigger the `non_exhaustive_omitted_patterns` lint. + // To understand the workings checkout `Constructor::split` and `SplitWildcard::new/into_ctors` + if is_non_exhaustive_and_wild + // We check that the match has a wildcard pattern and that that wildcard is useful, + // meaning there are variants that are covered by the wildcard. Without the check + // for `witness_preference` the lint would trigger on `if let NonExhaustiveEnum::A = foo {}` + && usefulness.is_useful() && matches!(witness_preference, RealArm) + && matches!( + &ctor, + Constructor::Missing { nonexhaustive_enum_missing_real_variants: true } + ) + { + let patterns = { + let mut split_wildcard = SplitWildcard::new(pcx); + split_wildcard.split(pcx, matrix.heads().map(DeconstructedPat::ctor)); + // Construct for each missing constructor a "wild" version of this + // constructor, that matches everything that can be built with + // it. For example, if `ctor` is a `Constructor::Variant` for + // `Option::Some`, we get the pattern `Some(_)`. + split_wildcard + .iter_missing(pcx) + // Filter out the `NonExhaustive` because we want to list only real + // variants. Also remove any unstable feature gated variants. + // Because of how we computed `nonexhaustive_enum_missing_real_variants`, + // this will not return an empty `Vec`. + .filter(|c| !(c.is_non_exhaustive() || c.is_unstable_variant(pcx))) + .cloned() + .map(|missing_ctor| DeconstructedPat::wild_from_ctor(pcx, missing_ctor)) + .collect::>() + }; + + lint_non_exhaustive_omitted_patterns(pcx.cx, pcx.ty, pcx.span, hir_id, patterns); + } + + ret.extend(usefulness); + } + } + + if ret.is_useful() { + v.head().set_reachable(); + } + debug!(?ret); ret } @@ -1172,7 +897,7 @@ fn is_useful<'p, 'tcx>( #[derive(Clone, Copy)] crate struct MatchArm<'p, 'tcx> { /// The pattern must have been lowered through `check_match::MatchVisitor::lower_pattern`. - crate pat: &'p Pat<'tcx>, + crate pat: &'p DeconstructedPat<'p, 'tcx>, crate hir_id: HirId, crate has_guard: bool, } @@ -1194,7 +919,7 @@ crate struct UsefulnessReport<'p, 'tcx> { crate arm_usefulness: Vec<(MatchArm<'p, 'tcx>, Reachability)>, /// If the match is exhaustive, this is empty. If not, this contains witnesses for the lack of /// exhaustiveness. - crate non_exhaustiveness_witnesses: Vec>, + crate non_exhaustiveness_witnesses: Vec>, } /// The entrypoint for the usefulness algorithm. Computes whether a match is exhaustive and which @@ -1214,28 +939,25 @@ crate fn compute_match_usefulness<'p, 'tcx>( .copied() .map(|arm| { let v = PatStack::from_pattern(arm.pat); - let usefulness = - is_useful(cx, &matrix, &v, LeaveOutWitness, arm.hir_id, arm.has_guard, true); + is_useful(cx, &matrix, &v, RealArm, arm.hir_id, arm.has_guard, true); if !arm.has_guard { matrix.push(v); } - let reachability = match usefulness { - NoWitnesses(subpats) if subpats.is_empty() => Reachability::Unreachable, - NoWitnesses(subpats) => { - Reachability::Reachable(subpats.list_unreachable_spans().unwrap()) - } - WithWitnesses(..) => bug!(), + let reachability = if arm.pat.is_reachable() { + Reachability::Reachable(arm.pat.unreachable_spans()) + } else { + Reachability::Unreachable }; (arm, reachability) }) .collect(); - let wild_pattern = cx.pattern_arena.alloc(Pat::wildcard_from_ty(scrut_ty)); + let wild_pattern = cx.pattern_arena.alloc(DeconstructedPat::wildcard(scrut_ty)); let v = PatStack::from_pattern(wild_pattern); - let usefulness = is_useful(cx, &matrix, &v, ConstructWitness, scrut_hir_id, false, true); + let usefulness = is_useful(cx, &matrix, &v, FakeExtraWildcard, scrut_hir_id, false, true); let non_exhaustiveness_witnesses = match usefulness { WithWitnesses(pats) => pats.into_iter().map(|w| w.single_pattern()).collect(), - NoWitnesses(_) => bug!(), + NoWitnesses { .. } => bug!(), }; UsefulnessReport { arm_usefulness, non_exhaustiveness_witnesses } } diff --git a/compiler/rustc_mir_dataflow/Cargo.toml b/compiler/rustc_mir_dataflow/Cargo.toml new file mode 100644 index 0000000000..ffd7e3cd06 --- /dev/null +++ b/compiler/rustc_mir_dataflow/Cargo.toml @@ -0,0 +1,23 @@ +[package] +name = "rustc_mir_dataflow" +version = "0.0.0" +edition = "2021" + +[lib] +doctest = false + +[dependencies] +polonius-engine = "0.13.0" +regex = "1" +smallvec = { version = "1.6.1", features = ["union", "may_dangle"] } +tracing = "0.1" +rustc_ast = { path = "../rustc_ast" } +rustc_data_structures = { path = "../rustc_data_structures" } +rustc_graphviz = { path = "../rustc_graphviz" } +rustc_hir = { path = "../rustc_hir" } +rustc_index = { path = "../rustc_index" } +rustc_middle = { path = "../rustc_middle" } +rustc_serialize = { path = "../rustc_serialize" } +rustc_session = { path = "../rustc_session" } +rustc_target = { path = "../rustc_target" } +rustc_span = { path = "../rustc_span" } diff --git a/compiler/rustc_mir/src/dataflow/drop_flag_effects.rs b/compiler/rustc_mir_dataflow/src/drop_flag_effects.rs similarity index 96% rename from compiler/rustc_mir/src/dataflow/drop_flag_effects.rs rename to compiler/rustc_mir_dataflow/src/drop_flag_effects.rs index d16366fded..e2269562b3 100644 --- a/compiler/rustc_mir/src/dataflow/drop_flag_effects.rs +++ b/compiler/rustc_mir_dataflow/src/drop_flag_effects.rs @@ -1,4 +1,4 @@ -use crate::util::elaborate_drops::DropFlagState; +use crate::elaborate_drops::DropFlagState; use rustc_middle::mir::{self, Body, Location}; use rustc_middle::ty::{self, TyCtxt}; use rustc_target::abi::VariantIdx; @@ -79,7 +79,7 @@ fn place_contents_drop_state_cannot_differ<'tcx>( } } -pub(crate) fn on_lookup_result_bits<'tcx, F>( +pub fn on_lookup_result_bits<'tcx, F>( tcx: TyCtxt<'tcx>, body: &Body<'tcx>, move_data: &MoveData<'tcx>, @@ -96,7 +96,7 @@ pub(crate) fn on_lookup_result_bits<'tcx, F>( } } -pub(crate) fn on_all_children_bits<'tcx, F>( +pub fn on_all_children_bits<'tcx, F>( tcx: TyCtxt<'tcx>, body: &Body<'tcx>, move_data: &MoveData<'tcx>, @@ -138,7 +138,7 @@ pub(crate) fn on_all_children_bits<'tcx, F>( on_all_children_bits(tcx, body, move_data, move_path_index, &mut each_child); } -pub(crate) fn on_all_drop_children_bits<'tcx, F>( +pub fn on_all_drop_children_bits<'tcx, F>( tcx: TyCtxt<'tcx>, body: &Body<'tcx>, ctxt: &MoveDataParamEnv<'tcx>, @@ -161,7 +161,7 @@ pub(crate) fn on_all_drop_children_bits<'tcx, F>( }) } -pub(crate) fn drop_flag_effects_for_function_entry<'tcx, F>( +pub fn drop_flag_effects_for_function_entry<'tcx, F>( tcx: TyCtxt<'tcx>, body: &Body<'tcx>, ctxt: &MoveDataParamEnv<'tcx>, @@ -179,7 +179,7 @@ pub(crate) fn drop_flag_effects_for_function_entry<'tcx, F>( } } -pub(crate) fn drop_flag_effects_for_location<'tcx, F>( +pub fn drop_flag_effects_for_location<'tcx, F>( tcx: TyCtxt<'tcx>, body: &Body<'tcx>, ctxt: &MoveDataParamEnv<'tcx>, @@ -204,7 +204,7 @@ pub(crate) fn drop_flag_effects_for_location<'tcx, F>( for_location_inits(tcx, body, move_data, loc, |mpi| callback(mpi, DropFlagState::Present)); } -pub(crate) fn for_location_inits<'tcx, F>( +pub fn for_location_inits<'tcx, F>( tcx: TyCtxt<'tcx>, body: &Body<'tcx>, move_data: &MoveData<'tcx>, diff --git a/compiler/rustc_mir/src/util/elaborate_drops.rs b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs similarity index 99% rename from compiler/rustc_mir/src/util/elaborate_drops.rs rename to compiler/rustc_mir_dataflow/src/elaborate_drops.rs index 50756fc15f..7607ccc3ab 100644 --- a/compiler/rustc_mir/src/util/elaborate_drops.rs +++ b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs @@ -1,7 +1,7 @@ -use crate::util::patch::MirPatch; use rustc_hir as hir; use rustc_hir::lang_items::LangItem; use rustc_index::vec::Idx; +use rustc_middle::mir::patch::MirPatch; use rustc_middle::mir::*; use rustc_middle::traits::Reveal; use rustc_middle::ty::subst::SubstsRef; diff --git a/compiler/rustc_mir/src/dataflow/framework/cursor.rs b/compiler/rustc_mir_dataflow/src/framework/cursor.rs similarity index 100% rename from compiler/rustc_mir/src/dataflow/framework/cursor.rs rename to compiler/rustc_mir_dataflow/src/framework/cursor.rs diff --git a/compiler/rustc_mir/src/dataflow/framework/direction.rs b/compiler/rustc_mir_dataflow/src/framework/direction.rs similarity index 100% rename from compiler/rustc_mir/src/dataflow/framework/direction.rs rename to compiler/rustc_mir_dataflow/src/framework/direction.rs diff --git a/compiler/rustc_mir/src/dataflow/framework/engine.rs b/compiler/rustc_mir_dataflow/src/framework/engine.rs similarity index 99% rename from compiler/rustc_mir/src/dataflow/framework/engine.rs rename to compiler/rustc_mir_dataflow/src/framework/engine.rs index 7ff7c86059..804abc3b42 100644 --- a/compiler/rustc_mir/src/dataflow/framework/engine.rs +++ b/compiler/rustc_mir_dataflow/src/framework/engine.rs @@ -11,6 +11,7 @@ use rustc_hir::def_id::DefId; use rustc_index::bit_set::BitSet; use rustc_index::vec::{Idx, IndexVec}; use rustc_middle::mir::{self, traversal, BasicBlock}; +use rustc_middle::mir::{create_dump_file, dump_enabled}; use rustc_middle::ty::TyCtxt; use rustc_span::symbol::{sym, Symbol}; @@ -20,7 +21,6 @@ use super::{ visit_results, Analysis, Direction, GenKill, GenKillAnalysis, GenKillSet, JoinSemiLattice, ResultsCursor, ResultsVisitor, }; -use crate::util::pretty::{create_dump_file, dump_enabled}; /// A dataflow analysis that has converged to fixpoint. pub struct Results<'tcx, A> diff --git a/compiler/rustc_mir/src/dataflow/framework/fmt.rs b/compiler/rustc_mir_dataflow/src/framework/fmt.rs similarity index 94% rename from compiler/rustc_mir/src/dataflow/framework/fmt.rs rename to compiler/rustc_mir_dataflow/src/framework/fmt.rs index 35115ca9db..1d1553bbbd 100644 --- a/compiler/rustc_mir/src/dataflow/framework/fmt.rs +++ b/compiler/rustc_mir_dataflow/src/framework/fmt.rs @@ -147,18 +147,18 @@ where } impl DebugWithContext for rustc_middle::mir::Local {} -impl DebugWithContext for crate::dataflow::move_paths::InitIndex {} +impl DebugWithContext for crate::move_paths::InitIndex {} -impl<'tcx, C> DebugWithContext for crate::dataflow::move_paths::MovePathIndex +impl<'tcx, C> DebugWithContext for crate::move_paths::MovePathIndex where - C: crate::dataflow::move_paths::HasMoveData<'tcx>, + C: crate::move_paths::HasMoveData<'tcx>, { fn fmt_with(&self, ctxt: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{}", ctxt.move_data().move_paths[*self]) } } -impl DebugWithContext for crate::dataflow::lattice::Dual +impl DebugWithContext for crate::lattice::Dual where T: DebugWithContext, { diff --git a/compiler/rustc_mir/src/dataflow/framework/graphviz.rs b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs similarity index 99% rename from compiler/rustc_mir/src/dataflow/framework/graphviz.rs rename to compiler/rustc_mir_dataflow/src/framework/graphviz.rs index 4e54257a1c..a370f8e40f 100644 --- a/compiler/rustc_mir/src/dataflow/framework/graphviz.rs +++ b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs @@ -6,11 +6,11 @@ use std::{io, ops, str}; use regex::Regex; use rustc_graphviz as dot; +use rustc_middle::mir::graphviz_safe_def_name; use rustc_middle::mir::{self, BasicBlock, Body, Location}; use super::fmt::{DebugDiffWithAdapter, DebugWithAdapter, DebugWithContext}; use super::{Analysis, Direction, Results, ResultsRefCursor, ResultsVisitor}; -use crate::util::graphviz_safe_def_name; #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum OutputStyle { diff --git a/compiler/rustc_mir/src/dataflow/framework/lattice.rs b/compiler/rustc_mir_dataflow/src/framework/lattice.rs similarity index 100% rename from compiler/rustc_mir/src/dataflow/framework/lattice.rs rename to compiler/rustc_mir_dataflow/src/framework/lattice.rs diff --git a/compiler/rustc_mir/src/dataflow/framework/mod.rs b/compiler/rustc_mir_dataflow/src/framework/mod.rs similarity index 99% rename from compiler/rustc_mir/src/dataflow/framework/mod.rs rename to compiler/rustc_mir_dataflow/src/framework/mod.rs index a5badc07d1..f0c9ac4c50 100644 --- a/compiler/rustc_mir/src/dataflow/framework/mod.rs +++ b/compiler/rustc_mir_dataflow/src/framework/mod.rs @@ -11,7 +11,7 @@ //! `visit_results`. The following example uses the `ResultsCursor` approach. //! //! ```ignore (cross-crate-imports) -//! use rustc_mir::dataflow::Analysis; // Makes `into_engine` available. +//! use rustc_const_eval::dataflow::Analysis; // Makes `into_engine` available. //! //! fn do_my_analysis(tcx: TyCtxt<'tcx>, body: &mir::Body<'tcx>) { //! let analysis = MyAnalysis::new() @@ -50,8 +50,7 @@ pub use self::cursor::{ResultsCursor, ResultsRefCursor}; pub use self::direction::{Backward, Direction, Forward}; pub use self::engine::{Engine, Results}; pub use self::lattice::{JoinSemiLattice, MeetSemiLattice}; -pub use self::visitor::{visit_results, ResultsVisitor}; -pub use self::visitor::{BorrowckFlowState, BorrowckResults}; +pub use self::visitor::{visit_results, ResultsVisitable, ResultsVisitor}; /// Define the domain of a dataflow problem. /// diff --git a/compiler/rustc_mir/src/dataflow/framework/tests.rs b/compiler/rustc_mir_dataflow/src/framework/tests.rs similarity index 100% rename from compiler/rustc_mir/src/dataflow/framework/tests.rs rename to compiler/rustc_mir_dataflow/src/framework/tests.rs diff --git a/compiler/rustc_mir/src/dataflow/framework/visitor.rs b/compiler/rustc_mir_dataflow/src/framework/visitor.rs similarity index 63% rename from compiler/rustc_mir/src/dataflow/framework/visitor.rs rename to compiler/rustc_mir_dataflow/src/framework/visitor.rs index 82eb734ed0..84136c4d78 100644 --- a/compiler/rustc_mir/src/dataflow/framework/visitor.rs +++ b/compiler/rustc_mir_dataflow/src/framework/visitor.rs @@ -1,7 +1,6 @@ use rustc_middle::mir::{self, BasicBlock, Location}; use super::{Analysis, Direction, Results}; -use crate::dataflow::impls::{borrows::Borrows, EverInitializedPlaces, MaybeUninitializedPlaces}; /// Calls the corresponding method in `ResultsVisitor` for every location in a `mir::Body` with the /// dataflow state at that location. @@ -186,95 +185,3 @@ where self.analysis.apply_terminator_effect(state, term, loc); } } - -/// A tuple with named fields that can hold either the results or the transient state of the -/// dataflow analyses used by the borrow checker. -#[derive(Debug)] -pub struct BorrowckAnalyses { - pub borrows: B, - pub uninits: U, - pub ever_inits: E, -} - -/// The results of the dataflow analyses used by the borrow checker. -pub type BorrowckResults<'mir, 'tcx> = BorrowckAnalyses< - Results<'tcx, Borrows<'mir, 'tcx>>, - Results<'tcx, MaybeUninitializedPlaces<'mir, 'tcx>>, - Results<'tcx, EverInitializedPlaces<'mir, 'tcx>>, ->; - -/// The transient state of the dataflow analyses used by the borrow checker. -pub type BorrowckFlowState<'mir, 'tcx> = - as ResultsVisitable<'tcx>>::FlowState; - -macro_rules! impl_visitable { - ( $( - $T:ident { $( $field:ident : $A:ident ),* $(,)? } - )* ) => { $( - impl<'tcx, $($A),*, D: Direction> ResultsVisitable<'tcx> for $T<$( Results<'tcx, $A> ),*> - where - $( $A: Analysis<'tcx, Direction = D>, )* - { - type Direction = D; - type FlowState = $T<$( $A::Domain ),*>; - - fn new_flow_state(&self, body: &mir::Body<'tcx>) -> Self::FlowState { - $T { - $( $field: self.$field.analysis.bottom_value(body) ),* - } - } - - fn reset_to_block_entry( - &self, - state: &mut Self::FlowState, - block: BasicBlock, - ) { - $( state.$field.clone_from(&self.$field.entry_set_for_block(block)); )* - } - - fn reconstruct_before_statement_effect( - &self, - state: &mut Self::FlowState, - stmt: &mir::Statement<'tcx>, - loc: Location, - ) { - $( self.$field.analysis - .apply_before_statement_effect(&mut state.$field, stmt, loc); )* - } - - fn reconstruct_statement_effect( - &self, - state: &mut Self::FlowState, - stmt: &mir::Statement<'tcx>, - loc: Location, - ) { - $( self.$field.analysis - .apply_statement_effect(&mut state.$field, stmt, loc); )* - } - - fn reconstruct_before_terminator_effect( - &self, - state: &mut Self::FlowState, - term: &mir::Terminator<'tcx>, - loc: Location, - ) { - $( self.$field.analysis - .apply_before_terminator_effect(&mut state.$field, term, loc); )* - } - - fn reconstruct_terminator_effect( - &self, - state: &mut Self::FlowState, - term: &mir::Terminator<'tcx>, - loc: Location, - ) { - $( self.$field.analysis - .apply_terminator_effect(&mut state.$field, term, loc); )* - } - } - )* } -} - -impl_visitable! { - BorrowckAnalyses { borrows: B, uninits: U, ever_inits: E } -} diff --git a/compiler/rustc_mir/src/dataflow/impls/borrowed_locals.rs b/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs similarity index 98% rename from compiler/rustc_mir/src/dataflow/impls/borrowed_locals.rs rename to compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs index 65e04ed683..158ba1b942 100644 --- a/compiler/rustc_mir/src/dataflow/impls/borrowed_locals.rs +++ b/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs @@ -1,6 +1,6 @@ -pub use super::*; +use super::*; -use crate::dataflow::{AnalysisDomain, GenKill, GenKillAnalysis}; +use crate::{AnalysisDomain, GenKill, GenKillAnalysis}; use rustc_middle::mir::visit::Visitor; use rustc_middle::mir::*; use rustc_middle::ty::{ParamEnv, TyCtxt}; @@ -169,6 +169,7 @@ where } mir::Rvalue::Cast(..) + | mir::Rvalue::ShallowInitBox(..) | mir::Rvalue::Use(..) | mir::Rvalue::ThreadLocalRef(..) | mir::Rvalue::Repeat(..) diff --git a/compiler/rustc_mir/src/dataflow/impls/init_locals.rs b/compiler/rustc_mir_dataflow/src/impls/init_locals.rs similarity index 95% rename from compiler/rustc_mir/src/dataflow/impls/init_locals.rs rename to compiler/rustc_mir_dataflow/src/impls/init_locals.rs index bb7292cd03..07570e764f 100644 --- a/compiler/rustc_mir/src/dataflow/impls/init_locals.rs +++ b/compiler/rustc_mir_dataflow/src/impls/init_locals.rs @@ -2,7 +2,7 @@ //! //! A local will be maybe initialized if *any* projections of that local might be initialized. -use crate::dataflow::{self, GenKill}; +use crate::GenKill; use rustc_index::bit_set::BitSet; use rustc_middle::mir::visit::{PlaceContext, Visitor}; @@ -10,7 +10,7 @@ use rustc_middle::mir::{self, BasicBlock, Local, Location}; pub struct MaybeInitializedLocals; -impl dataflow::AnalysisDomain<'tcx> for MaybeInitializedLocals { +impl crate::AnalysisDomain<'tcx> for MaybeInitializedLocals { type Domain = BitSet; const NAME: &'static str = "maybe_init_locals"; @@ -28,7 +28,7 @@ impl dataflow::AnalysisDomain<'tcx> for MaybeInitializedLocals { } } -impl dataflow::GenKillAnalysis<'tcx> for MaybeInitializedLocals { +impl crate::GenKillAnalysis<'tcx> for MaybeInitializedLocals { type Idx = Local; fn statement_effect( diff --git a/compiler/rustc_mir/src/dataflow/impls/liveness.rs b/compiler/rustc_mir_dataflow/src/impls/liveness.rs similarity index 81% rename from compiler/rustc_mir/src/dataflow/impls/liveness.rs rename to compiler/rustc_mir_dataflow/src/impls/liveness.rs index 2d20f0d954..3e2548845e 100644 --- a/compiler/rustc_mir/src/dataflow/impls/liveness.rs +++ b/compiler/rustc_mir_dataflow/src/impls/liveness.rs @@ -2,7 +2,7 @@ use rustc_index::bit_set::BitSet; use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor}; use rustc_middle::mir::{self, Local, Location}; -use crate::dataflow::{AnalysisDomain, Backward, GenKill, GenKillAnalysis}; +use crate::{AnalysisDomain, Backward, GenKill, GenKillAnalysis}; /// A [live-variable dataflow analysis][liveness]. /// @@ -11,6 +11,37 @@ use crate::dataflow::{AnalysisDomain, Backward, GenKill, GenKillAnalysis}; /// exist. See [this `mir-dataflow` test][flow-test] for an example. You almost never want to use /// this analysis without also looking at the results of [`MaybeBorrowedLocals`]. /// +/// ## Field-(in)sensitivity +/// +/// As the name suggests, this analysis is field insensitive. If a projection of a variable `x` is +/// assigned to (e.g. `x.0 = 42`), it does not "define" `x` as far as liveness is concerned. In fact, +/// such an assignment is currently marked as a "use" of `x` in an attempt to be maximally +/// conservative. +/// +/// ## Enums and `SetDiscriminant` +/// +/// Assigning a literal value to an `enum` (e.g. `Option`), does not result in a simple +/// assignment of the form `_1 = /*...*/` in the MIR. For example, the following assignment to `x`: +/// +/// ``` +/// x = Some(4); +/// ``` +/// +/// compiles to this MIR +/// +/// ``` +/// ((_1 as Some).0: i32) = const 4_i32; +/// discriminant(_1) = 1; +/// ``` +/// +/// However, `MaybeLiveLocals` **does** mark `x` (`_1`) as "killed" after a statement like this. +/// That's because it treats the `SetDiscriminant` operation as a definition of `x`, even though +/// the writes that actually initialized the locals happened earlier. +/// +/// This makes `MaybeLiveLocals` unsuitable for certain classes of optimization normally associated +/// with a live variables analysis, notably dead-store elimination. It's a dirty hack, but it works +/// okay for the generator state transform (currently the main consumuer of this analysis). +/// /// [`MaybeBorrowedLocals`]: super::MaybeBorrowedLocals /// [flow-test]: https://github.com/rust-lang/rust/blob/a08c47310c7d49cbdc5d7afb38408ba519967ecd/src/test/ui/mir-dataflow/liveness-ptr.rs /// [liveness]: https://en.wikipedia.org/wiki/Live_variable_analysis diff --git a/compiler/rustc_mir/src/dataflow/impls/mod.rs b/compiler/rustc_mir_dataflow/src/impls/mod.rs similarity index 95% rename from compiler/rustc_mir/src/dataflow/impls/mod.rs rename to compiler/rustc_mir_dataflow/src/impls/mod.rs index 185f0edfeb..474f4f2a79 100644 --- a/compiler/rustc_mir/src/dataflow/impls/mod.rs +++ b/compiler/rustc_mir_dataflow/src/impls/mod.rs @@ -7,27 +7,22 @@ use rustc_index::vec::Idx; use rustc_middle::mir::{self, Body, Location}; use rustc_middle::ty::{self, TyCtxt}; -use super::MoveDataParamEnv; - -use crate::util::elaborate_drops::DropFlagState; - -use super::move_paths::{HasMoveData, InitIndex, InitKind, MoveData, MovePathIndex}; -use super::{lattice, AnalysisDomain, GenKill, GenKillAnalysis}; - -use super::drop_flag_effects_for_function_entry; -use super::drop_flag_effects_for_location; -use super::on_lookup_result_bits; -use crate::dataflow::drop_flag_effects; -use crate::dataflow::framework::SwitchIntEdgeEffects; +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::on_lookup_result_bits; +use crate::MoveDataParamEnv; +use crate::{lattice, AnalysisDomain, GenKill, GenKillAnalysis}; mod borrowed_locals; -pub(super) mod borrows; mod init_locals; mod liveness; mod storage_liveness; pub use self::borrowed_locals::{MaybeBorrowedLocals, MaybeMutBorrowedLocals}; -pub use self::borrows::Borrows; pub use self::init_locals::MaybeInitializedLocals; pub use self::liveness::MaybeLiveLocals; pub use self::storage_liveness::{MaybeRequiresStorage, MaybeStorageLive}; @@ -607,6 +602,7 @@ impl<'tcx> AnalysisDomain<'tcx> for EverInitializedPlaces<'_, 'tcx> { impl<'tcx> GenKillAnalysis<'tcx> for EverInitializedPlaces<'_, 'tcx> { type Idx = InitIndex; + #[instrument(skip(self, trans), level = "debug")] fn statement_effect( &self, trans: &mut impl GenKill, @@ -618,24 +614,19 @@ impl<'tcx> GenKillAnalysis<'tcx> for EverInitializedPlaces<'_, 'tcx> { let init_loc_map = &move_data.init_loc_map; let rev_lookup = &move_data.rev_lookup; - debug!( - "statement {:?} at loc {:?} initializes move_indexes {:?}", - stmt, location, &init_loc_map[location] - ); + debug!("initializes move_indexes {:?}", &init_loc_map[location]); trans.gen_all(init_loc_map[location].iter().copied()); if let mir::StatementKind::StorageDead(local) = stmt.kind { // End inits for StorageDead, so that an immutable variable can // be reinitialized on the next iteration of the loop. let move_path_index = rev_lookup.find_local(local); - debug!( - "stmt {:?} at loc {:?} clears the ever initialized status of {:?}", - stmt, location, &init_path_map[move_path_index] - ); + debug!("clears the ever initialized status of {:?}", init_path_map[move_path_index]); trans.kill_all(init_path_map[move_path_index].iter().copied()); } } + #[instrument(skip(self, trans, _terminator), level = "debug")] fn terminator_effect( &self, trans: &mut impl GenKill, @@ -645,10 +636,8 @@ impl<'tcx> GenKillAnalysis<'tcx> for EverInitializedPlaces<'_, 'tcx> { let (body, move_data) = (self.body, self.move_data()); let term = body[location.block].terminator(); let init_loc_map = &move_data.init_loc_map; - debug!( - "terminator {:?} at loc {:?} initializes move_indexes {:?}", - term, location, &init_loc_map[location] - ); + debug!(?term); + debug!("initializes move_indexes {:?}", init_loc_map[location]); trans.gen_all( init_loc_map[location] .iter() diff --git a/compiler/rustc_mir/src/dataflow/impls/storage_liveness.rs b/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs similarity index 96% rename from compiler/rustc_mir/src/dataflow/impls/storage_liveness.rs rename to compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs index 792664597f..b468e50b39 100644 --- a/compiler/rustc_mir/src/dataflow/impls/storage_liveness.rs +++ b/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs @@ -1,7 +1,7 @@ pub use super::*; -use crate::dataflow::{self, GenKill, Results, ResultsRefCursor}; -use crate::util::storage::AlwaysLiveLocals; +use crate::storage::AlwaysLiveLocals; +use crate::{GenKill, Results, ResultsRefCursor}; use rustc_middle::mir::visit::{NonMutatingUseContext, PlaceContext, Visitor}; use rustc_middle::mir::*; use std::cell::RefCell; @@ -17,7 +17,7 @@ impl MaybeStorageLive { } } -impl dataflow::AnalysisDomain<'tcx> for MaybeStorageLive { +impl crate::AnalysisDomain<'tcx> for MaybeStorageLive { type Domain = BitSet; const NAME: &'static str = "maybe_storage_live"; @@ -39,7 +39,7 @@ impl dataflow::AnalysisDomain<'tcx> for MaybeStorageLive { } } -impl dataflow::GenKillAnalysis<'tcx> for MaybeStorageLive { +impl crate::GenKillAnalysis<'tcx> for MaybeStorageLive { type Idx = Local; fn statement_effect( @@ -97,7 +97,7 @@ impl<'mir, 'tcx> MaybeRequiresStorage<'mir, 'tcx> { } } -impl<'mir, 'tcx> dataflow::AnalysisDomain<'tcx> for MaybeRequiresStorage<'mir, 'tcx> { +impl<'mir, 'tcx> crate::AnalysisDomain<'tcx> for MaybeRequiresStorage<'mir, 'tcx> { type Domain = BitSet; const NAME: &'static str = "requires_storage"; @@ -116,7 +116,7 @@ impl<'mir, 'tcx> dataflow::AnalysisDomain<'tcx> for MaybeRequiresStorage<'mir, ' } } -impl<'mir, 'tcx> dataflow::GenKillAnalysis<'tcx> for MaybeRequiresStorage<'mir, 'tcx> { +impl<'mir, 'tcx> crate::GenKillAnalysis<'tcx> for MaybeRequiresStorage<'mir, 'tcx> { type Idx = Local; fn before_statement_effect( diff --git a/compiler/rustc_mir_dataflow/src/lib.rs b/compiler/rustc_mir_dataflow/src/lib.rs new file mode 100644 index 0000000000..402391b87e --- /dev/null +++ b/compiler/rustc_mir_dataflow/src/lib.rs @@ -0,0 +1,72 @@ +#![feature(associated_type_defaults)] +#![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(min_specialization)] +#![feature(once_cell)] +#![feature(stmt_expr_attributes)] +#![feature(trusted_step)] +#![recursion_limit = "256"] + +#[macro_use] +extern crate tracing; +#[macro_use] +extern crate rustc_middle; + +use rustc_ast::{self as ast, MetaItem}; +use rustc_middle::ty; +use rustc_session::Session; +use rustc_span::symbol::{sym, Symbol}; + +pub use self::drop_flag_effects::{ + drop_flag_effects_for_function_entry, drop_flag_effects_for_location, + move_path_children_matching, on_all_children_bits, on_all_drop_children_bits, + on_lookup_result_bits, +}; +pub use self::framework::{ + fmt, graphviz, lattice, visit_results, Analysis, AnalysisDomain, Backward, Direction, Engine, + Forward, GenKill, GenKillAnalysis, JoinSemiLattice, Results, ResultsCursor, ResultsRefCursor, + ResultsVisitable, ResultsVisitor, +}; + +use self::move_paths::MoveData; + +pub mod drop_flag_effects; +pub mod elaborate_drops; +mod framework; +pub mod impls; +pub mod move_paths; +pub mod rustc_peek; +pub mod storage; + +pub(crate) mod indexes { + pub(crate) use super::move_paths::MovePathIndex; +} + +pub struct MoveDataParamEnv<'tcx> { + pub move_data: MoveData<'tcx>, + pub param_env: ty::ParamEnv<'tcx>, +} + +pub fn has_rustc_mir_with( + _sess: &Session, + attrs: &[ast::Attribute], + name: Symbol, +) -> Option { + for attr in attrs { + if attr.has_name(sym::rustc_mir) { + let items = attr.meta_item_list(); + for item in items.iter().flat_map(|l| l.iter()) { + match item.meta_item() { + Some(mi) if mi.has_name(name) => return Some(mi.clone()), + _ => continue, + } + } + } + } + None +} diff --git a/compiler/rustc_mir/src/dataflow/move_paths/abs_domain.rs b/compiler/rustc_mir_dataflow/src/move_paths/abs_domain.rs similarity index 100% rename from compiler/rustc_mir/src/dataflow/move_paths/abs_domain.rs rename to compiler/rustc_mir_dataflow/src/move_paths/abs_domain.rs diff --git a/compiler/rustc_mir/src/dataflow/move_paths/builder.rs b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs similarity index 99% rename from compiler/rustc_mir/src/dataflow/move_paths/builder.rs rename to compiler/rustc_mir_dataflow/src/move_paths/builder.rs index cea465ea1e..e404b49ecb 100644 --- a/compiler/rustc_mir/src/dataflow/move_paths/builder.rs +++ b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs @@ -327,6 +327,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> { Rvalue::Use(ref operand) | Rvalue::Repeat(ref operand, _) | Rvalue::Cast(_, ref operand, _) + | Rvalue::ShallowInitBox(ref operand, _) | Rvalue::UnaryOp(_, ref operand) => self.gather_operand(operand), Rvalue::BinaryOp(ref _binop, box (ref lhs, ref rhs)) | Rvalue::CheckedBinaryOp(ref _binop, box (ref lhs, ref rhs)) => { @@ -342,7 +343,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> { | Rvalue::AddressOf(..) | Rvalue::Discriminant(..) | Rvalue::Len(..) - | Rvalue::NullaryOp(NullOp::SizeOf, _) + | Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf, _) | Rvalue::NullaryOp(NullOp::Box, _) => { // This returns an rvalue with uninitialized contents. We can't // move out of it here because it is an rvalue - assignments always diff --git a/compiler/rustc_mir/src/dataflow/move_paths/mod.rs b/compiler/rustc_mir_dataflow/src/move_paths/mod.rs similarity index 96% rename from compiler/rustc_mir/src/dataflow/move_paths/mod.rs rename to compiler/rustc_mir_dataflow/src/move_paths/mod.rs index 7c63025918..f2b3415938 100644 --- a/compiler/rustc_mir/src/dataflow/move_paths/mod.rs +++ b/compiler/rustc_mir_dataflow/src/move_paths/mod.rs @@ -1,6 +1,5 @@ -use core::slice::Iter; use rustc_data_structures::fx::FxHashMap; -use rustc_index::vec::{Enumerated, IndexVec}; +use rustc_index::vec::IndexVec; use rustc_middle::mir::*; use rustc_middle::ty::{ParamEnv, Ty, TyCtxt}; use rustc_span::Span; @@ -19,6 +18,12 @@ rustc_index::newtype_index! { } } +impl polonius_engine::Atom for MovePathIndex { + fn index(self) -> usize { + rustc_index::vec::Idx::index(self) + } +} + rustc_index::newtype_index! { pub struct MoveOutIndex { DEBUG_FORMAT = "mo{}" @@ -276,7 +281,7 @@ impl fmt::Debug for Init { } impl Init { - crate fn span<'tcx>(&self, body: &Body<'tcx>) -> Span { + pub fn span<'tcx>(&self, body: &Body<'tcx>) -> Span { match self.location { InitLocation::Argument(local) => body.local_decls[local].source_info.span, InitLocation::Statement(location) => body.source_info(location).span, @@ -331,19 +336,21 @@ impl MovePathLookup { /// An enumerated iterator of `local`s and their associated /// `MovePathIndex`es. - pub fn iter_locals_enumerated(&self) -> Enumerated> { + pub fn iter_locals_enumerated( + &self, + ) -> impl DoubleEndedIterator + ExactSizeIterator { self.locals.iter_enumerated() } } #[derive(Debug)] pub struct IllegalMoveOrigin<'tcx> { - pub(crate) location: Location, - pub(crate) kind: IllegalMoveOriginKind<'tcx>, + pub location: Location, + pub kind: IllegalMoveOriginKind<'tcx>, } #[derive(Debug)] -pub(crate) enum IllegalMoveOriginKind<'tcx> { +pub enum IllegalMoveOriginKind<'tcx> { /// Illegal move due to attempt to move from behind a reference. BorrowedContent { /// The place the reference refers to: if erroneous code was trying to diff --git a/compiler/rustc_mir/src/transform/rustc_peek.rs b/compiler/rustc_mir_dataflow/src/rustc_peek.rs similarity index 96% rename from compiler/rustc_mir/src/transform/rustc_peek.rs rename to compiler/rustc_mir_dataflow/src/rustc_peek.rs index f4a1b0ddba..c0bf4b659a 100644 --- a/compiler/rustc_mir/src/transform/rustc_peek.rs +++ b/compiler/rustc_mir_dataflow/src/rustc_peek.rs @@ -5,25 +5,25 @@ use rustc_span::symbol::sym; use rustc_span::Span; use rustc_target::spec::abi::Abi; -use crate::transform::MirPass; use rustc_index::bit_set::BitSet; +use rustc_middle::mir::MirPass; use rustc_middle::mir::{self, Body, Local, Location}; use rustc_middle::ty::{self, Ty, TyCtxt}; -use crate::dataflow::impls::{ +use crate::impls::{ DefinitelyInitializedPlaces, MaybeInitializedPlaces, MaybeLiveLocals, MaybeMutBorrowedLocals, MaybeUninitializedPlaces, }; -use crate::dataflow::move_paths::{HasMoveData, MoveData}; -use crate::dataflow::move_paths::{LookupResult, MovePathIndex}; -use crate::dataflow::MoveDataParamEnv; -use crate::dataflow::{Analysis, JoinSemiLattice, Results, ResultsCursor}; +use crate::move_paths::{HasMoveData, MoveData}; +use crate::move_paths::{LookupResult, MovePathIndex}; +use crate::MoveDataParamEnv; +use crate::{Analysis, JoinSemiLattice, Results, ResultsCursor}; pub struct SanityCheck; impl<'tcx> MirPass<'tcx> for SanityCheck { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - use crate::dataflow::has_rustc_mir_with; + use crate::has_rustc_mir_with; let def_id = body.source.def_id(); if !tcx.has_attr(def_id, sym::rustc_mir) { debug!("skipping rustc_peek::SanityCheck on {}", tcx.def_path_str(def_id)); @@ -289,7 +289,7 @@ impl<'tcx> RustcPeekAt<'tcx> for MaybeMutBorrowedLocals<'_, 'tcx> { flow_state: &BitSet, call: PeekCall, ) { - warn!("peek_at: place={:?}", place); + info!(?place, "peek_at"); let local = if let Some(l) = place.as_local() { l } else { @@ -311,7 +311,7 @@ impl<'tcx> RustcPeekAt<'tcx> for MaybeLiveLocals { flow_state: &BitSet, call: PeekCall, ) { - warn!("peek_at: place={:?}", place); + info!(?place, "peek_at"); let local = if let Some(l) = place.as_local() { l } else { diff --git a/compiler/rustc_mir/src/util/storage.rs b/compiler/rustc_mir_dataflow/src/storage.rs similarity index 100% rename from compiler/rustc_mir/src/util/storage.rs rename to compiler/rustc_mir_dataflow/src/storage.rs diff --git a/compiler/rustc_mir_transform/Cargo.toml b/compiler/rustc_mir_transform/Cargo.toml new file mode 100644 index 0000000000..e85d74ef3e --- /dev/null +++ b/compiler/rustc_mir_transform/Cargo.toml @@ -0,0 +1,30 @@ +[package] +name = "rustc_mir_transform" +version = "0.0.0" +edition = "2021" + +[lib] +doctest = false + +[dependencies] +itertools = "0.9" +smallvec = { version = "1.6.1", features = ["union", "may_dangle"] } +tracing = "0.1" +rustc_ast = { path = "../rustc_ast" } +rustc_attr = { path = "../rustc_attr" } +rustc_data_structures = { path = "../rustc_data_structures" } +rustc_errors = { path = "../rustc_errors" } +rustc_hir = { path = "../rustc_hir" } +rustc_index = { path = "../rustc_index" } +rustc_middle = { path = "../rustc_middle" } +rustc_const_eval = { path = "../rustc_const_eval" } +rustc_mir_dataflow = { path = "../rustc_mir_dataflow" } +rustc_query_system = { path = "../rustc_query_system" } +rustc_serialize = { path = "../rustc_serialize" } +rustc_session = { path = "../rustc_session" } +rustc_target = { path = "../rustc_target" } +rustc_trait_selection = { path = "../rustc_trait_selection" } +rustc_span = { path = "../rustc_span" } + +[dev-dependencies] +coverage_test_macros = { path = "src/coverage/test_macros" } diff --git a/compiler/rustc_mir/src/transform/abort_unwinding_calls.rs b/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs similarity index 93% rename from compiler/rustc_mir/src/transform/abort_unwinding_calls.rs rename to compiler/rustc_mir_transform/src/abort_unwinding_calls.rs index aecb2373ea..1abb64219f 100644 --- a/compiler/rustc_mir/src/transform/abort_unwinding_calls.rs +++ b/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs @@ -1,10 +1,11 @@ -use crate::transform::MirPass; +use crate::MirPass; use rustc_hir::def::DefKind; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::mir::*; use rustc_middle::ty::layout; use rustc_middle::ty::{self, TyCtxt}; use rustc_target::spec::abi::Abi; +use rustc_target::spec::PanicStrategy; /// A pass that runs which is targeted at ensuring that codegen guarantees about /// unwinding are upheld for compilations of panic=abort programs. @@ -82,10 +83,11 @@ impl<'tcx> MirPass<'tcx> for AbortUnwindingCalls { }; layout::fn_can_unwind(tcx, flags, sig.abi()) } - TerminatorKind::Drop { .. } - | TerminatorKind::DropAndReplace { .. } - | TerminatorKind::Assert { .. } - | TerminatorKind::FalseUnwind { .. } => { + TerminatorKind::Drop { .. } | TerminatorKind::DropAndReplace { .. } => { + tcx.sess.opts.debugging_opts.panic_in_drop == PanicStrategy::Unwind + && layout::fn_can_unwind(tcx, CodegenFnAttrFlags::empty(), Abi::Rust) + } + TerminatorKind::Assert { .. } | TerminatorKind::FalseUnwind { .. } => { layout::fn_can_unwind(tcx, CodegenFnAttrFlags::empty(), Abi::Rust) } _ => continue, diff --git a/compiler/rustc_mir/src/transform/add_call_guards.rs b/compiler/rustc_mir_transform/src/add_call_guards.rs similarity index 98% rename from compiler/rustc_mir/src/transform/add_call_guards.rs rename to compiler/rustc_mir_transform/src/add_call_guards.rs index 12ee6bb4c6..cd6b671a0d 100644 --- a/compiler/rustc_mir/src/transform/add_call_guards.rs +++ b/compiler/rustc_mir_transform/src/add_call_guards.rs @@ -1,4 +1,4 @@ -use crate::transform::MirPass; +use crate::MirPass; use rustc_index::vec::{Idx, IndexVec}; use rustc_middle::mir::*; use rustc_middle::ty::TyCtxt; diff --git a/compiler/rustc_mir/src/transform/add_moves_for_packed_drops.rs b/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs similarity index 98% rename from compiler/rustc_mir/src/transform/add_moves_for_packed_drops.rs rename to compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs index 417e0a51ae..9eaf2b6a21 100644 --- a/compiler/rustc_mir/src/transform/add_moves_for_packed_drops.rs +++ b/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs @@ -1,9 +1,9 @@ use rustc_middle::mir::*; use rustc_middle::ty::TyCtxt; -use crate::transform::MirPass; use crate::util; -use crate::util::patch::MirPatch; +use crate::MirPass; +use rustc_middle::mir::patch::MirPatch; // This pass moves values being dropped that are within a packed // struct to a separate local before dropping them, to ensure that diff --git a/compiler/rustc_mir/src/transform/add_retag.rs b/compiler/rustc_mir_transform/src/add_retag.rs similarity index 99% rename from compiler/rustc_mir/src/transform/add_retag.rs rename to compiler/rustc_mir_transform/src/add_retag.rs index cb608819ea..7a8dee09c2 100644 --- a/compiler/rustc_mir/src/transform/add_retag.rs +++ b/compiler/rustc_mir_transform/src/add_retag.rs @@ -4,7 +4,7 @@ //! of MIR building, and only after this pass we think of the program has having the //! normal MIR semantics. -use crate::transform::MirPass; +use crate::MirPass; use rustc_middle::mir::*; use rustc_middle::ty::{self, Ty, TyCtxt}; diff --git a/compiler/rustc_mir/src/transform/check_const_item_mutation.rs b/compiler/rustc_mir_transform/src/check_const_item_mutation.rs similarity index 99% rename from compiler/rustc_mir/src/transform/check_const_item_mutation.rs rename to compiler/rustc_mir_transform/src/check_const_item_mutation.rs index e2d50ba034..27fe80a456 100644 --- a/compiler/rustc_mir/src/transform/check_const_item_mutation.rs +++ b/compiler/rustc_mir_transform/src/check_const_item_mutation.rs @@ -6,7 +6,7 @@ use rustc_middle::ty::TyCtxt; use rustc_session::lint::builtin::CONST_ITEM_MUTATION; use rustc_span::def_id::DefId; -use crate::transform::MirPass; +use crate::MirPass; pub struct CheckConstItemMutation; diff --git a/compiler/rustc_mir/src/transform/check_packed_ref.rs b/compiler/rustc_mir_transform/src/check_packed_ref.rs similarity index 99% rename from compiler/rustc_mir/src/transform/check_packed_ref.rs rename to compiler/rustc_mir_transform/src/check_packed_ref.rs index 13b7221046..49be34c7a2 100644 --- a/compiler/rustc_mir/src/transform/check_packed_ref.rs +++ b/compiler/rustc_mir_transform/src/check_packed_ref.rs @@ -6,8 +6,8 @@ use rustc_middle::ty::{self, TyCtxt}; use rustc_session::lint::builtin::UNALIGNED_REFERENCES; use rustc_span::symbol::sym; -use crate::transform::MirPass; use crate::util; +use crate::MirPass; pub(crate) fn provide(providers: &mut Providers) { *providers = Providers { unsafe_derive_on_repr_packed, ..*providers }; diff --git a/compiler/rustc_mir/src/transform/check_unsafety.rs b/compiler/rustc_mir_transform/src/check_unsafety.rs similarity index 100% rename from compiler/rustc_mir/src/transform/check_unsafety.rs rename to compiler/rustc_mir_transform/src/check_unsafety.rs diff --git a/compiler/rustc_mir/src/transform/cleanup_post_borrowck.rs b/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs similarity index 98% rename from compiler/rustc_mir/src/transform/cleanup_post_borrowck.rs rename to compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs index 8ff0fae768..611d29a4ee 100644 --- a/compiler/rustc_mir/src/transform/cleanup_post_borrowck.rs +++ b/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs @@ -18,7 +18,7 @@ //! [`ForMatchGuard`]: rustc_middle::mir::FakeReadCause::ForMatchGuard //! [`Nop`]: rustc_middle::mir::StatementKind::Nop -use crate::transform::MirPass; +use crate::MirPass; use rustc_middle::mir::visit::MutVisitor; use rustc_middle::mir::{Body, BorrowKind, Location, Rvalue}; use rustc_middle::mir::{Statement, StatementKind}; diff --git a/compiler/rustc_mir/src/transform/const_debuginfo.rs b/compiler/rustc_mir_transform/src/const_debuginfo.rs similarity index 99% rename from compiler/rustc_mir/src/transform/const_debuginfo.rs rename to compiler/rustc_mir_transform/src/const_debuginfo.rs index 3cdaf4c7dc..b613634560 100644 --- a/compiler/rustc_mir/src/transform/const_debuginfo.rs +++ b/compiler/rustc_mir_transform/src/const_debuginfo.rs @@ -9,7 +9,7 @@ use rustc_middle::{ ty::TyCtxt, }; -use crate::transform::MirPass; +use crate::MirPass; use rustc_index::{bit_set::BitSet, vec::IndexVec}; pub struct ConstDebugInfo; diff --git a/compiler/rustc_mir/src/transform/const_goto.rs b/compiler/rustc_mir_transform/src/const_goto.rs similarity index 99% rename from compiler/rustc_mir/src/transform/const_goto.rs rename to compiler/rustc_mir_transform/src/const_goto.rs index ba10b54c5a..d319fdcaa6 100644 --- a/compiler/rustc_mir/src/transform/const_goto.rs +++ b/compiler/rustc_mir_transform/src/const_goto.rs @@ -17,7 +17,7 @@ //! } //! ``` -use crate::transform::MirPass; +use crate::MirPass; use rustc_middle::mir::*; use rustc_middle::ty::TyCtxt; use rustc_middle::{mir::visit::Visitor, ty::ParamEnv}; diff --git a/compiler/rustc_mir/src/transform/const_prop.rs b/compiler/rustc_mir_transform/src/const_prop.rs similarity index 99% rename from compiler/rustc_mir/src/transform/const_prop.rs rename to compiler/rustc_mir_transform/src/const_prop.rs index 5c51aa4ed6..17790ec91c 100644 --- a/compiler/rustc_mir/src/transform/const_prop.rs +++ b/compiler/rustc_mir_transform/src/const_prop.rs @@ -17,24 +17,24 @@ use rustc_middle::mir::{ Location, Operand, Place, Rvalue, SourceInfo, SourceScope, SourceScopeData, Statement, StatementKind, Terminator, TerminatorKind, UnOp, RETURN_PLACE, }; -use rustc_middle::ty::layout::{LayoutError, TyAndLayout}; +use rustc_middle::ty::layout::{LayoutError, LayoutOf, LayoutOfHelpers, TyAndLayout}; use rustc_middle::ty::subst::{InternalSubsts, Subst}; use rustc_middle::ty::{ self, ConstInt, ConstKind, Instance, ParamEnv, ScalarInt, Ty, TyCtxt, TypeFoldable, }; use rustc_session::lint; use rustc_span::{def_id::DefId, Span}; -use rustc_target::abi::{HasDataLayout, LayoutOf, Size, TargetDataLayout}; +use rustc_target::abi::{HasDataLayout, Size, TargetDataLayout}; use rustc_target::spec::abi::Abi; use rustc_trait_selection::traits; -use crate::const_eval::ConstEvalErr; -use crate::interpret::{ +use crate::MirPass; +use rustc_const_eval::const_eval::ConstEvalErr; +use rustc_const_eval::interpret::{ self, compile_time_machine, AllocId, Allocation, ConstValue, CtfeValidationMode, Frame, ImmTy, Immediate, InterpCx, InterpResult, LocalState, LocalValue, MemPlace, MemoryKind, OpTy, Operand as InterpOperand, PlaceTy, Scalar, ScalarMaybeUninit, StackPopCleanup, StackPopUnwind, }; -use crate::transform::MirPass; /// The maximum number of bytes that we'll allocate space for a local or the return value. /// Needed for #66397, because otherwise we eval into large places and that can cause OOM or just @@ -330,12 +330,12 @@ struct ConstPropagator<'mir, 'tcx> { source_info: Option, } -impl<'mir, 'tcx> LayoutOf<'tcx> for ConstPropagator<'mir, 'tcx> { - type Ty = Ty<'tcx>; - type TyAndLayout = Result, LayoutError<'tcx>>; +impl<'mir, 'tcx> LayoutOfHelpers<'tcx> for ConstPropagator<'mir, 'tcx> { + type LayoutOfResult = Result, LayoutError<'tcx>>; - fn layout_of(&self, ty: Ty<'tcx>) -> Self::TyAndLayout { - self.tcx.layout_of(self.param_env.and(ty)) + #[inline] + fn handle_layout_err(&self, err: LayoutError<'tcx>, _: Span, _: Ty<'tcx>) -> LayoutError<'tcx> { + err } } @@ -723,6 +723,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { | Rvalue::Repeat(..) | Rvalue::Len(..) | Rvalue::Cast(..) + | Rvalue::ShallowInitBox(..) | Rvalue::Discriminant(..) | Rvalue::NullaryOp(..) => {} } diff --git a/compiler/rustc_mir/src/transform/coverage/counters.rs b/compiler/rustc_mir_transform/src/coverage/counters.rs similarity index 100% rename from compiler/rustc_mir/src/transform/coverage/counters.rs rename to compiler/rustc_mir_transform/src/coverage/counters.rs diff --git a/compiler/rustc_mir/src/transform/coverage/debug.rs b/compiler/rustc_mir_transform/src/coverage/debug.rs similarity index 97% rename from compiler/rustc_mir/src/transform/coverage/debug.rs rename to compiler/rustc_mir_transform/src/coverage/debug.rs index 464079656f..513a85b591 100644 --- a/compiler/rustc_mir/src/transform/coverage/debug.rs +++ b/compiler/rustc_mir_transform/src/coverage/debug.rs @@ -44,7 +44,7 @@ //! points, which can be enabled via environment variable: //! //! ```shell -//! RUSTC_LOG=rustc_mir::transform::coverage=debug +//! RUSTC_LOG=rustc_mir_transform::transform::coverage=debug //! ``` //! //! Other module paths with coverage-related debug logs may also be of interest, particularly for @@ -52,7 +52,7 @@ //! code generation pass). For example: //! //! ```shell -//! RUSTC_LOG=rustc_mir::transform::coverage,rustc_codegen_ssa::coverageinfo,rustc_codegen_llvm::coverageinfo=debug +//! RUSTC_LOG=rustc_mir_transform::transform::coverage,rustc_codegen_ssa::coverageinfo,rustc_codegen_llvm::coverageinfo=debug //! ``` //! //! Coverage Debug Options @@ -111,9 +111,9 @@ use super::graph::{BasicCoverageBlock, BasicCoverageBlockData, CoverageGraph}; use super::spans::CoverageSpan; -use crate::util::generic_graphviz::GraphvizWriter; -use crate::util::pretty; -use crate::util::spanview::{self, SpanViewable}; +use rustc_middle::mir::create_dump_file; +use rustc_middle::mir::generic_graphviz::GraphvizWriter; +use rustc_middle::mir::spanview::{self, SpanViewable}; use rustc_data_structures::fx::FxHashMap; use rustc_middle::mir::coverage::*; @@ -181,13 +181,11 @@ impl DebugOptions { } }; } - _ => { - bug!( - "Unsupported setting `{}` in environment variable {}", - option, - RUSTC_COVERAGE_DEBUG_OPTIONS - ) - } + _ => bug!( + "Unsupported setting `{}` in environment variable {}", + option, + RUSTC_COVERAGE_DEBUG_OPTIONS + ), }; } } @@ -643,7 +641,7 @@ pub(super) fn dump_coverage_spanview( let def_id = mir_source.def_id(); let span_viewables = span_viewables(tcx, mir_body, basic_coverage_blocks, &coverage_spans); - let mut file = pretty::create_dump_file(tcx, "html", None, pass_name, &0, mir_source) + let mut file = create_dump_file(tcx, "html", None, pass_name, &0, mir_source) .expect("Unexpected error creating MIR spanview HTML file"); let crate_name = tcx.crate_name(def_id.krate); let item_name = tcx.def_path(def_id).to_filename_friendly_no_crate(); @@ -745,7 +743,7 @@ pub(super) fn dump_coverage_graphviz( .join("\n ") )); } - let mut file = pretty::create_dump_file(tcx, "dot", None, pass_name, &0, mir_source) + let mut file = create_dump_file(tcx, "dot", None, pass_name, &0, mir_source) .expect("Unexpected error creating BasicCoverageBlock graphviz DOT file"); graphviz_writer .write_graphviz(tcx, &mut file) diff --git a/compiler/rustc_mir/src/transform/coverage/graph.rs b/compiler/rustc_mir_transform/src/coverage/graph.rs similarity index 100% rename from compiler/rustc_mir/src/transform/coverage/graph.rs rename to compiler/rustc_mir_transform/src/coverage/graph.rs diff --git a/compiler/rustc_mir/src/transform/coverage/mod.rs b/compiler/rustc_mir_transform/src/coverage/mod.rs similarity index 99% rename from compiler/rustc_mir/src/transform/coverage/mod.rs rename to compiler/rustc_mir_transform/src/coverage/mod.rs index f7fbea6ad5..1c946bd2d8 100644 --- a/compiler/rustc_mir/src/transform/coverage/mod.rs +++ b/compiler/rustc_mir_transform/src/coverage/mod.rs @@ -12,8 +12,7 @@ use counters::CoverageCounters; use graph::{BasicCoverageBlock, BasicCoverageBlockData, CoverageGraph}; use spans::{CoverageSpan, CoverageSpans}; -use crate::transform::MirPass; -use crate::util::pretty; +use crate::MirPass; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::graph::WithNumNodes; @@ -22,14 +21,15 @@ 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::ich::StableHashingContext; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::mir::coverage::*; +use rustc_middle::mir::dump_enabled; use rustc_middle::mir::{ self, BasicBlock, BasicBlockData, Coverage, SourceInfo, Statement, StatementKind, Terminator, 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}; @@ -159,7 +159,7 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> { let mut graphviz_data = debug::GraphvizData::new(); let mut debug_used_expressions = debug::UsedExpressions::new(); - let dump_mir = pretty::dump_enabled(tcx, self.pass_name, def_id); + let dump_mir = dump_enabled(tcx, self.pass_name, def_id); let dump_graphviz = dump_mir && tcx.sess.opts.debugging_opts.dump_mir_graphviz; let dump_spanview = dump_mir && tcx.sess.opts.debugging_opts.dump_mir_spanview.is_some(); @@ -263,7 +263,7 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> { } if let Err(e) = result { - bug!("Error processing: {:?}: {:?}", self.mir_body.source.def_id(), e) + bug!("Error processing: {:?}: {:?}", self.mir_body.source.def_id(), e.message) }; // Depending on current `debug_options()`, `alert_on_unused_expressions()` could panic, so diff --git a/compiler/rustc_mir/src/transform/coverage/query.rs b/compiler/rustc_mir_transform/src/coverage/query.rs similarity index 100% rename from compiler/rustc_mir/src/transform/coverage/query.rs rename to compiler/rustc_mir_transform/src/coverage/query.rs diff --git a/compiler/rustc_mir/src/transform/coverage/spans.rs b/compiler/rustc_mir_transform/src/coverage/spans.rs similarity index 99% rename from compiler/rustc_mir/src/transform/coverage/spans.rs rename to compiler/rustc_mir_transform/src/coverage/spans.rs index 08cc87ccc3..cc525a4d6b 100644 --- a/compiler/rustc_mir/src/transform/coverage/spans.rs +++ b/compiler/rustc_mir_transform/src/coverage/spans.rs @@ -1,15 +1,13 @@ use super::debug::term_type; use super::graph::{BasicCoverageBlock, BasicCoverageBlockData, CoverageGraph, START_BCB}; -use crate::util::spanview::source_range_no_file; - use rustc_data_structures::graph::WithNumNodes; +use rustc_middle::mir::spanview::source_range_no_file; use rustc_middle::mir::{ self, AggregateKind, BasicBlock, FakeReadCause, Rvalue, Statement, StatementKind, Terminator, TerminatorKind, }; use rustc_middle::ty::TyCtxt; - use rustc_span::source_map::original_sp; use rustc_span::{BytePos, ExpnKind, MacroKind, Span, Symbol}; @@ -198,7 +196,11 @@ impl CoverageSpan { /// body_span), returns the macro name symbol. pub fn visible_macro(&self, body_span: Span) -> Option { if let Some(current_macro) = self.current_macro() { - if self.expn_span.parent().unwrap_or_else(|| bug!("macro must have a parent")).ctxt() + if self + .expn_span + .parent_callsite() + .unwrap_or_else(|| bug!("macro must have a parent")) + .ctxt() == body_span.ctxt() { return Some(current_macro); diff --git a/compiler/rustc_mir/src/transform/coverage/test_macros/Cargo.toml b/compiler/rustc_mir_transform/src/coverage/test_macros/Cargo.toml similarity index 85% rename from compiler/rustc_mir/src/transform/coverage/test_macros/Cargo.toml rename to compiler/rustc_mir_transform/src/coverage/test_macros/Cargo.toml index cc93fd482b..f5e8b65656 100644 --- a/compiler/rustc_mir/src/transform/coverage/test_macros/Cargo.toml +++ b/compiler/rustc_mir_transform/src/coverage/test_macros/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "coverage_test_macros" version = "0.0.0" -edition = "2018" +edition = "2021" [lib] proc-macro = true diff --git a/compiler/rustc_mir/src/transform/coverage/test_macros/src/lib.rs b/compiler/rustc_mir_transform/src/coverage/test_macros/src/lib.rs similarity index 100% rename from compiler/rustc_mir/src/transform/coverage/test_macros/src/lib.rs rename to compiler/rustc_mir_transform/src/coverage/test_macros/src/lib.rs diff --git a/compiler/rustc_mir/src/transform/coverage/tests.rs b/compiler/rustc_mir_transform/src/coverage/tests.rs similarity index 100% rename from compiler/rustc_mir/src/transform/coverage/tests.rs rename to compiler/rustc_mir_transform/src/coverage/tests.rs diff --git a/compiler/rustc_mir/src/transform/deaggregator.rs b/compiler/rustc_mir_transform/src/deaggregator.rs similarity index 98% rename from compiler/rustc_mir/src/transform/deaggregator.rs rename to compiler/rustc_mir_transform/src/deaggregator.rs index 5bd7256c66..a5491f0ef4 100644 --- a/compiler/rustc_mir/src/transform/deaggregator.rs +++ b/compiler/rustc_mir_transform/src/deaggregator.rs @@ -1,5 +1,5 @@ -use crate::transform::MirPass; use crate::util::expand_aggregate; +use crate::MirPass; use rustc_middle::mir::*; use rustc_middle::ty::TyCtxt; diff --git a/compiler/rustc_mir/src/transform/deduplicate_blocks.rs b/compiler/rustc_mir_transform/src/deduplicate_blocks.rs similarity index 99% rename from compiler/rustc_mir/src/transform/deduplicate_blocks.rs rename to compiler/rustc_mir_transform/src/deduplicate_blocks.rs index 912505c659..8d2413433a 100644 --- a/compiler/rustc_mir/src/transform/deduplicate_blocks.rs +++ b/compiler/rustc_mir_transform/src/deduplicate_blocks.rs @@ -3,7 +3,7 @@ use std::{collections::hash_map::Entry, hash::Hash, hash::Hasher, iter}; -use crate::transform::MirPass; +use crate::MirPass; use rustc_data_structures::fx::FxHashMap; use rustc_middle::mir::visit::MutVisitor; diff --git a/compiler/rustc_mir/src/transform/dest_prop.rs b/compiler/rustc_mir_transform/src/dest_prop.rs similarity index 99% rename from compiler/rustc_mir/src/transform/dest_prop.rs rename to compiler/rustc_mir_transform/src/dest_prop.rs index 4f5a467a6e..790d9243fb 100644 --- a/compiler/rustc_mir/src/transform/dest_prop.rs +++ b/compiler/rustc_mir_transform/src/dest_prop.rs @@ -96,12 +96,7 @@ //! [previous attempt]: https://github.com/rust-lang/rust/pull/47954 //! [subsequent approach]: https://github.com/rust-lang/rust/pull/71003 -use crate::dataflow::impls::{MaybeInitializedLocals, MaybeLiveLocals}; -use crate::dataflow::Analysis; -use crate::{ - transform::MirPass, - util::{dump_mir, PassWhere}, -}; +use crate::MirPass; use itertools::Itertools; use rustc_data_structures::unify::{InPlaceUnificationTable, UnifyKey}; use rustc_index::{ @@ -110,11 +105,14 @@ use rustc_index::{ }; use rustc_middle::mir::tcx::PlaceTy; use rustc_middle::mir::visit::{MutVisitor, PlaceContext, Visitor}; +use rustc_middle::mir::{dump_mir, PassWhere}; use rustc_middle::mir::{ traversal, Body, InlineAsmOperand, Local, LocalKind, Location, Operand, Place, PlaceElem, Rvalue, Statement, StatementKind, Terminator, TerminatorKind, }; use rustc_middle::ty::TyCtxt; +use rustc_mir_dataflow::impls::{MaybeInitializedLocals, MaybeLiveLocals}; +use rustc_mir_dataflow::Analysis; // Empirical measurements have resulted in some observations: // - Running on a body with a single block and 500 locals takes barely any time @@ -969,6 +967,7 @@ impl<'tcx> Visitor<'tcx> for BorrowCollector { } Rvalue::Cast(..) + | Rvalue::ShallowInitBox(..) | Rvalue::Use(..) | Rvalue::Repeat(..) | Rvalue::Len(..) diff --git a/compiler/rustc_mir/src/transform/dump_mir.rs b/compiler/rustc_mir_transform/src/dump_mir.rs similarity index 74% rename from compiler/rustc_mir/src/transform/dump_mir.rs rename to compiler/rustc_mir_transform/src/dump_mir.rs index 5b6edf17d0..2a24e1ea8d 100644 --- a/compiler/rustc_mir/src/transform/dump_mir.rs +++ b/compiler/rustc_mir_transform/src/dump_mir.rs @@ -5,9 +5,9 @@ use std::fmt; use std::fs::File; use std::io; -use crate::transform::MirPass; -use crate::util as mir_util; +use crate::MirPass; 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}; @@ -39,21 +39,14 @@ pub fn on_mir_pass<'tcx>( body: &Body<'tcx>, is_after: bool, ) { - if mir_util::dump_enabled(tcx, pass_name, body.source.def_id()) { - mir_util::dump_mir( - tcx, - Some(pass_num), - pass_name, - &Disambiguator { is_after }, - body, - |_, _| Ok(()), - ); + 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)?); - mir_util::write_mir_pretty(tcx, None, &mut f)?; + write_mir_pretty(tcx, None, &mut f)?; Ok(()) } diff --git a/compiler/rustc_mir/src/transform/early_otherwise_branch.rs b/compiler/rustc_mir_transform/src/early_otherwise_branch.rs similarity index 98% rename from compiler/rustc_mir/src/transform/early_otherwise_branch.rs rename to compiler/rustc_mir_transform/src/early_otherwise_branch.rs index e507bcb0f8..f191911a6c 100644 --- a/compiler/rustc_mir/src/transform/early_otherwise_branch.rs +++ b/compiler/rustc_mir_transform/src/early_otherwise_branch.rs @@ -1,4 +1,4 @@ -use crate::{transform::MirPass, util::patch::MirPatch}; +use rustc_middle::mir::patch::MirPatch; use rustc_middle::mir::*; use rustc_middle::ty::{Ty, TyCtxt}; use std::fmt::Debug; @@ -263,7 +263,7 @@ impl<'a, 'tcx> Helper<'a, 'tcx> { } // check that the value being matched on is the same. The - if this_bb_discr_info.targets_with_values.iter().find(|x| x.0 == value).is_none() { + if !this_bb_discr_info.targets_with_values.iter().any(|x| x.0 == value) { trace!("NO: values being matched on are not the same"); return None; } diff --git a/compiler/rustc_mir/src/transform/elaborate_drops.rs b/compiler/rustc_mir_transform/src/elaborate_drops.rs similarity index 94% rename from compiler/rustc_mir/src/transform/elaborate_drops.rs rename to compiler/rustc_mir_transform/src/elaborate_drops.rs index 9b44af06b7..b9a48197a3 100644 --- a/compiler/rustc_mir/src/transform/elaborate_drops.rs +++ b/compiler/rustc_mir_transform/src/elaborate_drops.rs @@ -1,18 +1,17 @@ -use crate::dataflow; -use crate::dataflow::impls::{MaybeInitializedPlaces, MaybeUninitializedPlaces}; -use crate::dataflow::move_paths::{LookupResult, MoveData, MovePathIndex}; -use crate::dataflow::on_lookup_result_bits; -use crate::dataflow::MoveDataParamEnv; -use crate::dataflow::{on_all_children_bits, on_all_drop_children_bits}; -use crate::dataflow::{Analysis, ResultsCursor}; -use crate::transform::MirPass; -use crate::util::elaborate_drops::{elaborate_drop, DropFlagState, Unwind}; -use crate::util::elaborate_drops::{DropElaborator, DropFlagMode, DropStyle}; -use crate::util::patch::MirPatch; +use crate::MirPass; use rustc_data_structures::fx::FxHashMap; use rustc_index::bit_set::BitSet; +use rustc_middle::mir::patch::MirPatch; use rustc_middle::mir::*; use rustc_middle::ty::{self, TyCtxt}; +use rustc_mir_dataflow::elaborate_drops::{elaborate_drop, DropFlagState, Unwind}; +use rustc_mir_dataflow::elaborate_drops::{DropElaborator, DropFlagMode, DropStyle}; +use rustc_mir_dataflow::impls::{MaybeInitializedPlaces, MaybeUninitializedPlaces}; +use rustc_mir_dataflow::move_paths::{LookupResult, MoveData, MovePathIndex}; +use rustc_mir_dataflow::on_lookup_result_bits; +use rustc_mir_dataflow::MoveDataParamEnv; +use rustc_mir_dataflow::{on_all_children_bits, on_all_drop_children_bits}; +use rustc_mir_dataflow::{Analysis, ResultsCursor}; use rustc_span::Span; use rustc_target::abi::VariantIdx; use std::fmt; @@ -214,14 +213,14 @@ impl<'a, 'b, 'tcx> DropElaborator<'a, 'tcx> for Elaborator<'a, 'b, 'tcx> { } fn field_subpath(&self, path: Self::Path, field: Field) -> Option { - dataflow::move_path_children_matching(self.ctxt.move_data(), path, |e| match e { + rustc_mir_dataflow::move_path_children_matching(self.ctxt.move_data(), path, |e| match e { ProjectionElem::Field(idx, _) => idx == field, _ => false, }) } fn array_subpath(&self, path: Self::Path, index: u64, size: u64) -> Option { - dataflow::move_path_children_matching(self.ctxt.move_data(), path, |e| match e { + rustc_mir_dataflow::move_path_children_matching(self.ctxt.move_data(), path, |e| match e { ProjectionElem::ConstantIndex { offset, min_length, from_end } => { debug_assert!(size == min_length, "min_length should be exact for arrays"); assert!(!from_end, "from_end should not be used for array element ConstantIndex"); @@ -232,13 +231,13 @@ impl<'a, 'b, 'tcx> DropElaborator<'a, 'tcx> for Elaborator<'a, 'b, 'tcx> { } fn deref_subpath(&self, path: Self::Path) -> Option { - dataflow::move_path_children_matching(self.ctxt.move_data(), path, |e| { + rustc_mir_dataflow::move_path_children_matching(self.ctxt.move_data(), path, |e| { e == ProjectionElem::Deref }) } fn downcast_subpath(&self, path: Self::Path, variant: VariantIdx) -> Option { - dataflow::move_path_children_matching(self.ctxt.move_data(), path, |e| match e { + rustc_mir_dataflow::move_path_children_matching(self.ctxt.move_data(), path, |e| match e { ProjectionElem::Downcast(_, idx) => idx == variant, _ => false, }) @@ -513,9 +512,14 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { fn drop_flags_for_args(&mut self) { let loc = Location::START; - dataflow::drop_flag_effects_for_function_entry(self.tcx, self.body, self.env, |path, ds| { - self.set_drop_flag(loc, path, ds); - }) + rustc_mir_dataflow::drop_flag_effects_for_function_entry( + self.tcx, + self.body, + self.env, + |path, ds| { + self.set_drop_flag(loc, path, ds); + }, + ) } fn drop_flags_for_locs(&mut self) { @@ -556,7 +560,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { } } let loc = Location { block: bb, statement_index: i }; - dataflow::drop_flag_effects_for_location( + rustc_mir_dataflow::drop_flag_effects_for_location( self.tcx, self.body, self.env, diff --git a/compiler/rustc_mir/src/transform/function_item_references.rs b/compiler/rustc_mir_transform/src/function_item_references.rs similarity index 98% rename from compiler/rustc_mir/src/transform/function_item_references.rs rename to compiler/rustc_mir_transform/src/function_item_references.rs index ba2c91a934..996c158c06 100644 --- a/compiler/rustc_mir/src/transform/function_item_references.rs +++ b/compiler/rustc_mir_transform/src/function_item_references.rs @@ -11,7 +11,7 @@ use rustc_session::lint::builtin::FUNCTION_ITEM_REFERENCES; use rustc_span::{symbol::sym, Span}; use rustc_target::spec::abi::Abi; -use crate::transform::MirPass; +use crate::MirPass; pub struct FunctionItemReferences; @@ -133,7 +133,7 @@ impl<'a, 'tcx> FunctionItemRefChecker<'a, 'tcx> { /// If the given predicate is the trait `fmt::Pointer`, returns the bound parameter type. fn is_pointer_trait(&self, bound: &PredicateKind<'tcx>) -> Option> { if let ty::PredicateKind::Trait(predicate) = bound { - if self.tcx.is_diagnostic_item(sym::pointer_trait, predicate.def_id()) { + if self.tcx.is_diagnostic_item(sym::Pointer, predicate.def_id()) { Some(predicate.trait_ref.self_ty()) } else { None diff --git a/compiler/rustc_mir/src/transform/generator.rs b/compiler/rustc_mir_transform/src/generator.rs similarity index 98% rename from compiler/rustc_mir/src/transform/generator.rs rename to compiler/rustc_mir_transform/src/generator.rs index acdaa5b456..bc72e9d94a 100644 --- a/compiler/rustc_mir/src/transform/generator.rs +++ b/compiler/rustc_mir_transform/src/generator.rs @@ -49,25 +49,25 @@ //! For generators with state 1 (returned) and state 2 (poisoned) it does nothing. //! Otherwise it drops all the values in scope at the last suspension point. -use crate::dataflow::impls::{ - MaybeBorrowedLocals, MaybeLiveLocals, MaybeRequiresStorage, MaybeStorageLive, -}; -use crate::dataflow::{self, Analysis}; -use crate::transform::simplify; -use crate::transform::MirPass; -use crate::util::dump_mir; +use crate::simplify; use crate::util::expand_aggregate; -use crate::util::storage; +use crate::MirPass; use rustc_data_structures::fx::FxHashMap; use rustc_hir as hir; use rustc_hir::lang_items::LangItem; use rustc_index::bit_set::{BitMatrix, BitSet}; use rustc_index::vec::{Idx, IndexVec}; +use rustc_middle::mir::dump_mir; use rustc_middle::mir::visit::{MutVisitor, PlaceContext, Visitor}; use rustc_middle::mir::*; use rustc_middle::ty::subst::{Subst, SubstsRef}; use rustc_middle::ty::GeneratorSubsts; use rustc_middle::ty::{self, AdtDef, Ty, TyCtxt}; +use rustc_mir_dataflow::impls::{ + MaybeBorrowedLocals, MaybeLiveLocals, MaybeRequiresStorage, MaybeStorageLive, +}; +use rustc_mir_dataflow::storage; +use rustc_mir_dataflow::{self, Analysis}; use rustc_target::abi::VariantIdx; use rustc_target::spec::PanicStrategy; use std::{iter, ops}; @@ -342,7 +342,7 @@ impl MutVisitor<'tcx> for TransformVisitor<'tcx> { let source_info = data.terminator().source_info; // We must assign the value first in case it gets declared dead below data.statements.extend(self.make_state(state_idx, v, source_info)); - let state = if let Some((resume, resume_arg)) = resume { + let state = if let Some((resume, mut resume_arg)) = resume { // Yield let state = 3 + self.suspension_points.len(); @@ -350,7 +350,8 @@ impl MutVisitor<'tcx> for TransformVisitor<'tcx> { // live across a yield. let resume_arg = if let Some(&(ty, variant, idx)) = self.remap.get(&resume_arg.local) { - self.make_field(variant, idx, ty) + replace_base(&mut resume_arg, self.make_field(variant, idx, ty), self.tcx); + resume_arg } else { resume_arg }; @@ -468,7 +469,7 @@ fn locals_live_across_suspend_points( .iterate_to_fixpoint(); let mut borrowed_locals_cursor = - dataflow::ResultsCursor::new(body_ref, &borrowed_locals_results); + rustc_mir_dataflow::ResultsCursor::new(body_ref, &borrowed_locals_results); // Calculate the MIR locals that we actually need to keep storage around // for. @@ -476,7 +477,7 @@ fn locals_live_across_suspend_points( .into_engine(tcx, body_ref) .iterate_to_fixpoint(); let mut requires_storage_cursor = - dataflow::ResultsCursor::new(body_ref, &requires_storage_results); + rustc_mir_dataflow::ResultsCursor::new(body_ref, &requires_storage_results); // Calculate the liveness of MIR locals ignoring borrows. let mut liveness = MaybeLiveLocals @@ -616,7 +617,7 @@ fn compute_storage_conflicts( body: &'mir Body<'tcx>, saved_locals: &GeneratorSavedLocals, always_live_locals: storage::AlwaysLiveLocals, - requires_storage: dataflow::Results<'tcx, MaybeRequiresStorage<'mir, 'tcx>>, + requires_storage: rustc_mir_dataflow::Results<'tcx, MaybeRequiresStorage<'mir, 'tcx>>, ) -> BitMatrix { assert_eq!(body.local_decls.len(), saved_locals.domain_size()); @@ -671,7 +672,7 @@ struct StorageConflictVisitor<'mir, 'tcx, 's> { local_conflicts: BitMatrix, } -impl dataflow::ResultsVisitor<'mir, 'tcx> for StorageConflictVisitor<'mir, 'tcx, '_> { +impl rustc_mir_dataflow::ResultsVisitor<'mir, 'tcx> for StorageConflictVisitor<'mir, 'tcx, '_> { type FlowState = BitSet; fn visit_statement_before_primary_effect( @@ -865,8 +866,8 @@ fn insert_switch<'tcx>( fn elaborate_generator_drops<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { use crate::shim::DropShimElaborator; - use crate::util::elaborate_drops::{elaborate_drop, Unwind}; - use crate::util::patch::MirPatch; + use rustc_middle::mir::patch::MirPatch; + use rustc_mir_dataflow::elaborate_drops::{elaborate_drop, Unwind}; // Note that `elaborate_drops` only drops the upvars of a generator, and // this is ok because `open_drop` can only be reached within that own diff --git a/compiler/rustc_mir/src/transform/inline.rs b/compiler/rustc_mir_transform/src/inline.rs similarity index 99% rename from compiler/rustc_mir/src/transform/inline.rs rename to compiler/rustc_mir_transform/src/inline.rs index 8e9da31eba..ee4e91ecb6 100644 --- a/compiler/rustc_mir/src/transform/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -13,7 +13,7 @@ use rustc_span::{hygiene::ExpnKind, ExpnData, Span}; use rustc_target::spec::abi::Abi; use super::simplify::{remove_dead_blocks, CfgSimplifier}; -use crate::transform::MirPass; +use crate::MirPass; use std::iter; use std::ops::{Range, RangeFrom}; @@ -147,7 +147,7 @@ impl Inliner<'tcx> { self.check_mir_body(callsite, callee_body, callee_attrs)?; if !self.tcx.consider_optimizing(|| { - format!("Inline {:?} into {}", callee_body.span, callsite.callee) + format!("Inline {:?} into {:?}", callsite.callee, caller_body.source) }) { return Err("optimization fuel exhausted"); } diff --git a/compiler/rustc_mir/src/transform/inline/cycle.rs b/compiler/rustc_mir_transform/src/inline/cycle.rs similarity index 100% rename from compiler/rustc_mir/src/transform/inline/cycle.rs rename to compiler/rustc_mir_transform/src/inline/cycle.rs diff --git a/compiler/rustc_mir/src/transform/instcombine.rs b/compiler/rustc_mir_transform/src/instcombine.rs similarity index 99% rename from compiler/rustc_mir/src/transform/instcombine.rs rename to compiler/rustc_mir_transform/src/instcombine.rs index 805f546104..e15a69c95a 100644 --- a/compiler/rustc_mir/src/transform/instcombine.rs +++ b/compiler/rustc_mir_transform/src/instcombine.rs @@ -1,6 +1,6 @@ //! Performs various peephole optimizations. -use crate::transform::MirPass; +use crate::MirPass; use rustc_hir::Mutability; use rustc_middle::mir::{ BinOp, Body, Constant, LocalDecls, Operand, Place, ProjectionElem, Rvalue, SourceInfo, diff --git a/compiler/rustc_mir/src/transform/mod.rs b/compiler/rustc_mir_transform/src/lib.rs similarity index 90% rename from compiler/rustc_mir/src/transform/mod.rs rename to compiler/rustc_mir_transform/src/lib.rs index d4c2456e9a..9b11c8f0b2 100644 --- a/compiler/rustc_mir/src/transform/mod.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -1,5 +1,25 @@ -use crate::{shim, util}; +#![feature(box_patterns)] +#![feature(box_syntax)] +#![feature(crate_visibility_modifier)] +#![cfg_attr(bootstrap, feature(const_panic))] +#![feature(in_band_lifetimes)] +#![feature(iter_zip)] +#![feature(map_try_insert)] +#![feature(min_specialization)] +#![feature(option_get_or_insert_default)] +#![feature(once_cell)] +#![feature(never_type)] +#![feature(trusted_step)] +#![feature(try_blocks)] +#![recursion_limit = "256"] + +#[macro_use] +extern crate tracing; +#[macro_use] +extern crate rustc_middle; + use required_consts::RequiredConstsVisitor; +use rustc_const_eval::util; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::steal::Steal; use rustc_hir as hir; @@ -11,57 +31,60 @@ use rustc_middle::mir::{traversal, Body, ConstQualifs, MirPhase, Promoted}; use rustc_middle::ty::query::Providers; use rustc_middle::ty::{self, TyCtxt, TypeFoldable}; use rustc_span::{Span, Symbol}; -use std::borrow::Cow; -pub mod abort_unwinding_calls; -pub mod add_call_guards; -pub mod add_moves_for_packed_drops; -pub mod add_retag; -pub mod check_const_item_mutation; -pub mod check_consts; -pub mod check_packed_ref; +mod abort_unwinding_calls; +mod add_call_guards; +mod add_moves_for_packed_drops; +mod add_retag; +mod check_const_item_mutation; +mod check_packed_ref; pub mod check_unsafety; -pub mod cleanup_post_borrowck; -pub mod const_debuginfo; -pub mod const_goto; -pub mod const_prop; -pub mod coverage; -pub mod deaggregator; -pub mod deduplicate_blocks; -pub mod dest_prop; +mod cleanup_post_borrowck; +mod const_debuginfo; +mod const_goto; +mod const_prop; +mod coverage; +mod deaggregator; +mod deduplicate_blocks; +mod dest_prop; pub mod dump_mir; -pub mod early_otherwise_branch; -pub mod elaborate_drops; -pub mod function_item_references; -pub mod generator; -pub mod inline; -pub mod instcombine; -pub mod lower_intrinsics; -pub mod lower_slice_len; -pub mod match_branches; -pub mod multiple_return_terminators; -pub mod nrvo; -pub mod promote_consts; -pub mod remove_noop_landing_pads; -pub mod remove_storage_markers; -pub mod remove_unneeded_drops; -pub mod remove_zsts; -pub mod required_consts; -pub mod rustc_peek; -pub mod separate_const_switch; -pub mod simplify; -pub mod simplify_branches; -pub mod simplify_comparison_integral; -pub mod simplify_try; -pub mod uninhabited_enum_branching; -pub mod unreachable_prop; -pub mod validate; +mod early_otherwise_branch; +mod elaborate_drops; +mod function_item_references; +mod generator; +mod inline; +mod instcombine; +mod lower_intrinsics; +mod lower_slice_len; +mod match_branches; +mod multiple_return_terminators; +mod normalize_array_len; +mod nrvo; +mod remove_noop_landing_pads; +mod remove_storage_markers; +mod remove_unneeded_drops; +mod remove_zsts; +mod required_consts; +mod separate_const_switch; +mod shim; +mod simplify; +mod simplify_branches; +mod simplify_comparison_integral; +mod simplify_try; +mod uninhabited_enum_branching; +mod unreachable_prop; -pub use rustc_middle::mir::MirSource; +use rustc_const_eval::transform::check_consts; +use rustc_const_eval::transform::promote_consts; +use rustc_const_eval::transform::validate; +pub use rustc_const_eval::transform::MirPass; +use rustc_mir_dataflow::rustc_peek; -pub(crate) fn provide(providers: &mut Providers) { - self::check_unsafety::provide(providers); - self::check_packed_ref::provide(providers); +pub fn provide(providers: &mut Providers) { + check_unsafety::provide(providers); + check_packed_ref::provide(providers); + coverage::query::provide(providers); + shim::provide(providers); *providers = Providers { mir_keys, mir_const, @@ -83,6 +106,8 @@ pub(crate) fn provide(providers: &mut Providers) { optimized_mir, is_mir_available, is_ctfe_mir_available: |tcx, did| is_mir_available(tcx, did), + mir_callgraph_reachable: inline::cycle::mir_callgraph_reachable, + mir_inliner_callees: inline::cycle::mir_inliner_callees, promoted_mir: |tcx, def_id| { let def_id = def_id.expect_local(); if let Some(def) = ty::WithOptConstParam::try_lookup(def_id, tcx) { @@ -96,7 +121,6 @@ pub(crate) fn provide(providers: &mut Providers) { }, ..*providers }; - coverage::query::provide(providers); } fn is_mir_available(tcx: TyCtxt<'_>, def_id: DefId) -> bool { @@ -110,7 +134,7 @@ fn mir_keys(tcx: TyCtxt<'_>, (): ()) -> FxHashSet { let mut set = FxHashSet::default(); // All body-owners have MIR associated with them. - set.extend(tcx.body_owners()); + set.extend(tcx.hir().body_owners()); // Additionally, tuple struct/variant constructors have MIR, but // they don't have a BodyId, so we need to build them separately. @@ -137,32 +161,12 @@ fn mir_keys(tcx: TyCtxt<'_>, (): ()) -> FxHashSet { NestedVisitorMap::None } } - tcx.hir() - .krate() - .visit_all_item_likes(&mut GatherCtors { tcx, set: &mut set }.as_deep_visitor()); + tcx.hir().visit_all_item_likes(&mut GatherCtors { tcx, set: &mut set }.as_deep_visitor()); set } -/// Generates a default name for the pass based on the name of the -/// type `T`. -pub fn default_name() -> Cow<'static, str> { - let name = std::any::type_name::(); - if let Some(tail) = name.rfind(':') { Cow::from(&name[tail + 1..]) } else { Cow::from(name) } -} - -/// A streamlined trait that you can implement to create a pass; the -/// pass will be named after the type, and it will consist of a main -/// loop that goes over each available MIR and applies `run_pass`. -pub trait MirPass<'tcx> { - fn name(&self) -> Cow<'_, str> { - default_name::() - } - - fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>); -} - -pub fn run_passes( +fn run_passes( tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, mir_phase: MirPhase, @@ -269,7 +273,7 @@ fn mir_const<'tcx>( let mut body = tcx.mir_built(def).steal(); - util::dump_mir(tcx, None, "mir_map", &0, &body, |_, _| Ok(())); + rustc_middle::mir::dump_mir(tcx, None, "mir_map", &0, &body, |_, _| Ok(())); run_passes( tcx, @@ -301,7 +305,6 @@ fn mir_promoted( // this point, before we steal the mir-const result. // Also this means promotion can rely on all const checks having been done. let _ = tcx.mir_const_qualif_opt_const_arg(def); - let _ = tcx.mir_abstract_const_opt_const_arg(def.to_global()); let mut body = tcx.mir_const(def).steal(); let mut required_consts = Vec::new(); @@ -486,6 +489,7 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { // machine than on MIR with async primitives. let optimizations_with_generators: &[&dyn MirPass<'tcx>] = &[ &lower_slice_len::LowerSliceLenCalls, // has to be done before inlining, otherwise actual call will be almost always inlined. Also simple, so can just do first + &normalize_array_len::NormalizeArrayLen, // has to run after `slice::len` lowering &unreachable_prop::UnreachablePropagation, &uninhabited_enum_branching::UninhabitedEnumBranching, &simplify::SimplifyCfg::new("after-uninhabited-enum-branching"), diff --git a/compiler/rustc_mir/src/transform/lower_intrinsics.rs b/compiler/rustc_mir_transform/src/lower_intrinsics.rs similarity index 94% rename from compiler/rustc_mir/src/transform/lower_intrinsics.rs rename to compiler/rustc_mir_transform/src/lower_intrinsics.rs index e9f1d4f2ce..5848163af7 100644 --- a/compiler/rustc_mir/src/transform/lower_intrinsics.rs +++ b/compiler/rustc_mir_transform/src/lower_intrinsics.rs @@ -1,6 +1,6 @@ //! Lowers intrinsic calls -use crate::transform::MirPass; +use crate::MirPass; use rustc_middle::mir::*; use rustc_middle::ty::subst::SubstsRef; use rustc_middle::ty::{self, Ty, TyCtxt}; @@ -92,14 +92,19 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics { // since their semantics depend on the value of overflow-checks flag used // during codegen. Issue #35310. } - sym::size_of => { + sym::size_of | sym::min_align_of => { if let Some((destination, target)) = *destination { let tp_ty = substs.type_at(0); + let null_op = match intrinsic_name { + sym::size_of => NullOp::SizeOf, + sym::min_align_of => NullOp::AlignOf, + _ => bug!("unexpected intrinsic"), + }; block.statements.push(Statement { source_info: terminator.source_info, kind: StatementKind::Assign(Box::new(( destination, - Rvalue::NullaryOp(NullOp::SizeOf, tp_ty), + Rvalue::NullaryOp(null_op, tp_ty), ))), }); terminator.kind = TerminatorKind::Goto { target }; diff --git a/compiler/rustc_mir/src/transform/lower_slice_len.rs b/compiler/rustc_mir_transform/src/lower_slice_len.rs similarity index 92% rename from compiler/rustc_mir/src/transform/lower_slice_len.rs rename to compiler/rustc_mir_transform/src/lower_slice_len.rs index c3eb2d9f92..a2cce9f1ed 100644 --- a/compiler/rustc_mir/src/transform/lower_slice_len.rs +++ b/compiler/rustc_mir_transform/src/lower_slice_len.rs @@ -1,7 +1,7 @@ //! This pass lowers calls to core::slice::len to just Len op. //! It should run before inlining! -use crate::transform::MirPass; +use crate::MirPass; use rustc_hir::def_id::DefId; use rustc_index::vec::IndexVec; use rustc_middle::mir::*; @@ -75,13 +75,11 @@ fn lower_slice_len_call<'tcx>( let deref_arg = tcx.mk_place_deref(arg); let r_value = Rvalue::Len(deref_arg); let len_statement_kind = StatementKind::Assign(Box::new((*dest, r_value))); - let add_statement = Statement { - kind: len_statement_kind, - source_info: terminator.source_info.clone(), - }; + let add_statement = + Statement { kind: len_statement_kind, source_info: terminator.source_info }; // modify terminator into simple Goto - let new_terminator_kind = TerminatorKind::Goto { target: bb.clone() }; + let new_terminator_kind = TerminatorKind::Goto { target: *bb }; let patch = SliceLenPatchInformation { add_statement, new_terminator_kind }; diff --git a/compiler/rustc_mir/src/transform/match_branches.rs b/compiler/rustc_mir_transform/src/match_branches.rs similarity index 98% rename from compiler/rustc_mir/src/transform/match_branches.rs rename to compiler/rustc_mir_transform/src/match_branches.rs index 37a3fa50a5..c618abe9d0 100644 --- a/compiler/rustc_mir/src/transform/match_branches.rs +++ b/compiler/rustc_mir_transform/src/match_branches.rs @@ -1,4 +1,4 @@ -use crate::transform::MirPass; +use crate::MirPass; use rustc_middle::mir::*; use rustc_middle::ty::TyCtxt; use std::iter; @@ -134,7 +134,7 @@ impl<'tcx> MirPass<'tcx> for MatchBranchSimplification { let const_cmp = Operand::const_from_scalar( tcx, switch_ty, - crate::interpret::Scalar::from_uint(val, size), + rustc_const_eval::interpret::Scalar::from_uint(val, size), rustc_span::DUMMY_SP, ); let op = if f_b { BinOp::Eq } else { BinOp::Ne }; diff --git a/compiler/rustc_mir/src/transform/multiple_return_terminators.rs b/compiler/rustc_mir_transform/src/multiple_return_terminators.rs similarity index 96% rename from compiler/rustc_mir/src/transform/multiple_return_terminators.rs rename to compiler/rustc_mir_transform/src/multiple_return_terminators.rs index cd2db18055..b614917a88 100644 --- a/compiler/rustc_mir/src/transform/multiple_return_terminators.rs +++ b/compiler/rustc_mir_transform/src/multiple_return_terminators.rs @@ -1,7 +1,7 @@ //! This pass removes jumps to basic blocks containing only a return, and replaces them with a //! return instead. -use crate::transform::{simplify, MirPass}; +use crate::{simplify, MirPass}; use rustc_index::bit_set::BitSet; use rustc_middle::mir::*; use rustc_middle::ty::TyCtxt; diff --git a/compiler/rustc_mir_transform/src/normalize_array_len.rs b/compiler/rustc_mir_transform/src/normalize_array_len.rs new file mode 100644 index 0000000000..76f0e83c8c --- /dev/null +++ b/compiler/rustc_mir_transform/src/normalize_array_len.rs @@ -0,0 +1,286 @@ +//! This pass eliminates casting of arrays into slices when their length +//! is taken using `.len()` method. Handy to preserve information in MIR for const prop + +use crate::MirPass; +use rustc_data_structures::fx::FxIndexMap; +use rustc_index::bit_set::BitSet; +use rustc_index::vec::IndexVec; +use rustc_middle::mir::*; +use rustc_middle::ty::{self, TyCtxt}; + +const MAX_NUM_BLOCKS: usize = 800; +const MAX_NUM_LOCALS: usize = 3000; + +pub struct NormalizeArrayLen; + +impl<'tcx> MirPass<'tcx> for NormalizeArrayLen { + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { + if tcx.sess.mir_opt_level() < 4 { + return; + } + + // early returns for edge cases of highly unrolled functions + if body.basic_blocks().len() > MAX_NUM_BLOCKS { + return; + } + if body.local_decls().len() > MAX_NUM_LOCALS { + return; + } + normalize_array_len_calls(tcx, body) + } +} + +pub fn normalize_array_len_calls<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { + let (basic_blocks, local_decls) = body.basic_blocks_and_local_decls_mut(); + + // do a preliminary analysis to see if we ever have locals of type `[T;N]` or `&[T;N]` + let mut interesting_locals = BitSet::new_empty(local_decls.len()); + for (local, decl) in local_decls.iter_enumerated() { + match decl.ty.kind() { + ty::Array(..) => { + interesting_locals.insert(local); + } + ty::Ref(.., ty, Mutability::Not) => match ty.kind() { + ty::Array(..) => { + interesting_locals.insert(local); + } + _ => {} + }, + _ => {} + } + } + if interesting_locals.is_empty() { + // we have found nothing to analyze + return; + } + let num_intesting_locals = interesting_locals.count(); + let mut state = FxIndexMap::with_capacity_and_hasher(num_intesting_locals, Default::default()); + let mut patches_scratchpad = + FxIndexMap::with_capacity_and_hasher(num_intesting_locals, Default::default()); + let mut replacements_scratchpad = + FxIndexMap::with_capacity_and_hasher(num_intesting_locals, Default::default()); + for block in basic_blocks { + // make length calls for arrays [T; N] not to decay into length calls for &[T] + // that forbids constant propagation + normalize_array_len_call( + tcx, + block, + local_decls, + &interesting_locals, + &mut state, + &mut patches_scratchpad, + &mut replacements_scratchpad, + ); + state.clear(); + patches_scratchpad.clear(); + replacements_scratchpad.clear(); + } +} + +struct Patcher<'a, 'tcx> { + tcx: TyCtxt<'tcx>, + patches_scratchpad: &'a FxIndexMap, + replacements_scratchpad: &'a mut FxIndexMap, + local_decls: &'a mut IndexVec>, + statement_idx: usize, +} + +impl<'a, 'tcx> Patcher<'a, 'tcx> { + fn patch_expand_statement( + &mut self, + statement: &mut Statement<'tcx>, + ) -> Option>> { + let idx = self.statement_idx; + if let Some(len_statemnt_idx) = self.patches_scratchpad.get(&idx).copied() { + let mut statements = Vec::with_capacity(2); + + // we are at statement that performs a cast. The only sound way is + // to create another local that performs a similar copy without a cast and then + // use this copy in the Len operation + + match &statement.kind { + StatementKind::Assign(box ( + .., + Rvalue::Cast( + CastKind::Pointer(ty::adjustment::PointerCast::Unsize), + operand, + _, + ), + )) => { + match operand { + Operand::Copy(place) | Operand::Move(place) => { + // create new local + let ty = operand.ty(self.local_decls, self.tcx); + let local_decl = LocalDecl::with_source_info(ty, statement.source_info); + let local = self.local_decls.push(local_decl); + // make it live + let mut make_live_statement = statement.clone(); + make_live_statement.kind = StatementKind::StorageLive(local); + statements.push(make_live_statement); + // copy into it + + let operand = Operand::Copy(*place); + let mut make_copy_statement = statement.clone(); + let assign_to = Place::from(local); + let rvalue = Rvalue::Use(operand); + make_copy_statement.kind = + StatementKind::Assign(box (assign_to, rvalue)); + statements.push(make_copy_statement); + + // to reorder we have to copy and make NOP + statements.push(statement.clone()); + statement.make_nop(); + + self.replacements_scratchpad.insert(len_statemnt_idx, local); + } + _ => { + unreachable!("it's a bug in the implementation") + } + } + } + _ => { + unreachable!("it's a bug in the implementation") + } + } + + self.statement_idx += 1; + + Some(statements.into_iter()) + } else if let Some(local) = self.replacements_scratchpad.get(&idx).copied() { + let mut statements = Vec::with_capacity(2); + + match &statement.kind { + StatementKind::Assign(box (into, Rvalue::Len(place))) => { + let add_deref = if let Some(..) = place.as_local() { + false + } else if let Some(..) = place.local_or_deref_local() { + true + } else { + unreachable!("it's a bug in the implementation") + }; + // replace len statement + let mut len_statement = statement.clone(); + let mut place = Place::from(local); + if add_deref { + place = self.tcx.mk_place_deref(place); + } + len_statement.kind = StatementKind::Assign(box (*into, Rvalue::Len(place))); + statements.push(len_statement); + + // make temporary dead + let mut make_dead_statement = statement.clone(); + make_dead_statement.kind = StatementKind::StorageDead(local); + statements.push(make_dead_statement); + + // make original statement NOP + statement.make_nop(); + } + _ => { + unreachable!("it's a bug in the implementation") + } + } + + self.statement_idx += 1; + + Some(statements.into_iter()) + } else { + self.statement_idx += 1; + None + } + } +} + +fn normalize_array_len_call<'tcx>( + tcx: TyCtxt<'tcx>, + block: &mut BasicBlockData<'tcx>, + local_decls: &mut IndexVec>, + interesting_locals: &BitSet, + state: &mut FxIndexMap, + patches_scratchpad: &mut FxIndexMap, + replacements_scratchpad: &mut FxIndexMap, +) { + for (statement_idx, statement) in block.statements.iter_mut().enumerate() { + match &mut statement.kind { + StatementKind::Assign(box (place, rvalue)) => { + match rvalue { + Rvalue::Cast( + CastKind::Pointer(ty::adjustment::PointerCast::Unsize), + operand, + cast_ty, + ) => { + let local = if let Some(local) = place.as_local() { local } else { return }; + match operand { + Operand::Copy(place) | Operand::Move(place) => { + let operand_local = + if let Some(local) = place.local_or_deref_local() { + local + } else { + return; + }; + if !interesting_locals.contains(operand_local) { + return; + } + let operand_ty = local_decls[operand_local].ty; + match (operand_ty.kind(), cast_ty.kind()) { + (ty::Array(of_ty_src, ..), ty::Slice(of_ty_dst)) => { + if of_ty_src == of_ty_dst { + // this is a cast from [T; N] into [T], so we are good + state.insert(local, statement_idx); + } + } + // current way of patching doesn't allow to work with `mut` + ( + ty::Ref( + ty::RegionKind::ReErased, + operand_ty, + Mutability::Not, + ), + ty::Ref(ty::RegionKind::ReErased, cast_ty, Mutability::Not), + ) => { + match (operand_ty.kind(), cast_ty.kind()) { + // current way of patching doesn't allow to work with `mut` + (ty::Array(of_ty_src, ..), ty::Slice(of_ty_dst)) => { + if of_ty_src == of_ty_dst { + // this is a cast from [T; N] into [T], so we are good + state.insert(local, statement_idx); + } + } + _ => {} + } + } + _ => {} + } + } + _ => {} + } + } + Rvalue::Len(place) => { + let local = if let Some(local) = place.local_or_deref_local() { + local + } else { + return; + }; + if let Some(cast_statement_idx) = state.get(&local).copied() { + patches_scratchpad.insert(cast_statement_idx, statement_idx); + } + } + _ => { + // invalidate + state.remove(&place.local); + } + } + } + _ => {} + } + } + + let mut patcher = Patcher { + tcx, + patches_scratchpad: &*patches_scratchpad, + replacements_scratchpad, + local_decls, + statement_idx: 0, + }; + + block.expand_statements(|st| patcher.patch_expand_statement(st)); +} diff --git a/compiler/rustc_mir/src/transform/nrvo.rs b/compiler/rustc_mir_transform/src/nrvo.rs similarity index 99% rename from compiler/rustc_mir/src/transform/nrvo.rs rename to compiler/rustc_mir_transform/src/nrvo.rs index 445dc12909..3ac4e77cf9 100644 --- a/compiler/rustc_mir/src/transform/nrvo.rs +++ b/compiler/rustc_mir_transform/src/nrvo.rs @@ -6,7 +6,7 @@ use rustc_middle::mir::visit::{MutVisitor, NonUseContext, PlaceContext, Visitor} use rustc_middle::mir::{self, BasicBlock, Local, Location}; use rustc_middle::ty::TyCtxt; -use crate::transform::MirPass; +use crate::MirPass; /// This pass looks for MIR that always copies the same local into the return place and eliminates /// the copy by renaming all uses of that local to `_0`. diff --git a/compiler/rustc_mir/src/transform/remove_noop_landing_pads.rs b/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs similarity index 98% rename from compiler/rustc_mir/src/transform/remove_noop_landing_pads.rs rename to compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs index 5347846a4b..298bcd9dc2 100644 --- a/compiler/rustc_mir/src/transform/remove_noop_landing_pads.rs +++ b/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs @@ -1,6 +1,6 @@ -use crate::transform::MirPass; -use crate::util::patch::MirPatch; +use crate::MirPass; use rustc_index::bit_set::BitSet; +use rustc_middle::mir::patch::MirPatch; use rustc_middle::mir::*; use rustc_middle::ty::TyCtxt; use rustc_target::spec::PanicStrategy; diff --git a/compiler/rustc_mir/src/transform/remove_storage_markers.rs b/compiler/rustc_mir_transform/src/remove_storage_markers.rs similarity index 96% rename from compiler/rustc_mir/src/transform/remove_storage_markers.rs rename to compiler/rustc_mir_transform/src/remove_storage_markers.rs index 2d529feb07..0c7323cbac 100644 --- a/compiler/rustc_mir/src/transform/remove_storage_markers.rs +++ b/compiler/rustc_mir_transform/src/remove_storage_markers.rs @@ -1,6 +1,6 @@ //! This pass removes storage markers if they won't be emitted during codegen. -use crate::transform::MirPass; +use crate::MirPass; use rustc_middle::mir::*; use rustc_middle::ty::TyCtxt; diff --git a/compiler/rustc_mir/src/transform/remove_unneeded_drops.rs b/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs similarity index 97% rename from compiler/rustc_mir/src/transform/remove_unneeded_drops.rs rename to compiler/rustc_mir_transform/src/remove_unneeded_drops.rs index 02e45021a0..5c9d04a08b 100644 --- a/compiler/rustc_mir/src/transform/remove_unneeded_drops.rs +++ b/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs @@ -1,6 +1,6 @@ //! This pass replaces a drop of a type that does not need dropping, with a goto -use crate::transform::MirPass; +use crate::MirPass; use rustc_middle::mir::*; use rustc_middle::ty::TyCtxt; diff --git a/compiler/rustc_mir/src/transform/remove_zsts.rs b/compiler/rustc_mir_transform/src/remove_zsts.rs similarity index 98% rename from compiler/rustc_mir/src/transform/remove_zsts.rs rename to compiler/rustc_mir_transform/src/remove_zsts.rs index 5876ac22c6..d93ffa38c6 100644 --- a/compiler/rustc_mir/src/transform/remove_zsts.rs +++ b/compiler/rustc_mir_transform/src/remove_zsts.rs @@ -1,6 +1,6 @@ //! Removes assignments to ZST places. -use crate::transform::MirPass; +use crate::MirPass; use rustc_middle::mir::tcx::PlaceTy; use rustc_middle::mir::{Body, LocalDecls, Place, StatementKind}; use rustc_middle::ty::{self, Ty, TyCtxt}; diff --git a/compiler/rustc_mir/src/transform/required_consts.rs b/compiler/rustc_mir_transform/src/required_consts.rs similarity index 100% rename from compiler/rustc_mir/src/transform/required_consts.rs rename to compiler/rustc_mir_transform/src/required_consts.rs diff --git a/compiler/rustc_mir/src/transform/separate_const_switch.rs b/compiler/rustc_mir_transform/src/separate_const_switch.rs similarity index 99% rename from compiler/rustc_mir/src/transform/separate_const_switch.rs rename to compiler/rustc_mir_transform/src/separate_const_switch.rs index 87cd27984a..3002e7041b 100644 --- a/compiler/rustc_mir/src/transform/separate_const_switch.rs +++ b/compiler/rustc_mir_transform/src/separate_const_switch.rs @@ -37,7 +37,7 @@ //! simplicity rather than completeness (it notably //! sometimes duplicates abusively). -use crate::transform::MirPass; +use crate::MirPass; use rustc_middle::mir::*; use rustc_middle::ty::TyCtxt; use smallvec::SmallVec; @@ -204,6 +204,7 @@ fn is_likely_const<'tcx>(mut tracked_place: Place<'tcx>, block: &BasicBlockData< | Rvalue::AddressOf(_, _) | Rvalue::Cast(_, Operand::Constant(_), _) | Rvalue::NullaryOp(_, _) + | Rvalue::ShallowInitBox(_, _) | Rvalue::UnaryOp(_, Operand::Constant(_)) => return true, // These rvalues make things ambiguous @@ -301,6 +302,7 @@ fn find_determining_place<'tcx>( | Rvalue::ThreadLocalRef(_) | Rvalue::AddressOf(_, _) | Rvalue::NullaryOp(_, _) + | Rvalue::ShallowInitBox(_, _) | Rvalue::UnaryOp(_, Operand::Constant(_)) | Rvalue::Cast(_, Operand::Constant(_), _) => return None, diff --git a/compiler/rustc_mir/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs similarity index 99% rename from compiler/rustc_mir/src/shim.rs rename to compiler/rustc_mir_transform/src/shim.rs index 8083ec9544..f2ea5fedc6 100644 --- a/compiler/rustc_mir/src/shim.rs +++ b/compiler/rustc_mir_transform/src/shim.rs @@ -15,13 +15,13 @@ use rustc_target::spec::abi::Abi; use std::fmt; use std::iter; -use crate::transform::{ +use crate::util::expand_aggregate; +use crate::{ abort_unwinding_calls, add_call_guards, add_moves_for_packed_drops, remove_noop_landing_pads, run_passes, simplify, }; -use crate::util::elaborate_drops::{self, DropElaborator, DropFlagMode, DropStyle}; -use crate::util::expand_aggregate; -use crate::util::patch::MirPatch; +use rustc_middle::mir::patch::MirPatch; +use rustc_mir_dataflow::elaborate_drops::{self, DropElaborator, DropFlagMode, DropStyle}; pub fn provide(providers: &mut Providers) { providers.mir_shims = make_shim; @@ -53,7 +53,7 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> Body<' ty::InstanceDef::ReifyShim(def_id) => { build_call_shim(tcx, instance, None, CallKind::Direct(def_id)) } - ty::InstanceDef::ClosureOnceShim { call_once: _ } => { + ty::InstanceDef::ClosureOnceShim { call_once: _, track_caller: _ } => { let fn_mut = tcx.require_lang_item(LangItem::FnMut, None); let call_mut = tcx .associated_items(fn_mut) @@ -940,7 +940,7 @@ pub fn build_adt_ctor(tcx: TyCtxt<'_>, ctor_id: DefId) -> Body<'_> { span, ); - crate::util::dump_mir(tcx, None, "mir_map", &0, &body, |_, _| Ok(())); + rustc_middle::mir::dump_mir(tcx, None, "mir_map", &0, &body, |_, _| Ok(())); body } diff --git a/compiler/rustc_mir/src/transform/simplify.rs b/compiler/rustc_mir_transform/src/simplify.rs similarity index 95% rename from compiler/rustc_mir/src/transform/simplify.rs rename to compiler/rustc_mir_transform/src/simplify.rs index 3ecb5133e3..d6cd505cbb 100644 --- a/compiler/rustc_mir/src/transform/simplify.rs +++ b/compiler/rustc_mir_transform/src/simplify.rs @@ -27,7 +27,7 @@ //! naively generate still contains the `_a = ()` write in the unreachable block "after" the //! return. -use crate::transform::MirPass; +use crate::MirPass; use rustc_index::vec::{Idx, IndexVec}; use rustc_middle::mir::coverage::*; use rustc_middle::mir::visit::{MutVisitor, MutatingUseContext, PlaceContext, Visitor}; @@ -95,8 +95,6 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> { pub fn simplify(mut self) { self.strip_nops(); - let mut start = START_BLOCK; - // Vec of the blocks that should be merged. We store the indices here, instead of the // statements itself to avoid moving the (relatively) large statements twice. // We do not push the statements directly into the target block (`bb`) as that is slower @@ -105,8 +103,6 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> { loop { let mut changed = false; - self.collapse_goto_chain(&mut start, &mut changed); - for bb in self.basic_blocks.indices() { if self.pred_count[bb] == 0 { continue; @@ -149,27 +145,6 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> { break; } } - - if start != START_BLOCK { - debug_assert!(self.pred_count[START_BLOCK] == 0); - self.basic_blocks.swap(START_BLOCK, start); - self.pred_count.swap(START_BLOCK, start); - - // pred_count == 1 if the start block has no predecessor _blocks_. - if self.pred_count[START_BLOCK] > 1 { - for (bb, data) in self.basic_blocks.iter_enumerated_mut() { - if self.pred_count[bb] == 0 { - continue; - } - - for target in data.terminator_mut().successors_mut() { - if *target == start { - *target = START_BLOCK; - } - } - } - } - } } /// This function will return `None` if diff --git a/compiler/rustc_mir/src/transform/simplify_branches.rs b/compiler/rustc_mir_transform/src/simplify_branches.rs similarity index 98% rename from compiler/rustc_mir/src/transform/simplify_branches.rs rename to compiler/rustc_mir_transform/src/simplify_branches.rs index a9a45e61a3..df90cfa318 100644 --- a/compiler/rustc_mir/src/transform/simplify_branches.rs +++ b/compiler/rustc_mir_transform/src/simplify_branches.rs @@ -1,6 +1,6 @@ //! A pass that simplifies branches when their condition is known. -use crate::transform::MirPass; +use crate::MirPass; use rustc_middle::mir::*; use rustc_middle::ty::TyCtxt; diff --git a/compiler/rustc_mir/src/transform/simplify_comparison_integral.rs b/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs similarity index 100% rename from compiler/rustc_mir/src/transform/simplify_comparison_integral.rs rename to compiler/rustc_mir_transform/src/simplify_comparison_integral.rs diff --git a/compiler/rustc_mir/src/transform/simplify_try.rs b/compiler/rustc_mir_transform/src/simplify_try.rs similarity index 99% rename from compiler/rustc_mir/src/transform/simplify_try.rs rename to compiler/rustc_mir_transform/src/simplify_try.rs index 9c3055c679..e436d73226 100644 --- a/compiler/rustc_mir/src/transform/simplify_try.rs +++ b/compiler/rustc_mir_transform/src/simplify_try.rs @@ -9,7 +9,7 @@ //! //! into just `x`. -use crate::transform::{simplify, MirPass}; +use crate::{simplify, MirPass}; use itertools::Itertools as _; use rustc_index::{bit_set::BitSet, vec::IndexVec}; use rustc_middle::mir::visit::{NonUseContext, PlaceContext, Visitor}; diff --git a/compiler/rustc_mir/src/transform/uninhabited_enum_branching.rs b/compiler/rustc_mir_transform/src/uninhabited_enum_branching.rs similarity index 99% rename from compiler/rustc_mir/src/transform/uninhabited_enum_branching.rs rename to compiler/rustc_mir_transform/src/uninhabited_enum_branching.rs index 5c6c158d46..5cef64d778 100644 --- a/compiler/rustc_mir/src/transform/uninhabited_enum_branching.rs +++ b/compiler/rustc_mir_transform/src/uninhabited_enum_branching.rs @@ -1,6 +1,6 @@ //! A pass that eliminates branches on uninhabited enum variants. -use crate::transform::MirPass; +use crate::MirPass; use rustc_data_structures::stable_set::FxHashSet; use rustc_middle::mir::{ BasicBlock, BasicBlockData, Body, Local, Operand, Rvalue, StatementKind, SwitchTargets, diff --git a/compiler/rustc_mir/src/transform/unreachable_prop.rs b/compiler/rustc_mir_transform/src/unreachable_prop.rs similarity index 98% rename from compiler/rustc_mir/src/transform/unreachable_prop.rs rename to compiler/rustc_mir_transform/src/unreachable_prop.rs index e7fb6b4f6b..baf381081d 100644 --- a/compiler/rustc_mir/src/transform/unreachable_prop.rs +++ b/compiler/rustc_mir_transform/src/unreachable_prop.rs @@ -2,8 +2,8 @@ //! when all of their successors are unreachable. This is achieved through a //! post-order traversal of the blocks. -use crate::transform::simplify; -use crate::transform::MirPass; +use crate::simplify; +use crate::MirPass; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_middle::mir::*; use rustc_middle::ty::TyCtxt; diff --git a/compiler/rustc_monomorphize/Cargo.toml b/compiler/rustc_monomorphize/Cargo.toml new file mode 100644 index 0000000000..f812afe6b6 --- /dev/null +++ b/compiler/rustc_monomorphize/Cargo.toml @@ -0,0 +1,19 @@ +[package] +name = "rustc_monomorphize" +version = "0.0.0" +edition = "2021" + +[lib] +doctest = false + +[dependencies] +smallvec = { version = "1.6.1", features = ["union", "may_dangle"] } +tracing = "0.1" +rustc_data_structures = { path = "../rustc_data_structures" } +rustc_errors = { path = "../rustc_errors" } +rustc_hir = { path = "../rustc_hir" } +rustc_index = { path = "../rustc_index" } +rustc_middle = { path = "../rustc_middle" } +rustc_session = { path = "../rustc_session" } +rustc_span = { path = "../rustc_span" } +rustc_target = { path = "../rustc_target" } diff --git a/compiler/rustc_mir/src/monomorphize/collector.rs b/compiler/rustc_monomorphize/src/collector.rs similarity index 98% rename from compiler/rustc_mir/src/monomorphize/collector.rs rename to compiler/rustc_monomorphize/src/collector.rs index 4cb362238c..5147408210 100644 --- a/compiler/rustc_mir/src/monomorphize/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -178,8 +178,6 @@ //! this is not implemented however: a mono item will be produced //! regardless of whether it is actually needed or not. -use crate::monomorphize; - use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::sync::{par_iter, MTLock, MTRef, ParallelIterator}; use rustc_errors::{ErrorReported, FatalError}; @@ -332,7 +330,7 @@ fn collect_roots(tcx: TyCtxt<'_>, mode: MonoItemCollectionMode) -> Vec( // involving a dependency, and the lack of context is confusing) in this MVP, we focus on // diagnostics on edges crossing a crate boundary: the collected mono items which are not // defined in the local crate. - if tcx.sess.diagnostic().err_count() > error_count && starting_point.node.krate() != LOCAL_CRATE + if tcx.sess.diagnostic().err_count() > error_count + && starting_point.node.krate() != LOCAL_CRATE + && starting_point.node.is_user_defined() { let formatted_item = with_no_trimmed_paths(|| starting_point.node.to_string()); tcx.sess.span_note_without_error( @@ -936,21 +936,13 @@ fn visit_instance_use<'tcx>( } } -// Returns `true` if we should codegen an instance in the local crate. -// Returns `false` if we can just link to the upstream crate and therefore don't -// need a mono item. +/// Returns `true` if we should codegen an instance in the local crate, or returns `false` if we +/// can just link to the upstream crate and therefore don't need a mono item. fn should_codegen_locally<'tcx>(tcx: TyCtxt<'tcx>, instance: &Instance<'tcx>) -> bool { - let def_id = match instance.def { - ty::InstanceDef::Item(def) => def.did, - ty::InstanceDef::DropGlue(def_id, Some(_)) => def_id, - ty::InstanceDef::VtableShim(..) - | ty::InstanceDef::ReifyShim(..) - | ty::InstanceDef::ClosureOnceShim { .. } - | ty::InstanceDef::Virtual(..) - | ty::InstanceDef::FnPtrShim(..) - | ty::InstanceDef::DropGlue(..) - | ty::InstanceDef::Intrinsic(_) - | ty::InstanceDef::CloneShim(..) => return true, + let def_id = if let Some(def_id) = instance.def.def_id_if_not_guaranteed_local_codegen() { + def_id + } else { + return true; }; if tcx.is_foreign_item(def_id) { @@ -1052,7 +1044,7 @@ fn find_vtable_types_for_unsizing<'tcx>( assert_eq!(source_adt_def, target_adt_def); let CustomCoerceUnsized::Struct(coerce_index) = - monomorphize::custom_coerce_unsize_info(tcx, source_ty, target_ty); + crate::custom_coerce_unsize_info(tcx, source_ty, target_ty); let source_fields = &source_adt_def.non_enum_variant().fields; let target_fields = &target_adt_def.non_enum_variant().fields; @@ -1085,7 +1077,7 @@ fn create_fn_mono_item<'tcx>( let def_id = instance.def_id(); if tcx.sess.opts.debugging_opts.profile_closures && def_id.is_local() && tcx.is_closure(def_id) { - monomorphize::util::dump_closure_profile(tcx, instance); + crate::util::dump_closure_profile(tcx, instance); } respan(source, MonoItem::Fn(instance.polymorphize(tcx))) diff --git a/compiler/rustc_mir/src/monomorphize/mod.rs b/compiler/rustc_monomorphize/src/lib.rs similarity index 65% rename from compiler/rustc_mir/src/monomorphize/mod.rs rename to compiler/rustc_monomorphize/src/lib.rs index 57d2723cf9..08b1d7b7fa 100644 --- a/compiler/rustc_mir/src/monomorphize/mod.rs +++ b/compiler/rustc_monomorphize/src/lib.rs @@ -1,13 +1,25 @@ -use rustc_middle::traits; -use rustc_middle::ty::adjustment::CustomCoerceUnsized; -use rustc_middle::ty::{self, Ty, TyCtxt}; +#![feature(array_windows)] +#![feature(bool_to_option)] +#![feature(crate_visibility_modifier)] +#![feature(control_flow_enum)] +#![feature(in_band_lifetimes)] +#![recursion_limit = "256"] + +#[macro_use] +extern crate tracing; +#[macro_use] +extern crate rustc_middle; use rustc_hir::lang_items::LangItem; +use rustc_middle::traits; +use rustc_middle::ty::adjustment::CustomCoerceUnsized; +use rustc_middle::ty::query::Providers; +use rustc_middle::ty::{self, Ty, TyCtxt}; -pub mod collector; -pub mod partitioning; -pub mod polymorphize; -pub mod util; +mod collector; +mod partitioning; +mod polymorphize; +mod util; fn custom_coerce_unsize_info<'tcx>( tcx: TyCtxt<'tcx>, @@ -31,3 +43,8 @@ fn custom_coerce_unsize_info<'tcx>( } } } + +pub fn provide(providers: &mut Providers) { + partitioning::provide(providers); + polymorphize::provide(providers); +} diff --git a/compiler/rustc_mir/src/monomorphize/partitioning/default.rs b/compiler/rustc_monomorphize/src/partitioning/default.rs similarity index 95% rename from compiler/rustc_mir/src/monomorphize/partitioning/default.rs rename to compiler/rustc_monomorphize/src/partitioning/default.rs index a559a6ce41..be68208225 100644 --- a/compiler/rustc_mir/src/monomorphize/partitioning/default.rs +++ b/compiler/rustc_monomorphize/src/partitioning/default.rs @@ -9,13 +9,13 @@ use rustc_middle::middle::exported_symbols::SymbolExportLevel; use rustc_middle::mir::mono::{CodegenUnit, CodegenUnitNameBuilder, Linkage, Visibility}; use rustc_middle::mir::mono::{InstantiationMode, MonoItem}; use rustc_middle::ty::print::characteristic_def_id_of_type; -use rustc_middle::ty::{self, DefIdTree, InstanceDef, TyCtxt}; +use rustc_middle::ty::{self, fold::TypeFoldable, DefIdTree, InstanceDef, TyCtxt}; use rustc_span::symbol::Symbol; use super::PartitioningCx; -use crate::monomorphize::collector::InliningMap; -use crate::monomorphize::partitioning::merging; -use crate::monomorphize::partitioning::{ +use crate::collector::InliningMap; +use crate::partitioning::merging; +use crate::partitioning::{ MonoItemPlacement, Partitioner, PostInliningPartitioning, PreInliningPartitioning, }; @@ -300,14 +300,21 @@ fn characteristic_def_id_of_mono_item<'tcx>( // call it. return None; } - // This is a method within an impl, find out what the self-type is: - let impl_self_ty = tcx.subst_and_normalize_erasing_regions( - instance.substs, - ty::ParamEnv::reveal_all(), - tcx.type_of(impl_def_id), - ); - if let Some(def_id) = characteristic_def_id_of_type(impl_self_ty) { - return Some(def_id); + + // When polymorphization is enabled, methods which do not depend on their generic + // parameters, but the self-type of their impl block do will fail to normalize. + if !tcx.sess.opts.debugging_opts.polymorphize + || !instance.definitely_needs_subst(tcx) + { + // This is a method within an impl, find out what the self-type is: + let impl_self_ty = tcx.subst_and_normalize_erasing_regions( + instance.substs, + ty::ParamEnv::reveal_all(), + tcx.type_of(impl_def_id), + ); + if let Some(def_id) = characteristic_def_id_of_type(impl_self_ty) { + return Some(def_id); + } } } diff --git a/compiler/rustc_mir/src/monomorphize/partitioning/merging.rs b/compiler/rustc_monomorphize/src/partitioning/merging.rs similarity index 98% rename from compiler/rustc_mir/src/monomorphize/partitioning/merging.rs rename to compiler/rustc_monomorphize/src/partitioning/merging.rs index cbe3666579..229468b47f 100644 --- a/compiler/rustc_mir/src/monomorphize/partitioning/merging.rs +++ b/compiler/rustc_monomorphize/src/partitioning/merging.rs @@ -6,7 +6,7 @@ use rustc_middle::mir::mono::{CodegenUnit, CodegenUnitNameBuilder}; use rustc_span::symbol::{Symbol, SymbolStr}; use super::PartitioningCx; -use crate::monomorphize::partitioning::PreInliningPartitioning; +use crate::partitioning::PreInliningPartitioning; pub fn merge_codegen_units<'tcx>( cx: &PartitioningCx<'_, 'tcx>, diff --git a/compiler/rustc_mir/src/monomorphize/partitioning/mod.rs b/compiler/rustc_monomorphize/src/partitioning/mod.rs similarity index 99% rename from compiler/rustc_mir/src/monomorphize/partitioning/mod.rs rename to compiler/rustc_monomorphize/src/partitioning/mod.rs index 6ed0ab8be4..7a7a56a034 100644 --- a/compiler/rustc_mir/src/monomorphize/partitioning/mod.rs +++ b/compiler/rustc_monomorphize/src/partitioning/mod.rs @@ -105,8 +105,8 @@ use rustc_middle::ty::query::Providers; use rustc_middle::ty::TyCtxt; use rustc_span::symbol::Symbol; -use crate::monomorphize::collector::InliningMap; -use crate::monomorphize::collector::{self, MonoItemCollectionMode}; +use crate::collector::InliningMap; +use crate::collector::{self, MonoItemCollectionMode}; pub struct PartitioningCx<'a, 'tcx> { tcx: TyCtxt<'tcx>, diff --git a/compiler/rustc_mir/src/monomorphize/polymorphize.rs b/compiler/rustc_monomorphize/src/polymorphize.rs similarity index 82% rename from compiler/rustc_mir/src/monomorphize/polymorphize.rs rename to compiler/rustc_monomorphize/src/polymorphize.rs index 3c55a4b0a8..e6e4438b6d 100644 --- a/compiler/rustc_mir/src/monomorphize/polymorphize.rs +++ b/compiler/rustc_monomorphize/src/polymorphize.rs @@ -27,20 +27,23 @@ pub fn provide(providers: &mut Providers) { providers.unused_generic_params = unused_generic_params; } -/// Determine which generic parameters are used by the function/method/closure represented by -/// `def_id`. Returns a bitset where bits representing unused parameters are set (`is_empty` -/// indicates all parameters are used). -#[instrument(skip(tcx))] -fn unused_generic_params(tcx: TyCtxt<'_>, def_id: DefId) -> FiniteBitSet { +/// Determine which generic parameters are used by the instance. +/// +/// Returns a bitset where bits representing unused parameters are set (`is_empty` indicates all +/// parameters are used). +#[instrument(level = "debug", skip(tcx))] +fn unused_generic_params<'tcx>( + tcx: TyCtxt<'tcx>, + instance: ty::InstanceDef<'tcx>, +) -> FiniteBitSet { if !tcx.sess.opts.debugging_opts.polymorphize { // If polymorphization disabled, then all parameters are used. return FiniteBitSet::new_empty(); } - // Polymorphization results are stored in cross-crate metadata only when there are unused - // parameters, so assume that non-local items must have only used parameters (else this query - // would not be invoked, and the cross-crate metadata used instead). - if !def_id.is_local() { + let def_id = instance.def_id(); + // Exit early if this instance should not be polymorphized. + if !should_polymorphize(tcx, def_id, instance) { return FiniteBitSet::new_empty(); } @@ -52,41 +55,25 @@ fn unused_generic_params(tcx: TyCtxt<'_>, def_id: DefId) -> FiniteBitSet { return FiniteBitSet::new_empty(); } - // Exit early when there is no MIR available. - let context = tcx.hir().body_const_context(def_id.expect_local()); - match context { - Some(ConstContext::ConstFn) | None if !tcx.is_mir_available(def_id) => { - debug!("no mir available"); - return FiniteBitSet::new_empty(); - } - Some(_) if !tcx.is_ctfe_mir_available(def_id) => { - debug!("no ctfe mir available"); - return FiniteBitSet::new_empty(); - } - _ => {} - } - // Create a bitset with N rightmost ones for each parameter. let generics_count: u32 = generics.count().try_into().expect("more generic parameters than can fit into a `u32`"); let mut unused_parameters = FiniteBitSet::::new_empty(); unused_parameters.set_range(0..generics_count); debug!(?unused_parameters, "(start)"); + mark_used_by_default_parameters(tcx, def_id, generics, &mut unused_parameters); debug!(?unused_parameters, "(after default)"); // Visit MIR and accumululate used generic parameters. - let body = match context { + let body = match tcx.hir().body_const_context(def_id.expect_local()) { // Const functions are actually called and should thus be considered for polymorphization - // via their runtime MIR + // via their runtime MIR. Some(ConstContext::ConstFn) | None => tcx.optimized_mir(def_id), Some(_) => tcx.mir_for_ctfe(def_id), }; let mut vis = MarkUsedGenericParams { tcx, def_id, unused_parameters: &mut unused_parameters }; vis.visit_body(body); - debug!(?unused_parameters, "(after visitor)"); - - mark_used_by_predicates(tcx, def_id, &mut unused_parameters); debug!(?unused_parameters, "(end)"); // Emit errors for debugging and testing if enabled. @@ -97,10 +84,53 @@ fn unused_generic_params(tcx: TyCtxt<'_>, def_id: DefId) -> FiniteBitSet { unused_parameters } +/// Returns `true` if the instance should be polymorphized. +fn should_polymorphize<'tcx>( + tcx: TyCtxt<'tcx>, + def_id: DefId, + instance: ty::InstanceDef<'tcx>, +) -> bool { + // If an instance's MIR body is not polymorphic then the modified substitutions that are + // derived from polymorphization's result won't make any difference. + if !instance.has_polymorphic_mir_body() { + return false; + } + + // Don't polymorphize intrinsics or virtual calls - calling `instance_mir` will panic. + if matches!(instance, ty::InstanceDef::Intrinsic(..) | ty::InstanceDef::Virtual(..)) { + return false; + } + + // Polymorphization results are stored in cross-crate metadata only when there are unused + // parameters, so assume that non-local items must have only used parameters (else this query + // would not be invoked, and the cross-crate metadata used instead). + if !def_id.is_local() { + return false; + } + + // Foreign items have no bodies to analyze. + if tcx.is_foreign_item(def_id) { + return false; + } + + // Make sure there is MIR available. + match tcx.hir().body_const_context(def_id.expect_local()) { + Some(ConstContext::ConstFn) | None if !tcx.is_mir_available(def_id) => { + debug!("no mir available"); + return false; + } + Some(_) if !tcx.is_ctfe_mir_available(def_id) => { + debug!("no ctfe mir available"); + return false; + } + _ => true, + } +} + /// Some parameters are considered used-by-default, such as non-generic parameters and the dummy /// generic parameters from closures, this function marks them as used. `leaf_is_closure` should /// be `true` if the item that `unused_generic_params` was invoked on is a closure. -#[instrument(skip(tcx, def_id, generics, unused_parameters))] +#[instrument(level = "debug", skip(tcx, def_id, generics, unused_parameters))] fn mark_used_by_default_parameters<'tcx>( tcx: TyCtxt<'tcx>, def_id: DefId, @@ -156,47 +186,9 @@ fn mark_used_by_default_parameters<'tcx>( } } -/// Search the predicates on used generic parameters for any unused generic parameters, and mark -/// those as used. -#[instrument(skip(tcx, def_id))] -fn mark_used_by_predicates<'tcx>( - tcx: TyCtxt<'tcx>, - def_id: DefId, - unused_parameters: &mut FiniteBitSet, -) { - let def_id = tcx.closure_base_def_id(def_id); - let predicates = tcx.explicit_predicates_of(def_id); - - let mut current_unused_parameters = FiniteBitSet::new_empty(); - // Run to a fixed point to support `where T: Trait, U: Trait`, starting with an empty - // bit set so that this is skipped if all parameters are already used. - while current_unused_parameters != *unused_parameters { - debug!(?current_unused_parameters, ?unused_parameters); - current_unused_parameters = *unused_parameters; - - for (predicate, _) in predicates.predicates { - // Consider all generic params in a predicate as used if any other parameter in the - // predicate is used. - let any_param_used = { - let mut vis = HasUsedGenericParams { tcx, unused_parameters }; - predicate.visit_with(&mut vis).is_break() - }; - - if any_param_used { - let mut vis = MarkUsedGenericParams { tcx, def_id, unused_parameters }; - predicate.visit_with(&mut vis); - } - } - } - - if let Some(parent) = predicates.parent { - mark_used_by_predicates(tcx, parent, unused_parameters); - } -} - /// Emit errors for the function annotated by `#[rustc_polymorphize_error]`, labelling each generic /// parameter which was unused. -#[instrument(skip(tcx, generics))] +#[instrument(level = "debug", skip(tcx, generics))] fn emit_unused_generic_params_error<'tcx>( tcx: TyCtxt<'tcx>, def_id: DefId, @@ -241,9 +233,10 @@ struct MarkUsedGenericParams<'a, 'tcx> { impl<'a, 'tcx> MarkUsedGenericParams<'a, 'tcx> { /// Invoke `unused_generic_params` on a body contained within the current item (e.g. /// a closure, generator or constant). - #[instrument(skip(self, def_id, substs))] + #[instrument(level = "debug", skip(self, def_id, substs))] fn visit_child_body(&mut self, def_id: DefId, substs: SubstsRef<'tcx>) { - let unused = self.tcx.unused_generic_params(def_id); + let instance = ty::InstanceDef::Item(ty::WithOptConstParam::unknown(def_id)); + let unused = self.tcx.unused_generic_params(instance); debug!(?self.unused_parameters, ?unused); for (i, arg) in substs.iter().enumerate() { let i = i.try_into().unwrap(); @@ -256,7 +249,7 @@ impl<'a, 'tcx> MarkUsedGenericParams<'a, 'tcx> { } impl<'a, 'tcx> Visitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> { - #[instrument(skip(self, local))] + #[instrument(level = "debug", skip(self, local))] fn visit_local_decl(&mut self, local: Local, local_decl: &LocalDecl<'tcx>) { if local == Local::from_usize(1) { let def_kind = self.tcx.def_kind(self.def_id); @@ -286,7 +279,7 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> { fn tcx_for_anon_const_substs(&self) -> Option> { Some(self.tcx) } - #[instrument(skip(self))] + #[instrument(level = "debug", skip(self))] fn visit_const(&mut self, c: &'tcx Const<'tcx>) -> ControlFlow { if !c.potentially_has_param_types_or_consts() { return ControlFlow::CONTINUE; @@ -319,7 +312,7 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> { } } - #[instrument(skip(self))] + #[instrument(level = "debug", skip(self))] fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow { if !ty.potentially_has_param_types_or_consts() { return ControlFlow::CONTINUE; @@ -361,7 +354,7 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for HasUsedGenericParams<'a, 'tcx> { Some(self.tcx) } - #[instrument(skip(self))] + #[instrument(level = "debug", skip(self))] fn visit_const(&mut self, c: &'tcx Const<'tcx>) -> ControlFlow { if !c.potentially_has_param_types_or_consts() { return ControlFlow::CONTINUE; @@ -379,7 +372,7 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for HasUsedGenericParams<'a, 'tcx> { } } - #[instrument(skip(self))] + #[instrument(level = "debug", skip(self))] fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow { if !ty.potentially_has_param_types_or_consts() { return ControlFlow::CONTINUE; diff --git a/compiler/rustc_mir/src/monomorphize/util.rs b/compiler/rustc_monomorphize/src/util.rs similarity index 100% rename from compiler/rustc_mir/src/monomorphize/util.rs rename to compiler/rustc_monomorphize/src/util.rs diff --git a/compiler/rustc_parse/Cargo.toml b/compiler/rustc_parse/Cargo.toml index 1ca1a92252..a823607ab0 100644 --- a/compiler/rustc_parse/Cargo.toml +++ b/compiler/rustc_parse/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustc_parse" version = "0.0.0" -edition = "2018" +edition = "2021" [lib] doctest = false @@ -18,3 +18,4 @@ rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } rustc_ast = { path = "../rustc_ast" } unicode-normalization = "0.1.11" +unicode-width = "0.1.4" diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs index 1e65cc2715..8e90f73b44 100644 --- a/compiler/rustc_parse/src/lexer/mod.rs +++ b/compiler/rustc_parse/src/lexer/mod.rs @@ -4,7 +4,9 @@ use rustc_ast::tokenstream::{Spacing, TokenStream}; use rustc_errors::{error_code, Applicability, DiagnosticBuilder, FatalError, PResult}; use rustc_lexer::unescape::{self, Mode}; use rustc_lexer::{Base, DocStyle, RawStrError}; -use rustc_session::lint::builtin::RUST_2021_PREFIXES_INCOMPATIBLE_SYNTAX; +use rustc_session::lint::builtin::{ + TEXT_DIRECTION_CODEPOINT_IN_COMMENT, RUST_2021_PREFIXES_INCOMPATIBLE_SYNTAX, +}; use rustc_session::lint::BuiltinLintDiagnostics; use rustc_session::parse::ParseSess; use rustc_span::symbol::{sym, Symbol}; @@ -129,6 +131,28 @@ impl<'a> StringReader<'a> { .struct_span_fatal(self.mk_sp(from_pos, to_pos), &format!("{}: {}", m, escaped_char(c))) } + /// Detect usages of Unicode codepoints changing the direction of the text on screen and loudly + /// complain about it. + fn lint_unicode_text_flow(&self, start: BytePos) { + // 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) { + self.sess.buffer_lint_with_diagnostic( + &TEXT_DIRECTION_CODEPOINT_IN_COMMENT, + span, + ast::CRATE_NODE_ID, + "unicode codepoint changing visible direction of text present in comment", + BuiltinLintDiagnostics::UnicodeTextFlow(span, content.to_string()), + ); + } + } + /// Turns simple `rustc_lexer::TokenKind` enum into a rich /// `rustc_ast::TokenKind`. This turns strings into interned /// symbols and runs additional validation. @@ -136,7 +160,12 @@ impl<'a> StringReader<'a> { Some(match token { rustc_lexer::TokenKind::LineComment { doc_style } => { // Skip non-doc comments - let doc_style = doc_style?; + let doc_style = if let Some(doc_style) = doc_style { + doc_style + } else { + self.lint_unicode_text_flow(start); + return None; + }; // Opening delimiter of the length 3 is not included into the symbol. let content_start = start + BytePos(3); @@ -158,7 +187,12 @@ impl<'a> StringReader<'a> { } // Skip non-doc comments - let doc_style = doc_style?; + let doc_style = if let Some(doc_style) = doc_style { + doc_style + } else { + self.lint_unicode_text_flow(start); + return None; + }; // Opening delimiter of the length 3 and closing delimiter of the length 2 // are not included into the symbol. diff --git a/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs b/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs index aa6b424ce2..569f186a72 100644 --- a/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs +++ b/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs @@ -3,7 +3,7 @@ use std::iter::once; use std::ops::Range; -use rustc_errors::{Applicability, Handler}; +use rustc_errors::{pluralize, Applicability, Handler}; use rustc_lexer::unescape::{EscapeError, Mode}; use rustc_span::{BytePos, Span}; @@ -49,24 +49,57 @@ pub(crate) fn emit_unescape_error( .emit(); } EscapeError::MoreThanOneChar => { - let (prefix, msg) = if mode.is_bytes() { - ("b", "if you meant to write a byte string literal, use double quotes") - } else { - ("", "if you meant to write a `str` literal, use double quotes") - }; + use unicode_normalization::{char::is_combining_mark, UnicodeNormalization}; - handler - .struct_span_err( - span_with_quotes, - "character literal may only contain one codepoint", - ) - .span_suggestion( + let mut has_help = false; + let mut handler = handler.struct_span_err( + span_with_quotes, + "character literal may only contain one codepoint", + ); + + if lit.chars().skip(1).all(|c| is_combining_mark(c)) { + let escaped_marks = + lit.chars().skip(1).map(|c| c.escape_default().to_string()).collect::>(); + handler.span_note( + span, + &format!( + "this `{}` is followed by the combining mark{} `{}`", + lit.chars().next().unwrap(), + pluralize!(escaped_marks.len()), + escaped_marks.join(""), + ), + ); + let normalized = lit.nfc().to_string(); + if normalized.chars().count() == 1 { + has_help = true; + handler.span_suggestion( + span, + &format!( + "consider using the normalized form `{}` of this character", + normalized.chars().next().unwrap().escape_default() + ), + normalized, + Applicability::MachineApplicable, + ); + } + } + + if !has_help { + let (prefix, msg) = if mode.is_bytes() { + ("b", "if you meant to write a byte string literal, use double quotes") + } else { + ("", "if you meant to write a `str` literal, use double quotes") + }; + + handler.span_suggestion( span_with_quotes, msg, format!("{}\"{}\"", prefix, lit), Applicability::MachineApplicable, - ) - .emit(); + ); + } + + handler.emit(); } EscapeError::EscapeOnlyChar => { let (c, char_span) = last_char(); @@ -154,12 +187,17 @@ pub(crate) fn emit_unescape_error( assert!(mode.is_bytes()); let (c, span) = last_char(); let mut err = handler.struct_span_err(span, "non-ASCII character in byte constant"); - err.span_label(span, "byte constant must be ASCII"); + let postfix = if unicode_width::UnicodeWidthChar::width(c).unwrap_or(1) == 0 { + format!(" but is {:?}", c) + } else { + String::new() + }; + err.span_label(span, &format!("byte constant must be ASCII{}", postfix)); if (c as u32) <= 0xFF { err.span_suggestion( span, &format!( - "if you meant to use the unicode code point for '{}', use a \\xHH escape", + "if you meant to use the unicode code point for {:?}, use a \\xHH escape", c ), format!("\\x{:X}", c as u32), @@ -173,7 +211,7 @@ pub(crate) fn emit_unescape_error( err.span_suggestion( span, &format!( - "if you meant to use the UTF-8 encoding of '{}', use \\xHH escapes", + "if you meant to use the UTF-8 encoding of {:?}, use \\xHH escapes", c ), utf8.as_bytes() @@ -187,10 +225,15 @@ pub(crate) fn emit_unescape_error( } EscapeError::NonAsciiCharInByteString => { assert!(mode.is_bytes()); - let (_c, span) = last_char(); + let (c, span) = last_char(); + let postfix = if unicode_width::UnicodeWidthChar::width(c).unwrap_or(1) == 0 { + format!(" but is {:?}", c) + } else { + String::new() + }; handler .struct_span_err(span, "raw byte string must be ASCII") - .span_label(span, "must be ASCII") + .span_label(span, &format!("must be ASCII{}", postfix)) .emit(); } EscapeError::OutOfRangeHexEscape => { diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs index bf76dedd25..a40f47f895 100644 --- a/compiler/rustc_parse/src/lib.rs +++ b/compiler/rustc_parse/src/lib.rs @@ -3,11 +3,12 @@ #![feature(array_windows)] #![feature(crate_visibility_modifier)] #![feature(if_let_guard)] -#![cfg_attr(bootstrap, feature(bindings_after_at))] #![feature(box_patterns)] -#![cfg_attr(bootstrap, allow(incomplete_features))] // if_let_guard #![recursion_limit = "256"] +#[macro_use] +extern crate tracing; + use rustc_ast as ast; use rustc_ast::token::{self, Nonterminal, Token, TokenKind}; use rustc_ast::tokenstream::{self, AttributesData, CanSynthesizeMissingTokens, LazyTokenStream}; @@ -133,7 +134,7 @@ fn maybe_source_file_to_parser( let mut parser = stream_to_parser(sess, stream, None); parser.unclosed_delims = unclosed_delims; if parser.token == token::Eof { - parser.token.span = Span::new(end_pos, end_pos, parser.token.span.ctxt()); + parser.token.span = Span::new(end_pos, end_pos, parser.token.span.ctxt(), None); } Ok(parser) diff --git a/compiler/rustc_parse/src/parser/attr.rs b/compiler/rustc_parse/src/parser/attr.rs index e9f0038b2d..b402b8ba53 100644 --- a/compiler/rustc_parse/src/parser/attr.rs +++ b/compiler/rustc_parse/src/parser/attr.rs @@ -1,10 +1,10 @@ -use super::{AttrWrapper, Capturing, Parser, PathStyle}; +use super::{AttrWrapper, Capturing, ForceCollect, Parser, PathStyle}; use rustc_ast as ast; use rustc_ast::attr; use rustc_ast::token::{self, Nonterminal}; use rustc_ast_pretty::pprust; -use rustc_errors::{error_code, PResult}; -use rustc_span::{sym, Span}; +use rustc_errors::{error_code, DiagnosticBuilder, PResult}; +use rustc_span::{sym, BytePos, Span}; use std::convert::TryInto; use tracing::debug; @@ -25,6 +25,12 @@ pub(super) const DEFAULT_INNER_ATTR_FORBIDDEN: InnerAttrPolicy<'_> = InnerAttrPo prev_attr_sp: None, }; +enum OuterAttributeType { + DocComment, + DocBlockComment, + Attribute, +} + impl<'a> Parser<'a> { /// Parses attributes that appear before an item. pub(super) fn parse_outer_attributes(&mut self) -> PResult<'a, AttrWrapper> { @@ -49,18 +55,32 @@ impl<'a> Parser<'a> { Some(self.parse_attribute(inner_parse_policy)?) } else if let token::DocComment(comment_kind, attr_style, data) = self.token.kind { if attr_style != ast::AttrStyle::Outer { - self.sess - .span_diagnostic - .struct_span_err_with_code( - self.token.span, - "expected outer doc comment", - error_code!(E0753), - ) - .note( - "inner doc comments like this (starting with \ - `//!` or `/*!`) can only appear before items", - ) - .emit(); + let span = self.token.span; + let mut err = self.sess.span_diagnostic.struct_span_err_with_code( + span, + "expected outer doc comment", + error_code!(E0753), + ); + if let Some(replacement_span) = self.annotate_following_item_if_applicable( + &mut err, + span, + match comment_kind { + token::CommentKind::Line => OuterAttributeType::DocComment, + token::CommentKind::Block => OuterAttributeType::DocBlockComment, + }, + ) { + err.note( + "inner doc comments like this (starting with `//!` or `/*!`) can \ + only appear before items", + ); + err.span_suggestion_verbose( + replacement_span, + "you might have meant to write a regular comment", + String::new(), + rustc_errors::Applicability::MachineApplicable, + ); + } + err.emit(); } self.bump(); just_parsed_doc_comment = true; @@ -97,7 +117,7 @@ impl<'a> Parser<'a> { inner_parse_policy, self.token ); let lo = self.token.span; - // Attributse can't have attributes of their own + // Attributes can't have attributes of their own [Editor's note: not with that attitude] self.collect_tokens_no_attrs(|this| { if this.eat(&token::Pound) { let style = if this.eat(&token::Not) { @@ -125,6 +145,75 @@ impl<'a> Parser<'a> { }) } + fn annotate_following_item_if_applicable( + &self, + err: &mut DiagnosticBuilder<'_>, + span: Span, + attr_type: OuterAttributeType, + ) -> Option { + let mut snapshot = self.clone(); + let lo = span.lo() + + BytePos(match attr_type { + OuterAttributeType::Attribute => 1, + _ => 2, + }); + let hi = lo + BytePos(1); + let replacement_span = span.with_lo(lo).with_hi(hi); + if let OuterAttributeType::DocBlockComment | OuterAttributeType::DocComment = attr_type { + snapshot.bump(); + } + loop { + // skip any other attributes, we want the item + if snapshot.token.kind == token::Pound { + if let Err(mut err) = snapshot.parse_attribute(InnerAttrPolicy::Permitted) { + err.cancel(); + return Some(replacement_span); + } + } else { + break; + } + } + match snapshot.parse_item_common( + AttrWrapper::empty(), + true, + false, + |_| true, + ForceCollect::No, + ) { + Ok(Some(item)) => { + let attr_name = match attr_type { + OuterAttributeType::Attribute => "attribute", + _ => "doc comment", + }; + err.span_label( + item.span, + &format!("the inner {} doesn't annotate this {}", attr_name, item.kind.descr()), + ); + err.span_suggestion_verbose( + replacement_span, + &format!( + "to annotate the {}, change the {} from inner to outer style", + item.kind.descr(), + attr_name + ), + (match attr_type { + OuterAttributeType::Attribute => "", + OuterAttributeType::DocBlockComment => "*", + OuterAttributeType::DocComment => "/", + }) + .to_string(), + rustc_errors::Applicability::MachineApplicable, + ); + return None; + } + Err(mut item_err) => { + item_err.cancel(); + } + Ok(None) => {} + } + Some(replacement_span) + } + pub(super) fn error_on_forbidden_inner_attr(&self, attr_sp: Span, policy: InnerAttrPolicy<'_>) { if let InnerAttrPolicy::Forbidden { reason, saw_doc_comment, prev_attr_sp } = policy { let prev_attr_note = @@ -138,11 +227,20 @@ impl<'a> Parser<'a> { } diag.note( - "inner attributes, like `#![no_std]`, annotate the item enclosing them, \ - and are usually found at the beginning of source files. \ - Outer attributes, like `#[test]`, annotate the item following them.", - ) - .emit(); + "inner attributes, like `#![no_std]`, annotate the item enclosing them, and \ + are usually found at the beginning of source files", + ); + if self + .annotate_following_item_if_applicable( + &mut diag, + attr_sp, + OuterAttributeType::Attribute, + ) + .is_some() + { + diag.note("outer attributes, like `#[test]`, annotate the item following them"); + }; + diag.emit(); } } diff --git a/compiler/rustc_parse/src/parser/attr_wrapper.rs b/compiler/rustc_parse/src/parser/attr_wrapper.rs index 9f06bdcc13..568682cc3e 100644 --- a/compiler/rustc_parse/src/parser/attr_wrapper.rs +++ b/compiler/rustc_parse/src/parser/attr_wrapper.rs @@ -34,7 +34,7 @@ pub struct AttrWrapper { // This struct is passed around very frequently, // so make sure it doesn't accidentally get larger -#[cfg(target_arch = "x86_64")] +#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] rustc_data_structures::static_assert_size!(AttrWrapper, 16); impl AttrWrapper { diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 94ca70d3f9..8095f386fa 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -277,7 +277,7 @@ impl<'a> Parser<'a> { self.struct_span_err(sp, &msg) .span_suggestion_short(sp, "change this to `;`", ";".to_string(), appl) .emit(); - return Ok(false); + return Ok(true); } else if self.look_ahead(0, |t| { t == &token::CloseDelim(token::Brace) || ( @@ -295,7 +295,7 @@ impl<'a> Parser<'a> { .span_label(self.token.span, "unexpected token") .span_suggestion_short(sp, "add `;` here", ";".to_string(), appl) .emit(); - return Ok(false); + return Ok(true); } } @@ -1334,30 +1334,25 @@ impl<'a> Parser<'a> { pub(super) fn recover_parens_around_for_head( &mut self, pat: P, - expr: &Expr, begin_paren: Option, ) -> P { match (&self.token.kind, begin_paren) { (token::CloseDelim(token::Paren), Some(begin_par_sp)) => { self.bump(); - let pat_str = self - // Remove the `(` from the span of the pattern: - .span_to_snippet(pat.span.trim_start(begin_par_sp).unwrap()) - .unwrap_or_else(|_| pprust::pat_to_string(&pat)); - - self.struct_span_err(self.prev_token.span, "unexpected closing `)`") - .span_label(begin_par_sp, "opening `(`") - .span_suggestion( - begin_par_sp.to(self.prev_token.span), - "remove parenthesis in `for` loop", - format!("{} in {}", pat_str, pprust::expr_to_string(&expr)), - // With e.g. `for (x) in y)` this would replace `(x) in y)` - // with `x) in y)` which is syntactically invalid. - // However, this is prevented before we get here. - Applicability::MachineApplicable, - ) - .emit(); + self.struct_span_err( + MultiSpan::from_spans(vec![begin_par_sp, self.prev_token.span]), + "unexpected parenthesis surrounding `for` loop head", + ) + .multipart_suggestion( + "remove parenthesis 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. + // However, this is prevented before we get here. + Applicability::MachineApplicable, + ) + .emit(); // Unwrap `(pat)` into `pat` to avoid the `unused_parens` lint. pat.and_then(|pat| match pat.kind { @@ -1633,50 +1628,57 @@ impl<'a> Parser<'a> { { let rfc_note = "anonymous parameters are removed in the 2018 edition (see RFC 1685)"; - let (ident, self_sugg, param_sugg, type_sugg) = match pat.kind { - PatKind::Ident(_, ident, _) => ( - ident, - format!("self: {}", ident), - format!("{}: TypeName", ident), - format!("_: {}", ident), - ), - // Also catches `fn foo(&a)`. - PatKind::Ref(ref pat, mutab) - if matches!(pat.clone().into_inner().kind, PatKind::Ident(..)) => - { - match pat.clone().into_inner().kind { - PatKind::Ident(_, ident, _) => { - let mutab = mutab.prefix_str(); - ( - ident, - format!("self: &{}{}", mutab, ident), - format!("{}: &{}TypeName", ident, mutab), - format!("_: &{}{}", mutab, ident), - ) + let (ident, self_sugg, param_sugg, type_sugg, self_span, param_span, type_span) = + match pat.kind { + PatKind::Ident(_, ident, _) => ( + ident, + "self: ".to_string(), + ": TypeName".to_string(), + "_: ".to_string(), + pat.span.shrink_to_lo(), + pat.span.shrink_to_hi(), + pat.span.shrink_to_lo(), + ), + // Also catches `fn foo(&a)`. + PatKind::Ref(ref inner_pat, mutab) + if matches!(inner_pat.clone().into_inner().kind, PatKind::Ident(..)) => + { + match inner_pat.clone().into_inner().kind { + PatKind::Ident(_, ident, _) => { + let mutab = mutab.prefix_str(); + ( + ident, + "self: ".to_string(), + format!("{}: &{}TypeName", ident, mutab), + "_: ".to_string(), + pat.span.shrink_to_lo(), + pat.span, + pat.span.shrink_to_lo(), + ) + } + _ => unreachable!(), } - _ => unreachable!(), - } - } - _ => { - // Otherwise, try to get a type and emit a suggestion. - if let Some(ty) = pat.to_ty() { - err.span_suggestion_verbose( - pat.span, - "explicitly ignore the parameter name", - format!("_: {}", pprust::ty_to_string(&ty)), - Applicability::MachineApplicable, - ); - err.note(rfc_note); } + _ => { + // Otherwise, try to get a type and emit a suggestion. + if let Some(ty) = pat.to_ty() { + err.span_suggestion_verbose( + pat.span, + "explicitly ignore the parameter name", + format!("_: {}", pprust::ty_to_string(&ty)), + Applicability::MachineApplicable, + ); + err.note(rfc_note); + } - return None; - } - }; + return None; + } + }; // `fn foo(a, b) {}`, `fn foo(a, b) {}` or `fn foo(usize, usize) {}` if first_param { err.span_suggestion( - pat.span, + self_span, "if this is a `self` type, give it a parameter name", self_sugg, Applicability::MaybeIncorrect, @@ -1686,14 +1688,14 @@ impl<'a> Parser<'a> { // `fn foo(HashMap: TypeName)`. if self.token != token::Lt { err.span_suggestion( - pat.span, + param_span, "if this is a parameter name, give it a type", param_sugg, Applicability::HasPlaceholders, ); } err.span_suggestion( - pat.span, + type_span, "if this is a type, explicitly ignore the parameter name", type_sugg, Applicability::MachineApplicable, @@ -1948,7 +1950,19 @@ impl<'a> Parser<'a> { } match self.parse_expr_res(Restrictions::CONST_EXPR, None) { Ok(expr) => { - if token::Comma == self.token.kind || self.token.kind.should_end_const_arg() { + // Find a mistake like `MyTrait`. + if token::EqEq == snapshot.token.kind { + err.span_suggestion( + snapshot.token.span, + "if you meant to use an associated type binding, replace `==` with `=`", + "=".to_string(), + Applicability::MaybeIncorrect, + ); + let value = self.mk_expr_err(start.to(expr.span)); + err.emit(); + return Ok(GenericArg::Const(AnonConst { id: ast::DUMMY_NODE_ID, value })); + } else if token::Comma == self.token.kind || self.token.kind.should_end_const_arg() + { // Avoid the following output by checking that we consumed a full const arg: // help: expressions must be enclosed in braces to be used as const generic // arguments diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index a1d3e9adba..3d29d30502 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -1,9 +1,12 @@ use super::pat::{RecoverColon, RecoverComma, PARAM_EXPECTED}; use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign}; -use super::{AttrWrapper, BlockMode, ForceCollect, Parser, PathStyle, Restrictions, TokenType}; +use super::{ + AttrWrapper, BlockMode, ClosureSpans, ForceCollect, Parser, PathStyle, Restrictions, TokenType, +}; use super::{SemiColonMode, SeqSep, TokenExpectType, TrailingToken}; use crate::maybe_recover_from_interpolated_ty_qpath; +use ast::token::DelimToken; use rustc_ast::ptr::P; use rustc_ast::token::{self, Token, TokenKind}; use rustc_ast::tokenstream::Spacing; @@ -91,6 +94,8 @@ impl<'a> Parser<'a> { /// Parses an expression. #[inline] pub fn parse_expr(&mut self) -> PResult<'a, P> { + self.current_closure.take(); + self.parse_expr_res(Restrictions::empty(), None) } @@ -516,6 +521,26 @@ impl<'a> Parser<'a> { token::BinOp(token::And) | token::AndAnd => { make_it!(this, attrs, |this, _| this.parse_borrow_expr(lo)) } + token::BinOp(token::Plus) if this.look_ahead(1, |tok| tok.is_numeric_lit()) => { + let mut err = this.struct_span_err(lo, "leading `+` is not supported"); + err.span_label(lo, "unexpected `+`"); + + // a block on the LHS might have been intended to be an expression instead + if let Some(sp) = this.sess.ambiguous_block_expr_parse.borrow().get(&lo) { + this.sess.expr_parentheses_needed(&mut err, *sp); + } else { + err.span_suggestion_verbose( + lo, + "try removing the `+`", + "".to_string(), + Applicability::MachineApplicable, + ); + } + err.emit(); + + this.bump(); + this.parse_prefix_expr(None) + } // `+expr` token::Ident(..) if this.token.is_keyword(kw::Box) => { make_it!(this, attrs, |this, _| this.parse_box_expr(lo)) } @@ -882,6 +907,12 @@ impl<'a> Parser<'a> { } } + fn look_ahead_type_ascription_as_field(&mut self) -> bool { + self.look_ahead(1, |t| t.is_ident()) + && self.look_ahead(2, |t| t == &token::Colon) + && self.look_ahead(3, |t| t.can_begin_expr()) + } + fn parse_dot_suffix_expr(&mut self, lo: Span, base: P) -> PResult<'a, P> { match self.token.uninterpolate().kind { token::Ident(..) => self.parse_dot_suffix(base, lo), @@ -1031,12 +1062,77 @@ impl<'a> Parser<'a> { /// Parse a function call expression, `expr(...)`. fn parse_fn_call_expr(&mut self, lo: Span, fun: P) -> P { - let seq = self.parse_paren_expr_seq().map(|args| { + let snapshot = if self.token.kind == token::OpenDelim(token::Paren) + && self.look_ahead_type_ascription_as_field() + { + Some((self.clone(), fun.kind.clone())) + } else { + None + }; + let open_paren = self.token.span; + + let mut seq = self.parse_paren_expr_seq().map(|args| { self.mk_expr(lo.to(self.prev_token.span), self.mk_call(fun, args), AttrVec::new()) }); + if let Some(expr) = + self.maybe_recover_struct_lit_bad_delims(lo, open_paren, &mut seq, snapshot) + { + return expr; + } self.recover_seq_parse_error(token::Paren, lo, seq) } + /// If we encounter a parser state that looks like the user has written a `struct` literal with + /// parentheses instead of braces, recover the parser state and provide suggestions. + #[instrument(skip(self, seq, snapshot), level = "trace")] + fn maybe_recover_struct_lit_bad_delims( + &mut self, + lo: Span, + open_paren: Span, + seq: &mut PResult<'a, P>, + snapshot: Option<(Self, ExprKind)>, + ) -> Option> { + match (seq.as_mut(), snapshot) { + (Err(ref mut err), Some((mut snapshot, ExprKind::Path(None, path)))) => { + let name = pprust::path_to_string(&path); + snapshot.bump(); // `(` + match snapshot.parse_struct_fields(path, false, token::Paren) { + Ok((fields, ..)) if snapshot.eat(&token::CloseDelim(token::Paren)) => { + // We have are certain we have `Enum::Foo(a: 3, b: 4)`, suggest + // `Enum::Foo { a: 3, b: 4 }` or `Enum::Foo(3, 4)`. + *self = snapshot; + let close_paren = self.prev_token.span; + let span = lo.to(self.prev_token.span); + err.cancel(); + self.struct_span_err( + span, + "invalid `struct` delimiters or `fn` call arguments", + ) + .multipart_suggestion( + &format!("if `{}` is a struct, use braces as delimiters", name), + vec![(open_paren, " { ".to_string()), (close_paren, " }".to_string())], + Applicability::MaybeIncorrect, + ) + .multipart_suggestion( + &format!("if `{}` is a function, use the arguments directly", name), + fields + .into_iter() + .map(|field| (field.span.until(field.expr.span), String::new())) + .collect(), + Applicability::MaybeIncorrect, + ) + .emit(); + return Some(self.mk_expr_err(span)); + } + Ok(_) => {} + Err(mut err) => err.emit(), + } + } + _ => {} + } + None + } + /// Parse an indexing expression `expr[...]`. fn parse_index_expr(&mut self, lo: Span, base: P) -> PResult<'a, P> { self.bump(); // `[` @@ -1109,7 +1205,7 @@ impl<'a> Parser<'a> { } else if self.check(&token::BinOp(token::Or)) || self.check(&token::OrOr) { self.parse_closure_expr(attrs) } else if self.check(&token::OpenDelim(token::Bracket)) { - self.parse_array_or_repeat_expr(attrs) + self.parse_array_or_repeat_expr(attrs, token::Bracket) } else if self.check_path() { self.parse_path_start_expr(attrs) } else if self.check_keyword(kw::Move) || self.check_keyword(kw::Static) { @@ -1227,11 +1323,15 @@ impl<'a> Parser<'a> { self.maybe_recover_from_bad_qpath(expr, true) } - fn parse_array_or_repeat_expr(&mut self, attrs: AttrVec) -> PResult<'a, P> { + fn parse_array_or_repeat_expr( + &mut self, + attrs: AttrVec, + close_delim: token::DelimToken, + ) -> PResult<'a, P> { let lo = self.token.span; - self.bump(); // `[` + self.bump(); // `[` or other open delim - let close = &token::CloseDelim(token::Bracket); + let close = &token::CloseDelim(close_delim); let kind = if self.eat(close) { // Empty vector ExprKind::Array(Vec::new()) @@ -1468,6 +1568,20 @@ impl<'a> Parser<'a> { pub(super) fn parse_lit(&mut self) -> PResult<'a, Lit> { self.parse_opt_lit().ok_or_else(|| { + if let token::Interpolated(inner) = &self.token.kind { + let expr = match inner.as_ref() { + token::NtExpr(expr) => Some(expr), + token::NtLiteral(expr) => Some(expr), + _ => None, + }; + if let Some(expr) = expr { + if matches!(expr.kind, ExprKind::Err) { + self.diagnostic() + .delay_span_bug(self.token.span, &"invalid interpolated expression"); + return self.diagnostic().struct_dummy(); + } + } + } let msg = format!("unexpected token: {}", super::token_descr(&self.token)); self.struct_span_err(self.token.span, &msg) }) @@ -1657,6 +1771,46 @@ impl<'a> Parser<'a> { } } + fn is_array_like_block(&mut self) -> bool { + self.look_ahead(1, |t| matches!(t.kind, TokenKind::Ident(..) | TokenKind::Literal(_))) + && self.look_ahead(2, |t| t == &token::Comma) + && self.look_ahead(3, |t| t.can_begin_expr()) + } + + /// Emits a suggestion if it looks like the user meant an array but + /// accidentally used braces, causing the code to be interpreted as a block + /// expression. + fn maybe_suggest_brackets_instead_of_braces( + &mut self, + lo: Span, + attrs: AttrVec, + ) -> Option> { + let mut snapshot = self.clone(); + match snapshot.parse_array_or_repeat_expr(attrs, token::Brace) { + Ok(arr) => { + let hi = snapshot.prev_token.span; + self.struct_span_err( + arr.span, + "this code is interpreted as a block expression, not an array", + ) + .multipart_suggestion( + "try using [] instead of {}", + vec![(lo, "[".to_owned()), (hi, "]".to_owned())], + Applicability::MaybeIncorrect, + ) + .note("to define an array, one would use square brackets instead of curly braces") + .emit(); + + *self = snapshot; + Some(self.mk_expr_err(arr.span)) + } + Err(mut e) => { + e.cancel(); + None + } + } + } + /// Parses a block or unsafe block. pub(super) fn parse_block_expr( &mut self, @@ -1665,6 +1819,12 @@ impl<'a> Parser<'a> { blk_mode: BlockCheckMode, mut attrs: AttrVec, ) -> PResult<'a, P> { + if self.is_array_like_block() { + if let Some(arr) = self.maybe_suggest_brackets_instead_of_braces(lo, attrs.clone()) { + return Ok(arr); + } + } + if let Some(label) = opt_label { self.sess.gated_spans.gate(sym::label_break_value, label.ident.span); } @@ -1716,7 +1876,7 @@ impl<'a> Parser<'a> { let capture_clause = self.parse_capture_clause()?; let decl = self.parse_fn_block_decl()?; let decl_hi = self.prev_token.span; - let body = match decl.output { + let mut body = match decl.output { FnRetTy::Default(_) => { let restrictions = self.restrictions - Restrictions::STMT_EXPR; self.parse_expr_res(restrictions, None)? @@ -1733,11 +1893,28 @@ impl<'a> Parser<'a> { self.sess.gated_spans.gate(sym::async_closure, span); } - Ok(self.mk_expr( + if self.token.kind == TokenKind::Semi && self.token_cursor.frame.delim == DelimToken::Paren + { + // It is likely that the closure body is a block but where the + // braces have been removed. We will recover and eat the next + // statements later in the parsing process. + body = self.mk_expr_err(body.span); + } + + let body_span = body.span; + + let closure = self.mk_expr( lo.to(body.span), ExprKind::Closure(capture_clause, asyncness, movability, decl, body, lo.to(decl_hi)), attrs, - )) + ); + + // Disable recovery for closure body + let spans = + ClosureSpans { whole_closure: closure.span, closing_pipe: decl_hi, body: body_span }; + self.current_closure = Some(spans); + + Ok(closure) } /// Parses an optional `move` prefix to a closure-like construct. @@ -1930,7 +2107,7 @@ impl<'a> Parser<'a> { self.check_for_for_in_in_typo(self.prev_token.span); let expr = self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL, None)?; - let pat = self.recover_parens_around_for_head(pat, &expr, begin_paren); + let pat = self.recover_parens_around_for_head(pat, begin_paren); let (iattrs, loop_block) = self.parse_inner_attrs_and_block()?; attrs.extend(iattrs); @@ -2145,7 +2322,24 @@ impl<'a> Parser<'a> { None }; let arrow_span = this.token.span; - this.expect(&token::FatArrow)?; + if let Err(mut err) = this.expect(&token::FatArrow) { + // We might have a `=>` -> `=` or `->` typo (issue #89396). + if TokenKind::FatArrow + .similar_tokens() + .map_or(false, |similar_tokens| similar_tokens.contains(&this.token.kind)) + { + err.span_suggestion( + this.token.span, + "try using a fat arrow here", + "=>".to_string(), + Applicability::MaybeIncorrect, + ); + err.emit(); + this.bump(); + } else { + return Err(err); + } + } let arm_start_span = this.token.span; let expr = this.parse_expr_res(Restrictions::STMT_EXPR, None).map_err(|mut err| { @@ -2332,14 +2526,12 @@ impl<'a> Parser<'a> { .emit(); } - /// Precondition: already parsed the '{'. - pub(super) fn parse_struct_expr( + pub(super) fn parse_struct_fields( &mut self, - qself: Option, pth: ast::Path, - attrs: AttrVec, recover: bool, - ) -> PResult<'a, P> { + close_delim: token::DelimToken, + ) -> PResult<'a, (Vec, ast::StructRest, bool)> { let mut fields = Vec::new(); let mut base = ast::StructRest::None; let mut recover_async = false; @@ -2351,11 +2543,11 @@ impl<'a> Parser<'a> { e.note("for more on editions, read https://doc.rust-lang.org/edition-guide"); }; - while self.token != token::CloseDelim(token::Brace) { + while self.token != token::CloseDelim(close_delim) { if self.eat(&token::DotDot) { let exp_span = self.prev_token.span; // We permit `.. }` on the left-hand side of a destructuring assignment. - if self.check(&token::CloseDelim(token::Brace)) { + if self.check(&token::CloseDelim(close_delim)) { self.sess.gated_spans.gate(sym::destructuring_assignment, self.prev_token.span); base = ast::StructRest::Rest(self.prev_token.span.shrink_to_hi()); break; @@ -2396,7 +2588,7 @@ impl<'a> Parser<'a> { } }; - match self.expect_one_of(&[token::Comma], &[token::CloseDelim(token::Brace)]) { + match self.expect_one_of(&[token::Comma], &[token::CloseDelim(close_delim)]) { Ok(_) => { if let Some(f) = parsed_field.or(recovery_field) { // Only include the field if there's no parse error for the field name. @@ -2427,8 +2619,21 @@ impl<'a> Parser<'a> { } } } + Ok((fields, base, recover_async)) + } - let span = pth.span.to(self.token.span); + /// Precondition: already parsed the '{'. + pub(super) fn parse_struct_expr( + &mut self, + qself: Option, + pth: ast::Path, + attrs: AttrVec, + recover: bool, + ) -> PResult<'a, P> { + let lo = pth.span; + let (fields, base, recover_async) = + self.parse_struct_fields(pth.clone(), recover, token::Brace)?; + let span = lo.to(self.token.span); self.expect(&token::CloseDelim(token::Brace))?; let expr = if recover_async { ExprKind::Err diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index c5b961f12b..624390a406 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -493,7 +493,20 @@ impl<'a> Parser<'a> { let ty_first = if self.token.is_keyword(kw::For) && self.look_ahead(1, |t| t != &token::Lt) { let span = self.prev_token.span.between(self.token.span); - self.struct_span_err(span, "missing trait in a trait impl").emit(); + self.struct_span_err(span, "missing trait in a trait impl") + .span_suggestion( + span, + "add a trait here", + " Trait ".into(), + Applicability::HasPlaceholders, + ) + .span_suggestion( + span.to(self.token.span), + "for an inherent impl, drop this `for`", + "".into(), + Applicability::MaybeIncorrect, + ) + .emit(); P(Ty { kind: TyKind::Path(None, err_path(span)), span, @@ -1534,6 +1547,20 @@ impl<'a> Parser<'a> { self.expect(&token::Not)?; // `!` let ident = self.parse_ident()?; + + if self.eat(&token::Not) { + // Handle macro_rules! foo! + let span = self.prev_token.span; + self.struct_span_err(span, "macro names aren't followed by a `!`") + .span_suggestion( + span, + "remove the `!`", + "".to_owned(), + Applicability::MachineApplicable, + ) + .emit(); + } + let body = self.parse_mac_args()?; self.eat_semi_for_macro_if_needed(&body); self.complain_if_pub_macro(vis, true); diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index c4419e995e..5c701fefd1 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -142,6 +142,17 @@ pub struct Parser<'a> { /// If present, this `Parser` is not parsing Rust code but rather a macro call. subparser_name: Option<&'static str>, capture_state: CaptureState, + /// This allows us to recover when the user forget to add braces around + /// multiple statements in the closure body. + pub current_closure: Option, +} + +/// Stores span informations about a closure. +#[derive(Clone)] +pub struct ClosureSpans { + pub whole_closure: Span, + pub closing_pipe: Span, + pub body: Span, } /// Indicates a range of tokens that should be replaced by @@ -440,6 +451,7 @@ impl<'a> Parser<'a> { replace_ranges: Vec::new(), inner_attr_ranges: Default::default(), }, + current_closure: None, }; // Make parser point to the first token. @@ -761,8 +773,11 @@ impl<'a> Parser<'a> { first = false; } else { match self.expect(t) { - Ok(false) => {} + Ok(false) => { + self.current_closure.take(); + } Ok(true) => { + self.current_closure.take(); recovered = true; break; } @@ -770,10 +785,29 @@ impl<'a> Parser<'a> { let sp = self.prev_token.span.shrink_to_hi(); let token_str = pprust::token_kind_to_string(t); - // Attempt to keep parsing if it was a similar separator. - if let Some(ref tokens) = t.similar_tokens() { - if tokens.contains(&self.token.kind) && !unclosed_delims { - self.bump(); + match self.current_closure.take() { + Some(closure_spans) if self.token.kind == TokenKind::Semi => { + // Finding a semicolon instead of a comma + // after a closure body indicates that the + // closure body may be a block but the user + // forgot to put braces around its + // statements. + + self.recover_missing_braces_around_closure_body( + closure_spans, + expect_err, + )?; + + continue; + } + + _ => { + // Attempt to keep parsing if it was a similar separator. + if let Some(ref tokens) = t.similar_tokens() { + if tokens.contains(&self.token.kind) && !unclosed_delims { + self.bump(); + } + } } } @@ -839,6 +873,65 @@ impl<'a> Parser<'a> { Ok((v, trailing, recovered)) } + fn recover_missing_braces_around_closure_body( + &mut self, + closure_spans: ClosureSpans, + mut expect_err: DiagnosticBuilder<'_>, + ) -> PResult<'a, ()> { + let initial_semicolon = self.token.span; + + while self.eat(&TokenKind::Semi) { + let _ = self.parse_stmt(ForceCollect::Yes)?; + } + + expect_err.set_primary_message( + "closure bodies that contain statements must be surrounded by braces", + ); + + let preceding_pipe_span = closure_spans.closing_pipe; + let following_token_span = self.token.span; + + let mut first_note = MultiSpan::from(vec![initial_semicolon]); + first_note.push_span_label( + initial_semicolon, + "this `;` turns the preceding closure into a statement".to_string(), + ); + first_note.push_span_label( + closure_spans.body, + "this expression is a statement because of the trailing semicolon".to_string(), + ); + expect_err.span_note(first_note, "statement found outside of a block"); + + let mut second_note = MultiSpan::from(vec![closure_spans.whole_closure]); + second_note.push_span_label( + closure_spans.whole_closure, + "this is the parsed closure...".to_string(), + ); + second_note.push_span_label( + following_token_span, + "...but likely you meant the closure to end here".to_string(), + ); + expect_err.span_note(second_note, "the closure body may be incorrectly delimited"); + + expect_err.set_span(vec![preceding_pipe_span, following_token_span]); + + let opening_suggestion_str = " {".to_string(); + let closing_suggestion_str = "}".to_string(); + + expect_err.multipart_suggestion( + "try adding braces", + vec![ + (preceding_pipe_span.shrink_to_hi(), opening_suggestion_str), + (following_token_span.shrink_to_lo(), closing_suggestion_str), + ], + Applicability::MaybeIncorrect, + ); + + expect_err.emit(); + + Ok(()) + } + /// Parses a sequence, not including the closing delimiter. The function /// `f` must consume tokens until reaching the next separator or /// closing bracket. diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs index 953c691506..c7d080a80f 100644 --- a/compiler/rustc_parse/src/parser/path.rs +++ b/compiler/rustc_parse/src/parser/path.rs @@ -495,20 +495,28 @@ impl<'a> Parser<'a> { None => { let after_eq = eq.shrink_to_hi(); let before_next = self.token.span.shrink_to_lo(); - self.struct_span_err(after_eq.to(before_next), "missing type to the right of `=`") - .span_suggestion( + let mut err = self + .struct_span_err(after_eq.to(before_next), "missing type to the right of `=`"); + if matches!(self.token.kind, token::Comma | token::Gt) { + err.span_suggestion( self.sess.source_map().next_point(eq).to(before_next), "to constrain the associated type, add a type after `=`", " TheType".to_string(), Applicability::HasPlaceholders, - ) - .span_suggestion( + ); + err.span_suggestion( eq.to(before_next), &format!("remove the `=` if `{}` is a type", ident), String::new(), Applicability::MaybeIncorrect, ) - .emit(); + } else { + err.span_label( + self.token.span, + &format!("expected type, found {}", super::token_descr(&self.token)), + ) + }; + return Err(err); } } Ok(self.mk_ty(span, ast::TyKind::Err)) @@ -572,6 +580,25 @@ 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 { return Ok(None); }; diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index 25dcb4a112..9ec6effeb4 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -155,17 +155,20 @@ impl<'a> Parser<'a> { let mac = MacCall { path, args, prior_type_ascription: self.last_type_ascription }; - let kind = if delim == token::Brace || self.token == token::Semi || self.token == token::Eof - { - StmtKind::MacCall(P(MacCallStmt { mac, style, attrs, tokens: None })) - } else { - // Since none of the above applied, this is an expression statement macro. - let e = self.mk_expr(lo.to(hi), ExprKind::MacCall(mac), AttrVec::new()); - let e = self.maybe_recover_from_bad_qpath(e, true)?; - let e = self.parse_dot_or_call_expr_with(e, lo, attrs.into())?; - let e = self.parse_assoc_expr_with(0, LhsExpr::AlreadyParsed(e))?; - StmtKind::Expr(e) - }; + let kind = + if (delim == token::Brace && self.token != token::Dot && self.token != token::Question) + || self.token == token::Semi + || self.token == token::Eof + { + StmtKind::MacCall(P(MacCallStmt { mac, style, attrs, tokens: None })) + } else { + // Since none of the above applied, this is an expression statement macro. + let e = self.mk_expr(lo.to(hi), ExprKind::MacCall(mac), AttrVec::new()); + let e = self.maybe_recover_from_bad_qpath(e, true)?; + let e = self.parse_dot_or_call_expr_with(e, lo, attrs.into())?; + let e = self.parse_assoc_expr_with(0, LhsExpr::AlreadyParsed(e))?; + StmtKind::Expr(e) + }; Ok(self.mk_stmt(lo.to(hi), kind)) } diff --git a/compiler/rustc_parse/src/validate_attr.rs b/compiler/rustc_parse/src/validate_attr.rs index 67695dc285..2aa20d02c8 100644 --- a/compiler/rustc_parse/src/validate_attr.rs +++ b/compiler/rustc_parse/src/validate_attr.rs @@ -4,7 +4,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, PResult}; +use rustc_errors::{Applicability, FatalError, PResult}; use rustc_feature::{AttributeTemplate, BUILTIN_ATTRIBUTE_MAP}; use rustc_session::lint::builtin::ILL_FORMED_ATTRIBUTE_INPUT; use rustc_session::parse::ParseSess; @@ -91,69 +91,11 @@ pub fn check_builtin_attribute( // Some special attributes like `cfg` must be checked // before the generic check, so we skip them here. let should_skip = |name| name == sym::cfg; - // Some of previously accepted forms were used in practice, - // report them as warnings for now. - let should_warn = |name| { - name == sym::doc - || name == sym::ignore - || name == sym::inline - || name == sym::link - || name == sym::test - || name == sym::bench - }; match parse_meta(sess, attr) { Ok(meta) => { if !should_skip(name) && !is_attr_template_compatible(&template, &meta.kind) { - let error_msg = format!("malformed `{}` attribute input", name); - let mut msg = "attribute must be of the form ".to_owned(); - let mut suggestions = vec![]; - let mut first = true; - if template.word { - first = false; - let code = format!("#[{}]", name); - msg.push_str(&format!("`{}`", &code)); - suggestions.push(code); - } - if let Some(descr) = template.list { - if !first { - msg.push_str(" or "); - } - first = false; - let code = format!("#[{}({})]", name, descr); - msg.push_str(&format!("`{}`", &code)); - suggestions.push(code); - } - if let Some(descr) = template.name_value_str { - if !first { - msg.push_str(" or "); - } - let code = format!("#[{} = \"{}\"]", name, descr); - msg.push_str(&format!("`{}`", &code)); - suggestions.push(code); - } - if should_warn(name) { - sess.buffer_lint( - &ILL_FORMED_ATTRIBUTE_INPUT, - meta.span, - ast::CRATE_NODE_ID, - &msg, - ); - } else { - sess.span_diagnostic - .struct_span_err(meta.span, &error_msg) - .span_suggestions( - meta.span, - if suggestions.len() == 1 { - "must be of the form" - } else { - "the following are the possible correct uses" - }, - suggestions.into_iter(), - Applicability::HasPlaceholders, - ) - .emit(); - } + emit_malformed_attribute(sess, attr, name, template); } } Err(mut err) => { @@ -161,3 +103,74 @@ pub fn check_builtin_attribute( } } } + +fn emit_malformed_attribute( + sess: &ParseSess, + attr: &Attribute, + name: Symbol, + template: AttributeTemplate, +) { + // Some of previously accepted forms were used in practice, + // report them as warnings for now. + let should_warn = |name| { + matches!(name, sym::doc | sym::ignore | sym::inline | sym::link | sym::test | sym::bench) + }; + + let error_msg = format!("malformed `{}` attribute input", name); + let mut msg = "attribute must be of the form ".to_owned(); + let mut suggestions = vec![]; + let mut first = true; + let inner = if attr.style == ast::AttrStyle::Inner { "!" } else { "" }; + if template.word { + first = false; + let code = format!("#{}[{}]", inner, name); + msg.push_str(&format!("`{}`", &code)); + suggestions.push(code); + } + if let Some(descr) = template.list { + if !first { + msg.push_str(" or "); + } + first = false; + let code = format!("#{}[{}({})]", inner, name, descr); + msg.push_str(&format!("`{}`", &code)); + suggestions.push(code); + } + if let Some(descr) = template.name_value_str { + if !first { + msg.push_str(" or "); + } + let code = format!("#{}[{} = \"{}\"]", inner, name, descr); + msg.push_str(&format!("`{}`", &code)); + suggestions.push(code); + } + if should_warn(name) { + sess.buffer_lint(&ILL_FORMED_ATTRIBUTE_INPUT, attr.span, ast::CRATE_NODE_ID, &msg); + } else { + sess.span_diagnostic + .struct_span_err(attr.span, &error_msg) + .span_suggestions( + attr.span, + if suggestions.len() == 1 { + "must be of the form" + } else { + "the following are the possible correct uses" + }, + suggestions.into_iter(), + Applicability::HasPlaceholders, + ) + .emit(); + } +} + +pub fn emit_fatal_malformed_builtin_attribute( + sess: &ParseSess, + attr: &Attribute, + name: Symbol, +) -> ! { + let template = BUILTIN_ATTRIBUTE_MAP.get(&name).expect("builtin attr defined").2; + 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). + FatalError.raise() +} diff --git a/compiler/rustc_parse_format/Cargo.toml b/compiler/rustc_parse_format/Cargo.toml index 7b77560717..aa1714e820 100644 --- a/compiler/rustc_parse_format/Cargo.toml +++ b/compiler/rustc_parse_format/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustc_parse_format" version = "0.0.0" -edition = "2018" +edition = "2021" [dependencies] rustc_span = { path = "../rustc_span" } diff --git a/compiler/rustc_passes/Cargo.toml b/compiler/rustc_passes/Cargo.toml index bf1e52cd9a..39e578bce7 100644 --- a/compiler/rustc_passes/Cargo.toml +++ b/compiler/rustc_passes/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustc_passes" version = "0.0.0" -edition = "2018" +edition = "2021" [dependencies] tracing = "0.1" diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index fd438bdc90..e5fbddda74 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -9,7 +9,7 @@ use rustc_middle::ty::query::Providers; use rustc_middle::ty::TyCtxt; use rustc_ast::{ast, AttrStyle, Attribute, Lit, LitKind, NestedMetaItem}; -use rustc_data_structures::stable_set::FxHashSet; +use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::{pluralize, struct_span_err, Applicability}; use rustc_feature::{AttributeType, BUILTIN_ATTRIBUTE_MAP}; use rustc_hir as hir; @@ -66,6 +66,7 @@ impl CheckAttrVisitor<'tcx> { target: Target, item: Option>, ) { + let mut doc_aliases = FxHashMap::default(); let mut is_valid = true; let mut specified_inline = None; let mut seen = FxHashSet::default(); @@ -79,7 +80,13 @@ impl CheckAttrVisitor<'tcx> { sym::track_caller => { self.check_track_caller(hir_id, &attr.span, attrs, span, target) } - sym::doc => self.check_doc_attrs(attr, hir_id, target, &mut specified_inline), + sym::doc => self.check_doc_attrs( + attr, + hir_id, + target, + &mut specified_inline, + &mut doc_aliases, + ), sym::no_link => self.check_no_link(hir_id, &attr, span, target), sym::export_name => self.check_export_name(hir_id, &attr, span, target), sym::rustc_layout_scalar_valid_range_start @@ -104,6 +111,7 @@ impl CheckAttrVisitor<'tcx> { sym::default_method_body_is_const => { self.check_default_method_body_is_const(attr, span, target) } + sym::must_not_suspend => self.check_must_not_suspend(&attr, span, target), sym::rustc_const_unstable | sym::rustc_const_stable | sym::unstable @@ -511,6 +519,7 @@ impl CheckAttrVisitor<'tcx> { hir_id: HirId, target: Target, is_list: bool, + aliases: &mut FxHashMap, ) -> bool { let tcx = self.tcx; let err_fn = move |span: Span, msg: &str| { @@ -581,17 +590,38 @@ impl CheckAttrVisitor<'tcx> { if &*item_name.as_str() == doc_alias { return err_fn(meta.span(), "is the same as the item's name"); } + let span = meta.span(); + if let Err(entry) = aliases.try_insert(doc_alias.to_owned(), span) { + self.tcx.struct_span_lint_hir(UNUSED_ATTRIBUTES, hir_id, span, |lint| { + lint.build("doc alias is duplicated") + .span_label(*entry.entry.get(), "first defined here") + .emit(); + }); + } true } - fn check_doc_alias(&self, meta: &NestedMetaItem, hir_id: HirId, target: Target) -> bool { + fn check_doc_alias( + &self, + meta: &NestedMetaItem, + hir_id: HirId, + target: Target, + aliases: &mut FxHashMap, + ) -> bool { if let Some(values) = meta.meta_item_list() { let mut errors = 0; for v in values { match v.literal() { Some(l) => match l.kind { LitKind::Str(s, _) => { - if !self.check_doc_alias_value(v, &s.as_str(), hir_id, target, true) { + if !self.check_doc_alias_value( + v, + &s.as_str(), + hir_id, + target, + true, + aliases, + ) { errors += 1; } } @@ -620,7 +650,7 @@ impl CheckAttrVisitor<'tcx> { } errors == 0 } else if let Some(doc_alias) = meta.value_str().map(|s| s.to_string()) { - self.check_doc_alias_value(meta, &doc_alias, hir_id, target, false) + self.check_doc_alias_value(meta, &doc_alias, hir_id, target, false, aliases) } else { self.tcx .sess @@ -857,6 +887,7 @@ impl CheckAttrVisitor<'tcx> { hir_id: HirId, target: Target, specified_inline: &mut Option<(bool, Span)>, + aliases: &mut FxHashMap, ) -> bool { let mut is_valid = true; @@ -866,7 +897,7 @@ impl CheckAttrVisitor<'tcx> { match i_meta.name_or_empty() { sym::alias if !self.check_attr_not_crate_level(&meta, hir_id, "alias") - || !self.check_doc_alias(&meta, hir_id, target) => + || !self.check_doc_alias(&meta, hir_id, target, aliases) => { is_valid = false } @@ -907,6 +938,7 @@ impl CheckAttrVisitor<'tcx> { // plugins: removed, but rustdoc warns about it itself sym::alias | sym::cfg + | sym::cfg_hide | sym::hidden | sym::html_favicon_url | sym::html_logo_url @@ -1014,6 +1046,21 @@ impl CheckAttrVisitor<'tcx> { is_valid } + /// 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 { + Target::Struct | Target::Enum | Target::Union | Target::Trait => true, + _ => { + self.tcx + .sess + .struct_span_err(attr.span, "`must_not_suspend` attribute should be applied to a struct, enum, or trait") + .span_label(*span, "is not a struct, enum, or trait") + .emit(); + false + } + } + } + /// Checks if `#[cold]` is applied to a non-function. Returns `true` if valid. fn check_cold(&self, hir_id: HirId, attr: &Attribute, span: &Span, target: Target) { match target { @@ -1720,8 +1767,7 @@ impl CheckAttrVisitor<'tcx> { fn check_macro_export(&self, hir_id: HirId, attr: &Attribute, target: Target) { if target != Target::MacroDef { self.tcx.struct_span_lint_hir(UNUSED_ATTRIBUTES, hir_id, attr.span, |lint| { - lint.build(&format!("`#[macro_export]` only has an effect on macro definitions")) - .emit(); + lint.build("`#[macro_export]` only has an effect on macro definitions").emit(); }); } } diff --git a/compiler/rustc_passes/src/check_const.rs b/compiler/rustc_passes/src/check_const.rs index 4a82252a32..a0ceb567f2 100644 --- a/compiler/rustc_passes/src/check_const.rs +++ b/compiler/rustc_passes/src/check_const.rs @@ -8,7 +8,6 @@ //! through, but errors for structured control flow in a `const` should be emitted here. use rustc_attr as attr; -use rustc_data_structures::stable_set::FxHashSet; use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_hir::def_id::LocalDefId; @@ -83,32 +82,41 @@ impl<'tcx> hir::itemlikevisit::ItemLikeVisitor<'tcx> for CheckConstTraitVisitor< let _: Option<_> = try { if let hir::ItemKind::Impl(ref imp) = item.kind { if let hir::Constness::Const = imp.constness { - let did = imp.of_trait.as_ref()?.trait_def_id()?; - let mut to_implement = FxHashSet::default(); + let trait_def_id = imp.of_trait.as_ref()?.trait_def_id()?; + let ancestors = self + .tcx + .trait_def(trait_def_id) + .ancestors(self.tcx, item.def_id.to_def_id()) + .ok()?; + let mut to_implement = Vec::new(); - for did in self.tcx.associated_item_def_ids(did) { + for trait_item in self.tcx.associated_items(trait_def_id).in_definition_order() + { if let ty::AssocItem { kind: ty::AssocKind::Fn, ident, defaultness, .. - } = self.tcx.associated_item(*did) + } = trait_item { // we can ignore functions that do not have default bodies: // if those are unimplemented it will be catched by typeck. - if defaultness.has_value() - && !self.tcx.has_attr(*did, sym::default_method_body_is_const) + if !defaultness.has_value() + || self + .tcx + .has_attr(trait_item.def_id, sym::default_method_body_is_const) { - to_implement.insert(ident); + continue; + } + + let is_implemented = ancestors + .leaf_def(self.tcx, trait_item.ident, trait_item.kind) + .map(|node_item| !node_item.defining_node.is_from_trait()) + .unwrap_or(false); + + if !is_implemented { + to_implement.push(ident.to_string()); } } } - for it in imp - .items - .iter() - .filter(|it| matches!(it.kind, hir::AssocItemKind::Fn { .. })) - { - to_implement.remove(&it.ident); - } - // all nonconst trait functions (not marked with #[default_method_body_is_const]) // must be implemented if !to_implement.is_empty() { @@ -118,7 +126,7 @@ impl<'tcx> hir::itemlikevisit::ItemLikeVisitor<'tcx> for CheckConstTraitVisitor< item.span, "const trait implementations may not use non-const default functions", ) - .note(&format!("`{}` not implemented", to_implement.into_iter().map(|id| id.to_string()).collect::>().join("`, `"))) + .note(&format!("`{}` not implemented", to_implement.join("`, `"))) .emit(); } } diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index ae65222f3f..7727913240 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -239,7 +239,35 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { } } + /// Automatically generated items marked with `rustc_trivial_field_reads` + /// will be ignored for the purposes of dead code analysis (see PR #85200 + /// for discussion). + fn should_ignore_item(&self, def_id: DefId) -> bool { + if let Some(impl_of) = self.tcx.impl_of_method(def_id) { + if !self.tcx.has_attr(impl_of, sym::automatically_derived) { + return false; + } + + if let Some(trait_of) = self.tcx.trait_id_of_impl(impl_of) { + if self.tcx.has_attr(trait_of, sym::rustc_trivial_field_reads) { + return true; + } + } + } + + return false; + } + fn visit_node(&mut self, node: Node<'tcx>) { + if let Some(item_def_id) = match node { + Node::ImplItem(hir::ImplItem { def_id, .. }) => Some(def_id.to_def_id()), + _ => None, + } { + if self.should_ignore_item(item_def_id) { + return; + } + } + let had_repr_c = self.repr_has_repr_c; let had_inherited_pub_visibility = self.inherited_pub_visibility; let had_pub_visibility = self.pub_visibility; @@ -448,15 +476,14 @@ fn has_allow_dead_code_or_lang_attr(tcx: TyCtxt<'_>, id: hir::HirId) -> bool { // or // 2) We are not sure to be live or not // * Implementations of traits and trait methods -struct LifeSeeder<'k, 'tcx> { +struct LifeSeeder<'tcx> { worklist: Vec, - krate: &'k hir::Crate<'k>, tcx: TyCtxt<'tcx>, // see `MarkSymbolVisitor::struct_constructors` struct_constructors: FxHashMap, } -impl<'v, 'k, 'tcx> ItemLikeVisitor<'v> for LifeSeeder<'k, 'tcx> { +impl<'v, 'tcx> ItemLikeVisitor<'v> for LifeSeeder<'tcx> { fn visit_item(&mut self, item: &hir::Item<'_>) { let allow_dead_code = has_allow_dead_code_or_lang_attr(self.tcx, item.hir_id()); if allow_dead_code { @@ -483,7 +510,7 @@ impl<'v, 'k, 'tcx> ItemLikeVisitor<'v> for LifeSeeder<'k, 'tcx> { self.worklist.push(item.def_id); } for impl_item_ref in items { - let impl_item = self.krate.impl_item(impl_item_ref.id); + let impl_item = self.tcx.hir().impl_item(impl_item_ref.id); if of_trait.is_some() || has_allow_dead_code_or_lang_attr(self.tcx, impl_item.hir_id()) { @@ -527,7 +554,6 @@ impl<'v, 'k, 'tcx> ItemLikeVisitor<'v> for LifeSeeder<'k, 'tcx> { fn create_and_seed_worklist<'tcx>( tcx: TyCtxt<'tcx>, access_levels: &privacy::AccessLevels, - krate: &hir::Crate<'_>, ) -> (Vec, FxHashMap) { let worklist = access_levels .map @@ -542,9 +568,8 @@ fn create_and_seed_worklist<'tcx>( .collect::>(); // Seed implemented trait items - let mut life_seeder = - LifeSeeder { worklist, krate, tcx, struct_constructors: Default::default() }; - krate.visit_all_item_likes(&mut life_seeder); + let mut life_seeder = LifeSeeder { worklist, tcx, struct_constructors: Default::default() }; + tcx.hir().visit_all_item_likes(&mut life_seeder); (life_seeder.worklist, life_seeder.struct_constructors) } @@ -552,9 +577,8 @@ fn create_and_seed_worklist<'tcx>( fn find_live<'tcx>( tcx: TyCtxt<'tcx>, access_levels: &privacy::AccessLevels, - krate: &hir::Crate<'_>, ) -> FxHashSet { - let (worklist, struct_constructors) = create_and_seed_worklist(tcx, access_levels, krate); + let (worklist, struct_constructors) = create_and_seed_worklist(tcx, access_levels); let mut symbol_visitor = MarkSymbolVisitor { worklist, tcx, @@ -772,8 +796,7 @@ impl Visitor<'tcx> for DeadVisitor<'tcx> { pub fn check_crate(tcx: TyCtxt<'_>) { let access_levels = &tcx.privacy_access_levels(()); - let krate = tcx.hir().krate(); - let live_symbols = find_live(tcx, access_levels, krate); + let live_symbols = find_live(tcx, access_levels); let mut visitor = DeadVisitor { tcx, live_symbols }; - intravisit::walk_crate(&mut visitor, krate); + tcx.hir().walk_toplevel_module(&mut visitor); } diff --git a/compiler/rustc_passes/src/diagnostic_items.rs b/compiler/rustc_passes/src/diagnostic_items.rs index 3f12a744be..30a0071f0f 100644 --- a/compiler/rustc_passes/src/diagnostic_items.rs +++ b/compiler/rustc_passes/src/diagnostic_items.rs @@ -10,8 +10,8 @@ //! * Compiler internal types like `Ty` and `TyCtxt` use rustc_ast as ast; -use rustc_data_structures::fx::FxHashMap; use rustc_hir as hir; +use rustc_hir::diagnostic_items::DiagnosticItems; use rustc_hir::itemlikevisit::ItemLikeVisitor; use rustc_middle::ty::query::Providers; use rustc_middle::ty::TyCtxt; @@ -19,9 +19,8 @@ use rustc_span::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE}; use rustc_span::symbol::{sym, Symbol}; struct DiagnosticItemCollector<'tcx> { - // items from this crate - items: FxHashMap, tcx: TyCtxt<'tcx>, + diagnostic_items: DiagnosticItems, } impl<'v, 'tcx> ItemLikeVisitor<'v> for DiagnosticItemCollector<'tcx> { @@ -44,7 +43,7 @@ impl<'v, 'tcx> ItemLikeVisitor<'v> for DiagnosticItemCollector<'tcx> { impl<'tcx> DiagnosticItemCollector<'tcx> { fn new(tcx: TyCtxt<'tcx>) -> DiagnosticItemCollector<'tcx> { - DiagnosticItemCollector { tcx, items: Default::default() } + DiagnosticItemCollector { tcx, diagnostic_items: DiagnosticItems::default() } } fn observe_item(&mut self, def_id: LocalDefId) { @@ -52,19 +51,14 @@ impl<'tcx> DiagnosticItemCollector<'tcx> { let attrs = self.tcx.hir().attrs(hir_id); if let Some(name) = extract(attrs) { // insert into our table - collect_item(self.tcx, &mut self.items, name, def_id.to_def_id()); + collect_item(self.tcx, &mut self.diagnostic_items, name, def_id.to_def_id()); } } } -fn collect_item( - tcx: TyCtxt<'_>, - items: &mut FxHashMap, - name: Symbol, - item_def_id: DefId, -) { - // Check for duplicates. - if let Some(original_def_id) = items.insert(name, item_def_id) { +fn collect_item(tcx: TyCtxt<'_>, items: &mut DiagnosticItems, name: Symbol, item_def_id: DefId) { + items.id_to_name.insert(item_def_id, name); + if let Some(original_def_id) = items.name_to_id.insert(name, item_def_id) { if original_def_id != item_def_id { let mut err = match tcx.hir().span_if_local(item_def_id) { Some(span) => tcx.sess.struct_span_err( @@ -98,31 +92,31 @@ fn extract(attrs: &[ast::Attribute]) -> Option { } /// Traverse and collect the diagnostic items in the current -fn diagnostic_items<'tcx>(tcx: TyCtxt<'tcx>, cnum: CrateNum) -> FxHashMap { +fn diagnostic_items<'tcx>(tcx: TyCtxt<'tcx>, cnum: CrateNum) -> DiagnosticItems { assert_eq!(cnum, LOCAL_CRATE); // Initialize the collector. let mut collector = DiagnosticItemCollector::new(tcx); // Collect diagnostic items in this crate. - tcx.hir().krate().visit_all_item_likes(&mut collector); + tcx.hir().visit_all_item_likes(&mut collector); - collector.items + collector.diagnostic_items } /// Traverse and collect all the diagnostic items in all crates. -fn all_diagnostic_items<'tcx>(tcx: TyCtxt<'tcx>, (): ()) -> FxHashMap { +fn all_diagnostic_items<'tcx>(tcx: TyCtxt<'tcx>, (): ()) -> DiagnosticItems { // Initialize the collector. - let mut collector = FxHashMap::default(); + let mut items = DiagnosticItems::default(); // Collect diagnostic items in other crates. for &cnum in tcx.crates(()).iter().chain(std::iter::once(&LOCAL_CRATE)) { - for (&name, &def_id) in tcx.diagnostic_items(cnum).iter() { - collect_item(tcx, &mut collector, name, def_id); + for (&name, &def_id) in &tcx.diagnostic_items(cnum).name_to_id { + collect_item(tcx, &mut items, name, def_id); } } - collector + items } pub fn provide(providers: &mut Providers) { diff --git a/compiler/rustc_passes/src/entry.rs b/compiler/rustc_passes/src/entry.rs index e881a855bb..63f9b3ed6b 100644 --- a/compiler/rustc_passes/src/entry.rs +++ b/compiler/rustc_passes/src/entry.rs @@ -1,6 +1,6 @@ use rustc_ast::entry::EntryPointType; use rustc_errors::struct_span_err; -use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE}; +use rustc_hir::def_id::{DefId, CRATE_DEF_ID, CRATE_DEF_INDEX, LOCAL_CRATE}; use rustc_hir::itemlikevisit::ItemLikeVisitor; use rustc_hir::{ForeignItem, HirId, ImplItem, Item, ItemKind, Node, TraitItem, CRATE_HIR_ID}; use rustc_middle::hir::map::Map; @@ -68,7 +68,7 @@ fn entry_fn(tcx: TyCtxt<'_>, (): ()) -> Option<(DefId, EntryFnType)> { non_main_fns: Vec::new(), }; - tcx.hir().krate().visit_all_item_likes(&mut ctxt); + tcx.hir().visit_all_item_likes(&mut ctxt); configure_main(tcx, &ctxt) } @@ -183,7 +183,7 @@ fn configure_main(tcx: TyCtxt<'_>, visitor: &EntryContext<'_, '_>) -> Option<(De } fn no_main_err(tcx: TyCtxt<'_>, visitor: &EntryContext<'_, '_>) { - let sp = tcx.hir().krate().module().inner; + let sp = tcx.def_span(CRATE_DEF_ID); if *tcx.sess.parse_sess.reached_eof.borrow() { // There's an unclosed brace that made the parser reach `Eof`, we shouldn't complain about // the missing `fn main()` then as it might have been hidden inside an unclosed block. diff --git a/compiler/rustc_passes/src/hir_id_validator.rs b/compiler/rustc_passes/src/hir_id_validator.rs index 944a3097a6..0e60ca9f90 100644 --- a/compiler/rustc_passes/src/hir_id_validator.rs +++ b/compiler/rustc_passes/src/hir_id_validator.rs @@ -1,5 +1,5 @@ use rustc_data_structures::fx::FxHashSet; -use rustc_data_structures::sync::{par_iter, Lock, ParallelIterator}; +use rustc_data_structures::sync::Lock; use rustc_hir as hir; use rustc_hir::def_id::{LocalDefId, CRATE_DEF_INDEX}; use rustc_hir::intravisit; @@ -11,12 +11,16 @@ use rustc_middle::ty::TyCtxt; pub fn check_crate(tcx: TyCtxt<'_>) { tcx.dep_graph.assert_ignored(); + if tcx.sess.opts.debugging_opts.hir_stats { + crate::hir_stats::print_hir_stats(tcx); + } + let errors = Lock::new(Vec::new()); let hir_map = tcx.hir(); - par_iter(&hir_map.krate().modules).for_each(|(&module_id, _)| { + hir_map.par_for_each_module(|module_id| { hir_map - .visit_item_likes_in_module(module_id, &mut OuterVisitor { hir_map, errors: &errors }); + .visit_item_likes_in_module(module_id, &mut OuterVisitor { hir_map, errors: &errors }) }); let errors = errors.into_inner(); @@ -159,14 +163,14 @@ impl<'a, 'hir> intravisit::Visitor<'hir> for HirIdValidator<'a, 'hir> { self.hir_ids_seen.insert(hir_id.local_id); } - fn visit_impl_item_ref(&mut self, _: &'hir hir::ImplItemRef<'hir>) { + fn visit_impl_item_ref(&mut self, _: &'hir hir::ImplItemRef) { // Explicitly do nothing here. ImplItemRefs contain hir::Visibility // values that actually belong to an ImplItem instead of the ItemKind::Impl // we are currently in. So for those it's correct that they have a // different owner. } - fn visit_foreign_item_ref(&mut self, _: &'hir hir::ForeignItemRef<'hir>) { + fn visit_foreign_item_ref(&mut self, _: &'hir hir::ForeignItemRef) { // Explicitly do nothing here. ForeignItemRefs contain hir::Visibility // values that actually belong to an ForeignItem instead of the ItemKind::ForeignMod // we are currently in. So for those it's correct that they have a diff --git a/compiler/rustc_passes/src/hir_stats.rs b/compiler/rustc_passes/src/hir_stats.rs index b8ce973185..d665c12f76 100644 --- a/compiler/rustc_passes/src/hir_stats.rs +++ b/compiler/rustc_passes/src/hir_stats.rs @@ -9,6 +9,7 @@ use rustc_hir as hir; use rustc_hir::intravisit as hir_visit; use rustc_hir::HirId; use rustc_middle::hir::map::Map; +use rustc_middle::ty::TyCtxt; use rustc_middle::util::common::to_readable_str; use rustc_span::Span; @@ -25,18 +26,19 @@ struct NodeData { } struct StatCollector<'k> { - krate: Option<&'k hir::Crate<'k>>, + krate: Option>, data: FxHashMap<&'static str, NodeData>, seen: FxHashSet, } -pub fn print_hir_stats(krate: &hir::Crate<'_>) { +pub fn print_hir_stats(tcx: TyCtxt<'_>) { let mut collector = StatCollector { - krate: Some(krate), + krate: Some(tcx.hir()), data: FxHashMap::default(), seen: FxHashSet::default(), }; - hir_visit::walk_crate(&mut collector, krate); + tcx.hir().walk_toplevel_module(&mut collector); + tcx.hir().walk_attributes(&mut collector); collector.print("HIR STATS"); } diff --git a/compiler/rustc_passes/src/intrinsicck.rs b/compiler/rustc_passes/src/intrinsicck.rs index 96e9a40df3..008b856ebf 100644 --- a/compiler/rustc_passes/src/intrinsicck.rs +++ b/compiler/rustc_passes/src/intrinsicck.rs @@ -141,6 +141,7 @@ impl ExprVisitor<'tcx> { template: &[InlineAsmTemplatePiece], is_input: bool, tied_input: Option<(&hir::Expr<'tcx>, Option)>, + target_features: &[Symbol], ) -> Option { // Check the type against the allowed types for inline asm. let ty = self.typeck_results.expr_ty_adjusted(expr); @@ -283,17 +284,20 @@ impl ExprVisitor<'tcx> { }; // Check whether the selected type requires a target feature. Note that - // this is different from the feature check we did earlier in AST - // lowering. While AST lowering checked that this register class is - // usable at all with the currently enabled features, some types may - // only be usable with a register class when a certain feature is - // enabled. We check this here since it depends on the results of typeck. + // this is different from the feature check we did earlier. While the + // previous check checked that this register class is usable at all + // with the currently enabled features, some types may only be usable + // with a register class when a certain feature is enabled. We check + // this here since it depends on the results of typeck. // // Also note that this check isn't run when the operand type is never - // (!). In that case we still need the earlier check in AST lowering to - // verify that the register class is usable at all. + // (!). In that case we still need the earlier check to verify that the + // register class is usable at all. if let Some(feature) = feature { - if !self.tcx.sess.target_features.contains(&Symbol::intern(feature)) { + let feat_sym = Symbol::intern(feature); + if !self.tcx.sess.target_features.contains(&feat_sym) + && !target_features.contains(&feat_sym) + { let msg = &format!("`{}` target feature is not enabled", feature); let mut err = self.tcx.sess.struct_span_err(expr.span, msg); err.note(&format!( @@ -349,23 +353,122 @@ impl ExprVisitor<'tcx> { Some(asm_ty) } - fn check_asm(&self, asm: &hir::InlineAsm<'tcx>) { - for (idx, (op, _)) in asm.operands.iter().enumerate() { + fn check_asm(&self, asm: &hir::InlineAsm<'tcx>, hir_id: hir::HirId) { + let hir = self.tcx.hir(); + let enclosing_id = hir.enclosing_body_owner(hir_id); + let enclosing_def_id = hir.local_def_id(enclosing_id).to_def_id(); + let attrs = self.tcx.codegen_fn_attrs(enclosing_def_id); + for (idx, (op, op_sp)) in asm.operands.iter().enumerate() { + // Validate register classes against currently enabled target + // features. We check that at least one type is available for + // the enabled features. + // + // We ignore target feature requirements for clobbers: if the + // feature is disabled then the compiler doesn't care what we + // do with the registers. + // + // Note that this is only possible for explicit register + // operands, which cannot be used in the asm string. + if let Some(reg) = op.reg() { + if !op.is_clobber() { + let mut missing_required_features = vec![]; + let reg_class = reg.reg_class(); + for &(_, feature) in reg_class.supported_types(self.tcx.sess.asm_arch.unwrap()) + { + match feature { + Some(feature) => { + let feat_sym = Symbol::intern(feature); + if self.tcx.sess.target_features.contains(&feat_sym) + || attrs.target_features.contains(&feat_sym) + { + missing_required_features.clear(); + break; + } else { + missing_required_features.push(feature); + } + } + None => { + missing_required_features.clear(); + break; + } + } + } + + // We are sorting primitive strs here and can use unstable sort here + missing_required_features.sort_unstable(); + missing_required_features.dedup(); + match &missing_required_features[..] { + [] => {} + [feature] => { + let msg = format!( + "register class `{}` requires the `{}` target feature", + reg_class.name(), + feature + ); + self.tcx.sess.struct_span_err(*op_sp, &msg).emit(); + // register isn't enabled, don't do more checks + continue; + } + features => { + let msg = format!( + "register class `{}` requires at least one of the following target features: {}", + reg_class.name(), + features.join(", ") + ); + self.tcx.sess.struct_span_err(*op_sp, &msg).emit(); + // register isn't enabled, don't do more checks + continue; + } + } + } + } + match *op { hir::InlineAsmOperand::In { reg, ref expr } => { - self.check_asm_operand_type(idx, reg, expr, asm.template, true, None); + self.check_asm_operand_type( + idx, + reg, + expr, + asm.template, + true, + None, + &attrs.target_features, + ); } hir::InlineAsmOperand::Out { reg, late: _, ref expr } => { if let Some(expr) = expr { - self.check_asm_operand_type(idx, reg, expr, asm.template, false, None); + self.check_asm_operand_type( + idx, + reg, + expr, + asm.template, + false, + None, + &attrs.target_features, + ); } } hir::InlineAsmOperand::InOut { reg, late: _, ref expr } => { - self.check_asm_operand_type(idx, reg, expr, asm.template, false, None); + self.check_asm_operand_type( + idx, + reg, + expr, + asm.template, + false, + None, + &attrs.target_features, + ); } hir::InlineAsmOperand::SplitInOut { reg, late: _, ref in_expr, ref out_expr } => { - let in_ty = - self.check_asm_operand_type(idx, reg, in_expr, asm.template, true, None); + let in_ty = self.check_asm_operand_type( + idx, + reg, + in_expr, + asm.template, + true, + None, + &attrs.target_features, + ); if let Some(out_expr) = out_expr { self.check_asm_operand_type( idx, @@ -374,6 +477,7 @@ impl ExprVisitor<'tcx> { asm.template, false, Some((in_expr, in_ty)), + &attrs.target_features, ); } } @@ -422,7 +526,7 @@ impl Visitor<'tcx> for ExprVisitor<'tcx> { } } - hir::ExprKind::InlineAsm(asm) => self.check_asm(asm), + hir::ExprKind::InlineAsm(asm) => self.check_asm(asm, expr.hir_id), _ => {} } diff --git a/compiler/rustc_passes/src/lang_items.rs b/compiler/rustc_passes/src/lang_items.rs index 77ff8dc5b4..388c33917c 100644 --- a/compiler/rustc_passes/src/lang_items.rs +++ b/compiler/rustc_passes/src/lang_items.rs @@ -10,9 +10,6 @@ use crate::check_attr::target_from_impl_item; use crate::weak_lang_items; -use rustc_middle::middle::cstore::ExternCrate; -use rustc_middle::ty::TyCtxt; - use rustc_ast::Attribute; use rustc_errors::{pluralize, struct_span_err}; use rustc_hir as hir; @@ -20,6 +17,8 @@ use rustc_hir::def_id::DefId; use rustc_hir::itemlikevisit::ItemLikeVisitor; use rustc_hir::lang_items::{extract, GenericRequirement, ITEM_REFS}; use rustc_hir::{HirId, LangItem, LanguageItems, Target}; +use rustc_middle::ty::TyCtxt; +use rustc_session::cstore::ExternCrate; use rustc_span::Span; use rustc_middle::ty::query::Providers; @@ -262,7 +261,7 @@ fn get_lang_items(tcx: TyCtxt<'_>, (): ()) -> LanguageItems { } // Collect lang items in this crate. - tcx.hir().krate().visit_all_item_likes(&mut collector); + tcx.hir().visit_all_item_likes(&mut collector); // Extract out the found lang items. let LanguageItemCollector { mut items, .. } = collector; diff --git a/compiler/rustc_passes/src/layout_test.rs b/compiler/rustc_passes/src/layout_test.rs index 64ea4ee570..558d8958b1 100644 --- a/compiler/rustc_passes/src/layout_test.rs +++ b/compiler/rustc_passes/src/layout_test.rs @@ -3,15 +3,16 @@ use rustc_hir as hir; use rustc_hir::def_id::LocalDefId; use rustc_hir::itemlikevisit::ItemLikeVisitor; use rustc_hir::ItemKind; -use rustc_middle::ty::layout::{HasParamEnv, HasTyCtxt, TyAndLayout}; +use rustc_middle::ty::layout::{HasParamEnv, HasTyCtxt, LayoutError, LayoutOfHelpers, TyAndLayout}; use rustc_middle::ty::{ParamEnv, Ty, TyCtxt}; use rustc_span::symbol::sym; -use rustc_target::abi::{HasDataLayout, LayoutOf, TargetDataLayout}; +use rustc_span::Span; +use rustc_target::abi::{HasDataLayout, TargetDataLayout}; pub fn test_layout(tcx: TyCtxt<'_>) { if tcx.features().rustc_attrs { // if the `rustc_attrs` feature is not enabled, don't bother testing layout - tcx.hir().krate().visit_all_item_likes(&mut LayoutTest { tcx }); + tcx.hir().visit_all_item_likes(&mut LayoutTest { tcx }); } } @@ -113,12 +114,16 @@ struct UnwrapLayoutCx<'tcx> { param_env: ParamEnv<'tcx>, } -impl LayoutOf<'tcx> for UnwrapLayoutCx<'tcx> { - type Ty = Ty<'tcx>; - type TyAndLayout = TyAndLayout<'tcx>; +impl LayoutOfHelpers<'tcx> for UnwrapLayoutCx<'tcx> { + type LayoutOfResult = TyAndLayout<'tcx>; - fn layout_of(&self, ty: Ty<'tcx>) -> Self::TyAndLayout { - self.tcx.layout_of(self.param_env.and(ty)).unwrap() + fn handle_layout_err(&self, err: LayoutError<'tcx>, span: Span, ty: Ty<'tcx>) -> ! { + span_bug!( + span, + "`#[rustc_layout(..)]` test resulted in `layout_of({}) = Err({})`", + ty, + err + ); } } diff --git a/compiler/rustc_passes/src/lib.rs b/compiler/rustc_passes/src/lib.rs index f583a5d58d..4adec3c4f6 100644 --- a/compiler/rustc_passes/src/lib.rs +++ b/compiler/rustc_passes/src/lib.rs @@ -9,8 +9,9 @@ #![feature(in_band_lifetimes)] #![feature(format_args_capture)] #![feature(iter_zip)] -#![feature(nll)] +#![feature(map_try_insert)] #![feature(min_specialization)] +#![feature(nll)] #![feature(try_blocks)] #![recursion_limit = "256"] diff --git a/compiler/rustc_passes/src/lib_features.rs b/compiler/rustc_passes/src/lib_features.rs index 7d15ca1e8f..ff8bd37238 100644 --- a/compiler/rustc_passes/src/lib_features.rs +++ b/compiler/rustc_passes/src/lib_features.rs @@ -6,7 +6,7 @@ use rustc_ast::{Attribute, MetaItem, MetaItemKind}; use rustc_errors::struct_span_err; -use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; +use rustc_hir::intravisit::{NestedVisitorMap, Visitor}; use rustc_middle::hir::map::Map; use rustc_middle::middle::lib_features::LibFeatures; use rustc_middle::ty::query::Providers; @@ -126,9 +126,7 @@ impl Visitor<'tcx> for LibFeatureCollector<'tcx> { fn get_lib_features(tcx: TyCtxt<'_>, (): ()) -> LibFeatures { let mut collector = LibFeatureCollector::new(tcx); - let krate = tcx.hir().krate(); - - intravisit::walk_crate(&mut collector, krate); + tcx.hir().walk_attributes(&mut collector); collector.lib_features } diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs index ab9bfea969..3d7a215754 100644 --- a/compiler/rustc_passes/src/liveness.rs +++ b/compiler/rustc_passes/src/liveness.rs @@ -265,12 +265,13 @@ impl IrMaps<'tcx> { self.capture_info_map.insert(hir_id, Rc::new(cs)); } - fn add_from_pat(&mut self, pat: &hir::Pat<'tcx>) { + fn collect_shorthand_field_ids(&self, pat: &hir::Pat<'tcx>) -> HirIdSet { // For struct patterns, take note of which fields used shorthand // (`x` rather than `x: x`). let mut shorthand_field_ids = HirIdSet::default(); let mut pats = VecDeque::new(); pats.push_back(pat); + while let Some(pat) = pats.pop_front() { use rustc_hir::PatKind::*; match &pat.kind { @@ -278,8 +279,10 @@ impl IrMaps<'tcx> { pats.extend(inner_pat.iter()); } Struct(_, fields, _) => { - let ids = fields.iter().filter(|f| f.is_shorthand).map(|f| f.pat.hir_id); - shorthand_field_ids.extend(ids); + let (short, not_short): (Vec<&_>, Vec<&_>) = + fields.iter().partition(|f| f.is_shorthand); + shorthand_field_ids.extend(short.iter().map(|f| f.pat.hir_id)); + pats.extend(not_short.iter().map(|f| f.pat)); } Ref(inner_pat, _) | Box(inner_pat) => { pats.push_back(inner_pat); @@ -296,6 +299,12 @@ impl IrMaps<'tcx> { } } + return shorthand_field_ids; + } + + fn add_from_pat(&mut self, pat: &hir::Pat<'tcx>) { + let shorthand_field_ids = self.collect_shorthand_field_ids(pat); + pat.each_binding(|_, hir_id, _, ident| { self.add_live_node_for_node(hir_id, VarDefNode(ident.span, hir_id)); self.add_variable(Local(LocalInfo { @@ -373,15 +382,13 @@ impl<'tcx> Visitor<'tcx> for IrMaps<'tcx> { } fn visit_param(&mut self, param: &'tcx hir::Param<'tcx>) { + let shorthand_field_ids = self.collect_shorthand_field_ids(param.pat); param.pat.each_binding(|_bm, hir_id, _x, ident| { let var = match param.pat.kind { - rustc_hir::PatKind::Struct(_, fields, _) => Local(LocalInfo { + rustc_hir::PatKind::Struct(..) => Local(LocalInfo { id: hir_id, name: ident.name, - is_shorthand: fields - .iter() - .find(|f| f.ident == ident) - .map_or(false, |f| f.is_shorthand), + is_shorthand: shorthand_field_ids.contains(&hir_id), }), _ => Param(hir_id, ident.name), }; @@ -775,7 +782,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { if blk.targeted_by_break { self.break_ln.insert(blk.hir_id, succ); } - let succ = self.propagate_through_opt_expr(blk.expr.as_deref(), succ); + let succ = self.propagate_through_opt_expr(blk.expr, succ); blk.stmts.iter().rev().fold(succ, |succ, stmt| self.propagate_through_stmt(stmt, succ)) } @@ -796,7 +803,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { // initialization, which is mildly more complex than checking // once at the func header but otherwise equivalent. - let succ = self.propagate_through_opt_expr(local.init.as_deref(), succ); + let succ = self.propagate_through_opt_expr(local.init, succ); self.define_bindings_in_pat(&local.pat, succ) } hir::StmtKind::Item(..) => succ, diff --git a/compiler/rustc_passes/src/reachable.rs b/compiler/rustc_passes/src/reachable.rs index 23f43233b7..bd1e9520ee 100644 --- a/compiler/rustc_passes/src/reachable.rs +++ b/compiler/rustc_passes/src/reachable.rs @@ -427,7 +427,7 @@ fn reachable_set<'tcx>(tcx: TyCtxt<'tcx>, (): ()) -> FxHashSet { access_levels, worklist: &mut reachable_context.worklist, }; - tcx.hir().krate().visit_all_item_likes(&mut collect_private_impl_items); + tcx.hir().visit_all_item_likes(&mut collect_private_impl_items); } // Step 2: Mark all symbols that the symbols on the worklist touch. diff --git a/compiler/rustc_passes/src/region.rs b/compiler/rustc_passes/src/region.rs index 08702cad41..5fc8e230d7 100644 --- a/compiler/rustc_passes/src/region.rs +++ b/compiler/rustc_passes/src/region.rs @@ -812,7 +812,7 @@ impl<'tcx> Visitor<'tcx> for RegionResolutionVisitor<'tcx> { resolve_expr(self, ex); } fn visit_local(&mut self, l: &'tcx Local<'tcx>) { - resolve_local(self, Some(&l.pat), l.init.as_deref()); + resolve_local(self, Some(&l.pat), l.init); } } diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs index a88393cea8..8c9f04bef1 100644 --- a/compiler/rustc_passes/src/stability.rs +++ b/compiler/rustc_passes/src/stability.rs @@ -8,6 +8,7 @@ use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, CRATE_DEF_INDEX, LOCAL_CRATE}; +use rustc_hir::hir_id::CRATE_HIR_ID; use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc_hir::{FieldDef, Generics, HirId, Item, TraitRef, Ty, TyKind, Variant}; use rustc_middle::hir::map::Map; @@ -678,7 +679,6 @@ fn stability_index(tcx: TyCtxt<'tcx>, (): ()) -> Index<'tcx> { .collect(); { - let krate = tcx.hir().krate(); let mut annotator = Annotator { tcx, index: &mut index, @@ -711,13 +711,13 @@ fn stability_index(tcx: TyCtxt<'tcx>, (): ()) -> Index<'tcx> { annotator.annotate( CRATE_DEF_ID, - krate.module().inner, + tcx.hir().span(CRATE_HIR_ID), None, AnnotationKind::Required, InheritDeprecation::Yes, InheritConstStability::No, InheritStability::No, - |v| intravisit::walk_crate(v, krate), + |v| tcx.hir().walk_toplevel_module(v), ); } index @@ -906,11 +906,10 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) { let access_levels = &tcx.privacy_access_levels(()); if tcx.stability().staged_api[&LOCAL_CRATE] { - let krate = tcx.hir().krate(); let mut missing = MissingStabilityAnnotations { tcx, access_levels }; - missing.check_missing_stability(CRATE_DEF_ID, krate.module().inner); - intravisit::walk_crate(&mut missing, krate); - krate.visit_all_item_likes(&mut missing.as_deep_visitor()); + missing.check_missing_stability(CRATE_DEF_ID, tcx.hir().span(CRATE_HIR_ID)); + tcx.hir().walk_toplevel_module(&mut missing); + tcx.hir().visit_all_item_likes(&mut missing.as_deep_visitor()); } let declared_lang_features = &tcx.features().declared_lang_features; @@ -929,6 +928,16 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) { let declared_lib_features = &tcx.features().declared_lib_features; let mut remaining_lib_features = FxHashMap::default(); for (feature, span) in declared_lib_features { + if !tcx.sess.opts.unstable_features.is_nightly_build() { + struct_span_err!( + tcx.sess, + *span, + E0554, + "`#![feature]` may not be used on the {} release channel", + env!("CFG_RELEASE_CHANNEL") + ) + .emit(); + } if remaining_lib_features.contains_key(&feature) { // Warn if the user enables a lib feature multiple times. duplicate_feature_err(tcx.sess, *span, *feature); diff --git a/compiler/rustc_passes/src/weak_lang_items.rs b/compiler/rustc_passes/src/weak_lang_items.rs index 3a662a9bab..c6c32e69aa 100644 --- a/compiler/rustc_passes/src/weak_lang_items.rs +++ b/compiler/rustc_passes/src/weak_lang_items.rs @@ -33,7 +33,7 @@ pub fn check_crate<'tcx>(tcx: TyCtxt<'tcx>, items: &mut lang_items::LanguageItem { let mut cx = Context { tcx, items }; - tcx.hir().krate().visit_all_item_likes(&mut cx.as_deep_visitor()); + tcx.hir().visit_all_item_likes(&mut cx.as_deep_visitor()); } verify(tcx, items); } @@ -66,8 +66,8 @@ fn verify<'tcx>(tcx: TyCtxt<'tcx>, items: &lang_items::LanguageItems) { tcx.sess.err("`#[panic_handler]` function required, but not found"); } else if item == LangItem::Oom { if !tcx.features().default_alloc_error_handler { - tcx.sess.err("`#[alloc_error_handler]` function required, but not found."); - tcx.sess.note_without_error("Use `#![feature(default_alloc_error_handler)]` for a default error handler."); + tcx.sess.err("`#[alloc_error_handler]` function required, but not found"); + tcx.sess.note_without_error("Use `#![feature(default_alloc_error_handler)]` for a default error handler"); } } else { tcx.sess.err(&format!("language item required, but not found: `{}`", name)); diff --git a/compiler/rustc_plugin_impl/Cargo.toml b/compiler/rustc_plugin_impl/Cargo.toml index c8eaca0703..4e666e7e93 100644 --- a/compiler/rustc_plugin_impl/Cargo.toml +++ b/compiler/rustc_plugin_impl/Cargo.toml @@ -2,7 +2,7 @@ name = "rustc_plugin_impl" version = "0.0.0" build = false -edition = "2018" +edition = "2021" [lib] doctest = false diff --git a/compiler/rustc_plugin_impl/src/load.rs b/compiler/rustc_plugin_impl/src/load.rs index 51cf85f794..c21075a443 100644 --- a/compiler/rustc_plugin_impl/src/load.rs +++ b/compiler/rustc_plugin_impl/src/load.rs @@ -4,7 +4,7 @@ use crate::Registry; use rustc_ast::Crate; use rustc_errors::struct_span_err; use rustc_metadata::locator; -use rustc_middle::middle::cstore::MetadataLoader; +use rustc_session::cstore::MetadataLoader; use rustc_session::Session; use rustc_span::symbol::{sym, Ident}; use rustc_span::Span; diff --git a/compiler/rustc_privacy/Cargo.toml b/compiler/rustc_privacy/Cargo.toml index 6ac2915c34..d952e288a6 100644 --- a/compiler/rustc_privacy/Cargo.toml +++ b/compiler/rustc_privacy/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustc_privacy" version = "0.0.0" -edition = "2018" +edition = "2021" [dependencies] rustc_middle = { path = "../rustc_middle" } diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 9c376c6c93..ae3a9c71c5 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -19,8 +19,8 @@ use rustc_hir::{AssocItemKind, HirIdSet, Node, PatKind}; use rustc_middle::bug; use rustc_middle::hir::map::Map; use rustc_middle::middle::privacy::{AccessLevel, AccessLevels}; -use rustc_middle::mir::abstract_const::Node as ACNode; 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}; @@ -470,7 +470,7 @@ impl EmbargoVisitor<'tcx> { let hir_id = self.tcx.hir().local_def_id_to_hir_id(local_def_id); let attrs = self.tcx.hir().attrs(hir_id); - if attr::find_transparency(&attrs, md.macro_rules).0 != Transparency::Opaque { + if attr::find_transparency(attrs, md.macro_rules).0 != Transparency::Opaque { return; } @@ -743,7 +743,9 @@ impl Visitor<'tcx> for EmbargoVisitor<'tcx> { } hir::ItemKind::Impl(ref impl_) => { for impl_item_ref in impl_.items { - if impl_.of_trait.is_some() || impl_item_ref.vis.node.is_pub() { + if impl_.of_trait.is_some() + || self.tcx.visibility(impl_item_ref.id.def_id) == ty::Visibility::Public + { self.update(impl_item_ref.id.def_id, item_level); } } @@ -768,7 +770,7 @@ impl Visitor<'tcx> for EmbargoVisitor<'tcx> { } hir::ItemKind::ForeignMod { items, .. } => { for foreign_item in items { - if foreign_item.vis.node.is_pub() { + if self.tcx.visibility(foreign_item.id.def_id) == ty::Visibility::Public { self.update(foreign_item.id.def_id, item_level); } } @@ -795,7 +797,7 @@ impl Visitor<'tcx> for EmbargoVisitor<'tcx> { // Re-exports are handled in `visit_mod`. However, in order to avoid looping over // all of the items of a mod in `visit_mod` looking for use statements, we handle // making sure that intermediate use statements have their visibilities updated here. - hir::ItemKind::Use(ref path, _) => { + hir::ItemKind::Use(path, _) => { if item_level.is_some() { self.update_visibility_of_intermediate_use_statements(path.segments.as_ref()); } @@ -1097,11 +1099,11 @@ impl<'tcx> Visitor<'tcx> for NamePrivacyVisitor<'tcx> { } fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) { - if let hir::ExprKind::Struct(ref qpath, fields, ref base) = expr.kind { + if let hir::ExprKind::Struct(qpath, fields, ref base) = expr.kind { let res = self.typeck_results().qpath_res(qpath, expr.hir_id); let adt = self.typeck_results().expr_ty(expr).ty_adt_def().unwrap(); let variant = adt.variant_of_res(res); - if let Some(ref base) = *base { + if let Some(base) = *base { // If the expression uses FRU we need to make sure all the unmentioned fields // are checked for privacy (RFC 736). Rather than computing the set of // unmentioned fields, just check them all. @@ -1310,7 +1312,7 @@ impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> { return; } match expr.kind { - hir::ExprKind::Assign(_, ref rhs, _) | hir::ExprKind::Match(ref rhs, ..) => { + hir::ExprKind::Assign(_, rhs, _) | hir::ExprKind::Match(rhs, ..) => { // Do not report duplicate errors for `x = y` and `match x { ... }`. if self.check_expr_pat_type(rhs.hir_id, rhs.span) { return; @@ -1395,7 +1397,7 @@ impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> { } fn visit_local(&mut self, local: &'tcx hir::Local<'tcx>) { - if let Some(ref init) = local.init { + if let Some(init) = local.init { if self.check_expr_pat_type(init.hir_id, init.span) { // Do not report duplicate errors for `let x = y`. return; @@ -1472,7 +1474,7 @@ impl<'a, 'tcx> ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> { // .. and it corresponds to a private type in the AST (this returns // `None` for type parameters). match self.tcx.hir().find(self.tcx.hir().local_def_id_to_hir_id(did)) { - Some(Node::Item(ref item)) => !item.vis.node.is_pub(), + Some(Node::Item(item)) => !item.vis.node.is_pub(), Some(_) | None => false, } } else { @@ -1488,7 +1490,7 @@ impl<'a, 'tcx> ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> { fn check_generic_bound(&mut self, bound: &hir::GenericBound<'_>) { if let hir::GenericBound::Trait(ref trait_ref, _) = *bound { - if self.path_is_private_type(&trait_ref.trait_ref.path) { + if self.path_is_private_type(trait_ref.trait_ref.path) { self.old_error_set.insert(trait_ref.trait_ref.hir_ref_id); } } @@ -1515,7 +1517,7 @@ impl<'a, 'b, 'tcx, 'v> Visitor<'v> for ObsoleteCheckTypeForPrivatenessVisitor<'a } fn visit_ty(&mut self, ty: &hir::Ty<'_>) { - if let hir::TyKind::Path(hir::QPath::Resolved(_, ref path)) = ty.kind { + if let hir::TyKind::Path(hir::QPath::Resolved(_, path)) = ty.kind { if self.inner.path_is_private_type(path) { self.contains_private = true; // Found what we're looking for, so let's stop working. @@ -1554,7 +1556,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> { // namespace (the contents have their own privacies). hir::ItemKind::ForeignMod { .. } => {} - hir::ItemKind::Trait(.., ref bounds, _) => { + hir::ItemKind::Trait(.., bounds, _) => { if !self.trait_is_public(item.def_id) { return; } @@ -1584,7 +1586,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> { at_outer_type: true, outer_type_is_public_path: false, }; - visitor.visit_ty(&impl_.self_ty); + visitor.visit_ty(impl_.self_ty); self_contains_private = visitor.contains_private; self_is_public_path = visitor.outer_type_is_public_path; } @@ -1662,12 +1664,12 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> { // // Those in 2. are warned via walk_generics and this // call here. - intravisit::walk_path(self, &tr.path); + intravisit::walk_path(self, tr.path); // Those in 3. are warned with this call. for impl_item_ref in impl_.items { let impl_item = self.tcx.hir().impl_item(impl_item_ref.id); - if let hir::ImplItemKind::TyAlias(ref ty) = impl_item.kind { + if let hir::ImplItemKind::TyAlias(ty) = impl_item.kind { self.visit_ty(ty); } } @@ -1678,7 +1680,10 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> { // methods will be visible as `Public::foo`. let mut found_pub_static = false; for impl_item_ref in impl_.items { - if self.item_is_public(impl_item_ref.id.def_id, &impl_item_ref.vis) { + if self.access_levels.is_reachable(impl_item_ref.id.def_id) + || self.tcx.visibility(impl_item_ref.id.def_id) + == ty::Visibility::Public + { let impl_item = self.tcx.hir().impl_item(impl_item_ref.id); match impl_item_ref.kind { AssocItemKind::Const => { @@ -1734,7 +1739,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> { } hir::WherePredicate::RegionPredicate(_) => {} hir::WherePredicate::EqPredicate(eq_pred) => { - self.visit_ty(&eq_pred.rhs_ty); + self.visit_ty(eq_pred.rhs_ty); } } } @@ -1747,7 +1752,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> { } fn visit_ty(&mut self, t: &'tcx hir::Ty<'tcx>) { - if let hir::TyKind::Path(hir::QPath::Resolved(_, ref path)) = t.kind { + if let hir::TyKind::Path(hir::QPath::Resolved(_, path)) = t.kind { if self.path_is_private_type(path) { self.old_error_set.insert(t.hir_id); } @@ -2169,7 +2174,7 @@ fn privacy_access_levels(tcx: TyCtxt<'_>, (): ()) -> &AccessLevels { changed: false, }; loop { - intravisit::walk_crate(&mut visitor, tcx.hir().krate()); + tcx.hir().walk_toplevel_module(&mut visitor); if visitor.changed { visitor.changed = false; } else { @@ -2184,19 +2189,17 @@ fn privacy_access_levels(tcx: TyCtxt<'_>, (): ()) -> &AccessLevels { fn check_private_in_public(tcx: TyCtxt<'_>, (): ()) { let access_levels = tcx.privacy_access_levels(()); - let krate = tcx.hir().krate(); - let mut visitor = ObsoleteVisiblePrivateTypesVisitor { tcx, - access_levels: &access_levels, + access_levels, in_variant: false, old_error_set: Default::default(), }; - intravisit::walk_crate(&mut visitor, krate); + tcx.hir().walk_toplevel_module(&mut visitor); let has_pub_restricted = { let mut pub_restricted_visitor = PubRestrictedVisitor { tcx, has_pub_restricted: false }; - intravisit::walk_crate(&mut pub_restricted_visitor, krate); + tcx.hir().walk_toplevel_module(&mut pub_restricted_visitor); pub_restricted_visitor.has_pub_restricted }; @@ -2225,5 +2228,5 @@ fn check_private_in_public(tcx: TyCtxt<'_>, (): ()) { .filter_map(|hir_id| tcx.hir().opt_local_def_id(hir_id)) .collect(), }; - krate.visit_all_item_likes(&mut DeepVisitor::new(&mut visitor)); + tcx.hir().visit_all_item_likes(&mut DeepVisitor::new(&mut visitor)); } diff --git a/compiler/rustc_query_impl/Cargo.toml b/compiler/rustc_query_impl/Cargo.toml index 7c8dbe3424..89df3d4674 100644 --- a/compiler/rustc_query_impl/Cargo.toml +++ b/compiler/rustc_query_impl/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustc_query_impl" version = "0.0.0" -edition = "2018" +edition = "2021" [lib] doctest = false diff --git a/compiler/rustc_query_impl/src/keys.rs b/compiler/rustc_query_impl/src/keys.rs index ad621d66cd..3448928759 100644 --- a/compiler/rustc_query_impl/src/keys.rs +++ b/compiler/rustc_query_impl/src/keys.rs @@ -305,6 +305,16 @@ impl<'tcx> Key for ty::PolyTraitRef<'tcx> { } } +impl<'tcx> Key for ty::PolyExistentialTraitRef<'tcx> { + #[inline(always)] + fn query_crate_is_local(&self) -> bool { + self.def_id().krate == LOCAL_CRATE + } + fn default_span(&self, tcx: TyCtxt<'_>) -> Span { + tcx.def_span(self.def_id()) + } +} + impl<'tcx> Key for (ty::PolyTraitRef<'tcx>, ty::PolyTraitRef<'tcx>) { #[inline(always)] fn query_crate_is_local(&self) -> bool { @@ -450,3 +460,25 @@ impl<'tcx> Key for (ty::Predicate<'tcx>, traits::WellFormedLoc) { DUMMY_SP } } + +impl<'tcx> Key for (ty::PolyFnSig<'tcx>, &'tcx ty::List>) { + #[inline(always)] + fn query_crate_is_local(&self) -> bool { + true + } + + fn default_span(&self, _: TyCtxt<'_>) -> Span { + DUMMY_SP + } +} + +impl<'tcx> Key for (ty::Instance<'tcx>, &'tcx ty::List>) { + #[inline(always)] + fn query_crate_is_local(&self) -> bool { + true + } + + fn default_span(&self, tcx: TyCtxt<'_>) -> Span { + self.0.default_span(tcx) + } +} diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs index bb0e651115..e50a8c191a 100644 --- a/compiler/rustc_query_impl/src/lib.rs +++ b/compiler/rustc_query_impl/src/lib.rs @@ -20,10 +20,10 @@ 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::ich::StableHashingContext; use rustc_middle::ty::query::{query_keys, query_storage, query_stored, query_values}; use rustc_middle::ty::query::{Providers, QueryEngine}; use rustc_middle::ty::{self, TyCtxt}; +use rustc_query_system::ich::StableHashingContext; use rustc_span::Span; #[macro_use] diff --git a/compiler/rustc_query_impl/src/on_disk_cache.rs b/compiler/rustc_query_impl/src/on_disk_cache.rs index ee64f22618..48eb488792 100644 --- a/compiler/rustc_query_impl/src/on_disk_cache.rs +++ b/compiler/rustc_query_impl/src/on_disk_cache.rs @@ -1,13 +1,15 @@ use crate::QueryCtxt; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet}; -use rustc_data_structures::sync::{HashMapExt, Lock, Lrc, OnceCell}; +use rustc_data_structures::memmap::Mmap; +use rustc_data_structures::sync::{HashMapExt, Lock, Lrc, RwLock}; use rustc_data_structures::unhash::UnhashMap; use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, StableCrateId, LOCAL_CRATE}; use rustc_hir::definitions::DefPathHash; use rustc_index::vec::{Idx, IndexVec}; -use rustc_middle::dep_graph::{DepNode, DepNodeIndex, SerializedDepNodeIndex}; +use rustc_middle::dep_graph::{DepNodeIndex, SerializedDepNodeIndex}; use rustc_middle::mir::interpret::{AllocDecodingSession, AllocDecodingState}; use rustc_middle::mir::{self, interpret}; +use rustc_middle::thir; use rustc_middle::ty::codec::{RefDecodable, TyDecoder, TyEncoder}; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_query_system::dep_graph::DepContext; @@ -22,8 +24,7 @@ use rustc_span::hygiene::{ }; use rustc_span::source_map::{SourceMap, StableSourceFileId}; use rustc_span::CachingSourceMapView; -use rustc_span::{BytePos, ExpnData, ExpnHash, SourceFile, Span, DUMMY_SP}; -use std::collections::hash_map::Entry; +use rustc_span::{BytePos, ExpnData, ExpnHash, Pos, SourceFile, Span}; use std::mem; const TAG_FILE_FOOTER: u128 = 0xC0FFEE_C0FFEE_C0FFEE_C0FFEE_C0FFEE; @@ -32,6 +33,7 @@ const TAG_FILE_FOOTER: u128 = 0xC0FFEE_C0FFEE_C0FFEE_C0FFEE_C0FFEE; const TAG_FULL_SPAN: u8 = 0; // A partial span with no location information, encoded only with a `SyntaxContext` const TAG_PARTIAL_SPAN: u8 = 1; +const TAG_RELATIVE_SPAN: u8 = 2; const TAG_SYNTAX_CONTEXT: u8 = 0; const TAG_EXPN_DATA: u8 = 1; @@ -42,14 +44,12 @@ const TAG_EXPN_DATA: u8 = 1; /// any side effects that have been emitted during a query. pub struct OnDiskCache<'sess> { // The complete cache data in serialized form. - serialized_data: Vec, + serialized_data: RwLock>, // Collects all `QuerySideEffects` created during the current compilation // session. current_side_effects: Lock>, - cnum_map: OnceCell>, - source_map: &'sess SourceMap, file_index_to_stable_id: FxHashMap, @@ -84,27 +84,11 @@ pub struct OnDiskCache<'sess> { expn_data: UnhashMap, // Additional information used when decoding hygiene data. hygiene_context: HygieneDecodeContext, - // Maps `DefPathHash`es to their `RawDefId`s from the *previous* + // Maps `ExpnHash`es to their raw value from the *previous* // compilation session. This is used as an initial 'guess' when - // we try to map a `DefPathHash` to its `DefId` in the current compilation - // session. - foreign_def_path_hashes: UnhashMap, - // Likewise for ExpnId. + // we try to map an `ExpnHash` to its value in the current + // compilation session. foreign_expn_data: UnhashMap, - - // The *next* compilation sessison's `foreign_def_path_hashes` - at - // the end of our current compilation session, this will get written - // out to the `foreign_def_path_hashes` field of the `Footer`, which - // will become `foreign_def_path_hashes` of the next compilation session. - // This stores any `DefPathHash` that we may need to map to a `DefId` - // during the next compilation session. - latest_foreign_def_path_hashes: Lock>, - - // Caches all lookups of `DefPathHashes`, both for local and foreign - // definitions. A definition from the previous compilation session - // may no longer exist in the current compilation session, so - // we use `Option` so that we can cache a lookup failure. - def_path_hash_to_def_id_cache: Lock>>, } // This type is used only for serialization and deserialization. @@ -119,7 +103,6 @@ struct Footer { syntax_contexts: FxHashMap, // See `OnDiskCache.expn_data` expn_data: UnhashMap, - foreign_def_path_hashes: UnhashMap, foreign_expn_data: UnhashMap, } @@ -142,19 +125,6 @@ impl AbsoluteBytePos { } } -/// Represents a potentially invalid `DefId`. This is used during incremental -/// compilation to represent a `DefId` from the *previous* compilation session, -/// which may no longer be valid. This is used to help map a `DefPathHash` -/// to a `DefId` in the current compilation session. -#[derive(Encodable, Decodable, Copy, Clone, Debug)] -crate struct RawDefId { - // We deliberately do not use `CrateNum` and `DefIndex` - // here, since a crate/index from the previous compilation - // session may no longer exist. - pub krate: u32, - pub index: u32, -} - /// An `EncodedSourceFileId` is the same as a `StableSourceFileId` except that /// the source crate is represented as a [StableCrateId] instead of as a /// `CrateNum`. This way `EncodedSourceFileId` can be encoded and decoded @@ -167,8 +137,8 @@ struct EncodedSourceFileId { } impl EncodedSourceFileId { - fn translate(&self, cnum_map: &UnhashMap) -> StableSourceFileId { - let cnum = cnum_map[&self.stable_crate_id]; + fn translate(&self, tcx: TyCtxt<'_>) -> StableSourceFileId { + let cnum = tcx.stable_crate_id_to_crate_num(self.stable_crate_id); StableSourceFileId { file_name_hash: self.file_name_hash, cnum } } @@ -182,7 +152,8 @@ impl EncodedSourceFileId { } impl<'sess> rustc_middle::ty::OnDiskCache<'sess> for OnDiskCache<'sess> { - fn new(sess: &'sess Session, data: Vec, start_pos: usize) -> Self { + /// Creates a new `OnDiskCache` instance from the serialized data in `data`. + fn new(sess: &'sess Session, data: Mmap, start_pos: usize) -> Self { debug_assert!(sess.opts.incremental.is_some()); // Wrap in a scope so we can borrow `data`. @@ -204,10 +175,9 @@ impl<'sess> rustc_middle::ty::OnDiskCache<'sess> for OnDiskCache<'sess> { }; Self { - serialized_data: data, + serialized_data: RwLock::new(Some(data)), file_index_to_stable_id: footer.file_index_to_stable_id, file_index_to_file: Default::default(), - cnum_map: OnceCell::new(), source_map: sess.source_map(), current_side_effects: Default::default(), query_result_index: footer.query_result_index.into_iter().collect(), @@ -217,18 +187,14 @@ impl<'sess> rustc_middle::ty::OnDiskCache<'sess> for OnDiskCache<'sess> { expn_data: footer.expn_data, foreign_expn_data: footer.foreign_expn_data, hygiene_context: Default::default(), - foreign_def_path_hashes: footer.foreign_def_path_hashes, - latest_foreign_def_path_hashes: Default::default(), - def_path_hash_to_def_id_cache: Default::default(), } } fn new_empty(source_map: &'sess SourceMap) -> Self { Self { - serialized_data: Vec::new(), + serialized_data: RwLock::new(None), file_index_to_stable_id: Default::default(), file_index_to_file: Default::default(), - cnum_map: OnceCell::new(), source_map, current_side_effects: Default::default(), query_result_index: Default::default(), @@ -238,13 +204,27 @@ impl<'sess> rustc_middle::ty::OnDiskCache<'sess> for OnDiskCache<'sess> { expn_data: UnhashMap::default(), foreign_expn_data: UnhashMap::default(), hygiene_context: Default::default(), - foreign_def_path_hashes: Default::default(), - latest_foreign_def_path_hashes: Default::default(), - def_path_hash_to_def_id_cache: Default::default(), } } - fn serialize(&self, tcx: TyCtxt<'sess>, encoder: &mut FileEncoder) -> FileEncodeResult { + /// Execute all cache promotions and release the serialized backing Mmap. + /// + /// Cache promotions require invoking queries, which needs to read the serialized data. + /// In order to serialize the new on-disk cache, the former on-disk cache file needs to be + /// deleted, hence we won't be able to refer to its memmapped data. + fn drop_serialized_data(&self, tcx: TyCtxt<'tcx>) { + // Load everything into memory so we can write it out to the on-disk + // cache. The vast majority of cacheable query results should already + // be in memory, so this should be a cheap operation. + // Do this *before* we clone 'latest_foreign_def_path_hashes', since + // loading existing queries may cause us to create new DepNodes, which + // may in turn end up invoking `store_foreign_def_id_hash` + tcx.dep_graph.exec_cache_promotions(QueryCtxt::from_tcx(tcx)); + + *self.serialized_data.write() = None; + } + + fn serialize<'tcx>(&self, tcx: TyCtxt<'tcx>, encoder: &mut FileEncoder) -> FileEncodeResult { // Serializing the `DepGraph` should not modify it. tcx.dep_graph.with_ignore(|| { // Allocate `SourceFileIndex`es. @@ -266,22 +246,6 @@ impl<'sess> rustc_middle::ty::OnDiskCache<'sess> for OnDiskCache<'sess> { (file_to_file_index, file_index_to_stable_id) }; - // Register any dep nodes that we reused from the previous session, - // but didn't `DepNode::construct` in this session. This ensures - // that their `DefPathHash` to `RawDefId` mappings are registered - // in 'latest_foreign_def_path_hashes' if necessary, since that - // normally happens in `DepNode::construct`. - tcx.dep_graph.register_reused_dep_nodes(tcx); - - // Load everything into memory so we can write it out to the on-disk - // cache. The vast majority of cacheable query results should already - // be in memory, so this should be a cheap operation. - // Do this *before* we clone 'latest_foreign_def_path_hashes', since - // loading existing queries may cause us to create new DepNodes, which - // may in turn end up invoking `store_foreign_def_id_hash` - tcx.dep_graph.exec_cache_promotions(QueryCtxt::from_tcx(tcx)); - - let latest_foreign_def_path_hashes = self.latest_foreign_def_path_hashes.lock().clone(); let hygiene_encode_context = HygieneEncodeContext::default(); let mut encoder = CacheEncoder { @@ -293,7 +257,6 @@ impl<'sess> rustc_middle::ty::OnDiskCache<'sess> for OnDiskCache<'sess> { source_map: CachingSourceMapView::new(tcx.sess.source_map()), file_to_file_index, hygiene_context: &hygiene_encode_context, - latest_foreign_def_path_hashes, }; // Encode query results. @@ -370,9 +333,6 @@ impl<'sess> rustc_middle::ty::OnDiskCache<'sess> for OnDiskCache<'sess> { }, )?; - let foreign_def_path_hashes = - std::mem::take(&mut encoder.latest_foreign_def_path_hashes); - // `Encode the file footer. let footer_pos = encoder.position() as u64; encoder.encode_tagged( @@ -385,7 +345,6 @@ impl<'sess> rustc_middle::ty::OnDiskCache<'sess> for OnDiskCache<'sess> { syntax_contexts, expn_data, foreign_expn_data, - foreign_def_path_hashes, }, )?; @@ -400,81 +359,22 @@ impl<'sess> rustc_middle::ty::OnDiskCache<'sess> for OnDiskCache<'sess> { }) } - fn def_path_hash_to_def_id(&self, tcx: TyCtxt<'tcx>, hash: DefPathHash) -> Option { - let mut cache = self.def_path_hash_to_def_id_cache.lock(); - match cache.entry(hash) { - Entry::Occupied(e) => *e.get(), - Entry::Vacant(e) => { - debug!("def_path_hash_to_def_id({:?})", hash); - // Check if the `DefPathHash` corresponds to a definition in the current - // crate - if let Some(def_id) = - tcx.definitions_untracked().local_def_path_hash_to_def_id(hash) - { - let def_id = def_id.to_def_id(); - e.insert(Some(def_id)); - return Some(def_id); - } - // This `raw_def_id` represents the `DefId` of this `DefPathHash` in - // the *previous* compliation session. The `DefPathHash` includes the - // owning crate, so if the corresponding definition still exists in the - // current compilation session, the crate is guaranteed to be the same - // (otherwise, we would compute a different `DefPathHash`). - let raw_def_id = self.get_raw_def_id(&hash)?; - debug!("def_path_hash_to_def_id({:?}): raw_def_id = {:?}", hash, raw_def_id); - // If the owning crate no longer exists, the corresponding definition definitely - // no longer exists. - let krate = self.try_remap_cnum(tcx, hash.stable_crate_id())?; - debug!("def_path_hash_to_def_id({:?}): krate = {:?}", hash, krate); - // If our `DefPathHash` corresponded to a definition in the local crate, - // we should have either found it in `local_def_path_hash_to_def_id`, or - // never attempted to load it in the first place. Any query result or `DepNode` - // that references a local `DefId` should depend on some HIR-related `DepNode`. - // If a local definition is removed/modified such that its old `DefPathHash` - // no longer has a corresponding definition, that HIR-related `DepNode` should - // end up red. This should prevent us from ever calling - // `tcx.def_path_hash_to_def_id`, since we'll end up recomputing any - // queries involved. - debug_assert_ne!(krate, LOCAL_CRATE); - // Try to find a definition in the current session, using the previous `DefIndex` - // as an initial guess. - let opt_def_id = - tcx.cstore_untracked().def_path_hash_to_def_id(krate, raw_def_id.index, hash); - debug!("def_path_to_def_id({:?}): opt_def_id = {:?}", hash, opt_def_id); - e.insert(opt_def_id); - opt_def_id - } + fn 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) } } - - fn register_reused_dep_node(&self, tcx: TyCtxt<'sess>, dep_node: &DepNode) { - // For reused dep nodes, we only need to store the mapping if the node - // is one whose query key we can reconstruct from the hash. We use the - // mapping to aid that reconstruction in the next session. While we also - // use it to decode `DefId`s we encoded in the cache as `DefPathHashes`, - // they're already registered during `DefId` encoding. - if dep_node.kind.can_reconstruct_query_key() { - let hash = DefPathHash(dep_node.hash.into()); - - // We can't simply copy the `RawDefId` from `foreign_def_path_hashes` to - // `latest_foreign_def_path_hashes`, since the `RawDefId` might have - // changed in the current compilation session (e.g. we've added/removed crates, - // or added/removed definitions before/after the target definition). - if let Some(def_id) = self.def_path_hash_to_def_id(tcx, hash) { - if !def_id.is_local() { - self.store_foreign_def_id_hash(def_id, hash); - } - } - } - } - - fn store_foreign_def_id_hash(&self, def_id: DefId, hash: DefPathHash) { - // We may overwrite an existing entry, but it will have the same value, - // so it's fine - self.latest_foreign_def_path_hashes - .lock() - .insert(hash, RawDefId { krate: def_id.krate.as_u32(), index: def_id.index.as_u32() }); - } } impl<'sess> OnDiskCache<'sess> { @@ -505,17 +405,6 @@ impl<'sess> OnDiskCache<'sess> { debug_assert!(prev.is_none()); } - fn get_raw_def_id(&self, hash: &DefPathHash) -> Option { - self.foreign_def_path_hashes.get(hash).copied() - } - - fn try_remap_cnum(&self, tcx: TyCtxt<'_>, stable_crate_id: StableCrateId) -> Option { - let cnum_map = self.cnum_map.get_or_init(|| Self::compute_cnum_map(tcx)); - debug!("try_remap_cnum({:?}): cnum_map={:?}", stable_crate_id, cnum_map); - - cnum_map.get(&stable_crate_id).copied() - } - /// Returns the cached query result if there is something in the cache for /// the given `SerializedDepNodeIndex`; otherwise returns `None`. pub fn try_load_query_result<'tcx, T>( @@ -564,7 +453,7 @@ impl<'sess> OnDiskCache<'sess> { }) } - fn with_decoder<'a, 'tcx, T, F: FnOnce(&mut CacheDecoder<'sess, 'tcx>) -> T>( + fn with_decoder<'a, 'tcx, T, F: for<'s> FnOnce(&mut CacheDecoder<'s, 'tcx>) -> T>( &'sess self, tcx: TyCtxt<'tcx>, pos: AbsoluteBytePos, @@ -573,13 +462,11 @@ impl<'sess> OnDiskCache<'sess> { where T: Decodable>, { - let cnum_map = self.cnum_map.get_or_init(|| Self::compute_cnum_map(tcx)); - + let serialized_data = self.serialized_data.read(); let mut decoder = CacheDecoder { tcx, - opaque: opaque::Decoder::new(&self.serialized_data[..], pos.to_usize()), + opaque: opaque::Decoder::new(serialized_data.as_deref().unwrap_or(&[]), pos.to_usize()), source_map: self.source_map, - cnum_map, file_index_to_file: &self.file_index_to_file, file_index_to_stable_id: &self.file_index_to_stable_id, alloc_decoding_session: self.alloc_decoding_state.new_decoding_session(), @@ -590,23 +477,6 @@ impl<'sess> OnDiskCache<'sess> { }; f(&mut decoder) } - - // This function builds mapping from previous-session-`CrateNum` to - // current-session-`CrateNum`. There might be `CrateNum`s from the previous - // `Session` that don't occur in the current one. For these, the mapping - // maps to None. - fn compute_cnum_map(tcx: TyCtxt<'_>) -> UnhashMap { - tcx.dep_graph.with_ignore(|| { - tcx.crates(()) - .iter() - .chain(std::iter::once(&LOCAL_CRATE)) - .map(|&cnum| { - let hash = tcx.def_path_hash(cnum.as_def_id()).stable_crate_id(); - (hash, cnum) - }) - .collect() - }) - } } //- DECODING ------------------------------------------------------------------- @@ -618,7 +488,6 @@ pub struct CacheDecoder<'a, 'tcx> { tcx: TyCtxt<'tcx>, opaque: opaque::Decoder<'a>, source_map: &'a SourceMap, - cnum_map: &'a UnhashMap, file_index_to_file: &'a Lock>>, file_index_to_stable_id: &'a FxHashMap, alloc_decoding_session: AllocDecodingSession<'a>, @@ -631,10 +500,10 @@ pub struct CacheDecoder<'a, 'tcx> { impl<'a, 'tcx> CacheDecoder<'a, 'tcx> { fn file_index_to_file(&self, index: SourceFileIndex) -> Lrc { let CacheDecoder { + tcx, ref file_index_to_file, ref file_index_to_stable_id, ref source_map, - ref cnum_map, .. } = *self; @@ -642,7 +511,7 @@ impl<'a, 'tcx> CacheDecoder<'a, 'tcx> { .borrow_mut() .entry(index) .or_insert_with(|| { - let stable_id = file_index_to_stable_id[&index].translate(cnum_map); + let stable_id = file_index_to_stable_id[&index].translate(tcx); source_map .source_file_by_stable_id(stable_id) .expect("failed to lookup `SourceFile` in new context") @@ -784,7 +653,7 @@ impl<'a, 'tcx> Decodable> for ExpnId { return Ok(expn_id); } - let krate = decoder.cnum_map[&hash.stable_crate_id()]; + let krate = decoder.tcx.stable_crate_id_to_crate_num(hash.stable_crate_id()); let expn_id = if krate == LOCAL_CRATE { // We look up the position of the associated `ExpnData` and decode it. @@ -795,33 +664,58 @@ impl<'a, 'tcx> Decodable> for ExpnId { let data: ExpnData = decoder .with_position(pos.to_usize(), |decoder| decode_tagged(decoder, TAG_EXPN_DATA))?; - rustc_span::hygiene::register_local_expn_id(data, hash) + let expn_id = rustc_span::hygiene::register_local_expn_id(data, hash); + + #[cfg(debug_assertions)] + { + use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; + let mut hcx = decoder.tcx.create_stable_hashing_context(); + let mut hasher = StableHasher::new(); + hcx.while_hashing_spans(true, |hcx| { + expn_id.expn_data().hash_stable(hcx, &mut hasher) + }); + let local_hash: u64 = hasher.finish(); + debug_assert_eq!(hash.local_hash(), local_hash); + } + + expn_id } else { let index_guess = decoder.foreign_expn_data[&hash]; - decoder.tcx.cstore_untracked().expn_hash_to_expn_id(krate, index_guess, hash) + decoder.tcx.cstore_untracked().expn_hash_to_expn_id( + decoder.tcx.sess, + krate, + index_guess, + hash, + ) }; - #[cfg(debug_assertions)] - { - use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; - let mut hcx = decoder.tcx.create_stable_hashing_context(); - let mut hasher = StableHasher::new(); - hcx.while_hashing_spans(true, |hcx| expn_id.expn_data().hash_stable(hcx, &mut hasher)); - let local_hash: u64 = hasher.finish(); - debug_assert_eq!(hash.local_hash(), local_hash); - } - + debug_assert_eq!(expn_id.krate, krate); Ok(expn_id) } } impl<'a, 'tcx> Decodable> for Span { fn decode(decoder: &mut CacheDecoder<'a, 'tcx>) -> Result { + let ctxt = SyntaxContext::decode(decoder)?; + let parent = Option::::decode(decoder)?; let tag: u8 = Decodable::decode(decoder)?; if tag == TAG_PARTIAL_SPAN { - let ctxt = SyntaxContext::decode(decoder)?; - return Ok(DUMMY_SP.with_ctxt(ctxt)); + return Ok(Span::new(BytePos(0), BytePos(0), ctxt, parent)); + } else if tag == TAG_RELATIVE_SPAN { + let dlo = u32::decode(decoder)?; + let dto = u32::decode(decoder)?; + + let enclosing = + decoder.tcx.definitions_untracked().def_span(parent.unwrap()).data_untracked(); + let span = Span::new( + enclosing.lo + BytePos::from_u32(dlo), + enclosing.lo + BytePos::from_u32(dto), + ctxt, + parent, + ); + + return Ok(span); } else { debug_assert_eq!(tag, TAG_FULL_SPAN); } @@ -830,20 +724,19 @@ impl<'a, 'tcx> Decodable> for Span { let line_lo = usize::decode(decoder)?; let col_lo = BytePos::decode(decoder)?; let len = BytePos::decode(decoder)?; - let ctxt = SyntaxContext::decode(decoder)?; let file_lo = decoder.file_index_to_file(file_lo_index); let lo = file_lo.lines[line_lo - 1] + col_lo; let hi = lo + len; - Ok(Span::new(lo, hi, ctxt)) + Ok(Span::new(lo, hi, ctxt, parent)) } } impl<'a, 'tcx> Decodable> for CrateNum { fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Result { let stable_id = StableCrateId::decode(d)?; - let cnum = d.cnum_map[&stable_id]; + let cnum = d.tcx.stable_crate_id_to_crate_num(stable_id); Ok(cnum) } } @@ -871,12 +764,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) - .unwrap()) + Ok(d.tcx().on_disk_cache.as_ref().unwrap().def_path_hash_to_def_id(d.tcx(), def_path_hash)) } } @@ -894,7 +782,7 @@ impl<'a, 'tcx> Decodable> } } -impl<'a, 'tcx> Decodable> for &'tcx [mir::abstract_const::Node<'tcx>] { +impl<'a, 'tcx> Decodable> for &'tcx [thir::abstract_const::Node<'tcx>] { fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Result { RefDecodable::decode(d) } @@ -941,7 +829,6 @@ pub struct CacheEncoder<'a, 'tcx, E: OpaqueEncoder> { source_map: CachingSourceMapView<'tcx>, file_to_file_index: FxHashMap<*const SourceFile, SourceFileIndex>, hygiene_context: &'a HygieneEncodeContext, - latest_foreign_def_path_hashes: UnhashMap, } impl<'a, 'tcx, E> CacheEncoder<'a, 'tcx, E> @@ -996,10 +883,22 @@ where E: 'a + OpaqueEncoder, { fn encode(&self, s: &mut CacheEncoder<'a, 'tcx, E>) -> Result<(), E::Error> { - let span_data = self.data(); - if self.is_dummy() { - TAG_PARTIAL_SPAN.encode(s)?; - return span_data.ctxt.encode(s); + let span_data = self.data_untracked(); + span_data.ctxt.encode(s)?; + span_data.parent.encode(s)?; + + if span_data.is_dummy() { + return TAG_PARTIAL_SPAN.encode(s); + } + + if let Some(parent) = span_data.parent { + let enclosing = s.tcx.definitions_untracked().def_span(parent).data_untracked(); + if enclosing.contains(span_data) { + TAG_RELATIVE_SPAN.encode(s)?; + (span_data.lo - enclosing.lo).to_u32().encode(s)?; + (span_data.hi - enclosing.lo).to_u32().encode(s)?; + return Ok(()); + } } let pos = s.source_map.byte_pos_to_line_and_col(span_data.lo); @@ -1009,8 +908,7 @@ where }; if partial_span { - TAG_PARTIAL_SPAN.encode(s)?; - return span_data.ctxt.encode(s); + return TAG_PARTIAL_SPAN.encode(s); } let (file_lo, line_lo, col_lo) = pos.unwrap(); @@ -1023,8 +921,7 @@ where source_file_index.encode(s)?; line_lo.encode(s)?; col_lo.encode(s)?; - len.encode(s)?; - span_data.ctxt.encode(s) + len.encode(s) } } @@ -1064,17 +961,7 @@ where E: 'a + OpaqueEncoder, { fn encode(&self, s: &mut CacheEncoder<'a, 'tcx, E>) -> Result<(), E::Error> { - let def_path_hash = s.tcx.def_path_hash(*self); - // Store additional information when we encode a foreign `DefId`, - // so that we can map its `DefPathHash` back to a `DefId` in the next - // compilation session. - if !self.is_local() { - s.latest_foreign_def_path_hashes.insert( - def_path_hash, - RawDefId { krate: self.krate.as_u32(), index: self.index.as_u32() }, - ); - } - def_path_hash.encode(s) + s.tcx.def_path_hash(*self).encode(s) } } diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index 90a6ba474b..4d1e39db0e 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -36,7 +36,6 @@ impl<'tcx> std::ops::Deref for QueryCtxt<'tcx> { impl HasDepContext for QueryCtxt<'tcx> { type DepKind = rustc_middle::dep_graph::DepKind; - type StableHashingContext = rustc_middle::ich::StableHashingContext<'tcx>; type DepContext = TyCtxt<'tcx>; #[inline] @@ -253,17 +252,17 @@ macro_rules! handle_cycle_error { $error.emit(); Value::from_cycle_error($tcx) }}; - ([fatal_cycle $($rest:tt)*][$tcx:expr, $error:expr]) => {{ + ([(fatal_cycle) $($rest:tt)*][$tcx:expr, $error:expr]) => {{ $error.emit(); $tcx.sess.abort_if_errors(); unreachable!() }}; - ([cycle_delay_bug $($rest:tt)*][$tcx:expr, $error:expr]) => {{ + ([(cycle_delay_bug) $($rest:tt)*][$tcx:expr, $error:expr]) => {{ $error.delay_as_bug(); Value::from_cycle_error($tcx) }}; - ([$other:ident $(($($other_args:tt)*))* $(, $($modifiers:tt)*)*][$($args:tt)*]) => { - handle_cycle_error!([$($($modifiers)*)*][$($args)*]) + ([$other:tt $($modifiers:tt)*][$($args:tt)*]) => { + handle_cycle_error!([$($modifiers)*][$($args)*]) }; } @@ -271,11 +270,11 @@ macro_rules! is_anon { ([]) => {{ false }}; - ([anon $($rest:tt)*]) => {{ + ([(anon) $($rest:tt)*]) => {{ true }}; - ([$other:ident $(($($other_args:tt)*))* $(, $($modifiers:tt)*)*]) => { - is_anon!([$($($modifiers)*)*]) + ([$other:tt $($modifiers:tt)*]) => { + is_anon!([$($modifiers)*]) }; } @@ -283,11 +282,11 @@ macro_rules! is_eval_always { ([]) => {{ false }}; - ([eval_always $($rest:tt)*]) => {{ + ([(eval_always) $($rest:tt)*]) => {{ true }}; - ([$other:ident $(($($other_args:tt)*))* $(, $($modifiers:tt)*)*]) => { - is_eval_always!([$($($modifiers)*)*]) + ([$other:tt $($modifiers:tt)*]) => { + is_eval_always!([$($modifiers)*]) }; } @@ -295,11 +294,11 @@ macro_rules! hash_result { ([][$hcx:expr, $result:expr]) => {{ dep_graph::hash_result($hcx, &$result) }}; - ([no_hash $($rest:tt)*][$hcx:expr, $result:expr]) => {{ + ([(no_hash) $($rest:tt)*][$hcx:expr, $result:expr]) => {{ None }}; - ([$other:ident $(($($other_args:tt)*))* $(, $($modifiers:tt)*)*][$($args:tt)*]) => { - hash_result!([$($($modifiers)*)*][$($args)*]) + ([$other:tt $($modifiers:tt)*][$($args:tt)*]) => { + hash_result!([$($modifiers)*][$($args)*]) }; } @@ -321,10 +320,13 @@ macro_rules! define_queries { pub fn $name<$tcx>(tcx: QueryCtxt<$tcx>, key: query_keys::$name<$tcx>) -> QueryStackFrame { let kind = dep_graph::DepKind::$name; let name = stringify!($name); - let description = ty::print::with_forced_impl_filename_line( + // Disable visible paths printing for performance reasons. + // Showing visible path instead of any path is not that important in production. + let description = ty::print::with_no_visible_paths( + || ty::print::with_forced_impl_filename_line( // Force filename-line mode to avoid invoking `type_of` query. || queries::$name::describe(tcx, key) - ); + )); let description = if tcx.sess.verbose() { format!("{} [{}]", description, name) } else { @@ -426,6 +428,7 @@ macro_rules! define_queries { use rustc_middle::ty::query::query_keys; use rustc_query_system::dep_graph::DepNodeParams; use rustc_query_system::query::{force_query, QueryDescription}; + use rustc_query_system::dep_graph::FingerprintStyle; // We use this for most things when incr. comp. is turned off. pub const Null: QueryStruct = QueryStruct { @@ -452,9 +455,9 @@ macro_rules! define_queries { const is_anon: bool = is_anon!([$($modifiers)*]); #[inline(always)] - fn can_reconstruct_query_key() -> bool { + fn fingerprint_style() -> FingerprintStyle { as DepNodeParams>> - ::can_reconstruct_query_key() + ::fingerprint_style() } fn recover<'tcx>(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option> { @@ -470,7 +473,7 @@ macro_rules! define_queries { return } - if !can_reconstruct_query_key() { + if !fingerprint_style().reconstructible() { return } diff --git a/compiler/rustc_query_impl/src/stats.rs b/compiler/rustc_query_impl/src/stats.rs index fa48df3ed4..c3bbd51f3d 100644 --- a/compiler/rustc_query_impl/src/stats.rs +++ b/compiler/rustc_query_impl/src/stats.rs @@ -5,8 +5,6 @@ use rustc_query_system::query::{QueryCache, QueryCacheStore}; use std::any::type_name; use std::mem; -#[cfg(debug_assertions)] -use std::sync::atomic::Ordering; trait KeyStats { fn key_stats(&self, stats: &mut QueryStats); @@ -27,7 +25,6 @@ impl KeyStats for DefId { #[derive(Clone)] struct QueryStats { name: &'static str, - cache_hits: usize, key_size: usize, key_type: &'static str, value_size: usize, @@ -42,10 +39,6 @@ where { let mut stats = QueryStats { name, - #[cfg(debug_assertions)] - cache_hits: map.cache_hits.load(Ordering::Relaxed), - #[cfg(not(debug_assertions))] - cache_hits: 0, key_size: mem::size_of::(), key_type: type_name::(), value_size: mem::size_of::(), @@ -63,12 +56,6 @@ where pub fn print_stats(tcx: TyCtxt<'_>) { let queries = query_stats(tcx); - if cfg!(debug_assertions) { - let hits: usize = queries.iter().map(|s| s.cache_hits).sum(); - let results: usize = queries.iter().map(|s| s.entry_count).sum(); - eprintln!("\nQuery cache hit rate: {}", hits as f64 / (hits + results) as f64); - } - let mut query_key_sizes = queries.clone(); query_key_sizes.sort_by_key(|q| q.key_size); eprintln!("\nLarge query keys:"); @@ -83,20 +70,6 @@ pub fn print_stats(tcx: TyCtxt<'_>) { eprintln!(" {} - {} x {} - {}", q.name, q.value_size, q.entry_count, q.value_type); } - if cfg!(debug_assertions) { - let mut query_cache_hits = queries.clone(); - query_cache_hits.sort_by_key(|q| q.cache_hits); - eprintln!("\nQuery cache hits:"); - for q in query_cache_hits.iter().rev() { - eprintln!( - " {} - {} ({}%)", - q.name, - q.cache_hits, - q.cache_hits as f64 / (q.cache_hits + q.entry_count) as f64 - ); - } - } - let mut query_value_count = queries.clone(); query_value_count.sort_by_key(|q| q.entry_count); eprintln!("\nQuery value count:"); diff --git a/compiler/rustc_query_system/Cargo.toml b/compiler/rustc_query_system/Cargo.toml index 47fb78be64..898a8caa3c 100644 --- a/compiler/rustc_query_system/Cargo.toml +++ b/compiler/rustc_query_system/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustc_query_system" version = "0.0.0" -edition = "2018" +edition = "2021" [lib] doctest = false @@ -10,12 +10,16 @@ doctest = false rustc_arena = { path = "../rustc_arena" } tracing = "0.1" rustc-rayon-core = "0.3.1" +rustc_ast = { path = "../rustc_ast" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } -rustc_macros = { path = "../rustc_macros" } +rustc_feature = { path = "../rustc_feature" } +rustc_hir = { path = "../rustc_hir" } rustc_index = { path = "../rustc_index" } +rustc_macros = { path = "../rustc_macros" } rustc_serialize = { path = "../rustc_serialize" } rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } +rustc_target = { path = "../rustc_target" } parking_lot = "0.11" smallvec = { version = "1.6.1", features = ["union", "may_dangle"] } 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 59ef6052a6..8602219a7f 100644 --- a/compiler/rustc_query_system/src/dep_graph/dep_node.rs +++ b/compiler/rustc_query_system/src/dep_graph/dep_node.rs @@ -42,29 +42,17 @@ //! `DefId` it was computed from. In other cases, too much information gets //! lost during fingerprint computation. -use super::{DepContext, DepKind}; +use super::{DepContext, DepKind, FingerprintStyle}; +use crate::ich::StableHashingContext; use rustc_data_structures::fingerprint::{Fingerprint, PackedFingerprint}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; - use std::fmt; use std::hash::Hash; #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable)] pub struct DepNode { pub kind: K, - // Important - whenever a `DepNode` is constructed, we need to make - // sure to register a `DefPathHash -> DefId` mapping if needed. - // This is currently done in two places: - // - // * When a `DepNode::construct` is called, `arg.to_fingerprint()` - // is responsible for calling `OnDiskCache::store_foreign_def_id_hash` - // if needed - // * When we serialize the on-disk cache, `OnDiskCache::serialize` is - // responsible for calling `DepGraph::register_reused_dep_nodes`. - // - // FIXME: Enforce this by preventing manual construction of `DefNode` - // (e.g. add a `_priv: ()` field) pub hash: PackedFingerprint, } @@ -87,7 +75,7 @@ impl DepNode { #[cfg(debug_assertions)] { - if !kind.can_reconstruct_query_key() + if !kind.fingerprint_style().reconstructible() && (tcx.sess().opts.debugging_opts.incremental_info || tcx.sess().opts.debugging_opts.query_dep_graph) { @@ -106,7 +94,7 @@ impl fmt::Debug for DepNode { } pub trait DepNodeParams: fmt::Debug + Sized { - fn can_reconstruct_query_key() -> bool; + fn fingerprint_style() -> FingerprintStyle; /// This method turns the parameters of a DepNodeConstructor into an opaque /// Fingerprint to be used in DepNode. @@ -123,7 +111,7 @@ pub trait DepNodeParams: fmt::Debug + Sized { /// This method tries to recover the query key from the given `DepNode`, /// something which is needed when forcing `DepNode`s during red-green /// evaluation. The query system will only call this method if - /// `can_reconstruct_query_key()` is `true`. + /// `fingerprint_style()` is not `FingerprintStyle::Opaque`. /// It is always valid to return `None` here, in which case incremental /// compilation will treat the query as having changed instead of forcing it. fn recover(tcx: Ctxt, dep_node: &DepNode) -> Option; @@ -131,11 +119,11 @@ pub trait DepNodeParams: fmt::Debug + Sized { impl DepNodeParams for T where - T: HashStable + fmt::Debug, + T: for<'a> HashStable> + fmt::Debug, { #[inline] - default fn can_reconstruct_query_key() -> bool { - false + default fn fingerprint_style() -> FingerprintStyle { + FingerprintStyle::Opaque } default fn to_fingerprint(&self, tcx: Ctxt) -> Fingerprint { diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_query_system/src/dep_graph/graph.rs index 9c3dad8bd6..114d12fb90 100644 --- a/compiler/rustc_query_system/src/dep_graph/graph.rs +++ b/compiler/rustc_query_system/src/dep_graph/graph.rs @@ -1,3 +1,4 @@ +use parking_lot::Mutex; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::profiling::{EventId, QueryInvocationId, SelfProfilerRef}; @@ -7,10 +8,9 @@ use rustc_data_structures::steal::Steal; use rustc_data_structures::sync::{AtomicU32, AtomicU64, Lock, Lrc, Ordering}; use rustc_index::vec::IndexVec; use rustc_serialize::opaque::{FileEncodeResult, FileEncoder}; - -use parking_lot::Mutex; use smallvec::{smallvec, SmallVec}; use std::collections::hash_map::Entry; +use std::fmt::Debug; use std::hash::Hash; use std::marker::PhantomData; use std::sync::atomic::Ordering::Relaxed; @@ -18,6 +18,7 @@ use std::sync::atomic::Ordering::Relaxed; use super::query::DepGraphQuery; use super::serialized::{GraphEncoder, SerializedDepGraph, SerializedDepNodeIndex}; use super::{DepContext, DepKind, DepNode, HasDepContext, WorkProductId}; +use crate::ich::StableHashingContext; use crate::query::{QueryContext, QuerySideEffects}; #[cfg(debug_assertions)] @@ -95,9 +96,9 @@ struct DepGraphData { dep_node_debug: Lock, String>>, } -pub fn hash_result(hcx: &mut HashCtxt, result: &R) -> Option +pub fn hash_result(hcx: &mut StableHashingContext<'_>, result: &R) -> Option where - R: HashStable, + R: for<'a> HashStable>, { let mut stable_hasher = StableHasher::new(); result.hash_stable(hcx, &mut stable_hasher); @@ -208,82 +209,16 @@ impl DepGraph { /// `arg` parameter. /// /// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/incremental-compilation.html - pub fn with_task, A, R>( + pub fn with_task, A: Debug, R>( &self, key: DepNode, cx: Ctxt, arg: A, task: fn(Ctxt, A) -> R, - hash_result: impl FnOnce(&mut Ctxt::StableHashingContext, &R) -> Option, + hash_result: fn(&mut StableHashingContext<'_>, &R) -> Option, ) -> (R, DepNodeIndex) { - self.with_task_impl( - key, - cx, - arg, - task, - |_key| { - Some(TaskDeps { - #[cfg(debug_assertions)] - node: Some(_key), - reads: SmallVec::new(), - read_set: Default::default(), - phantom_data: PhantomData, - }) - }, - hash_result, - ) - } - - fn with_task_impl, A, R>( - &self, - key: DepNode, - cx: Ctxt, - arg: A, - task: fn(Ctxt, A) -> R, - create_task: fn(DepNode) -> Option>, - hash_result: impl FnOnce(&mut Ctxt::StableHashingContext, &R) -> Option, - ) -> (R, DepNodeIndex) { - if let Some(ref data) = self.data { - let dcx = cx.dep_context(); - let task_deps = create_task(key).map(Lock::new); - let result = K::with_deps(task_deps.as_ref(), || task(cx, arg)); - let edges = task_deps.map_or_else(|| smallvec![], |lock| lock.into_inner().reads); - - let mut hcx = dcx.create_stable_hashing_context(); - let hashing_timer = dcx.profiler().incr_result_hashing(); - let current_fingerprint = hash_result(&mut hcx, &result); - - let print_status = cfg!(debug_assertions) && dcx.sess().opts.debugging_opts.dep_tasks; - - // Get timer for profiling `DepNode` interning - let node_intern_timer = self - .node_intern_event_id - .map(|eid| dcx.profiler().generic_activity_with_event_id(eid)); - // Intern the new `DepNode`. - let (dep_node_index, prev_and_color) = data.current.intern_node( - dcx.profiler(), - &data.previous, - key, - edges, - current_fingerprint, - print_status, - ); - drop(node_intern_timer); - - hashing_timer.finish_with_query_invocation_id(dep_node_index.into()); - - if let Some((prev_index, color)) = prev_and_color { - debug_assert!( - data.colors.get(prev_index).is_none(), - "DepGraph::with_task() - Duplicate DepNodeColor \ - insertion for {:?}", - key - ); - - data.colors.insert(prev_index, color); - } - - (result, dep_node_index) + if self.is_fully_enabled() { + self.with_task_impl(key, cx, arg, task, hash_result) } else { // Incremental compilation is turned off. We just execute the task // without tracking. We still provide a dep-node index that uniquely @@ -293,6 +228,82 @@ impl DepGraph { } } + fn with_task_impl, A: Debug, R>( + &self, + key: DepNode, + cx: Ctxt, + arg: A, + task: fn(Ctxt, A) -> R, + hash_result: fn(&mut StableHashingContext<'_>, &R) -> Option, + ) -> (R, DepNodeIndex) { + // This function is only called when the graph is enabled. + let data = self.data.as_ref().unwrap(); + + // If the following assertion triggers, it can have two reasons: + // 1. Something is wrong with DepNode creation, either here or + // in `DepGraph::try_mark_green()`. + // 2. Two distinct query keys get mapped to the same `DepNode` + // (see for example #48923). + assert!( + !self.dep_node_exists(&key), + "forcing query with already existing `DepNode`\n\ + - query-key: {:?}\n\ + - dep-node: {:?}", + arg, + key + ); + + let task_deps = if key.kind.is_eval_always() { + None + } else { + Some(Lock::new(TaskDeps { + #[cfg(debug_assertions)] + node: Some(key), + reads: SmallVec::new(), + read_set: Default::default(), + phantom_data: PhantomData, + })) + }; + let result = K::with_deps(task_deps.as_ref(), || task(cx, arg)); + 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 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(), + &data.previous, + key, + edges, + current_fingerprint, + print_status, + ); + drop(node_intern_timer); + + hashing_timer.finish_with_query_invocation_id(dep_node_index.into()); + + if let Some((prev_index, color)) = prev_and_color { + debug_assert!( + data.colors.get(prev_index).is_none(), + "DepGraph::with_task() - Duplicate DepNodeColor \ + insertion for {:?}", + key + ); + + data.colors.insert(prev_index, color); + } + + (result, dep_node_index) + } + /// Executes something within an "anonymous" task, that is, a task the /// `DepNode` of which is determined by the list of inputs it read from. pub fn with_anon_task, OP, R>( @@ -357,19 +368,6 @@ impl DepGraph { } } - /// Executes something within an "eval-always" task which is a task - /// that runs whenever anything changes. - pub fn with_eval_always_task, A, R>( - &self, - key: DepNode, - cx: Ctxt, - arg: A, - task: fn(Ctxt, A) -> R, - hash_result: impl FnOnce(&mut Ctxt::StableHashingContext, &R) -> Option, - ) -> (R, DepNodeIndex) { - self.with_task_impl(key, cx, arg, task, |_| None, hash_result) - } - #[inline] pub fn read_index(&self, dep_node_index: DepNodeIndex) { if let Some(ref data) = self.data { @@ -484,22 +482,11 @@ impl DepGraph { None } - /// Try to read a node index for the node dep_node. + /// Try to mark a node index for the node dep_node. + /// /// A node will have an index, when it's already been marked green, or when we can mark it /// green. This function will mark the current task as a reader of the specified node, when /// a node index can be found for that node. - pub fn try_mark_green_and_read>( - &self, - tcx: Ctxt, - dep_node: &DepNode, - ) -> Option<(SerializedDepNodeIndex, DepNodeIndex)> { - self.try_mark_green(tcx, dep_node).map(|(prev_index, dep_node_index)| { - debug_assert!(self.is_green(&dep_node)); - self.read_index(dep_node_index); - (prev_index, dep_node_index) - }) - } - pub fn try_mark_green>( &self, tcx: Ctxt, @@ -773,20 +760,6 @@ impl DepGraph { } } - // Register reused dep nodes (i.e. nodes we've marked red or green) with the context. - pub fn register_reused_dep_nodes>(&self, tcx: Ctxt) { - let data = self.data.as_ref().unwrap(); - for prev_index in data.colors.values.indices() { - match data.colors.get(prev_index) { - Some(DepNodeColor::Red) | Some(DepNodeColor::Green(_)) => { - let dep_node = data.previous.index_to_node(prev_index); - tcx.register_reused_dep_node(&dep_node); - } - None => {} - } - } - } - pub fn print_incremental_info(&self) { if let Some(data) = &self.data { data.current.encoder.borrow().print_incremental_info( diff --git a/compiler/rustc_query_system/src/dep_graph/mod.rs b/compiler/rustc_query_system/src/dep_graph/mod.rs index 15e2633c4f..dcda572833 100644 --- a/compiler/rustc_query_system/src/dep_graph/mod.rs +++ b/compiler/rustc_query_system/src/dep_graph/mod.rs @@ -9,6 +9,7 @@ pub use graph::{hash_result, DepGraph, DepNodeColor, DepNodeIndex, TaskDeps, Wor pub use query::DepGraphQuery; pub use serialized::{SerializedDepGraph, SerializedDepNodeIndex}; +use crate::ich::StableHashingContext; use rustc_data_structures::profiling::SelfProfilerRef; use rustc_data_structures::sync::Lock; use rustc_serialize::{opaque::FileEncoder, Encodable}; @@ -19,16 +20,13 @@ use std::hash::Hash; pub trait DepContext: Copy { type DepKind: self::DepKind; - type StableHashingContext; /// Create a hashing context for hashing new results. - fn create_stable_hashing_context(&self) -> Self::StableHashingContext; + fn create_stable_hashing_context(&self) -> StableHashingContext<'_>; /// Access the DepGraph. fn dep_graph(&self) -> &DepGraph; - fn register_reused_dep_node(&self, dep_node: &DepNode); - /// Access the profiler. fn profiler(&self) -> &SelfProfilerRef; @@ -38,18 +36,13 @@ pub trait DepContext: Copy { pub trait HasDepContext: Copy { type DepKind: self::DepKind; - type StableHashingContext; - type DepContext: self::DepContext< - DepKind = Self::DepKind, - StableHashingContext = Self::StableHashingContext, - >; + type DepContext: self::DepContext; fn dep_context(&self) -> &Self::DepContext; } impl HasDepContext for T { type DepKind = T::DepKind; - type StableHashingContext = T::StableHashingContext; type DepContext = Self; fn dep_context(&self) -> &Self::DepContext { @@ -57,6 +50,27 @@ impl HasDepContext for T { } } +/// Describes the contents of the fingerprint generated by a given query. +#[derive(PartialEq, Eq, Copy, Clone)] +pub enum FingerprintStyle { + /// The fingerprint is actually a DefPathHash. + DefPathHash, + /// Query key was `()` or equivalent, so fingerprint is just zero. + Unit, + /// Some opaque hash. + Opaque, +} + +impl FingerprintStyle { + #[inline] + pub fn reconstructible(self) -> bool { + match self { + FingerprintStyle::DefPathHash | FingerprintStyle::Unit => true, + FingerprintStyle::Opaque => false, + } + } +} + /// Describe the different families of dependency nodes. pub trait DepKind: Copy + fmt::Debug + Eq + Hash + Send + Encodable + 'static { const NULL: Self; @@ -80,5 +94,5 @@ pub trait DepKind: Copy + fmt::Debug + Eq + Hash + Send + Encodable where OP: for<'a> FnOnce(Option<&'a Lock>>); - fn can_reconstruct_query_key(&self) -> bool; + 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 73c00fc49b..f5f67fcd0a 100644 --- a/compiler/rustc_query_system/src/dep_graph/serialized.rs +++ b/compiler/rustc_query_system/src/dep_graph/serialized.rs @@ -99,7 +99,7 @@ impl SerializedDepGraph { impl<'a, K: DepKind + Decodable>> Decodable> for SerializedDepGraph { - #[instrument(skip(d))] + #[instrument(level = "debug", skip(d))] fn decode(d: &mut opaque::Decoder<'a>) -> Result, String> { let start_position = d.position(); @@ -187,7 +187,7 @@ impl EncoderState { } } - #[instrument(skip(self, record_graph))] + #[instrument(level = "debug", skip(self, record_graph))] fn encode_node( &mut self, node: &NodeInfo, diff --git a/compiler/rustc_middle/src/ich/hcx.rs b/compiler/rustc_query_system/src/ich/hcx.rs similarity index 72% rename from compiler/rustc_middle/src/ich/hcx.rs rename to compiler/rustc_query_system/src/ich/hcx.rs index 32ccdafaeb..f2e935c59f 100644 --- a/compiler/rustc_middle/src/ich/hcx.rs +++ b/compiler/rustc_query_system/src/ich/hcx.rs @@ -1,21 +1,16 @@ use crate::ich; -use crate::middle::cstore::CrateStore; -use crate::ty::{fast_reject, TyCtxt}; - use rustc_ast as ast; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::sync::Lrc; use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::definitions::{DefPathHash, Definitions}; +use rustc_session::cstore::CrateStore; use rustc_session::Session; use rustc_span::source_map::SourceMap; use rustc_span::symbol::Symbol; -use rustc_span::{BytePos, CachingSourceMapView, SourceFile, SpanData}; - -use smallvec::SmallVec; -use std::cmp::Ord; +use rustc_span::{BytePos, CachingSourceMapView, SourceFile, Span, SpanData}; fn compute_ignored_attr_names() -> FxHashSet { debug_assert!(!ich::IGNORED_ATTRIBUTES.is_empty()); @@ -28,7 +23,6 @@ fn compute_ignored_attr_names() -> FxHashSet { /// things (e.g., each `DefId`/`DefPath` is only hashed once). #[derive(Clone)] pub struct StableHashingContext<'a> { - sess: &'a Session, definitions: &'a Definitions, cstore: &'a dyn CrateStore, pub(super) body_resolver: BodyResolver<'a>, @@ -78,7 +72,6 @@ impl<'a> StableHashingContext<'a> { !always_ignore_spans && !sess.opts.debugging_opts.incremental_ignore_spans; StableHashingContext { - sess, body_resolver: BodyResolver(krate), definitions, cstore, @@ -184,42 +177,15 @@ impl<'a> StableHashingContext<'a> { } } -/// Something that can provide a stable hashing context. -pub trait StableHashingContextProvider<'a> { - fn get_stable_hashing_context(&self) -> StableHashingContext<'a>; -} - -impl<'a, 'b, T: StableHashingContextProvider<'a>> StableHashingContextProvider<'a> for &'b T { - fn get_stable_hashing_context(&self) -> StableHashingContext<'a> { - (**self).get_stable_hashing_context() - } -} - -impl<'a, 'b, T: StableHashingContextProvider<'a>> StableHashingContextProvider<'a> for &'b mut T { - fn get_stable_hashing_context(&self) -> StableHashingContext<'a> { - (**self).get_stable_hashing_context() - } -} - -impl StableHashingContextProvider<'tcx> for TyCtxt<'tcx> { - fn get_stable_hashing_context(&self) -> StableHashingContext<'tcx> { - (*self).create_stable_hashing_context() - } -} - -impl<'a> StableHashingContextProvider<'a> for StableHashingContext<'a> { - fn get_stable_hashing_context(&self) -> StableHashingContext<'a> { - self.clone() - } -} - impl<'a> HashStable> for ast::NodeId { + #[inline] fn hash_stable(&self, _: &mut StableHashingContext<'a>, _: &mut StableHasher) { panic!("Node IDs should not appear in incremental state"); } } impl<'a> rustc_span::HashStableContext for StableHashingContext<'a> { + #[inline] fn hash_spans(&self) -> bool { self.hash_spans } @@ -229,6 +195,12 @@ impl<'a> rustc_span::HashStableContext for StableHashingContext<'a> { self.def_path_hash(def_id) } + #[inline] + fn def_span(&self, def_id: LocalDefId) -> Span { + self.definitions.def_span(def_id) + } + + #[inline] fn span_data_to_lines_and_cols( &mut self, span: &SpanData, @@ -237,40 +209,4 @@ impl<'a> rustc_span::HashStableContext for StableHashingContext<'a> { } } -impl rustc_session::HashStableContext for StableHashingContext<'a> {} - -pub fn hash_stable_trait_impls<'a>( - hcx: &mut StableHashingContext<'a>, - hasher: &mut StableHasher, - blanket_impls: &[DefId], - non_blanket_impls: &FxHashMap>, -) { - { - let mut blanket_impls: SmallVec<[_; 8]> = - blanket_impls.iter().map(|&def_id| hcx.def_path_hash(def_id)).collect(); - - if blanket_impls.len() > 1 { - blanket_impls.sort_unstable(); - } - - blanket_impls.hash_stable(hcx, hasher); - } - - { - let mut keys: SmallVec<[_; 8]> = - non_blanket_impls.keys().map(|k| (k, k.map_def(|d| hcx.def_path_hash(d)))).collect(); - keys.sort_unstable_by(|&(_, ref k1), &(_, ref k2)| k1.cmp(k2)); - keys.len().hash_stable(hcx, hasher); - for (key, ref stable_key) in keys { - stable_key.hash_stable(hcx, hasher); - let mut impls: SmallVec<[_; 8]> = - non_blanket_impls[key].iter().map(|&impl_id| hcx.def_path_hash(impl_id)).collect(); - - if impls.len() > 1 { - impls.sort_unstable(); - } - - impls.hash_stable(hcx, hasher); - } - } -} +impl<'a> rustc_session::HashStableContext for StableHashingContext<'a> {} diff --git a/compiler/rustc_middle/src/ich/impls_hir.rs b/compiler/rustc_query_system/src/ich/impls_hir.rs similarity index 80% rename from compiler/rustc_middle/src/ich/impls_hir.rs rename to compiler/rustc_query_system/src/ich/impls_hir.rs index 5dfd00bc6d..04eb263a97 100644 --- a/compiler/rustc_middle/src/ich/impls_hir.rs +++ b/compiler/rustc_query_system/src/ich/impls_hir.rs @@ -2,7 +2,6 @@ //! types in no particular order. use crate::ich::{NodeIdHashingMode, StableHashingContext}; -use rustc_attr as attr; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey}; use rustc_hir as hir; @@ -27,6 +26,7 @@ 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() { @@ -34,6 +34,7 @@ impl<'ctx> rustc_hir::HashStableContext for StableHashingContext<'ctx> { } } + #[inline] fn hash_reference_to_item(&mut self, id: hir::HirId, hasher: &mut StableHasher) { let hcx = self; @@ -42,6 +43,7 @@ impl<'ctx> rustc_hir::HashStableContext for StableHashingContext<'ctx> { }) } + #[inline] fn hash_hir_mod(&mut self, module: &hir::Mod<'_>, hasher: &mut StableHasher) { let hcx = self; let hir::Mod { inner: ref inner_span, ref item_ids } = *module; @@ -104,6 +106,7 @@ impl<'ctx> rustc_hir::HashStableContext for StableHashingContext<'ctx> { } } + #[inline] fn hash_hir_item_like(&mut self, f: F) { let prev_hash_node_ids = self.node_id_hashing_mode; self.node_id_hashing_mode = NodeIdHashingMode::Ignore; @@ -114,16 +117,8 @@ impl<'ctx> rustc_hir::HashStableContext for StableHashingContext<'ctx> { } } -impl<'a> ToStableHashKey> for hir::ItemLocalId { - type KeyType = hir::ItemLocalId; - - #[inline] - fn to_stable_hash_key(&self, _: &StableHashingContext<'a>) -> hir::ItemLocalId { - *self - } -} - impl<'a> HashStable> for hir::Body<'_> { + #[inline] fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { let hir::Body { params, value, generator_kind } = self; @@ -135,19 +130,6 @@ impl<'a> HashStable> for hir::Body<'_> { } } -impl<'a> ToStableHashKey> for hir::BodyId { - type KeyType = (DefPathHash, hir::ItemLocalId); - - #[inline] - fn to_stable_hash_key( - &self, - hcx: &StableHashingContext<'a>, - ) -> (DefPathHash, hir::ItemLocalId) { - let hir::BodyId { hir_id } = *self; - hir_id.to_stable_hash_key(hcx) - } -} - 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| { @@ -171,21 +153,3 @@ impl<'a> ToStableHashKey> for hir::TraitCandidate { ) } } - -impl<'hir> HashStable> for attr::InlineAttr { - fn hash_stable(&self, hcx: &mut StableHashingContext<'hir>, hasher: &mut StableHasher) { - mem::discriminant(self).hash_stable(hcx, hasher); - } -} - -impl<'hir> HashStable> for attr::InstructionSetAttr { - fn hash_stable(&self, hcx: &mut StableHashingContext<'hir>, hasher: &mut StableHasher) { - mem::discriminant(self).hash_stable(hcx, hasher); - } -} - -impl<'hir> HashStable> for attr::OptimizeAttr { - fn hash_stable(&self, hcx: &mut StableHashingContext<'hir>, hasher: &mut StableHasher) { - mem::discriminant(self).hash_stable(hcx, hasher); - } -} diff --git a/compiler/rustc_middle/src/ich/impls_syntax.rs b/compiler/rustc_query_system/src/ich/impls_syntax.rs similarity index 100% rename from compiler/rustc_middle/src/ich/impls_syntax.rs rename to compiler/rustc_query_system/src/ich/impls_syntax.rs diff --git a/compiler/rustc_middle/src/ich/mod.rs b/compiler/rustc_query_system/src/ich/mod.rs similarity index 74% rename from compiler/rustc_middle/src/ich/mod.rs rename to compiler/rustc_query_system/src/ich/mod.rs index c8fb2bf39c..54416902e5 100644 --- a/compiler/rustc_middle/src/ich/mod.rs +++ b/compiler/rustc_query_system/src/ich/mod.rs @@ -1,15 +1,11 @@ //! ICH - Incremental Compilation Hash -pub use self::hcx::{ - hash_stable_trait_impls, NodeIdHashingMode, StableHashingContext, StableHashingContextProvider, -}; +pub use self::hcx::{NodeIdHashingMode, StableHashingContext}; use rustc_span::symbol::{sym, Symbol}; mod hcx; - mod impls_hir; mod impls_syntax; -mod impls_ty; pub const IGNORED_ATTRIBUTES: &[Symbol] = &[ sym::cfg, diff --git a/compiler/rustc_query_system/src/lib.rs b/compiler/rustc_query_system/src/lib.rs index c205f0fb53..bc23de069b 100644 --- a/compiler/rustc_query_system/src/lib.rs +++ b/compiler/rustc_query_system/src/lib.rs @@ -1,3 +1,4 @@ +#![feature(assert_matches)] #![feature(bool_to_option)] #![feature(core_intrinsics)] #![feature(hash_raw_entry)] @@ -14,4 +15,5 @@ extern crate rustc_macros; pub mod cache; pub mod dep_graph; +pub mod ich; pub mod query; diff --git a/compiler/rustc_query_system/src/query/config.rs b/compiler/rustc_query_system/src/query/config.rs index d1e527dff9..76a165ed8e 100644 --- a/compiler/rustc_query_system/src/query/config.rs +++ b/compiler/rustc_query_system/src/query/config.rs @@ -2,6 +2,7 @@ use crate::dep_graph::DepNode; use crate::dep_graph::SerializedDepNodeIndex; +use crate::ich::StableHashingContext; use crate::query::caches::QueryCache; use crate::query::{QueryCacheStore, QueryContext, QueryState}; @@ -23,7 +24,7 @@ pub(crate) struct QueryVtable { pub dep_kind: CTX::DepKind, pub eval_always: bool, - pub hash_result: fn(&mut CTX::StableHashingContext, &V) -> Option, + pub hash_result: fn(&mut StableHashingContext<'_>, &V) -> Option, 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, @@ -39,7 +40,7 @@ impl QueryVtable { pub(crate) fn hash_result( &self, - hcx: &mut CTX::StableHashingContext, + hcx: &mut StableHashingContext<'_>, value: &V, ) -> Option { (self.hash_result)(hcx, value) @@ -74,10 +75,8 @@ pub trait QueryAccessors: QueryConfig { // 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 CTX::StableHashingContext, - result: &Self::Value, - ) -> Option; + fn hash_result(hcx: &mut StableHashingContext<'_>, result: &Self::Value) + -> Option; fn handle_cycle_error(tcx: CTX, diag: DiagnosticBuilder<'_>) -> Self::Value; } diff --git a/compiler/rustc_query_system/src/query/job.rs b/compiler/rustc_query_system/src/query/job.rs index c3fdf4fc22..98b2a450b1 100644 --- a/compiler/rustc_query_system/src/query/job.rs +++ b/compiler/rustc_query_system/src/query/job.rs @@ -143,6 +143,8 @@ impl QueryJobId where D: Copy + Clone + Eq + Hash, { + #[cold] + #[inline(never)] pub(super) fn find_cycle_in_stack( &self, query_map: QueryMap, diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs index 3f22de6fba..07d7205997 100644 --- a/compiler/rustc_query_system/src/query/plumbing.rs +++ b/compiler/rustc_query_system/src/query/plumbing.rs @@ -2,8 +2,7 @@ //! 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, DepNodeParams}; -use crate::dep_graph::{DepNodeIndex, SerializedDepNodeIndex}; +use crate::dep_graph::{DepContext, DepKind, DepNode, DepNodeIndex, DepNodeParams}; use crate::query::caches::QueryCache; use crate::query::config::{QueryDescription, QueryVtable, QueryVtableExt}; use crate::query::job::{ @@ -13,12 +12,12 @@ use crate::query::{QueryContext, QueryMap, QuerySideEffects, QueryStackFrame}; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::{FxHashMap, FxHasher}; +#[cfg(parallel_compiler)] +use rustc_data_structures::profiling::TimingGuard; 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; -#[cfg(not(parallel_compiler))] -use rustc_errors::DiagnosticBuilder; -use rustc_errors::{Diagnostic, FatalError}; +use rustc_errors::{DiagnosticBuilder, FatalError}; use rustc_span::{Span, DUMMY_SP}; use std::cell::Cell; use std::collections::hash_map::Entry; @@ -27,24 +26,15 @@ use std::hash::{Hash, Hasher}; use std::mem; use std::num::NonZeroU32; use std::ptr; -#[cfg(debug_assertions)] -use std::sync::atomic::{AtomicUsize, Ordering}; pub struct QueryCacheStore { cache: C, shards: Sharded, - #[cfg(debug_assertions)] - pub cache_hits: AtomicUsize, } impl Default for QueryCacheStore { fn default() -> Self { - Self { - cache: C::default(), - shards: Default::default(), - #[cfg(debug_assertions)] - cache_hits: AtomicUsize::new(0), - } + Self { cache: C::default(), shards: Default::default() } } } @@ -148,24 +138,21 @@ impl Default for QueryState { /// A type representing the responsibility to execute the job in the `job` field. /// This will poison the relevant query if dropped. -struct JobOwner<'tcx, D, C> +struct JobOwner<'tcx, D, K> where D: Copy + Clone + Eq + Hash, - C: QueryCache, + K: Eq + Hash + Clone, { - state: &'tcx QueryState, - cache: &'tcx QueryCacheStore, - key: C::Key, + state: &'tcx QueryState, + key: K, id: QueryJobId, } #[cold] #[inline(never)] -#[cfg(not(parallel_compiler))] fn mk_cycle( tcx: CTX, - root: QueryJobId, - span: Span, + error: CycleError, handle_cycle_error: fn(CTX, DiagnosticBuilder<'_>) -> V, cache: &dyn crate::query::QueryStorage, ) -> R @@ -174,20 +161,15 @@ where V: std::fmt::Debug, R: Clone, { - let error: CycleError = root.find_cycle_in_stack( - tcx.try_collect_active_jobs().unwrap(), - &tcx.current_query_job(), - span, - ); let error = report_cycle(tcx.dep_context().sess(), error); let value = handle_cycle_error(tcx, error); cache.store_nocache(value) } -impl<'tcx, D, C> JobOwner<'tcx, D, C> +impl<'tcx, D, K> JobOwner<'tcx, D, K> where D: Copy + Clone + Eq + Hash, - C: QueryCache, + K: Eq + Hash + Clone, { /// Either gets a `JobOwner` corresponding the query, allowing us to /// start executing the query, or returns with the result of the query. @@ -199,14 +181,13 @@ where /// for some compile-time benchmarks. #[inline(always)] fn try_start<'b, CTX>( - tcx: CTX, - state: &'b QueryState, - cache: &'b QueryCacheStore, + tcx: &'b CTX, + state: &'b QueryState, span: Span, - key: C::Key, + key: K, lookup: QueryLookup, - query: &QueryVtable, - ) -> TryGetJob<'b, CTX::DepKind, C> + dep_kind: CTX::DepKind, + ) -> TryGetJob<'b, CTX::DepKind, K> where CTX: QueryContext, { @@ -227,26 +208,24 @@ where let key = entry.key().clone(); entry.insert(QueryResult::Started(job)); - let global_id = QueryJobId::new(id, shard, query.dep_kind); - let owner = JobOwner { state, cache, id: global_id, key }; + let global_id = QueryJobId::new(id, shard, dep_kind); + let owner = JobOwner { state, id: global_id, key }; return TryGetJob::NotYetStarted(owner); } Entry::Occupied(mut entry) => { match entry.get_mut() { #[cfg(not(parallel_compiler))] QueryResult::Started(job) => { - let id = QueryJobId::new(job.id, shard, query.dep_kind); + let id = QueryJobId::new(job.id, shard, dep_kind); drop(state_lock); // If we are single-threaded we know that we have cycle error, // so we just return the error. - return TryGetJob::Cycle(mk_cycle( - tcx, - id, + return TryGetJob::Cycle(id.find_cycle_in_stack( + tcx.try_collect_active_jobs().unwrap(), + &tcx.current_query_job(), span, - query.handle_cycle_error, - &cache.cache, )); } #[cfg(parallel_compiler)] @@ -258,7 +237,6 @@ where // Get the latch out let latch = job.latch(); - let key = entry.key().clone(); drop(state_lock); @@ -266,30 +244,10 @@ where // thread. let result = latch.wait_on(tcx.current_query_job(), span); - if let Err(cycle) = result { - let cycle = report_cycle(tcx.dep_context().sess(), cycle); - let value = (query.handle_cycle_error)(tcx, cycle); - let value = cache.cache.store_nocache(value); - return TryGetJob::Cycle(value); + match result { + Ok(()) => TryGetJob::JobCompleted(query_blocked_prof_timer), + Err(cycle) => TryGetJob::Cycle(cycle), } - - let cached = cache - .cache - .lookup(cache, &key, |value, index| { - if unlikely!(tcx.dep_context().profiler().enabled()) { - tcx.dep_context().profiler().query_cache_hit(index.into()); - } - #[cfg(debug_assertions)] - { - cache.cache_hits.fetch_add(1, Ordering::Relaxed); - } - (value.clone(), index) - }) - .unwrap_or_else(|_| panic!("value must be in cache after waiting")); - - query_blocked_prof_timer.finish_with_query_invocation_id(cached.1.into()); - - return TryGetJob::JobCompleted(cached); } QueryResult::Poisoned => FatalError.raise(), } @@ -299,11 +257,18 @@ where /// Completes the query by updating the query cache with the `result`, /// signals the waiter and forgets the JobOwner, so it won't poison the query - fn complete(self, result: C::Value, dep_node_index: DepNodeIndex) -> C::Stored { + fn complete( + self, + cache: &QueryCacheStore, + result: C::Value, + dep_node_index: DepNodeIndex, + ) -> C::Stored + where + C: QueryCache, + { // We can move out of `self` here because we `mem::forget` it below let key = unsafe { ptr::read(&self.key) }; let state = self.state; - let cache = self.cache; // Forget ourself so our destructor won't poison the query mem::forget(self); @@ -330,19 +295,10 @@ where } } -fn with_diagnostics(f: F) -> (R, ThinVec) -where - F: FnOnce(Option<&Lock>>) -> R, -{ - let diagnostics = Lock::new(ThinVec::new()); - let result = f(Some(&diagnostics)); - (result, diagnostics.into_inner()) -} - -impl<'tcx, D, C> Drop for JobOwner<'tcx, D, C> +impl<'tcx, D, K> Drop for JobOwner<'tcx, D, K> where D: Copy + Clone + Eq + Hash, - C: QueryCache, + K: Eq + Hash + Clone, { #[inline(never)] #[cold] @@ -373,22 +329,22 @@ pub(crate) struct CycleError { } /// The result of `try_start`. -enum TryGetJob<'tcx, D, C> +enum TryGetJob<'tcx, D, K> where D: Copy + Clone + Eq + Hash, - C: QueryCache, + K: Eq + Hash + Clone, { /// The query is not yet started. Contains a guard to the cache eventually used to start it. - NotYetStarted(JobOwner<'tcx, D, C>), + NotYetStarted(JobOwner<'tcx, D, K>), /// The query was already completed. /// Returns the result of the query and its dep-node index /// if it succeeded or a cycle error if it failed. #[cfg(parallel_compiler)] - JobCompleted((C::Stored, DepNodeIndex)), + JobCompleted(TimingGuard<'tcx>), /// Trying to execute the query resulted in a cycle. - Cycle(C::Stored), + Cycle(CycleError), } /// Checks if the query is already computed and in the cache. @@ -412,10 +368,6 @@ where if unlikely!(tcx.profiler().enabled()) { tcx.profiler().query_cache_hit(index.into()); } - #[cfg(debug_assertions)] - { - cache.cache_hits.fetch_add(1, Ordering::Relaxed); - } tcx.dep_graph().read_index(index); on_hit(value) }) @@ -428,119 +380,142 @@ fn try_execute_query( span: Span, key: C::Key, lookup: QueryLookup, + dep_node: Option>, query: &QueryVtable, compute: fn(CTX::DepContext, C::Key) -> C::Value, -) -> C::Stored +) -> (C::Stored, Option) where C: QueryCache, - C::Key: DepNodeParams, + C::Key: Clone + DepNodeParams, CTX: QueryContext, { - let job = match JobOwner::<'_, CTX::DepKind, C>::try_start( - tcx, + match JobOwner::<'_, CTX::DepKind, C::Key>::try_start( + &tcx, state, - cache, span, key.clone(), lookup, - query, + query.dep_kind, ) { - TryGetJob::NotYetStarted(job) => job, - TryGetJob::Cycle(result) => return result, - #[cfg(parallel_compiler)] - TryGetJob::JobCompleted((v, index)) => { - tcx.dep_context().dep_graph().read_index(index); - return v; + TryGetJob::NotYetStarted(job) => { + let (result, dep_node_index) = execute_job(tcx, key, dep_node, query, job.id, compute); + let result = job.complete(cache, result, dep_node_index); + (result, Some(dep_node_index)) } - }; + TryGetJob::Cycle(error) => { + let result = mk_cycle(tcx, error, query.handle_cycle_error, &cache.cache); + (result, None) + } + #[cfg(parallel_compiler)] + TryGetJob::JobCompleted(query_blocked_prof_timer) => { + let (v, index) = cache + .cache + .lookup(cache, &key, |value, index| (value.clone(), index)) + .unwrap_or_else(|_| panic!("value must be in cache after waiting")); + if unlikely!(tcx.dep_context().profiler().enabled()) { + tcx.dep_context().profiler().query_cache_hit(index.into()); + } + query_blocked_prof_timer.finish_with_query_invocation_id(index.into()); + + (v, Some(index)) + } + } +} + +fn execute_job( + tcx: CTX, + key: K, + mut dep_node_opt: Option>, + query: &QueryVtable, + job_id: QueryJobId, + compute: fn(CTX::DepContext, K) -> V, +) -> (V, DepNodeIndex) +where + K: Clone + DepNodeParams, + V: Debug, + CTX: QueryContext, +{ let dep_graph = tcx.dep_context().dep_graph(); // 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, || compute(*tcx.dep_context(), key)); let dep_node_index = dep_graph.next_virtual_depnode_index(); prof_timer.finish_with_query_invocation_id(dep_node_index.into()); - return job.complete(result, dep_node_index); + return (result, dep_node_index); } - if query.anon { - let prof_timer = tcx.dep_context().profiler().query_provider(); + if !query.anon && !query.eval_always { + // `to_dep_node` is expensive for some `DepKind`s. + let dep_node = + dep_node_opt.get_or_insert_with(|| query.to_dep_node(*tcx.dep_context(), &key)); - let ((result, dep_node_index), diagnostics) = with_diagnostics(|diagnostics| { - tcx.start_query(job.id, diagnostics, || { - dep_graph.with_anon_task(*tcx.dep_context(), query.dep_kind, || { - compute(*tcx.dep_context(), key) - }) - }) - }); - - prof_timer.finish_with_query_invocation_id(dep_node_index.into()); - - dep_graph.read_index(dep_node_index); - - let side_effects = QuerySideEffects { diagnostics }; - - if unlikely!(!side_effects.is_empty()) { - tcx.store_side_effects_for_anon_node(dep_node_index, side_effects); - } - - return job.complete(result, dep_node_index); - } - - let dep_node = query.to_dep_node(*tcx.dep_context(), &key); - - if !query.eval_always { - // The diagnostics for this query will be - // promoted to the current session during + // The diagnostics for this query will be promoted to the current session during // `try_mark_green()`, so we can ignore them here. - let loaded = tcx.start_query(job.id, None, || { - let marked = dep_graph.try_mark_green_and_read(tcx, &dep_node); - marked.map(|(prev_dep_node_index, dep_node_index)| { - ( - load_from_disk_and_cache_in_memory( - tcx, - key.clone(), - prev_dep_node_index, - dep_node_index, - &dep_node, - query, - compute, - ), - dep_node_index, - ) - }) - }); - if let Some((result, dep_node_index)) = loaded { - return job.complete(result, dep_node_index); + if let Some(ret) = tcx.start_query(job_id, None, || { + try_load_from_disk_and_cache_in_memory(tcx, &key, &dep_node, query, compute) + }) { + return ret; } } - let (result, dep_node_index) = force_query_with_job(tcx, key, job, dep_node, query, compute); - dep_graph.read_index(dep_node_index); - result + let prof_timer = tcx.dep_context().profiler().query_provider(); + let diagnostics = Lock::new(ThinVec::new()); + + 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) + }); + } + + // `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) + }); + + prof_timer.finish_with_query_invocation_id(dep_node_index.into()); + + let diagnostics = diagnostics.into_inner(); + let side_effects = QuerySideEffects { diagnostics }; + + if unlikely!(!side_effects.is_empty()) { + if query.anon { + tcx.store_side_effects_for_anon_node(dep_node_index, side_effects); + } else { + tcx.store_side_effects(dep_node_index, side_effects); + } + } + + (result, dep_node_index) } -fn load_from_disk_and_cache_in_memory( +fn try_load_from_disk_and_cache_in_memory( tcx: CTX, - key: K, - prev_dep_node_index: SerializedDepNodeIndex, - dep_node_index: DepNodeIndex, + key: &K, dep_node: &DepNode, query: &QueryVtable, compute: fn(CTX::DepContext, K) -> V, -) -> V +) -> Option<(V, DepNodeIndex)> where + K: Clone, CTX: QueryContext, + V: Debug, { // Note this function can be called concurrently from the same query // We must ensure that this is handled correctly. - debug_assert!(tcx.dep_context().dep_graph().is_green(dep_node)); + let dep_graph = tcx.dep_context().dep_graph(); + let (prev_dep_node_index, dep_node_index) = dep_graph.try_mark_green(tcx, &dep_node)?; + + debug_assert!(dep_graph.is_green(dep_node)); // First we try to load the result from the on-disk cache. - let result = if query.cache_on_disk(tcx, &key, None) { + // Some things are never cached on disk. + if query.cache_on_disk(tcx, key, None) { 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()); @@ -548,47 +523,43 @@ where // We always expect to find a cached result for things that // can be forced from `DepNode`. debug_assert!( - !dep_node.kind.can_reconstruct_query_key() || result.is_some(), + !dep_node.kind.fingerprint_style().reconstructible() || result.is_some(), "missing on-disk cache entry for {:?}", dep_node ); - result - } else { - // Some things are never cached on disk. - None - }; - if let Some(result) = result { - // If `-Zincremental-verify-ich` is specified, re-hash results from - // the cache and make sure that they have the expected fingerprint. - if unlikely!(tcx.dep_context().sess().opts.debugging_opts.incremental_verify_ich) { - incremental_verify_ich(*tcx.dep_context(), &result, dep_node, query); + if let Some(result) = result { + // If `-Zincremental-verify-ich` is specified, re-hash results from + // the cache and make sure that they have the expected fingerprint. + if unlikely!(tcx.dep_context().sess().opts.debugging_opts.incremental_verify_ich) { + incremental_verify_ich(*tcx.dep_context(), &result, dep_node, query); + } + + return Some((result, dep_node_index)); } - - result - } else { - // We could not load a result from the on-disk cache, so - // recompute. - let prof_timer = tcx.dep_context().profiler().query_provider(); - - // The dep-graph for this computation is already in-place. - let result = tcx.dep_context().dep_graph().with_ignore(|| compute(*tcx.dep_context(), key)); - - prof_timer.finish_with_query_invocation_id(dep_node_index.into()); - - // Verify that re-running the query produced a result with the expected hash - // This catches bugs in query implementations, turning them into ICEs. - // For example, a query might sort its result by `DefId` - since `DefId`s are - // not stable across compilation sessions, the result could get up getting sorted - // in a different order when the query is re-run, even though all of the inputs - // (e.g. `DefPathHash` values) were green. - // - // See issue #82920 for an example of a miscompilation that would get turned into - // an ICE by this check - incremental_verify_ich(*tcx.dep_context(), &result, dep_node, query); - - result } + + // We could not load a result from the on-disk cache, so + // recompute. + 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())); + + prof_timer.finish_with_query_invocation_id(dep_node_index.into()); + + // Verify that re-running the query produced a result with the expected hash + // This catches bugs in query implementations, turning them into ICEs. + // For example, a query might sort its result by `DefId` - since `DefId`s are + // not stable across compilation sessions, the result could get up getting sorted + // in a different order when the query is re-run, even though all of the inputs + // (e.g. `DefPathHash` values) were green. + // + // See issue #82920 for an example of a miscompilation that would get turned into + // an ICE by this check + incremental_verify_ich(*tcx.dep_context(), &result, dep_node, query); + + Some((result, dep_node_index)) } fn incremental_verify_ich( @@ -648,88 +619,6 @@ fn incremental_verify_ich( } } -fn force_query_with_job( - tcx: CTX, - key: C::Key, - job: JobOwner<'_, CTX::DepKind, C>, - dep_node: DepNode, - query: &QueryVtable, - compute: fn(CTX::DepContext, C::Key) -> C::Value, -) -> (C::Stored, DepNodeIndex) -where - C: QueryCache, - CTX: QueryContext, -{ - // If the following assertion triggers, it can have two reasons: - // 1. Something is wrong with DepNode creation, either here or - // in `DepGraph::try_mark_green()`. - // 2. Two distinct query keys get mapped to the same `DepNode` - // (see for example #48923). - assert!( - !tcx.dep_context().dep_graph().dep_node_exists(&dep_node), - "forcing query with already existing `DepNode`\n\ - - query-key: {:?}\n\ - - dep-node: {:?}", - key, - dep_node - ); - - let prof_timer = tcx.dep_context().profiler().query_provider(); - - let ((result, dep_node_index), diagnostics) = with_diagnostics(|diagnostics| { - tcx.start_query(job.id, diagnostics, || { - if query.eval_always { - tcx.dep_context().dep_graph().with_eval_always_task( - dep_node, - *tcx.dep_context(), - key, - compute, - query.hash_result, - ) - } else { - tcx.dep_context().dep_graph().with_task( - dep_node, - *tcx.dep_context(), - key, - compute, - query.hash_result, - ) - } - }) - }); - - prof_timer.finish_with_query_invocation_id(dep_node_index.into()); - - let side_effects = QuerySideEffects { diagnostics }; - - if unlikely!(!side_effects.is_empty()) && dep_node.kind != DepKind::NULL { - tcx.store_side_effects(dep_node_index, side_effects); - } - - let result = job.complete(result, dep_node_index); - - (result, dep_node_index) -} - -#[inline(never)] -fn get_query_impl( - tcx: CTX, - state: &QueryState, - cache: &QueryCacheStore, - span: Span, - key: C::Key, - lookup: QueryLookup, - query: &QueryVtable, - compute: fn(CTX::DepContext, C::Key) -> C::Value, -) -> C::Stored -where - CTX: QueryContext, - C: QueryCache, - C::Key: DepNodeParams, -{ - try_execute_query(tcx, state, cache, span, key, lookup, query, compute) -} - /// Ensure that either this query has all green inputs or been executed. /// Executing `query::ensure(D)` is considered a read of the dep-node `D`. /// Returns true if the query should still run. @@ -739,13 +628,17 @@ where /// /// Note: The optimization is only available during incr. comp. #[inline(never)] -fn ensure_must_run(tcx: CTX, key: &K, query: &QueryVtable) -> bool +fn ensure_must_run( + tcx: CTX, + key: &K, + query: &QueryVtable, +) -> (bool, Option>) where K: crate::dep_graph::DepNodeParams, CTX: QueryContext, { if query.eval_always { - return true; + return (true, None); } // Ensuring an anonymous query makes no sense @@ -753,19 +646,21 @@ where let dep_node = query.to_dep_node(*tcx.dep_context(), key); - match tcx.dep_context().dep_graph().try_mark_green_and_read(tcx, &dep_node) { + let dep_graph = tcx.dep_context().dep_graph(); + match dep_graph.try_mark_green(tcx, &dep_node) { None => { - // A None return from `try_mark_green_and_read` means that this is either + // A None return from `try_mark_green` means that this is either // a new dep node or that the dep node has already been marked red. // Either way, we can't call `dep_graph.read()` as we don't have the // DepNodeIndex. We must invoke the query itself. The performance cost // this introduces should be negligible as we'll immediately hit the // in-memory cache, or another query down the line will. - true + (true, Some(dep_node)) } Some((_, dep_node_index)) => { + dep_graph.read_index(dep_node_index); tcx.dep_context().profiler().query_cache_hit(dep_node_index.into()); - false + (false, None) } } } @@ -793,10 +688,6 @@ where if unlikely!(tcx.dep_context().profiler().enabled()) { tcx.dep_context().profiler().query_cache_hit(index.into()); } - #[cfg(debug_assertions)] - { - cache.cache_hits.fetch_add(1, Ordering::Relaxed); - } }); let lookup = match cached { @@ -804,23 +695,8 @@ where Err(lookup) => lookup, }; - let job = match JobOwner::<'_, CTX::DepKind, C>::try_start( - tcx, - state, - cache, - DUMMY_SP, - key.clone(), - lookup, - query, - ) { - TryGetJob::NotYetStarted(job) => job, - TryGetJob::Cycle(_) => return true, - #[cfg(parallel_compiler)] - TryGetJob::JobCompleted(_) => return true, - }; - - force_query_with_job(tcx, key, job, dep_node, query, compute); - + let _ = + try_execute_query(tcx, state, cache, DUMMY_SP, key, lookup, Some(dep_node), query, compute); true } @@ -842,25 +718,33 @@ where CTX: QueryContext, { let query = &Q::VTABLE; - if let QueryMode::Ensure = mode { - if !ensure_must_run(tcx, &key, query) { + let dep_node = if let QueryMode::Ensure = mode { + let (must_run, dep_node) = ensure_must_run(tcx, &key, query); + if !must_run { return None; } - } + dep_node + } else { + None + }; debug!("ty::query::get_query<{}>(key={:?}, span={:?})", Q::NAME, key, span); let compute = Q::compute_fn(tcx, &key); - let value = get_query_impl( + let (result, dep_node_index) = try_execute_query( tcx, Q::query_state(tcx), Q::query_cache(tcx), span, key, lookup, + dep_node, query, compute, ); - Some(value) + if let Some(dep_node_index) = dep_node_index { + tcx.dep_context().dep_graph().read_index(dep_node_index) + } + Some(result) } pub fn force_query(tcx: CTX, dep_node: &DepNode) -> bool @@ -873,7 +757,7 @@ where return false; } - if !>::can_reconstruct_query_key() { + if !>::fingerprint_style().reconstructible() { return false; } diff --git a/compiler/rustc_resolve/Cargo.toml b/compiler/rustc_resolve/Cargo.toml index 1581b05627..f1d3315d6e 100644 --- a/compiler/rustc_resolve/Cargo.toml +++ b/compiler/rustc_resolve/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustc_resolve" version = "0.0.0" -edition = "2018" +edition = "2021" [lib] test = false diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 2ee483d850..2a562a06cb 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -9,11 +9,9 @@ use crate::def_collector::collect_definitions; use crate::imports::{Import, ImportKind}; use crate::macros::{MacroRulesBinding, MacroRulesScope, MacroRulesScopeRef}; use crate::Namespace::{self, MacroNS, TypeNS, ValueNS}; -use crate::{CrateLint, Determinacy, PathResult, ResolutionError, VisResolutionError}; -use crate::{ - ExternPreludeEntry, ModuleOrUniformRoot, ParentScope, PerNS, Resolver, ResolverArenas, -}; -use crate::{Module, ModuleData, ModuleKind, NameBinding, NameBindingKind, Segment, ToNameBinding}; +use crate::{CrateLint, Determinacy, ExternPreludeEntry, Module, ModuleKind, ModuleOrUniformRoot}; +use crate::{NameBinding, NameBindingKind, ParentScope, PathResult, PerNS, ResolutionError}; +use crate::{Resolver, ResolverArenas, Segment, ToNameBinding, VisResolutionError}; use rustc_ast::visit::{self, AssocCtxt, Visitor}; use rustc_ast::{self as ast, AssocItem, AssocItemKind, MetaItemKind, StmtKind}; @@ -29,8 +27,8 @@ use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_INDEX}; use rustc_metadata::creader::LoadedMacro; use rustc_middle::bug; use rustc_middle::hir::exports::Export; -use rustc_middle::middle::cstore::CrateStore; use rustc_middle::ty; +use rustc_session::cstore::CrateStore; use rustc_span::hygiene::{ExpnId, LocalExpnId, MacroKind}; use rustc_span::source_map::{respan, Spanned}; use rustc_span::symbol::{kw, sym, Ident, Symbol}; @@ -95,100 +93,96 @@ impl<'a> Resolver<'a> { } /// Walks up the tree of definitions starting at `def_id`, - /// stopping at the first `DefKind::Mod` encountered - fn nearest_parent_mod(&mut self, def_id: DefId) -> Module<'a> { - let def_key = self.cstore().def_key(def_id); - - let mut parent_id = DefId { - krate: def_id.krate, - index: def_key.parent.expect("failed to get parent for module"), - }; - // The immediate parent may not be a module - // (e.g. `const _: () = { #[path = "foo.rs"] mod foo; };`) - // Walk up the tree until we hit a module or the crate root. - while parent_id.index != CRATE_DEF_INDEX - && self.cstore().def_kind(parent_id) != DefKind::Mod - { - let parent_def_key = self.cstore().def_key(parent_id); - parent_id.index = parent_def_key.parent.expect("failed to get parent for module"); - } - self.get_module(parent_id) - } - - pub fn get_module(&mut self, def_id: DefId) -> Module<'a> { - // If this is a local module, it will be in `module_map`, no need to recalculate it. - if let Some(def_id) = def_id.as_local() { - return self.module_map[&def_id]; - } - - // Cache module resolution - if let Some(&module) = self.extern_module_map.get(&def_id) { - return module; - } - - let (name, parent) = if def_id.index == CRATE_DEF_INDEX { - // This is the crate root - (self.cstore().crate_name(def_id.krate), None) - } else { - let def_key = self.cstore().def_key(def_id); - let name = def_key - .disambiguated_data - .data - .get_opt_name() - .expect("given a DefId that wasn't a module"); - - let parent = Some(self.nearest_parent_mod(def_id)); - (name, parent) - }; - - // Allocate and return a new module with the information we found - let kind = ModuleKind::Def(DefKind::Mod, def_id, name); - let module = self.arenas.alloc_module(ModuleData::new( - parent, - kind, - def_id, - self.cstore().module_expansion_untracked(def_id, &self.session), - self.cstore().get_span_untracked(def_id, &self.session), - )); - self.extern_module_map.insert(def_id, module); - module - } - - crate fn macro_def_scope(&mut self, expn_id: ExpnId) -> Module<'a> { - let def_id = match expn_id.expn_data().macro_def_id { - Some(def_id) => def_id, - None => { - return expn_id - .as_local() - .and_then(|expn_id| self.ast_transform_scopes.get(&expn_id)) - .unwrap_or(&self.graph_root); + /// stopping at the first encountered module. + /// Parent block modules for arbitrary def-ids are not recorded for the local crate, + /// and are not preserved in metadata for foreign crates, so block modules are never + /// returned by this function. + /// + /// For the local crate ignoring block modules may be incorrect, so use this method with care. + /// + /// For foreign crates block modules can be ignored without introducing observable differences, + /// moreover they has to be ignored right now because they are not kept in metadata. + /// Foreign parent modules are used for resolving names used by foreign macros with def-site + /// hygiene, therefore block module ignorability relies on macros with def-site hygiene and + /// block module parents being unreachable from other crates. + /// Reachable macros with block module parents exist due to `#[macro_export] macro_rules!`, + /// but they cannot use def-site hygiene, so the assumption holds + /// (). + fn get_nearest_non_block_module(&mut self, mut def_id: DefId) -> Module<'a> { + loop { + match self.get_module(def_id) { + Some(module) => return module, + None => { + def_id.index = + self.def_key(def_id).parent.expect("non-root `DefId` without parent") + } } - }; - self.macro_def_scope_from_def_id(def_id) + } } - crate fn macro_def_scope_from_def_id(&mut self, def_id: DefId) -> Module<'a> { + pub fn expect_module(&mut self, def_id: DefId) -> Module<'a> { + self.get_module(def_id).expect("argument `DefId` is not a module") + } + + /// If `def_id` refers to a module (in resolver's sense, i.e. a module item, crate root, enum, + /// or trait), then this function returns that module's resolver representation, otherwise it + /// returns `None`. + crate fn get_module(&mut self, def_id: DefId) -> Option> { + if let module @ Some(..) = self.module_map.get(&def_id) { + return module.copied(); + } + + if !def_id.is_local() { + let def_kind = self.cstore().def_kind(def_id); + match def_kind { + DefKind::Mod | DefKind::Enum | DefKind::Trait => { + let def_key = self.cstore().def_key(def_id); + let parent = def_key.parent.map(|index| { + self.get_nearest_non_block_module(DefId { index, krate: def_id.krate }) + }); + let name = if def_id.index == CRATE_DEF_INDEX { + self.cstore().crate_name(def_id.krate) + } 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().get_span_untracked(def_id, &self.session), + // FIXME: Account for `#[no_implicit_prelude]` attributes. + parent.map_or(false, |module| module.no_implicit_prelude), + )) + } + _ => None, + } + } else { + None + } + } + + crate fn expn_def_scope(&mut self, expn_id: ExpnId) -> Module<'a> { + match expn_id.expn_data().macro_def_id { + Some(def_id) => self.macro_def_scope(def_id), + None => expn_id + .as_local() + .and_then(|expn_id| self.ast_transform_scopes.get(&expn_id)) + .unwrap_or(&self.graph_root), + } + } + + crate fn macro_def_scope(&mut self, def_id: DefId) -> Module<'a> { if let Some(id) = def_id.as_local() { self.local_macro_def_scopes[&id] } else { - // This is not entirely correct - a `macro_rules!` macro may occur - // inside a 'block' module: - // - // ```rust - // const _: () = { - // #[macro_export] - // macro_rules! my_macro { - // () => {}; - // } - // ` - // We don't record this information for external crates, so - // the module we compute here will be the closest 'mod' item - // (not necesssarily the actual parent of the `macro_rules!` - // macro). `macro_rules!` macros can't use def-site hygiene, - // so this hopefully won't be a problem. - // - // See https://github.com/rust-lang/rust/pull/77984#issuecomment-712445508 - self.nearest_parent_mod(def_id) + self.get_nearest_non_block_module(def_id) } } @@ -226,9 +220,7 @@ impl<'a> Resolver<'a> { } crate fn build_reduced_graph_external(&mut self, module: Module<'a>) { - let def_id = module.def_id().expect("unpopulated module without a def-id"); - for child in self.cstore().item_children_untracked(def_id, self.session) { - let child = child.map_id(|_| panic!("unexpected id")); + for child in self.cstore().item_children_untracked(module.def_id(), self.session) { let parent_scope = ParentScope::module(module, self); BuildReducedGraphVisitor { r: self, parent_scope } .build_reduced_graph_for_external_crate_res(child); @@ -275,7 +267,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { self.r.visibilities[&def_id.expect_local()] } // Otherwise, the visibility is restricted to the nearest parent `mod` item. - _ => ty::Visibility::Restricted(self.parent_scope.module.nearest_parent_mod), + _ => ty::Visibility::Restricted(self.parent_scope.module.nearest_parent_mod()), }) } ast::VisibilityKind::Restricted { ref path, id, .. } => { @@ -718,7 +710,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { local_def_id, ); self.r.extern_crate_map.insert(local_def_id, crate_id); - self.r.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX }) + self.r.expect_module(crate_id.as_def_id()) }; let used = self.process_macro_use_imports(item, module); @@ -769,21 +761,15 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { } ItemKind::Mod(..) => { - let module_kind = ModuleKind::Def(DefKind::Mod, def_id, ident.name); - let module = self.r.arenas.alloc_module(ModuleData { - no_implicit_prelude: parent.no_implicit_prelude || { - self.r.session.contains_name(&item.attrs, sym::no_implicit_prelude) - }, - ..ModuleData::new( - Some(parent), - module_kind, - def_id, - expansion.to_expn_id(), - item.span, - ) - }); + let module = self.r.new_module( + Some(parent), + ModuleKind::Def(DefKind::Mod, def_id, ident.name), + expansion.to_expn_id(), + item.span, + parent.no_implicit_prelude + || self.r.session.contains_name(&item.attrs, sym::no_implicit_prelude), + ); self.r.define(parent, ident, TypeNS, (module, vis, sp, expansion)); - self.r.module_map.insert(local_def_id, module); // Descend into the module. self.parent_scope.module = module; @@ -814,13 +800,12 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { } ItemKind::Enum(_, _) => { - let module_kind = ModuleKind::Def(DefKind::Enum, def_id, ident.name); let module = self.r.new_module( - parent, - module_kind, - parent.nearest_parent_mod, + Some(parent), + ModuleKind::Def(DefKind::Enum, def_id, ident.name), expansion.to_expn_id(), item.span, + parent.no_implicit_prelude, ); self.r.define(parent, ident, TypeNS, (module, vis, sp, expansion)); self.parent_scope.module = module; @@ -889,13 +874,12 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { ItemKind::Trait(..) => { // Add all the items within to a new module. - let module_kind = ModuleKind::Def(DefKind::Trait, def_id, ident.name); let module = self.r.new_module( - parent, - module_kind, - parent.nearest_parent_mod, + Some(parent), + ModuleKind::Def(DefKind::Trait, def_id, ident.name), expansion.to_expn_id(), item.span, + parent.no_implicit_prelude, ); self.r.define(parent, ident, TypeNS, (module, vis, sp, expansion)); self.parent_scope.module = module; @@ -934,11 +918,11 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { let expansion = self.parent_scope.expansion; if self.block_needs_anonymous_module(block) { let module = self.r.new_module( - parent, + Some(parent), ModuleKind::Block(block.id), - parent.nearest_parent_mod, expansion.to_expn_id(), block.span, + parent.no_implicit_prelude, ); self.r.block_map.insert(block.id, module); self.parent_scope.module = module; // Descend into the block. @@ -946,20 +930,15 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { } /// Builds the reduced graph for a single item in an external crate. - fn build_reduced_graph_for_external_crate_res(&mut self, child: Export) { + fn build_reduced_graph_for_external_crate_res(&mut self, child: Export) { let parent = self.parent_scope.module; let Export { ident, res, vis, span } = child; + let res = res.expect_non_local(); let expansion = self.parent_scope.expansion; // Record primary definitions. match res { - Res::Def(kind @ (DefKind::Mod | DefKind::Enum | DefKind::Trait), def_id) => { - let module = self.r.new_module( - parent, - ModuleKind::Def(kind, def_id, ident.name), - def_id, - expansion.to_expn_id(), - span, - ); + Res::Def(DefKind::Mod | DefKind::Enum | DefKind::Trait, def_id) => { + let module = self.r.expect_module(def_id); self.r.define(parent, ident, TypeNS, (module, vis, span, expansion)); } Res::Def( diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs index 6f4f1bdaea..5879cb1daa 100644 --- a/compiler/rustc_resolve/src/def_collector.rs +++ b/compiler/rustc_resolve/src/def_collector.rs @@ -32,7 +32,13 @@ impl<'a, 'b> DefCollector<'a, 'b> { fn create_def(&mut self, node_id: NodeId, data: DefPathData, span: Span) -> LocalDefId { let parent_def = self.parent_def; debug!("create_def(node_id={:?}, data={:?}, parent_def={:?})", node_id, data, parent_def); - self.resolver.create_def(parent_def, node_id, data, self.expansion.to_expn_id(), span) + self.resolver.create_def( + parent_def, + node_id, + data, + self.expansion.to_expn_id(), + span.with_parent(None), + ) } fn with_parent(&mut self, parent_def: LocalDefId, f: F) { diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 0b1687d1bd..05675e086d 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -198,7 +198,7 @@ impl<'a> Resolver<'a> { err.span_label(first_use_span, format!("first use of `{}`", name)); err } - ResolutionError::MethodNotMemberOfTrait(method, trait_) => { + ResolutionError::MethodNotMemberOfTrait(method, trait_, candidate) => { let mut err = struct_span_err!( self.session, span, @@ -208,9 +208,17 @@ impl<'a> Resolver<'a> { trait_ ); err.span_label(span, format!("not a member of trait `{}`", trait_)); + if let Some(candidate) = candidate { + err.span_suggestion( + method.span, + "there is an associated function with a similar name", + candidate.to_ident_string(), + Applicability::MaybeIncorrect, + ); + } err } - ResolutionError::TypeNotMemberOfTrait(type_, trait_) => { + ResolutionError::TypeNotMemberOfTrait(type_, trait_, candidate) => { let mut err = struct_span_err!( self.session, span, @@ -220,9 +228,17 @@ impl<'a> Resolver<'a> { trait_ ); err.span_label(span, format!("not a member of trait `{}`", trait_)); + if let Some(candidate) = candidate { + err.span_suggestion( + type_.span, + "there is an associated type with a similar name", + candidate.to_ident_string(), + Applicability::MaybeIncorrect, + ); + } err } - ResolutionError::ConstNotMemberOfTrait(const_, trait_) => { + ResolutionError::ConstNotMemberOfTrait(const_, trait_, candidate) => { let mut err = struct_span_err!( self.session, span, @@ -232,6 +248,14 @@ impl<'a> Resolver<'a> { trait_ ); err.span_label(span, format!("not a member of trait `{}`", trait_)); + if let Some(candidate) = candidate { + err.span_suggestion( + const_.span, + "there is an associated constant with a similar name", + candidate.to_ident_string(), + Applicability::MaybeIncorrect, + ); + } err } ResolutionError::VariableNotBoundInPattern(binding_error) => { @@ -777,7 +801,7 @@ impl<'a> Resolver<'a> { None => worklist_via_import.pop(), Some(x) => Some(x), } { - let in_module_is_extern = !in_module.def_id().unwrap().is_local(); + let in_module_is_extern = !in_module.def_id().is_local(); // We have to visit module children in deterministic order to avoid // instabilities in reported imports (#43552). in_module.for_each_child(self, |this, ident, ns, name_binding| { @@ -860,7 +884,7 @@ impl<'a> Resolver<'a> { if !is_extern_crate_that_also_appears_in_prelude { // add the module to the lookup - if seen_modules.insert(module.def_id().unwrap()) { + if seen_modules.insert(module.def_id()) { if via_import { &mut worklist_via_import } else { &mut worklist } .push((module, path_segments, child_accessible)); } @@ -915,8 +939,7 @@ impl<'a> Resolver<'a> { continue; } if let Some(crate_id) = self.crate_loader.maybe_process_path_extern(ident.name) { - let crate_root = - self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX }); + let crate_root = self.expect_module(crate_id.as_def_id()); suggestions.extend(self.lookup_import_candidates_from_module( lookup_ident, namespace, @@ -950,7 +973,15 @@ impl<'a> Resolver<'a> { let import_suggestions = self.lookup_import_candidates(ident, Namespace::MacroNS, parent_scope, is_expected); - show_candidates(err, None, &import_suggestions, false, true); + show_candidates( + &self.definitions, + self.session, + err, + None, + &import_suggestions, + false, + true, + ); if macro_kind == MacroKind::Derive && (ident.name == sym::Send || ident.name == sym::Sync) { let msg = format!("unsafe traits like `{}` should be implemented explicitly", ident); @@ -1246,6 +1277,34 @@ impl<'a> Resolver<'a> { err.emit(); } + + crate fn find_similarly_named_module_or_crate( + &mut self, + ident: Symbol, + current_module: &Module<'a>, + ) -> Option { + let mut candidates = self + .extern_prelude + .iter() + .map(|(ident, _)| ident.name) + .chain( + self.module_map + .iter() + .filter(|(_, module)| { + current_module.is_ancestor_of(module) && !ptr::eq(current_module, *module) + }) + .map(|(_, module)| module.kind.name()) + .flatten(), + ) + .filter(|c| !c.to_string().is_empty()) + .collect::>(); + candidates.sort(); + candidates.dedup(); + match find_best_match_for_name(&candidates, ident, None) { + Some(sugg) if sugg == ident => None, + sugg => sugg, + } + } } impl<'a, 'b> ImportResolver<'a, 'b> { @@ -1690,6 +1749,8 @@ fn find_span_immediately_after_crate_name( /// entities with that name in all crates. This method allows outputting the /// results of this search in a programmer-friendly way crate fn show_candidates( + definitions: &rustc_hir::definitions::Definitions, + session: &Session, err: &mut DiagnosticBuilder<'_>, // This is `None` if all placement locations are inside expansions use_placement_span: Option, @@ -1701,40 +1762,111 @@ 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(); + + 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)) + }); + // we want consistent results across executions, but candidates are produced // by iterating through a hash map, so make sure they are ordered: - let mut path_strings: Vec<_> = - candidates.iter().map(|c| path_names_to_string(&c.path)).collect(); + for path_strings in [&mut accessible_path_strings, &mut inaccessible_path_strings] { + path_strings.sort_by(|a, b| a.0.cmp(&b.0)); + let core_path_strings = + path_strings.drain_filter(|p| p.0.starts_with("core::")).collect::>(); + path_strings.extend(core_path_strings); + path_strings.dedup_by(|a, b| a.0 == b.0); + } - path_strings.sort(); - path_strings.dedup(); + if !accessible_path_strings.is_empty() { + let (determiner, kind) = if accessible_path_strings.len() == 1 { + ("this", accessible_path_strings[0].1) + } else { + ("one of these", "items") + }; - let (determiner, kind) = if candidates.len() == 1 { - ("this", candidates[0].descr) - } else { - ("one of these", "items") - }; + let instead = if instead { " instead" } else { "" }; + let mut msg = format!("consider importing {} {}{}", determiner, kind, instead); - let instead = if instead { " instead" } else { "" }; - let mut msg = format!("consider importing {} {}{}", determiner, kind, instead); + if let Some(span) = use_placement_span { + for candidate in &mut accessible_path_strings { + // produce an additional newline to separate the new use statement + // from the directly following item. + let additional_newline = if found_use { "" } else { "\n" }; + candidate.0 = format!("use {};\n{}", &candidate.0, additional_newline); + } - if let Some(span) = use_placement_span { - for candidate in &mut path_strings { - // produce an additional newline to separate the new use statement - // from the directly following item. - let additional_newline = if found_use { "" } else { "\n" }; - *candidate = format!("use {};\n{}", candidate, additional_newline); + err.span_suggestions( + span, + &msg, + accessible_path_strings.into_iter().map(|a| a.0), + Applicability::Unspecified, + ); + } else { + msg.push(':'); + + for candidate in accessible_path_strings { + msg.push('\n'); + msg.push_str(&candidate.0); + } + + err.note(&msg); } - - err.span_suggestions(span, &msg, path_strings.into_iter(), Applicability::Unspecified); } else { - msg.push(':'); + assert!(!inaccessible_path_strings.is_empty()); - for candidate in path_strings { - msg.push('\n'); - msg.push_str(&candidate); + if inaccessible_path_strings.len() == 1 { + let (name, descr, def_id) = &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()) { + let span = definitions.def_span(local_def_id); + let span = session.source_map().guess_head_span(span); + let mut multi_span = MultiSpan::from_span(span); + multi_span.push_span_label(span, "not accessible".to_string()); + err.span_note(multi_span, &msg); + } else { + err.note(&msg); + } + } else { + let (_, descr_first, _) = &inaccessible_path_strings[0]; + let descr = if inaccessible_path_strings + .iter() + .skip(1) + .all(|(_, descr, _)| descr == descr_first) + { + descr_first.to_string() + } else { + "item".to_string() + }; + + let mut msg = format!("these {}s exist but are inaccessible", descr); + let mut has_colon = false; + + let mut spans = Vec::new(); + 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); + spans.push((name, span)); + } else { + if !has_colon { + msg.push(':'); + has_colon = true; + } + msg.push('\n'); + msg.push_str(name); + } + } + + let mut multi_span = MultiSpan::from_spans(spans.iter().map(|(_, sp)| *sp).collect()); + for (name, span) in spans { + multi_span.push_span_label(span, format!("`{}`: not accessible", name)); + } + + err.span_note(multi_span, &msg); } - - err.note(&msg); } } diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index dfb6d89a0d..515b2c3fd2 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -9,9 +9,7 @@ use crate::{BindingKey, ModuleKind, ResolutionError, Resolver, Segment}; use crate::{CrateLint, Module, ModuleOrUniformRoot, ParentScope, PerNS, ScopeSet, Weak}; use crate::{NameBinding, NameBindingKind, PathResult, PrivacyError, ToNameBinding}; -use rustc_ast::unwrap_or; use rustc_ast::NodeId; -use rustc_ast_lowering::ResolverAstLowering; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::ptr_key::PtrKey; use rustc_errors::{pluralize, struct_span_err, Applicability}; @@ -350,10 +348,10 @@ impl<'a> Resolver<'a> { if !self.is_accessible_from(single_import.vis.get(), parent_scope.module) { continue; } - let module = unwrap_or!( - single_import.imported_module.get(), - return Err((Undetermined, Weak::No)) - ); + let module = match single_import.imported_module.get() { + Some(x) => x, + None => return Err((Undetermined, Weak::No)), + }; let ident = match single_import.kind { ImportKind::Single { source, .. } => source, _ => unreachable!(), @@ -428,7 +426,7 @@ impl<'a> Resolver<'a> { match ident.span.glob_adjust(module.expansion, glob_import.span) { Some(Some(def)) => { tmp_parent_scope = - ParentScope { module: self.macro_def_scope(def), ..*parent_scope }; + ParentScope { module: self.expn_def_scope(def), ..*parent_scope }; adjusted_parent_scope = &tmp_parent_scope; } Some(None) => {} @@ -586,7 +584,7 @@ impl<'a> Resolver<'a> { for import in module.glob_importers.borrow_mut().iter() { let mut ident = key.ident; let scope = match ident.span.reverse_glob_adjust(module.expansion, import.span) { - Some(Some(def)) => self.macro_def_scope(def), + Some(Some(def)) => self.expn_def_scope(def), Some(None) => import.parent_scope.module, None => continue, }; @@ -990,7 +988,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> { } if let ModuleOrUniformRoot::Module(module) = module { - if module.def_id() == import.parent_scope.module.def_id() { + if ptr::eq(module, import.parent_scope.module) { // Importing a module into itself is not allowed. return Some(UnresolvedImportError { span: import.span, @@ -1340,9 +1338,9 @@ impl<'a, 'b> ImportResolver<'a, 'b> { }; if module.is_trait() { - self.r.session.span_err(import.span, "items in traits are not importable."); + self.r.session.span_err(import.span, "items in traits are not importable"); return; - } else if module.def_id() == import.parent_scope.module.def_id() { + } else if ptr::eq(module, import.parent_scope.module) { return; } else if let ImportKind::Glob { is_prelude: true, .. } = import.kind { self.r.prelude = Some(module); @@ -1365,7 +1363,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> { .collect::>(); for (mut key, binding) in bindings { let scope = match key.ident.span.reverse_glob_adjust(module.expansion, import.span) { - Some(Some(def)) => self.r.macro_def_scope(def), + Some(Some(def)) => self.r.expn_def_scope(def), Some(None) => import.parent_scope.module, None => continue, }; @@ -1387,13 +1385,13 @@ impl<'a, 'b> ImportResolver<'a, 'b> { let mut reexports = Vec::new(); - module.for_each_child(self.r, |this, ident, _, binding| { + module.for_each_child(self.r, |_, ident, _, binding| { // Filter away ambiguous imports and anything that has def-site hygiene. // FIXME: Implement actual cross-crate hygiene. let is_good_import = binding.is_import() && !binding.is_ambiguity() && !ident.span.from_expansion(); if is_good_import || binding.is_macro_def() { - let res = binding.res().map_id(|id| this.local_def_id(id)); + let res = binding.res().expect_non_local(); if res != def::Res::Err { reexports.push(Export { ident, res, span: binding.span, vis: binding.vis }); } @@ -1401,7 +1399,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> { }); if !reexports.is_empty() { - if let Some(def_id) = module.def_id() { + if let Some(def_id) = module.opt_def_id() { // Call to `expect_local` should be fine because current // code is only called for local modules. self.r.export_map.insert(def_id.expect_local(), reexports); diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 6057396836..9563325796 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -799,9 +799,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { } fn with_scope(&mut self, id: NodeId, f: impl FnOnce(&mut Self) -> T) -> T { - let id = self.r.local_def_id(id); - let module = self.r.module_map.get(&id).cloned(); // clones a reference - if let Some(module) = module { + if let Some(module) = self.r.get_module(self.r.local_def_id(id).to_def_id()) { // Move down in the graph. let orig_module = replace(&mut self.parent_scope.module, module); self.with_rib(ValueNS, ModuleRibKind(module), |this| { @@ -1311,14 +1309,15 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { use crate::ResolutionError::*; match &item.kind { AssocItemKind::Const(_default, _ty, _expr) => { - debug!("resolve_implementation AssocItemKind::Const",); + debug!("resolve_implementation AssocItemKind::Const"); // If this is a trait impl, ensure the const // exists in trait this.check_trait_item( item.ident, + &item.kind, ValueNS, item.span, - |n, s| ConstNotMemberOfTrait(n, s), + |i, s, c| ConstNotMemberOfTrait(i, s, c), ); // We allow arbitrary const expressions inside of associated consts, @@ -1340,6 +1339,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { ); } AssocItemKind::Fn(box FnKind(.., generics, _)) => { + debug!("resolve_implementation AssocItemKind::Fn"); // We also need a new scope for the impl item type parameters. this.with_generic_param_rib( generics, @@ -1349,9 +1349,10 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { // exists in trait this.check_trait_item( item.ident, + &item.kind, ValueNS, item.span, - |n, s| MethodNotMemberOfTrait(n, s), + |i, s, c| MethodNotMemberOfTrait(i, s, c), ); visit::walk_assoc_item( @@ -1368,6 +1369,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { _, _, )) => { + debug!("resolve_implementation AssocItemKind::TyAlias"); // We also need a new scope for the impl item type parameters. this.with_generic_param_rib( generics, @@ -1377,9 +1379,10 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { // exists in trait this.check_trait_item( item.ident, + &item.kind, TypeNS, item.span, - |n, s| TypeNotMemberOfTrait(n, s), + |i, s, c| TypeNotMemberOfTrait(i, s, c), ); visit::walk_assoc_item( @@ -1403,9 +1406,15 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { }); } - fn check_trait_item(&mut self, ident: Ident, ns: Namespace, span: Span, err: F) - where - F: FnOnce(Symbol, &str) -> ResolutionError<'_>, + fn check_trait_item( + &mut self, + ident: Ident, + kind: &AssocItemKind, + ns: Namespace, + span: Span, + err: F, + ) where + F: FnOnce(Ident, &str, Option) -> ResolutionError<'_>, { // If there is a TraitRef in scope for an impl, then the method must be in the // trait. @@ -1422,8 +1431,9 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { ) .is_err() { + let candidate = self.find_similarly_named_assoc_item(ident.name, kind); let path = &self.current_trait_ref.as_ref().unwrap().1.path; - self.report_error(span, err(ident.name, &path_names_to_string(path))); + self.report_error(span, err(ident, &path_names_to_string(path), candidate)); } } } @@ -1872,7 +1882,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { if this.should_report_errs() { let (err, candidates) = this.smart_resolve_report_errors(path, span, source, res); - let def_id = this.parent_scope.module.nearest_parent_mod; + let def_id = this.parent_scope.module.nearest_parent_mod(); let instead = res.is_some(); let suggestion = if res.is_none() { this.report_missing_type_error(path) } else { None }; @@ -1940,7 +1950,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { drop(parent_err); - let def_id = this.parent_scope.module.nearest_parent_mod; + let def_id = this.parent_scope.module.nearest_parent_mod(); if this.should_report_errs() { this.r.use_injections.push(UseError { @@ -1999,9 +2009,8 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { let item_span = path.iter().last().map_or(span, |segment| segment.ident.span); - let mut hm = self.r.session.confused_type_with_std_module.borrow_mut(); - hm.insert(item_span, span); - hm.insert(span, span); + self.r.confused_type_with_std_module.insert(item_span, span); + self.r.confused_type_with_std_module.insert(span, span); } } diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index b2c0c78746..7b0dd82f0e 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -7,12 +7,12 @@ use crate::{PathResult, PathSource, Segment}; use rustc_ast::visit::FnKind; use rustc_ast::{ - self as ast, Expr, ExprKind, GenericParam, GenericParamKind, Item, ItemKind, NodeId, Path, Ty, - TyKind, + self as ast, AssocItemKind, Expr, ExprKind, GenericParam, GenericParamKind, Item, ItemKind, + NodeId, Path, Ty, TyKind, }; use rustc_ast_pretty::pprust::path_segment_to_string; use rustc_data_structures::fx::FxHashSet; -use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder, SuggestionStyle}; +use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder}; use rustc_hir as hir; use rustc_hir::def::Namespace::{self, *}; use rustc_hir::def::{self, CtorKind, CtorOf, DefKind}; @@ -768,6 +768,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { args[1].span.lo(), args.last().unwrap().span.hi(), call_span.ctxt(), + None, )) } else { None @@ -1025,9 +1026,15 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { self.suggest_using_enum_variant(err, source, def_id, span); } - (Res::Def(DefKind::Struct, def_id), _) if ns == ValueNS => { + (Res::Def(DefKind::Struct, def_id), source) if ns == ValueNS => { let (ctor_def, ctor_vis, fields) = if let Some(struct_ctor) = self.r.struct_constructors.get(&def_id).cloned() { + if let PathSource::Expr(Some(parent)) = source { + if let ExprKind::Field(..) | ExprKind::MethodCall(..) = parent.kind { + bad_struct_syntax_suggestion(def_id); + return true; + } + } struct_ctor } else { bad_struct_syntax_suggestion(def_id); @@ -1143,6 +1150,40 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { true } + /// Given the target `ident` and `kind`, search for the similarly named associated item + /// in `self.current_trait_ref`. + crate fn find_similarly_named_assoc_item( + &mut self, + ident: Symbol, + kind: &AssocItemKind, + ) -> Option { + let module = if let Some((module, _)) = self.current_trait_ref { + module + } else { + return None; + }; + if ident == kw::Underscore { + // We do nothing for `_`. + return None; + } + + let resolutions = self.r.resolutions(module); + let targets = resolutions + .borrow() + .iter() + .filter_map(|(key, res)| res.borrow().binding.map(|binding| (key, binding.res()))) + .filter(|(_, res)| match (kind, res) { + (AssocItemKind::Const(..), Res::Def(DefKind::AssocConst, _)) => true, + (AssocItemKind::Fn(_), Res::Def(DefKind::AssocFn, _)) => true, + (AssocItemKind::TyAlias(..), Res::Def(DefKind::AssocTy, _)) => true, + _ => false, + }) + .map(|(key, _)| key.ident.name) + .collect::>(); + + find_best_match_for_name(&targets, ident, None) + } + fn lookup_assoc_candidate( &mut self, ident: Ident, @@ -1450,7 +1491,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { // form the path let mut path_segments = path_segments.clone(); path_segments.push(ast::PathSegment::from_ident(ident)); - let module_def_id = module.def_id().unwrap(); + let module_def_id = module.def_id(); if module_def_id == def_id { let path = Path { span: name_binding.span, segments: path_segments, tokens: None }; @@ -1959,11 +2000,10 @@ impl<'tcx> LifetimeContext<'_, 'tcx> { introduce_suggestion.push((*span, formatter(<_name))); } } - err.multipart_suggestion_with_style( + err.multipart_suggestion_verbose( &msg, introduce_suggestion, Applicability::MaybeIncorrect, - SuggestionStyle::ShowAlways, ); } @@ -1975,14 +2015,13 @@ impl<'tcx> LifetimeContext<'_, 'tcx> { }) .map(|(formatter, span)| (*span, formatter(name))) .collect(); - err.multipart_suggestion_with_style( + err.multipart_suggestion_verbose( &format!( "consider using the `{}` lifetime", lifetime_names.iter().next().unwrap() ), spans_suggs, Applicability::MaybeIncorrect, - SuggestionStyle::ShowAlways, ); }; let suggest_new = |err: &mut DiagnosticBuilder<'_>, suggs: Vec>| { @@ -2073,11 +2112,10 @@ impl<'tcx> LifetimeContext<'_, 'tcx> { }; spans_suggs.push((span, sugg.to_string())); } - err.multipart_suggestion_with_style( + err.multipart_suggestion_verbose( "consider using the `'static` lifetime", spans_suggs, Applicability::MaybeIncorrect, - SuggestionStyle::ShowAlways, ); continue; } @@ -2162,11 +2200,10 @@ impl<'tcx> LifetimeContext<'_, 'tcx> { .unwrap_or((span, sugg)); introduce_suggestion.push((span, sugg.to_string())); } - err.multipart_suggestion_with_style( + err.multipart_suggestion_verbose( &msg, introduce_suggestion, Applicability::MaybeIncorrect, - SuggestionStyle::ShowAlways, ); if should_break { break; @@ -2242,11 +2279,10 @@ impl<'tcx> LifetimeContext<'_, 'tcx> { if spans_suggs.len() > 0 { // This happens when we have `Foo` where we point at the space before `T`, // but this can be confusing so we give a suggestion with placeholders. - err.multipart_suggestion_with_style( + err.multipart_suggestion_verbose( "consider using one of the available lifetimes here", spans_suggs, Applicability::HasPlaceholders, - SuggestionStyle::ShowAlways, ); } } diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs index 4c1d537d55..eb6f302a11 100644 --- a/compiler/rustc_resolve/src/late/lifetimes.rs +++ b/compiler/rustc_resolve/src/late/lifetimes.rs @@ -522,8 +522,7 @@ fn item_for(tcx: TyCtxt<'_>, local_def_id: LocalDefId) -> LocalDefId { _ => {} } let item = { - let hir = tcx.hir(); - let mut parent_iter = hir.parent_iter(hir_id); + let mut parent_iter = tcx.hir().parent_iter(hir_id); loop { let node = parent_iter.next().map(|n| n.1); match node { @@ -1652,7 +1651,11 @@ fn extract_labels(ctxt: &mut LifetimeContext<'_, '_>, body: &hir::Body<'_>) { } fn expression_label(ex: &hir::Expr<'_>) -> Option { - if let hir::ExprKind::Loop(_, Some(label), ..) = ex.kind { Some(label.ident) } else { None } + match ex.kind { + hir::ExprKind::Loop(_, Some(label), ..) => Some(label.ident), + hir::ExprKind::Block(_, Some(label)) => Some(label.ident), + _ => None, + } } fn check_if_label_shadows_lifetime(tcx: TyCtxt<'_>, mut scope: ScopeRef<'_>, label: Ident) { @@ -2024,7 +2027,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { // ensure that we issue lints in a repeatable order def_ids.sort_by_cached_key(|&def_id| self.tcx.def_path_hash(def_id)); - for def_id in def_ids { + 'lifetimes: for def_id in def_ids { debug!("check_uses_for_lifetimes_defined_by_scope: def_id = {:?}", def_id); let lifetimeuseset = self.lifetime_uses.remove(&def_id); @@ -2067,6 +2070,27 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { { continue; } + + // opaque types generated when desugaring an async function can have a single + // use lifetime even if it is explicitly denied (Issue #77175) + if let hir::Node::Item(hir::Item { + kind: hir::ItemKind::OpaqueTy(ref opaque), + .. + }) = self.tcx.hir().get(parent_hir_id) + { + if opaque.origin != hir::OpaqueTyOrigin::AsyncFn { + continue 'lifetimes; + } + // We want to do this only if the liftime identifier is already defined + // in the async function that generated this. Otherwise it could be + // an opaque type defined by the developer and we still want this + // lint to fail compilation + for p in opaque.generics.params { + if defined_by.contains_key(&p.name) { + continue 'lifetimes; + } + } + } } } @@ -2716,6 +2740,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { for input in inputs { gather.visit_ty(input); } + trace!(?gather.anon_count); let late_bound_vars = self.map.late_bound_vars.entry(hir_id).or_default(); let named_late_bound_vars = late_bound_vars.len() as u32; late_bound_vars.extend( @@ -3004,6 +3029,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { NestedVisitorMap::None } + #[instrument(skip(self), level = "trace")] fn visit_ty(&mut self, ty: &hir::Ty<'_>) { // If we enter a `BareFn`, then we enter a *new* binding scope if let hir::TyKind::BareFn(_) = ty.kind { @@ -3024,6 +3050,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { intravisit::walk_generic_args(self, path_span, generic_args) } + #[instrument(skip(self), level = "trace")] fn visit_lifetime(&mut self, lifetime_ref: &hir::Lifetime) { if lifetime_ref.is_elided() { self.anon_count += 1; diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 152d34fd63..9652c48368 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -10,14 +10,19 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![feature(box_patterns)] +#![feature(drain_filter)] #![feature(bool_to_option)] #![feature(crate_visibility_modifier)] #![feature(format_args_capture)] #![feature(iter_zip)] +#![feature(never_type)] #![feature(nll)] #![recursion_limit = "256"] #![allow(rustdoc::private_intra_doc_links)] +#[macro_use] +extern crate tracing; + pub use rustc_hir::def::{Namespace, PerNS}; use Determinacy::*; @@ -39,16 +44,17 @@ use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder}; use rustc_expand::base::{DeriveResolutions, SyntaxExtension, SyntaxExtensionKind}; use rustc_hir::def::Namespace::*; use rustc_hir::def::{self, CtorOf, DefKind, NonMacroAttrKind, PartialRes}; -use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefPathHash, LocalDefId, CRATE_DEF_INDEX}; +use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefPathHash, LocalDefId}; +use rustc_hir::def_id::{CRATE_DEF_ID, CRATE_DEF_INDEX, LOCAL_CRATE}; use rustc_hir::definitions::{DefKey, DefPathData, Definitions}; use rustc_hir::TraitCandidate; use rustc_index::vec::IndexVec; use rustc_metadata::creader::{CStore, CrateLoader}; use rustc_middle::hir::exports::ExportMap; -use rustc_middle::middle::cstore::{CrateStore, MetadataLoaderDyn}; use rustc_middle::span_bug; use rustc_middle::ty::query::Providers; use rustc_middle::ty::{self, DefIdTree, MainDefinition, ResolverOutputs}; +use rustc_session::cstore::{CrateStore, MetadataLoaderDyn}; use rustc_session::lint; use rustc_session::lint::{BuiltinLintDiagnostics, LintBuffer}; use rustc_session::Session; @@ -200,11 +206,11 @@ enum ResolutionError<'a> { /// parameter list. NameAlreadyUsedInParameterList(Symbol, Span), /// Error E0407: method is not a member of trait. - MethodNotMemberOfTrait(Symbol, &'a str), + MethodNotMemberOfTrait(Ident, &'a str, Option), /// Error E0437: type is not a member of trait. - TypeNotMemberOfTrait(Symbol, &'a str), + TypeNotMemberOfTrait(Ident, &'a str, Option), /// Error E0438: const is not a member of trait. - ConstNotMemberOfTrait(Symbol, &'a str), + ConstNotMemberOfTrait(Ident, &'a str, Option), /// Error E0408: variable `{}` is not bound in all patterns. VariableNotBoundInPattern(&'a BindingError), /// Error E0409: variable `{}` is bound in inconsistent ways within the same match arm. @@ -407,7 +413,7 @@ impl ModuleOrUniformRoot<'_> { fn same_def(lhs: Self, rhs: Self) -> bool { match (lhs, rhs) { (ModuleOrUniformRoot::Module(lhs), ModuleOrUniformRoot::Module(rhs)) => { - lhs.def_id() == rhs.def_id() + ptr::eq(lhs, rhs) } ( ModuleOrUniformRoot::CrateRootAndExternPrelude, @@ -504,10 +510,6 @@ pub struct ModuleData<'a> { /// What kind of module this is, because this may not be a `mod`. kind: ModuleKind, - /// The [`DefId`] of the nearest `mod` item ancestor (which may be this module). - /// This may be the crate root. - nearest_parent_mod: DefId, - /// Mapping between names and their (possibly in-progress) resolutions in this module. /// Resolutions in modules from other crates are not populated until accessed. lazy_resolutions: Resolutions<'a>, @@ -538,18 +540,21 @@ impl<'a> ModuleData<'a> { fn new( parent: Option>, kind: ModuleKind, - nearest_parent_mod: DefId, expansion: ExpnId, span: Span, + no_implicit_prelude: bool, ) -> Self { + let is_foreign = match kind { + ModuleKind::Def(_, def_id, _) => !def_id.is_local(), + ModuleKind::Block(_) => false, + }; ModuleData { parent, kind, - nearest_parent_mod, lazy_resolutions: Default::default(), - populate_on_access: Cell::new(!nearest_parent_mod.is_local()), + populate_on_access: Cell::new(is_foreign), unexpanded_invocations: Default::default(), - no_implicit_prelude: false, + no_implicit_prelude, glob_importers: RefCell::new(Vec::new()), globs: RefCell::new(Vec::new()), traits: RefCell::new(None), @@ -597,7 +602,11 @@ impl<'a> ModuleData<'a> { } } - fn def_id(&self) -> Option { + fn def_id(&self) -> DefId { + self.opt_def_id().expect("`ModuleData::def_id` is called on a block module") + } + + fn opt_def_id(&self) -> Option { match self.kind { ModuleKind::Def(_, def_id, _) => Some(def_id), _ => None, @@ -622,6 +631,15 @@ impl<'a> ModuleData<'a> { } } + /// The [`DefId`] of the nearest `mod` item ancestor (which may be this module). + /// This may be the crate root. + fn nearest_parent_mod(&self) -> DefId { + match self.kind { + ModuleKind::Def(DefKind::Mod, def_id, _) => def_id, + _ => self.parent.expect("non-root module without parent").nearest_parent_mod(), + } + } + fn is_ancestor_of(&self, mut other: &Self) -> bool { while !ptr::eq(self, other) { if let Some(parent) = other.parent { @@ -911,7 +929,7 @@ pub struct Resolver<'a> { /// `CrateNum` resolutions of `extern crate` items. extern_crate_map: FxHashMap, - export_map: ExportMap, + export_map: ExportMap, trait_map: Option>>, /// A map from nodes to anonymous modules. @@ -933,8 +951,7 @@ pub struct Resolver<'a> { /// some AST passes can generate identifiers that only resolve to local or /// language items. empty_module: Module<'a>, - module_map: FxHashMap>, - extern_module_map: FxHashMap>, + module_map: FxHashMap>, binding_parent_modules: FxHashMap>, Module<'a>>, underscore_disambiguator: u32, @@ -1012,8 +1029,6 @@ pub struct Resolver<'a> { next_node_id: NodeId, - def_id_to_span: IndexVec, - node_id_to_def_id: FxHashMap, def_id_to_node_id: IndexVec, @@ -1038,6 +1053,7 @@ pub struct Resolver<'a> { /// A list of proc macro LocalDefIds, written out in the order in which /// they are declared in the static array generated by proc_macro_harness. proc_macros: Vec, + confused_type_with_std_module: FxHashMap, } /// Nothing really interesting here; it just provides memory for the rest of the crate. @@ -1052,11 +1068,24 @@ pub struct ResolverArenas<'a> { } impl<'a> ResolverArenas<'a> { - fn alloc_module(&'a self, module: ModuleData<'a>) -> Module<'a> { - let module = self.modules.alloc(module); - if module.def_id().map_or(true, |def_id| def_id.is_local()) { + fn new_module( + &'a self, + parent: Option>, + kind: ModuleKind, + expn_id: ExpnId, + span: Span, + no_implicit_prelude: bool, + module_map: &mut FxHashMap>, + ) -> Module<'a> { + let module = + self.modules.alloc(ModuleData::new(parent, kind, expn_id, span, no_implicit_prelude)); + let def_id = module.opt_def_id(); + if def_id.map_or(true, |def_id| def_id.is_local()) { self.local_modules.borrow_mut().push(module); } + if let Some(def_id) = def_id { + module_map.insert(def_id, module); + } module } fn local_modules(&'a self) -> std::cell::Ref<'a, Vec>> { @@ -1115,6 +1144,11 @@ impl ResolverAstLowering for Resolver<'_> { } } + #[inline] + fn def_span(&self, id: LocalDefId) -> Span { + self.definitions.def_span(id) + } + fn item_generics_num_lifetimes(&self, def_id: DefId) -> usize { if let Some(def_id) = def_id.as_local() { self.item_generics_num_lifetimes[&def_id] @@ -1127,7 +1161,7 @@ impl ResolverAstLowering for Resolver<'_> { self.legacy_const_generic_args(expr) } - fn get_partial_res(&mut self, id: NodeId) -> Option { + fn get_partial_res(&self, id: NodeId) -> Option { self.partial_res_map.get(&id).cloned() } @@ -1196,9 +1230,7 @@ impl ResolverAstLowering for Resolver<'_> { disambiguator }; - let def_id = self.definitions.create_def(parent, data, expn_id, next_disambiguator); - - assert_eq!(self.def_id_to_span.push(span), def_id); + let def_id = self.definitions.create_def(parent, data, expn_id, next_disambiguator, span); // Some things for which we allocate `LocalDefId`s don't correspond to // anything in the AST, so they don't have a `NodeId`. For these cases @@ -1224,6 +1256,11 @@ impl<'a, 'b> rustc_span::HashStableContext for ExpandHasher<'a, 'b> { 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) @@ -1247,35 +1284,31 @@ impl<'a> Resolver<'a> { metadata_loader: Box, arenas: &'a ResolverArenas<'a>, ) -> Resolver<'a> { - let root_local_def_id = LocalDefId { local_def_index: CRATE_DEF_INDEX }; - let root_def_id = root_local_def_id.to_def_id(); - let root_module_kind = ModuleKind::Def(DefKind::Mod, root_def_id, kw::Empty); - let graph_root = arenas.alloc_module(ModuleData { - no_implicit_prelude: session.contains_name(&krate.attrs, sym::no_implicit_prelude), - ..ModuleData::new(None, root_module_kind, root_def_id, ExpnId::root(), krate.span) - }); - let empty_module_kind = ModuleKind::Def(DefKind::Mod, root_def_id, kw::Empty); - let empty_module = arenas.alloc_module(ModuleData { - no_implicit_prelude: true, - ..ModuleData::new( - Some(graph_root), - empty_module_kind, - root_def_id, - ExpnId::root(), - DUMMY_SP, - ) - }); + let root_def_id = CRATE_DEF_ID.to_def_id(); let mut module_map = FxHashMap::default(); - module_map.insert(root_local_def_id, graph_root); + let graph_root = arenas.new_module( + None, + ModuleKind::Def(DefKind::Mod, root_def_id, kw::Empty), + ExpnId::root(), + krate.span, + session.contains_name(&krate.attrs, sym::no_implicit_prelude), + &mut module_map, + ); + let empty_module = arenas.new_module( + None, + ModuleKind::Def(DefKind::Mod, root_def_id, kw::Empty), + ExpnId::root(), + DUMMY_SP, + true, + &mut FxHashMap::default(), + ); - let definitions = Definitions::new(session.local_stable_crate_id()); + let definitions = Definitions::new(session.local_stable_crate_id(), krate.span); let root = definitions.get_root_def(); let mut visibilities = FxHashMap::default(); - visibilities.insert(root_local_def_id, ty::Visibility::Public); + visibilities.insert(CRATE_DEF_ID, ty::Visibility::Public); - let mut def_id_to_span = IndexVec::default(); - assert_eq!(def_id_to_span.push(rustc_span::DUMMY_SP), root); let mut def_id_to_node_id = IndexVec::default(); assert_eq!(def_id_to_node_id.push(CRATE_NODE_ID), root); let mut node_id_to_def_id = FxHashMap::default(); @@ -1335,7 +1368,6 @@ impl<'a> Resolver<'a> { empty_module, module_map, block_map: Default::default(), - extern_module_map: FxHashMap::default(), binding_parent_modules: FxHashMap::default(), ast_transform_scopes: FxHashMap::default(), @@ -1392,7 +1424,6 @@ impl<'a> Resolver<'a> { .collect(), lint_buffer: LintBuffer::default(), next_node_id: NodeId::from_u32(1), - def_id_to_span, node_id_to_def_id, def_id_to_node_id, placeholder_field_indices: Default::default(), @@ -1404,6 +1435,7 @@ impl<'a> Resolver<'a> { main_def: Default::default(), trait_impls: Default::default(), proc_macros: Default::default(), + confused_type_with_std_module: Default::default(), }; let root_parent_scope = ParentScope::module(graph_root, &resolver); @@ -1412,6 +1444,18 @@ impl<'a> Resolver<'a> { resolver } + fn new_module( + &mut self, + parent: Option>, + kind: ModuleKind, + expn_id: ExpnId, + span: Span, + no_implicit_prelude: bool, + ) -> Module<'a> { + let module_map = &mut self.module_map; + 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()), @@ -1447,6 +1491,7 @@ impl<'a> Resolver<'a> { let maybe_unused_extern_crates = self.maybe_unused_extern_crates; let glob_map = self.glob_map; let main_def = self.main_def; + let confused_type_with_std_module = self.confused_type_with_std_module; ResolverOutputs { definitions, cstore: Box::new(self.crate_loader.into_cstore()), @@ -1464,6 +1509,7 @@ impl<'a> Resolver<'a> { main_def, trait_impls: self.trait_impls, proc_macros, + confused_type_with_std_module, } } @@ -1483,9 +1529,10 @@ impl<'a> Resolver<'a> { .iter() .map(|(ident, entry)| (ident.name, entry.introduced_by_item)) .collect(), - main_def: self.main_def.clone(), + main_def: self.main_def, trait_impls: self.trait_impls.clone(), proc_macros, + confused_type_with_std_module: self.confused_type_with_std_module.clone(), } } @@ -1545,7 +1592,7 @@ impl<'a> Resolver<'a> { if let Some(module) = current_trait { if self.trait_may_have_item(Some(module), assoc_item) { - let def_id = module.def_id().unwrap(); + let def_id = module.def_id(); found_traits.push(TraitCandidate { def_id, import_ids: smallvec![] }); } } @@ -1623,18 +1670,6 @@ impl<'a> Resolver<'a> { import_ids } - fn new_module( - &self, - parent: Module<'a>, - kind: ModuleKind, - nearest_parent_mod: DefId, - expn_id: ExpnId, - span: Span, - ) -> Module<'a> { - let module = ModuleData::new(Some(parent), kind, nearest_parent_mod, expn_id, span); - self.arenas.alloc_module(module) - } - fn new_key(&mut self, ident: Ident, ns: Namespace) -> BindingKey { let ident = ident.normalize_to_macros_2_0(); let disambiguator = if ident.name == kw::Underscore { @@ -2007,7 +2042,7 @@ impl<'a> Resolver<'a> { derive_fallback_lint_id: Option, ) -> Option<(Module<'a>, Option)> { if !module.expansion.outer_expn_is_descendant_of(*ctxt) { - return Some((self.macro_def_scope(ctxt.remove_mark()), None)); + return Some((self.expn_def_scope(ctxt.remove_mark()), None)); } if let ModuleKind::Block(..) = module.kind { @@ -2076,7 +2111,7 @@ impl<'a> Resolver<'a> { ModuleOrUniformRoot::Module(m) => { if let Some(def) = ident.span.normalize_to_macros_2_0_and_adjust(m.expansion) { tmp_parent_scope = - ParentScope { module: self.macro_def_scope(def), ..*parent_scope }; + ParentScope { module: self.expn_def_scope(def), ..*parent_scope }; adjusted_parent_scope = &tmp_parent_scope; } } @@ -2149,7 +2184,7 @@ impl<'a> Resolver<'a> { ctxt.adjust(ExpnId::root()) }; let module = match mark { - Some(def) => self.macro_def_scope(def), + Some(def) => self.expn_def_scope(def), None => { debug!( "resolve_crate_root({:?}): found no mark (ident.span = {:?})", @@ -2158,7 +2193,9 @@ impl<'a> Resolver<'a> { return self.graph_root; } }; - let module = self.get_module(DefId { index: CRATE_DEF_INDEX, ..module.nearest_parent_mod }); + let module = self.expect_module( + module.opt_def_id().map_or(LOCAL_CRATE, |def_id| def_id.krate).as_def_id(), + ); debug!( "resolve_crate_root({:?}): got module {:?} ({:?}) (ident.span = {:?})", ident, @@ -2170,10 +2207,10 @@ impl<'a> Resolver<'a> { } fn resolve_self(&mut self, ctxt: &mut SyntaxContext, module: Module<'a>) -> Module<'a> { - let mut module = self.get_module(module.nearest_parent_mod); + let mut module = self.expect_module(module.nearest_parent_mod()); while module.span.ctxt().normalize_to_macros_2_0() != *ctxt { - let parent = module.parent.unwrap_or_else(|| self.macro_def_scope(ctxt.remove_mark())); - module = self.get_module(parent.nearest_parent_mod); + let parent = module.parent.unwrap_or_else(|| self.expn_def_scope(ctxt.remove_mark())); + module = self.expect_module(parent.nearest_parent_mod()); } module } @@ -2518,7 +2555,22 @@ impl<'a> Resolver<'a> { (format!("use of undeclared type `{}`", ident), suggestion) } else { - (format!("use of undeclared crate or module `{}`", ident), None) + ( + 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())], + String::from( + "there is a crate or module with a similar name", + ), + Applicability::MaybeIncorrect, + ) + }), + ) } } else { let parent = path[i - 1].ident.name; @@ -2887,7 +2939,7 @@ impl<'a> Resolver<'a> { } fn is_accessible_from(&self, vis: ty::Visibility, module: Module<'a>) -> bool { - vis.is_accessible_from(module.nearest_parent_mod, self) + vis.is_accessible_from(module.nearest_parent_mod(), self) } fn set_binding_parent_module(&mut self, binding: &'a NameBinding<'a>, module: Module<'a>) { @@ -2911,7 +2963,7 @@ impl<'a> Resolver<'a> { self.binding_parent_modules.get(&PtrKey(modularized)), ) { (Some(macro_rules), Some(modularized)) => { - macro_rules.nearest_parent_mod == modularized.nearest_parent_mod + macro_rules.nearest_parent_mod() == modularized.nearest_parent_mod() && modularized.is_ancestor_of(macro_rules) } _ => false, @@ -2955,7 +3007,15 @@ impl<'a> Resolver<'a> { (None, false) }; if !candidates.is_empty() { - diagnostics::show_candidates(&mut err, span, &candidates, instead, found_use); + diagnostics::show_candidates( + &self.definitions, + self.session, + &mut err, + span, + &candidates, + instead, + found_use, + ); } else if let Some((span, msg, sugg, appl)) = suggestion { err.span_suggestion(span, msg, sugg, appl); } @@ -2977,7 +3037,7 @@ impl<'a> Resolver<'a> { } let container = match parent.kind { - ModuleKind::Def(kind, _, _) => kind.descr(parent.def_id().unwrap()), + ModuleKind::Def(kind, _, _) => kind.descr(parent.def_id()), ModuleKind::Block(..) => "block", }; @@ -3256,7 +3316,7 @@ impl<'a> Resolver<'a> { } else { self.crate_loader.maybe_process_path_extern(ident.name)? }; - let crate_root = self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX }); + let crate_root = self.expect_module(crate_id.as_def_id()); Some( (crate_root, ty::Visibility::Public, DUMMY_SP, LocalExpnId::ROOT) .to_name_binding(self.arenas), @@ -3297,7 +3357,7 @@ impl<'a> Resolver<'a> { tokens: None, } }; - let module = self.get_module(module_id); + let module = self.expect_module(module_id); let parent_scope = &ParentScope::module(module, self); let res = self.resolve_ast_path(&path, ns, parent_scope).map_err(|_| ())?; Ok((path, res)) @@ -3355,7 +3415,7 @@ impl<'a> Resolver<'a> { /// Retrieves the span of the given `DefId` if `DefId` is in the local crate. #[inline] pub fn opt_span(&self, def_id: DefId) -> Option { - if let Some(def_id) = def_id.as_local() { Some(self.def_id_to_span[def_id]) } else { None } + def_id.as_local().map(|def_id| self.definitions.def_span(def_id)) } /// Checks if an expression refers to a function marked with diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index 6dc3aa0888..4f6e23d8f8 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -180,6 +180,10 @@ impl<'a> ResolverExpand for Resolver<'a> { self.next_node_id() } + fn invocation_parent(&self, id: LocalExpnId) -> LocalDefId { + self.invocation_parents[&id].0 + } + fn resolve_dollar_crates(&mut self) { hygiene::update_dollar_crate_names(|ctxt| { let ident = Ident::new(kw::DollarCrate, DUMMY_SP.with_ctxt(ctxt)); @@ -221,7 +225,8 @@ impl<'a> ResolverExpand for Resolver<'a> { features: &[Symbol], parent_module_id: Option, ) -> LocalExpnId { - let parent_module = parent_module_id.map(|module_id| self.local_def_id(module_id)); + let parent_module = + parent_module_id.map(|module_id| self.local_def_id(module_id).to_def_id()); let expn_id = LocalExpnId::fresh( ExpnData::allow_unstable( ExpnKind::AstPass(pass), @@ -229,13 +234,13 @@ impl<'a> ResolverExpand for Resolver<'a> { self.session.edition(), features.into(), None, - parent_module.map(LocalDefId::to_def_id), + parent_module, ), self.create_stable_hashing_context(), ); - let parent_scope = parent_module - .map_or(self.empty_module, |parent_def_id| self.module_map[&parent_def_id]); + let parent_scope = + parent_module.map_or(self.empty_module, |def_id| self.expect_module(def_id)); self.ast_transform_scopes.insert(expn_id, parent_scope); expn_id @@ -294,51 +299,18 @@ impl<'a> ResolverExpand for Resolver<'a> { )?; let span = invoc.span(); + let def_id = res.opt_def_id(); invoc_id.set_expn_data( ext.expn_data( parent_scope.expansion, span, fast_print_path(path), - res.opt_def_id(), - res.opt_def_id().map(|macro_def_id| { - self.macro_def_scope_from_def_id(macro_def_id).nearest_parent_mod - }), + def_id, + def_id.map(|def_id| self.macro_def_scope(def_id).nearest_parent_mod()), ), self.create_stable_hashing_context(), ); - if let Res::Def(_, _) = res { - // Gate macro attributes in `#[derive]` output. - if !self.session.features_untracked().macro_attributes_in_derive_output - && kind == MacroKind::Attr - && ext.builtin_name != Some(sym::derive) - { - let mut expn_id = parent_scope.expansion; - loop { - // Helper attr table is a quick way to determine whether the attr is `derive`. - if self.helper_attrs.contains_key(&expn_id) { - feature_err( - &self.session.parse_sess, - sym::macro_attributes_in_derive_output, - path.span, - "macro attributes in `#[derive]` output are unstable", - ) - .emit(); - break; - } else { - let expn_data = expn_id.expn_data(); - match expn_data.kind { - ExpnKind::Root - | ExpnKind::Macro(MacroKind::Bang | MacroKind::Derive, _) => { - break; - } - _ => expn_id = expn_data.parent.expect_local(), - } - } - } - } - } - Ok(ext) } @@ -1165,7 +1137,7 @@ impl<'a> Resolver<'a> { } if let Some(depr) = &ext.deprecation { let path = pprust::path_to_string(&path); - let (message, lint) = stability::deprecation_message(depr, "macro", &path); + let (message, lint) = stability::deprecation_message_and_lint(depr, "macro", &path); stability::early_report_deprecation( &mut self.lint_buffer, &message, diff --git a/compiler/rustc_save_analysis/Cargo.toml b/compiler/rustc_save_analysis/Cargo.toml index 535a48bcda..15a89d82fa 100644 --- a/compiler/rustc_save_analysis/Cargo.toml +++ b/compiler/rustc_save_analysis/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustc_save_analysis" version = "0.0.0" -edition = "2018" +edition = "2021" [dependencies] tracing = "0.1" diff --git a/compiler/rustc_save_analysis/src/dump_visitor.rs b/compiler/rustc_save_analysis/src/dump_visitor.rs index 29068761d6..f4567b3348 100644 --- a/compiler/rustc_save_analysis/src/dump_visitor.rs +++ b/compiler/rustc_save_analysis/src/dump_visitor.rs @@ -18,7 +18,7 @@ use rustc_ast::walk_list; use rustc_data_structures::fx::FxHashSet; use rustc_hir as hir; use rustc_hir::def::{DefKind as HirDefKind, Res}; -use rustc_hir::def_id::{DefId, LocalDefId}; +use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID}; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir_pretty::{bounds_to_string, fn_to_string, generic_params_to_string, ty_to_string}; use rustc_middle::hir::map::Map; @@ -128,7 +128,7 @@ impl<'tcx> DumpVisitor<'tcx> { self.save_ctxt.lookup_def_id(ref_id) } - pub fn dump_crate_info(&mut self, name: &str, krate: &hir::Crate<'_>) { + pub fn dump_crate_info(&mut self, name: &str) { let source_file = self.tcx.sess.local_crate_source_file.as_ref(); let crate_root = source_file.map(|source_file| { let source_file = Path::new(source_file); @@ -146,7 +146,7 @@ impl<'tcx> DumpVisitor<'tcx> { }, crate_root: crate_root.unwrap_or_else(|| "".to_owned()), external_crates: self.save_ctxt.get_external_crates(), - span: self.span_from_span(krate.module().inner), + span: self.span_from_span(self.tcx.def_span(CRATE_DEF_ID)), }; self.dumper.crate_prelude(data); @@ -682,7 +682,7 @@ impl<'tcx> DumpVisitor<'tcx> { ); } - // super-traits + // supertraits for super_bound in trait_refs.iter() { let (def_id, sub_span) = match *super_bound { hir::GenericBound::Trait(ref trait_ref, _) => ( @@ -693,7 +693,6 @@ impl<'tcx> DumpVisitor<'tcx> { (Some(self.tcx.require_lang_item(lang_item, Some(span))), span) } hir::GenericBound::Outlives(..) => continue, - hir::GenericBound::Unsized(_) => continue, }; if let Some(id) = def_id { @@ -1091,13 +1090,13 @@ impl<'tcx> DumpVisitor<'tcx> { } } - pub(crate) fn process_crate(&mut self, krate: &'tcx hir::Crate<'tcx>) { + pub(crate) fn process_crate(&mut self) { let id = hir::CRATE_HIR_ID; let qualname = format!("::{}", self.tcx.def_path_str(self.tcx.hir().local_def_id(id).to_def_id())); let sm = self.tcx.sess.source_map(); - let krate_mod = krate.module(); + let krate_mod = self.tcx.hir().root_module(); let filename = sm.span_to_filename(krate_mod.inner); let data_id = id_from_hir_id(id, &self.save_ctxt); let children = @@ -1122,7 +1121,7 @@ impl<'tcx> DumpVisitor<'tcx> { attributes: lower_attributes(attrs.to_owned(), &self.save_ctxt), }, ); - intravisit::walk_crate(self, krate); + self.tcx.hir().walk_toplevel_module(self); } fn process_bounds(&mut self, bounds: hir::GenericBounds<'tcx>) { diff --git a/compiler/rustc_save_analysis/src/lib.rs b/compiler/rustc_save_analysis/src/lib.rs index 41d174cde0..543cd0247a 100644 --- a/compiler/rustc_save_analysis/src/lib.rs +++ b/compiler/rustc_save_analysis/src/lib.rs @@ -1,7 +1,6 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![feature(if_let_guard)] #![feature(nll)] -#![cfg_attr(bootstrap, allow(incomplete_features))] // if_let_guard #![recursion_limit = "256"] mod dump_visitor; @@ -20,11 +19,11 @@ use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::Node; use rustc_hir_pretty::{enum_def_to_string, fn_to_string, ty_to_string}; use rustc_middle::hir::map::Map; -use rustc_middle::middle::cstore::ExternCrate; use rustc_middle::middle::privacy::AccessLevels; use rustc_middle::ty::{self, print::with_no_trimmed_paths, DefIdTree, TyCtxt}; use rustc_middle::{bug, span_bug}; use rustc_session::config::{CrateType, Input, OutputType}; +use rustc_session::cstore::ExternCrate; use rustc_session::output::{filename_for_metadata, out_filename}; use rustc_span::source_map::Spanned; use rustc_span::symbol::Ident; @@ -1004,9 +1003,9 @@ pub fn process_crate<'l, 'tcx, H: SaveHandler>( let mut visitor = DumpVisitor::new(save_ctxt); - visitor.dump_crate_info(cratename, tcx.hir().krate()); + visitor.dump_crate_info(cratename); visitor.dump_compilation_options(input, cratename); - visitor.process_crate(tcx.hir().krate()); + visitor.process_crate(); handler.save(&visitor.save_ctxt, &visitor.analysis()) }) diff --git a/compiler/rustc_serialize/Cargo.toml b/compiler/rustc_serialize/Cargo.toml index 593a7563e3..49778f8225 100644 --- a/compiler/rustc_serialize/Cargo.toml +++ b/compiler/rustc_serialize/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustc_serialize" version = "0.0.0" -edition = "2018" +edition = "2021" [dependencies] indexmap = "1" diff --git a/compiler/rustc_serialize/src/serialize.rs b/compiler/rustc_serialize/src/serialize.rs index ecc8dae048..6671c7c0fa 100644 --- a/compiler/rustc_serialize/src/serialize.rs +++ b/compiler/rustc_serialize/src/serialize.rs @@ -366,6 +366,18 @@ direct_serialize_impls! { char emit_char read_char } +impl Encodable for ! { + fn encode(&self, _s: &mut S) -> Result<(), S::Error> { + unreachable!() + } +} + +impl Decodable for ! { + fn decode(_d: &mut D) -> Result { + unreachable!() + } +} + impl Encodable for ::std::num::NonZeroU32 { fn encode(&self, s: &mut S) -> Result<(), S::Error> { s.emit_u32(self.get()) @@ -488,8 +500,8 @@ impl Decodable for [u8; N] { d.read_seq(|d, len| { assert!(len == N); let mut v = [0u8; N]; - for i in 0..len { - v[i] = d.read_seq_elt(|d| Decodable::decode(d))?; + for x in &mut v { + *x = d.read_seq_elt(|d| Decodable::decode(d))?; } Ok(v) }) diff --git a/compiler/rustc_session/Cargo.toml b/compiler/rustc_session/Cargo.toml index 5b617a2997..37cfc4a0dc 100644 --- a/compiler/rustc_session/Cargo.toml +++ b/compiler/rustc_session/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustc_session" version = "0.0.0" -edition = "2018" +edition = "2021" [dependencies] getopts = "0.2" @@ -9,6 +9,7 @@ rustc_macros = { path = "../rustc_macros" } tracing = "0.1" rustc_errors = { path = "../rustc_errors" } rustc_feature = { path = "../rustc_feature" } +rustc_hir = { path = "../rustc_hir" } rustc_target = { path = "../rustc_target" } rustc_serialize = { path = "../rustc_serialize" } rustc_data_structures = { path = "../rustc_data_structures" } diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index fdedb7e6a4..ac4bce7350 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -1920,9 +1920,10 @@ fn parse_extern_dep_specs( fn parse_remap_path_prefix( matches: &getopts::Matches, + debugging_opts: &DebuggingOptions, error_format: ErrorOutputType, ) -> Vec<(PathBuf, PathBuf)> { - matches + let mut mapping: Vec<(PathBuf, PathBuf)> = matches .opt_strs("remap-path-prefix") .into_iter() .map(|remap| match remap.rsplit_once('=') { @@ -1932,7 +1933,15 @@ fn parse_remap_path_prefix( ), Some((from, to)) => (PathBuf::from(from), PathBuf::from(to)), }) - .collect() + .collect(); + match &debugging_opts.remap_cwd_prefix { + Some(to) => match std::env::current_dir() { + Ok(cwd) => mapping.push((cwd, to.clone())), + Err(_) => (), + }, + None => (), + }; + mapping } pub fn build_session_options(matches: &getopts::Matches) -> Options { @@ -2000,6 +2009,15 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { ); } + if debugging_opts.profile_sample_use.is_some() + && (cg.profile_generate.enabled() || cg.profile_use.is_some()) + { + early_error( + error_format, + "option `-Z profile-sample-use` cannot be used with `-C profile-generate` or `-C profile-use`", + ); + } + if debugging_opts.instrument_coverage.is_some() && debugging_opts.instrument_coverage != Some(InstrumentCoverage::Off) { @@ -2077,7 +2095,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { let crate_name = matches.opt_str("crate-name"); - let remap_path_prefix = parse_remap_path_prefix(matches, error_format); + let remap_path_prefix = parse_remap_path_prefix(matches, &debugging_opts, error_format); let pretty = parse_pretty(&debugging_opts, error_format); diff --git a/compiler/rustc_middle/src/middle/cstore.rs b/compiler/rustc_session/src/cstore.rs similarity index 86% rename from compiler/rustc_middle/src/middle/cstore.rs rename to compiler/rustc_session/src/cstore.rs index 8150e67929..59e7abc2ea 100644 --- a/compiler/rustc_middle/src/middle/cstore.rs +++ b/compiler/rustc_session/src/cstore.rs @@ -2,15 +2,13 @@ //! are *mostly* used as a part of that interface, but these should //! probably get a better home if someone can find one. -use crate::ty::TyCtxt; - +use crate::search_paths::PathKind; +use crate::utils::NativeLibKind; +use crate::Session; use rustc_ast as ast; use rustc_data_structures::sync::{self, MetadataRef}; use rustc_hir::def_id::{CrateNum, DefId, StableCrateId, LOCAL_CRATE}; use rustc_hir::definitions::{DefKey, DefPath, DefPathHash}; -use rustc_macros::HashStable; -use rustc_session::search_paths::PathKind; -use rustc_session::utils::NativeLibKind; use rustc_span::hygiene::{ExpnHash, ExpnId}; use rustc_span::symbol::Symbol; use rustc_span::Span; @@ -23,7 +21,7 @@ use std::path::{Path, PathBuf}; /// Where a crate came from on the local filesystem. One of these three options /// must be non-None. -#[derive(PartialEq, Clone, Debug, HashStable, Encodable, Decodable)] +#[derive(PartialEq, Clone, Debug, HashStable_Generic, Encodable, Decodable)] pub struct CrateSource { pub dylib: Option<(PathBuf, PathKind)>, pub rlib: Option<(PathBuf, PathKind)>, @@ -31,13 +29,14 @@ pub struct CrateSource { } impl CrateSource { + #[inline] pub fn paths(&self) -> impl Iterator { self.dylib.iter().chain(self.rlib.iter()).chain(self.rmeta.iter()).map(|p| &p.0) } } #[derive(Encodable, Decodable, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Debug)] -#[derive(HashStable)] +#[derive(HashStable_Generic)] pub enum CrateDepKind { /// A dependency that is only used for its macros. MacrosOnly, @@ -50,6 +49,7 @@ pub enum CrateDepKind { } impl CrateDepKind { + #[inline] pub fn macros_only(self) -> bool { match self { CrateDepKind::MacrosOnly => true, @@ -58,13 +58,13 @@ impl CrateDepKind { } } -#[derive(Copy, Debug, PartialEq, Clone, Encodable, Decodable, HashStable)] +#[derive(Copy, Debug, PartialEq, Clone, Encodable, Decodable, HashStable_Generic)] pub enum LinkagePreference { RequireDynamic, RequireStatic, } -#[derive(Debug, Encodable, Decodable, HashStable)] +#[derive(Debug, Encodable, Decodable, HashStable_Generic)] pub struct NativeLib { pub kind: NativeLibKind, pub name: Option, @@ -75,7 +75,7 @@ pub struct NativeLib { pub dll_imports: Vec, } -#[derive(Clone, Debug, Encodable, Decodable, HashStable)] +#[derive(Clone, Debug, Encodable, Decodable, HashStable_Generic)] pub struct DllImport { pub name: Symbol, pub ordinal: Option, @@ -92,7 +92,7 @@ pub struct DllImport { /// /// The usize value, where present, indicates the size of the function's argument list /// in bytes. -#[derive(Clone, PartialEq, Debug, Encodable, Decodable, HashStable)] +#[derive(Clone, PartialEq, Debug, Encodable, Decodable, HashStable_Generic)] pub enum DllCallingConvention { C, Stdcall(usize), @@ -100,13 +100,13 @@ pub enum DllCallingConvention { Vectorcall(usize), } -#[derive(Clone, TyEncodable, TyDecodable, HashStable, Debug)] +#[derive(Clone, Encodable, Decodable, HashStable_Generic, Debug)] pub struct ForeignModule { pub foreign_items: Vec, pub def_id: DefId, } -#[derive(Copy, Clone, Debug, HashStable)] +#[derive(Copy, Clone, Debug, HashStable_Generic)] pub struct ExternCrate { pub src: ExternCrateSource, @@ -125,10 +125,12 @@ impl ExternCrate { /// If true, then this crate is the crate named by the extern /// crate referenced above. If false, then this crate is a dep /// of the crate. + #[inline] pub fn is_direct(&self) -> bool { self.dependency_of == LOCAL_CRATE } + #[inline] pub fn rank(&self) -> impl PartialOrd { // Prefer: // - direct extern crate to indirect @@ -137,7 +139,7 @@ impl ExternCrate { } } -#[derive(Copy, Clone, Debug, HashStable)] +#[derive(Copy, Clone, Debug, HashStable_Generic)] pub enum ExternCrateSource { /// Crate is loaded by `extern crate`. Extern( @@ -150,17 +152,6 @@ pub enum ExternCrateSource { Path, } -#[derive(Encodable, Decodable)] -pub struct EncodedMetadata { - pub raw_data: Vec, -} - -impl EncodedMetadata { - pub fn new() -> EncodedMetadata { - EncodedMetadata { raw_data: Vec::new() } - } -} - /// The backend's way to give the crate store access to the metadata in a library. /// Note that it returns the raw metadata bytes stored in the library file, whether /// it is compressed, uncompressed, some weird mix, etc. @@ -199,18 +190,17 @@ pub trait CrateStore: std::fmt::Debug { // incr. comp. uses to identify a CrateNum. fn crate_name(&self, cnum: CrateNum) -> Symbol; fn stable_crate_id(&self, cnum: CrateNum) -> StableCrateId; + fn stable_crate_id_to_crate_num(&self, stable_crate_id: StableCrateId) -> CrateNum; /// Fetch a DefId from a DefPathHash for a foreign crate. - fn def_path_hash_to_def_id( + fn def_path_hash_to_def_id(&self, cnum: CrateNum, hash: DefPathHash) -> DefId; + fn expn_hash_to_expn_id( &self, + sess: &Session, cnum: CrateNum, index_guess: u32, - hash: DefPathHash, - ) -> Option; - fn expn_hash_to_expn_id(&self, cnum: CrateNum, index_guess: u32, hash: ExpnHash) -> ExpnId; - - // utility functions - fn encode_metadata(&self, tcx: TyCtxt<'_>) -> EncodedMetadata; + hash: ExpnHash, + ) -> ExpnId; } pub type CrateStoreDyn = dyn CrateStore + sync::Sync; diff --git a/compiler/rustc_session/src/filesearch.rs b/compiler/rustc_session/src/filesearch.rs index 6fe6a555f1..9359a55e55 100644 --- a/compiler/rustc_session/src/filesearch.rs +++ b/compiler/rustc_session/src/filesearch.rs @@ -1,3 +1,5 @@ +//! A module for searching for libraries + pub use self::FileMatch::*; use std::env; @@ -14,8 +16,6 @@ pub enum FileMatch { FileDoesntMatch, } -// A module for searching for libraries - #[derive(Clone)] pub struct FileSearch<'a> { sysroot: &'a Path, @@ -83,22 +83,10 @@ impl<'a> FileSearch<'a> { FileSearch { sysroot, triple, search_paths, tlib_path, kind } } - // Returns just the directories within the search paths. + /// Returns just the directories within the search paths. pub fn search_path_dirs(&self) -> Vec { self.search_paths().map(|sp| sp.dir.to_path_buf()).collect() } - - // Returns a list of directories where target-specific tool binaries are located. - pub fn get_tools_search_paths(&self, self_contained: bool) -> Vec { - let rustlib_path = rustc_target::target_rustlib_path(self.sysroot, &self.triple); - let p = std::array::IntoIter::new([ - Path::new(&self.sysroot), - Path::new(&rustlib_path), - Path::new("bin"), - ]) - .collect::(); - if self_contained { vec![p.clone(), p.join("self-contained")] } else { vec![p] } - } } pub fn make_target_lib_path(sysroot: &Path, target_triple: &str) -> PathBuf { @@ -107,8 +95,8 @@ pub fn make_target_lib_path(sysroot: &Path, target_triple: &str) -> PathBuf { .collect::() } -// This function checks if sysroot is found using env::args().next(), and if it -// is not found, uses env::current_exe() to imply sysroot. +/// This function checks if sysroot is found using env::args().next(), and if it +/// is not found, uses env::current_exe() to imply sysroot. pub fn get_or_default_sysroot() -> PathBuf { // Follow symlinks. If the resolved path is relative, make it absolute. fn canonicalize(path: PathBuf) -> PathBuf { diff --git a/compiler/rustc_session/src/lib.rs b/compiler/rustc_session/src/lib.rs index 9a82ae3fc1..6c86f86ecd 100644 --- a/compiler/rustc_session/src/lib.rs +++ b/compiler/rustc_session/src/lib.rs @@ -1,4 +1,5 @@ #![feature(crate_visibility_modifier)] +#![feature(min_specialization)] #![feature(once_cell)] #![recursion_limit = "256"] @@ -14,6 +15,7 @@ pub mod parse; mod code_stats; #[macro_use] pub mod config; +pub mod cstore; pub mod filesearch; mod options; pub mod search_paths; @@ -28,4 +30,4 @@ pub use getopts; /// Requirements for a `StableHashingContext` to be used in this crate. /// This is a hack to allow using the `HashStable_Generic` derive macro /// instead of implementing everything in `rustc_middle`. -pub trait HashStableContext {} +pub trait HashStableContext: rustc_ast::HashStableContext + rustc_hir::HashStableContext {} diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 9a1be40558..b3d36b396c 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -349,6 +349,7 @@ mod desc { pub const parse_threads: &str = parse_number; pub const parse_passes: &str = "a space-separated list of passes, or `all`"; pub const parse_panic_strategy: &str = "either `unwind` or `abort`"; + pub const parse_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`"; @@ -549,7 +550,7 @@ mod parse { } } - crate fn parse_panic_strategy(slot: &mut Option, v: Option<&str>) -> bool { + crate fn parse_opt_panic_strategy(slot: &mut Option, v: Option<&str>) -> bool { match v { Some("unwind") => *slot = Some(PanicStrategy::Unwind), Some("abort") => *slot = Some(PanicStrategy::Abort), @@ -558,6 +559,15 @@ mod parse { true } + crate fn parse_panic_strategy(slot: &mut PanicStrategy, v: Option<&str>) -> bool { + match v { + Some("unwind") => *slot = PanicStrategy::Unwind, + Some("abort") => *slot = PanicStrategy::Abort, + _ => return false, + } + true + } + crate fn parse_relro_level(slot: &mut Option, v: Option<&str>) -> bool { match v { Some(s) => match s.parse::() { @@ -958,7 +968,7 @@ options! { "optimization level (0-3, s, or z; default: 0)"), overflow_checks: Option = (None, parse_opt_bool, [TRACKED], "use overflow checks for integer arithmetic"), - panic: Option = (None, parse_panic_strategy, [TRACKED], + panic: Option = (None, parse_opt_panic_strategy, [TRACKED], "panic strategy to compile crate with"), passes: Vec = (Vec::new(), parse_list, [TRACKED], "a list of extra LLVM passes to run (space separated)"), @@ -1030,6 +1040,8 @@ options! { "combine CGUs into a single one"), crate_attr: Vec = (Vec::new(), parse_string_push, [TRACKED], "inject the given attribute in the crate"), + debug_info_for_profiling: bool = (false, parse_bool, [TRACKED], + "emit discriminators and other data necessary for AutoFDO"), debug_macros: bool = (false, parse_bool, [TRACKED], "emit line numbers debug info inside macros (default: no)"), deduplicate_diagnostics: bool = (true, parse_bool, [UNTRACKED], @@ -1106,6 +1118,8 @@ options! { incremental_info: bool = (false, parse_bool, [UNTRACKED], "print high-level information about incremental reuse (or the lack thereof) \ (default: no)"), + incremental_relative_spans: bool = (false, parse_bool, [TRACKED], + "hash spans relative to their parent item for incr. comp. (default: no)"), incremental_verify_ich: bool = (false, parse_bool, [UNTRACKED], "verify incr. comp. hashes of green query instances (default: no)"), inline_mir: Option = (None, parse_opt_bool, [TRACKED], @@ -1184,6 +1198,8 @@ options! { "pass `-install_name @rpath/...` to the macOS linker (default: no)"), panic_abort_tests: bool = (false, parse_bool, [TRACKED], "support compiling tests with panic=abort (default: no)"), + panic_in_drop: PanicStrategy = (PanicStrategy::Unwind, parse_panic_strategy, [TRACKED], + "panic strategy for panics in drops"), parse_only: bool = (false, parse_bool, [UNTRACKED], "parse only; do not compile, assemble, or link (default: no)"), partially_uninit_const_threshold: Option = (None, parse_opt_number, [TRACKED], @@ -1228,14 +1244,20 @@ options! { (default based on relative source path)"), profiler_runtime: String = (String::from("profiler_builtins"), parse_string, [TRACKED], "name of the profiler runtime crate to automatically inject (default: `profiler_builtins`)"), + profile_sample_use: Option = (None, parse_opt_pathbuf, [TRACKED], + "use the given `.prof` file for sampled profile-guided optimization (also known as AutoFDO)"), query_dep_graph: bool = (false, parse_bool, [UNTRACKED], "enable queries of the dependency graph for regression testing (default: no)"), query_stats: bool = (false, parse_bool, [UNTRACKED], "print some statistics about the query system (default: no)"), + randomize_layout: bool = (false, parse_bool, [TRACKED], + "randomize the layout of types (default: no)"), relax_elf_relocations: Option = (None, parse_opt_bool, [TRACKED], "whether ELF relocations can be relaxed"), relro_level: Option = (None, parse_relro_level, [TRACKED], "choose which RELRO level to use"), + remap_cwd_prefix: Option = (None, parse_opt_pathbuf, [TRACKED], + "remap paths under the current working directory to this path prefix"), simulate_remapped_rust_src_base: Option = (None, parse_opt_pathbuf, [TRACKED], "simulate the effect of remap-debuginfo = true at bootstrapping by remapping path \ to rust's source base directory. only meant for testing purposes"), diff --git a/compiler/rustc_session/src/search_paths.rs b/compiler/rustc_session/src/search_paths.rs index 83b737a73b..acb6c735e0 100644 --- a/compiler/rustc_session/src/search_paths.rs +++ b/compiler/rustc_session/src/search_paths.rs @@ -9,17 +9,17 @@ pub struct SearchPath { pub files: Vec, } -// The obvious implementation of `SearchPath::files` is a `Vec`. But -// it is searched repeatedly by `find_library_crate`, and the searches involve -// checking the prefix and suffix of the filename of each `PathBuf`. This is -// doable, but very slow, because it involves calls to `file_name` and -// `extension` that are themselves slow. -// -// This type augments the `PathBuf` with an `Option` containing the -// `PathBuf`'s filename. The prefix and suffix checking is much faster on the -// `Option` than the `PathBuf`. (It's an `Option` because -// `Path::file_name` can fail; if that happens then all subsequent checking -// will also fail, which is fine.) +/// The obvious implementation of `SearchPath::files` is a `Vec`. But +/// it is searched repeatedly by `find_library_crate`, and the searches involve +/// checking the prefix and suffix of the filename of each `PathBuf`. This is +/// doable, but very slow, because it involves calls to `file_name` and +/// `extension` that are themselves slow. +/// +/// This type augments the `PathBuf` with an `Option` containing the +/// `PathBuf`'s filename. The prefix and suffix checking is much faster on the +/// `Option` than the `PathBuf`. (It's an `Option` because +/// `Path::file_name` can fail; if that happens then all subsequent checking +/// will also fail, which is fine.) #[derive(Clone, Debug)] pub struct SearchPathFile { pub path: PathBuf, diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 0f7db69fef..b6ba6cc1dd 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -2,10 +2,9 @@ use crate::cgu_reuse_tracker::CguReuseTracker; use crate::code_stats::CodeStats; pub use crate::code_stats::{DataTypeKind, FieldInfo, SizeKind, VariantInfo}; use crate::config::{self, CrateType, OutputType, SwitchWithOptPath}; -use crate::filesearch; -use crate::lint::{self, LintId}; use crate::parse::ParseSess; use crate::search_paths::{PathKind, SearchPath}; +use crate::{filesearch, lint}; pub use rustc_ast::attr::MarkedAttrs; pub use rustc_ast::Attribute; @@ -36,15 +35,11 @@ use std::fmt; use std::io::Write; use std::num::NonZeroU32; use std::ops::{Div, Mul}; -use std::path::PathBuf; +use std::path::{Path, PathBuf}; use std::str::FromStr; use std::sync::Arc; use std::time::Duration; -pub trait SessionLintStore: sync::Send + sync::Sync { - fn name_to_lint(&self, lint_name: &str) -> LintId; -} - pub struct OptimizationFuel { /// If `-zfuel=crate=n` is specified, initially set to `n`, otherwise `0`. remaining: u64, @@ -131,9 +126,8 @@ pub struct Session { pub target: Target, pub host: Target, pub opts: config::Options, - pub host_tlib_path: SearchPath, - /// `None` if the host and target are the same. - pub target_tlib_path: Option, + pub host_tlib_path: Lrc, + pub target_tlib_path: Lrc, pub parse_sess: ParseSess, pub sysroot: PathBuf, /// The name of the root source file of the crate, in the local file system. @@ -154,8 +148,6 @@ pub struct Session { features: OnceCell, - lint_store: OnceCell>, - incr_comp_session: OneThread>, /// Used for incremental compilation tests. Will only be populated if /// `-Zquery-dep-graph` is specified. @@ -183,10 +175,6 @@ pub struct Session { /// Cap lint level specified by a driver specifically. pub driver_lint_caps: FxHashMap, - /// Mapping from ident span to path span for paths that don't exist as written, but that - /// exist under `std`. For example, wrote `str::from_utf8` instead of `std::str::from_utf8`. - pub confused_type_with_std_module: Lock>, - /// Tracks the current behavior of the CTFE engine when an error occurs. /// Options range from returning the error without a backtrace to returning an error /// and immediately printing the backtrace to stderr. @@ -593,13 +581,6 @@ impl Session { } } - pub fn init_lint_store(&self, lint_store: Lrc) { - self.lint_store - .set(lint_store) - .map_err(|_| ()) - .expect("`lint_store` was initialized twice"); - } - /// Calculates the flavor of LTO to use for this compilation. pub fn lto(&self) -> config::Lto { // If our target has codegen requirements ignore the command line @@ -788,8 +769,7 @@ impl Session { &self.sysroot, self.opts.target_triple.triple(), &self.opts.search_paths, - // `target_tlib_path == None` means it's the same as `host_tlib_path`. - self.target_tlib_path.as_ref().unwrap_or(&self.host_tlib_path), + &self.target_tlib_path, kind, ) } @@ -803,6 +783,18 @@ impl Session { ) } + /// Returns a list of directories where target-specific tool binaries are located. + pub fn get_tools_search_paths(&self, self_contained: bool) -> Vec { + let rustlib_path = rustc_target::target_rustlib_path(&self.sysroot, &config::host_triple()); + let p = std::array::IntoIter::new([ + Path::new(&self.sysroot), + Path::new(&rustlib_path), + Path::new("bin"), + ]) + .collect::(); + if self_contained { vec![p.clone(), p.join("self-contained")] } else { vec![p] } + } + pub fn init_incr_comp_session( &self, session_dir: PathBuf, @@ -887,13 +879,18 @@ impl Session { /// This expends fuel if applicable, and records fuel if applicable. pub fn consider_optimizing String>(&self, crate_name: &str, msg: T) -> bool { let mut ret = true; - if let Some(c) = self.opts.debugging_opts.fuel.as_ref().map(|i| &i.0) { + if let Some((ref c, _)) = self.opts.debugging_opts.fuel { if c == crate_name { assert_eq!(self.threads(), 1); let mut fuel = self.optimization_fuel.lock(); ret = fuel.remaining != 0; if fuel.remaining == 0 && !fuel.out_of_fuel { - self.warn(&format!("optimization-fuel-exhausted: {}", msg())); + if self.diagnostic().can_emit_warnings() { + // We only call `msg` in case we can actually emit warnings. + // Otherwise, this could cause a `delay_good_path_bug` to + // trigger (issue #79546). + self.warn(&format!("optimization-fuel-exhausted: {}", msg())); + } fuel.out_of_fuel = true; } else if fuel.remaining > 0 { fuel.remaining -= 1; @@ -1246,11 +1243,13 @@ pub fn build_session( let host_triple = config::host_triple(); let target_triple = sopts.target_triple.triple(); - let host_tlib_path = SearchPath::from_sysroot_and_triple(&sysroot, host_triple); + let host_tlib_path = Lrc::new(SearchPath::from_sysroot_and_triple(&sysroot, host_triple)); let target_tlib_path = if host_triple == target_triple { - None + // Use the same `SearchPath` if host and target triple are identical to avoid unnecessary + // rescanning of the target lib path and an unnecessary allocation. + host_tlib_path.clone() } else { - Some(SearchPath::from_sysroot_and_triple(&sysroot, target_triple)) + Lrc::new(SearchPath::from_sysroot_and_triple(&sysroot, target_triple)) }; let file_path_mapping = sopts.file_path_mapping(); @@ -1298,7 +1297,6 @@ pub fn build_session( crate_types: OnceCell::new(), stable_crate_id: OnceCell::new(), features: OnceCell::new(), - lint_store: OnceCell::new(), incr_comp_session: OneThread::new(RefCell::new(IncrCompSession::NotInitialized)), cgu_reuse_tracker, prof, @@ -1313,7 +1311,6 @@ pub fn build_session( print_fuel, jobserver: jobserver::client(), driver_lint_caps, - confused_type_with_std_module: Lock::new(Default::default()), ctfe_backtrace, miri_unleashed_features: Lock::new(Default::default()), asm_arch, @@ -1356,6 +1353,16 @@ fn validate_commandline_args_with_session_available(sess: &Session) { } } + // Do the same for sample profile data. + if let Some(ref path) = sess.opts.debugging_opts.profile_sample_use { + if !path.exists() { + sess.err(&format!( + "File `{}` passed to `-C profile-sample-use` does not exist.", + path.display() + )); + } + } + // Unwind tables cannot be disabled if the target requires them. if let Some(include_uwtables) = sess.opts.cg.force_unwind_tables { if sess.target.requires_uwtable && !include_uwtables { @@ -1387,7 +1394,7 @@ fn validate_commandline_args_with_session_available(sess: &Session) { // Cannot enable crt-static with sanitizers on Linux if sess.crt_static(None) && !sess.opts.debugging_opts.sanitizer.is_empty() { sess.err( - "Sanitizer is incompatible with statically linked libc, \ + "sanitizer is incompatible with statically linked libc, \ disable it using `-C target-feature=-crt-static`", ); } diff --git a/compiler/rustc_span/Cargo.toml b/compiler/rustc_span/Cargo.toml index e475e89d87..781fb8c1e5 100644 --- a/compiler/rustc_span/Cargo.toml +++ b/compiler/rustc_span/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustc_span" version = "0.0.0" -edition = "2018" +edition = "2021" [lib] doctest = false diff --git a/compiler/rustc_span/src/caching_source_map_view.rs b/compiler/rustc_span/src/caching_source_map_view.rs index 8e21b9ff44..fdabf404a3 100644 --- a/compiler/rustc_span/src/caching_source_map_view.rs +++ b/compiler/rustc_span/src/caching_source_map_view.rs @@ -215,13 +215,13 @@ impl<'sm> CachingSourceMapView<'sm> { // Span lo and hi may equal line end when last line doesn't // end in newline, hence the inclusive upper bounds below. - debug_assert!(span_data.lo >= lo.line.start); - debug_assert!(span_data.lo <= lo.line.end); - debug_assert!(span_data.hi >= hi.line.start); - debug_assert!(span_data.hi <= hi.line.end); - debug_assert!(lo.file.contains(span_data.lo)); - debug_assert!(lo.file.contains(span_data.hi)); - debug_assert_eq!(lo.file_index, hi.file_index); + assert!(span_data.lo >= lo.line.start); + assert!(span_data.lo <= lo.line.end); + assert!(span_data.hi >= hi.line.start); + assert!(span_data.hi <= hi.line.end); + assert!(lo.file.contains(span_data.lo)); + assert!(lo.file.contains(span_data.hi)); + assert_eq!(lo.file_index, hi.file_index); Some(( lo.file.clone(), diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs index c22093c5a4..aa15febe88 100644 --- a/compiler/rustc_span/src/hygiene.rs +++ b/compiler/rustc_span/src/hygiene.rs @@ -601,7 +601,10 @@ pub fn debug_hygiene_data(verbose: bool) -> String { let expn_data = expn_data.as_ref().expect("no expansion data for an expansion ID"); debug_expn_data((&id.to_expn_id(), expn_data)) }); - data.foreign_expn_data.iter().for_each(debug_expn_data); + // Sort the hash map for more reproducible output. + let mut foreign_expn_data: Vec<_> = data.foreign_expn_data.iter().collect(); + foreign_expn_data.sort_by_key(|(id, _)| (id.krate, id.local_id)); + foreign_expn_data.into_iter().for_each(debug_expn_data); s.push_str("\n\nSyntaxContexts:"); data.syntax_context_data.iter().enumerate().for_each(|(id, ctxt)| { s.push_str(&format!( @@ -1098,6 +1101,7 @@ pub enum DesugaringKind { Await, ForLoop(ForLoopLoc), LetElse, + WhileLoop, } /// A location in the desugaring of a `for` loop @@ -1119,6 +1123,7 @@ impl DesugaringKind { DesugaringKind::OpaqueTy => "`impl Trait`", DesugaringKind::ForLoop(_) => "`for` loop", DesugaringKind::LetElse => "`let...else`", + DesugaringKind::WhileLoop => "`while` loop", } } } @@ -1357,9 +1362,7 @@ fn for_all_expns_in( mut f: impl FnMut(ExpnId, &ExpnData, ExpnHash) -> Result<(), E>, ) -> Result<(), E> { let all_data: Vec<_> = HygieneData::with(|data| { - expns - .map(|expn| (expn, data.expn_data(expn).clone(), data.expn_hash(expn).clone())) - .collect() + expns.map(|expn| (expn, data.expn_data(expn).clone(), data.expn_hash(expn))).collect() }); for (expn, data, hash) in all_data.into_iter() { f(expn, &data, hash)?; diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index b4cc8b2b4a..032ae73bbf 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -21,11 +21,13 @@ #![feature(nll)] #![feature(min_specialization)] #![feature(thread_local_const_init)] -#![cfg_attr(bootstrap, allow(incomplete_features))] // if_let_guard #[macro_use] extern crate rustc_macros; +#[macro_use] +extern crate tracing; + use rustc_data_structures::AtomicRef; use rustc_macros::HashStable_Generic; use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; @@ -42,7 +44,7 @@ use hygiene::Transparency; pub use hygiene::{DesugaringKind, ExpnKind, ForLoopLoc, MacroKind}; pub use hygiene::{ExpnData, ExpnHash, ExpnId, LocalExpnId, SyntaxContext}; pub mod def_id; -use def_id::{CrateNum, DefId, DefPathHash, LOCAL_CRATE}; +use def_id::{CrateNum, DefId, DefPathHash, LocalDefId, LOCAL_CRATE}; pub mod lev_distance; mod span_encoding; pub use span_encoding::{Span, DUMMY_SP}; @@ -79,7 +81,7 @@ mod tests; // threads within the compilation session, but is not accessible outside the // session. pub struct SessionGlobals { - symbol_interner: Lock, + symbol_interner: symbol::Interner, span_interner: Lock, hygiene_data: Lock, source_map: Lock>>, @@ -88,7 +90,7 @@ pub struct SessionGlobals { impl SessionGlobals { pub fn new(edition: Edition) -> SessionGlobals { SessionGlobals { - symbol_interner: Lock::new(symbol::Interner::fresh()), + symbol_interner: symbol::Interner::fresh(), span_interner: Lock::new(span_encoding::SpanInterner::default()), hygiene_data: Lock::new(hygiene::HygieneData::new(edition)), source_map: Lock::new(None), @@ -435,24 +437,38 @@ pub struct SpanData { /// Information about where the macro came from, if this piece of /// code was created by a macro expansion. pub ctxt: SyntaxContext, + pub parent: Option, } impl SpanData { #[inline] pub fn span(&self) -> Span { - Span::new(self.lo, self.hi, self.ctxt) + Span::new(self.lo, self.hi, self.ctxt, self.parent) } #[inline] pub fn with_lo(&self, lo: BytePos) -> Span { - Span::new(lo, self.hi, self.ctxt) + Span::new(lo, self.hi, self.ctxt, self.parent) } #[inline] pub fn with_hi(&self, hi: BytePos) -> Span { - Span::new(self.lo, hi, self.ctxt) + Span::new(self.lo, hi, self.ctxt, self.parent) } #[inline] pub fn with_ctxt(&self, ctxt: SyntaxContext) -> Span { - Span::new(self.lo, self.hi, ctxt) + Span::new(self.lo, self.hi, ctxt, self.parent) + } + #[inline] + pub fn with_parent(&self, parent: Option) -> Span { + Span::new(self.lo, self.hi, self.ctxt, parent) + } + /// Returns `true` if this is a dummy span with any hygienic context. + #[inline] + pub fn is_dummy(self) -> bool { + self.lo.0 == 0 && self.hi.0 == 0 + } + /// Returns `true` if `self` fully encloses `other`. + pub fn contains(self, other: Self) -> bool { + self.lo <= other.lo && other.hi <= self.hi } } @@ -508,18 +524,25 @@ impl Span { } #[inline] pub fn ctxt(self) -> SyntaxContext { - self.data().ctxt + self.data_untracked().ctxt } #[inline] pub fn with_ctxt(self, ctxt: SyntaxContext) -> Span { - self.data().with_ctxt(ctxt) + self.data_untracked().with_ctxt(ctxt) + } + #[inline] + pub fn parent(self) -> Option { + self.data().parent + } + #[inline] + pub fn with_parent(self, ctxt: Option) -> Span { + self.data().with_parent(ctxt) } /// Returns `true` if this is a dummy span with any hygienic context. #[inline] pub fn is_dummy(self) -> bool { - let span = self.data(); - span.lo.0 == 0 && span.hi.0 == 0 + self.data_untracked().is_dummy() } /// Returns `true` if this span comes from a macro or desugaring. @@ -535,26 +558,26 @@ impl Span { #[inline] pub fn with_root_ctxt(lo: BytePos, hi: BytePos) -> Span { - Span::new(lo, hi, SyntaxContext::root()) + Span::new(lo, hi, SyntaxContext::root(), None) } /// Returns a new span representing an empty span at the beginning of this span. #[inline] pub fn shrink_to_lo(self) -> Span { - let span = self.data(); + let span = self.data_untracked(); span.with_hi(span.lo) } /// Returns a new span representing an empty span at the end of this span. #[inline] pub fn shrink_to_hi(self) -> Span { - let span = self.data(); + let span = self.data_untracked(); span.with_lo(span.hi) } #[inline] /// Returns `true` if `hi == lo`. pub fn is_empty(&self) -> bool { - let span = self.data(); + let span = self.data_untracked(); span.hi == span.lo } @@ -567,7 +590,7 @@ impl Span { pub fn contains(self, other: Span) -> bool { let span = self.data(); let other = other.data(); - span.lo <= other.lo && other.hi <= span.hi + span.contains(other) } /// Returns `true` if `self` touches `other`. @@ -603,7 +626,7 @@ impl Span { /// The `Span` for the tokens in the previous macro expansion from which `self` was generated, /// if any. - pub fn parent(self) -> Option { + pub fn parent_callsite(self) -> Option { let expn_data = self.ctxt().outer_expn_data(); if !expn_data.is_root() { Some(expn_data.call_site) } else { None } } @@ -611,7 +634,7 @@ impl Span { /// Walk down the expansion ancestors to find a span that's contained within `outer`. pub fn find_ancestor_inside(mut self, outer: Span) -> Option { while !outer.contains(self) { - self = self.parent()?; + self = self.parent_callsite()?; } Some(self) } @@ -732,6 +755,7 @@ impl Span { cmp::min(span_data.lo, end_data.lo), cmp::max(span_data.hi, end_data.hi), if span_data.ctxt == SyntaxContext::root() { end_data.ctxt } else { span_data.ctxt }, + if span_data.parent == end_data.parent { span_data.parent } else { None }, ) } @@ -749,6 +773,7 @@ impl Span { span.hi, end.lo, if end.ctxt == SyntaxContext::root() { end.ctxt } else { span.ctxt }, + if span.parent == end.parent { span.parent } else { None }, ) } @@ -760,12 +785,30 @@ impl Span { /// ^^^^^^^^^^^^^^^^^ /// ``` pub fn until(self, end: Span) -> Span { - let span = self.data(); - let end = end.data(); + // Most of this function's body is copied from `to`. + // We can't just do `self.to(end.shrink_to_lo())`, + // because to also does some magic where it uses min/max so + // it can handle overlapping spans. Some advanced mis-use of + // `until` with different ctxts makes this visible. + let span_data = self.data(); + let end_data = end.data(); + // FIXME(jseyfried): `self.ctxt` should always equal `end.ctxt` here (cf. issue #23480). + // Return the macro span on its own to avoid weird diagnostic output. It is preferable to + // have an incomplete span than a completely nonsensical one. + if span_data.ctxt != end_data.ctxt { + if span_data.ctxt == SyntaxContext::root() { + return end; + } else if end_data.ctxt == SyntaxContext::root() { + return self; + } + // Both spans fall within a macro. + // FIXME(estebank): check if it is the *same* macro. + } Span::new( - span.lo, - end.lo, - if end.ctxt == SyntaxContext::root() { end.ctxt } else { span.ctxt }, + span_data.lo, + end_data.lo, + if end_data.ctxt == SyntaxContext::root() { end_data.ctxt } else { span_data.ctxt }, + if span_data.parent == end_data.parent { span_data.parent } else { None }, ) } @@ -775,6 +818,7 @@ impl Span { span.lo + BytePos::from_usize(inner.start), span.lo + BytePos::from_usize(inner.end), span.ctxt, + span.parent, ) } @@ -813,7 +857,7 @@ impl Span { pub fn remove_mark(&mut self) -> ExpnId { let mut span = self.data(); let mark = span.ctxt.remove_mark(); - *self = Span::new(span.lo, span.hi, span.ctxt); + *self = Span::new(span.lo, span.hi, span.ctxt, span.parent); mark } @@ -821,7 +865,7 @@ impl Span { pub fn adjust(&mut self, expn_id: ExpnId) -> Option { let mut span = self.data(); let mark = span.ctxt.adjust(expn_id); - *self = Span::new(span.lo, span.hi, span.ctxt); + *self = Span::new(span.lo, span.hi, span.ctxt, span.parent); mark } @@ -829,7 +873,7 @@ impl Span { pub fn normalize_to_macros_2_0_and_adjust(&mut self, expn_id: ExpnId) -> Option { let mut span = self.data(); let mark = span.ctxt.normalize_to_macros_2_0_and_adjust(expn_id); - *self = Span::new(span.lo, span.hi, span.ctxt); + *self = Span::new(span.lo, span.hi, span.ctxt, span.parent); mark } @@ -837,7 +881,7 @@ impl Span { pub fn glob_adjust(&mut self, expn_id: ExpnId, glob_span: Span) -> Option> { let mut span = self.data(); let mark = span.ctxt.glob_adjust(expn_id, glob_span); - *self = Span::new(span.lo, span.hi, span.ctxt); + *self = Span::new(span.lo, span.hi, span.ctxt, span.parent); mark } @@ -849,7 +893,7 @@ impl Span { ) -> Option> { let mut span = self.data(); let mark = span.ctxt.reverse_glob_adjust(expn_id, glob_span); - *self = Span::new(span.lo, span.hi, span.ctxt); + *self = Span::new(span.lo, span.hi, span.ctxt, span.parent); mark } @@ -901,7 +945,7 @@ impl Decodable for Span { let lo = d.read_struct_field("lo", Decodable::decode)?; let hi = d.read_struct_field("hi", Decodable::decode)?; - Ok(Span::new(lo, hi, SyntaxContext::root())) + Ok(Span::new(lo, hi, SyntaxContext::root(), None)) }) } } @@ -962,7 +1006,7 @@ impl fmt::Debug for Span { impl fmt::Debug for SpanData { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - (*SPAN_DEBUG)(Span::new(self.lo, self.hi, self.ctxt), f) + (*SPAN_DEBUG)(Span::new(self.lo, self.hi, self.ctxt, self.parent), f) } } @@ -1923,6 +1967,7 @@ pub struct FileLines { pub static SPAN_DEBUG: AtomicRef) -> fmt::Result> = AtomicRef::new(&(default_span_debug as fn(_, &mut fmt::Formatter<'_>) -> _)); +pub static SPAN_TRACK: AtomicRef = AtomicRef::new(&((|_| {}) as fn(_))); // _____________________________________________________________________________ // SpanLinesError, SpanSnippetError, DistinctSources, MalformedSourceMapPositions @@ -1977,6 +2022,7 @@ impl InnerSpan { pub trait HashStableContext { fn def_path_hash(&self, def_id: DefId) -> DefPathHash; fn hash_spans(&self) -> bool; + fn def_span(&self, def_id: LocalDefId) -> Span; fn span_data_to_lines_and_cols( &mut self, span: &SpanData, @@ -2000,22 +2046,35 @@ where fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { const TAG_VALID_SPAN: u8 = 0; const TAG_INVALID_SPAN: u8 = 1; + const TAG_RELATIVE_SPAN: u8 = 2; if !ctx.hash_spans() { return; } - self.ctxt().hash_stable(ctx, hasher); + let span = self.data_untracked(); + span.ctxt.hash_stable(ctx, hasher); + span.parent.hash_stable(ctx, hasher); - if self.is_dummy() { + if span.is_dummy() { Hash::hash(&TAG_INVALID_SPAN, hasher); return; } + if let Some(parent) = span.parent { + let def_span = ctx.def_span(parent).data_untracked(); + if def_span.contains(span) { + // This span is enclosed in a definition: only hash the relative position. + Hash::hash(&TAG_RELATIVE_SPAN, hasher); + (span.lo - def_span.lo).to_u32().hash_stable(ctx, hasher); + (span.hi - def_span.lo).to_u32().hash_stable(ctx, hasher); + return; + } + } + // If this is not an empty or invalid span, we want to hash the last // position that belongs to it, as opposed to hashing the first // position past it. - let span = self.data(); let (file, line_lo, col_lo, line_hi, col_hi) = match ctx.span_data_to_lines_and_cols(&span) { Some(pos) => pos, diff --git a/compiler/rustc_span/src/source_map.rs b/compiler/rustc_span/src/source_map.rs index 9b8c8594ee..74958c4984 100644 --- a/compiler/rustc_span/src/source_map.rs +++ b/compiler/rustc_span/src/source_map.rs @@ -474,11 +474,12 @@ impl SourceMap { f.lookup_line(sp.lo()) != f.lookup_line(sp.hi()) } + #[instrument(skip(self), level = "trace")] pub fn is_valid_span(&self, sp: Span) -> Result<(Loc, Loc), SpanLinesError> { let lo = self.lookup_char_pos(sp.lo()); - debug!("span_to_lines: lo={:?}", lo); + trace!(?lo); let hi = self.lookup_char_pos(sp.hi()); - debug!("span_to_lines: hi={:?}", hi); + trace!(?hi); if lo.file.start_pos != hi.file.start_pos { return Err(SpanLinesError::DistinctSources(DistinctSources { begin: (lo.file.name.clone(), lo.file.start_pos), @@ -652,6 +653,18 @@ impl SourceMap { }) } + /// Extends the given `Span` while the next character matches the predicate + pub fn span_extend_while( + &self, + span: Span, + f: impl Fn(char) -> bool, + ) -> Result { + self.span_to_source(span, |s, _start, end| { + let n = s[end..].char_indices().find(|&(_, c)| !f(c)).map_or(s.len() - end, |(i, _)| i); + Ok(span.with_hi(span.hi() + BytePos(n as u32))) + }) + } + /// Extends the given `Span` to just after the next occurrence of `c`. pub fn span_extend_to_next_char(&self, sp: Span, c: char, accept_newlines: bool) -> Span { if let Ok(next_source) = self.span_to_next_source(sp) { @@ -794,7 +807,7 @@ impl SourceMap { start_of_next_point.checked_add(width - 1).unwrap_or(start_of_next_point); let end_of_next_point = BytePos(cmp::max(sp.lo().0 + 1, end_of_next_point)); - Span::new(BytePos(start_of_next_point), end_of_next_point, sp.ctxt()) + Span::new(BytePos(start_of_next_point), end_of_next_point, sp.ctxt(), None) } /// Finds the width of the character, either before or after the end of provided span, @@ -1012,6 +1025,32 @@ impl SourceMap { let source_file = &self.files()[source_file_index]; source_file.is_imported() } + + /// Gets the span of a statement. If the statement is a macro expansion, the + /// span in the context of the block span is found. The trailing semicolon is included + /// on a best-effort basis. + pub fn stmt_span(&self, stmt_span: Span, block_span: Span) -> Span { + if !stmt_span.from_expansion() { + return stmt_span; + } + let mac_call = original_sp(stmt_span, block_span); + self.mac_call_stmt_semi_span(mac_call).map_or(mac_call, |s| mac_call.with_hi(s.hi())) + } + + /// Tries to find the span of the semicolon of a macro call statement. + /// The input must be the *call site* span of a statement from macro expansion. + /// + /// v output + /// mac!(); + /// ^^^^^^ input + pub fn mac_call_stmt_semi_span(&self, mac_call: Span) -> Option { + let span = self.span_extend_while(mac_call, char::is_whitespace).ok()?; + let span = span.shrink_to_hi().with_hi(BytePos(span.hi().0.checked_add(1)?)); + if self.span_to_snippet(span).as_deref() != Ok(";") { + return None; + } + Some(span) + } } #[derive(Clone)] diff --git a/compiler/rustc_span/src/span_encoding.rs b/compiler/rustc_span/src/span_encoding.rs index cb017709c6..e9120b98aa 100644 --- a/compiler/rustc_span/src/span_encoding.rs +++ b/compiler/rustc_span/src/span_encoding.rs @@ -4,7 +4,9 @@ // The encoding format for inline spans were obtained by optimizing over crates in rustc/libstd. // See https://internals.rust-lang.org/t/rfc-compiler-refactoring-spans/1357/28 +use crate::def_id::LocalDefId; use crate::hygiene::SyntaxContext; +use crate::SPAN_TRACK; use crate::{BytePos, SpanData}; use rustc_data_structures::fx::FxIndexSet; @@ -54,6 +56,10 @@ use rustc_data_structures::fx::FxIndexSet; /// the code. No crates in `rustc-perf` need more than 15 bits for `ctxt`, /// but larger crates might need more than 16 bits. /// +/// In order to reliably use parented spans in incremental compilation, +/// the dependency to the parent definition's span. This is performed +/// using the callback `SPAN_TRACK` to access the query engine. +/// #[derive(Clone, Copy, Eq, PartialEq, Hash)] pub struct Span { base_or_index: u32, @@ -70,25 +76,42 @@ pub const DUMMY_SP: Span = Span { base_or_index: 0, len_or_tag: 0, ctxt_or_zero: impl Span { #[inline] - pub fn new(mut lo: BytePos, mut hi: BytePos, ctxt: SyntaxContext) -> Self { + pub fn new( + mut lo: BytePos, + mut hi: BytePos, + ctxt: SyntaxContext, + parent: Option, + ) -> Self { if lo > hi { std::mem::swap(&mut lo, &mut hi); } let (base, len, ctxt2) = (lo.0, hi.0 - lo.0, ctxt.as_u32()); - if len <= MAX_LEN && ctxt2 <= MAX_CTXT { + if len <= MAX_LEN && ctxt2 <= MAX_CTXT && parent.is_none() { // Inline format. Span { base_or_index: base, len_or_tag: len as u16, ctxt_or_zero: ctxt2 as u16 } } else { // Interned format. - let index = with_span_interner(|interner| interner.intern(&SpanData { lo, hi, ctxt })); + let index = + with_span_interner(|interner| interner.intern(&SpanData { lo, hi, ctxt, parent })); Span { base_or_index: index, len_or_tag: LEN_TAG, ctxt_or_zero: 0 } } } #[inline] pub fn data(self) -> SpanData { + let data = self.data_untracked(); + if let Some(parent) = data.parent { + (*SPAN_TRACK)(parent); + } + data + } + + /// Internal function to translate between an encoded span and the expanded representation. + /// This function must not be used outside the incremental engine. + #[inline] + pub fn data_untracked(self) -> SpanData { if self.len_or_tag != LEN_TAG { // Inline format. debug_assert!(self.len_or_tag as u32 <= MAX_LEN); @@ -96,6 +119,7 @@ impl Span { lo: BytePos(self.base_or_index), hi: BytePos(self.base_or_index + self.len_or_tag as u32), ctxt: SyntaxContext::from_u32(self.ctxt_or_zero as u32), + parent: None, } } else { // Interned format. diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 5150900e9d..16205ad1cf 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -5,6 +5,7 @@ use rustc_arena::DroplessArena; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey}; +use rustc_data_structures::sync::Lock; use rustc_macros::HashStable_Generic; use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; @@ -168,6 +169,7 @@ symbols! { Default, Deref, DirBuilder, + Display, DoubleEndedIterator, Duration, Encodable, @@ -193,6 +195,7 @@ symbols! { Hasher, Implied, Input, + Into, IntoIterator, IoRead, IoWrite, @@ -203,6 +206,7 @@ symbols! { Left, LinkedList, LintPass, + Mutex, None, Ok, Option, @@ -218,6 +222,7 @@ symbols! { PathBuf, Pending, Pin, + Pointer, Poll, ProcMacro, ProcMacroHack, @@ -241,6 +246,7 @@ symbols! { Send, SeqCst, Some, + String, StructuralEq, StructuralPartialEq, Sync, @@ -248,11 +254,15 @@ symbols! { ToOwned, ToString, Try, + TryFrom, + TryInto, Ty, TyCtxt, TyKind, Unknown, + UnsafeArg, Vec, + VecDeque, Yield, _DECLS, _Self, @@ -389,6 +399,7 @@ symbols! { cfg_attr_multi, cfg_doctest, cfg_eval, + cfg_hide, cfg_panic, cfg_sanitize, cfg_target_abi, @@ -406,6 +417,7 @@ symbols! { clone_from, closure, closure_to_fn_coercion, + closure_track_caller, cmp, cmp_max, cmp_min, @@ -429,6 +441,8 @@ symbols! { const_compare_raw_pointers, const_constructor, const_eval_limit, + const_eval_select, + const_eval_select_ct, const_evaluatable_checked, const_extern_fn, const_fn, @@ -504,7 +518,6 @@ symbols! { debug_assert_macro, debug_assertions, debug_struct, - debug_trait, debug_trait_builder, debug_tuple, decl_macro, @@ -536,7 +549,9 @@ symbols! { div_assign, doc, doc_alias, + doc_auto_cfg, doc_cfg, + doc_cfg_hide, doc_keyword, doc_masked, doc_notable_trait, @@ -651,7 +666,6 @@ symbols! { from_output, from_residual, from_size_align_unchecked, - from_trait, from_usize, fsub_fast, fundamental, @@ -674,8 +688,6 @@ symbols! { gt, half_open_range_patterns, hash, - hashmap_type, - hashset_type, hexagon_target_feature, hidden, homogeneous_aggregate, @@ -720,7 +732,6 @@ symbols! { instruction_set, intel, into_iter, - into_trait, intra_doc_pointers, intrinsics, irrefutable_let_patterns, @@ -808,6 +819,7 @@ symbols! { mem_size_of, mem_size_of_val, mem_uninitialized, + mem_variant_count, mem_zeroed, member_constraints, memory, @@ -837,6 +849,7 @@ symbols! { mul, mul_assign, mul_with_overflow, + must_not_suspend, must_use, mut_ptr, mut_slice_ptr, @@ -884,6 +897,7 @@ symbols! { nomem, non_ascii_idents, non_exhaustive, + non_exhaustive_omitted_patterns_lint, non_modrs_mods, none_error, nontemporal_store, @@ -910,7 +924,6 @@ symbols! { optin_builtin_traits, option, option_env, - option_type, options, or, or_patterns, @@ -924,6 +937,7 @@ symbols! { panic_2021, panic_abort, panic_bounds_check, + panic_display, panic_fmt, panic_handler, panic_impl, @@ -935,7 +949,6 @@ symbols! { panic_unwind, panicking, param_attrs, - parent_trait, partial_cmp, partial_ord, passes, @@ -952,7 +965,6 @@ symbols! { plugins, pointee_trait, pointer, - pointer_trait, pointer_trait_fmt, poll, position, @@ -1048,7 +1060,6 @@ symbols! { repr_transparent, residual, result, - result_type, rhs, rintf32, rintf64, @@ -1089,6 +1100,7 @@ symbols! { rustc_diagnostic_item, rustc_diagnostic_macros, rustc_dirty, + rustc_do_not_const_check, rustc_dummy, rustc_dump_env_program_clauses, rustc_dump_program_clauses, @@ -1135,6 +1147,7 @@ symbols! { rustc_synthetic, rustc_test_marker, rustc_then_this_would_need, + rustc_trivial_field_reads, rustc_unsafe_specialization_marker, rustc_variance, rustdoc, @@ -1148,7 +1161,6 @@ symbols! { self_in_typedefs, self_struct_ctor, semitransparent, - send_trait, shl, shl_assign, should_panic, @@ -1211,6 +1223,7 @@ symbols! { simd_select_bitmask, simd_shl, simd_shr, + simd_shuffle, simd_sub, simd_trunc, simd_xor, @@ -1257,7 +1270,6 @@ symbols! { store, str, str_alloc, - string_type, stringify, struct_field_attributes, struct_inherit, @@ -1272,7 +1284,6 @@ symbols! { suggestion, sym, sync, - sync_trait, t32, target_abi, target_arch, @@ -1318,9 +1329,7 @@ symbols! { truncf64, try_blocks, try_from, - try_from_trait, try_into, - try_into_trait, try_trait_v2, tt, tuple, @@ -1392,8 +1401,6 @@ symbols! { var, variant_count, vec, - vec_type, - vecdeque_type, version, vis, visible_private_types, @@ -1418,6 +1425,7 @@ symbols! { wrapping_sub, wreg, write_bytes, + write_str, x87_reg, xer, xmm_reg, @@ -1612,7 +1620,7 @@ impl fmt::Display for MacroRulesNormalizedIdent { pub struct Symbol(SymbolIndex); rustc_index::newtype_index! { - pub struct SymbolIndex { .. } + struct SymbolIndex { .. } } impl Symbol { @@ -1622,14 +1630,15 @@ impl Symbol { /// Maps a string to its interned representation. pub fn intern(string: &str) -> Self { - with_interner(|interner| interner.intern(string)) + with_session_globals(|session_globals| session_globals.symbol_interner.intern(string)) } /// Convert to a `SymbolStr`. This is a slowish operation because it /// requires locking the symbol interner. pub fn as_str(self) -> SymbolStr { - with_interner(|interner| unsafe { - SymbolStr { string: std::mem::transmute::<&str, &str>(interner.get(self)) } + with_session_globals(|session_globals| { + let symbol_str = session_globals.symbol_interner.get(self); + unsafe { SymbolStr { string: std::mem::transmute::<&str, &str>(symbol_str) } } }) } @@ -1637,10 +1646,6 @@ impl Symbol { self.0.as_u32() } - pub fn len(self) -> usize { - with_interner(|interner| interner.get(self).len()) - } - pub fn is_empty(self) -> bool { self == kw::Empty } @@ -1695,13 +1700,19 @@ impl ToStableHashKey for Symbol { } } +#[derive(Default)] +pub(crate) struct Interner(Lock); + // The `&'static str`s in this type actually point into the arena. // // The `FxHashMap`+`Vec` pair could be replaced by `FxIndexSet`, but #75278 // found that to regress performance up to 2% in some cases. This might be // revisited after further improvements to `indexmap`. +// +// This type is private to prevent accidentally constructing more than one `Interner` on the same +// thread, which makes it easy to mixup `Symbol`s between `Interner`s. #[derive(Default)] -pub struct Interner { +struct InternerInner { arena: DroplessArena, names: FxHashMap<&'static str, Symbol>, strings: Vec<&'static str>, @@ -1709,37 +1720,38 @@ pub struct Interner { impl Interner { fn prefill(init: &[&'static str]) -> Self { - Interner { + Interner(Lock::new(InternerInner { strings: init.into(), names: init.iter().copied().zip((0..).map(Symbol::new)).collect(), ..Default::default() - } + })) } #[inline] - pub fn intern(&mut self, string: &str) -> Symbol { - if let Some(&name) = self.names.get(string) { + fn intern(&self, string: &str) -> Symbol { + let mut inner = self.0.lock(); + if let Some(&name) = inner.names.get(string) { return name; } - let name = Symbol::new(self.strings.len() as u32); + let name = Symbol::new(inner.strings.len() as u32); // `from_utf8_unchecked` is safe since we just allocated a `&str` which is known to be // UTF-8. let string: &str = - unsafe { str::from_utf8_unchecked(self.arena.alloc_slice(string.as_bytes())) }; + unsafe { str::from_utf8_unchecked(inner.arena.alloc_slice(string.as_bytes())) }; // It is safe to extend the arena allocation to `'static` because we only access // these while the arena is still alive. let string: &'static str = unsafe { &*(string as *const str) }; - self.strings.push(string); - self.names.insert(string, name); + inner.strings.push(string); + inner.names.insert(string, name); name } // Get the symbol as a string. `Symbol::as_str()` should be used in // preference to this function. - pub fn get(&self, symbol: Symbol) -> &str { - self.strings[symbol.0.as_usize()] + fn get(&self, symbol: Symbol) -> &str { + self.0.lock().strings[symbol.0.as_usize()] } } @@ -1870,11 +1882,6 @@ impl Ident { } } -#[inline] -fn with_interner T>(f: F) -> T { - with_session_globals(|session_globals| f(&mut *session_globals.symbol_interner.lock())) -} - /// An alternative to [`Symbol`], useful when the chars within the symbol need to /// be accessed. It deliberately has limited functionality and should only be /// used for temporary values. diff --git a/compiler/rustc_span/src/symbol/tests.rs b/compiler/rustc_span/src/symbol/tests.rs index 11dea265b4..0958fce5fe 100644 --- a/compiler/rustc_span/src/symbol/tests.rs +++ b/compiler/rustc_span/src/symbol/tests.rs @@ -4,7 +4,7 @@ use crate::create_default_session_globals_then; #[test] fn interner_tests() { - let mut i: Interner = Interner::default(); + let i = Interner::default(); // first one is zero: assert_eq!(i.intern("dog"), Symbol::new(0)); // re-use gets the same entry: diff --git a/compiler/rustc_symbol_mangling/Cargo.toml b/compiler/rustc_symbol_mangling/Cargo.toml index aebf77a1fd..b9751f0adb 100644 --- a/compiler/rustc_symbol_mangling/Cargo.toml +++ b/compiler/rustc_symbol_mangling/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustc_symbol_mangling" version = "0.0.0" -edition = "2018" +edition = "2021" [lib] doctest = false @@ -16,4 +16,5 @@ rustc_middle = { path = "../rustc_middle" } rustc_hir = { path = "../rustc_hir" } rustc_target = { path = "../rustc_target" } rustc_data_structures = { path = "../rustc_data_structures" } +rustc_query_system = { path = "../rustc_query_system" } rustc_session = { path = "../rustc_session" } diff --git a/compiler/rustc_symbol_mangling/src/legacy.rs b/compiler/rustc_symbol_mangling/src/legacy.rs index e236ef996b..de18614360 100644 --- a/compiler/rustc_symbol_mangling/src/legacy.rs +++ b/compiler/rustc_symbol_mangling/src/legacy.rs @@ -1,12 +1,12 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_hir::def_id::CrateNum; use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData}; -use rustc_middle::ich::NodeIdHashingMode; use rustc_middle::mir::interpret::{ConstValue, Scalar}; use rustc_middle::ty::print::{PrettyPrinter, Print, Printer}; use rustc_middle::ty::subst::{GenericArg, GenericArgKind}; use rustc_middle::ty::{self, Instance, Ty, TyCtxt, TypeFoldable}; use rustc_middle::util::common::record_time; +use rustc_query_system::ich::NodeIdHashingMode; use tracing::debug; diff --git a/compiler/rustc_symbol_mangling/src/test.rs b/compiler/rustc_symbol_mangling/src/test.rs index 183df96f31..f7d68b5cc7 100644 --- a/compiler/rustc_symbol_mangling/src/test.rs +++ b/compiler/rustc_symbol_mangling/src/test.rs @@ -23,7 +23,7 @@ pub fn report_symbol_names(tcx: TyCtxt<'_>) { tcx.dep_graph.with_ignore(|| { let mut visitor = SymbolNamesTest { tcx }; - tcx.hir().krate().visit_all_item_likes(&mut visitor); + tcx.hir().visit_all_item_likes(&mut visitor); }) } diff --git a/compiler/rustc_target/Cargo.toml b/compiler/rustc_target/Cargo.toml index e47a84dbc1..925813e6bb 100644 --- a/compiler/rustc_target/Cargo.toml +++ b/compiler/rustc_target/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustc_target" version = "0.0.0" -edition = "2018" +edition = "2021" [dependencies] bitflags = "1.2.1" diff --git a/compiler/rustc_target/src/abi/call/m68k.rs b/compiler/rustc_target/src/abi/call/m68k.rs new file mode 100644 index 0000000000..58fdc00b69 --- /dev/null +++ b/compiler/rustc_target/src/abi/call/m68k.rs @@ -0,0 +1,30 @@ +use crate::abi::call::{ArgAbi, FnAbi}; + +fn classify_ret(ret: &mut ArgAbi<'_, Ty>) { + if ret.layout.is_aggregate() { + ret.make_indirect(); + } else { + ret.extend_integer_width_to(32); + } +} + +fn classify_arg(arg: &mut ArgAbi<'_, Ty>) { + if arg.layout.is_aggregate() { + arg.make_indirect_byval(); + } else { + arg.extend_integer_width_to(32); + } +} + +pub fn compute_abi_info(fn_abi: &mut FnAbi<'_, Ty>) { + if !fn_abi.ret.is_ignore() { + classify_ret(&mut fn_abi.ret); + } + + for arg in &mut fn_abi.args { + if arg.is_ignore() { + continue; + } + classify_arg(arg); + } +} diff --git a/compiler/rustc_target/src/abi/call/mips64.rs b/compiler/rustc_target/src/abi/call/mips64.rs index 28ca93c469..2e00ffc7e1 100644 --- a/compiler/rustc_target/src/abi/call/mips64.rs +++ b/compiler/rustc_target/src/abi/call/mips64.rs @@ -3,7 +3,7 @@ use crate::abi::{self, HasDataLayout, Size, TyAbiInterface}; fn extend_integer_width_mips(arg: &mut ArgAbi<'_, Ty>, bits: u64) { // Always sign extend u32 values on 64-bit mips - if let abi::Abi::Scalar(ref scalar) = arg.layout.abi { + if let abi::Abi::Scalar(scalar) = arg.layout.abi { if let abi::Int(i, signed) = scalar.value { if !signed && i.size().bits() == 32 { if let PassMode::Direct(ref mut attrs) = arg.mode { @@ -23,7 +23,7 @@ where C: HasDataLayout, { match ret.layout.field(cx, i).abi { - abi::Abi::Scalar(ref scalar) => match scalar.value { + abi::Abi::Scalar(scalar) => match scalar.value { abi::F32 => Some(Reg::f32()), abi::F64 => Some(Reg::f64()), _ => None, @@ -107,7 +107,7 @@ where let offset = arg.layout.fields.offset(i); // We only care about aligned doubles - if let abi::Abi::Scalar(ref scalar) = field.abi { + if let abi::Abi::Scalar(scalar) = field.abi { if let abi::F64 = scalar.value { if offset.is_aligned(dl.f64_align.abi) { // Insert enough integers to cover [last_offset, offset) diff --git a/compiler/rustc_target/src/abi/call/mod.rs b/compiler/rustc_target/src/abi/call/mod.rs index 6d3c731809..d9eb299e2f 100644 --- a/compiler/rustc_target/src/abi/call/mod.rs +++ b/compiler/rustc_target/src/abi/call/mod.rs @@ -1,6 +1,7 @@ use crate::abi::{self, Abi, Align, FieldsShape, Size}; use crate::abi::{HasDataLayout, TyAbiInterface, TyAndLayout}; use crate::spec::{self, HasTargetSpec}; +use std::fmt; mod aarch64; mod amdgpu; @@ -8,6 +9,7 @@ mod arm; mod avr; mod bpf; mod hexagon; +mod m68k; mod mips; mod mips64; mod msp430; @@ -24,7 +26,7 @@ mod x86; mod x86_64; mod x86_win64; -#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, HashStable_Generic)] pub enum PassMode { /// Ignore the argument. /// @@ -59,7 +61,7 @@ pub use attr_impl::ArgAttribute; mod attr_impl { // The subset of llvm::Attribute needed for arguments, packed into a bitfield. bitflags::bitflags! { - #[derive(Default)] + #[derive(Default, HashStable_Generic)] pub struct ArgAttribute: u16 { const NoAlias = 1 << 1; const NoCapture = 1 << 2; @@ -76,7 +78,7 @@ mod attr_impl { /// Sometimes an ABI requires small integers to be extended to a full or partial register. This enum /// defines if this extension should be zero-extension or sign-extension when necessary. When it is /// not necessary to extend the argument, this enum is ignored. -#[derive(Copy, Clone, PartialEq, Eq, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)] pub enum ArgExtension { None, Zext, @@ -85,7 +87,7 @@ pub enum ArgExtension { /// A compact representation of LLVM attributes (at least those relevant for this module) /// that can be manipulated without interacting with LLVM's Attribute machinery. -#[derive(Copy, Clone, PartialEq, Eq, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)] pub struct ArgAttributes { pub regular: ArgAttribute, pub arg_ext: ArgExtension, @@ -126,14 +128,14 @@ impl ArgAttributes { } } -#[derive(Copy, Clone, PartialEq, Eq, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)] pub enum RegKind { Integer, Float, Vector, } -#[derive(Copy, Clone, PartialEq, Eq, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)] pub struct Reg { pub kind: RegKind, pub size: Size, @@ -183,7 +185,7 @@ impl Reg { /// An argument passed entirely registers with the /// same kind (e.g., HFA / HVA on PPC64 and AArch64). -#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, HashStable_Generic)] pub struct Uniform { pub unit: Reg, @@ -208,7 +210,7 @@ impl Uniform { } } -#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, HashStable_Generic)] pub struct CastTarget { pub prefix: [Option; 8], pub prefix_chunk_size: Size, @@ -322,7 +324,7 @@ impl<'a, Ty> TyAndLayout<'a, Ty> { Abi::Uninhabited => Err(Heterogeneous), // The primitive for this algorithm. - Abi::Scalar(ref scalar) => { + Abi::Scalar(scalar) => { let kind = match scalar.value { abi::Int(..) | abi::Pointer => RegKind::Integer, abi::F32 | abi::F64 => RegKind::Float, @@ -436,7 +438,7 @@ impl<'a, Ty> TyAndLayout<'a, Ty> { /// Information about how to pass an argument to, /// or return a value from, a function, under some ABI. -#[derive(Debug)] +#[derive(PartialEq, Eq, Hash, Debug, HashStable_Generic)] pub struct ArgAbi<'a, Ty> { pub layout: TyAndLayout<'a, Ty>, @@ -450,9 +452,9 @@ impl<'a, Ty> ArgAbi<'a, Ty> { pub fn new( cx: &impl HasDataLayout, layout: TyAndLayout<'a, Ty>, - scalar_attrs: impl Fn(&TyAndLayout<'a, Ty>, &abi::Scalar, Size) -> ArgAttributes, + scalar_attrs: impl Fn(&TyAndLayout<'a, Ty>, abi::Scalar, Size) -> ArgAttributes, ) -> Self { - let mode = match &layout.abi { + let mode = match layout.abi { Abi::Uninhabited => PassMode::Ignore, Abi::Scalar(scalar) => PassMode::Direct(scalar_attrs(&layout, scalar, Size::ZERO)), Abi::ScalarPair(a, b) => PassMode::Pair( @@ -504,7 +506,7 @@ impl<'a, Ty> ArgAbi<'a, Ty> { pub fn extend_integer_width_to(&mut self, bits: u64) { // Only integers have signedness - if let Abi::Scalar(ref scalar) = self.layout.abi { + if let Abi::Scalar(scalar) = self.layout.abi { if let abi::Int(i, signed) = scalar.value { if i.size().bits() < bits { if let PassMode::Direct(ref mut attrs) = self.mode { @@ -544,7 +546,7 @@ impl<'a, Ty> ArgAbi<'a, Ty> { } } -#[derive(Copy, Clone, PartialEq, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)] pub enum Conv { // General language calling conventions, for which every target // should have its own backend (e.g. LLVM) support. @@ -578,7 +580,7 @@ pub enum Conv { /// /// I will do my best to describe this structure, but these /// comments are reverse-engineered and may be inaccurate. -NDM -#[derive(Debug)] +#[derive(PartialEq, Eq, Hash, Debug, HashStable_Generic)] pub struct FnAbi<'a, Ty> { /// The LLVM types of each argument. pub args: Vec>, @@ -599,8 +601,29 @@ pub struct FnAbi<'a, Ty> { pub can_unwind: bool, } +/// Error produced by attempting to adjust a `FnAbi`, for a "foreign" ABI. +#[derive(Clone, Debug, HashStable_Generic)] +pub enum AdjustForForeignAbiError { + /// Target architecture doesn't support "foreign" (i.e. non-Rust) ABIs. + Unsupported { arch: String, abi: spec::abi::Abi }, +} + +impl fmt::Display for AdjustForForeignAbiError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::Unsupported { arch, abi } => { + write!(f, "target architecture {:?} does not support `extern {}` ABI", arch, abi) + } + } + } +} + impl<'a, Ty> FnAbi<'a, Ty> { - pub fn adjust_for_cabi(&mut self, cx: &C, abi: spec::abi::Abi) -> Result<(), String> + pub fn adjust_for_foreign_abi( + &mut self, + cx: &C, + abi: spec::abi::Abi, + ) -> Result<(), AdjustForForeignAbiError> where Ty: TyAbiInterface<'a, C> + Copy, C: HasDataLayout + HasTargetSpec, @@ -634,6 +657,7 @@ impl<'a, Ty> FnAbi<'a, Ty> { "amdgpu" => amdgpu::compute_abi_info(cx, self), "arm" => arm::compute_abi_info(cx, self), "avr" => avr::compute_abi_info(self), + "m68k" => m68k::compute_abi_info(self), "mips" => mips::compute_abi_info(cx, self), "mips64" => mips64::compute_abi_info(cx, self), "powerpc" => powerpc::compute_abi_info(self), @@ -655,7 +679,9 @@ impl<'a, Ty> FnAbi<'a, Ty> { } "asmjs" => wasm::compute_c_abi_info(cx, self), "bpf" => bpf::compute_abi_info(self), - a => return Err(format!("unrecognized arch \"{}\" in target specification", a)), + arch => { + return Err(AdjustForForeignAbiError::Unsupported { arch: arch.to_string(), abi }); + } } Ok(()) diff --git a/compiler/rustc_target/src/abi/call/riscv.rs b/compiler/rustc_target/src/abi/call/riscv.rs index 8c2ef8c7a0..bbefc73a07 100644 --- a/compiler/rustc_target/src/abi/call/riscv.rs +++ b/compiler/rustc_target/src/abi/call/riscv.rs @@ -44,7 +44,7 @@ where Ty: TyAbiInterface<'a, C> + Copy, { match arg_layout.abi { - Abi::Scalar(ref scalar) => match scalar.value { + Abi::Scalar(scalar) => match scalar.value { abi::Int(..) | abi::Pointer => { if arg_layout.size.bits() > xlen { return Err(CannotUseFpConv); @@ -297,7 +297,7 @@ fn classify_arg<'a, Ty, C>( } fn extend_integer_width<'a, Ty>(arg: &mut ArgAbi<'a, Ty>, xlen: u64) { - if let Abi::Scalar(ref scalar) = arg.layout.abi { + if let Abi::Scalar(scalar) = arg.layout.abi { if let abi::Int(i, _) = scalar.value { // 32-bit integers are always sign-extended if i.size().bits() == 32 && xlen > 32 { diff --git a/compiler/rustc_target/src/abi/call/s390x.rs b/compiler/rustc_target/src/abi/call/s390x.rs index 594108925d..38aaee64a4 100644 --- a/compiler/rustc_target/src/abi/call/s390x.rs +++ b/compiler/rustc_target/src/abi/call/s390x.rs @@ -18,7 +18,7 @@ where C: HasDataLayout, { match layout.abi { - abi::Abi::Scalar(ref scalar) => scalar.value.is_float(), + abi::Abi::Scalar(scalar) => scalar.value.is_float(), abi::Abi::Aggregate { .. } => { if layout.fields.count() == 1 && layout.fields.offset(0).bytes() == 0 { is_single_fp_element(cx, layout.field(cx, 0)) diff --git a/compiler/rustc_target/src/abi/call/x86.rs b/compiler/rustc_target/src/abi/call/x86.rs index 3fc197b5d7..28064d85bf 100644 --- a/compiler/rustc_target/src/abi/call/x86.rs +++ b/compiler/rustc_target/src/abi/call/x86.rs @@ -14,7 +14,7 @@ where C: HasDataLayout, { match layout.abi { - abi::Abi::Scalar(ref scalar) => scalar.value.is_float(), + abi::Abi::Scalar(scalar) => scalar.value.is_float(), abi::Abi::Aggregate { .. } => { if layout.fields.count() == 1 && layout.fields.offset(0).bytes() == 0 { is_single_fp_element(cx, layout.field(cx, 0)) diff --git a/compiler/rustc_target/src/abi/call/x86_64.rs b/compiler/rustc_target/src/abi/call/x86_64.rs index 08f0aaba59..fae3c3af61 100644 --- a/compiler/rustc_target/src/abi/call/x86_64.rs +++ b/compiler/rustc_target/src/abi/call/x86_64.rs @@ -49,7 +49,7 @@ where let mut c = match layout.abi { Abi::Uninhabited => return Ok(()), - Abi::Scalar(ref scalar) => match scalar.value { + Abi::Scalar(scalar) => match scalar.value { abi::Int(..) | abi::Pointer => Class::Int, abi::F32 | abi::F64 => Class::Sse, }, diff --git a/compiler/rustc_target/src/abi/mod.rs b/compiler/rustc_target/src/abi/mod.rs index 820399943f..a57ad8f2bb 100644 --- a/compiler/rustc_target/src/abi/mod.rs +++ b/compiler/rustc_target/src/abi/mod.rs @@ -7,13 +7,12 @@ use std::convert::{TryFrom, TryInto}; use std::fmt; use std::iter::Step; use std::num::NonZeroUsize; -use std::ops::{Add, AddAssign, Deref, Mul, Range, RangeInclusive, Sub}; +use std::ops::{Add, AddAssign, Deref, Mul, RangeInclusive, Sub}; use std::str::FromStr; use rustc_index::vec::{Idx, IndexVec}; use rustc_macros::HashStable_Generic; use rustc_serialize::json::{Json, ToJson}; -use rustc_span::Span; pub mod call; @@ -393,6 +392,21 @@ impl Size { // Truncate (shift left to drop out leftover values, shift right to fill with zeroes). (value << shift) >> shift } + + #[inline] + pub fn signed_int_min(&self) -> i128 { + self.sign_extend(1_u128 << (self.bits() - 1)) as i128 + } + + #[inline] + pub fn signed_int_max(&self) -> i128 { + i128::MAX >> (128 - self.bits()) + } + + #[inline] + pub fn unsigned_int_max(&self) -> u128 { + u128::MAX >> (128 - self.bits()) + } } // Panicking addition, subtraction and multiplication for convenience. @@ -740,9 +754,8 @@ impl Primitive { /// /// 254 (-2), 255 (-1), 0, 1, 2 /// -/// This is intended specifically to mirror LLVM’s `!range` metadata, -/// semantics. -#[derive(Clone, PartialEq, Eq, Hash)] +/// This is intended specifically to mirror LLVM’s `!range` metadata semantics. +#[derive(Clone, Copy, PartialEq, Eq, Hash)] #[derive(HashStable_Generic)] pub struct WrappingRange { pub start: u128, @@ -760,13 +773,6 @@ impl WrappingRange { } } - /// Returns `true` if zero is contained in the range. - /// Equal to `range.contains(0)` but should be faster. - #[inline(always)] - pub fn contains_zero(&self) -> bool { - self.start > self.end || self.start == 0 - } - /// Returns `self` with replaced `start` #[inline(always)] pub fn with_start(mut self, start: u128) -> Self { @@ -780,17 +786,29 @@ impl WrappingRange { self.end = end; self } + + /// Returns `true` if `size` completely fills the range. + #[inline] + pub fn is_full_for(&self, size: Size) -> bool { + let max_value = size.unsigned_int_max(); + debug_assert!(self.start <= max_value && self.end <= max_value); + self.start == (self.end.wrapping_add(1) & max_value) + } } impl fmt::Debug for WrappingRange { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(fmt, "{}..={}", self.start, self.end)?; + if self.start > self.end { + write!(fmt, "(..={}) | ({}..)", self.end, self.start)?; + } else { + write!(fmt, "{}..={}", self.start, self.end)?; + } Ok(()) } } /// Information about one scalar component of a Rust type. -#[derive(Clone, PartialEq, Eq, Hash, Debug)] +#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] #[derive(HashStable_Generic)] pub struct Scalar { pub value: Primitive, @@ -804,25 +822,16 @@ pub struct Scalar { impl Scalar { #[inline] pub fn is_bool(&self) -> bool { - matches!(self.value, Int(I8, false)) - && matches!(self.valid_range, WrappingRange { start: 0, end: 1 }) + matches!( + self, + Scalar { value: Int(I8, false), valid_range: WrappingRange { start: 0, end: 1 } } + ) } - /// Returns the valid range as a `x..y` range. - /// - /// If `x` and `y` are equal, the range is full, not empty. - pub fn valid_range_exclusive(&self, cx: &C) -> Range { - // For a (max) value of -1, max will be `-1 as usize`, which overflows. - // However, that is fine here (it would still represent the full range), - // i.e., if the range is everything. - let bits = self.value.size(cx).bits(); - assert!(bits <= 128); - let mask = !0u128 >> (128 - bits); - let start = self.valid_range.start; - let end = self.valid_range.end; - assert_eq!(start, start & mask); - assert_eq!(end, end & mask); - start..(end.wrapping_add(1) & mask) + /// Returns `true` if all possible numbers are valid, i.e `valid_range` covers the whole layout + #[inline] + pub fn is_always_valid(&self, cx: &C) -> bool { + self.valid_range.is_full_for(self.value.size(cx)) } } @@ -961,7 +970,7 @@ impl AddressSpace { /// Describes how values of the type are passed by target ABIs, /// in terms of categories of C types there are ABI rules for. -#[derive(Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)] +#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, HashStable_Generic)] pub enum Abi { Uninhabited, Scalar(Scalar), @@ -989,8 +998,8 @@ impl Abi { /// Returns `true` if this is a single signed integer scalar #[inline] pub fn is_signed(&self) -> bool { - match *self { - Abi::Scalar(ref scal) => match scal.value { + match self { + Abi::Scalar(scal) => match scal.value { Primitive::Int(_, signed) => signed, _ => false, }, @@ -1059,7 +1068,7 @@ pub enum TagEncoding { }, } -#[derive(Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)] +#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, HashStable_Generic)] pub struct Niche { pub offset: Size, pub scalar: Scalar, @@ -1072,10 +1081,10 @@ impl Niche { } pub fn available(&self, cx: &C) -> u128 { - let Scalar { value, valid_range: ref v } = self.scalar; - let bits = value.size(cx).bits(); - assert!(bits <= 128); - let max_value = !0u128 >> (128 - bits); + let Scalar { value, valid_range: v } = self.scalar; + let size = value.size(cx); + assert!(size.bits() <= 128); + let max_value = size.unsigned_int_max(); // Find out how many values are outside the valid range. let niche = v.end.wrapping_add(1)..v.start; @@ -1085,24 +1094,58 @@ impl Niche { pub fn reserve(&self, cx: &C, count: u128) -> Option<(u128, Scalar)> { assert!(count > 0); - let Scalar { value, valid_range: v } = self.scalar.clone(); - let bits = value.size(cx).bits(); - assert!(bits <= 128); - let max_value = !0u128 >> (128 - bits); + let Scalar { value, valid_range: v } = self.scalar; + let size = value.size(cx); + assert!(size.bits() <= 128); + let max_value = size.unsigned_int_max(); - if count > max_value { + let niche = v.end.wrapping_add(1)..v.start; + let available = niche.end.wrapping_sub(niche.start) & max_value; + if count > available { return None; } - // Compute the range of invalid values being reserved. - let start = v.end.wrapping_add(1) & max_value; - let end = v.end.wrapping_add(count) & max_value; - - if v.contains(end) { - return None; + // Extend the range of valid values being reserved by moving either `v.start` or `v.end` bound. + // Given an eventual `Option`, we try to maximize the chance for `None` to occupy the niche of zero. + // This is accomplished by prefering enums with 2 variants(`count==1`) and always taking the shortest path to niche zero. + // Having `None` in niche zero can enable some special optimizations. + // + // Bound selection criteria: + // 1. Select closest to zero given wrapping semantics. + // 2. Avoid moving past zero if possible. + // + // In practice this means that enums with `count > 1` are unlikely to claim niche zero, since they have to fit perfectly. + // If niche zero is already reserved, the selection of bounds are of little interest. + let move_start = |v: WrappingRange| { + let start = v.start.wrapping_sub(count) & max_value; + Some((start, Scalar { value, valid_range: v.with_start(start) })) + }; + let move_end = |v: WrappingRange| { + let start = v.end.wrapping_add(1) & max_value; + let end = v.end.wrapping_add(count) & max_value; + Some((start, Scalar { value, valid_range: v.with_end(end) })) + }; + let distance_end_zero = max_value - v.end; + if v.start > v.end { + // zero is unavailable because wrapping occurs + move_end(v) + } else if v.start <= distance_end_zero { + if count <= v.start { + move_start(v) + } else { + // moved past zero, use other bound + move_end(v) + } + } else { + let end = v.end.wrapping_add(count) & max_value; + let overshot_zero = (1..=v.end).contains(&end); + if overshot_zero { + // moved past zero, use other bound + move_start(v) + } else { + move_end(v) + } } - - Some((start, Scalar { value, valid_range: v.with_end(end) })) } } @@ -1139,7 +1182,7 @@ pub struct Layout { impl Layout { pub fn scalar(cx: &C, scalar: Scalar) -> Self { - let largest_niche = Niche::from_scalar(cx, Size::ZERO, scalar.clone()); + let largest_niche = Niche::from_scalar(cx, Size::ZERO, scalar); let size = scalar.value.size(cx); let align = scalar.value.align(cx); Layout { @@ -1173,46 +1216,6 @@ impl<'a, Ty> Deref for TyAndLayout<'a, Ty> { } } -/// Trait for context types that can compute layouts of things. -pub trait LayoutOf<'a>: Sized { - type Ty: TyAbiInterface<'a, Self>; - type TyAndLayout: MaybeResult>; - - fn layout_of(&self, ty: Self::Ty) -> Self::TyAndLayout; - fn spanned_layout_of(&self, ty: Self::Ty, _span: Span) -> Self::TyAndLayout { - self.layout_of(ty) - } -} - -pub trait MaybeResult { - type Error; - - fn from(x: Result) -> Self; - fn to_result(self) -> Result; -} - -impl MaybeResult for T { - type Error = !; - - fn from(Ok(x): Result) -> Self { - x - } - fn to_result(self) -> Result { - Ok(self) - } -} - -impl MaybeResult for Result { - type Error = E; - - fn from(x: Result) -> Self { - x - } - fn to_result(self) -> Result { - self - } -} - #[derive(Copy, Clone, PartialEq, Eq, Debug)] pub enum PointerKind { /// Most general case, we know no restrictions to tell LLVM. @@ -1305,25 +1308,22 @@ impl<'a, Ty> TyAndLayout<'a, Ty> { Ty: TyAbiInterface<'a, C>, C: HasDataLayout, { - let scalar_allows_raw_init = move |s: &Scalar| -> bool { + let scalar_allows_raw_init = move |s: Scalar| -> bool { if zero { // The range must contain 0. - s.valid_range.contains_zero() + s.valid_range.contains(0) } else { - // The range must include all values. `valid_range_exclusive` handles - // the wrap-around using target arithmetic; with wrap-around then the full - // range is one where `start == end`. - let range = s.valid_range_exclusive(cx); - range.start == range.end + // The range must include all values. + s.is_always_valid(cx) } }; // Check the ABI. - let valid = match &self.abi { + let valid = match self.abi { Abi::Uninhabited => false, // definitely UB Abi::Scalar(s) => scalar_allows_raw_init(s), Abi::ScalarPair(s1, s2) => scalar_allows_raw_init(s1) && scalar_allows_raw_init(s2), - Abi::Vector { element: s, count } => *count == 0 || scalar_allows_raw_init(s), + Abi::Vector { element: s, count } => count == 0 || scalar_allows_raw_init(s), Abi::Aggregate { .. } => true, // Fields are checked below. }; if !valid { diff --git a/compiler/rustc_target/src/lib.rs b/compiler/rustc_target/src/lib.rs index e75c52555b..23d5d575d9 100644 --- a/compiler/rustc_target/src/lib.rs +++ b/compiler/rustc_target/src/lib.rs @@ -15,7 +15,6 @@ #![feature(exhaustive_patterns)] #![feature(min_specialization)] #![feature(step_trait)] -#![feature(unchecked_math)] use std::path::{Path, PathBuf}; diff --git a/compiler/rustc_target/src/spec/aarch64_apple_darwin.rs b/compiler/rustc_target/src/spec/aarch64_apple_darwin.rs index bf3ec8f916..dc91f12309 100644 --- a/compiler/rustc_target/src/spec/aarch64_apple_darwin.rs +++ b/compiler/rustc_target/src/spec/aarch64_apple_darwin.rs @@ -4,7 +4,9 @@ pub fn target() -> Target { let mut base = super::apple_base::opts("macos"); base.cpu = "apple-a12".to_string(); base.max_atomic_width = Some(128); - base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::LEAK | SanitizerSet::THREAD; + + // FIXME: The leak sanitizer currently fails the tests, see #88132. + base.supported_sanitizers = SanitizerSet::ADDRESS | 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()); diff --git a/compiler/rustc_target/src/spec/aarch64_kmc_solid_asp3.rs b/compiler/rustc_target/src/spec/aarch64_kmc_solid_asp3.rs new file mode 100644 index 0000000000..61e3be617e --- /dev/null +++ b/compiler/rustc_target/src/spec/aarch64_kmc_solid_asp3.rs @@ -0,0 +1,19 @@ +use super::{RelocModel, Target, TargetOptions}; + +pub fn target() -> Target { + let base = super::solid_base::opts("asp3"); + Target { + llvm_target: "aarch64-unknown-none".to_string(), + pointer_width: 64, + data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".to_string(), + arch: "aarch64".to_string(), + options: TargetOptions { + linker: Some("aarch64-kmc-elf-gcc".to_owned()), + features: "+neon,+fp-armv8".to_string(), + relocation_model: RelocModel::Static, + disable_redzone: true, + max_atomic_width: Some(128), + ..base + }, + } +} diff --git a/compiler/rustc_target/src/spec/android_base.rs b/compiler/rustc_target/src/spec/android_base.rs index aaf81648c5..0f01a78c8c 100644 --- a/compiler/rustc_target/src/spec/android_base.rs +++ b/compiler/rustc_target/src/spec/android_base.rs @@ -1,7 +1,7 @@ use crate::spec::{LinkerFlavor, TargetOptions}; pub fn opts() -> TargetOptions { - let mut base = super::linux_gnu_base::opts(); + let mut base = super::linux_base::opts(); base.os = "android".to_string(); // Many of the symbols defined in compiler-rt are also defined in libgcc. // Android's linker doesn't like that by default. diff --git a/compiler/rustc_target/src/spec/armv6k_nintendo_3ds.rs b/compiler/rustc_target/src/spec/armv6k_nintendo_3ds.rs new file mode 100644 index 0000000000..01f5c197d2 --- /dev/null +++ b/compiler/rustc_target/src/spec/armv6k_nintendo_3ds.rs @@ -0,0 +1,43 @@ +use crate::spec::{LinkArgs, LinkerFlavor, PanicStrategy, RelocModel, Target, TargetOptions}; + +/// A base target for Nintendo 3DS devices using the devkitARM toolchain. +/// +/// Requires the devkitARM toolchain for 3DS targets on the host system. + +pub fn target() -> Target { + let mut pre_link_args = LinkArgs::new(); + pre_link_args.insert( + LinkerFlavor::Gcc, + vec![ + "-specs=3dsx.specs".to_string(), + "-mtune=mpcore".to_string(), + "-mfloat-abi=hard".to_string(), + "-mtp=soft".to_string(), + ], + ); + + Target { + llvm_target: "armv6k-none-eabihf".to_string(), + pointer_width: 32, + data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(), + arch: "arm".to_string(), + + options: TargetOptions { + os: "horizon".to_string(), + env: "newlib".to_string(), + vendor: "nintendo".to_string(), + abi: "eabihf".to_string(), + linker_flavor: LinkerFlavor::Gcc, + cpu: "mpcore".to_string(), + executables: true, + families: vec!["unix".to_string()], + linker: Some("arm-none-eabi-gcc".to_string()), + relocation_model: RelocModel::Static, + 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/armv7_unknown_linux_uclibceabihf.rs b/compiler/rustc_target/src/spec/armv7_unknown_linux_uclibceabihf.rs new file mode 100644 index 0000000000..d230f77bde --- /dev/null +++ b/compiler/rustc_target/src/spec/armv7_unknown_linux_uclibceabihf.rs @@ -0,0 +1,24 @@ +use crate::spec::{Target, TargetOptions}; + +// This target is for uclibc Linux on ARMv7 without NEON or +// thumb-mode. See the thumbv7neon variant for enabling both. + +pub fn target() -> Target { + let base = super::linux_uclibc_base::opts(); + Target { + llvm_target: "armv7-unknown-linux-gnueabihf".to_string(), + pointer_width: 32, + data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(), + arch: "arm".to_string(), + + options: TargetOptions { + // Info about features at https://wiki.debian.org/ArmHardFloatPort + features: "+v7,+vfp3,-d32,+thumb2,-neon".to_string(), + cpu: "generic".to_string(), + max_atomic_width: Some(64), + mcount: "_mcount".to_string(), + abi: "eabihf".to_string(), + ..base + }, + } +} diff --git a/compiler/rustc_target/src/spec/armv7a_kmc_solid_asp3_eabi.rs b/compiler/rustc_target/src/spec/armv7a_kmc_solid_asp3_eabi.rs new file mode 100644 index 0000000000..344c48022b --- /dev/null +++ b/compiler/rustc_target/src/spec/armv7a_kmc_solid_asp3_eabi.rs @@ -0,0 +1,19 @@ +use super::{RelocModel, Target, TargetOptions}; + +pub fn target() -> Target { + let base = super::solid_base::opts("asp3"); + Target { + llvm_target: "armv7a-none-eabi".to_string(), + pointer_width: 32, + data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(), + arch: "arm".to_string(), + options: TargetOptions { + linker: Some("arm-kmc-eabi-gcc".to_owned()), + features: "+v7,+soft-float,+thumb2,-neon".to_string(), + relocation_model: RelocModel::Static, + disable_redzone: true, + max_atomic_width: Some(64), + ..base + }, + } +} diff --git a/compiler/rustc_target/src/spec/armv7a_kmc_solid_asp3_eabihf.rs b/compiler/rustc_target/src/spec/armv7a_kmc_solid_asp3_eabihf.rs new file mode 100644 index 0000000000..375502478f --- /dev/null +++ b/compiler/rustc_target/src/spec/armv7a_kmc_solid_asp3_eabihf.rs @@ -0,0 +1,19 @@ +use super::{RelocModel, Target, TargetOptions}; + +pub fn target() -> Target { + let base = super::solid_base::opts("asp3"); + Target { + llvm_target: "armv7a-none-eabihf".to_string(), + pointer_width: 32, + data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(), + arch: "arm".to_string(), + options: TargetOptions { + linker: Some("arm-kmc-eabi-gcc".to_owned()), + features: "+v7,+vfp3,-d32,+thumb2,-neon".to_string(), + relocation_model: RelocModel::Static, + disable_redzone: true, + max_atomic_width: Some(64), + ..base + }, + } +} diff --git a/compiler/rustc_target/src/spec/m68k_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/m68k_unknown_linux_gnu.rs new file mode 100644 index 0000000000..fff7b25a34 --- /dev/null +++ b/compiler/rustc_target/src/spec/m68k_unknown_linux_gnu.rs @@ -0,0 +1,15 @@ +use crate::abi::Endian; +use crate::spec::{Target, TargetOptions}; + +pub fn target() -> Target { + let mut base = super::linux_base::opts(); + base.max_atomic_width = Some(32); + + Target { + llvm_target: "m68k-unknown-linux-gnu".to_string(), + pointer_width: 32, + data_layout: "E-m:e-p:32:16:32-i8:8:8-i16:16:16-i32:16:32-n8:16:32-a:0:16-S16".to_string(), + arch: "m68k".to_string(), + options: TargetOptions { endian: Endian::Big, mcount: "_mcount".to_string(), ..base }, + } +} diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 273221360b..ff5dfa3f74 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -75,6 +75,7 @@ mod netbsd_base; mod openbsd_base; mod redox_base; mod solaris_base; +mod solid_base; mod thumb_base; mod uefi_msvc_base; mod vxworks_base; @@ -287,6 +288,7 @@ impl ToJson for MergeFunctions { pub enum RelocModel { Static, Pic, + Pie, DynamicNoPic, Ropi, Rwpi, @@ -300,6 +302,7 @@ impl FromStr for RelocModel { Ok(match s { "static" => RelocModel::Static, "pic" => RelocModel::Pic, + "pie" => RelocModel::Pie, "dynamic-no-pic" => RelocModel::DynamicNoPic, "ropi" => RelocModel::Ropi, "rwpi" => RelocModel::Rwpi, @@ -314,6 +317,7 @@ impl ToJson for RelocModel { match *self { RelocModel::Static => "static", RelocModel::Pic => "pic", + RelocModel::Pie => "pie", RelocModel::DynamicNoPic => "dynamic-no-pic", RelocModel::Ropi => "ropi", RelocModel::Rwpi => "rwpi", @@ -742,6 +746,7 @@ supported_targets! { ("x86_64-unknown-linux-gnux32", x86_64_unknown_linux_gnux32), ("i686-unknown-linux-gnu", i686_unknown_linux_gnu), ("i586-unknown-linux-gnu", i586_unknown_linux_gnu), + ("m68k-unknown-linux-gnu", m68k_unknown_linux_gnu), ("mips-unknown-linux-gnu", mips_unknown_linux_gnu), ("mips64-unknown-linux-gnuabi64", mips64_unknown_linux_gnuabi64), ("mips64el-unknown-linux-gnuabi64", mips64el_unknown_linux_gnuabi64), @@ -931,6 +936,10 @@ supported_targets! { ("powerpc-wrs-vxworks-spe", powerpc_wrs_vxworks_spe), ("powerpc64-wrs-vxworks", powerpc64_wrs_vxworks), + ("aarch64-kmc-solid_asp3", aarch64_kmc_solid_asp3), + ("armv7a-kmc-solid_asp3-eabi", armv7a_kmc_solid_asp3_eabi), + ("armv7a-kmc-solid_asp3-eabihf", armv7a_kmc_solid_asp3_eabihf), + ("mipsel-sony-psp", mipsel_sony_psp), ("mipsel-unknown-none", mipsel_unknown_none), ("thumbv4t-none-eabi", thumbv4t_none_eabi), @@ -941,6 +950,10 @@ supported_targets! { ("bpfeb-unknown-none", bpfeb_unknown_none), ("bpfel-unknown-none", bpfel_unknown_none), + + ("armv6k-nintendo-3ds", armv6k_nintendo_3ds), + + ("armv7-unknown-linux-uclibceabihf", armv7_unknown_linux_uclibceabihf), } /// Warnings encountered when parsing the target `json`. diff --git a/compiler/rustc_target/src/spec/solid_base.rs b/compiler/rustc_target/src/spec/solid_base.rs new file mode 100644 index 0000000000..c6a279d92e --- /dev/null +++ b/compiler/rustc_target/src/spec/solid_base.rs @@ -0,0 +1,12 @@ +use super::FramePointer; +use crate::spec::TargetOptions; + +pub fn opts(kernel: &str) -> TargetOptions { + TargetOptions { + os: format!("solid_{}", kernel), + vendor: "kmc".to_string(), + frame_pointer: FramePointer::NonLeaf, + has_elf_tls: true, + ..Default::default() + } +} diff --git a/compiler/rustc_trait_selection/Cargo.toml b/compiler/rustc_trait_selection/Cargo.toml index e2c626d1b2..d59bdae033 100644 --- a/compiler/rustc_trait_selection/Cargo.toml +++ b/compiler/rustc_trait_selection/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustc_trait_selection" version = "0.0.0" -edition = "2018" +edition = "2021" [lib] doctest = false @@ -17,7 +17,9 @@ rustc_errors = { path = "../rustc_errors" } rustc_hir = { path = "../rustc_hir" } rustc_index = { path = "../rustc_index" } rustc_infer = { path = "../rustc_infer" } +rustc_lint_defs = { path = "../rustc_lint_defs" } rustc_macros = { path = "../rustc_macros" } +rustc_query_system = { path = "../rustc_query_system" } rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } rustc_target = { path = "../rustc_target" } diff --git a/compiler/rustc_trait_selection/src/autoderef.rs b/compiler/rustc_trait_selection/src/autoderef.rs index 969962e55b..53afe4ca06 100644 --- a/compiler/rustc_trait_selection/src/autoderef.rs +++ b/compiler/rustc_trait_selection/src/autoderef.rs @@ -5,7 +5,7 @@ use rustc_hir as hir; use rustc_infer::infer::InferCtxt; use rustc_middle::ty::{self, TraitRef, Ty, TyCtxt, WithConstness}; use rustc_middle::ty::{ToPredicate, TypeFoldable}; -use rustc_session::DiagnosticMessageId; +use rustc_session::{DiagnosticMessageId, Limit}; use rustc_span::def_id::LOCAL_CRATE; use rustc_span::Span; @@ -135,7 +135,7 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> { let obligation = traits::Obligation::new( cause.clone(), self.param_env, - trait_ref.without_const().to_predicate(tcx), + ty::Binder::dummy(trait_ref).without_const().to_predicate(tcx), ); if !self.infcx.predicate_may_hold(&obligation) { debug!("overloaded_deref_ty: cannot match obligation"); @@ -217,7 +217,10 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> { pub fn report_autoderef_recursion_limit_error<'tcx>(tcx: TyCtxt<'tcx>, span: Span, ty: Ty<'tcx>) { // We've reached the recursion limit, error gracefully. - let suggested_limit = tcx.recursion_limit() * 2; + let suggested_limit = match tcx.recursion_limit() { + Limit(0) => Limit(2), + limit => limit * 2, + }; let msg = format!("reached the recursion limit while auto-dereferencing `{:?}`", ty); let error_id = (DiagnosticMessageId::ErrorId(55), Some(span), msg); let fresh = tcx.sess.one_time_diagnostics.borrow_mut().insert(error_id); @@ -231,7 +234,8 @@ pub fn report_autoderef_recursion_limit_error<'tcx>(tcx: TyCtxt<'tcx>, span: Spa ) .span_label(span, "deref recursion limit reached") .help(&format!( - "consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate (`{}`)", + "consider increasing the recursion limit by adding a \ + `#![recursion_limit = \"{}\"]` attribute to your crate (`{}`)", suggested_limit, tcx.crate_name(LOCAL_CRATE), )) diff --git a/compiler/rustc_trait_selection/src/infer.rs b/compiler/rustc_trait_selection/src/infer.rs index c90649353e..70816b5722 100644 --- a/compiler/rustc_trait_selection/src/infer.rs +++ b/compiler/rustc_trait_selection/src/infer.rs @@ -1,11 +1,8 @@ use crate::traits::query::evaluate_obligation::InferCtxtExt as _; -use crate::traits::query::outlives_bounds::InferCtxtExt as _; use crate::traits::{self, TraitEngine, TraitEngineExt}; -use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::lang_items::LangItem; -use rustc_infer::infer::outlives::env::OutlivesEnvironment; use rustc_infer::traits::ObligationCause; use rustc_middle::arena::ArenaAllocatable; use rustc_middle::infer::canonical::{Canonical, CanonicalizedQueryResponse, QueryResponse}; @@ -119,7 +116,7 @@ impl<'cx, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'cx, 'tcx> { cause: traits::ObligationCause::dummy(), param_env, recursion_depth: 0, - predicate: trait_ref.without_const().to_predicate(self.tcx), + predicate: ty::Binder::dummy(trait_ref).without_const().to_predicate(self.tcx), }; self.evaluate_obligation(&obligation).unwrap_or(traits::EvaluationResult::EvaluatedToErr) } @@ -179,48 +176,3 @@ impl<'tcx> InferCtxtBuilderExt<'tcx> for InferCtxtBuilder<'tcx> { ) } } - -pub trait OutlivesEnvironmentExt<'tcx> { - fn add_implied_bounds( - &mut self, - infcx: &InferCtxt<'a, 'tcx>, - fn_sig_tys: &[Ty<'tcx>], - body_id: hir::HirId, - span: Span, - ); -} - -impl<'tcx> OutlivesEnvironmentExt<'tcx> for OutlivesEnvironment<'tcx> { - /// This method adds "implied bounds" into the outlives environment. - /// Implied bounds are outlives relationships that we can deduce - /// on the basis that certain types must be well-formed -- these are - /// either the types that appear in the function signature or else - /// the input types to an impl. For example, if you have a function - /// like - /// - /// ``` - /// fn foo<'a, 'b, T>(x: &'a &'b [T]) { } - /// ``` - /// - /// we can assume in the caller's body that `'b: 'a` and that `T: - /// 'b` (and hence, transitively, that `T: 'a`). This method would - /// add those assumptions into the outlives-environment. - /// - /// Tests: `src/test/ui/regions/regions-free-region-ordering-*.rs` - fn add_implied_bounds( - &mut self, - infcx: &InferCtxt<'a, 'tcx>, - fn_sig_tys: &[Ty<'tcx>], - body_id: hir::HirId, - span: Span, - ) { - debug!("add_implied_bounds()"); - - for &ty in fn_sig_tys { - let ty = infcx.resolve_vars_if_possible(ty); - debug!("add_implied_bounds: ty = {}", ty); - let implied_bounds = infcx.implied_outlives_bounds(self.param_env, body_id, ty, span); - self.add_outlives_bounds(Some(infcx), implied_bounds) - } - } -} diff --git a/compiler/rustc_trait_selection/src/opaque_types.rs b/compiler/rustc_trait_selection/src/opaque_types.rs index b743c809ca..c220546268 100644 --- a/compiler/rustc_trait_selection/src/opaque_types.rs +++ b/compiler/rustc_trait_selection/src/opaque_types.rs @@ -1,4 +1,3 @@ -use crate::infer::InferCtxtExt as _; use crate::traits::{self, ObligationCause, PredicateObligation}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::Lrc; @@ -499,7 +498,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { /// - `substs`, the substs used to instantiate this opaque type /// - `instantiated_ty`, the inferred type C1 -- fully resolved, lifted version of /// `opaque_defn.concrete_ty` - #[instrument(skip(self))] + #[instrument(level = "debug", skip(self))] fn infer_opaque_definition_from_instantiation( &self, opaque_type_key: OpaqueTypeKey<'tcx>, @@ -518,6 +517,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { debug!(?id_substs); let map: FxHashMap, GenericArg<'tcx>> = substs.iter().enumerate().map(|(index, subst)| (subst, id_substs[index])).collect(); + debug!("map = {:#?}", map); // Convert the type from the function into a type valid outside // the function, by replacing invalid regions with 'static, @@ -673,6 +673,7 @@ impl TypeFolder<'tcx> for ReverseMapper<'tcx> { self.tcx } + #[instrument(skip(self), level = "debug")] fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { match r { // Ignore bound regions and `'static` regions that appear in the @@ -863,7 +864,6 @@ struct Instantiator<'a, 'tcx> { } impl<'a, 'tcx> Instantiator<'a, 'tcx> { - #[instrument(skip(self))] fn instantiate_opaque_types_in_map>(&mut self, value: T) -> T { let tcx = self.infcx.tcx; value.fold_with(&mut BottomUpFolder { @@ -954,6 +954,7 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> { }) } + #[instrument(skip(self), level = "debug")] fn fold_opaque_ty( &mut self, ty: Ty<'tcx>, @@ -964,25 +965,18 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> { let tcx = infcx.tcx; let OpaqueTypeKey { def_id, substs } = opaque_type_key; - debug!("instantiate_opaque_types: Opaque(def_id={:?}, substs={:?})", def_id, substs); - // 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!("instantiate_opaque_types: returning concrete ty {:?}", opaque_defn.concrete_ty); + 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, }); - // Make sure that we are in fact defining the *entire* type - // (e.g., `type Foo = impl Bar;` needs to be - // defined by a function like `fn foo() -> Foo`). - debug!("instantiate_opaque_types: param_env={:#?}", self.param_env,); - debug!("instantiate_opaque_types: generics={:#?}", tcx.generics_of(def_id),); - // 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`, @@ -999,43 +993,40 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> { infcx.opaque_types_vars.insert(ty_var, ty); } - debug!("instantiate_opaque_types: ty_var={:?}", ty_var); - self.compute_opaque_type_obligations(opaque_type_key); - - ty_var - } - - fn compute_opaque_type_obligations(&mut self, opaque_type_key: OpaqueTypeKey<'tcx>) { - let infcx = self.infcx; - let tcx = infcx.tcx; - let OpaqueTypeKey { def_id, substs } = opaque_type_key; + debug!("generated new type inference var {:?}", ty_var.kind()); let item_bounds = tcx.explicit_item_bounds(def_id); - debug!("instantiate_opaque_types: bounds={:#?}", item_bounds); - let bounds: Vec<_> = - item_bounds.iter().map(|(bound, _)| bound.subst(tcx, substs)).collect(); - let param_env = tcx.param_env(def_id); - let InferOk { value: bounds, obligations } = infcx.partially_normalize_associated_types_in( - ObligationCause::misc(self.value_span, self.body_id), - param_env, - bounds, - ); - self.obligations.extend(obligations); + self.obligations.reserve(item_bounds.len()); + for (predicate, _) in item_bounds { + debug!(?predicate); + let predicate = predicate.subst(tcx, substs); + debug!(?predicate); - debug!("instantiate_opaque_types: bounds={:?}", bounds); + // 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); - for predicate in &bounds { 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; + return tcx.ty_error(); } } - } - - self.obligations.reserve(bounds.len()); - for predicate in bounds { // 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`. @@ -1045,9 +1036,11 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> { traits::ObligationCause::new(self.value_span, self.body_id, traits::OpaqueType); // Require that the predicate holds for the concrete type. - debug!("instantiate_opaque_types: predicate={:?}", predicate); + debug!(?predicate); self.obligations.push(traits::Obligation::new(cause, self.param_env, predicate)); } + + ty_var } } @@ -1071,11 +1064,7 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> { /// 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`. -pub fn may_define_opaque_type( - tcx: TyCtxt<'_>, - def_id: LocalDefId, - opaque_hir_id: hir::HirId, -) -> bool { +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. @@ -1111,18 +1100,17 @@ pub fn may_define_opaque_type( /// /// Requires that trait definitions have been processed so that we can /// elaborate predicates and walk supertraits. +#[instrument(skip(tcx, predicates), level = "debug")] crate fn required_region_bounds( tcx: TyCtxt<'tcx>, erased_self_ty: Ty<'tcx>, predicates: impl Iterator>, ) -> Vec> { - debug!("required_region_bounds(erased_self_ty={:?})", erased_self_ty); - assert!(!erased_self_ty.has_escaping_bound_vars()); traits::elaborate_predicates(tcx, predicates) .filter_map(|obligation| { - debug!("required_region_bounds(obligation={:?})", obligation); + debug!(?obligation); match obligation.predicate.kind().skip_binder() { ty::PredicateKind::Projection(..) | ty::PredicateKind::Trait(..) diff --git a/compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs b/compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs index 7a690af0cc..ec62ee4006 100644 --- a/compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs @@ -7,16 +7,21 @@ use crate::traits::{ ChalkEnvironmentAndGoal, FulfillmentError, FulfillmentErrorCode, ObligationCause, PredicateObligation, SelectionError, TraitEngine, }; -use rustc_data_structures::fx::FxIndexSet; +use rustc_data_structures::fx::{FxHashMap, FxIndexSet}; use rustc_middle::ty::{self, Ty}; pub struct FulfillmentContext<'tcx> { obligations: FxIndexSet>, + + relationships: FxHashMap, } impl FulfillmentContext<'tcx> { crate fn new() -> Self { - FulfillmentContext { obligations: FxIndexSet::default() } + FulfillmentContext { + obligations: FxIndexSet::default(), + relationships: FxHashMap::default(), + } } } @@ -39,6 +44,8 @@ impl TraitEngine<'tcx> for FulfillmentContext<'tcx> { assert!(!infcx.is_in_snapshot()); let obligation = infcx.resolve_vars_if_possible(obligation); + super::relationships::update(self, infcx, &obligation); + self.obligations.insert(obligation); } @@ -57,7 +64,6 @@ impl TraitEngine<'tcx> for FulfillmentContext<'tcx> { .map(|obligation| FulfillmentError { obligation: obligation.clone(), code: FulfillmentErrorCode::CodeAmbiguity, - points_at_arg_span: false, // FIXME - does Chalk have a notation of 'root obligation'? // This is just for diagnostics, so it's okay if this is wrong root_obligation: obligation.clone(), @@ -112,7 +118,6 @@ impl TraitEngine<'tcx> for FulfillmentContext<'tcx> { code: FulfillmentErrorCode::CodeSelectionError( SelectionError::Unimplemented, ), - points_at_arg_span: false, // FIXME - does Chalk have a notation of 'root obligation'? // This is just for diagnostics, so it's okay if this is wrong root_obligation: obligation, @@ -129,7 +134,6 @@ impl TraitEngine<'tcx> for FulfillmentContext<'tcx> { code: FulfillmentErrorCode::CodeSelectionError( SelectionError::Unimplemented, ), - points_at_arg_span: false, // FIXME - does Chalk have a notation of 'root obligation'? // This is just for diagnostics, so it's okay if this is wrong root_obligation: obligation, @@ -149,4 +153,8 @@ impl TraitEngine<'tcx> for FulfillmentContext<'tcx> { fn pending_obligations(&self) -> Vec> { self.obligations.iter().cloned().collect() } + + fn relationships(&mut self) -> &mut FxHashMap { + &mut self.relationships + } } diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs index ddabe5967d..1193d10d6a 100644 --- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs +++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs @@ -6,16 +6,16 @@ //! this is not as easy. //! //! In this case we try to build an abstract representation of this constant using -//! `mir_abstract_const` which can then be checked for structural equality with other +//! `thir_abstract_const` which can then be checked for structural equality with other //! generic constants mentioned in the `caller_bounds` of the current environment. use rustc_errors::ErrorReported; use rustc_hir::def::DefKind; -use rustc_index::bit_set::BitSet; use rustc_index::vec::IndexVec; use rustc_infer::infer::InferCtxt; -use rustc_middle::mir::abstract_const::{Node, NodeId, NotConstEvaluatable}; +use rustc_middle::mir; use rustc_middle::mir::interpret::ErrorHandled; -use rustc_middle::mir::{self, Rvalue, StatementKind, TerminatorKind}; +use rustc_middle::thir; +use rustc_middle::thir::abstract_const::{self, Node, NodeId, NotConstEvaluatable}; use rustc_middle::ty::subst::{Subst, SubstsRef}; use rustc_middle::ty::{self, TyCtxt, TypeFoldable}; use rustc_session::lint; @@ -196,7 +196,7 @@ impl<'tcx> AbstractConst<'tcx> { tcx: TyCtxt<'tcx>, uv: ty::Unevaluated<'tcx, ()>, ) -> Result>, ErrorReported> { - let inner = tcx.mir_abstract_const_opt_const_arg(uv.def)?; + let inner = tcx.thir_abstract_const_opt_const_arg(uv.def)?; debug!("AbstractConst::new({:?}) = {:?}", uv, inner); Ok(inner.map(|inner| AbstractConst { inner, substs: uv.substs(tcx) })) } @@ -223,137 +223,88 @@ impl<'tcx> AbstractConst<'tcx> { } } -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -struct WorkNode<'tcx> { - node: Node<'tcx>, - span: Span, - used: bool, -} - struct AbstractConstBuilder<'a, 'tcx> { tcx: TyCtxt<'tcx>, - body: &'a mir::Body<'tcx>, + body_id: thir::ExprId, + body: &'a thir::Thir<'tcx>, /// The current WIP node tree. - /// - /// We require all nodes to be used in the final abstract const, - /// so we store this here. Note that we also consider nodes as used - /// if they are mentioned in an assert, so some used nodes are never - /// actually reachable by walking the [`AbstractConst`]. - nodes: IndexVec>, - locals: IndexVec, - /// We only allow field accesses if they access - /// the result of a checked operation. - checked_op_locals: BitSet, + nodes: IndexVec>, } impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> { - fn error(&mut self, span: Option, msg: &str) -> Result { + fn root_span(&self) -> Span { + self.body.exprs[self.body_id].span + } + + fn error(&mut self, span: Span, msg: &str) -> Result { self.tcx .sess - .struct_span_err(self.body.span, "overly complex generic constant") - .span_label(span.unwrap_or(self.body.span), msg) + .struct_span_err(self.root_span(), "overly complex generic constant") + .span_label(span, msg) .help("consider moving this anonymous constant into a `const` function") .emit(); Err(ErrorReported) } + fn maybe_supported_error(&mut self, span: Span, msg: &str) -> Result { + self.tcx + .sess + .struct_span_err(self.root_span(), "overly complex generic constant") + .span_label(span, msg) + .help("consider moving this anonymous constant into a `const` function") + .note("this operation may be supported in the future") + .emit(); + + Err(ErrorReported) + } fn new( tcx: TyCtxt<'tcx>, - body: &'a mir::Body<'tcx>, + (body, body_id): (&'a thir::Thir<'tcx>, thir::ExprId), ) -> Result>, ErrorReported> { - let mut builder = AbstractConstBuilder { - tcx, - body, - nodes: IndexVec::new(), - locals: IndexVec::from_elem(NodeId::MAX, &body.local_decls), - checked_op_locals: BitSet::new_empty(body.local_decls.len()), - }; + let builder = AbstractConstBuilder { tcx, body_id, body, nodes: IndexVec::new() }; - // We don't have to look at concrete constants, as we - // can just evaluate them. - if !body.is_polymorphic { + struct IsThirPolymorphic<'a, 'tcx> { + is_poly: bool, + thir: &'a thir::Thir<'tcx>, + tcx: TyCtxt<'tcx>, + } + + use thir::visit; + impl<'a, 'tcx: 'a> visit::Visitor<'a, 'tcx> for IsThirPolymorphic<'a, 'tcx> { + fn thir(&self) -> &'a thir::Thir<'tcx> { + &self.thir + } + + fn visit_expr(&mut self, expr: &thir::Expr<'tcx>) { + self.is_poly |= expr.ty.definitely_has_param_types_or_consts(self.tcx); + if !self.is_poly { + visit::walk_expr(self, expr) + } + } + + fn visit_pat(&mut self, pat: &thir::Pat<'tcx>) { + self.is_poly |= pat.ty.definitely_has_param_types_or_consts(self.tcx); + if !self.is_poly { + visit::walk_pat(self, pat); + } + } + + fn visit_const(&mut self, ct: &'tcx ty::Const<'tcx>) { + self.is_poly |= ct.definitely_has_param_types_or_consts(self.tcx); + } + } + + let mut is_poly_vis = IsThirPolymorphic { is_poly: false, thir: body, tcx }; + visit::walk_expr(&mut is_poly_vis, &body[body_id]); + debug!("AbstractConstBuilder: is_poly={}", is_poly_vis.is_poly); + if !is_poly_vis.is_poly { return Ok(None); } - // We only allow consts without control flow, so - // we check for cycles here which simplifies the - // rest of this implementation. - if body.is_cfg_cyclic() { - builder.error(None, "cyclic anonymous constants are forbidden")?; - } - Ok(Some(builder)) } - fn add_node(&mut self, node: Node<'tcx>, span: Span) -> NodeId { - // Mark used nodes. - match node { - Node::Leaf(_) => (), - Node::Binop(_, lhs, rhs) => { - self.nodes[lhs].used = true; - self.nodes[rhs].used = true; - } - Node::UnaryOp(_, input) => { - self.nodes[input].used = true; - } - Node::FunctionCall(func, nodes) => { - self.nodes[func].used = true; - nodes.iter().for_each(|&n| self.nodes[n].used = true); - } - Node::Cast(_, operand, _) => { - self.nodes[operand].used = true; - } - } - - // Nodes start as unused. - self.nodes.push(WorkNode { node, span, used: false }) - } - - fn place_to_local( - &mut self, - span: Span, - p: &mir::Place<'tcx>, - ) -> Result { - const ZERO_FIELD: mir::Field = mir::Field::from_usize(0); - // Do not allow any projections. - // - // One exception are field accesses on the result of checked operations, - // which are required to support things like `1 + 2`. - if let Some(p) = p.as_local() { - debug_assert!(!self.checked_op_locals.contains(p)); - Ok(p) - } else if let &[mir::ProjectionElem::Field(ZERO_FIELD, _)] = p.projection.as_ref() { - // Only allow field accesses if the given local - // contains the result of a checked operation. - if self.checked_op_locals.contains(p.local) { - Ok(p.local) - } else { - self.error(Some(span), "unsupported projection")?; - } - } else { - self.error(Some(span), "unsupported projection")?; - } - } - - fn operand_to_node( - &mut self, - span: Span, - op: &mir::Operand<'tcx>, - ) -> Result { - debug!("operand_to_node: op={:?}", op); - match op { - mir::Operand::Copy(p) | mir::Operand::Move(p) => { - let local = self.place_to_local(span, p)?; - Ok(self.locals[local]) - } - mir::Operand::Constant(ct) => match ct.literal { - mir::ConstantKind::Ty(ct) => Ok(self.add_node(Node::Leaf(ct), span)), - mir::ConstantKind::Val(..) => self.error(Some(span), "unsupported constant")?, - }, - } - } - /// We do not allow all binary operations in abstract consts, so filter disallowed ones. fn check_binop(op: mir::BinOp) -> bool { use mir::BinOp::*; @@ -373,170 +324,166 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> { } } - fn build_statement(&mut self, stmt: &mir::Statement<'tcx>) -> Result<(), ErrorReported> { - debug!("AbstractConstBuilder: stmt={:?}", stmt); - let span = stmt.source_info.span; - match stmt.kind { - StatementKind::Assign(box (ref place, ref rvalue)) => { - let local = self.place_to_local(span, place)?; - match *rvalue { - Rvalue::Use(ref operand) => { - self.locals[local] = self.operand_to_node(span, operand)?; - Ok(()) - } - Rvalue::BinaryOp(op, box (ref lhs, ref rhs)) if Self::check_binop(op) => { - let lhs = self.operand_to_node(span, lhs)?; - let rhs = self.operand_to_node(span, rhs)?; - self.locals[local] = self.add_node(Node::Binop(op, lhs, rhs), span); - if op.is_checkable() { - bug!("unexpected unchecked checkable binary operation"); - } else { - Ok(()) - } - } - Rvalue::CheckedBinaryOp(op, box (ref lhs, ref rhs)) - if Self::check_binop(op) => - { - let lhs = self.operand_to_node(span, lhs)?; - let rhs = self.operand_to_node(span, rhs)?; - self.locals[local] = self.add_node(Node::Binop(op, lhs, rhs), span); - self.checked_op_locals.insert(local); - Ok(()) - } - Rvalue::UnaryOp(op, ref operand) if Self::check_unop(op) => { - let operand = self.operand_to_node(span, operand)?; - self.locals[local] = self.add_node(Node::UnaryOp(op, operand), span); - Ok(()) - } - Rvalue::Cast(cast_kind, ref operand, ty) => { - let operand = self.operand_to_node(span, operand)?; - self.locals[local] = - self.add_node(Node::Cast(cast_kind, operand, ty), span); - Ok(()) - } - _ => self.error(Some(span), "unsupported rvalue")?, - } - } - // These are not actually relevant for us here, so we can ignore them. - StatementKind::AscribeUserType(..) - | StatementKind::StorageLive(_) - | StatementKind::StorageDead(_) => Ok(()), - _ => self.error(Some(stmt.source_info.span), "unsupported statement")?, - } - } - - /// Possible return values: - /// - /// - `None`: unsupported terminator, stop building - /// - `Some(None)`: supported terminator, finish building - /// - `Some(Some(block))`: support terminator, build `block` next - fn build_terminator( - &mut self, - terminator: &mir::Terminator<'tcx>, - ) -> Result, ErrorReported> { - debug!("AbstractConstBuilder: terminator={:?}", terminator); - match terminator.kind { - TerminatorKind::Goto { target } => Ok(Some(target)), - TerminatorKind::Return => Ok(None), - TerminatorKind::Call { - ref func, - ref args, - destination: Some((ref place, target)), - // We do not care about `cleanup` here. Any branch which - // uses `cleanup` will fail const-eval and they therefore - // do not matter when checking for const evaluatability. - // - // Do note that even if `panic::catch_unwind` is made const, - // we still do not have to care about this, as we do not look - // into functions. - cleanup: _, - // Do not allow overloaded operators for now, - // we probably do want to allow this in the future. - // - // This is currently fairly irrelevant as it requires `const Trait`s. - from_hir_call: true, - fn_span, - } => { - let local = self.place_to_local(fn_span, place)?; - let func = self.operand_to_node(fn_span, func)?; - let args = self.tcx.arena.alloc_from_iter( - args.iter() - .map(|arg| self.operand_to_node(terminator.source_info.span, arg)) - .collect::, _>>()?, - ); - self.locals[local] = self.add_node(Node::FunctionCall(func, args), fn_span); - Ok(Some(target)) - } - TerminatorKind::Assert { ref cond, expected: false, target, .. } => { - let p = match cond { - mir::Operand::Copy(p) | mir::Operand::Move(p) => p, - mir::Operand::Constant(_) => bug!("unexpected assert"), - }; - - const ONE_FIELD: mir::Field = mir::Field::from_usize(1); - debug!("proj: {:?}", p.projection); - if let Some(p) = p.as_local() { - debug_assert!(!self.checked_op_locals.contains(p)); - // Mark locals directly used in asserts as used. - // - // This is needed because division does not use `CheckedBinop` but instead - // adds an explicit assert for `divisor != 0`. - self.nodes[self.locals[p]].used = true; - return Ok(Some(target)); - } else if let &[mir::ProjectionElem::Field(ONE_FIELD, _)] = p.projection.as_ref() { - // Only allow asserts checking the result of a checked operation. - if self.checked_op_locals.contains(p.local) { - return Ok(Some(target)); - } - } - - self.error(Some(terminator.source_info.span), "unsupported assertion")?; - } - _ => self.error(Some(terminator.source_info.span), "unsupported terminator")?, - } - } - - /// Builds the abstract const by walking the mir from start to finish - /// and bailing out when encountering an unsupported operation. + /// Builds the abstract const by walking the thir and bailing out when + /// encountering an unspported operation. fn build(mut self) -> Result<&'tcx [Node<'tcx>], ErrorReported> { - let mut block = &self.body.basic_blocks()[mir::START_BLOCK]; - // We checked for a cyclic cfg above, so this should terminate. - loop { - debug!("AbstractConstBuilder: block={:?}", block); - for stmt in block.statements.iter() { - self.build_statement(stmt)?; - } + debug!("Abstractconstbuilder::build: body={:?}", &*self.body); + self.recurse_build(self.body_id)?; - if let Some(next) = self.build_terminator(block.terminator())? { - block = &self.body.basic_blocks()[next]; - } else { - break; - } - } - - assert_eq!(self.locals[mir::RETURN_PLACE], self.nodes.last().unwrap()); for n in self.nodes.iter() { - if let Node::Leaf(ty::Const { val: ty::ConstKind::Unevaluated(ct), ty: _ }) = n.node { + if let Node::Leaf(ty::Const { val: ty::ConstKind::Unevaluated(ct), ty: _ }) = n { // `AbstractConst`s should not contain any promoteds as they require references which // are not allowed. assert_eq!(ct.promoted, None); } } - self.nodes[self.locals[mir::RETURN_PLACE]].used = true; - if let Some(&unused) = self.nodes.iter().find(|n| !n.used) { - self.error(Some(unused.span), "dead code")?; - } + Ok(self.tcx.arena.alloc_from_iter(self.nodes.into_iter())) + } - Ok(self.tcx.arena.alloc_from_iter(self.nodes.into_iter().map(|n| n.node))) + fn recurse_build(&mut self, node: thir::ExprId) -> Result { + use thir::ExprKind; + let node = &self.body.exprs[node]; + debug!("recurse_build: node={:?}", node); + Ok(match &node.kind { + // I dont know if handling of these 3 is correct + &ExprKind::Scope { value, .. } => self.recurse_build(value)?, + &ExprKind::PlaceTypeAscription { source, .. } + | &ExprKind::ValueTypeAscription { source, .. } => self.recurse_build(source)?, + + // subtle: associated consts are literals this arm handles + // `::ASSOC` as well as `12` + &ExprKind::Literal { literal, .. } => self.nodes.push(Node::Leaf(literal)), + + ExprKind::Call { fun, args, .. } => { + let fun = self.recurse_build(*fun)?; + + let mut new_args = Vec::::with_capacity(args.len()); + for &id in args.iter() { + new_args.push(self.recurse_build(id)?); + } + let new_args = self.tcx.arena.alloc_slice(&new_args); + self.nodes.push(Node::FunctionCall(fun, new_args)) + } + &ExprKind::Binary { op, lhs, rhs } if Self::check_binop(op) => { + let lhs = self.recurse_build(lhs)?; + let rhs = self.recurse_build(rhs)?; + self.nodes.push(Node::Binop(op, lhs, rhs)) + } + &ExprKind::Unary { op, arg } if Self::check_unop(op) => { + let arg = self.recurse_build(arg)?; + self.nodes.push(Node::UnaryOp(op, arg)) + } + // This is necessary so that the following compiles: + // + // ``` + // fn foo(a: [(); N + 1]) { + // bar::<{ N + 1 }>(); + // } + // ``` + ExprKind::Block { body: thir::Block { stmts: box [], expr: Some(e), .. } } => { + self.recurse_build(*e)? + } + // `ExprKind::Use` happens when a `hir::ExprKind::Cast` is a + // "coercion cast" i.e. using a coercion or is a no-op. + // This is important so that `N as usize as usize` doesnt unify with `N as usize`. (untested) + &ExprKind::Use { source } => { + let arg = self.recurse_build(source)?; + self.nodes.push(Node::Cast(abstract_const::CastKind::Use, arg, node.ty)) + } + &ExprKind::Cast { source } => { + let arg = self.recurse_build(source)?; + self.nodes.push(Node::Cast(abstract_const::CastKind::As, arg, node.ty)) + } + + // FIXME(generic_const_exprs): We may want to support these. + ExprKind::AddressOf { .. } + | ExprKind::Borrow { .. } + | ExprKind::Deref { .. } => self.maybe_supported_error( + node.span, + "dereferencing is not supported in generic constants", + )?, + ExprKind::Repeat { .. } | ExprKind::Array { .. } => self.maybe_supported_error( + node.span, + "array construction is not supported in generic constants", + )?, + ExprKind::Block { .. } => self.maybe_supported_error( + node.span, + "blocks are not supported in generic constant", + )?, + ExprKind::NeverToAny { .. } => self.maybe_supported_error( + node.span, + "converting nevers to any is not supported in generic constant", + )?, + ExprKind::Tuple { .. } => self.maybe_supported_error( + node.span, + "tuple construction is not supported in generic constants", + )?, + ExprKind::Index { .. } => self.maybe_supported_error( + node.span, + "indexing is not supported in generic constant", + )?, + ExprKind::Field { .. } => self.maybe_supported_error( + node.span, + "field access is not supported in generic constant", + )?, + ExprKind::ConstBlock { .. } => self.maybe_supported_error( + node.span, + "const blocks are not supported in generic constant", + )?, + ExprKind::Adt(_) => self.maybe_supported_error( + node.span, + "struct/enum construction is not supported in generic constants", + )?, + // dont know if this is correct + ExprKind::Pointer { .. } => + self.error(node.span, "pointer casts are not allowed in generic constants")?, + ExprKind::Yield { .. } => + self.error(node.span, "generator control flow is not allowed in generic constants")?, + ExprKind::Continue { .. } | ExprKind::Break { .. } | ExprKind::Loop { .. } => self + .error( + node.span, + "loops and loop control flow are not supported in generic constants", + )?, + ExprKind::Box { .. } => + self.error(node.span, "allocations are not allowed in generic constants")?, + + ExprKind::Unary { .. } => unreachable!(), + // we handle valid unary/binary ops above + ExprKind::Binary { .. } => + self.error(node.span, "unsupported binary operation in generic constants")?, + ExprKind::LogicalOp { .. } => + self.error(node.span, "unsupported operation in generic constants, short-circuiting operations would imply control flow")?, + ExprKind::Assign { .. } | ExprKind::AssignOp { .. } => { + self.error(node.span, "assignment is not supported in generic constants")? + } + ExprKind::Closure { .. } | ExprKind::Return { .. } => self.error( + node.span, + "closures and function keywords are not supported in generic constants", + )?, + // let expressions imply control flow + ExprKind::Match { .. } | ExprKind::If { .. } | ExprKind::Let { .. } => + self.error(node.span, "control flow is not supported in generic constants")?, + ExprKind::LlvmInlineAsm { .. } | ExprKind::InlineAsm { .. } => { + self.error(node.span, "assembly is not supported in generic constants")? + } + + // we dont permit let stmts so `VarRef` and `UpvarRef` cant happen + ExprKind::VarRef { .. } + | ExprKind::UpvarRef { .. } + | ExprKind::StaticRef { .. } + | ExprKind::ThreadLocalRef(_) => { + self.error(node.span, "unsupported operation in generic constant")? + } + }) } } /// Builds an abstract const, do not use this directly, but use `AbstractConst::new` instead. -pub(super) fn mir_abstract_const<'tcx>( +pub(super) fn thir_abstract_const<'tcx>( tcx: TyCtxt<'tcx>, def: ty::WithOptConstParam, -) -> Result]>, ErrorReported> { +) -> Result]>, ErrorReported> { if tcx.features().generic_const_exprs { match tcx.def_kind(def.did) { // FIXME(generic_const_exprs): We currently only do this for anonymous constants, @@ -547,8 +494,16 @@ pub(super) fn mir_abstract_const<'tcx>( DefKind::AnonConst => (), _ => return Ok(None), } - let body = tcx.mir_const(def).borrow(); - AbstractConstBuilder::new(tcx, &body)?.map(AbstractConstBuilder::build).transpose() + + let body = tcx.thir_body(def); + if body.0.borrow().exprs.is_empty() { + // type error in constant, there is no thir + return Err(ErrorReported); + } + + AbstractConstBuilder::new(tcx, (&*body.0.borrow(), body.1))? + .map(AbstractConstBuilder::build) + .transpose() } else { Ok(None) } @@ -682,11 +637,16 @@ pub(super) fn try_unify<'tcx>( && iter::zip(a_args, b_args) .all(|(&an, &bn)| try_unify(tcx, a.subtree(an), b.subtree(bn))) } - (Node::Cast(a_cast_kind, a_operand, a_ty), Node::Cast(b_cast_kind, b_operand, b_ty)) - if (a_ty == b_ty) && (a_cast_kind == b_cast_kind) => + (Node::Cast(a_kind, a_operand, a_ty), Node::Cast(b_kind, b_operand, b_ty)) + if (a_ty == b_ty) && (a_kind == b_kind) => { try_unify(tcx, a.subtree(a_operand), b.subtree(b_operand)) } - _ => false, + // use this over `_ => false` to make adding variants to `Node` less error prone + (Node::Cast(..), _) + | (Node::FunctionCall(..), _) + | (Node::UnaryOp(..), _) + | (Node::Binop(..), _) + | (Node::Leaf(..), _) => 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 9ce6c58a0f..225ff5e597 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -19,7 +19,7 @@ use rustc_hir::intravisit::Visitor; use rustc_hir::GenericParam; use rustc_hir::Item; use rustc_hir::Node; -use rustc_middle::mir::abstract_const::NotConstEvaluatable; +use rustc_middle::thir::abstract_const::NotConstEvaluatable; use rustc_middle::ty::error::ExpectedFound; use rustc_middle::ty::fold::TypeFolder; use rustc_middle::ty::{ @@ -66,7 +66,6 @@ pub trait InferCtxtExt<'tcx> { root_obligation: &PredicateObligation<'tcx>, error: &SelectionError<'tcx>, fallback_has_occurred: bool, - points_at_arg: bool, ); /// Given some node representing a fn-like thing in the HIR map, @@ -237,7 +236,6 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { root_obligation: &PredicateObligation<'tcx>, error: &SelectionError<'tcx>, fallback_has_occurred: bool, - points_at_arg: bool, ) { let tcx = self.tcx; let mut span = obligation.cause.span; @@ -249,10 +247,10 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { if let ObligationCauseCode::WellFormed(Some(wf_loc)) = root_obligation.cause.code.peel_derives() { - if let Some(cause) = self.tcx.diagnostic_hir_wf_check(( - tcx.erase_regions(obligation.predicate), - wf_loc.clone(), - )) { + if let Some(cause) = self + .tcx + .diagnostic_hir_wf_check((tcx.erase_regions(obligation.predicate), *wf_loc)) + { obligation.cause = cause; span = obligation.cause.span; } @@ -387,7 +385,6 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { &obligation, &mut err, &trait_ref, - points_at_arg, have_alt_message, ) { self.note_obligation_cause(&mut err, &obligation); @@ -430,8 +427,8 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { err.span_label(enclosing_scope_span, s.as_str()); } - self.suggest_dereferences(&obligation, &mut err, trait_ref, points_at_arg); - self.suggest_fn_call(&obligation, &mut err, trait_ref, points_at_arg); + self.suggest_dereferences(&obligation, &mut err, trait_ref); + self.suggest_fn_call(&obligation, &mut err, trait_ref); self.suggest_remove_reference(&obligation, &mut err, trait_ref); self.suggest_semicolon_removal(&obligation, &mut err, span, trait_ref); self.note_version_mismatch(&mut err, &trait_ref); @@ -500,12 +497,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { // Changing mutability doesn't make a difference to whether we have // an `Unsize` impl (Fixes ICE in #71036) if !is_unsize { - self.suggest_change_mut( - &obligation, - &mut err, - trait_ref, - points_at_arg, - ); + self.suggest_change_mut(&obligation, &mut err, trait_ref); } // If this error is due to `!: Trait` not implemented but `(): Trait` is @@ -524,12 +516,12 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { }); let unit_obligation = obligation.with(predicate.to_predicate(tcx)); if self.predicate_may_hold(&unit_obligation) { - err.note("this trait is implemented for `()`."); + err.note("this trait is implemented for `()`"); err.note( "this error might have been caused by changes to \ Rust's type-inference algorithm (see issue #48950 \ \ - for more information).", + for more information)", ); err.help("did you intend to use the type `()` here instead?"); } @@ -541,9 +533,9 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { // example). let trait_is_debug = - self.tcx.is_diagnostic_item(sym::debug_trait, trait_ref.def_id()); + self.tcx.is_diagnostic_item(sym::Debug, trait_ref.def_id()); let trait_is_display = - self.tcx.is_diagnostic_item(sym::display_trait, trait_ref.def_id()); + self.tcx.is_diagnostic_item(sym::Display, trait_ref.def_id()); let in_std_macro = match obligation.cause.span.ctxt().outer_expn_data().macro_def_id { @@ -730,7 +722,10 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { }; let found_did = match *found_trait_ty.kind() { - ty::Closure(did, _) | ty::Foreign(did) | ty::FnDef(did, _) => Some(did), + ty::Closure(did, _) + | ty::Foreign(did) + | ty::FnDef(did, _) + | ty::Generator(did, ..) => Some(did), ty::Adt(def, _) => Some(def.did), _ => None, }; @@ -847,6 +842,9 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { Overflow => { bug!("overflow should be handled before the `report_selection_error` path"); } + SelectionError::ErrorReporting => { + bug!("ErrorReporting Overflow should not reach `report_selection_err` call") + } }; self.note_obligation_cause(&mut err, &obligation); @@ -1200,13 +1198,13 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> { false } + #[instrument(skip(self), level = "debug")] fn report_fulfillment_error( &self, error: &FulfillmentError<'tcx>, body_id: Option, fallback_has_occurred: bool, ) { - debug!("report_fulfillment_error({:?})", error); match error.code { FulfillmentErrorCode::CodeSelectionError(ref selection_error) => { self.report_selection_error( @@ -1214,7 +1212,6 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> { &error.root_obligation, selection_error, fallback_has_occurred, - error.points_at_arg_span, ); } FulfillmentErrorCode::CodeProjectionError(ref e) => { @@ -1534,6 +1531,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> { ) } + #[instrument(skip(self), level = "debug")] fn maybe_report_ambiguity( &self, obligation: &PredicateObligation<'tcx>, @@ -1548,8 +1546,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> { let span = obligation.cause.span; debug!( - "maybe_report_ambiguity(predicate={:?}, obligation={:?} body_id={:?}, code={:?})", - predicate, obligation, body_id, obligation.cause.code, + ?predicate, ?obligation.cause.code, ); // Ambiguity errors are often caused as fallout from earlier @@ -1562,7 +1559,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> { let mut err = match bound_predicate.skip_binder() { ty::PredicateKind::Trait(data) => { let trait_ref = bound_predicate.rebind(data.trait_ref); - debug!("trait_ref {:?}", trait_ref); + debug!(?trait_ref); if predicate.references_error() { return; diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs index 3a32f1cb90..6128c119b6 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs @@ -154,9 +154,6 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { flags.push((sym::from_method, Some(method.to_string()))); } } - if let Some((t, _)) = self.get_parent_trait_ref(&obligation.cause.code) { - flags.push((sym::parent_trait, Some(t))); - } if let Some(k) = obligation.cause.span.desugaring_kind() { flags.push((sym::from_desugaring, None)); 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 db3432b014..1a8f863952 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -9,7 +9,10 @@ use crate::traits::normalize_projection_type; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::stack::ensure_sufficient_stack; -use rustc_errors::{error_code, struct_span_err, Applicability, DiagnosticBuilder, Style}; +use rustc_data_structures::sync::Lrc; +use rustc_errors::{ + error_code, pluralize, struct_span_err, Applicability, DiagnosticBuilder, Style, +}; use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; @@ -21,9 +24,10 @@ use rustc_middle::ty::{ Infer, InferTy, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness, }; 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, MultiSpan, Span, DUMMY_SP}; +use rustc_span::{BytePos, DesugaringKind, ExpnKind, ForLoopLoc, MultiSpan, Span, DUMMY_SP}; use rustc_target::spec::abi; use std::fmt; @@ -54,7 +58,6 @@ pub trait InferCtxtExt<'tcx> { obligation: &PredicateObligation<'tcx>, err: &mut DiagnosticBuilder<'tcx>, trait_ref: ty::PolyTraitRef<'tcx>, - points_at_arg: bool, ); fn get_closure_name( @@ -69,7 +72,6 @@ pub trait InferCtxtExt<'tcx> { obligation: &PredicateObligation<'tcx>, err: &mut DiagnosticBuilder<'_>, trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, - points_at_arg: bool, ); fn suggest_add_reference_to_arg( @@ -77,7 +79,6 @@ pub trait InferCtxtExt<'tcx> { obligation: &PredicateObligation<'tcx>, err: &mut DiagnosticBuilder<'_>, trait_ref: &ty::Binder<'tcx, ty::TraitRef<'tcx>>, - points_at_arg: bool, has_custom_message: bool, ) -> bool; @@ -93,7 +94,6 @@ pub trait InferCtxtExt<'tcx> { obligation: &PredicateObligation<'tcx>, err: &mut DiagnosticBuilder<'_>, trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, - points_at_arg: bool, ); fn suggest_semicolon_removal( @@ -490,16 +490,19 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { obligation: &PredicateObligation<'tcx>, err: &mut DiagnosticBuilder<'tcx>, trait_ref: ty::PolyTraitRef<'tcx>, - points_at_arg: bool, ) { // It only make sense when suggesting dereferences for arguments - if !points_at_arg { + let code = if let ObligationCauseCode::FunctionArgumentObligation { parent_code, .. } = + &obligation.cause.code + { + parent_code.clone() + } else { return; - } + }; let param_env = obligation.param_env; let body_id = obligation.cause.body_id; let span = obligation.cause.span; - let real_trait_ref = match &obligation.cause.code { + let real_trait_ref = match &*code { ObligationCauseCode::ImplDerivedObligation(cause) | ObligationCauseCode::DerivedObligation(cause) | ObligationCauseCode::BuiltinDerivedObligation(cause) => cause.parent_trait_ref, @@ -584,7 +587,6 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { obligation: &PredicateObligation<'tcx>, err: &mut DiagnosticBuilder<'_>, trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, - points_at_arg: bool, ) { let self_ty = match trait_ref.self_ty().no_bound_vars() { None => return, @@ -656,11 +658,11 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { } _ => return, }; - if points_at_arg { + if matches!(obligation.cause.code, ObligationCauseCode::FunctionArgumentObligation { .. }) { // When the obligation error has been ensured to have been caused by // an argument, the `obligation.cause.span` points at the expression - // of the argument, so we can provide a suggestion. This is signaled - // by `points_at_arg`. Otherwise, we give a more general note. + // of the argument, so we can provide a suggestion. Otherwise, we give + // a more general note. err.span_suggestion_verbose( obligation.cause.span.shrink_to_hi(), &msg, @@ -676,13 +678,22 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { &self, obligation: &PredicateObligation<'tcx>, err: &mut DiagnosticBuilder<'_>, - trait_ref: &ty::Binder<'tcx, ty::TraitRef<'tcx>>, - points_at_arg: bool, + poly_trait_ref: &ty::Binder<'tcx, ty::TraitRef<'tcx>>, has_custom_message: bool, ) -> bool { - if !points_at_arg { + let span = obligation.cause.span; + + let code = if let ObligationCauseCode::FunctionArgumentObligation { parent_code, .. } = + &obligation.cause.code + { + parent_code.clone() + } else if let ExpnKind::Desugaring(DesugaringKind::ForLoop(ForLoopLoc::IntoIter)) = + span.ctxt().outer_expn_data().kind + { + Lrc::new(obligation.cause.code.clone()) + } else { return false; - } + }; // List of traits for which it would be nonsensical to suggest borrowing. // For instance, immutable references are always Copy, so suggesting to @@ -693,11 +704,12 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { .filter_map(|lang_item| self.tcx.lang_items().require(*lang_item).ok()) .collect(); - never_suggest_borrow.push(self.tcx.get_diagnostic_item(sym::send_trait).unwrap()); + if let Some(def_id) = self.tcx.get_diagnostic_item(sym::Send) { + never_suggest_borrow.push(def_id); + } - let span = obligation.cause.span; let param_env = obligation.param_env; - let trait_ref = trait_ref.skip_binder(); + let trait_ref = poly_trait_ref.skip_binder(); let found_ty = trait_ref.self_ty(); let found_ty_str = found_ty.to_string(); @@ -707,22 +719,28 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { 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_trait_ref: ty::TraitRef<'tcx>, - expected_trait_ref: ty::TraitRef<'tcx>, - mtbl: bool, + 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>>, blacklist: &[DefId]| -> bool { - if blacklist.contains(&expected_trait_ref.def_id) { + if blacklist.contains(&expected_trait_ref.def_id()) { return false; } - let new_obligation = Obligation::new( + let imm_result = self.predicate_must_hold_modulo_regions(&Obligation::new( ObligationCause::dummy(), param_env, - new_trait_ref.without_const().to_predicate(self.tcx), - ); + new_imm_trait_ref.without_const().to_predicate(self.tcx), + )); - if self.predicate_must_hold_modulo_regions(&new_obligation) { + 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), + )); + + if imm_result || mut_result { if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) { // We have a very specific type of error, where just borrowing this argument // might solve the problem. In cases like this, the important part is the @@ -754,7 +772,11 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { ); // This if is to prevent a special edge-case - if !span.from_expansion() { + if matches!( + span.ctxt().outer_expn_data().kind, + ExpnKind::Root + | ExpnKind::Desugaring(DesugaringKind::ForLoop(ForLoopLoc::IntoIter)) + ) { // We don't want a borrowing suggestion on the fields in structs, // ``` // struct Foo { @@ -762,15 +784,24 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { // } // ``` - err.span_suggestion( - span, - &format!( - "consider{} borrowing here", - if mtbl { " mutably" } else { "" } - ), - format!("&{}{}", if mtbl { "mut " } else { "" }, snippet), - Applicability::MaybeIncorrect, - ); + if imm_result && mut_result { + err.span_suggestions( + span.shrink_to_lo(), + "consider borrowing here", + ["&".to_string(), "&mut ".to_string()].into_iter(), + Applicability::MaybeIncorrect, + ); + } else { + err.span_suggestion_verbose( + span.shrink_to_lo(), + &format!( + "consider{} borrowing here", + if mut_result { " mutably" } else { "" } + ), + format!("&{}", if mut_result { "mut " } else { "" }), + Applicability::MaybeIncorrect, + ); + } } return true; } @@ -778,35 +809,22 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { return false; }; - if let ObligationCauseCode::ImplDerivedObligation(obligation) = &obligation.cause.code { - let expected_trait_ref = obligation.parent_trait_ref.skip_binder(); - let new_imm_trait_ref = - ty::TraitRef::new(obligation.parent_trait_ref.def_id(), imm_substs); - let new_mut_trait_ref = - ty::TraitRef::new(obligation.parent_trait_ref.def_id(), mut_substs); - if try_borrowing(new_imm_trait_ref, expected_trait_ref, false, &[]) { - return true; - } else { - return try_borrowing(new_mut_trait_ref, expected_trait_ref, true, &[]); - } + 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, &[]); } else if let ObligationCauseCode::BindingObligation(_, _) - | ObligationCauseCode::ItemObligation(_) = &obligation.cause.code + | ObligationCauseCode::ItemObligation(_) = &*code { - if try_borrowing( - ty::TraitRef::new(trait_ref.def_id, imm_substs), - trait_ref, - false, + 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[..], - ) { - return true; - } else { - return try_borrowing( - ty::TraitRef::new(trait_ref.def_id, mut_substs), - trait_ref, - true, - &never_suggest_borrow[..], - ); - } + ); } else { false } @@ -882,8 +900,12 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { obligation: &PredicateObligation<'tcx>, err: &mut DiagnosticBuilder<'_>, trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, - points_at_arg: bool, ) { + let points_at_arg = matches!( + obligation.cause.code, + ObligationCauseCode::FunctionArgumentObligation { .. }, + ); + let span = obligation.cause.span; if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) { let refs_number = @@ -1241,33 +1263,40 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { trait_ref: ty::PolyTraitRef<'tcx>, ) -> String { let inputs = trait_ref.skip_binder().substs.type_at(1); - let sig = if let ty::Tuple(inputs) = inputs.kind() { - tcx.mk_fn_sig( - inputs.iter().map(|k| k.expect_ty()), - tcx.mk_ty_infer(ty::TyVar(ty::TyVid { index: 0 })), - false, - hir::Unsafety::Normal, - abi::Abi::Rust, - ) - } else { - tcx.mk_fn_sig( + let sig = match inputs.kind() { + ty::Tuple(inputs) + if tcx.fn_trait_kind_from_lang_item(trait_ref.def_id()).is_some() => + { + tcx.mk_fn_sig( + inputs.iter().map(|k| k.expect_ty()), + tcx.mk_ty_infer(ty::TyVar(ty::TyVid::from_u32(0))), + false, + hir::Unsafety::Normal, + abi::Abi::Rust, + ) + } + _ => tcx.mk_fn_sig( std::iter::once(inputs), - tcx.mk_ty_infer(ty::TyVar(ty::TyVid { index: 0 })), + tcx.mk_ty_infer(ty::TyVar(ty::TyVid::from_u32(0))), false, hir::Unsafety::Normal, abi::Abi::Rust, - ) + ), }; trait_ref.rebind(sig).to_string() } - let argument_is_closure = expected_ref.skip_binder().substs.type_at(0).is_closure(); + let argument_kind = match expected_ref.skip_binder().substs.type_at(0) { + t if t.is_closure() => "closure", + t if t.is_generator() => "generator", + _ => "function", + }; let mut err = struct_span_err!( self.tcx.sess, span, E0631, "type mismatch in {} arguments", - if argument_is_closure { "closure" } else { "function" } + argument_kind ); let found_str = format!("expected signature of `{}`", build_fn_sig_string(self.tcx, found)); @@ -1609,12 +1638,12 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { // Special case the primary error message when send or sync is the trait that was // not implemented. - let is_send = self.tcx.is_diagnostic_item(sym::send_trait, trait_ref.def_id); - let is_sync = self.tcx.is_diagnostic_item(sym::sync_trait, trait_ref.def_id); let hir = self.tcx.hir(); - let trait_explanation = if is_send || is_sync { + let trait_explanation = if let Some(name @ (sym::Send | sym::Sync)) = + self.tcx.get_diagnostic_name(trait_ref.def_id) + { let (trait_name, trait_verb) = - if is_send { ("`Send`", "sent") } else { ("`Sync`", "shared") }; + if name == sym::Send { ("`Send`", "sent") } else { ("`Sync`", "shared") }; err.clear_code(); err.set_primary_message(format!( @@ -2248,7 +2277,11 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { parent_trait_ref = child_trait_ref; } if count > 0 { - err.note(&format!("{} redundant requirements hidden", count)); + err.note(&format!( + "{} redundant requirement{} hidden", + count, + pluralize!(count) + )); err.note(&format!( "required because of the requirements on the impl of `{}` for `{}`", parent_trait_ref.print_only_trait_path(), @@ -2280,6 +2313,56 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { ) }); } + ObligationCauseCode::FunctionArgumentObligation { + arg_hir_id, + call_hir_id, + ref parent_code, + } => { + let hir = self.tcx.hir(); + if let Some(Node::Expr(expr @ hir::Expr { kind: hir::ExprKind::Block(..), .. })) = + hir.find(arg_hir_id) + { + let in_progress_typeck_results = + self.in_progress_typeck_results.map(|t| t.borrow()); + let parent_id = hir.local_def_id(hir.get_parent_item(arg_hir_id)); + let typeck_results: &TypeckResults<'tcx> = match &in_progress_typeck_results { + Some(t) if t.hir_owner == parent_id => t, + _ => self.tcx.typeck(parent_id), + }; + let ty = typeck_results.expr_ty_adjusted(expr); + let span = expr.peel_blocks().span; + if Some(span) != err.span.primary_span() { + err.span_label( + span, + &if ty.references_error() { + String::new() + } else { + format!("this tail expression is of type `{:?}`", ty) + }, + ); + } + } + if let Some(Node::Expr(hir::Expr { + kind: + hir::ExprKind::Call(hir::Expr { span, .. }, _) + | hir::ExprKind::MethodCall(_, span, ..), + .. + })) = hir.find(call_hir_id) + { + if Some(*span) != err.span.primary_span() { + err.span_label(*span, "required by a bound introduced by this call"); + } + } + ensure_sufficient_stack(|| { + self.note_obligation_cause_code( + err, + predicate, + &parent_code, + obligated_types, + seen_requirements, + ) + }); + } ObligationCauseCode::CompareImplMethodObligation { item_name, trait_item_def_id, @@ -2352,10 +2435,13 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { } fn suggest_new_overflow_limit(&self, err: &mut DiagnosticBuilder<'_>) { - let current_limit = self.tcx.recursion_limit(); - let suggested_limit = current_limit * 2; + let suggested_limit = match self.tcx.recursion_limit() { + Limit(0) => Limit(2), + limit => limit * 2, + }; err.help(&format!( - "consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate (`{}`)", + "consider increasing the recursion limit by adding a \ + `#![recursion_limit = \"{}\"]` attribute to your crate (`{}`)", suggested_limit, self.tcx.crate_name(LOCAL_CRATE), )); diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index 18abcc72bc..465d1465d5 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -1,12 +1,13 @@ use crate::infer::{InferCtxt, TyOrConstInferVar}; +use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::obligation_forest::ProcessResult; use rustc_data_structures::obligation_forest::{Error, ForestObligation, Outcome}; use rustc_data_structures::obligation_forest::{ObligationForest, ObligationProcessor}; use rustc_errors::ErrorReported; use rustc_hir as hir; use rustc_infer::traits::{SelectionError, TraitEngine, TraitEngineExt as _, TraitObligation}; -use rustc_middle::mir::abstract_const::NotConstEvaluatable; use rustc_middle::mir::interpret::ErrorHandled; +use rustc_middle::thir::abstract_const::NotConstEvaluatable; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::subst::SubstsRef; use rustc_middle::ty::ToPredicate; @@ -53,6 +54,9 @@ pub struct FulfillmentContext<'tcx> { // A list of all obligations that have been registered with this // fulfillment context. predicates: ObligationForest>, + + relationships: FxHashMap, + // Should this fulfillment context register type-lives-for-region // obligations on its parent infcx? In some cases, region // obligations are either already known to hold (normalization) or @@ -97,6 +101,7 @@ impl<'a, 'tcx> FulfillmentContext<'tcx> { pub fn new() -> FulfillmentContext<'tcx> { FulfillmentContext { predicates: ObligationForest::new(), + relationships: FxHashMap::default(), register_region_obligations: true, usable_in_snapshot: false, } @@ -105,6 +110,7 @@ impl<'a, 'tcx> FulfillmentContext<'tcx> { pub fn new_in_snapshot() -> FulfillmentContext<'tcx> { FulfillmentContext { predicates: ObligationForest::new(), + relationships: FxHashMap::default(), register_region_obligations: true, usable_in_snapshot: true, } @@ -113,6 +119,7 @@ impl<'a, 'tcx> FulfillmentContext<'tcx> { pub fn new_ignoring_regions() -> FulfillmentContext<'tcx> { FulfillmentContext { predicates: ObligationForest::new(), + relationships: FxHashMap::default(), register_region_obligations: false, usable_in_snapshot: false, } @@ -210,6 +217,8 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> { assert!(!infcx.is_in_snapshot() || self.usable_in_snapshot); + super::relationships::update(self, infcx, &obligation); + self.predicates .register_obligation(PendingPredicateObligation { obligation, stalled_on: vec![] }); } @@ -265,6 +274,10 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> { fn pending_obligations(&self) -> Vec> { self.predicates.map_pending_obligations(|o| o.obligation.clone()) } + + fn relationships(&mut self) -> &mut FxHashMap { + &mut self.relationships + } } struct FulfillProcessor<'a, 'b, 'tcx> { @@ -405,7 +418,8 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> { | ty::PredicateKind::Coerce(_) | ty::PredicateKind::ConstEvaluatable(..) | ty::PredicateKind::ConstEquate(..) => { - let pred = infcx.replace_bound_vars_with_placeholders(binder); + let pred = + ty::Binder::dummy(infcx.replace_bound_vars_with_placeholders(binder)); ProcessResult::Changed(mk_pending(vec![ obligation.with(pred.to_predicate(self.selcx.tcx())), ])) diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index 17a4184c3c..b31d6d68b0 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -15,6 +15,7 @@ mod object_safety; mod on_unimplemented; mod project; pub mod query; +pub(crate) mod relationships; mod select; mod specialize; mod structural_match; @@ -63,7 +64,9 @@ pub use self::specialize::specialization_graph::FutureCompatOverlapErrorKind; 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_predicates, elaborate_trait_ref, elaborate_trait_refs}; +pub use self::util::{ + elaborate_obligations, elaborate_predicates, elaborate_trait_ref, elaborate_trait_refs, +}; pub use self::util::{expand_trait_aliases, TraitAliasExpander}; pub use self::util::{ get_vtable_index_of_object_method, impl_item_is_final, predicate_for_trait_def, upcast_choices, @@ -139,7 +142,8 @@ pub fn type_known_to_meet_bound_modulo_regions<'a, 'tcx>( infcx.tcx.def_path_str(def_id) ); - let trait_ref = ty::TraitRef { def_id, substs: infcx.tcx.mk_substs_trait(ty, &[]) }; + let trait_ref = + ty::Binder::dummy(ty::TraitRef { def_id, substs: infcx.tcx.mk_substs_trait(ty, &[]) }); let obligation = Obligation { param_env, cause: ObligationCause::misc(span, hir::CRATE_HIR_ID), @@ -621,10 +625,35 @@ fn dump_vtable_entries<'tcx>( trait_ref: ty::PolyTraitRef<'tcx>, entries: &[VtblEntry<'tcx>], ) { - let msg = format!("Vtable entries for `{}`: {:#?}", trait_ref, entries); + let msg = format!("vtable entries for `{}`: {:#?}", trait_ref, entries); tcx.sess.struct_span_err(sp, &msg).emit(); } +fn own_existential_vtable_entries<'tcx>( + tcx: TyCtxt<'tcx>, + trait_ref: ty::PolyExistentialTraitRef<'tcx>, +) -> &'tcx [DefId] { + let trait_methods = tcx + .associated_items(trait_ref.def_id()) + .in_definition_order() + .filter(|item| item.kind == ty::AssocKind::Fn); + // Now list each method's DefId (for within its trait). + let own_entries = trait_methods.filter_map(move |trait_method| { + debug!("own_existential_vtable_entry: trait_method={:?}", trait_method); + let def_id = trait_method.def_id; + + // Some methods cannot be called on an object; skip those. + if !is_vtable_safe_method(tcx, trait_ref.def_id(), &trait_method) { + debug!("own_existential_vtable_entry: not vtable safe"); + return None; + } + + Some(def_id) + }); + + tcx.arena.alloc_from_iter(own_entries.into_iter()) +} + /// Given a trait `trait_ref`, iterates the vtable entries /// that come from `trait_ref`, including its supertraits. fn vtable_entries<'tcx>( @@ -641,21 +670,15 @@ fn vtable_entries<'tcx>( entries.extend(COMMON_VTABLE_ENTRIES); } VtblSegment::TraitOwnEntries { trait_ref, emit_vptr } => { - let trait_methods = tcx - .associated_items(trait_ref.def_id()) - .in_definition_order() - .filter(|item| item.kind == ty::AssocKind::Fn); - // Now list each method's DefId and InternalSubsts (for within its trait). - // If the method can never be called from this object, produce `Vacant`. - let own_entries = trait_methods.map(move |trait_method| { - debug!("vtable_entries: trait_method={:?}", trait_method); - let def_id = trait_method.def_id; + let existential_trait_ref = trait_ref + .map_bound(|trait_ref| ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref)); - // Some methods cannot be called on an object; skip those. - if !is_vtable_safe_method(tcx, trait_ref.def_id(), &trait_method) { - debug!("vtable_entries: not vtable safe"); - return VtblEntry::Vacant; - } + // Lookup the shape of vtable for the trait. + let own_existential_entries = + tcx.own_existential_vtable_entries(existential_trait_ref); + + let own_entries = own_existential_entries.iter().copied().map(|def_id| { + debug!("vtable_entries: trait_method={:?}", def_id); // The method may have some early-bound lifetimes; add regions for those. let substs = trait_ref.map_bound(|trait_ref| { @@ -804,19 +827,20 @@ pub fn provide(providers: &mut ty::query::Providers) { specialization_graph_of: specialize::specialization_graph_provider, specializes: specialize::specializes, codegen_fulfill_obligation: codegen::codegen_fulfill_obligation, + own_existential_vtable_entries, vtable_entries, vtable_trait_upcasting_coercion_new_vptr_slot, subst_and_check_impossible_predicates, - mir_abstract_const: |tcx, def_id| { + thir_abstract_const: |tcx, def_id| { let def_id = def_id.expect_local(); if let Some(def) = ty::WithOptConstParam::try_lookup(def_id, tcx) { - tcx.mir_abstract_const_of_const_arg(def) + tcx.thir_abstract_const_of_const_arg(def) } else { - const_evaluatable::mir_abstract_const(tcx, ty::WithOptConstParam::unknown(def_id)) + const_evaluatable::thir_abstract_const(tcx, ty::WithOptConstParam::unknown(def_id)) } }, - mir_abstract_const_of_const_arg: |tcx, (did, param_did)| { - const_evaluatable::mir_abstract_const( + thir_abstract_const_of_const_arg: |tcx, (did, param_did)| { + const_evaluatable::thir_abstract_const( tcx, ty::WithOptConstParam { did, const_param_did: Some(param_did) }, ) diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs index 57b8a84300..0bb00dfeb4 100644 --- a/compiler/rustc_trait_selection/src/traits/object_safety.rs +++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs @@ -250,7 +250,7 @@ fn predicates_reference_self( trait_def_id: DefId, supertraits_only: bool, ) -> SmallVec<[Span; 1]> { - let trait_ref = ty::Binder::dummy(ty::TraitRef::identity(tcx, trait_def_id)); + let trait_ref = ty::TraitRef::identity(tcx, trait_def_id); let predicates = if supertraits_only { tcx.super_predicates_of(trait_def_id) } else { @@ -465,9 +465,9 @@ fn virtual_call_violation_for_method<'tcx>( let param_env = tcx.param_env(method.def_id); - let abi_of_ty = |ty: Ty<'tcx>| -> Option<&Abi> { + let abi_of_ty = |ty: Ty<'tcx>| -> Option { match tcx.layout_of(param_env.and(ty)) { - Ok(layout) => Some(&layout.abi), + Ok(layout) => Some(layout.abi), Err(err) => { // #78372 tcx.sess.delay_span_bug( @@ -554,11 +554,11 @@ fn object_ty_for_trait<'tcx>( let trait_ref = ty::TraitRef::identity(tcx, trait_def_id); - let trait_predicate = ty::Binder::dummy(ty::ExistentialPredicate::Trait( - ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref), - )); + let trait_predicate = trait_ref.map_bound(|trait_ref| { + ty::ExistentialPredicate::Trait(ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref)) + }); - let mut associated_types = traits::supertraits(tcx, ty::Binder::dummy(trait_ref)) + let mut associated_types = traits::supertraits(tcx, trait_ref) .flat_map(|super_trait_ref| { tcx.associated_items(super_trait_ref.def_id()) .in_definition_order() @@ -671,10 +671,10 @@ fn receiver_is_dispatchable<'tcx>( let param_env = tcx.param_env(method.def_id); // Self: Unsize - let unsize_predicate = ty::TraitRef { + let unsize_predicate = ty::Binder::dummy(ty::TraitRef { def_id: unsize_did, substs: tcx.mk_substs_trait(tcx.types.self_param, &[unsized_self_ty.into()]), - } + }) .without_const() .to_predicate(tcx); @@ -689,7 +689,9 @@ fn receiver_is_dispatchable<'tcx>( } }); - ty::TraitRef { def_id: unsize_did, substs }.without_const().to_predicate(tcx) + ty::Binder::dummy(ty::TraitRef { def_id: unsize_did, substs }) + .without_const() + .to_predicate(tcx) }; let caller_bounds: Vec> = param_env @@ -703,10 +705,10 @@ fn receiver_is_dispatchable<'tcx>( // Receiver: DispatchFromDyn U]> let obligation = { - let predicate = ty::TraitRef { + let predicate = ty::Binder::dummy(ty::TraitRef { def_id: dispatch_from_dyn_did, substs: tcx.mk_substs_trait(receiver_ty, &[unsized_receiver_ty.into()]), - } + }) .without_const() .to_predicate(tcx); @@ -789,8 +791,7 @@ fn contains_illegal_self_type_reference<'tcx, T: TypeFoldable<'tcx>>( // Compute supertraits of current trait lazily. if self.supertraits.is_none() { - let trait_ref = - ty::Binder::dummy(ty::TraitRef::identity(self.tcx, self.trait_def_id)); + let trait_ref = ty::TraitRef::identity(self.tcx, self.trait_def_id); self.supertraits = Some( traits::supertraits(self.tcx, trait_ref).map(|t| t.def_id()).collect(), ); @@ -836,7 +837,7 @@ fn contains_illegal_self_type_reference<'tcx, T: TypeFoldable<'tcx>>( // // This shouldn't really matter though as we can't really use any // constants which are not considered const evaluatable. - use rustc_middle::mir::abstract_const::Node; + 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) => { diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 42c5afbd5d..db8a6d9620 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -27,7 +27,7 @@ use rustc_hir::lang_items::LangItem; use rustc_infer::infer::resolve::OpportunisticRegionResolver; use rustc_middle::ty::fold::{TypeFoldable, TypeFolder}; use rustc_middle::ty::subst::Subst; -use rustc_middle::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, WithConstness}; +use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, WithConstness}; use rustc_span::symbol::sym; use std::collections::BTreeMap; @@ -558,7 +558,7 @@ impl<'me, 'tcx> BoundVarReplacer<'me, 'tcx> { fn universe_for(&mut self, debruijn: ty::DebruijnIndex) -> ty::UniverseIndex { let infcx = self.infcx; let index = - self.universe_indices.len() - debruijn.as_usize() + self.current_index.as_usize() - 1; + self.universe_indices.len() + self.current_index.as_usize() - debruijn.as_usize() - 1; let universe = self.universe_indices[index].unwrap_or_else(|| { for i in self.universe_indices.iter_mut().take(index + 1) { *i = i.or_else(|| Some(infcx.create_next_universe())) @@ -595,7 +595,7 @@ impl TypeFolder<'tcx> for BoundVarReplacer<'_, 'tcx> { ty::ReLateBound(debruijn, br) if debruijn >= self.current_index => { let universe = self.universe_for(debruijn); let p = ty::PlaceholderRegion { universe, name: br.kind }; - self.mapped_regions.insert(p.clone(), br); + self.mapped_regions.insert(p, br); self.infcx.tcx.mk_region(ty::RePlaceholder(p)) } _ => r, @@ -613,7 +613,7 @@ impl TypeFolder<'tcx> for BoundVarReplacer<'_, 'tcx> { ty::Bound(debruijn, bound_ty) if debruijn >= self.current_index => { let universe = self.universe_for(debruijn); let p = ty::PlaceholderType { universe, name: bound_ty.var }; - self.mapped_types.insert(p.clone(), bound_ty); + self.mapped_types.insert(p, bound_ty); self.infcx.tcx.mk_ty(ty::Placeholder(p)) } _ if t.has_vars_bound_at_or_above(self.current_index) => t.super_fold_with(self), @@ -637,7 +637,7 @@ impl TypeFolder<'tcx> for BoundVarReplacer<'_, 'tcx> { universe, name: ty::BoundConst { var: bound_const, ty }, }; - self.mapped_consts.insert(p.clone(), bound_const); + self.mapped_consts.insert(p, bound_const); self.infcx.tcx.mk_const(ty::Const { val: ty::ConstKind::Placeholder(p), ty }) } _ if ct.has_vars_bound_at_or_above(self.current_index) => ct.super_fold_with(self), @@ -810,17 +810,7 @@ pub fn normalize_projection_type<'a, 'b, 'tcx>( // and a deferred predicate to resolve this when more type // information is available. - let tcx = selcx.infcx().tcx; - let def_id = projection_ty.item_def_id; - let ty_var = selcx.infcx().next_ty_var(TypeVariableOrigin { - kind: TypeVariableOriginKind::NormalizeProjectionType, - span: tcx.def_span(def_id), - }); - let projection = ty::Binder::dummy(ty::ProjectionPredicate { projection_ty, ty: ty_var }); - let obligation = - Obligation::with_depth(cause, depth + 1, param_env, projection.to_predicate(tcx)); - obligations.push(obligation); - ty_var + selcx.infcx().infer_projection(param_env, projection_ty, cause, depth + 1, obligations) }) } @@ -1038,7 +1028,7 @@ fn normalize_to_error<'a, 'tcx>( cause: ObligationCause<'tcx>, depth: usize, ) -> NormalizedTy<'tcx> { - let trait_ref = projection_ty.trait_ref(selcx.tcx()).to_poly_trait_ref(); + let trait_ref = ty::Binder::dummy(projection_ty.trait_ref(selcx.tcx())); let trait_obligation = Obligation { cause, recursion_depth: depth, @@ -1300,7 +1290,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( // If we are resolving `>::Item == Type`, // start out by selecting the predicate `T as TraitRef<...>`: - let poly_trait_ref = obligation.predicate.trait_ref(selcx.tcx()).to_poly_trait_ref(); + let poly_trait_ref = ty::Binder::dummy(obligation.predicate.trait_ref(selcx.tcx())); let trait_obligation = obligation.with(poly_trait_ref.to_poly_trait_predicate()); let _ = selcx.infcx().commit_if_ok(|_| { let impl_source = match selcx.select(&trait_obligation) { @@ -1495,7 +1485,8 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( } super::ImplSource::AutoImpl(..) | super::ImplSource::Builtin(..) - | super::ImplSource::TraitUpcasting(_) => { + | super::ImplSource::TraitUpcasting(_) + | super::ImplSource::ConstDrop(_) => { // These traits have no associated types. selcx.tcx().sess.delay_span_bug( obligation.cause.span, @@ -1567,7 +1558,8 @@ fn confirm_select_candidate<'cx, 'tcx>( | super::ImplSource::Param(..) | super::ImplSource::Builtin(..) | super::ImplSource::TraitUpcasting(_) - | super::ImplSource::TraitAlias(..) => { + | super::ImplSource::TraitAlias(..) + | super::ImplSource::ConstDrop(_) => { // we don't create Select candidates with this kind of resolution span_bug!( obligation.cause.span, diff --git a/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs b/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs index 032d402fec..2fa6c0c025 100644 --- a/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs +++ b/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs @@ -83,17 +83,21 @@ impl<'cx, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'cx, 'tcx> { ) -> EvaluationResult { match self.evaluate_obligation(obligation) { Ok(result) => result, - Err(OverflowError) => { + Err(OverflowError::Canonical) => { let mut selcx = SelectionContext::with_query_mode(&self, TraitQueryMode::Standard); - selcx.evaluate_root_obligation(obligation).unwrap_or_else(|r| { - span_bug!( - obligation.cause.span, - "Overflow should be caught earlier in standard query mode: {:?}, {:?}", - obligation, - r, - ) + selcx.evaluate_root_obligation(obligation).unwrap_or_else(|r| match r { + OverflowError::Canonical => { + span_bug!( + obligation.cause.span, + "Overflow should be caught earlier in standard query mode: {:?}, {:?}", + obligation, + r, + ) + } + OverflowError::ErrorReporting => EvaluationResult::EvaluatedToErr, }) } + Err(OverflowError::ErrorReporting) => EvaluationResult::EvaluatedToErr, } } } diff --git a/compiler/rustc_trait_selection/src/traits/query/mod.rs b/compiler/rustc_trait_selection/src/traits/query/mod.rs index f6f42814d3..ef34936781 100644 --- a/compiler/rustc_trait_selection/src/traits/query/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/query/mod.rs @@ -9,7 +9,6 @@ pub mod dropck_outlives; pub mod evaluate_obligation; pub mod method_autoderef; pub mod normalize; -pub mod outlives_bounds; pub mod type_op; pub use rustc_middle::traits::query::*; diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs index 03087e3353..04c382d439 100644 --- a/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs +++ b/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs @@ -1,6 +1,6 @@ use crate::infer::canonical::{Canonicalized, CanonicalizedQueryResponse}; -use crate::traits::query::outlives_bounds::OutlivesBound; use crate::traits::query::Fallible; +use rustc_infer::traits::query::OutlivesBound; use rustc_middle::ty::{ParamEnvAnd, Ty, TyCtxt}; #[derive(Copy, Clone, Debug, HashStable, TypeFoldable, Lift)] diff --git a/compiler/rustc_trait_selection/src/traits/relationships.rs b/compiler/rustc_trait_selection/src/traits/relationships.rs new file mode 100644 index 0000000000..7751dd84f4 --- /dev/null +++ b/compiler/rustc_trait_selection/src/traits/relationships.rs @@ -0,0 +1,69 @@ +use crate::infer::InferCtxt; +use crate::traits::query::evaluate_obligation::InferCtxtExt; +use crate::traits::{ObligationCause, PredicateObligation}; +use rustc_infer::traits::TraitEngine; +use rustc_middle::ty::{self, ToPredicate}; + +pub(crate) fn update<'tcx, T>( + engine: &mut T, + infcx: &InferCtxt<'_, 'tcx>, + obligation: &PredicateObligation<'tcx>, +) where + T: TraitEngine<'tcx>, +{ + // (*) binder skipped + if let ty::PredicateKind::Trait(predicate) = obligation.predicate.kind().skip_binder() { + if let Some(ty) = + infcx.shallow_resolve(predicate.self_ty()).ty_vid().map(|t| infcx.root_var(t)) + { + if infcx + .tcx + .lang_items() + .sized_trait() + .map_or(false, |st| st != predicate.trait_ref.def_id) + { + let new_self_ty = infcx.tcx.types.unit; + + let trait_ref = ty::TraitRef { + substs: infcx + .tcx + .mk_substs_trait(new_self_ty, &predicate.trait_ref.substs[1..]), + ..predicate.trait_ref + }; + + // Then contstruct a new obligation with Self = () added + // to the ParamEnv, and see if it holds. + let o = rustc_infer::traits::Obligation::new( + ObligationCause::dummy(), + obligation.param_env, + obligation + .predicate + .kind() + .map_bound(|_| { + // (*) binder moved here + ty::PredicateKind::Trait(ty::TraitPredicate { + trait_ref, + constness: predicate.constness, + }) + }) + .to_predicate(infcx.tcx), + ); + // Don't report overflow errors. Otherwise equivalent to may_hold. + if let Ok(result) = infcx.probe(|_| infcx.evaluate_obligation(&o)) { + if result.may_apply() { + engine.relationships().entry(ty).or_default().self_in_trait = true; + } + } + } + } + } + + if let ty::PredicateKind::Projection(predicate) = obligation.predicate.kind().skip_binder() { + // If the projection predicate (Foo::Bar == X) has X as a non-TyVid, + // we need to make it into one. + if let Some(vid) = predicate.ty.ty_vid() { + debug!("relationship: {:?}.output = true", vid); + engine.relationships().entry(vid).or_default().output = true; + } + } +} 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 e18828fec3..856ea43b1f 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -6,14 +6,19 @@ //! //! [rustc dev guide]:https://rustc-dev-guide.rust-lang.org/traits/resolution.html#candidate-assembly use rustc_hir as hir; +use rustc_hir::def_id::DefId; +use rustc_infer::traits::TraitEngine; use rustc_infer::traits::{Obligation, SelectionError, TraitObligation}; +use rustc_lint_defs::builtin::DEREF_INTO_DYN_SUPERTRAIT; use rustc_middle::ty::print::with_no_trimmed_paths; -use rustc_middle::ty::{self, TypeFoldable}; +use rustc_middle::ty::{self, ToPredicate, Ty, TypeFoldable, WithConstness}; use rustc_target::spec::abi::Abi; +use crate::traits; use crate::traits::coherence::Conflict; +use crate::traits::query::evaluate_obligation::InferCtxtExt; use crate::traits::{util, SelectionResult}; -use crate::traits::{Overflow, Unimplemented}; +use crate::traits::{ErrorReporting, Overflow, Unimplemented}; use super::BuiltinImplConditions; use super::IntercrateAmbiguityCause; @@ -156,7 +161,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { Ok(Some(EvaluatedCandidate { candidate: c, evaluation: eval })) } Ok(_) => Ok(None), - Err(OverflowError) => Err(Overflow), + Err(OverflowError::Canonical) => Err(Overflow), + Err(OverflowError::ErrorReporting) => Err(ErrorReporting), }) .flat_map(Result::transpose) .collect::, _>>()?; @@ -220,6 +226,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { self.filter_impls(candidates.pop().unwrap().candidate, stack.obligation) } + #[instrument(skip(self, stack), level = "debug")] pub(super) fn assemble_candidates<'o>( &mut self, stack: &TraitObligationStack<'o, 'tcx>, @@ -277,6 +284,16 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { 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 @@ -465,7 +482,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { .. } = self_ty.fn_sig(self.tcx()).skip_binder() { - candidates.vec.push(FnPointerCandidate); + candidates.vec.push(FnPointerCandidate { is_const: false }); } } // Provide an impl for suitable functions, rejecting `#[target_feature]` functions (RFC 2396). @@ -478,7 +495,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } = self_ty.fn_sig(self.tcx()).skip_binder() { if self.tcx().codegen_fn_attrs(def_id).target_features.is_empty() { - candidates.vec.push(FnPointerCandidate); + candidates + .vec + .push(FnPointerCandidate { is_const: self.tcx().is_const_fn(def_id) }); } } } @@ -659,6 +678,55 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { }) } + /// Temporary migration for #89190 + fn need_migrate_deref_output_trait_object( + &mut self, + ty: Ty<'tcx>, + cause: &traits::ObligationCause<'tcx>, + param_env: ty::ParamEnv<'tcx>, + ) -> Option<(Ty<'tcx>, DefId)> { + let tcx = self.tcx(); + if tcx.features().trait_upcasting { + return None; + } + + // + let trait_ref = ty::TraitRef { + def_id: tcx.lang_items().deref_trait()?, + substs: tcx.mk_substs_trait(ty, &[]), + }; + + let obligation = traits::Obligation::new( + cause.clone(), + param_env, + ty::Binder::dummy(trait_ref).without_const().to_predicate(tcx), + ); + if !self.infcx.predicate_may_hold(&obligation) { + return None; + } + + let mut fulfillcx = traits::FulfillmentContext::new_in_snapshot(); + let normalized_ty = fulfillcx.normalize_projection_type( + &self.infcx, + param_env, + ty::ProjectionTy { + item_def_id: tcx.lang_items().deref_target()?, + substs: trait_ref.substs, + }, + cause.clone(), + ); + + let data = if let ty::Dynamic(ref data, ..) = normalized_ty.kind() { + data + } else { + return None; + }; + + let def_id = data.principal_def_id()?; + + return Some((normalized_ty, def_id)); + } + /// Searches for unsizing that might apply to `obligation`. fn assemble_candidates_for_unsizing( &mut self, @@ -719,6 +787,30 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let principal_a = data_a.principal().unwrap(); let target_trait_did = principal_def_id_b.unwrap(); let source_trait_ref = principal_a.with_self_ty(self.tcx(), source); + if let Some((deref_output_ty, deref_output_trait_did)) = self + .need_migrate_deref_output_trait_object( + source, + &obligation.cause, + obligation.param_env, + ) + { + if deref_output_trait_did == target_trait_did { + self.tcx().struct_span_lint_hir( + DEREF_INTO_DYN_SUPERTRAIT, + obligation.cause.body_id, + obligation.cause.span, + |lint| { + lint.build(&format!( + "`{}` implements `Deref` with supertrait `{}` as output", + source, + deref_output_ty + )).emit(); + }, + ); + return; + } + } + for (idx, upcast_trait_ref) in util::supertraits(self.tcx(), source_trait_ref).enumerate() { @@ -803,4 +895,122 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } } } + + fn assemble_const_drop_candidates( + &mut self, + obligation: &TraitObligation<'tcx>, + candidates: &mut SelectionCandidateSet<'tcx>, + ) -> Result<(), SelectionError<'tcx>> { + let mut stack: Vec<(Ty<'tcx>, usize)> = vec![(obligation.self_ty().skip_binder(), 0)]; + + while let Some((ty, depth)) = stack.pop() { + let mut noreturn = false; + + self.check_recursion_depth(depth, obligation)?; + let mut copy_candidates = SelectionCandidateSet { vec: Vec::new(), ambiguous: false }; + let mut copy_obligation = + obligation.with(obligation.predicate.rebind(ty::TraitPredicate { + trait_ref: ty::TraitRef { + def_id: self.tcx().require_lang_item(hir::LangItem::Copy, None), + substs: self.tcx().mk_substs_trait(ty, &[]), + }, + constness: ty::BoundConstness::NotConst, + })); + copy_obligation.recursion_depth = depth + 1; + self.assemble_candidates_from_impls(©_obligation, &mut copy_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() { + noreturn = true; + } + debug!(?copy_candidates.vec, "assemble_const_drop_candidates - copy"); + + match ty.kind() { + ty::Int(_) + | ty::Uint(_) + | ty::Float(_) + | ty::Infer(ty::IntVar(_)) + | ty::Infer(ty::FloatVar(_)) + | ty::FnPtr(_) + | ty::Never + | ty::Ref(..) + | ty::FnDef(..) + | ty::RawPtr(_) + | ty::Bool + | ty::Char + | ty::Str + | ty::Foreign(_) => {} // Do nothing. These types satisfy `const Drop`. + + ty::Adt(def, subst) => { + let mut set = SelectionCandidateSet { vec: Vec::new(), ambiguous: false }; + self.assemble_candidates_from_impls( + &obligation.with(obligation.predicate.map_bound(|mut pred| { + pred.trait_ref.substs = self.tcx().mk_substs_trait(ty, &[]); + pred + })), + &mut set, + ); + stack.extend(def.all_fields().map(|f| (f.ty(self.tcx(), subst), depth + 1))); + + debug!(?set.vec, "assemble_const_drop_candidates - ty::Adt"); + if set.vec.into_iter().any(|candidate| { + if let SelectionCandidate::ImplCandidate(did) = candidate { + matches!(self.tcx().impl_constness(did), hir::Constness::NotConst) + } else { + false + } + }) { + if !noreturn { + // has non-const Drop + return Ok(()); + } + debug!("not returning"); + } + } + + ty::Array(ty, _) => stack.push((ty, depth + 1)), + + ty::Tuple(_) => stack.extend(ty.tuple_fields().map(|t| (t, depth + 1))), + + ty::Closure(_, substs) => { + let substs = substs.as_closure(); + let ty = self.infcx.shallow_resolve(substs.tupled_upvars_ty()); + stack.push((ty, depth + 1)); + } + + ty::Generator(_, substs, _) => { + let substs = substs.as_generator(); + let ty = self.infcx.shallow_resolve(substs.tupled_upvars_ty()); + + stack.push((ty, depth + 1)); + stack.push((substs.witness(), depth + 1)); + } + + ty::GeneratorWitness(tys) => stack.extend( + self.tcx().erase_late_bound_regions(*tys).iter().map(|t| (t, depth + 1)), + ), + + ty::Slice(ty) => stack.push((ty, depth + 1)), + + ty::Opaque(..) + | ty::Dynamic(..) + | ty::Error(_) + | ty::Bound(..) + | ty::Infer(_) + | ty::Placeholder(_) + | ty::Projection(..) + | ty::Param(..) => { + if !noreturn { + return Ok(()); + } + debug!("not returning"); + } + } + debug!(?stack, "assemble_const_drop_candidates - in loop"); + } + // all types have passed. + candidates.vec.push(ConstDropCandidate); + + Ok(()) + } } diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 6fae817398..a36cb1358b 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -28,7 +28,7 @@ use crate::traits::TraitNotObjectSafe; use crate::traits::VtblSegment; use crate::traits::{BuiltinDerivedObligation, ImplDerivedObligation}; use crate::traits::{ - ImplSourceAutoImplData, ImplSourceBuiltinData, ImplSourceClosureData, + ImplSourceAutoImplData, ImplSourceBuiltinData, ImplSourceClosureData, ImplSourceConstDropData, ImplSourceDiscriminantKindData, ImplSourceFnPointerData, ImplSourceGeneratorData, ImplSourceObjectData, ImplSourcePointeeData, ImplSourceTraitAliasData, ImplSourceTraitUpcastingData, ImplSourceUserDefinedData, @@ -92,7 +92,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { Ok(ImplSource::Generator(vtable_generator)) } - FnPointerCandidate => { + FnPointerCandidate { .. } => { let data = self.confirm_fn_pointer_candidate(obligation)?; Ok(ImplSource::FnPointer(data)) } @@ -124,6 +124,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let data = self.confirm_trait_upcasting_unsize_candidate(obligation, idx)?; Ok(ImplSource::TraitUpcasting(data)) } + + ConstDropCandidate => Ok(ImplSource::ConstDrop(ImplSourceConstDropData)), } } @@ -139,6 +141,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let placeholder_trait_predicate = self.infcx().replace_bound_vars_with_placeholders(trait_predicate); let placeholder_self_ty = placeholder_trait_predicate.self_ty(); + let placeholder_trait_predicate = ty::Binder::dummy(placeholder_trait_predicate); let (def_id, substs) = match *placeholder_self_ty.kind() { ty::Projection(proj) => (proj.item_def_id, proj.substs), ty::Opaque(def_id, substs) => (def_id, substs), @@ -162,7 +165,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligations.extend(self.infcx.commit_if_ok(|_| { self.infcx .at(&obligation.cause, obligation.param_env) - .sup(placeholder_trait_predicate.trait_ref.to_poly_trait_ref(), candidate.value) + .sup(placeholder_trait_predicate.to_poly_trait_ref(), candidate.value) .map(|InferOk { obligations, .. }| obligations) .map_err(|_| Unimplemented) })?); @@ -598,12 +601,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { Ok(ImplSourceGeneratorData { generator_def_id, substs, nested: obligations }) } + #[instrument(skip(self), level = "debug")] fn confirm_closure_candidate( &mut self, obligation: &TraitObligation<'tcx>, ) -> Result>, SelectionError<'tcx>> { - debug!(?obligation, "confirm_closure_candidate"); - let kind = self .tcx() .fn_trait_kind_from_lang_item(obligation.predicate.def_id()) @@ -644,7 +646,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligations.push(Obligation::new( obligation.cause.clone(), obligation.param_env, - ty::PredicateKind::ClosureKind(closure_def_id, substs, kind) + ty::Binder::dummy(ty::PredicateKind::ClosureKind(closure_def_id, substs, kind)) .to_predicate(self.tcx()), )); } @@ -677,6 +679,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { /// because these output type parameters should not affect the /// selection of the impl. Therefore, if there is a mismatch, we /// report an error to the user. + #[instrument(skip(self), level = "trace")] fn confirm_poly_trait_refs( &mut self, obligation_cause: ObligationCause<'tcx>, @@ -896,10 +899,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ); // We can only make objects from sized types. - let tr = ty::TraitRef::new( + let tr = ty::Binder::dummy(ty::TraitRef::new( tcx.require_lang_item(LangItem::Sized, None), tcx.mk_substs_trait(source, &[]), - ); + )); nested.push(predicate_to_obligation(tr.without_const().to_predicate(tcx))); // If the type is `Foo + 'a`, ensure that the type diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index cf6f76a932..85502a399d 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -14,18 +14,17 @@ use super::util; use super::util::{closure_trait_ref_and_return_type, predicate_for_trait_def}; use super::wf; use super::DerivedObligationCause; +use super::Normalized; use super::Obligation; use super::ObligationCauseCode; use super::Selection; use super::SelectionResult; use super::TraitQueryMode; -use super::{Normalized, ProjectionCacheKey}; +use super::{ErrorReporting, Overflow, SelectionError, Unimplemented}; use super::{ObligationCause, PredicateObligation, TraitObligation}; -use super::{Overflow, SelectionError, Unimplemented}; use crate::infer::{InferCtxt, InferOk, TypeFreshener}; use crate::traits::error_reporting::InferCtxtExt; -use crate::traits::project::ProjectionCacheKeyExt; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_data_structures::sync::Lrc; @@ -34,8 +33,8 @@ use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_infer::infer::LateBoundRegionConversionTime; use rustc_middle::dep_graph::{DepKind, DepNodeIndex}; -use rustc_middle::mir::abstract_const::NotConstEvaluatable; use rustc_middle::mir::interpret::ErrorHandled; +use rustc_middle::thir::abstract_const::NotConstEvaluatable; use rustc_middle::ty::fast_reject; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::relate::TypeRelation; @@ -452,6 +451,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { /// Evaluates the predicates in `predicates` recursively. Note that /// this applies projections in the predicates, and therefore /// is run within an inference probe. + #[instrument(skip(self, stack), level = "debug")] fn evaluate_predicates_recursively<'o, I>( &mut self, stack: TraitObligationStackList<'o, 'tcx>, @@ -461,7 +461,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { I: IntoIterator> + std::fmt::Debug, { let mut result = EvaluatedToOk; - debug!(?predicates, "evaluate_predicates_recursively"); for obligation in predicates { let eval = self.evaluate_predicate_recursively(stack, obligation.clone())?; if let EvaluatedToErr = eval { @@ -578,14 +577,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { match project::poly_project_and_unify_type(self, &project_obligation) { Ok(Ok(Some(mut subobligations))) => { self.add_depth(subobligations.iter_mut(), obligation.recursion_depth); - let result = self - .evaluate_predicates_recursively(previous_stack, subobligations); - if let Some(key) = - ProjectionCacheKey::from_poly_projection_predicate(self, data) - { - self.infcx.inner.borrow_mut().projection_cache().complete(key); - } - result + self.evaluate_predicates_recursively(previous_stack, subobligations) } Ok(Ok(None)) => Ok(EvaluatedToAmbig), Ok(Err(project::InProgress)) => Ok(EvaluatedToRecur), @@ -691,13 +683,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { result } + #[instrument(skip(self, previous_stack), level = "debug")] fn evaluate_trait_predicate_recursively<'o>( &mut self, previous_stack: TraitObligationStackList<'o, 'tcx>, mut obligation: TraitObligation<'tcx>, ) -> Result { - debug!(?obligation, "evaluate_trait_predicate_recursively"); - if !self.intercrate && obligation.is_global(self.tcx()) && obligation @@ -709,7 +700,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // If a param env has no global bounds, global obligations do not // depend on its particular value in order to work, so we can clear // out the param env and get better caching. - debug!("evaluate_trait_predicate_recursively - in global"); + debug!("in global"); obligation.param_env = obligation.param_env.without_caller_bounds(); } @@ -761,7 +752,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } else { debug!(?result, "PROVISIONAL"); debug!( - "evaluate_trait_predicate_recursively: caching provisionally because {:?} \ + "caching provisionally because {:?} \ is a cycle participant (at depth {}, reached depth {})", fresh_trait_ref, stack.depth, reached_depth, ); @@ -909,7 +900,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { match self.candidate_from_obligation(stack) { Ok(Some(c)) => self.evaluate_candidate(stack, &c), Ok(None) => Ok(EvaluatedToAmbig), - Err(Overflow) => Err(OverflowError), + Err(Overflow) => Err(OverflowError::Canonical), + Err(ErrorReporting) => Err(OverflowError::ErrorReporting), Err(..) => Ok(EvaluatedToErr), } } @@ -1058,26 +1050,38 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { it.for_each(|o| o.recursion_depth = cmp::max(min_depth, o.recursion_depth) + 1); } + fn check_recursion_depth>( + &self, + depth: usize, + error_obligation: &Obligation<'tcx, T>, + ) -> Result<(), OverflowError> { + if !self.infcx.tcx.recursion_limit().value_within_limit(depth) { + match self.query_mode { + TraitQueryMode::Standard => { + if self.infcx.is_tainted_by_errors() { + return Err(OverflowError::ErrorReporting); + } + self.infcx.report_overflow_error(error_obligation, true); + } + TraitQueryMode::Canonical => { + return Err(OverflowError::Canonical); + } + } + } + Ok(()) + } + /// Checks that the recursion limit has not been exceeded. /// /// The weird return type of this function allows it to be used with the `try` (`?`) /// operator within certain functions. + #[inline(always)] fn check_recursion_limit, V: Display + TypeFoldable<'tcx>>( &self, obligation: &Obligation<'tcx, T>, error_obligation: &Obligation<'tcx, V>, ) -> Result<(), OverflowError> { - if !self.infcx.tcx.recursion_limit().value_within_limit(obligation.recursion_depth) { - match self.query_mode { - TraitQueryMode::Standard => { - self.infcx().report_overflow_error(error_obligation, true); - } - TraitQueryMode::Canonical => { - return Err(OverflowError); - } - } - } - Ok(()) + self.check_recursion_depth(obligation.recursion_depth, error_obligation) } fn in_task(&mut self, op: OP) -> (R, DepNodeIndex) @@ -1099,28 +1103,25 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let tcx = self.tcx(); // Respect const trait obligations if self.is_trait_predicate_const(obligation.predicate.skip_binder()) { - if Some(obligation.predicate.skip_binder().trait_ref.def_id) - != tcx.lang_items().sized_trait() - // const Sized bounds are skipped - { - 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 => {} - _ => { - // reject all other types of candidates - return Err(Unimplemented); - } + 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); } } } @@ -1510,21 +1511,24 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ( BuiltinCandidate { has_nested: false } | DiscriminantKindCandidate - | PointeeCandidate, + | PointeeCandidate + | ConstDropCandidate, _, ) => true, ( _, BuiltinCandidate { has_nested: false } | DiscriminantKindCandidate - | PointeeCandidate, + | PointeeCandidate + | ConstDropCandidate, ) => false, (ParamCandidate(other), ParamCandidate(victim)) => { - let value_same_except_bound_vars = other.value.skip_binder() + let same_except_bound_vars = other.value.skip_binder() == victim.value.skip_binder() + && other.constness == victim.constness && !other.value.skip_binder().has_escaping_bound_vars(); - if value_same_except_bound_vars { + if same_except_bound_vars { // See issue #84398. In short, we can generate multiple ParamCandidates which are // the same except for unused bound vars. Just pick the one with the fewest bound vars // or the current one if tied (they should both evaluate to the same answer). This is @@ -1541,6 +1545,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } } + // Drop otherwise equivalent non-const fn pointer candidates + (FnPointerCandidate { .. }, FnPointerCandidate { is_const: false }) => true, + // Global bounds from the where clause should be ignored // here (see issue #50825). Otherwise, we have a where // clause so don't go around looking for impls. @@ -1551,7 +1558,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ImplCandidate(..) | ClosureCandidate | GeneratorCandidate - | FnPointerCandidate + | FnPointerCandidate { .. } | BuiltinObjectCandidate | BuiltinUnsizeCandidate | TraitUpcastingUnsizeCandidate(_) @@ -1569,7 +1576,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ImplCandidate(_) | ClosureCandidate | GeneratorCandidate - | FnPointerCandidate + | FnPointerCandidate { .. } | BuiltinObjectCandidate | BuiltinUnsizeCandidate | TraitUpcastingUnsizeCandidate(_) @@ -1599,7 +1606,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ImplCandidate(..) | ClosureCandidate | GeneratorCandidate - | FnPointerCandidate + | FnPointerCandidate { .. } | BuiltinObjectCandidate | BuiltinUnsizeCandidate | TraitUpcastingUnsizeCandidate(_) @@ -1611,7 +1618,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ImplCandidate(..) | ClosureCandidate | GeneratorCandidate - | FnPointerCandidate + | FnPointerCandidate { .. } | BuiltinObjectCandidate | BuiltinUnsizeCandidate | TraitUpcastingUnsizeCandidate(_) @@ -1692,7 +1699,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ImplCandidate(_) | ClosureCandidate | GeneratorCandidate - | FnPointerCandidate + | FnPointerCandidate { .. } | BuiltinObjectCandidate | BuiltinUnsizeCandidate | TraitUpcastingUnsizeCandidate(_) @@ -1701,7 +1708,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ImplCandidate(_) | ClosureCandidate | GeneratorCandidate - | FnPointerCandidate + | FnPointerCandidate { .. } | BuiltinObjectCandidate | BuiltinUnsizeCandidate | TraitUpcastingUnsizeCandidate(_) @@ -2053,7 +2060,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let cause = ObligationCause::new( obligation.cause.span, obligation.cause.body_id, - ObligationCauseCode::MatchImpl(Lrc::new(obligation.cause.code.clone()), impl_def_id), + ObligationCauseCode::MatchImpl(obligation.cause.clone(), impl_def_id), ); let InferOk { obligations, .. } = self @@ -2125,13 +2132,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { /// Returns `Ok` if `poly_trait_ref` being true implies that the /// obligation is satisfied. + #[instrument(skip(self), level = "debug")] fn match_poly_trait_ref( &mut self, obligation: &TraitObligation<'tcx>, poly_trait_ref: ty::PolyTraitRef<'tcx>, ) -> Result>, ()> { - debug!(?obligation, ?poly_trait_ref, "match_poly_trait_ref"); - self.infcx .at(&obligation.cause, obligation.param_env) .sup(obligation.predicate.to_poly_trait_ref(), poly_trait_ref) @@ -2175,12 +2181,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } } + #[instrument(skip(self), level = "debug")] fn closure_trait_ref_unnormalized( &mut self, obligation: &TraitObligation<'tcx>, substs: SubstsRef<'tcx>, ) -> ty::PolyTraitRef<'tcx> { - debug!(?obligation, ?substs, "closure_trait_ref_unnormalized"); let closure_sig = substs.as_closure().sig(); debug!(?closure_sig); @@ -2479,7 +2485,7 @@ impl<'tcx> ProvisionalEvaluationCache<'tcx> { "get_provisional = {:#?}", self.map.borrow().get(&fresh_trait_ref), ); - Some(self.map.borrow().get(&fresh_trait_ref)?.clone()) + Some(*self.map.borrow().get(&fresh_trait_ref)?) } /// Insert a provisional result into the cache. The result came diff --git a/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs b/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs index c8bcab6efd..ec7dcd4a41 100644 --- a/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs +++ b/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs @@ -50,7 +50,7 @@ impl ChildrenExt for Children { let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap(); if let Some(st) = fast_reject::simplify_type(tcx, trait_ref.self_ty(), false) { debug!("insert_blindly: impl_def_id={:?} st={:?}", impl_def_id, st); - self.nonblanket_impls.entry(st).or_default().push(impl_def_id) + self.non_blanket_impls.entry(st).or_default().push(impl_def_id) } else { debug!("insert_blindly: impl_def_id={:?} st=None", impl_def_id); self.blanket_impls.push(impl_def_id) @@ -65,7 +65,7 @@ impl ChildrenExt for Children { let vec: &mut Vec; if let Some(st) = fast_reject::simplify_type(tcx, trait_ref.self_ty(), false) { debug!("remove_existing: impl_def_id={:?} st={:?}", impl_def_id, st); - vec = self.nonblanket_impls.get_mut(&st).unwrap(); + vec = self.non_blanket_impls.get_mut(&st).unwrap(); } else { debug!("remove_existing: impl_def_id={:?} st=None", impl_def_id); vec = &mut self.blanket_impls; @@ -104,19 +104,21 @@ impl ChildrenExt for Children { let self_ty = trait_ref.self_ty(); // FIXME: should postpone string formatting until we decide to actually emit. - with_no_trimmed_paths(|| OverlapError { - with_impl: possible_sibling, - trait_desc: trait_ref.print_only_trait_path().to_string(), - // Only report the `Self` type if it has at least - // some outer concrete shell; otherwise, it's - // not adding much information. - self_desc: if self_ty.has_concrete_skeleton() { - Some(self_ty.to_string()) - } else { - None - }, - intercrate_ambiguity_causes: overlap.intercrate_ambiguity_causes, - involves_placeholder: overlap.involves_placeholder, + with_no_trimmed_paths(|| { + OverlapError { + with_impl: possible_sibling, + trait_desc: trait_ref.print_only_trait_path().to_string(), + // Only report the `Self` type if it has at least + // some outer concrete shell; otherwise, it's + // not adding much information. + self_desc: if self_ty.has_concrete_skeleton() { + Some(self_ty.to_string()) + } else { + None + }, + intercrate_ambiguity_causes: overlap.intercrate_ambiguity_causes, + involves_placeholder: overlap.involves_placeholder, + } }) }; @@ -216,7 +218,7 @@ impl ChildrenExt for Children { } fn iter_children(children: &mut Children) -> impl Iterator + '_ { - let nonblanket = children.nonblanket_impls.iter_mut().flat_map(|(_, v)| v.iter()); + let nonblanket = children.non_blanket_impls.iter().flat_map(|(_, v)| v.iter()); children.blanket_impls.iter().chain(nonblanket).cloned() } @@ -224,7 +226,7 @@ fn filtered_children( children: &mut Children, st: SimplifiedType, ) -> impl Iterator + '_ { - let nonblanket = children.nonblanket_impls.entry(st).or_default().iter(); + let nonblanket = children.non_blanket_impls.entry(st).or_default().iter(); children.blanket_impls.iter().chain(nonblanket).cloned() } diff --git a/compiler/rustc_trait_selection/src/traits/util.rs b/compiler/rustc_trait_selection/src/traits/util.rs index fd94f9f799..ed49abbbed 100644 --- a/compiler/rustc_trait_selection/src/traits/util.rs +++ b/compiler/rustc_trait_selection/src/traits/util.rs @@ -248,7 +248,7 @@ pub fn predicate_for_trait_ref<'tcx>( cause, param_env, recursion_depth, - predicate: trait_ref.without_const().to_predicate(tcx), + predicate: ty::Binder::dummy(trait_ref).without_const().to_predicate(tcx), } } @@ -285,15 +285,10 @@ pub fn upcast_choices( /// that come from `trait_ref`, excluding its supertraits. Used in /// computing the vtable base for an upcast trait of a trait object. pub fn count_own_vtable_entries(tcx: TyCtxt<'tcx>, trait_ref: ty::PolyTraitRef<'tcx>) -> usize { - let mut entries = 0; - // Count number of methods and add them to the total offset. - // Skip over associated types and constants. - for trait_item in tcx.associated_items(trait_ref.def_id()).in_definition_order() { - if trait_item.kind == ty::AssocKind::Fn { - entries += 1; - } - } - entries + let existential_trait_ref = + trait_ref.map_bound(|trait_ref| ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref)); + let existential_trait_ref = tcx.erase_regions(existential_trait_ref); + tcx.own_existential_vtable_entries(existential_trait_ref).len() } /// Given an upcast trait object described by `object`, returns the @@ -304,22 +299,21 @@ pub fn get_vtable_index_of_object_method( object: &super::ImplSourceObjectData<'tcx, N>, method_def_id: DefId, ) -> usize { + let existential_trait_ref = object + .upcast_trait_ref + .map_bound(|trait_ref| ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref)); + let existential_trait_ref = tcx.erase_regions(existential_trait_ref); // Count number of methods preceding the one we are selecting and // add them to the total offset. - // Skip over associated types and constants, as those aren't stored in the vtable. - let mut entries = object.vtable_base; - for trait_item in tcx.associated_items(object.upcast_trait_ref.def_id()).in_definition_order() { - if trait_item.def_id == method_def_id { - // The item with the ID we were given really ought to be a method. - assert_eq!(trait_item.kind, ty::AssocKind::Fn); - return entries; - } - if trait_item.kind == ty::AssocKind::Fn { - entries += 1; - } - } - - bug!("get_vtable_index_of_object_method: {:?} was not found", method_def_id); + let index = tcx + .own_existential_vtable_entries(existential_trait_ref) + .iter() + .copied() + .position(|def_id| def_id == method_def_id) + .unwrap_or_else(|| { + bug!("get_vtable_index_of_object_method: {:?} was not found", method_def_id); + }); + object.vtable_base + index } pub fn closure_trait_ref_and_return_type( diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index 75307f1356..cb47ba9c36 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -209,7 +209,7 @@ fn extend_cause_with_original_assoc_item_obligation<'tcx>( _ => return, }; let fix_span = - |impl_item_ref: &hir::ImplItemRef<'_>| match tcx.hir().impl_item(impl_item_ref.id).kind { + |impl_item_ref: &hir::ImplItemRef| match tcx.hir().impl_item(impl_item_ref.id).kind { hir::ImplItemKind::Const(ty, _) | hir::ImplItemKind::TyAlias(ty) => ty.span, _ => impl_item_ref.span, }; @@ -349,7 +349,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { new_cause, depth, param_env, - ty::PredicateKind::WellFormed(arg).to_predicate(tcx), + ty::Binder::dummy(ty::PredicateKind::WellFormed(arg)).to_predicate(tcx), ) }), ); @@ -399,7 +399,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { cause.clone(), depth, param_env, - ty::PredicateKind::WellFormed(arg).to_predicate(tcx), + ty::Binder::dummy(ty::PredicateKind::WellFormed(arg)).to_predicate(tcx), ) }), ); @@ -416,7 +416,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { cause, self.recursion_depth, self.param_env, - trait_ref.without_const().to_predicate(self.infcx.tcx), + ty::Binder::dummy(trait_ref).without_const().to_predicate(self.infcx.tcx), )); } } @@ -443,9 +443,9 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { let obligations = self.nominal_obligations(uv.def.did, substs); self.out.extend(obligations); - let predicate = ty::PredicateKind::ConstEvaluatable( + let predicate = ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable( ty::Unevaluated::new(uv.def, substs), - ) + )) .to_predicate(self.tcx()); let cause = self.cause(traits::MiscObligation); self.out.push(traits::Obligation::with_depth( @@ -469,8 +469,10 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { cause, self.recursion_depth, self.param_env, - ty::PredicateKind::WellFormed(resolved_constant.into()) - .to_predicate(self.tcx()), + ty::Binder::dummy(ty::PredicateKind::WellFormed( + resolved_constant.into(), + )) + .to_predicate(self.tcx()), )); } } @@ -556,8 +558,10 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { cause, depth, param_env, - ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(rty, r)) - .to_predicate(self.tcx()), + ty::Binder::dummy(ty::PredicateKind::TypeOutlives( + ty::OutlivesPredicate(rty, r), + )) + .to_predicate(self.tcx()), )); } } @@ -646,7 +650,8 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { cause.clone(), depth, param_env, - ty::PredicateKind::ObjectSafe(did).to_predicate(tcx), + ty::Binder::dummy(ty::PredicateKind::ObjectSafe(did)) + .to_predicate(tcx), ) })); } @@ -673,7 +678,8 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { cause, self.recursion_depth, param_env, - ty::PredicateKind::WellFormed(ty.into()).to_predicate(self.tcx()), + ty::Binder::dummy(ty::PredicateKind::WellFormed(ty.into())) + .to_predicate(self.tcx()), )); } else { // Yes, resolved, proceed with the result. diff --git a/compiler/rustc_traits/Cargo.toml b/compiler/rustc_traits/Cargo.toml index 219165ff55..2e56a1bf68 100644 --- a/compiler/rustc_traits/Cargo.toml +++ b/compiler/rustc_traits/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustc_traits" version = "0.0.0" -edition = "2018" +edition = "2021" [dependencies] tracing = "0.1" diff --git a/compiler/rustc_traits/src/chalk/lowering.rs b/compiler/rustc_traits/src/chalk/lowering.rs index 1d4196e574..e24f699adf 100644 --- a/compiler/rustc_traits/src/chalk/lowering.rs +++ b/compiler/rustc_traits/src/chalk/lowering.rs @@ -892,7 +892,7 @@ impl<'tcx> TypeVisitor<'tcx> for BoundVarsCollector<'tcx> { match r { ty::ReLateBound(index, br) if *index == self.binder_index => match br.kind { ty::BoundRegionKind::BrNamed(def_id, _name) => { - if self.named_parameters.iter().find(|d| **d == def_id).is_none() { + if !self.named_parameters.iter().any(|d| *d == def_id) { self.named_parameters.push(def_id); } } diff --git a/compiler/rustc_traits/src/implied_outlives_bounds.rs b/compiler/rustc_traits/src/implied_outlives_bounds.rs index 1d10d06849..37e0073373 100644 --- a/compiler/rustc_traits/src/implied_outlives_bounds.rs +++ b/compiler/rustc_traits/src/implied_outlives_bounds.rs @@ -4,14 +4,14 @@ use rustc_hir as hir; use rustc_infer::infer::canonical::{self, Canonical}; +use rustc_infer::infer::outlives::components::{push_outlives_components, Component}; use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; +use rustc_infer::traits::query::OutlivesBound; use rustc_infer::traits::TraitEngineExt as _; -use rustc_middle::ty::outlives::Component; use rustc_middle::ty::query::Providers; use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable}; use rustc_span::source_map::DUMMY_SP; use rustc_trait_selection::infer::InferCtxtBuilderExt; -use rustc_trait_selection::traits::query::outlives_bounds::OutlivesBound; use rustc_trait_selection::traits::query::{CanonicalTyGoal, Fallible, NoSolution}; use rustc_trait_selection::traits::wf; use rustc_trait_selection::traits::FulfillmentContext; @@ -118,7 +118,7 @@ fn compute_implied_outlives_bounds<'tcx>( ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(ty_a, r_b)) => { let ty_a = infcx.resolve_vars_if_possible(ty_a); let mut components = smallvec![]; - tcx.push_outlives_components(ty_a, &mut components); + push_outlives_components(tcx, ty_a, &mut components); implied_bounds_from_components(r_b, components) } }, diff --git a/compiler/rustc_traits/src/lib.rs b/compiler/rustc_traits/src/lib.rs index 48c46c3069..8612499623 100644 --- a/compiler/rustc_traits/src/lib.rs +++ b/compiler/rustc_traits/src/lib.rs @@ -19,7 +19,7 @@ mod normalize_erasing_regions; mod normalize_projection_ty; mod type_op; -pub use type_op::{type_op_ascribe_user_type_with_span, type_op_prove_predicate_with_span}; +pub use type_op::{type_op_ascribe_user_type_with_span, type_op_prove_predicate_with_cause}; use rustc_middle::ty::query::Providers; diff --git a/compiler/rustc_traits/src/type_op.rs b/compiler/rustc_traits/src/type_op.rs index a76fb84261..cc0b7d5817 100644 --- a/compiler/rustc_traits/src/type_op.rs +++ b/compiler/rustc_traits/src/type_op.rs @@ -156,7 +156,8 @@ impl AscribeUserTypeCx<'me, 'tcx> { self.relate(self_ty, Variance::Invariant, impl_self_ty)?; self.prove_predicate( - ty::PredicateKind::WellFormed(impl_self_ty.into()).to_predicate(self.tcx()), + ty::Binder::dummy(ty::PredicateKind::WellFormed(impl_self_ty.into())) + .to_predicate(self.tcx()), span, ); } @@ -173,7 +174,7 @@ impl AscribeUserTypeCx<'me, 'tcx> { // type were ill-formed but did not appear in `ty`, // which...could happen with normalization... self.prove_predicate( - ty::PredicateKind::WellFormed(ty.into()).to_predicate(self.tcx()), + ty::Binder::dummy(ty::PredicateKind::WellFormed(ty.into())).to_predicate(self.tcx()), span, ); Ok(()) @@ -256,7 +257,7 @@ fn type_op_prove_predicate<'tcx>( canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, ProvePredicate<'tcx>>>, ) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, ()>>, NoSolution> { tcx.infer_ctxt().enter_canonical_trait_query(&canonicalized, |infcx, fulfill_cx, key| { - type_op_prove_predicate_with_span(infcx, fulfill_cx, key, None); + type_op_prove_predicate_with_cause(infcx, fulfill_cx, key, ObligationCause::dummy()); Ok(()) }) } @@ -264,17 +265,12 @@ fn type_op_prove_predicate<'tcx>( /// The core of the `type_op_prove_predicate` query: for diagnostics purposes in NLL HRTB errors, /// this query can be re-run to better track the span of the obligation cause, and improve the error /// message. Do not call directly unless you're in that very specific context. -pub fn type_op_prove_predicate_with_span<'a, 'tcx: 'a>( +pub fn type_op_prove_predicate_with_cause<'a, 'tcx: 'a>( infcx: &'a InferCtxt<'a, 'tcx>, fulfill_cx: &'a mut dyn TraitEngine<'tcx>, key: ParamEnvAnd<'tcx, ProvePredicate<'tcx>>, - span: Option, + cause: ObligationCause<'tcx>, ) { - let cause = if let Some(span) = span { - ObligationCause::dummy_with_span(span) - } else { - ObligationCause::dummy() - }; let (param_env, ProvePredicate { predicate }) = key.into_parts(); fulfill_cx.register_predicate_obligation(infcx, Obligation::new(cause, param_env, predicate)); } diff --git a/compiler/rustc_ty_utils/Cargo.toml b/compiler/rustc_ty_utils/Cargo.toml index 2eb27fb1ad..78df95e680 100644 --- a/compiler/rustc_ty_utils/Cargo.toml +++ b/compiler/rustc_ty_utils/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustc_ty_utils" version = "0.0.0" -edition = "2018" +edition = "2021" [dependencies] tracing = "0.1" diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs index b00d2ab356..87b729faa5 100644 --- a/compiler/rustc_ty_utils/src/instance.rs +++ b/compiler/rustc_ty_utils/src/instance.rs @@ -386,7 +386,8 @@ fn resolve_associated_item<'tcx>( | traits::ImplSource::TraitAlias(..) | traits::ImplSource::DiscriminantKind(..) | traits::ImplSource::Pointee(..) - | traits::ImplSource::TraitUpcasting(_) => None, + | traits::ImplSource::TraitUpcasting(_) + | traits::ImplSource::ConstDrop(_) => None, }) } diff --git a/compiler/rustc_ty_utils/src/lib.rs b/compiler/rustc_ty_utils/src/lib.rs index 313571274c..60f8e196bc 100644 --- a/compiler/rustc_ty_utils/src/lib.rs +++ b/compiler/rustc_ty_utils/src/lib.rs @@ -6,8 +6,6 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![feature(control_flow_enum)] -#![feature(half_open_range_patterns)] -#![feature(exclusive_range_pattern)] #![feature(nll)] #![recursion_limit = "256"] diff --git a/compiler/rustc_ty_utils/src/needs_drop.rs b/compiler/rustc_ty_utils/src/needs_drop.rs index bf155ecbd1..3f66e5b4eb 100644 --- a/compiler/rustc_ty_utils/src/needs_drop.rs +++ b/compiler/rustc_ty_utils/src/needs_drop.rs @@ -12,13 +12,13 @@ use rustc_span::{sym, DUMMY_SP}; type NeedsDropResult = Result; fn needs_drop_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { - let adt_fields = - move |adt_def: &ty::AdtDef, _| tcx.adt_drop_tys(adt_def.did).map(|tys| tys.iter()); - // If we don't know a type doesn't need drop, for example if it's a type // parameter without a `Copy` bound, then we conservatively return that it // needs drop. - let res = NeedsDropTypes::new(tcx, query.param_env, query.value, adt_fields).next().is_some(); + 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(); + debug!("needs_drop_raw({:?}) = {:?}", query, res); res } @@ -27,12 +27,10 @@ fn has_significant_drop_raw<'tcx>( tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>, ) -> bool { - let significant_drop_fields = move |adt_def: &ty::AdtDef, _| { - tcx.adt_significant_drop_tys(adt_def.did).map(|tys| tys.iter()) - }; - let res = NeedsDropTypes::new(tcx, query.param_env, query.value, significant_drop_fields) - .next() - .is_some(); + let res = + drop_tys_helper(tcx, query.value, query.param_env, adt_consider_insignificant_dtor(tcx)) + .next() + .is_some(); debug!("has_significant_drop_raw({:?}) = {:?}", query, res); res } @@ -143,10 +141,8 @@ where Ok(tys) => tys, }; for required_ty in tys { - let subst_ty = tcx.normalize_erasing_regions( - self.param_env, - required_ty.subst(tcx, substs), - ); + let subst_ty = + tcx.normalize_erasing_regions(self.param_env, required_ty); queue_type(self, subst_ty); } } @@ -185,23 +181,24 @@ enum DtorType { // Depending on the implentation of `adt_has_dtor`, it is used to check if the // ADT has a destructor or if the ADT only has a significant destructor. For // understanding significant destructor look at `adt_significant_drop_tys`. -fn adt_drop_tys_helper<'tcx>( +fn drop_tys_helper<'tcx>( tcx: TyCtxt<'tcx>, - def_id: DefId, + ty: Ty<'tcx>, + param_env: rustc_middle::ty::ParamEnv<'tcx>, adt_has_dtor: impl Fn(&ty::AdtDef) -> Option, -) -> Result<&ty::List>, AlwaysRequiresDrop> { +) -> impl Iterator>> { let adt_components = move |adt_def: &ty::AdtDef, substs: SubstsRef<'tcx>| { if adt_def.is_manually_drop() { - debug!("adt_drop_tys: `{:?}` is manually drop", adt_def); + debug!("drop_tys_helper: `{:?}` is manually drop", adt_def); return Ok(Vec::new().into_iter()); } else if let Some(dtor_info) = adt_has_dtor(adt_def) { match dtor_info { DtorType::Significant => { - debug!("adt_drop_tys: `{:?}` implements `Drop`", adt_def); + debug!("drop_tys_helper: `{:?}` implements `Drop`", adt_def); return Err(AlwaysRequiresDrop); } DtorType::Insignificant => { - debug!("adt_drop_tys: `{:?}` drop is insignificant", adt_def); + debug!("drop_tys_helper: `{:?}` drop is insignificant", adt_def); // Since the destructor is insignificant, we just want to make sure all of // the passed in type parameters are also insignificant. @@ -210,34 +207,27 @@ fn adt_drop_tys_helper<'tcx>( } } } else if adt_def.is_union() { - debug!("adt_drop_tys: `{:?}` is a union", adt_def); + debug!("drop_tys_helper: `{:?}` is a union", adt_def); return Ok(Vec::new().into_iter()); } - Ok(adt_def.all_fields().map(|field| tcx.type_of(field.did)).collect::>().into_iter()) + 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()) }; - let adt_ty = tcx.type_of(def_id); - let param_env = tcx.param_env(def_id); - let res: Result, _> = - NeedsDropTypes::new(tcx, param_env, adt_ty, adt_components).collect(); - - debug!("adt_drop_tys(`{}`) = `{:?}`", tcx.def_path_str(def_id), res); - res.map(|components| tcx.intern_type_list(&components)) + NeedsDropTypes::new(tcx, param_env, ty, adt_components) } -fn adt_drop_tys(tcx: TyCtxt<'_>, def_id: DefId) -> Result<&ty::List>, AlwaysRequiresDrop> { - // This is for the "needs_drop" query, that considers all `Drop` impls, therefore all dtors are - // significant. - let adt_has_dtor = - |adt_def: &ty::AdtDef| adt_def.destructor(tcx).map(|_| DtorType::Significant); - adt_drop_tys_helper(tcx, def_id, adt_has_dtor) -} - -fn adt_significant_drop_tys( - tcx: TyCtxt<'_>, - def_id: DefId, -) -> Result<&ty::List>, AlwaysRequiresDrop> { - let adt_has_dtor = |adt_def: &ty::AdtDef| { +fn adt_consider_insignificant_dtor<'tcx>( + tcx: TyCtxt<'tcx>, +) -> impl Fn(&ty::AdtDef) -> Option + 'tcx { + move |adt_def: &ty::AdtDef| { let is_marked_insig = tcx.has_attr(adt_def.did, sym::rustc_insignificant_dtor); if is_marked_insig { // In some cases like `std::collections::HashMap` where the struct is a wrapper around @@ -254,8 +244,31 @@ fn adt_significant_drop_tys( // treat this as the simple case of Drop impl for type. None } - }; - adt_drop_tys_helper(tcx, def_id, adt_has_dtor) + } +} + +fn adt_drop_tys(tcx: TyCtxt<'_>, def_id: DefId) -> Result<&ty::List>, AlwaysRequiresDrop> { + // This is for the "adt_drop_tys" query, that considers all `Drop` impls, therefore all dtors are + // 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) + .collect::, _>>() + .map(|components| tcx.intern_type_list(&components)) +} + +fn adt_significant_drop_tys( + tcx: TyCtxt<'_>, + def_id: DefId, +) -> Result<&ty::List>, AlwaysRequiresDrop> { + drop_tys_helper( + tcx, + tcx.type_of(def_id), + tcx.param_env(def_id), + adt_consider_insignificant_dtor(tcx), + ) + .collect::, _>>() + .map(|components| tcx.intern_type_list(&components)) } pub(crate) fn provide(providers: &mut ty::query::Providers) { diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index 27ad7bf4c2..7512403249 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -100,7 +100,7 @@ fn associated_item_from_trait_item_ref( fn associated_item_from_impl_item_ref( tcx: TyCtxt<'_>, parent_def_id: LocalDefId, - impl_item_ref: &hir::ImplItemRef<'_>, + impl_item_ref: &hir::ImplItemRef, ) -> ty::AssocItem { let def_id = impl_item_ref.id.def_id; let (kind, has_self) = match impl_item_ref.kind { @@ -248,6 +248,7 @@ fn trait_of_item(tcx: TyCtxt<'_>, def_id: DefId) -> Option { } /// See `ParamEnv` struct definition for details. +#[instrument(level = "debug", skip(tcx))] fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> { // The param_env of an impl Trait type is its defining function's param_env if let Some(parent) = ty::is_impl_trait_defn(tcx, def_id) { @@ -275,9 +276,20 @@ fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> { predicates.extend(environment); } + // It's important that we include the default substs in unevaluated + // constants, since `Unevaluated` instances in predicates whose substs are None + // can lead to "duplicate" caller bounds candidates during trait selection, + // duplicate in the sense that both have their default substs, but the + // candidate that resulted from a superpredicate still uses `None` in its + // `substs_` field of `Unevaluated` to indicate that it has its default substs, + // whereas the other candidate has `substs_: Some(default_substs)`, see + // issue #89334 + predicates = tcx.expose_default_const_substs(predicates); + let unnormalized_env = ty::ParamEnv::new(tcx.intern_predicates(&predicates), traits::Reveal::UserFacing); + debug!("unnormalized_env caller bounds: {:?}", unnormalized_env.caller_bounds()); let body_id = def_id .as_local() .map(|def_id| tcx.hir().local_def_id_to_hir_id(def_id)) diff --git a/compiler/rustc_type_ir/Cargo.toml b/compiler/rustc_type_ir/Cargo.toml index 1f6acbe0d8..439e6cdf70 100644 --- a/compiler/rustc_type_ir/Cargo.toml +++ b/compiler/rustc_type_ir/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustc_type_ir" version = "0.0.0" -edition = "2018" +edition = "2021" [lib] doctest = false diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs index c405bbe2d1..91dbbec782 100644 --- a/compiler/rustc_type_ir/src/lib.rs +++ b/compiler/rustc_type_ir/src/lib.rs @@ -363,10 +363,11 @@ pub enum IntVarValue { #[derive(Clone, Copy, PartialEq, Eq)] pub struct FloatVarValue(pub FloatTy); -/// A **ty**pe **v**ariable **ID**. -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable)] -pub struct TyVid { - pub index: u32, +rustc_index::newtype_index! { + /// A **ty**pe **v**ariable **ID**. + pub struct TyVid { + DEBUG_FORMAT = "_#{}t" + } } /// An **int**egral (`u32`, `i32`, `usize`, etc.) type **v**ariable **ID**. @@ -422,10 +423,10 @@ pub enum InferTy { impl UnifyKey for TyVid { type Value = (); fn index(&self) -> u32 { - self.index + self.as_u32() } fn from_index(i: u32) -> TyVid { - TyVid { index: i } + TyVid::from_u32(i) } fn tag() -> &'static str { "TyVid" @@ -436,6 +437,7 @@ impl EqUnifyValue for IntVarValue {} impl UnifyKey for IntVid { type Value = Option; + #[inline] // make this function eligible for inlining - it is quite hot. fn index(&self) -> u32 { self.index } @@ -558,7 +560,7 @@ impl HashStable for InferTy { fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { use InferTy::*; match self { - TyVar(v) => v.index.hash_stable(ctx, hasher), + TyVar(v) => v.as_u32().hash_stable(ctx, hasher), IntVar(v) => v.index.hash_stable(ctx, hasher), FloatVar(v) => v.index.hash_stable(ctx, hasher), FreshTy(v) | FreshIntTy(v) | FreshFloatTy(v) => v.hash_stable(ctx, hasher), @@ -587,12 +589,6 @@ impl fmt::Debug for FloatVarValue { } } -impl fmt::Debug for TyVid { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "_#{}t", self.index) - } -} - impl fmt::Debug for IntVid { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "_#{}i", self.index) diff --git a/compiler/rustc_typeck/Cargo.toml b/compiler/rustc_typeck/Cargo.toml index dd76a5e4b9..7e570e151c 100644 --- a/compiler/rustc_typeck/Cargo.toml +++ b/compiler/rustc_typeck/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustc_typeck" version = "0.0.0" -edition = "2018" +edition = "2021" [lib] test = false diff --git a/compiler/rustc_typeck/src/astconv/errors.rs b/compiler/rustc_typeck/src/astconv/errors.rs index 695132281c..ec75e4a55d 100644 --- a/compiler/rustc_typeck/src/astconv/errors.rs +++ b/compiler/rustc_typeck/src/astconv/errors.rs @@ -199,7 +199,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { /// When there are any missing associated types, emit an E0191 error and attempt to supply a /// reasonable suggestion on how to write it. For the case of multiple associated types in the - /// same trait bound have the same name (as they come from different super-traits), we instead + /// same trait bound have the same name (as they come from different supertraits), we instead /// emit a generic note suggesting using a `where` clause to constraint instead. pub(crate) fn complain_about_missing_associated_types( &self, @@ -340,7 +340,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { using the fully-qualified path to the associated types"; if !where_constraints.is_empty() && suggestions.is_empty() { // If there are duplicates associated type names and a single trait bound do not - // use structured suggestion, it means that there are multiple super-traits with + // use structured suggestion, it means that there are multiple supertraits with // the same associated type name. err.help(where_msg); } diff --git a/compiler/rustc_typeck/src/astconv/generics.rs b/compiler/rustc_typeck/src/astconv/generics.rs index fd0544a47b..5befe44802 100644 --- a/compiler/rustc_typeck/src/astconv/generics.rs +++ b/compiler/rustc_typeck/src/astconv/generics.rs @@ -132,7 +132,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } let kind_ord = param.kind.to_ord(tcx); - let arg_ord = arg.to_ord(&tcx.features()); + let arg_ord = arg.to_ord(tcx.features()); // This note is only true when generic parameters are strictly ordered by their kind. if possible_ordering_error && kind_ord.cmp(&arg_ord) != core::cmp::Ordering::Equal { @@ -423,7 +423,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { is_method_call: IsMethodCall, ) -> GenericArgCountResult { let empty_args = hir::GenericArgs::none(); - let suppress_mismatch = Self::check_impl_trait(tcx, seg, &generics); + let suppress_mismatch = Self::check_impl_trait(tcx, seg, generics); let gen_args = seg.args.unwrap_or(&empty_args); let gen_pos = if is_method_call == IsMethodCall::Yes { @@ -441,6 +441,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { /// Checks that the correct number of generic arguments have been provided. /// This is used both for datatypes and function calls. + #[instrument(skip(tcx, gen_pos), level = "debug")] pub(crate) fn check_generic_arg_count( tcx: TyCtxt<'_>, span: Span, @@ -452,11 +453,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { has_self: bool, infer_args: bool, ) -> GenericArgCountResult { - debug!( - "check_generic_arg_count(span: {:?}, def_id: {:?}, seg: {:?}, gen_params: {:?}, gen_args: {:?})", - span, def_id, seg, gen_params, gen_args - ); - let default_counts = gen_params.own_defaults(); let param_counts = gen_params.own_counts(); @@ -556,9 +552,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let mut check_types_and_consts = |expected_min, expected_max, provided, params_offset, args_offset| { debug!( - "check_types_and_consts(expected_min: {:?}, expected_max: {:?}, \ - provided: {:?}, params_offset: {:?}, args_offset: {:?}", - expected_min, expected_max, provided, params_offset, args_offset + ?expected_min, + ?expected_max, + ?provided, + ?params_offset, + ?args_offset, + "check_types_and_consts" ); if (expected_min..=expected_max).contains(&provided) { return true; @@ -589,7 +588,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } }; - debug!("gen_args_info: {:?}", gen_args_info); + debug!(?gen_args_info); WrongNumberOfGenericArgs::new( tcx, @@ -601,7 +600,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { def_id, ) .diagnostic() - .emit(); + .emit_unless(gen_args.has_err()); false }; @@ -614,8 +613,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { - default_counts.types - default_counts.consts }; - debug!("expected_min: {:?}", expected_min); - debug!("arg_counts.lifetimes: {:?}", gen_args.num_lifetime_params()); + debug!(?expected_min); + debug!(arg_counts.lifetimes=?gen_args.num_lifetime_params()); check_types_and_consts( expected_min, diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs index 059e0cadd1..889b68773c 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -111,11 +111,6 @@ pub trait AstConv<'tcx> { fn record_ty(&self, hir_id: hir::HirId, ty: Ty<'tcx>, span: Span); } -pub enum SizedByDefault { - Yes, - No, -} - #[derive(Debug)] struct ConvertedBinding<'a, 'tcx> { hir_id: hir::HirId, @@ -357,8 +352,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { span, def_id, seg, - &generics, - &generic_args, + generics, + generic_args, GenericArgPosition::Type, self_ty.is_some(), infer_args, @@ -368,7 +363,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // Traits always have `Self` as a generic parameter, which means they will not return early // here and so associated type bindings will be handled regardless of whether there are any // non-`Self` generic parameters. - if generics.params.len() == 0 { + if generics.params.is_empty() { return (tcx.intern_substs(&[]), arg_count); } @@ -422,7 +417,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let tcx = self.astconv.tcx(); match (¶m.kind, arg) { (GenericParamDefKind::Lifetime, GenericArg::Lifetime(lt)) => { - self.astconv.ast_region_to_region(<, Some(param)).into() + self.astconv.ast_region_to_region(lt, Some(param)).into() } (&GenericParamDefKind::Type { has_default, .. }, GenericArg::Type(ty)) => { if has_default { @@ -446,7 +441,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { self.inferred_params.push(ty.span); tcx.ty_error().into() } else { - self.astconv.ast_ty_to_ty(&ty).into() + self.astconv.ast_ty_to_ty(ty).into() } } (GenericParamDefKind::Const { .. }, GenericArg::Const(ct)) => { @@ -627,10 +622,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { .iter() .map(|binding| { let kind = match binding.kind { - hir::TypeBindingKind::Equality { ref ty } => { + hir::TypeBindingKind::Equality { ty } => { ConvertedBindingKind::Equality(self.ast_ty_to_ty(ty)) } - hir::TypeBindingKind::Constraint { ref bounds } => { + hir::TypeBindingKind::Constraint { bounds } => { ConvertedBindingKind::Constraint(bounds) } }; @@ -698,6 +693,61 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { ) } + fn instantiate_poly_trait_ref_inner( + &self, + hir_id: hir::HirId, + span: Span, + binding_span: Option, + constness: ty::BoundConstness, + bounds: &mut Bounds<'tcx>, + speculative: bool, + trait_ref_span: Span, + trait_def_id: DefId, + trait_segment: &hir::PathSegment<'_>, + args: &GenericArgs<'_>, + infer_args: bool, + self_ty: Ty<'tcx>, + ) -> GenericArgCountResult { + let (substs, arg_count) = self.create_substs_for_ast_path( + trait_ref_span, + trait_def_id, + &[], + trait_segment, + args, + infer_args, + Some(self_ty), + ); + + let tcx = self.tcx(); + let bound_vars = tcx.late_bound_vars(hir_id); + debug!(?bound_vars); + + let assoc_bindings = self.create_assoc_bindings_for_generic_args(args); + + let poly_trait_ref = + ty::Binder::bind_with_vars(ty::TraitRef::new(trait_def_id, substs), bound_vars); + + debug!(?poly_trait_ref, ?assoc_bindings); + bounds.trait_bounds.push((poly_trait_ref, span, constness)); + + let mut dup_bindings = FxHashMap::default(); + for binding in &assoc_bindings { + // Specify type to assert that error was already reported in `Err` case. + let _: Result<_, ErrorReported> = self.add_predicates_for_ast_type_binding( + hir_id, + poly_trait_ref, + binding, + bounds, + speculative, + &mut dup_bindings, + binding_span.unwrap_or(binding.span), + ); + // Okay to ignore `Err` because of `ErrorReported` (see above). + } + + arg_count + } + /// Given a trait bound like `Debug`, applies that trait bound the given self-type to construct /// a full trait reference. The resulting trait reference is returned. This may also generate /// auxiliary bounds, which are added to `bounds`. @@ -718,7 +768,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { /// `Bar<'a>`. The returned poly-trait-ref will have this binder instantiated explicitly, /// however. #[tracing::instrument(level = "debug", skip(self, span, constness, bounds, speculative))] - pub fn instantiate_poly_trait_ref( + pub(crate) fn instantiate_poly_trait_ref( &self, trait_ref: &hir::TraitRef<'_>, span: Span, @@ -727,48 +777,34 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { bounds: &mut Bounds<'tcx>, speculative: bool, ) -> GenericArgCountResult { + let hir_id = trait_ref.hir_ref_id; + let binding_span = None; + let trait_ref_span = trait_ref.path.span; let trait_def_id = trait_ref.trait_def_id().unwrap_or_else(|| FatalError.raise()); + let trait_segment = trait_ref.path.segments.last().unwrap(); + let args = trait_segment.args(); + let infer_args = trait_segment.infer_args; self.prohibit_generics(trait_ref.path.segments.split_last().unwrap().1); + self.complain_about_internal_fn_trait(span, trait_def_id, trait_segment); - let tcx = self.tcx(); - let bound_vars = tcx.late_bound_vars(trait_ref.hir_ref_id); - debug!(?bound_vars); - - let (substs, arg_count) = self.create_substs_for_ast_trait_ref( - trait_ref.path.span, + self.instantiate_poly_trait_ref_inner( + hir_id, + span, + binding_span, + constness, + bounds, + speculative, + trait_ref_span, trait_def_id, + trait_segment, + args, + infer_args, self_ty, - trait_ref.path.segments.last().unwrap(), - ); - let assoc_bindings = self - .create_assoc_bindings_for_generic_args(trait_ref.path.segments.last().unwrap().args()); - - let poly_trait_ref = - ty::Binder::bind_with_vars(ty::TraitRef::new(trait_def_id, substs), bound_vars); - - debug!(?poly_trait_ref, ?assoc_bindings); - bounds.trait_bounds.push((poly_trait_ref, span, constness)); - - let mut dup_bindings = FxHashMap::default(); - for binding in &assoc_bindings { - // Specify type to assert that error was already reported in `Err` case. - let _: Result<_, ErrorReported> = self.add_predicates_for_ast_type_binding( - trait_ref.hir_ref_id, - poly_trait_ref, - binding, - bounds, - speculative, - &mut dup_bindings, - binding.span, - ); - // Okay to ignore `Err` because of `ErrorReported` (see above). - } - - arg_count + ) } - pub fn instantiate_lang_item_trait_ref( + pub(crate) fn instantiate_lang_item_trait_ref( &self, lang_item: hir::LangItem, span: Span, @@ -777,36 +813,28 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { self_ty: Ty<'tcx>, bounds: &mut Bounds<'tcx>, ) { + let binding_span = Some(span); + let constness = ty::BoundConstness::NotConst; + let speculative = false; + let trait_ref_span = span; let trait_def_id = self.tcx().require_lang_item(lang_item, Some(span)); + let trait_segment = &hir::PathSegment::invalid(); + let infer_args = false; - let (substs, _) = self.create_substs_for_ast_path( + self.instantiate_poly_trait_ref_inner( + hir_id, span, + binding_span, + constness, + bounds, + speculative, + trait_ref_span, trait_def_id, - &[], - &hir::PathSegment::invalid(), + trait_segment, args, - false, - Some(self_ty), + infer_args, + self_ty, ); - let assoc_bindings = self.create_assoc_bindings_for_generic_args(args); - let tcx = self.tcx(); - let bound_vars = tcx.late_bound_vars(hir_id); - let poly_trait_ref = - ty::Binder::bind_with_vars(ty::TraitRef::new(trait_def_id, substs), bound_vars); - bounds.trait_bounds.push((poly_trait_ref, span, ty::BoundConstness::NotConst)); - - let mut dup_bindings = FxHashMap::default(); - for binding in assoc_bindings { - let _: Result<_, ErrorReported> = self.add_predicates_for_ast_type_binding( - hir_id, - poly_trait_ref, - &binding, - bounds, - false, - &mut dup_bindings, - span, - ); - } } fn ast_path_to_mono_trait_ref( @@ -853,46 +881,73 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { .is_some() } - // Returns `true` if a bounds list includes `?Sized`. - pub fn is_unsized(&self, ast_bounds: &[hir::GenericBound<'_>], span: Span) -> bool { + // Sets `implicitly_sized` to true on `Bounds` if necessary + pub(crate) fn add_implicitly_sized<'hir>( + &self, + bounds: &mut Bounds<'hir>, + ast_bounds: &'hir [hir::GenericBound<'hir>], + self_ty_where_predicates: Option<(hir::HirId, &'hir [hir::WherePredicate<'hir>])>, + span: Span, + ) { let tcx = self.tcx(); // Try to find an unbound in bounds. let mut unbound = None; - for ab in ast_bounds { - if let hir::GenericBound::Trait(ptr, hir::TraitBoundModifier::Maybe) = ab { - if unbound.is_none() { - unbound = Some(&ptr.trait_ref); - } else { - tcx.sess.emit_err(MultipleRelaxedDefaultBounds { span }); - } - } - } - - let kind_id = tcx.lang_items().require(LangItem::Sized); - match unbound { - Some(tpb) => { - // FIXME(#8559) currently requires the unbound to be built-in. - if let Ok(kind_id) = kind_id { - if tpb.path.res != Res::Def(DefKind::Trait, kind_id) { - tcx.sess.span_warn( - span, - "default bound relaxed for a type parameter, but \ - this does nothing because the given bound is not \ - a default; only `?Sized` is supported", - ); - return false; + let mut search_bounds = |ast_bounds: &'hir [hir::GenericBound<'hir>]| { + for ab in ast_bounds { + if let hir::GenericBound::Trait(ptr, hir::TraitBoundModifier::Maybe) = ab { + if unbound.is_none() { + unbound = Some(&ptr.trait_ref); + } else { + tcx.sess.emit_err(MultipleRelaxedDefaultBounds { span }); } } } - _ if kind_id.is_ok() => { - return false; + }; + search_bounds(ast_bounds); + if let Some((self_ty, where_clause)) = self_ty_where_predicates { + let self_ty_def_id = tcx.hir().local_def_id(self_ty).to_def_id(); + for clause in where_clause { + if let hir::WherePredicate::BoundPredicate(pred) = clause { + match pred.bounded_ty.kind { + hir::TyKind::Path(hir::QPath::Resolved(_, path)) => match path.res { + Res::Def(DefKind::TyParam, def_id) if def_id == self_ty_def_id => {} + _ => continue, + }, + _ => continue, + } + search_bounds(pred.bounds); + } } - // No lang item for `Sized`, so we can't add it as a bound. - None => {} } - true + let sized_def_id = tcx.lang_items().require(LangItem::Sized); + match (&sized_def_id, unbound) { + (Ok(sized_def_id), Some(tpb)) + if tpb.path.res == Res::Def(DefKind::Trait, *sized_def_id) => + { + // There was in fact a `?Sized` bound, return without doing anything + return; + } + (_, Some(_)) => { + // There was a `?Trait` bound, but it was not `?Sized`; warn. + tcx.sess.span_warn( + span, + "default bound relaxed for a type parameter, but \ + this does nothing because the given bound is not \ + a default; only `?Sized` is supported", + ); + // Otherwise, add implicitly sized if `Sized` is available. + } + _ => { + // There was no `?Sized` bound; add implicitly sized if `Sized` is available. + } + } + if sized_def_id.is_err() { + // No lang item for `Sized`, so we can't add it as a bound. + return; + } + bounds.implicitly_sized = Some(span); } /// This helper takes a *converted* parameter type (`param_ty`) @@ -910,46 +965,43 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { /// **A note on binders:** there is an implied binder around /// `param_ty` and `ast_bounds`. See `instantiate_poly_trait_ref` /// for more details. - #[tracing::instrument(level = "debug", skip(self, bounds))] - fn add_bounds( + #[tracing::instrument(level = "debug", skip(self, ast_bounds, bounds))] + pub(crate) fn add_bounds<'hir, I: Iterator>>( &self, param_ty: Ty<'tcx>, - ast_bounds: &[hir::GenericBound<'_>], + ast_bounds: I, bounds: &mut Bounds<'tcx>, bound_vars: &'tcx ty::List, ) { for ast_bound in ast_bounds { - match *ast_bound { - hir::GenericBound::Trait(ref b, hir::TraitBoundModifier::None) => { - self.instantiate_poly_trait_ref( - &b.trait_ref, - b.span, - ty::BoundConstness::NotConst, + match ast_bound { + hir::GenericBound::Trait(poly_trait_ref, modifier) => { + let constness = match modifier { + hir::TraitBoundModifier::MaybeConst => ty::BoundConstness::ConstIfConst, + hir::TraitBoundModifier::None => ty::BoundConstness::NotConst, + hir::TraitBoundModifier::Maybe => continue, + }; + + let _ = self.instantiate_poly_trait_ref( + &poly_trait_ref.trait_ref, + poly_trait_ref.span, + constness, param_ty, bounds, false, ); } - hir::GenericBound::Trait(ref b, hir::TraitBoundModifier::MaybeConst) => { - self.instantiate_poly_trait_ref( - &b.trait_ref, - b.span, - ty::BoundConstness::ConstIfConst, - param_ty, - bounds, - false, - ); - } - hir::GenericBound::Trait(_, hir::TraitBoundModifier::Maybe) - | hir::GenericBound::Unsized(_) => {} - hir::GenericBound::LangItemTrait(lang_item, span, hir_id, args) => self - .instantiate_lang_item_trait_ref( + &hir::GenericBound::LangItemTrait(lang_item, span, hir_id, args) => { + self.instantiate_lang_item_trait_ref( lang_item, span, hir_id, args, param_ty, bounds, - ), - hir::GenericBound::Outlives(ref l) => bounds.region_bounds.push(( - ty::Binder::bind_with_vars(self.ast_region_to_region(l, None), bound_vars), - l.span, - )), + ); + } + hir::GenericBound::Outlives(lifetime) => { + let region = self.ast_region_to_region(lifetime, None); + bounds + .region_bounds + .push((ty::Binder::bind_with_vars(region, bound_vars), lifetime.span)); + } } } } @@ -970,24 +1022,20 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { /// example above, but is not true in supertrait listings like `trait Foo: Bar + Baz`. /// /// `span` should be the declaration size of the parameter. - pub fn compute_bounds( + pub(crate) fn compute_bounds( &self, param_ty: Ty<'tcx>, ast_bounds: &[hir::GenericBound<'_>], - sized_by_default: SizedByDefault, - span: Span, ) -> Bounds<'tcx> { - self.compute_bounds_inner(param_ty, &ast_bounds, sized_by_default, span) + self.compute_bounds_inner(param_ty, ast_bounds) } /// Convert the bounds in `ast_bounds` that refer to traits which define an associated type /// named `assoc_name` into ty::Bounds. Ignore the rest. - pub fn compute_bounds_that_match_assoc_type( + pub(crate) fn compute_bounds_that_match_assoc_type( &self, param_ty: Ty<'tcx>, ast_bounds: &[hir::GenericBound<'_>], - sized_by_default: SizedByDefault, - span: Span, assoc_name: Ident, ) -> Bounds<'tcx> { let mut result = Vec::new(); @@ -1002,25 +1050,17 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } } - self.compute_bounds_inner(param_ty, &result, sized_by_default, span) + self.compute_bounds_inner(param_ty, &result) } fn compute_bounds_inner( &self, param_ty: Ty<'tcx>, ast_bounds: &[hir::GenericBound<'_>], - sized_by_default: SizedByDefault, - span: Span, ) -> Bounds<'tcx> { let mut bounds = Bounds::default(); - self.add_bounds(param_ty, ast_bounds, &mut bounds, ty::List::empty()); - - bounds.implicitly_sized = if let SizedByDefault::Yes = sized_by_default { - if !self.is_unsized(ast_bounds, span) { Some(span) } else { None } - } else { - None - }; + self.add_bounds(param_ty, ast_bounds.iter(), &mut bounds, ty::List::empty()); bounds } @@ -1188,7 +1228,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } match binding.kind { - ConvertedBindingKind::Equality(ref ty) => { + ConvertedBindingKind::Equality(ty) => { // "Desugar" a constraint like `T: Iterator` this to // the "projection predicate" for: // @@ -1212,7 +1252,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // Calling `skip_binder` is okay, because `add_bounds` expects the `param_ty` // parameter to have a skipped binder. let param_ty = tcx.mk_ty(ty::Projection(projection_ty.skip_binder())); - self.add_bounds(param_ty, ast_bounds, bounds, candidate.bound_vars()); + self.add_bounds(param_ty, ast_bounds.iter(), bounds, candidate.bound_vars()); } } Ok(()) @@ -1279,7 +1319,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { ); first_trait.label_with_exp_info(&mut err, "first non-auto trait", "first use"); err.help(&format!( - "consider creating a new trait with all of these as super-traits and using that \ + "consider creating a new trait with all of these as supertraits and using that \ trait here instead: `trait NewTrait: {} {{}}`", regular_traits .iter() @@ -1495,9 +1535,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let mut err = struct_span_err!(self.tcx().sess, span, E0223, "ambiguous associated type"); if let (true, Ok(snippet)) = ( self.tcx() - .sess + .resolutions(()) .confused_type_with_std_module - .borrow() .keys() .any(|full_span| full_span.contains(span)), self.tcx().sess.source_map().span_to_snippet(span), @@ -1645,14 +1684,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { constraint=constraint, )); } else { - err.span_suggestion( - span, + err.span_suggestion_verbose( + span.with_hi(assoc_name.span.lo()), "use fully qualified syntax to disambiguate", format!( - "<{} as {}>::{}", + "<{} as {}>::", ty_param_name(), bound.print_only_trait_path(), - assoc_name, ), Applicability::MaybeIncorrect, ); @@ -2166,7 +2204,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { assert_eq!(opt_self_ty, None); let path_segs = - self.def_ids_for_value_path_segments(&path.segments, None, kind, def_id); + self.def_ids_for_value_path_segments(path.segments, None, kind, def_id); let generic_segs: FxHashSet<_> = path_segs.iter().map(|PathSeg(_, index)| index).collect(); self.prohibit_generics(path.segments.iter().enumerate().filter_map( @@ -2263,34 +2301,32 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let tcx = self.tcx(); let result_ty = match ast_ty.kind { - hir::TyKind::Slice(ref ty) => tcx.mk_slice(self.ast_ty_to_ty(&ty)), + hir::TyKind::Slice(ref ty) => tcx.mk_slice(self.ast_ty_to_ty(ty)), hir::TyKind::Ptr(ref mt) => { - tcx.mk_ptr(ty::TypeAndMut { ty: self.ast_ty_to_ty(&mt.ty), mutbl: mt.mutbl }) + tcx.mk_ptr(ty::TypeAndMut { ty: self.ast_ty_to_ty(mt.ty), mutbl: mt.mutbl }) } hir::TyKind::Rptr(ref region, ref mt) => { let r = self.ast_region_to_region(region, None); debug!(?r); - let t = self.ast_ty_to_ty_inner(&mt.ty, true); + let t = self.ast_ty_to_ty_inner(mt.ty, true); tcx.mk_ref(r, ty::TypeAndMut { ty: t, mutbl: mt.mutbl }) } hir::TyKind::Never => tcx.types.never, - hir::TyKind::Tup(ref fields) => { - tcx.mk_tup(fields.iter().map(|t| self.ast_ty_to_ty(&t))) - } - hir::TyKind::BareFn(ref bf) => { - require_c_abi_if_c_variadic(tcx, &bf.decl, bf.abi, ast_ty.span); + hir::TyKind::Tup(fields) => tcx.mk_tup(fields.iter().map(|t| self.ast_ty_to_ty(t))), + hir::TyKind::BareFn(bf) => { + require_c_abi_if_c_variadic(tcx, bf.decl, bf.abi, ast_ty.span); tcx.mk_fn_ptr(self.ty_of_fn( ast_ty.hir_id, bf.unsafety, bf.abi, - &bf.decl, + bf.decl, &hir::Generics::empty(), None, Some(ast_ty), )) } - hir::TyKind::TraitObject(ref bounds, ref lifetime, _) => { + hir::TyKind::TraitObject(bounds, ref lifetime, _) => { self.conv_object_ty_poly_trait_ref(ast_ty.span, bounds, lifetime, borrowed) } hir::TyKind::Path(hir::QPath::Resolved(ref maybe_qself, ref path)) => { @@ -2298,7 +2334,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let opt_self_ty = maybe_qself.as_ref().map(|qself| self.ast_ty_to_ty(qself)); self.res_to_ty(opt_self_ty, path, false) } - hir::TyKind::OpaqueDef(item_id, ref lifetimes) => { + hir::TyKind::OpaqueDef(item_id, lifetimes) => { let opaque_ty = tcx.hir().item(item_id); let def_id = item_id.def_id.to_def_id(); @@ -2313,7 +2349,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { debug!(?qself, ?segment); let ty = self.ast_ty_to_ty(qself); - let res = if let hir::TyKind::Path(hir::QPath::Resolved(_, ref path)) = qself.kind { + let res = if let hir::TyKind::Path(hir::QPath::Resolved(_, path)) = qself.kind { path.res } else { Res::Err @@ -2338,7 +2374,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { hir::TyKind::Array(ref ty, ref length) => { let length_def_id = tcx.hir().local_def_id(length.hir_id); let length = ty::Const::from_anon_const(tcx, length_def_id); - let array_ty = tcx.mk_ty(ty::Array(self.ast_ty_to_ty(&ty), length)); + let array_ty = tcx.mk_ty(ty::Array(self.ast_ty_to_ty(ty), length)); self.normalize_ty(ast_ty.span, array_ty) } hir::TyKind::Typeof(ref e) => { @@ -2376,13 +2412,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let substs = InternalSubsts::for_item(tcx, def_id, |param, _| { if let Some(i) = (param.index as usize).checked_sub(generics.parent_count) { // Our own parameters are the resolved lifetimes. - match param.kind { - GenericParamDefKind::Lifetime - if let hir::GenericArg::Lifetime(lifetime) = &lifetimes[i] => - { + if let GenericParamDefKind::Lifetime = param.kind { + if let hir::GenericArg::Lifetime(lifetime) = &lifetimes[i] { self.ast_region_to_region(lifetime, None).into() + } else { + bug!() } - _ => bug!(), + } else { + bug!() } } else { match param.kind { @@ -2443,7 +2480,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let input_tys = decl.inputs.iter().map(|a| self.ty_of_arg(a, None)); let output_ty = match decl.output { - hir::FnRetTy::Return(ref output) => { + hir::FnRetTy::Return(output) => { visitor.visit_ty(output); self.ast_ty_to_ty(output) } diff --git a/compiler/rustc_typeck/src/check/_match.rs b/compiler/rustc_typeck/src/check/_match.rs index 01227cad33..6a231e719e 100644 --- a/compiler/rustc_typeck/src/check/_match.rs +++ b/compiler/rustc_typeck/src/check/_match.rs @@ -524,13 +524,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { for o in obligations { match o.predicate.kind().skip_binder() { ty::PredicateKind::Trait(t) => { - let pred = ty::PredicateKind::Trait(ty::TraitPredicate { - trait_ref: ty::TraitRef { - def_id: t.def_id(), - substs: self.infcx.tcx.mk_substs_trait(outer_ty, &[]), - }, - constness: t.constness, - }); + let pred = + ty::Binder::dummy(ty::PredicateKind::Trait(ty::TraitPredicate { + trait_ref: ty::TraitRef { + def_id: t.def_id(), + substs: self.infcx.tcx.mk_substs_trait(outer_ty, &[]), + }, + constness: t.constness, + })); let obl = Obligation::new( o.cause.clone(), self.param_env, diff --git a/compiler/rustc_typeck/src/check/callee.rs b/compiler/rustc_typeck/src/check/callee.rs index d101551085..06c4209879 100644 --- a/compiler/rustc_typeck/src/check/callee.rs +++ b/compiler/rustc_typeck/src/check/callee.rs @@ -17,7 +17,7 @@ use rustc_infer::{ use rustc_middle::ty::adjustment::{ Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability, }; -use rustc_middle::ty::subst::SubstsRef; +use rustc_middle::ty::subst::{Subst, SubstsRef}; use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable}; use rustc_span::symbol::{sym, Ident}; use rustc_span::Span; @@ -72,7 +72,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { arg_exprs: &'tcx [hir::Expr<'tcx>], expected: Expectation<'tcx>, ) -> Ty<'tcx> { - let original_callee_ty = self.check_expr(callee_expr); + let original_callee_ty = match &callee_expr.kind { + hir::ExprKind::Path(hir::QPath::Resolved(..) | hir::QPath::TypeRelative(..)) => self + .check_expr_with_expectation_and_args( + callee_expr, + Expectation::NoExpectation, + arg_exprs, + ), + _ => self.check_expr(callee_expr), + }; + let expr_ty = self.structurally_resolved_type(call_expr.span, original_callee_ty); let mut autoderef = self.autoderef(callee_expr.span, expr_ty); @@ -237,12 +246,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if borrow { // Check for &self vs &mut self in the method signature. Since this is either // the Fn or FnMut trait, it should be one of those. - let (region, mutbl) = - if let ty::Ref(r, _, mutbl) = method.sig.inputs()[0].kind() { - (r, mutbl) - } else { - span_bug!(call_expr.span, "input to call/call_mut is not a ref?"); - }; + let (region, mutbl) = if let ty::Ref(r, _, mutbl) = + method.sig.inputs()[0].kind() + { + (r, mutbl) + } else { + // The `fn`/`fn_mut` lang item is ill-formed, which should have + // caused an error elsewhere. + self.tcx + .sess + .delay_span_bug(call_expr.span, "input to call/call_mut is not a ref?"); + return None; + }; let mutbl = match mutbl { hir::Mutability::Not => AutoBorrowMutability::Not, @@ -302,6 +317,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) -> Ty<'tcx> { let (fn_sig, def_id) = match *callee_ty.kind() { ty::FnDef(def_id, subst) => { + let fn_sig = self.tcx.fn_sig(def_id).subst(self.tcx, subst); + // Unit testing: function items annotated with // `#[rustc_evaluate_where_clauses]` trigger special output // to let us test the trait evaluation system. @@ -314,7 +331,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let obligation = Obligation::new( ObligationCause::dummy_with_span(callee_expr.span), self.param_env, - predicate.clone(), + *predicate, ); let result = self.infcx.evaluate_obligation(&obligation); self.tcx @@ -327,7 +344,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .emit(); } } - (callee_ty.fn_sig(self.tcx), Some(def_id)) + (fn_sig, Some(def_id)) } ty::FnPtr(sig) => (sig, None), ref t => { @@ -341,6 +358,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } + let callee_ty = self.resolve_vars_if_possible(callee_ty); let mut err = type_error_struct!( self.tcx.sess, callee_expr.span, diff --git a/compiler/rustc_typeck/src/check/cast.rs b/compiler/rustc_typeck/src/check/cast.rs index 14550690e6..78849b276d 100644 --- a/compiler/rustc_typeck/src/check/cast.rs +++ b/compiler/rustc_typeck/src/check/cast.rs @@ -351,7 +351,7 @@ impl<'a, 'tcx> CastCheck<'tcx> { ); let mut sugg = None; let mut sugg_mutref = false; - if let ty::Ref(reg, _, mutbl) = *self.cast_ty.kind() { + if let ty::Ref(reg, cast_ty, mutbl) = *self.cast_ty.kind() { if let ty::RawPtr(TypeAndMut { ty: expr_ty, .. }) = *self.expr_ty.kind() { if fcx .try_coerce( @@ -362,10 +362,11 @@ impl<'a, 'tcx> CastCheck<'tcx> { ), self.cast_ty, AllowTwoPhase::No, + None, ) .is_ok() { - sugg = Some(format!("&{}*", mutbl.prefix_str())); + sugg = Some((format!("&{}*", mutbl.prefix_str()), cast_ty == expr_ty)); } } else if let ty::Ref(expr_reg, expr_ty, expr_mutbl) = *self.expr_ty.kind() { if expr_mutbl == Mutability::Not @@ -379,6 +380,7 @@ impl<'a, 'tcx> CastCheck<'tcx> { ), self.cast_ty, AllowTwoPhase::No, + None, ) .is_ok() { @@ -394,10 +396,11 @@ impl<'a, 'tcx> CastCheck<'tcx> { fcx.tcx.mk_ref(reg, TypeAndMut { ty: self.expr_ty, mutbl }), self.cast_ty, AllowTwoPhase::No, + None, ) .is_ok() { - sugg = Some(format!("&{}", mutbl.prefix_str())); + sugg = Some((format!("&{}", mutbl.prefix_str()), false)); } } else if let ty::RawPtr(TypeAndMut { mutbl, .. }) = *self.cast_ty.kind() { if fcx @@ -409,22 +412,51 @@ impl<'a, 'tcx> CastCheck<'tcx> { ), self.cast_ty, AllowTwoPhase::No, + None, ) .is_ok() { - sugg = Some(format!("&{}", mutbl.prefix_str())); + sugg = Some((format!("&{}", mutbl.prefix_str()), false)); } } if sugg_mutref { err.span_label(self.span, "invalid cast"); err.span_note(self.expr.span, "this reference is immutable"); err.span_note(self.cast_span, "trying to cast to a mutable reference type"); - } else if let Some(sugg) = sugg { + } else if let Some((sugg, remove_cast)) = sugg { err.span_label(self.span, "invalid cast"); - err.span_suggestion_verbose( - self.expr.span.shrink_to_lo(), + + let has_parens = fcx + .tcx + .sess + .source_map() + .span_to_snippet(self.expr.span) + .map_or(false, |snip| snip.starts_with('(')); + + // 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 mut suggestion = vec![(self.expr.span.shrink_to_lo(), sugg)]; + if needs_parens { + suggestion[0].1 += "("; + suggestion.push((self.expr.span.shrink_to_hi(), ")".to_string())); + } + if remove_cast { + suggestion.push(( + self.expr.span.shrink_to_hi().to(self.cast_span), + String::new(), + )); + } + + err.multipart_suggestion_verbose( "consider borrowing the value", - sugg, + suggestion, Applicability::MachineApplicable, ); } else if !matches!( @@ -434,7 +466,7 @@ impl<'a, 'tcx> CastCheck<'tcx> { let mut label = true; // Check `impl From for self.cast_ty {}` for accurate suggestion: if let Ok(snippet) = fcx.tcx.sess.source_map().span_to_snippet(self.expr.span) { - if let Some(from_trait) = fcx.tcx.get_diagnostic_item(sym::from_trait) { + if let Some(from_trait) = fcx.tcx.get_diagnostic_item(sym::From) { let ty = fcx.resolve_vars_if_possible(self.cast_ty); // Erase regions to avoid panic in `prove_value` when calling // `type_implements_trait`. @@ -666,6 +698,7 @@ impl<'a, 'tcx> CastCheck<'tcx> { self.expr_ty, fcx.tcx.mk_fn_ptr(f), AllowTwoPhase::No, + None, ); if let Err(TypeError::IntrinsicCast) = res { return Err(CastError::IllegalCast); @@ -829,7 +862,7 @@ impl<'a, 'tcx> CastCheck<'tcx> { // Coerce to a raw pointer so that we generate AddressOf in MIR. let array_ptr_type = fcx.tcx.mk_ptr(m_expr); - fcx.try_coerce(self.expr, self.expr_ty, array_ptr_type, AllowTwoPhase::No) + fcx.try_coerce(self.expr, self.expr_ty, array_ptr_type, AllowTwoPhase::No, None) .unwrap_or_else(|_| { bug!( "could not cast from reference to array to pointer to array ({:?} to {:?})", @@ -861,7 +894,7 @@ impl<'a, 'tcx> CastCheck<'tcx> { } fn try_coercion_cast(&self, fcx: &FnCtxt<'a, 'tcx>) -> Result<(), ty::error::TypeError<'_>> { - match fcx.try_coerce(self.expr, self.expr_ty, self.cast_ty, AllowTwoPhase::No) { + match fcx.try_coerce(self.expr, self.expr_ty, self.cast_ty, AllowTwoPhase::No, None) { Ok(_) => Ok(()), Err(err) => Err(err), } diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs index 8a91738a2c..66316214e5 100644 --- a/compiler/rustc_typeck/src/check/check.rs +++ b/compiler/rustc_typeck/src/check/check.rs @@ -31,7 +31,7 @@ use std::ops::ControlFlow; pub fn check_wf_new(tcx: TyCtxt<'_>) { let visit = wfcheck::CheckTypeWellFormedVisitor::new(tcx); - tcx.hir().krate().par_visit_all_item_likes(&visit); + tcx.hir().par_visit_all_item_likes(&visit); } pub(super) fn check_abi(tcx: TyCtxt<'_>, hir_id: hir::HirId, span: Span, abi: Abi) { @@ -58,7 +58,7 @@ pub(super) fn check_abi(tcx: TyCtxt<'_>, hir_id: hir::HirId, span: Span, abi: Ab tcx.sess, span, E0781, - "the `\"C-cmse-nonsecure-call\"` ABI is only allowed on function pointers." + "the `\"C-cmse-nonsecure-call\"` ABI is only allowed on function pointers" ) .emit() } @@ -70,6 +70,7 @@ pub(super) fn check_abi(tcx: TyCtxt<'_>, hir_id: hir::HirId, span: Span, abi: Ab /// /// * ... /// * inherited: other fields inherited from the enclosing fn (if any) +#[instrument(skip(inherited, body), level = "debug")] pub(super) fn check_fn<'a, 'tcx>( inherited: &'a Inherited<'a, 'tcx>, param_env: ty::ParamEnv<'tcx>, @@ -82,8 +83,6 @@ pub(super) fn check_fn<'a, 'tcx>( ) -> (FnCtxt<'a, 'tcx>, Option>) { let mut fn_sig = fn_sig; - debug!("check_fn(sig={:?}, fn_id={}, param_env={:?})", fn_sig, fn_id, param_env); - // Create the function context. This is either derived from scratch or, // in the case of closures, based on the outer context. let mut fcx = FnCtxt::new(inherited, param_env, body.value.hir_id); @@ -214,7 +213,7 @@ pub(super) fn check_fn<'a, 'tcx>( fcx.require_type_is_sized(declared_ret_ty, decl.output.span(), traits::SizedReturnType); } else { fcx.require_type_is_sized(declared_ret_ty, decl.output.span(), traits::SizedReturnType); - fcx.check_return_expr(&body.value); + fcx.check_return_expr(&body.value, false); } fcx.in_tail_expr = false; @@ -241,32 +240,16 @@ pub(super) fn check_fn<'a, 'tcx>( // we saw and assigning it to the expected return type. This isn't // really expected to fail, since the coercions would have failed // earlier when trying to find a LUB. - // - // However, the behavior around `!` is sort of complex. In the - // event that the `actual_return_ty` comes back as `!`, that - // indicates that the fn either does not return or "returns" only - // values of type `!`. In this case, if there is an expected - // return type that is *not* `!`, that should be ok. But if the - // return type is being inferred, we want to "fallback" to `!`: - // - // let x = move || panic!(); - // - // To allow for that, I am creating a type variable with diverging - // fallback. This was deemed ever so slightly better than unifying - // the return value with `!` because it allows for the caller to - // make more assumptions about the return type (e.g., they could do - // - // let y: Option = Some(x()); - // - // which would then cause this return type to become `u32`, not - // `!`). let coercion = fcx.ret_coercion.take().unwrap().into_inner(); let mut actual_return_ty = coercion.complete(&fcx); - if actual_return_ty.is_never() { - actual_return_ty = fcx.next_diverging_ty_var(TypeVariableOrigin { - kind: TypeVariableOriginKind::DivergingFn, - span, - }); + debug!("actual_return_ty = {:?}", actual_return_ty); + if let ty::Dynamic(..) = declared_ret_ty.kind() { + // We have special-cased the case where the function is declared + // `-> dyn Foo` and we don't actually relate it to the + // `fcx.ret_coercion`, so just substitute a type variable. + actual_return_ty = + fcx.next_ty_var(TypeVariableOrigin { kind: TypeVariableOriginKind::DynReturnFn, span }); + debug!("actual_return_ty replaced with {:?}", actual_return_ty); } fcx.demand_suptype(span, revealed_ret_ty, actual_return_ty); @@ -688,7 +671,7 @@ fn check_opaque_meets_bounds<'tcx>( // Finally, resolve all regions. This catches wily misuses of // lifetime parameters. let fcx = FnCtxt::new(&inh, param_env, hir_id); - fcx.regionck_item(hir_id, span, &[]); + fcx.regionck_item(hir_id, span, FxHashSet::default()); }); } @@ -906,7 +889,7 @@ pub(super) fn check_impl_items_against_trait<'tcx>( full_impl_span: Span, impl_id: LocalDefId, impl_trait_ref: ty::TraitRef<'tcx>, - impl_item_refs: &[hir::ImplItemRef<'_>], + impl_item_refs: &[hir::ImplItemRef], ) { // If the trait reference itself is erroneous (so the compilation is going // to fail), skip checking the items here -- the `impl_item` table in `tcx` diff --git a/compiler/rustc_typeck/src/check/closure.rs b/compiler/rustc_typeck/src/check/closure.rs index 65ba1c08b6..410ac24b1f 100644 --- a/compiler/rustc_typeck/src/check/closure.rs +++ b/compiler/rustc_typeck/src/check/closure.rs @@ -33,6 +33,7 @@ struct ClosureSignatures<'tcx> { } impl<'a, 'tcx> FnCtxt<'a, 'tcx> { + #[instrument(skip(self, expr, _capture, decl, body_id), level = "debug")] pub fn check_expr_closure( &self, expr: &hir::Expr<'_>, @@ -42,7 +43,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { gen: Option, expected: Expectation<'tcx>, ) -> Ty<'tcx> { - debug!("check_expr_closure(expr={:?},expected={:?})", expr, expected); + trace!("decl = {:#?}", decl); + trace!("expr = {:#?}", expr); // It's always helpful for inference if we know the kind of // closure sooner rather than later, so first examine the expected @@ -55,6 +57,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.check_closure(expr, expected_kind, decl, body, gen, expected_sig) } + #[instrument(skip(self, expr, body, decl), level = "debug")] fn check_closure( &self, expr: &hir::Expr<'_>, @@ -64,14 +67,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { gen: Option, expected_sig: Option>, ) -> Ty<'tcx> { - debug!("check_closure(opt_kind={:?}, expected_sig={:?})", opt_kind, expected_sig); - + trace!("decl = {:#?}", decl); let expr_def_id = self.tcx.hir().local_def_id(expr.hir_id); + debug!(?expr_def_id); let ClosureSignatures { bound_sig, liberated_sig } = self.sig_of_closure(expr.hir_id, expr_def_id.to_def_id(), decl, body, expected_sig); - debug!("check_closure: ty_of_closure returns {:?}", liberated_sig); + debug!(?bound_sig, ?liberated_sig); let return_type_pre_known = !liberated_sig.output().is_ty_infer(); @@ -130,10 +133,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) }); - debug!( - "check_closure: expr_def_id={:?}, sig={:?}, opt_kind={:?}", - expr_def_id, sig, opt_kind - ); + debug!(?sig, ?opt_kind); let closure_kind_ty = match opt_kind { Some(kind) => kind.to_ty(self.tcx), @@ -159,19 +159,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let closure_type = self.tcx.mk_closure(expr_def_id.to_def_id(), closure_substs.substs); - debug!("check_closure: expr.hir_id={:?} closure_type={:?}", expr.hir_id, closure_type); + debug!(?expr.hir_id, ?closure_type); closure_type } /// Given the expected type, figures out what it can about this closure we /// are about to type check: + #[instrument(skip(self), level = "debug")] fn deduce_expectations_from_expected_type( &self, expected_ty: Ty<'tcx>, ) -> (Option>, Option) { - debug!("deduce_expectations_from_expected_type(expected_ty={:?})", expected_ty); - match *expected_ty.kind() { ty::Dynamic(ref object_type, ..) => { let sig = object_type.projection_bounds().find_map(|pb| { @@ -314,6 +313,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// If there is no expected signature, then we will convert the /// types that the user gave into a signature. + #[instrument(skip(self, hir_id, expr_def_id, decl, body), level = "debug")] fn sig_of_closure_no_expectation( &self, hir_id: hir::HirId, @@ -321,8 +321,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { decl: &hir::FnDecl<'_>, body: &hir::Body<'_>, ) -> ClosureSignatures<'tcx> { - debug!("sig_of_closure_no_expectation()"); - let bound_sig = self.supplied_sig_of_closure(hir_id, expr_def_id, decl, body); self.closure_sigs(expr_def_id, body, bound_sig) @@ -375,6 +373,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// - `expected_sig`: the expected signature (if any). Note that /// this is missing a binder: that is, there may be late-bound /// regions with depth 1, which are bound then by the closure. + #[instrument(skip(self, hir_id, expr_def_id, decl, body), level = "debug")] fn sig_of_closure_with_expectation( &self, hir_id: hir::HirId, @@ -383,8 +382,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { body: &hir::Body<'_>, expected_sig: ExpectedSig<'tcx>, ) -> ClosureSignatures<'tcx> { - debug!("sig_of_closure_with_expectation(expected_sig={:?})", expected_sig); - // Watch out for some surprises and just ignore the // expectation if things don't see to match up with what we // expect. @@ -553,6 +550,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// types that the user gave into a signature. /// /// Also, record this closure signature for later. + #[instrument(skip(self, decl, body), level = "debug")] fn supplied_sig_of_closure( &self, hir_id: hir::HirId, @@ -562,10 +560,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) -> ty::PolyFnSig<'tcx> { let astconv: &dyn AstConv<'_> = self; - debug!( - "supplied_sig_of_closure(decl={:?}, body.generator_kind={:?})", - decl, body.generator_kind, - ); + trace!("decl = {:#?}", decl); + debug!(?body.generator_kind); let bound_vars = self.tcx.late_bound_vars(hir_id); @@ -578,7 +574,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // we expect the return type of the block to match that of the enclosing // function. Some(hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Fn)) => { - debug!("supplied_sig_of_closure: closure is async fn body"); + debug!("closure is async fn body"); self.deduce_future_output_from_obligations(expr_def_id).unwrap_or_else(|| { // AFAIK, deducing the future output // always succeeds *except* in error cases @@ -606,7 +602,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { bound_vars, ); - debug!("supplied_sig_of_closure: result={:?}", result); + debug!(?result); let c_result = self.inh.infcx.canonicalize_response(result); self.typeck_results.borrow_mut().user_provided_sigs.insert(expr_def_id, c_result); diff --git a/compiler/rustc_typeck/src/check/coercion.rs b/compiler/rustc_typeck/src/check/coercion.rs index 3bfab9d513..a87318ff34 100644 --- a/compiler/rustc_typeck/src/check/coercion.rs +++ b/compiler/rustc_typeck/src/check/coercion.rs @@ -42,7 +42,7 @@ use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::infer::{Coercion, InferOk, InferResult}; -use rustc_infer::traits::Obligation; +use rustc_infer::traits::{Obligation, TraitEngine, TraitEngineExt}; use rustc_middle::lint::in_external_macro; use rustc_middle::ty::adjustment::{ Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability, PointerCast, @@ -54,7 +54,7 @@ use rustc_middle::ty::subst::SubstsRef; use rustc_middle::ty::{self, ToPredicate, Ty, TypeAndMut}; use rustc_session::parse::feature_err; use rustc_span::symbol::sym; -use rustc_span::{self, BytePos, Span}; +use rustc_span::{self, BytePos, DesugaringKind, Span}; use rustc_target::spec::abi::Abi; use rustc_trait_selection::traits::error_reporting::InferCtxtExt; use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode}; @@ -146,6 +146,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { .and_then(|InferOk { value: ty, obligations }| success(f(ty), ty, obligations)) } + #[instrument(skip(self))] fn coerce(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> CoerceResult<'tcx> { // First, remove any resolved type variables (at the top level, at least): let a = self.shallow_resolve(a); @@ -159,24 +160,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { // Coercing from `!` to any type is allowed: if a.is_never() { - // Subtle: If we are coercing from `!` to `?T`, where `?T` is an unbound - // type variable, we want `?T` to fallback to `!` if not - // otherwise constrained. An example where this arises: - // - // let _: Option = Some({ return; }); - // - // here, we would coerce from `!` to `?T`. - return if b.is_ty_var() { - // Micro-optimization: no need for this if `b` is - // already resolved in some way. - let diverging_ty = self.next_diverging_ty_var(TypeVariableOrigin { - kind: TypeVariableOriginKind::AdjustmentType, - span: self.cause.span, - }); - self.coerce_from_inference_variable(diverging_ty, b, simple(Adjust::NeverToAny)) - } else { - success(simple(Adjust::NeverToAny)(b), b, vec![]) - }; + return success(simple(Adjust::NeverToAny)(b), b, vec![]); } // Coercing *from* an unresolved inference variable means that @@ -273,10 +257,10 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { obligations.push(Obligation::new( self.cause.clone(), self.param_env, - ty::PredicateKind::Coerce(ty::CoercePredicate { + ty::Binder::dummy(ty::PredicateKind::Coerce(ty::CoercePredicate { a: source_ty, b: target_ty, - }) + })) .to_predicate(self.tcx()), )); } @@ -499,12 +483,11 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { // &[T; n] or &mut [T; n] -> &[T] // or &mut [T; n] -> &mut [T] // or &Concrete -> &Trait, etc. + #[instrument(skip(self), level = "debug")] fn coerce_unsized(&self, mut source: Ty<'tcx>, mut target: Ty<'tcx>) -> CoerceResult<'tcx> { - debug!("coerce_unsized(source={:?}, target={:?})", source, target); - source = self.shallow_resolve(source); target = self.shallow_resolve(target); - debug!("coerce_unsized: resolved source={:?} target={:?}", source, target); + debug!(?source, ?target); // These 'if' statements require some explanation. // The `CoerceUnsized` trait is special - it is only @@ -707,13 +690,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { // Object safety violations or miscellaneous. Err(err) => { - self.report_selection_error( - obligation.clone(), - &obligation, - &err, - false, - false, - ); + self.report_selection_error(obligation.clone(), &obligation, &err, false); // Treat this like an obligation and follow through // with the unsizing - the lack of a coercion should // be silent, as it causes a type mismatch later. @@ -941,11 +918,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expr_ty: Ty<'tcx>, target: Ty<'tcx>, allow_two_phase: AllowTwoPhase, + cause: Option>, ) -> RelateResult<'tcx, Ty<'tcx>> { let source = self.resolve_vars_with_obligations(expr_ty); debug!("coercion::try({:?}: {:?} -> {:?})", expr, source, target); - let cause = self.cause(expr.span, ObligationCauseCode::ExprAssignable); + let cause = + cause.unwrap_or_else(|| self.cause(expr.span, ObligationCauseCode::ExprAssignable)); let coerce = Coerce::new(self, cause, allow_two_phase); let ok = self.commit_if_ok(|_| coerce.coerce(source, target))?; @@ -955,14 +934,25 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } /// Same as `try_coerce()`, but without side-effects. + /// + /// Returns false if the coercion creates any obligations that result in + /// errors. pub fn can_coerce(&self, expr_ty: Ty<'tcx>, target: Ty<'tcx>) -> bool { let source = self.resolve_vars_with_obligations(expr_ty); - debug!("coercion::can({:?} -> {:?})", source, target); + debug!("coercion::can_with_predicates({:?} -> {:?})", source, target); let cause = self.cause(rustc_span::DUMMY_SP, ObligationCauseCode::ExprAssignable); // We don't ever need two-phase here since we throw out the result of the coercion let coerce = Coerce::new(self, cause, AllowTwoPhase::No); - self.probe(|_| coerce.coerce(source, target)).is_ok() + self.probe(|_| { + let ok = match coerce.coerce(source, target) { + Ok(ok) => ok, + _ => return false, + }; + let mut fcx = traits::FulfillmentContext::new_in_snapshot(); + fcx.register_predicate_obligations(self, ok.obligations); + fcx.select_where_possible(&self).is_ok() + }) } /// Given a type and a target type, this function will calculate and return @@ -1003,6 +993,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { exprs.len() ); + // The following check fixes #88097, where the compiler erroneously + // attempted to coerce a closure type to itself via a function pointer. + if prev_ty == new_ty { + return Ok(prev_ty); + } + // Special-case that coercion alone cannot handle: // Function items or non-capturing closures of differing IDs or InternalSubsts. let (a_sig, b_sig) = { @@ -1363,7 +1359,13 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { // Special-case the first expression we are coercing. // To be honest, I'm not entirely sure why we do this. // We don't allow two-phase borrows, see comment in try_find_coercion_lub for why - fcx.try_coerce(expression, expression_ty, self.expected_ty, AllowTwoPhase::No) + fcx.try_coerce( + expression, + expression_ty, + self.expected_ty, + AllowTwoPhase::No, + Some(cause.clone()), + ) } else { match self.expressions { Expressions::Dynamic(ref exprs) => fcx.try_find_coercion_lub( @@ -1494,21 +1496,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { fcx.emit_coerce_suggestions(&mut err, expr, found, expected, None); } - // Error possibly reported in `check_assign` so avoid emitting error again. - let assign_to_bool = expression - // #67273: Use initial expected type as opposed to `expected`. - // Otherwise we end up using prior coercions in e.g. a `match` expression: - // ``` - // match i { - // 0 => true, // Because of this... - // 1 => i = 1, // ...`expected == bool` now, but not when checking `i = 1`. - // _ => (), - // }; - // ``` - .filter(|e| fcx.is_assign_to_bool(e, self.expected_ty())) - .is_some(); - - err.emit_unless(assign_to_bool || unsized_return); + err.emit_unless(unsized_return); self.final_ty = Some(fcx.tcx.ty_error()); } @@ -1546,8 +1534,10 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { // If the block is from an external macro or try (`?`) desugaring, then // do not suggest adding a semicolon, because there's nowhere to put it. // See issues #81943 and #87051. - if cond_expr.span.desugaring_kind().is_none() - && !in_external_macro(fcx.tcx.sess, cond_expr.span) + if matches!( + cond_expr.span.desugaring_kind(), + None | Some(DesugaringKind::WhileLoop) + ) && !in_external_macro(fcx.tcx.sess, cond_expr.span) && !matches!( cond_expr.kind, hir::ExprKind::Match(.., hir::MatchSource::TryDesugar) diff --git a/compiler/rustc_typeck/src/check/compare_method.rs b/compiler/rustc_typeck/src/check/compare_method.rs index d59291b8fd..5e12497f34 100644 --- a/compiler/rustc_typeck/src/check/compare_method.rs +++ b/compiler/rustc_typeck/src/check/compare_method.rs @@ -1,4 +1,5 @@ use crate::errors::LifetimesOrBoundsMismatchOnTrait; +use rustc_data_structures::stable_set::FxHashSet; use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticId, ErrorReported}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; @@ -250,7 +251,7 @@ fn compare_predicate_entailment<'tcx>( // Compute placeholder form of impl and trait method tys. let tcx = infcx.tcx; - let mut wf_tys = vec![]; + let mut wf_tys = FxHashSet::default(); let (impl_sig, _) = infcx.replace_bound_vars_with_fresh_vars( impl_m_span, @@ -265,14 +266,9 @@ fn compare_predicate_entailment<'tcx>( // First liberate late bound regions and subst placeholders let trait_sig = tcx.liberate_late_bound_regions(impl_m.def_id, tcx.fn_sig(trait_m.def_id)); let trait_sig = trait_sig.subst(tcx, trait_to_placeholder_substs); - // Next, add all inputs and output as well-formed tys. Importantly, - // we have to do this before normalization, since the normalized ty may - // not contain the input parameters. See issue #87748. - wf_tys.extend(trait_sig.inputs_and_output.iter()); let trait_sig = inh.normalize_associated_types_in(impl_m_span, impl_m_hir_id, param_env, trait_sig); - // Also add the resulting inputs and output as well-formed. - // This probably isn't strictly necessary. + // Add the resulting inputs and output as well-formed. wf_tys.extend(trait_sig.inputs_and_output.iter()); let trait_fty = tcx.mk_fn_ptr(ty::Binder::dummy(trait_sig)); @@ -398,7 +394,7 @@ fn compare_predicate_entailment<'tcx>( // Finally, resolve all regions. This catches wily misuses of // lifetime parameters. let fcx = FnCtxt::new(&inh, param_env, impl_m_hir_id); - fcx.regionck_item(impl_m_hir_id, impl_m_span, &wf_tys); + fcx.regionck_item(impl_m_hir_id, impl_m_span, wf_tys); Ok(()) }) @@ -1098,7 +1094,7 @@ crate fn compare_const_impl<'tcx>( } let fcx = FnCtxt::new(&inh, param_env, impl_c_hir_id); - fcx.regionck_item(impl_c_hir_id, impl_c_span, &[]); + fcx.regionck_item(impl_c_hir_id, impl_c_span, FxHashSet::default()); }); } @@ -1216,7 +1212,7 @@ fn compare_type_predicate_entailment<'tcx>( // Finally, resolve all regions. This catches wily misuses of // lifetime parameters. let fcx = FnCtxt::new(&inh, param_env, impl_ty_hir_id); - fcx.regionck_item(impl_ty_hir_id, impl_ty_span, &[]); + fcx.regionck_item(impl_ty_hir_id, impl_ty_span, FxHashSet::default()); Ok(()) }) @@ -1436,10 +1432,10 @@ pub fn check_type_bounds<'tcx>( // lifetime parameters. let fcx = FnCtxt::new(&inh, param_env, impl_ty_hir_id); let implied_bounds = match impl_ty.container { - ty::TraitContainer(_) => vec![], + ty::TraitContainer(_) => FxHashSet::default(), ty::ImplContainer(def_id) => fcx.impl_implied_bounds(def_id, impl_ty_span), }; - fcx.regionck_item(impl_ty_hir_id, impl_ty_span, &implied_bounds); + fcx.regionck_item(impl_ty_hir_id, impl_ty_span, implied_bounds); Ok(()) }) diff --git a/compiler/rustc_typeck/src/check/demand.rs b/compiler/rustc_typeck/src/check/demand.rs index 808685d7fa..540365956a 100644 --- a/compiler/rustc_typeck/src/check/demand.rs +++ b/compiler/rustc_typeck/src/check/demand.rs @@ -17,7 +17,6 @@ use rustc_span::{BytePos, Span}; use super::method::probe; -use std::fmt; use std::iter; impl<'a, 'tcx> FnCtxt<'a, 'tcx> { @@ -60,6 +59,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.demand_suptype_with_origin(&self.misc(sp), expected, actual) } + #[instrument(skip(self), level = "debug")] pub fn demand_suptype_with_origin( &self, cause: &ObligationCause<'tcx>, @@ -135,22 +135,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) -> (Ty<'tcx>, Option>) { let expected = self.resolve_vars_with_obligations(expected); - let e = match self.try_coerce(expr, checked_ty, expected, allow_two_phase) { + let e = match self.try_coerce(expr, checked_ty, expected, allow_two_phase, None) { Ok(ty) => return (ty, None), Err(e) => e, }; + self.set_tainted_by_errors(); 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); - if self.is_assign_to_bool(expr, expected) { - // Error reported in `check_assign` so avoid emitting error again. - err.delay_as_bug(); - return (expected, None); - } - self.emit_coerce_suggestions(&mut err, expr, expr_ty, expected, expected_ty_expr); (expected, Some(err)) @@ -172,14 +167,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - /// Returns whether the expected type is `bool` and the expression is `x = y`. - pub fn is_assign_to_bool(&self, expr: &hir::Expr<'_>, expected: Ty<'tcx>) -> bool { - if let hir::ExprKind::Assign(..) = expr.kind { - return expected == self.tcx.types.bool; - } - false - } - /// If the expected type is an enum (Issue #55250) with any variants whose /// sole field is of the found type, suggest such variants. (Issue #42764) fn suggest_compatible_variants( @@ -589,7 +576,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // E.g. for `&format!("")`, where we want the span to the // `format!()` invocation instead of its expansion. if let Some(call_span) = - iter::successors(Some(expr.span), |s| s.parent()).find(|&s| sp.contains(s)) + iter::successors(Some(expr.span), |s| s.parent_callsite()) + .find(|&s| sp.contains(s)) { if sm.span_to_snippet(call_span).is_ok() { return Some(( @@ -771,9 +759,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // For now, don't suggest casting with `as`. let can_cast = false; - let prefix = if let Some(hir::Node::Expr(hir::Expr { - kind: hir::ExprKind::Struct(_, fields, _), - .. + let mut sugg = vec![]; + + if let Some(hir::Node::Expr(hir::Expr { + kind: hir::ExprKind::Struct(_, fields, _), .. })) = self.tcx.hir().find(self.tcx.hir().get_parent_node(expr.hir_id)) { // `expr` is a literal field for a struct, only suggest if appropriate @@ -782,12 +771,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .find(|field| field.expr.hir_id == expr.hir_id && field.is_shorthand) { // This is a field literal - Some(field) => format!("{}: ", field.ident), + Some(field) => { + sugg.push((field.ident.span.shrink_to_lo(), format!("{}: ", field.ident))); + } // Likely a field was meant, but this field wasn't found. Do not suggest anything. None => return false, } - } else { - String::new() }; if let hir::ExprKind::Call(path, args) = &expr.kind { @@ -842,28 +831,38 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { checked_ty, expected_ty, ); - let with_opt_paren: fn(&dyn fmt::Display) -> String = - if expr.precedence().order() < PREC_POSTFIX { - |s| format!("({})", s) - } else { - |s| s.to_string() - }; + let close_paren = if expr.precedence().order() < PREC_POSTFIX { + sugg.push((expr.span.shrink_to_lo(), "(".to_string())); + ")" + } else { + "" + }; - let cast_suggestion = format!("{}{} as {}", prefix, with_opt_paren(&src), expected_ty); - let into_suggestion = format!("{}{}.into()", prefix, with_opt_paren(&src)); - let suffix_suggestion = with_opt_paren(&format_args!( - "{}{}", + let mut cast_suggestion = sugg.clone(); + cast_suggestion + .push((expr.span.shrink_to_hi(), format!("{} as {}", close_paren, expected_ty))); + let mut into_suggestion = sugg.clone(); + into_suggestion.push((expr.span.shrink_to_hi(), format!("{}.into()", close_paren))); + let mut suffix_suggestion = sugg.clone(); + suffix_suggestion.push(( if matches!( (&expected_ty.kind(), &checked_ty.kind()), (ty::Int(_) | ty::Uint(_), ty::Float(_)) ) { // Remove fractional part from literal, for example `42.0f32` into `42` let src = src.trim_end_matches(&checked_ty.to_string()); - src.split('.').next().unwrap() + let len = src.split('.').next().unwrap().len(); + expr.span.with_lo(expr.span.lo() + BytePos(len as u32)) } else { - src.trim_end_matches(&checked_ty.to_string()) + let len = src.trim_end_matches(&checked_ty.to_string()).len(); + expr.span.with_lo(expr.span.lo() + BytePos(len as u32)) + }, + if expr.precedence().order() < PREC_POSTFIX { + // Readd `)` + format!("{})", expected_ty) + } else { + expected_ty.to_string() }, - expected_ty, )); let literal_is_ty_suffixed = |expr: &hir::Expr<'_>| { if let hir::ExprKind::Lit(lit) = &expr.kind { lit.node.is_suffixed() } else { false } @@ -890,22 +889,32 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .ok() .map(|src| (expr, src)) }); - let (span, msg, suggestion) = if let (Some((lhs_expr, lhs_src)), false) = + let (msg, suggestion) = if let (Some((lhs_expr, lhs_src)), false) = (lhs_expr_and_src, exp_to_found_is_fallible) { let msg = format!( "you can convert `{}` from `{}` to `{}`, matching the type of `{}`", lhs_src, expected_ty, checked_ty, src ); - let suggestion = format!("{}::from({})", checked_ty, lhs_src); - (lhs_expr.span, msg, suggestion) + let suggestion = vec![ + (lhs_expr.span.shrink_to_lo(), format!("{}::from(", checked_ty)), + (lhs_expr.span.shrink_to_hi(), ")".to_string()), + ]; + (msg, suggestion) } else { let msg = format!("{} and panic if the converted value doesn't fit", msg); - let suggestion = - format!("{}{}.try_into().unwrap()", prefix, with_opt_paren(&src)); - (expr.span, msg, suggestion) + let mut suggestion = sugg.clone(); + suggestion.push(( + expr.span.shrink_to_hi(), + format!("{}.try_into().unwrap()", close_paren), + )); + (msg, suggestion) }; - err.span_suggestion(span, &msg, suggestion, Applicability::MachineApplicable); + err.multipart_suggestion_verbose( + &msg, + suggestion, + Applicability::MachineApplicable, + ); }; let suggest_to_change_suffix_or_into = @@ -943,7 +952,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } else { into_suggestion.clone() }; - err.span_suggestion(expr.span, msg, suggestion, Applicability::MachineApplicable); + err.multipart_suggestion_verbose(msg, suggestion, Applicability::MachineApplicable); }; match (&expected_ty.kind(), &checked_ty.kind()) { @@ -997,16 +1006,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if found.bit_width() < exp.bit_width() { suggest_to_change_suffix_or_into(err, false, true); } else if literal_is_ty_suffixed(expr) { - err.span_suggestion( - expr.span, + err.multipart_suggestion_verbose( &lit_msg, suffix_suggestion, Applicability::MachineApplicable, ); } else if can_cast { // Missing try_into implementation for `f64` to `f32` - err.span_suggestion( - expr.span, + err.multipart_suggestion_verbose( &format!("{}, producing the closest possible value", cast_msg), cast_suggestion, Applicability::MaybeIncorrect, // lossy conversion @@ -1016,16 +1023,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } (&ty::Uint(_) | &ty::Int(_), &ty::Float(_)) => { if literal_is_ty_suffixed(expr) { - err.span_suggestion( - expr.span, + err.multipart_suggestion_verbose( &lit_msg, suffix_suggestion, Applicability::MachineApplicable, ); } else if can_cast { // Missing try_into implementation for `{float}` to `{integer}` - err.span_suggestion( - expr.span, + err.multipart_suggestion_verbose( &format!("{}, rounding the float towards zero", msg), cast_suggestion, Applicability::MaybeIncorrect, // lossy conversion @@ -1036,8 +1041,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { (&ty::Float(ref exp), &ty::Uint(ref found)) => { // if `found` is `None` (meaning found is `usize`), don't suggest `.into()` if exp.bit_width() > found.bit_width().unwrap_or(256) { - err.span_suggestion( - expr.span, + err.multipart_suggestion_verbose( &format!( "{}, producing the floating point representation of the integer", msg, @@ -1046,16 +1050,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Applicability::MachineApplicable, ); } else if literal_is_ty_suffixed(expr) { - err.span_suggestion( - expr.span, + err.multipart_suggestion_verbose( &lit_msg, suffix_suggestion, Applicability::MachineApplicable, ); } else { // Missing try_into implementation for `{integer}` to `{float}` - err.span_suggestion( - expr.span, + err.multipart_suggestion_verbose( &format!( "{}, producing the floating point representation of the integer, rounded if necessary", @@ -1070,8 +1072,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { (&ty::Float(ref exp), &ty::Int(ref found)) => { // if `found` is `None` (meaning found is `isize`), don't suggest `.into()` if exp.bit_width() > found.bit_width().unwrap_or(256) { - err.span_suggestion( - expr.span, + err.multipart_suggestion_verbose( &format!( "{}, producing the floating point representation of the integer", &msg, @@ -1080,16 +1081,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Applicability::MachineApplicable, ); } else if literal_is_ty_suffixed(expr) { - err.span_suggestion( - expr.span, + err.multipart_suggestion_verbose( &lit_msg, suffix_suggestion, Applicability::MachineApplicable, ); } else { // Missing try_into implementation for `{integer}` to `{float}` - err.span_suggestion( - expr.span, + err.multipart_suggestion_verbose( &format!( "{}, producing the floating point representation of the integer, \ rounded if necessary", diff --git a/compiler/rustc_typeck/src/check/dropck.rs b/compiler/rustc_typeck/src/check/dropck.rs index fd150978f0..9e2460b570 100644 --- a/compiler/rustc_typeck/src/check/dropck.rs +++ b/compiler/rustc_typeck/src/check/dropck.rs @@ -239,8 +239,12 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>( ty::PredicateKind::ConstEvaluatable(a), ty::PredicateKind::ConstEvaluatable(b), ) => tcx.try_unify_abstract_consts((a, b)), - (ty::PredicateKind::TypeOutlives(a), ty::PredicateKind::TypeOutlives(b)) => { - relator.relate(predicate.rebind(a.0), p.rebind(b.0)).is_ok() + ( + ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(ty_a, lt_a)), + ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(ty_b, lt_b)), + ) => { + relator.relate(predicate.rebind(ty_a), p.rebind(ty_b)).is_ok() + && relator.relate(predicate.rebind(lt_a), p.rebind(lt_b)).is_ok() } _ => predicate == p, } diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs index 64594a82ec..2d0a4068fb 100644 --- a/compiler/rustc_typeck/src/check/expr.rs +++ b/compiler/rustc_typeck/src/check/expr.rs @@ -77,7 +77,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { !self.typeck_results.borrow().adjustments().contains_key(expr.hir_id), "expression with never type wound up being adjusted" ); - let adj_ty = self.next_diverging_ty_var(TypeVariableOrigin { + let adj_ty = self.next_ty_var(TypeVariableOrigin { kind: TypeVariableOriginKind::AdjustmentType, span: expr.span, }); @@ -92,8 +92,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let expr = expr.peel_drop_temps(); self.suggest_deref_ref_or_into(&mut err, expr, expected_ty, ty, None); extend_err(&mut err); - // Error possibly reported in `check_assign` so avoid emitting error again. - err.emit_unless(self.is_assign_to_bool(expr, expected_ty)); + err.emit(); } ty } @@ -156,11 +155,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Note that inspecting a type's structure *directly* may expose the fact /// that there are actually multiple representations for `Error`, so avoid /// that when err needs to be handled differently. - #[instrument(skip(self), level = "debug")] + #[instrument(skip(self, expr), level = "debug")] pub(super) fn check_expr_with_expectation( &self, expr: &'tcx hir::Expr<'tcx>, expected: Expectation<'tcx>, + ) -> Ty<'tcx> { + self.check_expr_with_expectation_and_args(expr, expected, &[]) + } + + /// Same as `check_expr_with_expectation`, but allows us to pass in the arguments of a + /// `ExprKind::Call` when evaluating its callee when it is an `ExprKind::Path`. + pub(super) fn check_expr_with_expectation_and_args( + &self, + expr: &'tcx hir::Expr<'tcx>, + expected: Expectation<'tcx>, + args: &'tcx [hir::Expr<'tcx>], ) -> Ty<'tcx> { if self.tcx().sess.verbose() { // make this code only run with -Zverbose because it is probably slow @@ -198,7 +208,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let old_diverges = self.diverges.replace(Diverges::Maybe); let old_has_errors = self.has_errors.replace(false); - let ty = ensure_sufficient_stack(|| self.check_expr_kind(expr, expected)); + let ty = ensure_sufficient_stack(|| match &expr.kind { + hir::ExprKind::Path( + qpath @ hir::QPath::Resolved(..) | qpath @ hir::QPath::TypeRelative(..), + ) => self.check_expr_path(qpath, expr, args), + _ => self.check_expr_kind(expr, expected), + }); // Warn for non-block expressions with diverging children. match expr.kind { @@ -238,12 +253,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ty } + #[instrument(skip(self, expr), level = "debug")] fn check_expr_kind( &self, expr: &'tcx hir::Expr<'tcx>, expected: Expectation<'tcx>, ) -> Ty<'tcx> { - debug!("check_expr_kind(expected={:?}, expr={:?})", expected, expr); + trace!("expr={:#?}", expr); let tcx = self.tcx; match expr.kind { @@ -261,7 +277,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ExprKind::Path(QPath::LangItem(lang_item, _)) => { self.check_lang_item_path(lang_item, expr) } - ExprKind::Path(ref qpath) => self.check_expr_path(qpath, expr), + ExprKind::Path(ref qpath) => self.check_expr_path(qpath, expr, &[]), ExprKind::InlineAsm(asm) => self.check_expr_asm(asm), ExprKind::LlvmInlineAsm(asm) => { for expr in asm.outputs_exprs.iter().chain(asm.inputs_exprs.iter()) { @@ -481,10 +497,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.resolve_lang_item_path(lang_item, expr.span, expr.hir_id).1 } - fn check_expr_path( + pub(crate) fn check_expr_path( &self, qpath: &'tcx hir::QPath<'tcx>, expr: &'tcx hir::Expr<'tcx>, + args: &'tcx [hir::Expr<'tcx>], ) -> Ty<'tcx> { let tcx = self.tcx; let (res, opt_ty, segs) = @@ -517,16 +534,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // We just want to check sizedness, so instead of introducing // placeholder lifetimes with probing, we just replace higher lifetimes // with fresh vars. + let span = args.get(i).map(|a| a.span).unwrap_or(expr.span); let input = self .replace_bound_vars_with_fresh_vars( - expr.span, + span, infer::LateBoundRegionConversionTime::FnCall, fn_sig.input(i), ) .0; self.require_type_is_sized_deferred( input, - expr.span, + span, traits::SizedArgumentType(None), ); } @@ -747,7 +765,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if self.ret_coercion_span.get().is_none() { self.ret_coercion_span.set(Some(e.span)); } - self.check_return_expr(e); + self.check_return_expr(e, true); } else { let mut coercion = self.ret_coercion.as_ref().unwrap().borrow_mut(); if self.ret_coercion_span.get().is_none() { @@ -776,16 +794,32 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.tcx.types.never } - pub(super) fn check_return_expr(&self, return_expr: &'tcx hir::Expr<'tcx>) { + /// `explicit_return` is `true` if we're checkng an explicit `return expr`, + /// and `false` if we're checking a trailing expression. + pub(super) fn check_return_expr( + &self, + return_expr: &'tcx hir::Expr<'tcx>, + explicit_return: bool, + ) { let ret_coercion = self.ret_coercion.as_ref().unwrap_or_else(|| { span_bug!(return_expr.span, "check_return_expr called outside fn body") }); let ret_ty = ret_coercion.borrow().expected_ty(); let return_expr_ty = self.check_expr_with_hint(return_expr, ret_ty); + let mut span = return_expr.span; + // Use the span of the trailing expression for our cause, + // not the span of the entire function + if !explicit_return { + if let ExprKind::Block(body, _) = return_expr.kind { + if let Some(last_expr) = body.expr { + span = last_expr.span; + } + } + } ret_coercion.borrow_mut().coerce( self, - &self.cause(return_expr.span, ObligationCauseCode::ReturnValue(return_expr.hir_id)), + &self.cause(span, ObligationCauseCode::ReturnValue(return_expr.hir_id)), return_expr, return_expr_ty, ); @@ -1236,6 +1270,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { variant, fields, base_expr.is_none(), + expr.span, ); if let Some(base_expr) = base_expr { // If check_expr_struct_fields hit an error, do not attempt to populate @@ -1283,6 +1318,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { variant: &'tcx ty::VariantDef, ast_fields: &'tcx [hir::ExprField<'tcx>], check_completeness: bool, + expr_span: Span, ) -> bool { let tcx = self.tcx; @@ -1334,7 +1370,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ident, }); } else { - self.report_unknown_field(adt_ty, variant, field, ast_fields, kind_name, span); + self.report_unknown_field( + adt_ty, variant, field, ast_fields, kind_name, expr_span, + ); } tcx.ty_error() @@ -1467,7 +1505,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { field: &hir::ExprField<'_>, skip_fields: &[hir::ExprField<'_>], kind_name: &str, - ty_span: Span, + expr_span: Span, ) { if variant.is_recovered() { self.set_tainted_by_errors(); @@ -1510,8 +1548,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ), ); err.span_label(field.ident.span, "field does not exist"); - err.span_suggestion( - ty_span, + err.span_suggestion_verbose( + expr_span, &format!( "`{adt}::{variant}` is a tuple {kind_name}, use the appropriate syntax", adt = ty, @@ -1528,8 +1566,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { _ => { err.span_label(variant.ident.span, format!("`{adt}` defined here", adt = ty)); err.span_label(field.ident.span, "field does not exist"); - err.span_suggestion( - ty_span, + err.span_suggestion_verbose( + expr_span, &format!( "`{adt}` is a tuple {kind_name}, use the appropriate syntax", adt = ty, @@ -1660,15 +1698,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Save the index of all fields regardless of their visibility in case // of error recovery. self.write_field_index(expr.hir_id, index); + let adjustments = self.adjust_steps(&autoderef); if field.vis.is_accessible_from(def_scope, self.tcx) { - let adjustments = self.adjust_steps(&autoderef); self.apply_adjustments(base, adjustments); self.register_predicates(autoderef.into_obligations()); self.tcx.check_stability(field.did, Some(expr.hir_id), expr.span, None); return field_ty; } - private_candidate = Some((base_def.did, field_ty)); + private_candidate = Some((adjustments, base_def.did, field_ty)); } } ty::Tuple(tys) => { @@ -1691,7 +1729,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } self.structurally_resolved_type(autoderef.span(), autoderef.final_ty(false)); - if let Some((did, field_ty)) = private_candidate { + if let Some((adjustments, did, field_ty)) = private_candidate { + // (#90483) apply adjustments to avoid ExprUseVisitor from + // creating erroneous projection. + self.apply_adjustments(base, adjustments); self.ban_private_field_access(expr, expr_t, field, did); return field_ty; } @@ -1822,6 +1863,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { field, expr_t, expr, + None, ); } err.emit(); @@ -1838,13 +1880,43 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expr_t ); err.span_label(field.span, "method, not a field"); - if !self.expr_in_place(expr.hir_id) { + let expr_is_call = + if let hir::Node::Expr(hir::Expr { kind: ExprKind::Call(callee, _args), .. }) = + self.tcx.hir().get(self.tcx.hir().get_parent_node(expr.hir_id)) + { + expr.hir_id == callee.hir_id + } else { + false + }; + let expr_snippet = + self.tcx.sess.source_map().span_to_snippet(expr.span).unwrap_or(String::new()); + let is_wrapped = expr_snippet.starts_with('(') && expr_snippet.ends_with(')'); + let after_open = expr.span.lo() + rustc_span::BytePos(1); + let before_close = expr.span.hi() - rustc_span::BytePos(1); + + if expr_is_call && is_wrapped { + err.multipart_suggestion( + "remove wrapping parentheses to call the method", + vec![ + (expr.span.with_hi(after_open), String::new()), + (expr.span.with_lo(before_close), String::new()), + ], + Applicability::MachineApplicable, + ); + } else if !self.expr_in_place(expr.hir_id) { + // Suggest call parentheses inside the wrapping parentheses + let span = if is_wrapped { + expr.span.with_lo(after_open).with_hi(before_close) + } else { + expr.span + }; self.suggest_method_call( &mut err, "use parentheses to call the method", field, expr_t, expr, + Some(span), ); } else { err.help("methods are immutable and cannot be assigned to"); @@ -2067,7 +2139,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { idx_t } else { let base_t = self.structurally_resolved_type(base.span, base_t); - match self.lookup_indexing(expr, base, base_t, idx_t) { + match self.lookup_indexing(expr, base, base_t, idx, idx_t) { Some((index_ty, element_ty)) => { // two-phase not needed because index_ty is never mutable self.demand_coerce(idx, idx_t, index_ty, None, AllowTwoPhase::No); diff --git a/compiler/rustc_typeck/src/check/fallback.rs b/compiler/rustc_typeck/src/check/fallback.rs index 8f6cdc7bb1..296e45337e 100644 --- a/compiler/rustc_typeck/src/check/fallback.rs +++ b/compiler/rustc_typeck/src/check/fallback.rs @@ -1,29 +1,52 @@ use crate::check::FnCtxt; -use rustc_infer::infer::type_variable::Diverging; +use rustc_data_structures::{ + fx::FxHashMap, + graph::WithSuccessors, + graph::{iterate::DepthFirstSearch, vec_graph::VecGraph}, + stable_set::FxHashSet, +}; use rustc_middle::ty::{self, Ty}; impl<'tcx> FnCtxt<'_, 'tcx> { /// Performs type inference fallback, returning true if any fallback /// occurs. pub(super) fn type_inference_fallback(&self) -> bool { + debug!( + "type-inference-fallback start obligations: {:#?}", + self.fulfillment_cx.borrow_mut().pending_obligations() + ); + // All type checking constraints were added, try to fallback unsolved variables. self.select_obligations_where_possible(false, |_| {}); - let mut fallback_has_occurred = false; + debug!( + "type-inference-fallback post selection obligations: {:#?}", + self.fulfillment_cx.borrow_mut().pending_obligations() + ); + + // Check if we have any unsolved varibales. If not, no need for fallback. + let unsolved_variables = self.unsolved_variables(); + if unsolved_variables.is_empty() { + return false; + } + + let diverging_fallback = self.calculate_diverging_fallback(&unsolved_variables); + + let mut fallback_has_occurred = false; // We do fallback in two passes, to try to generate // better error messages. // The first time, we do *not* replace opaque types. - for ty in &self.unsolved_variables() { + for ty in unsolved_variables { debug!("unsolved_variable = {:?}", ty); - fallback_has_occurred |= self.fallback_if_possible(ty); + fallback_has_occurred |= self.fallback_if_possible(ty, &diverging_fallback); } - // We now see if we can make progress. This might - // cause us to unify inference variables for opaque types, - // since we may have unified some other type variables - // during the first phase of fallback. - // This means that we only replace inference variables with their underlying - // opaque types as a last resort. + // We now see if we can make progress. This might cause us to + // unify inference variables for opaque types, since we may + // have unified some other type variables during the first + // phase of fallback. This means that we only replace + // inference variables with their underlying opaque types as a + // last resort. // // In code like this: // @@ -62,36 +85,44 @@ impl<'tcx> FnCtxt<'_, 'tcx> { // // - Unconstrained floats are replaced with with `f64`. // - // - Non-numerics get replaced with `!` when `#![feature(never_type_fallback)]` - // is enabled. Otherwise, they are replaced with `()`. + // - Non-numerics may get replaced with `()` or `!`, depending on + // how they were categorized by `calculate_diverging_fallback` + // (and the setting of `#![feature(never_type_fallback)]`). + // + // Fallback becomes very dubious if we have encountered + // type-checking errors. In that case, fallback to Error. // - // Fallback becomes very dubious if we have encountered type-checking errors. - // In that case, fallback to Error. // The return value indicates whether fallback has occurred. - fn fallback_if_possible(&self, ty: Ty<'tcx>) -> bool { + fn fallback_if_possible( + &self, + ty: Ty<'tcx>, + diverging_fallback: &FxHashMap, Ty<'tcx>>, + ) -> bool { // Careful: we do NOT shallow-resolve `ty`. We know that `ty` - // is an unsolved variable, and we determine its fallback based - // solely on how it was created, not what other type variables - // it may have been unified with since then. + // is an unsolved variable, and we determine its fallback + // based solely on how it was created, not what other type + // variables it may have been unified with since then. // - // The reason this matters is that other attempts at fallback may - // (in principle) conflict with this fallback, and we wish to generate - // a type error in that case. (However, this actually isn't true right now, - // because we're only using the builtin fallback rules. This would be - // true if we were using user-supplied fallbacks. But it's still useful - // to write the code to detect bugs.) + // The reason this matters is that other attempts at fallback + // may (in principle) conflict with this fallback, and we wish + // to generate a type error in that case. (However, this + // actually isn't true right now, because we're only using the + // builtin fallback rules. This would be true if we were using + // user-supplied fallbacks. But it's still useful to write the + // code to detect bugs.) // - // (Note though that if we have a general type variable `?T` that is then unified - // with an integer type variable `?I` that ultimately never gets - // resolved to a special integral type, `?T` is not considered unsolved, - // but `?I` is. The same is true for float variables.) + // (Note though that if we have a general type variable `?T` + // that is then unified with an integer type variable `?I` + // that ultimately never gets resolved to a special integral + // type, `?T` is not considered unsolved, but `?I` is. The + // same is true for float variables.) let fallback = match ty.kind() { _ if self.is_tainted_by_errors() => self.tcx.ty_error(), ty::Infer(ty::IntVar(_)) => self.tcx.types.i32, ty::Infer(ty::FloatVar(_)) => self.tcx.types.f64, - _ => match self.type_var_diverges(ty) { - Diverging::Diverges => self.tcx.mk_diverging_default(), - Diverging::NotDiverging => return false, + _ => match diverging_fallback.get(&ty) { + Some(&fallback_ty) => fallback_ty, + None => return false, }, }; debug!("fallback_if_possible(ty={:?}): defaulting to `{:?}`", ty, fallback); @@ -105,11 +136,10 @@ impl<'tcx> FnCtxt<'_, 'tcx> { true } - /// Second round of fallback: Unconstrained type variables - /// created from the instantiation of an opaque - /// type fall back to the opaque type itself. This is a - /// somewhat incomplete attempt to manage "identity passthrough" - /// for `impl Trait` types. + /// Second round of fallback: Unconstrained type variables created + /// from the instantiation of an opaque type fall back to the + /// opaque type itself. This is a somewhat incomplete attempt to + /// manage "identity passthrough" for `impl Trait` types. /// /// For example, in this code: /// @@ -158,4 +188,274 @@ impl<'tcx> FnCtxt<'_, 'tcx> { return false; } } + + /// The "diverging fallback" system is rather complicated. This is + /// a result of our need to balance 'do the right thing' with + /// backwards compatibility. + /// + /// "Diverging" type variables are variables created when we + /// coerce a `!` type into an unbound type variable `?X`. If they + /// never wind up being constrained, the "right and natural" thing + /// is that `?X` should "fallback" to `!`. This means that e.g. an + /// expression like `Some(return)` will ultimately wind up with a + /// type like `Option` (presuming it is not assigned or + /// constrained to have some other type). + /// + /// However, the fallback used to be `()` (before the `!` type was + /// added). Moreover, there are cases where the `!` type 'leaks + /// out' from dead code into type variables that affect live + /// code. The most common case is something like this: + /// + /// ```rust + /// match foo() { + /// 22 => Default::default(), // call this type `?D` + /// _ => return, // return has type `!` + /// } // call the type of this match `?M` + /// ``` + /// + /// Here, coercing the type `!` into `?M` will create a diverging + /// type variable `?X` where `?X <: ?M`. We also have that `?D <: + /// ?M`. If `?M` winds up unconstrained, then `?X` will + /// fallback. If it falls back to `!`, then all the type variables + /// will wind up equal to `!` -- this includes the type `?D` + /// (since `!` doesn't implement `Default`, we wind up a "trait + /// not implemented" error in code like this). But since the + /// original fallback was `()`, this code used to compile with `?D + /// = ()`. This is somewhat surprising, since `Default::default()` + /// on its own would give an error because the types are + /// insufficiently constrained. + /// + /// Our solution to this dilemma is to modify diverging variables + /// so that they can *either* fallback to `!` (the default) or to + /// `()` (the backwards compatibility case). We decide which + /// fallback to use based on whether there is a coercion pattern + /// like this: + /// + /// ``` + /// ?Diverging -> ?V + /// ?NonDiverging -> ?V + /// ?V != ?NonDiverging + /// ``` + /// + /// Here `?Diverging` represents some diverging type variable and + /// `?NonDiverging` represents some non-diverging type + /// variable. `?V` can be any type variable (diverging or not), so + /// long as it is not equal to `?NonDiverging`. + /// + /// Intuitively, what we are looking for is a case where a + /// "non-diverging" type variable (like `?M` in our example above) + /// is coerced *into* some variable `?V` that would otherwise + /// fallback to `!`. In that case, we make `?V` fallback to `!`, + /// along with anything that would flow into `?V`. + /// + /// The algorithm we use: + /// * Identify all variables that are coerced *into* by a + /// diverging variable. Do this by iterating over each + /// diverging, unsolved variable and finding all variables + /// reachable from there. Call that set `D`. + /// * Walk over all unsolved, non-diverging variables, and find + /// any variable that has an edge into `D`. + fn calculate_diverging_fallback( + &self, + unsolved_variables: &[Ty<'tcx>], + ) -> FxHashMap, Ty<'tcx>> { + debug!("calculate_diverging_fallback({:?})", unsolved_variables); + + let relationships = self.fulfillment_cx.borrow_mut().relationships().clone(); + + // Construct a coercion graph where an edge `A -> B` indicates + // a type variable is that is coerced + let coercion_graph = self.create_coercion_graph(); + + // Extract the unsolved type inference variable vids; note that some + // unsolved variables are integer/float variables and are excluded. + let unsolved_vids = unsolved_variables.iter().filter_map(|ty| ty.ty_vid()); + + // Compute the diverging root vids D -- that is, the root vid of + // those type variables that (a) are the target of a coercion from + // a `!` type and (b) have not yet been solved. + // + // These variables are the ones that are targets for fallback to + // either `!` or `()`. + let diverging_roots: FxHashSet = self + .diverging_type_vars + .borrow() + .iter() + .map(|&ty| self.infcx.shallow_resolve(ty)) + .filter_map(|ty| ty.ty_vid()) + .map(|vid| self.infcx.root_var(vid)) + .collect(); + debug!( + "calculate_diverging_fallback: diverging_type_vars={:?}", + self.diverging_type_vars.borrow() + ); + debug!("calculate_diverging_fallback: diverging_roots={:?}", diverging_roots); + + // Find all type variables that are reachable from a diverging + // type variable. These will typically default to `!`, unless + // we find later that they are *also* reachable from some + // other type variable outside this set. + let mut roots_reachable_from_diverging = DepthFirstSearch::new(&coercion_graph); + let mut diverging_vids = vec![]; + let mut non_diverging_vids = vec![]; + for unsolved_vid in unsolved_vids { + let root_vid = self.infcx.root_var(unsolved_vid); + debug!( + "calculate_diverging_fallback: unsolved_vid={:?} root_vid={:?} diverges={:?}", + unsolved_vid, + root_vid, + diverging_roots.contains(&root_vid), + ); + if diverging_roots.contains(&root_vid) { + diverging_vids.push(unsolved_vid); + roots_reachable_from_diverging.push_start_node(root_vid); + + debug!( + "calculate_diverging_fallback: root_vid={:?} reaches {:?}", + root_vid, + coercion_graph.depth_first_search(root_vid).collect::>() + ); + + // drain the iterator to visit all nodes reachable from this node + roots_reachable_from_diverging.complete_search(); + } else { + non_diverging_vids.push(unsolved_vid); + } + } + + debug!( + "calculate_diverging_fallback: roots_reachable_from_diverging={:?}", + roots_reachable_from_diverging, + ); + + // Find all type variables N0 that are not reachable from a + // diverging variable, and then compute the set reachable from + // N0, which we call N. These are the *non-diverging* type + // variables. (Note that this set consists of "root variables".) + let mut roots_reachable_from_non_diverging = DepthFirstSearch::new(&coercion_graph); + for &non_diverging_vid in &non_diverging_vids { + let root_vid = self.infcx.root_var(non_diverging_vid); + if roots_reachable_from_diverging.visited(root_vid) { + continue; + } + roots_reachable_from_non_diverging.push_start_node(root_vid); + roots_reachable_from_non_diverging.complete_search(); + } + debug!( + "calculate_diverging_fallback: roots_reachable_from_non_diverging={:?}", + roots_reachable_from_non_diverging, + ); + + debug!("inherited: {:#?}", self.inh.fulfillment_cx.borrow_mut().pending_obligations()); + debug!("obligations: {:#?}", self.fulfillment_cx.borrow_mut().pending_obligations()); + debug!("relationships: {:#?}", relationships); + + // For each diverging variable, figure out whether it can + // reach a member of N. If so, it falls back to `()`. Else + // `!`. + let mut diverging_fallback = FxHashMap::default(); + diverging_fallback.reserve(diverging_vids.len()); + for &diverging_vid in &diverging_vids { + let diverging_ty = self.tcx.mk_ty_var(diverging_vid); + let root_vid = self.infcx.root_var(diverging_vid); + let can_reach_non_diverging = coercion_graph + .depth_first_search(root_vid) + .any(|n| roots_reachable_from_non_diverging.visited(n)); + + let mut relationship = ty::FoundRelationships { self_in_trait: false, output: false }; + + for (vid, rel) in relationships.iter() { + if self.infcx.root_var(*vid) == root_vid { + relationship.self_in_trait |= rel.self_in_trait; + relationship.output |= rel.output; + } + } + + if relationship.self_in_trait && relationship.output { + // This case falls back to () to ensure that the code pattern in + // src/test/ui/never_type/fallback-closure-ret.rs continues to + // compile when never_type_fallback is enabled. + // + // This rule is not readily explainable from first principles, + // but is rather intended as a patchwork fix to ensure code + // which compiles before the stabilization of never type + // fallback continues to work. + // + // Typically this pattern is encountered in a function taking a + // closure as a parameter, where the return type of that closure + // (checked by `relationship.output`) is expected to implement + // some trait (checked by `relationship.self_in_trait`). This + // can come up in non-closure cases too, so we do not limit this + // rule to specifically `FnOnce`. + // + // When the closure's body is something like `panic!()`, the + // return type would normally be inferred to `!`. However, it + // needs to fall back to `()` in order to still compile, as the + // trait is specifically implemented for `()` but not `!`. + // + // For details on the requirements for these relationships to be + // set, see the relationship finding module in + // compiler/rustc_trait_selection/src/traits/relationships.rs. + debug!("fallback to () - found trait and projection: {:?}", diverging_vid); + diverging_fallback.insert(diverging_ty, self.tcx.types.unit); + } else if can_reach_non_diverging { + debug!("fallback to () - reached non-diverging: {:?}", diverging_vid); + diverging_fallback.insert(diverging_ty, self.tcx.types.unit); + } else { + debug!("fallback to ! - all diverging: {:?}", diverging_vid); + diverging_fallback.insert(diverging_ty, self.tcx.mk_diverging_default()); + } + } + + diverging_fallback + } + + /// Returns a graph whose nodes are (unresolved) inference variables and where + /// an edge `?A -> ?B` indicates that the variable `?A` is coerced to `?B`. + fn create_coercion_graph(&self) -> VecGraph { + let pending_obligations = self.fulfillment_cx.borrow_mut().pending_obligations(); + debug!("create_coercion_graph: pending_obligations={:?}", pending_obligations); + let coercion_edges: Vec<(ty::TyVid, ty::TyVid)> = pending_obligations + .into_iter() + .filter_map(|obligation| { + // The predicates we are looking for look like `Coerce(?A -> ?B)`. + // They will have no bound variables. + obligation.predicate.kind().no_bound_vars() + }) + .filter_map(|atom| { + // We consider both subtyping and coercion to imply 'flow' from + // some position in the code `a` to a different position `b`. + // This is then used to determine which variables interact with + // live code, and as such must fall back to `()` to preserve + // soundness. + // + // In practice currently the two ways that this happens is + // coercion and subtyping. + let (a, b) = if let ty::PredicateKind::Coerce(ty::CoercePredicate { a, b }) = atom { + (a, b) + } else if let ty::PredicateKind::Subtype(ty::SubtypePredicate { + a_is_expected: _, + a, + b, + }) = atom + { + (a, b) + } else { + return None; + }; + + let a_vid = self.root_vid(a)?; + let b_vid = self.root_vid(b)?; + Some((a_vid, b_vid)) + }) + .collect(); + debug!("create_coercion_graph: coercion_edges={:?}", coercion_edges); + let num_ty_vars = self.infcx.num_ty_vars(); + VecGraph::new(num_ty_vars, coercion_edges) + } + + /// If `ty` is an unresolved type variable, returns its root vid. + fn root_vid(&self, ty: Ty<'tcx>) -> Option { + Some(self.infcx.root_var(self.infcx.shallow_resolve(ty).ty_vid()?)) + } } diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs index 9748c0835b..ac4bb65224 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs @@ -83,19 +83,26 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// version (resolve_vars_if_possible), this version will /// also select obligations if it seems useful, in an effort /// to get more type information. - pub(in super::super) fn resolve_vars_with_obligations(&self, mut ty: Ty<'tcx>) -> Ty<'tcx> { - debug!("resolve_vars_with_obligations(ty={:?})", ty); + pub(in super::super) fn resolve_vars_with_obligations(&self, ty: Ty<'tcx>) -> Ty<'tcx> { + self.resolve_vars_with_obligations_and_mutate_fulfillment(ty, |_| {}) + } + #[instrument(skip(self, mutate_fulfillment_errors), level = "debug")] + pub(in super::super) fn resolve_vars_with_obligations_and_mutate_fulfillment( + &self, + mut ty: Ty<'tcx>, + mutate_fulfillment_errors: impl Fn(&mut Vec>), + ) -> Ty<'tcx> { // No Infer()? Nothing needs doing. if !ty.has_infer_types_or_consts() { - debug!("resolve_vars_with_obligations: ty={:?}", ty); + debug!("no inference var, nothing needs doing"); return ty; } // If `ty` is a type variable, see whether we already know what it is. ty = self.resolve_vars_if_possible(ty); if !ty.has_infer_types_or_consts() { - debug!("resolve_vars_with_obligations: ty={:?}", ty); + debug!(?ty); return ty; } @@ -103,10 +110,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // possible. This can help substantially when there are // indirect dependencies that don't seem worth tracking // precisely. - self.select_obligations_where_possible(false, |_| {}); + self.select_obligations_where_possible(false, mutate_fulfillment_errors); ty = self.resolve_vars_if_possible(ty); - debug!("resolve_vars_with_obligations: ty={:?}", ty); + debug!(?ty); ty } @@ -222,6 +229,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// This should be invoked **before any unifications have /// occurred**, so that annotations like `Vec<_>` are preserved /// properly. + #[instrument(skip(self), level = "debug")] pub fn write_user_type_annotation_from_substs( &self, hir_id: hir::HirId, @@ -229,37 +237,25 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { substs: SubstsRef<'tcx>, user_self_ty: Option>, ) { - debug!( - "write_user_type_annotation_from_substs: hir_id={:?} def_id={:?} substs={:?} \ - user_self_ty={:?} in fcx {}", - hir_id, - def_id, - substs, - user_self_ty, - self.tag(), - ); + debug!("fcx {}", self.tag()); if self.can_contain_user_lifetime_bounds((substs, user_self_ty)) { let canonicalized = self.infcx.canonicalize_user_type_annotation(UserType::TypeOf( def_id, UserSubsts { substs, user_self_ty }, )); - debug!("write_user_type_annotation_from_substs: canonicalized={:?}", canonicalized); + debug!(?canonicalized); self.write_user_type_annotation(hir_id, canonicalized); } } + #[instrument(skip(self), level = "debug")] pub fn write_user_type_annotation( &self, hir_id: hir::HirId, canonical_user_type_annotation: CanonicalUserType<'tcx>, ) { - debug!( - "write_user_type_annotation: hir_id={:?} canonical_user_type_annotation={:?} tag={}", - hir_id, - canonical_user_type_annotation, - self.tag(), - ); + debug!("fcx {}", self.tag()); if !canonical_user_type_annotation.is_identity() { self.typeck_results @@ -267,17 +263,27 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .user_provided_types_mut() .insert(hir_id, canonical_user_type_annotation); } else { - debug!("write_user_type_annotation: skipping identity substs"); + debug!("skipping identity substs"); } } + #[instrument(skip(self, expr), level = "debug")] pub fn apply_adjustments(&self, expr: &hir::Expr<'_>, adj: Vec>) { - debug!("apply_adjustments(expr={:?}, adj={:?})", expr, adj); + debug!("expr = {:#?}", expr); if adj.is_empty() { return; } + for a in &adj { + if let Adjust::NeverToAny = a.kind { + if a.target.is_ty_var() { + self.diverging_type_vars.borrow_mut().insert(a.target); + debug!("apply_adjustments: adding `{:?}` as diverging type var", a.target); + } + } + } + let autoborrow_mut = adj.iter().any(|adj| { matches!( adj, @@ -568,7 +574,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.register_predicate(traits::Obligation::new( cause, self.param_env, - ty::PredicateKind::WellFormed(arg).to_predicate(self.tcx), + ty::Binder::dummy(ty::PredicateKind::WellFormed(arg)).to_predicate(self.tcx), )); } @@ -635,8 +641,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } + #[instrument(skip(self), level = "debug")] pub(in super::super) fn select_all_obligations_or_error(&self) { - debug!("select_all_obligations_or_error"); if let Err(errors) = self .fulfillment_cx .borrow_mut() @@ -677,16 +683,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ret_ty.builtin_deref(true).unwrap() } + #[instrument(skip(self), level = "debug")] fn self_type_matches_expected_vid( &self, trait_ref: ty::PolyTraitRef<'tcx>, expected_vid: ty::TyVid, ) -> bool { let self_ty = self.shallow_resolve(trait_ref.skip_binder().self_ty()); - debug!( - "self_type_matches_expected_vid(trait_ref={:?}, self_ty={:?}, expected_vid={:?})", - trait_ref, self_ty, expected_vid - ); + debug!(?self_ty); + match *self_ty.kind() { ty::Infer(ty::TyVar(found_vid)) => { // FIXME: consider using `sub_root_var` here so we @@ -699,6 +704,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } + #[instrument(skip(self), level = "debug")] pub(in super::super) fn obligations_for_self_ty<'b>( &'b self, self_ty: ty::TyVid, @@ -708,12 +714,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // FIXME: consider using `sub_root_var` here so we // can see through subtyping. let ty_var_root = self.root_var(self_ty); - debug!( - "obligations_for_self_ty: self_ty={:?} ty_var_root={:?} pending_obligations={:?}", - self_ty, - ty_var_root, - self.fulfillment_cx.borrow().pending_obligations() - ); + trace!("pending_obligations = {:#?}", self.fulfillment_cx.borrow().pending_obligations()); self.fulfillment_cx .borrow() @@ -763,6 +764,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Unifies the output type with the expected type early, for more coercions /// and forward type information on the input expressions. + #[instrument(skip(self, call_span), level = "debug")] pub(in super::super) fn expected_inputs_for_expected_output( &self, call_span: Span, @@ -809,10 +811,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Ok(formal_args.iter().map(|&ty| self.resolve_vars_if_possible(ty)).collect()) }) .unwrap_or_default(); - debug!( - "expected_inputs_for_expected_output(formal={:?} -> {:?}, expected={:?} -> {:?})", - formal_args, formal_ret, expect_args, expected_ret - ); + debug!(?formal_args, ?formal_ret, ?expect_args, ?expected_ret); expect_args } @@ -1172,12 +1171,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { { return None; } - let original_span = original_sp(last_stmt.span, blk.span); - Some((original_span.with_lo(original_span.hi() - BytePos(1)), needs_box)) + let span = if last_stmt.span.from_expansion() { + let mac_call = original_sp(last_stmt.span, blk.span); + self.tcx.sess.source_map().mac_call_stmt_semi_span(mac_call)? + } else { + last_stmt.span.with_lo(last_stmt.span.hi() - BytePos(1)) + }; + Some((span, needs_box)) } // Instantiates the given path, which must refer to an item with the given // number of type parameters and type. + #[instrument(skip(self, span), level = "debug")] pub fn instantiate_value_path( &self, segments: &[hir::PathSegment<'_>], @@ -1186,11 +1191,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { span: Span, hir_id: hir::HirId, ) -> (Ty<'tcx>, Res) { - debug!( - "instantiate_value_path(segments={:?}, self_ty={:?}, res={:?}, hir_id={})", - segments, self_ty, res, hir_id, - ); - let tcx = self.tcx; let path_segs = match res { @@ -1213,7 +1213,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } Res::Def(DefKind::AssocFn | DefKind::AssocConst, def_id) => { let container = tcx.associated_item(def_id).container; - debug!("instantiate_value_path: def_id={:?} container={:?}", def_id, container); + debug!(?def_id, ?container); match container { ty::TraitContainer(trait_did) => { callee::check_legal_trait_for_method_call(tcx, span, None, span, trait_did) diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs index 9efb52a08b..551522334a 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs @@ -9,6 +9,7 @@ use crate::check::{ }; use rustc_ast as ast; +use rustc_data_structures::sync::Lrc; use rustc_errors::{Applicability, DiagnosticBuilder, DiagnosticId}; use rustc_hir as hir; use rustc_hir::def::{CtorOf, DefKind, Res}; @@ -324,6 +325,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.point_at_arg_instead_of_call_if_possible( errors, &final_arg_types[..], + expr, sp, &args, ); @@ -354,8 +356,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { continue; } - debug!("checking the argument"); let formal_ty = formal_tys[i]; + debug!("checking argument {}: {:?} = {:?}", i, arg, formal_ty); // The special-cased logic below has three functions: // 1. Provide as good of an expected type as possible. @@ -367,6 +369,42 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // to, which is `expected_ty` if `rvalue_hint` returns an // `ExpectHasType(expected_ty)`, or the `formal_ty` otherwise. let coerce_ty = expected.only_has_type(self).unwrap_or(formal_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 + // fulfillment error to be more accurate. + 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), + }; + } + } + }, + ); + // 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); @@ -494,15 +532,25 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Some((variant, ty)) } else { - struct_span_err!( - self.tcx.sess, - path_span, - E0071, - "expected struct, variant or union type, found {}", - ty.sort_string(self.tcx) - ) - .span_label(path_span, "not a struct") - .emit(); + match ty.kind() { + ty::Error(_) => { + // E0071 might be caused by a spelling error, which will have + // already caused an error message and probably a suggestion + // elsewhere. Refrain from emitting more unhelpful errors here + // (issue #88844). + } + _ => { + struct_span_err!( + self.tcx.sess, + path_span, + E0071, + "expected struct, variant or union type, found {}", + ty.sort_string(self.tcx) + ) + .span_label(path_span, "not a struct") + .emit(); + } + } None } } @@ -907,6 +955,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &self, errors: &mut Vec>, final_arg_types: &[(usize, Ty<'tcx>, Ty<'tcx>)], + expr: &'tcx hir::Expr<'tcx>, call_sp: Span, args: &'tcx [hir::Expr<'tcx>], ) { @@ -956,7 +1005,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // 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; - error.points_at_arg_span = true; + 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), + }; } } } diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs b/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs index 0acf1d26e2..dcc635a1f0 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs @@ -8,11 +8,11 @@ use rustc_errors::{Applicability, DiagnosticBuilder}; use rustc_hir as hir; use rustc_hir::def::{CtorOf, DefKind}; use rustc_hir::lang_items::LangItem; -use rustc_hir::{Expr, ExprKind, ItemKind, Node, Stmt, StmtKind}; +use rustc_hir::{Expr, ExprKind, ItemKind, Node, Path, QPath, Stmt, StmtKind, TyKind}; use rustc_infer::infer; use rustc_middle::lint::in_external_macro; use rustc_middle::ty::{self, Binder, Ty}; -use rustc_span::symbol::kw; +use rustc_span::symbol::{kw, sym}; use std::iter; @@ -341,12 +341,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { for (sp, label) in spans_and_labels { multi_span.push_span_label(sp, label); } - err.span_note(multi_span, "closures can only be coerced to `fn` types if they do not capture any variables"); + err.span_note( + multi_span, + "closures can only be coerced to `fn` types if they do not capture any variables" + ); } } } /// When encountering an `impl Future` where `BoxFuture` is expected, suggest `Box::pin`. + #[instrument(skip(self, err))] pub(in super::super) fn suggest_calling_boxed_future_when_appropriate( &self, err: &mut DiagnosticBuilder<'_>, @@ -361,33 +365,74 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return false; } let pin_did = self.tcx.lang_items().pin_type(); - match expected.kind() { - ty::Adt(def, _) if Some(def.did) != pin_did => return false, - // This guards the `unwrap` and `mk_box` below. - _ if pin_did.is_none() || self.tcx.lang_items().owned_box().is_none() => return false, - _ => {} + // This guards the `unwrap` and `mk_box` below. + if pin_did.is_none() || self.tcx.lang_items().owned_box().is_none() { + return false; } - let boxed_found = self.tcx.mk_box(found); - let new_found = self.tcx.mk_lang_item(boxed_found, LangItem::Pin).unwrap(); - if self.can_coerce(new_found, expected) { - match found.kind() { - ty::Adt(def, _) if def.is_box() => { - err.help("use `Box::pin`"); - } - _ => { - err.multipart_suggestion( - "you need to pin and box this expression", - vec![ - (expr.span.shrink_to_lo(), "Box::pin(".to_string()), - (expr.span.shrink_to_hi(), ")".to_string()), - ], - Applicability::MachineApplicable, - ); + let box_found = self.tcx.mk_box(found); + let pin_box_found = self.tcx.mk_lang_item(box_found, LangItem::Pin).unwrap(); + let pin_found = self.tcx.mk_lang_item(found, LangItem::Pin).unwrap(); + match expected.kind() { + ty::Adt(def, _) if Some(def.did) == pin_did => { + if self.can_coerce(pin_box_found, expected) { + debug!("can coerce {:?} to {:?}, suggesting Box::pin", pin_box_found, expected); + match found.kind() { + ty::Adt(def, _) if def.is_box() => { + err.help("use `Box::pin`"); + } + _ => { + err.multipart_suggestion( + "you need to pin and box this expression", + vec![ + (expr.span.shrink_to_lo(), "Box::pin(".to_string()), + (expr.span.shrink_to_hi(), ")".to_string()), + ], + Applicability::MaybeIncorrect, + ); + } + } + true + } else if self.can_coerce(pin_found, expected) { + match found.kind() { + ty::Adt(def, _) if def.is_box() => { + err.help("use `Box::pin`"); + true + } + _ => false, + } + } else { + false } } - true - } else { - false + ty::Adt(def, _) if def.is_box() && self.can_coerce(box_found, expected) => { + // Check if the parent expression is a call to Pin::new. If it + // is and we were expecting a Box, ergo Pin>, we + // can suggest Box::pin. + let parent = self.tcx.hir().get_parent_node(expr.hir_id); + let fn_name = match self.tcx.hir().find(parent) { + Some(Node::Expr(Expr { kind: ExprKind::Call(fn_name, _), .. })) => fn_name, + _ => return false, + }; + match fn_name.kind { + ExprKind::Path(QPath::TypeRelative( + hir::Ty { + kind: TyKind::Path(QPath::Resolved(_, Path { res: recv_ty, .. })), + .. + }, + method, + )) if recv_ty.opt_def_id() == pin_did && method.ident.name == sym::new => { + err.span_suggestion( + fn_name.span, + "use `Box::pin` to pin and box this expression", + "Box::pin".to_string(), + Applicability::MachineApplicable, + ); + true + } + _ => false, + } + } + _ => false, } } @@ -484,8 +529,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { debug!("suggest_missing_return_type: return type {:?}", ty); debug!("suggest_missing_return_type: expected type {:?}", ty); let bound_vars = self.tcx.late_bound_vars(fn_id); - let ty = self.tcx.erase_late_bound_regions(Binder::bind_with_vars(ty, bound_vars)); + let ty = Binder::bind_with_vars(ty, bound_vars); let ty = self.normalize_associated_types_in(sp, ty); + let ty = self.tcx.erase_late_bound_regions(ty); if self.can_coerce(expected, ty) { err.span_label(sp, format!("expected `{}` because of return type", expected)); return true; diff --git a/compiler/rustc_typeck/src/check/generator_interior.rs b/compiler/rustc_typeck/src/check/generator_interior.rs index 5f26e701c0..2910ce6de6 100644 --- a/compiler/rustc_typeck/src/check/generator_interior.rs +++ b/compiler/rustc_typeck/src/check/generator_interior.rs @@ -1,10 +1,11 @@ //! This calculates the types which has storage which lives across a suspension point in a //! generator from the perspective of typeck. The actual types used at runtime -//! is calculated in `rustc_mir::transform::generator` and may be a subset of the +//! is calculated in `rustc_const_eval::transform::generator` and may be a subset of the //! types computed here. use super::FnCtxt; use rustc_data_structures::fx::{FxHashSet, FxIndexSet}; +use rustc_errors::pluralize; use rustc_hir as hir; use rustc_hir::def::{CtorKind, DefKind, Res}; use rustc_hir::def_id::DefId; @@ -12,9 +13,11 @@ use rustc_hir::hir_id::HirIdSet; use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc_hir::{Arm, Expr, ExprKind, Guard, HirId, Pat, PatKind}; use rustc_middle::middle::region::{self, YieldData}; -use rustc_middle::ty::{self, Ty}; +use rustc_middle::ty::{self, Ty, TyCtxt}; +use rustc_span::symbol::sym; use rustc_span::Span; use smallvec::SmallVec; +use tracing::debug; struct InteriorVisitor<'a, 'tcx> { fcx: &'a FnCtxt<'a, 'tcx>, @@ -30,12 +33,14 @@ struct InteriorVisitor<'a, 'tcx> { /// that they may succeed the said yield point in the post-order. guard_bindings: SmallVec<[SmallVec<[HirId; 4]>; 1]>, guard_bindings_set: HirIdSet, + linted_values: HirIdSet, } impl<'a, 'tcx> InteriorVisitor<'a, 'tcx> { fn record( &mut self, ty: Ty<'tcx>, + hir_id: HirId, scope: Option, expr: Option<&'tcx Expr<'tcx>>, source_span: Span, @@ -117,6 +122,23 @@ impl<'a, 'tcx> InteriorVisitor<'a, 'tcx> { } else { // Insert the type into the ordered set. let scope_span = scope.map(|s| s.span(self.fcx.tcx, self.region_scope_tree)); + + if !self.linted_values.contains(&hir_id) { + check_must_not_suspend_ty( + self.fcx, + ty, + hir_id, + SuspendCheckData { + expr, + source_span, + yield_span: yield_data.span, + plural_len: 1, + ..Default::default() + }, + ); + self.linted_values.insert(hir_id); + } + self.types.insert(ty::GeneratorInteriorTypeCause { span: source_span, ty: &ty, @@ -163,6 +185,7 @@ pub fn resolve_interior<'a, 'tcx>( prev_unresolved_span: None, guard_bindings: <_>::default(), guard_bindings_set: <_>::default(), + linted_values: <_>::default(), }; intravisit::walk_body(&mut visitor, body); @@ -290,7 +313,7 @@ impl<'a, 'tcx> Visitor<'tcx> for InteriorVisitor<'a, 'tcx> { if let PatKind::Binding(..) = pat.kind { let scope = self.region_scope_tree.var_scope(pat.hir_id.local_id); let ty = self.fcx.typeck_results.borrow().pat_ty(pat); - self.record(ty, Some(scope), None, pat.span, false); + self.record(ty, pat.hir_id, Some(scope), None, pat.span, false); } } @@ -342,7 +365,14 @@ impl<'a, 'tcx> Visitor<'tcx> for InteriorVisitor<'a, 'tcx> { // If there are adjustments, then record the final type -- // this is the actual value that is being produced. if let Some(adjusted_ty) = self.fcx.typeck_results.borrow().expr_ty_adjusted_opt(expr) { - self.record(adjusted_ty, scope, Some(expr), expr.span, guard_borrowing_from_pattern); + self.record( + adjusted_ty, + expr.hir_id, + scope, + Some(expr), + expr.span, + guard_borrowing_from_pattern, + ); } // Also record the unadjusted type (which is the only type if @@ -380,9 +410,23 @@ impl<'a, 'tcx> Visitor<'tcx> for InteriorVisitor<'a, 'tcx> { tcx.mk_region(ty::RegionKind::ReErased), ty::TypeAndMut { ty, mutbl: hir::Mutability::Not }, ); - self.record(ref_ty, scope, Some(expr), expr.span, guard_borrowing_from_pattern); + self.record( + ref_ty, + expr.hir_id, + scope, + Some(expr), + expr.span, + guard_borrowing_from_pattern, + ); } - self.record(ty, scope, Some(expr), expr.span, guard_borrowing_from_pattern); + self.record( + ty, + expr.hir_id, + scope, + Some(expr), + expr.span, + guard_borrowing_from_pattern, + ); } else { self.fcx.tcx.sess.delay_span_bug(expr.span, "no type for node"); } @@ -409,3 +453,173 @@ impl<'a, 'tcx> Visitor<'tcx> for ArmPatCollector<'a> { } } } + +#[derive(Default)] +pub struct SuspendCheckData<'a, 'tcx> { + expr: Option<&'tcx Expr<'tcx>>, + source_span: Span, + yield_span: Span, + descr_pre: &'a str, + descr_post: &'a str, + plural_len: usize, +} + +// Returns whether it emitted a diagnostic or not +// Note that this fn and the proceding one are based on the code +// for creating must_use diagnostics +// +// Note that this technique was chosen over things like a `Suspend` marker trait +// as it is simpler and has precendent in the compiler +pub fn check_must_not_suspend_ty<'tcx>( + fcx: &FnCtxt<'_, 'tcx>, + ty: Ty<'tcx>, + hir_id: HirId, + data: SuspendCheckData<'_, 'tcx>, +) -> bool { + if ty.is_unit() + // FIXME: should this check `is_ty_uninhabited_from`. This query is not available in this stage + // of typeck (before ReVar and RePlaceholder are removed), but may remove noise, like in + // `must_use` + // || fcx.tcx.is_ty_uninhabited_from(fcx.tcx.parent_module(hir_id).to_def_id(), ty, fcx.param_env) + { + return false; + } + + let plural_suffix = pluralize!(data.plural_len); + + match *ty.kind() { + ty::Adt(..) if ty.is_box() => { + let boxed_ty = ty.boxed_ty(); + let descr_pre = &format!("{}boxed ", data.descr_pre); + check_must_not_suspend_ty(fcx, boxed_ty, hir_id, SuspendCheckData { descr_pre, ..data }) + } + ty::Adt(def, _) => check_must_not_suspend_def(fcx.tcx, def.did, hir_id, data), + // FIXME: support adding the attribute to TAITs + ty::Opaque(def, _) => { + let mut has_emitted = false; + for &(predicate, _) in fcx.tcx.explicit_item_bounds(def) { + // We only look at the `DefId`, so it is safe to skip the binder here. + if let ty::PredicateKind::Trait(ref poly_trait_predicate) = + predicate.kind().skip_binder() + { + let def_id = poly_trait_predicate.trait_ref.def_id; + let descr_pre = &format!("{}implementer{} of ", data.descr_pre, plural_suffix); + if check_must_not_suspend_def( + fcx.tcx, + def_id, + hir_id, + SuspendCheckData { descr_pre, ..data }, + ) { + has_emitted = true; + break; + } + } + } + has_emitted + } + ty::Dynamic(binder, _) => { + let mut has_emitted = false; + for predicate in binder.iter() { + if let ty::ExistentialPredicate::Trait(ref trait_ref) = predicate.skip_binder() { + let def_id = trait_ref.def_id; + let descr_post = &format!(" trait object{}{}", plural_suffix, data.descr_post); + if check_must_not_suspend_def( + fcx.tcx, + def_id, + hir_id, + SuspendCheckData { descr_post, ..data }, + ) { + has_emitted = true; + break; + } + } + } + has_emitted + } + ty::Tuple(ref tys) => { + let mut has_emitted = false; + let spans = if let Some(hir::ExprKind::Tup(comps)) = data.expr.map(|e| &e.kind) { + debug_assert_eq!(comps.len(), tys.len()); + comps.iter().map(|e| e.span).collect() + } else { + vec![] + }; + for (i, ty) in tys.iter().map(|k| k.expect_ty()).enumerate() { + let descr_post = &format!(" in tuple element {}", i); + let span = *spans.get(i).unwrap_or(&data.source_span); + if check_must_not_suspend_ty( + fcx, + ty, + hir_id, + SuspendCheckData { descr_post, source_span: span, ..data }, + ) { + has_emitted = true; + } + } + has_emitted + } + ty::Array(ty, len) => { + let descr_pre = &format!("{}array{} of ", data.descr_pre, plural_suffix); + check_must_not_suspend_ty( + fcx, + ty, + hir_id, + SuspendCheckData { + descr_pre, + plural_len: len.try_eval_usize(fcx.tcx, fcx.param_env).unwrap_or(0) as usize + + 1, + ..data + }, + ) + } + _ => false, + } +} + +fn check_must_not_suspend_def( + tcx: TyCtxt<'_>, + def_id: DefId, + hir_id: HirId, + data: SuspendCheckData<'_, '_>, +) -> bool { + for attr in tcx.get_attrs(def_id).iter() { + if attr.has_name(sym::must_not_suspend) { + tcx.struct_span_lint_hir( + rustc_session::lint::builtin::MUST_NOT_SUSPEND, + hir_id, + data.source_span, + |lint| { + let msg = format!( + "{}`{}`{} held across a suspend point, but should not be", + data.descr_pre, + tcx.def_path_str(def_id), + data.descr_post, + ); + let mut err = lint.build(&msg); + + // add span pointing to the offending yield/await + err.span_label(data.yield_span, "the value is held across this suspend point"); + + // Add optional reason note + if let Some(note) = attr.value_str() { + // FIXME(guswynn): consider formatting this better + err.span_note(data.source_span, ¬e.as_str()); + } + + // Add some quick suggestions on what to do + // FIXME: can `drop` work as a suggestion here as well? + err.span_help( + data.source_span, + "consider using a block (`{ ... }`) \ + to shrink the value's scope, ending before the suspend point", + ); + + err.emit(); + }, + ); + + return true; + } + } + false +} diff --git a/compiler/rustc_typeck/src/check/inherited.rs b/compiler/rustc_typeck/src/check/inherited.rs index 6006c8f751..f7552c1f4e 100644 --- a/compiler/rustc_typeck/src/check/inherited.rs +++ b/compiler/rustc_typeck/src/check/inherited.rs @@ -1,6 +1,7 @@ use super::callee::DeferredCallResolution; use super::MaybeInProgressTables; +use rustc_data_structures::fx::FxHashSet; use rustc_hir as hir; use rustc_hir::def_id::{DefIdMap, LocalDefId}; use rustc_hir::HirIdMap; @@ -56,6 +57,11 @@ pub struct Inherited<'a, 'tcx> { pub(super) constness: hir::Constness, pub(super) body_id: Option, + + /// Whenever we introduce an adjustment from `!` into a type variable, + /// we record that type variable here. This is later used to inform + /// fallback. See the `fallback` module for details. + pub(super) diverging_type_vars: RefCell>>, } impl<'a, 'tcx> Deref for Inherited<'a, 'tcx> { @@ -121,6 +127,7 @@ impl Inherited<'a, 'tcx> { deferred_call_resolutions: RefCell::new(Default::default()), deferred_cast_checks: RefCell::new(Vec::new()), deferred_generator_interiors: RefCell::new(Vec::new()), + diverging_type_vars: RefCell::new(Default::default()), constness, body_id, } diff --git a/compiler/rustc_typeck/src/check/intrinsic.rs b/compiler/rustc_typeck/src/check/intrinsic.rs index 664954b0eb..b0cb8443bf 100644 --- a/compiler/rustc_typeck/src/check/intrinsic.rs +++ b/compiler/rustc_typeck/src/check/intrinsic.rs @@ -2,7 +2,7 @@ //! intrinsics that the compiler exposes. use crate::errors::{ - SimdShuffleMissingLength, UnrecognizedAtomicOperation, UnrecognizedIntrinsicFunction, + UnrecognizedAtomicOperation, UnrecognizedIntrinsicFunction, WrongNumberOfGenericArgumentsToIntrinsic, }; use crate::require_same_types; @@ -390,6 +390,8 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { sym::black_box => (1, vec![param(0)], param(0)), + sym::const_eval_select => (4, vec![param(0), param(1), param(2)], param(3)), + other => { tcx.sess.emit_err(UnrecognizedIntrinsicFunction { span: it.span, name: other }); return; @@ -468,6 +470,7 @@ pub fn check_platform_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) | sym::simd_reduce_max | sym::simd_reduce_min_nanless | sym::simd_reduce_max_nanless => (2, vec![param(0)], param(1)), + sym::simd_shuffle => (3, vec![param(0), param(0), param(1)], param(2)), name if name.as_str().starts_with("simd_shuffle") => { match name.as_str()["simd_shuffle".len()..].parse() { Ok(n) => { @@ -475,7 +478,9 @@ pub fn check_platform_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) (2, params, param(1)) } Err(_) => { - tcx.sess.emit_err(SimdShuffleMissingLength { span: it.span, name }); + let msg = + format!("unrecognized platform-specific intrinsic function: `{}`", name); + tcx.sess.struct_span_err(it.span, &msg).emit(); return; } } diff --git a/compiler/rustc_typeck/src/check/method/confirm.rs b/compiler/rustc_typeck/src/check/method/confirm.rs index 88be49e96e..dc54f63f49 100644 --- a/compiler/rustc_typeck/src/check/method/confirm.rs +++ b/compiler/rustc_typeck/src/check/method/confirm.rs @@ -28,7 +28,7 @@ struct ConfirmContext<'a, 'tcx> { impl<'a, 'tcx> Deref for ConfirmContext<'a, 'tcx> { type Target = FnCtxt<'a, 'tcx>; fn deref(&self) -> &Self::Target { - &self.fcx + self.fcx } } @@ -290,7 +290,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { .autoderef(self.span, self_ty) .include_raw_pointers() .find_map(|(ty, _)| match ty.kind() { - ty::Dynamic(ref data, ..) => Some(closure( + ty::Dynamic(data, ..) => Some(closure( self, ty, data.principal().unwrap_or_else(|| { @@ -323,7 +323,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { self.tcx, self.span, pick.item.def_id, - &generics, + generics, seg, IsMethodCall::Yes, ); @@ -343,7 +343,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { def_id: DefId, ) -> (Option<&'a hir::GenericArgs<'a>>, bool) { if def_id == self.pick.item.def_id { - if let Some(ref data) = self.seg.args { + if let Some(data) = self.seg.args { return (Some(data), false); } } diff --git a/compiler/rustc_typeck/src/check/method/mod.rs b/compiler/rustc_typeck/src/check/method/mod.rs index 2136d92542..f0f2470e80 100644 --- a/compiler/rustc_typeck/src/check/method/mod.rs +++ b/compiler/rustc_typeck/src/check/method/mod.rs @@ -21,7 +21,7 @@ use rustc_infer::infer::{self, InferOk}; use rustc_middle::ty::subst::Subst; use rustc_middle::ty::subst::{InternalSubsts, SubstsRef}; use rustc_middle::ty::GenericParamDefKind; -use rustc_middle::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TypeFoldable, WithConstness}; +use rustc_middle::ty::{self, ToPredicate, Ty, TypeFoldable, WithConstness}; use rustc_span::symbol::Ident; use rustc_span::Span; use rustc_trait_selection::traits; @@ -141,6 +141,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { method_name: Ident, self_ty: Ty<'tcx>, call_expr: &hir::Expr<'_>, + span: Option, ) { let params = self .probe_for_name( @@ -159,7 +160,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .unwrap_or(0); // Account for `foo.bar`; - let sugg_span = call_expr.span.shrink_to_hi(); + let sugg_span = span.unwrap_or(call_expr.span).shrink_to_hi(); let (suggestion, applicability) = ( format!("({})", (0..params).map(|_| "_").collect::>().join(", ")), if params > 0 { Applicability::HasPlaceholders } else { Applicability::MaybeIncorrect }, @@ -289,6 +290,44 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) } + pub(super) fn obligation_for_method( + &self, + span: Span, + trait_def_id: DefId, + self_ty: Ty<'tcx>, + opt_input_types: Option<&[Ty<'tcx>]>, + ) -> (traits::Obligation<'tcx, ty::Predicate<'tcx>>, &'tcx ty::List>) + { + // Construct a trait-reference `self_ty : Trait` + let substs = InternalSubsts::for_item(self.tcx, trait_def_id, |param, _| { + match param.kind { + GenericParamDefKind::Lifetime | GenericParamDefKind::Const { .. } => {} + GenericParamDefKind::Type { .. } => { + if param.index == 0 { + return self_ty.into(); + } else if let Some(input_types) = opt_input_types { + return input_types[param.index as usize - 1].into(); + } + } + } + self.var_for_def(span, param) + }); + + let trait_ref = ty::TraitRef::new(trait_def_id, substs); + + // Construct an obligation + let poly_trait_ref = ty::Binder::dummy(trait_ref); + ( + traits::Obligation::misc( + span, + self.body_id, + self.param_env, + poly_trait_ref.without_const().to_predicate(self.tcx), + ), + substs, + ) + } + /// `lookup_method_in_trait` is used for overloaded operators. /// It does a very narrow slice of what the normal probe/confirm path does. /// In particular, it doesn't really do any probing: it simply constructs @@ -299,7 +338,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // code with the other method-lookup code. In particular, the second half // of this method is basically the same as confirmation. #[instrument(level = "debug", skip(self, span, opt_input_types))] - pub fn lookup_method_in_trait( + pub(super) fn lookup_method_in_trait( &self, span: Span, m_name: Ident, @@ -312,36 +351,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self_ty, m_name, trait_def_id, opt_input_types ); - // Construct a trait-reference `self_ty : Trait` - let substs = InternalSubsts::for_item(self.tcx, trait_def_id, |param, _| { - match param.kind { - GenericParamDefKind::Lifetime | GenericParamDefKind::Const { .. } => {} - GenericParamDefKind::Type { .. } => { - if param.index == 0 { - return self_ty.into(); - } else if let Some(ref input_types) = opt_input_types { - return input_types[param.index as usize - 1].into(); - } - } - } - self.var_for_def(span, param) - }); - - let trait_ref = ty::TraitRef::new(trait_def_id, substs); - - // Construct an obligation - let poly_trait_ref = trait_ref.to_poly_trait_ref(); - let obligation = traits::Obligation::misc( - span, - self.body_id, - self.param_env, - poly_trait_ref.without_const().to_predicate(self.tcx), - ); + let (obligation, substs) = + self.obligation_for_method(span, trait_def_id, self_ty, opt_input_types); // Now we want to know if this can be matched if !self.predicate_may_hold(&obligation) { debug!("--> Cannot match obligation"); - return None; // Cannot be matched, no such method resolution is possible. + // Cannot be matched, no such method resolution is possible. + return None; } // Trait must have a method named `m_name` and it should not have @@ -412,10 +429,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { obligations.push(traits::Obligation::new( cause, self.param_env, - ty::PredicateKind::WellFormed(method_ty.into()).to_predicate(tcx), + ty::Binder::dummy(ty::PredicateKind::WellFormed(method_ty.into())).to_predicate(tcx), )); - let callee = MethodCallee { def_id, substs: trait_ref.substs, sig: fn_sig }; + let callee = MethodCallee { def_id, substs, sig: fn_sig }; debug!("callee = {:?}", callee); diff --git a/compiler/rustc_typeck/src/check/method/probe.rs b/compiler/rustc_typeck/src/check/method/probe.rs index 1c7d68a3d5..6eeb28e32f 100644 --- a/compiler/rustc_typeck/src/check/method/probe.rs +++ b/compiler/rustc_typeck/src/check/method/probe.rs @@ -21,9 +21,7 @@ use rustc_infer::infer::{self, InferOk, TyCtxtInferExt}; use rustc_middle::middle::stability; use rustc_middle::ty::subst::{InternalSubsts, Subst, SubstsRef}; use rustc_middle::ty::GenericParamDefKind; -use rustc_middle::ty::{ - self, ParamEnvAnd, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness, -}; +use rustc_middle::ty::{self, ParamEnvAnd, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness}; use rustc_session::lint; use rustc_span::def_id::LocalDefId; use rustc_span::lev_distance::{find_best_match_for_name, lev_distance}; @@ -90,7 +88,7 @@ struct ProbeContext<'a, 'tcx> { impl<'a, 'tcx> Deref for ProbeContext<'a, 'tcx> { type Target = FnCtxt<'a, 'tcx>; fn deref(&self) -> &Self::Target { - &self.fcx + self.fcx } } @@ -186,7 +184,7 @@ pub enum AutorefOrPtrAdjustment<'tcx> { impl<'tcx> AutorefOrPtrAdjustment<'tcx> { fn get_unsize(&self) -> Option> { match self { - AutorefOrPtrAdjustment::Autoref { mutbl: _, unsize } => unsize.clone(), + AutorefOrPtrAdjustment::Autoref { mutbl: _, unsize } => *unsize, AutorefOrPtrAdjustment::ToConstPtr => None, } } @@ -616,7 +614,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { let lang_items = self.tcx.lang_items(); match *self_ty.value.value.kind() { - ty::Dynamic(ref data, ..) if let Some(p) = data.principal() => { + ty::Dynamic(data, ..) if let Some(p) = data.principal() => { // Subtle: we can't use `instantiate_query_response` here: using it will // commit to all of the type equalities assumed by inference going through // autoderef (see the `method-probe-no-guessing` test). @@ -636,7 +634,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { // type variables in any form, so just do that! let (QueryResponse { value: generalized_self_ty, .. }, _ignored_var_values) = self.fcx - .instantiate_canonical_with_fresh_inference_vars(self.span, &self_ty); + .instantiate_canonical_with_fresh_inference_vars(self.span, self_ty); self.assemble_inherent_candidates_from_object(generalized_self_ty); self.assemble_inherent_impl_candidates_for_type(p.def_id()); @@ -755,17 +753,27 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { let (impl_ty, impl_substs) = self.impl_ty_and_substs(impl_def_id); let impl_ty = impl_ty.subst(self.tcx, impl_substs); + debug!("impl_ty: {:?}", impl_ty); + // Determine the receiver type that the method itself expects. - let xform_tys = self.xform_self_ty(&item, impl_ty, impl_substs); + let (xform_self_ty, xform_ret_ty) = self.xform_self_ty(&item, impl_ty, impl_substs); + debug!("xform_self_ty: {:?}, xform_ret_ty: {:?}", xform_self_ty, xform_ret_ty); // We can't use normalize_associated_types_in as it will pollute the // fcx's fulfillment context after this probe is over. + // Note: we only normalize `xform_self_ty` here since the normalization + // of the return type can lead to inference results that prohibit + // valid canidates from being found, see issue #85671 + // FIXME Postponing the normalization of the return type likely only hides a deeper bug, + // which might be caused by the `param_env` itself. The clauses of the `param_env` + // maybe shouldn't include `Param`s, but rather fresh variables or be canonicalized, + // see isssue #89650 let cause = traits::ObligationCause::misc(self.span, self.body_id); let selcx = &mut traits::SelectionContext::new(self.fcx); - let traits::Normalized { value: (xform_self_ty, xform_ret_ty), obligations } = - traits::normalize(selcx, self.param_env, cause, xform_tys); + let traits::Normalized { value: xform_self_ty, obligations } = + traits::normalize(selcx, self.param_env, cause, xform_self_ty); debug!( - "assemble_inherent_impl_probe: xform_self_ty = {:?}/{:?}", + "assemble_inherent_impl_probe after normalization: xform_self_ty = {:?}/{:?}", xform_self_ty, xform_ret_ty ); @@ -966,8 +974,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { let trait_ref = ty::TraitRef::new(trait_def_id, trait_substs); if self.tcx.is_trait_alias(trait_def_id) { - // For trait aliases, assume all super-traits are relevant. - let bounds = iter::once(trait_ref.to_poly_trait_ref()); + // For trait aliases, assume all supertraits are relevant. + let bounds = iter::once(ty::Binder::dummy(trait_ref)); self.elaborate_bounds(bounds, |this, new_trait_ref, item| { let new_trait_ref = this.erase_late_bound_regions(new_trait_ref); @@ -1372,7 +1380,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { trait_ref: ty::TraitRef<'tcx>, ) -> traits::SelectionResult<'tcx, traits::Selection<'tcx>> { let cause = traits::ObligationCause::misc(self.span, self.body_id); - let predicate = trait_ref.to_poly_trait_ref().to_poly_trait_predicate(); + let predicate = ty::Binder::dummy(trait_ref).to_poly_trait_predicate(); let obligation = traits::Obligation::new(cause, self.param_env, predicate); traits::SelectionContext::new(self).select(&obligation) } @@ -1422,6 +1430,9 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { }; let mut result = ProbeResult::Match; + let mut xform_ret_ty = probe.xform_ret_ty; + debug!(?xform_ret_ty); + let selcx = &mut traits::SelectionContext::new(self); let cause = traits::ObligationCause::misc(self.span, self.body_id); @@ -1431,6 +1442,16 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { // don't have enough information to fully evaluate). match probe.kind { InherentImplCandidate(ref substs, ref ref_obligations) => { + // `xform_ret_ty` hasn't been normalized yet, only `xform_self_ty`, + // see the reasons mentioned in the comments in `assemble_inherent_impl_probe` + // for why this is necessary + let traits::Normalized { + value: normalized_xform_ret_ty, + obligations: normalization_obligations, + } = traits::normalize(selcx, self.param_env, cause.clone(), probe.xform_ret_ty); + xform_ret_ty = normalized_xform_ret_ty; + debug!("xform_ret_ty after normalization: {:?}", xform_ret_ty); + // Check whether the impl imposes obligations we have to worry about. let impl_def_id = probe.item.container.id(); let impl_bounds = self.tcx.predicates_of(impl_def_id); @@ -1444,7 +1465,9 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { let candidate_obligations = impl_obligations .chain(norm_obligations.into_iter()) - .chain(ref_obligations.iter().cloned()); + .chain(ref_obligations.iter().cloned()) + .chain(normalization_obligations.into_iter()); + // Evaluate those obligations to see if they might possibly hold. for o in candidate_obligations { let o = self.resolve_vars_if_possible(o); @@ -1470,7 +1493,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { } } } - let predicate = trait_ref.without_const().to_predicate(self.tcx); + let predicate = + ty::Binder::dummy(trait_ref).without_const().to_predicate(self.tcx); let obligation = traits::Obligation::new(cause, self.param_env, predicate); if !self.predicate_may_hold(&obligation) { result = ProbeResult::NoMatch; @@ -1528,9 +1552,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { } if let ProbeResult::Match = result { - if let (Some(return_ty), Some(xform_ret_ty)) = - (self.return_type, probe.xform_ret_ty) - { + if let (Some(return_ty), Some(xform_ret_ty)) = (self.return_type, xform_ret_ty) { let xform_ret_ty = self.resolve_vars_if_possible(xform_ret_ty); debug!( "comparing return_ty {:?} with xform ret ty {:?}", @@ -1670,6 +1692,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { self.static_candidates.push(source); } + #[instrument(level = "debug", skip(self))] fn xform_self_ty( &self, item: &ty::AssocItem, @@ -1684,9 +1707,10 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { } } + #[instrument(level = "debug", skip(self))] fn xform_method_sig(&self, method: DefId, substs: SubstsRef<'tcx>) -> ty::FnSig<'tcx> { let fn_sig = self.tcx.fn_sig(method); - debug!("xform_self_ty(fn_sig={:?}, substs={:?})", fn_sig, substs); + debug!(?fn_sig); assert!(!substs.has_escaping_bound_vars()); diff --git a/compiler/rustc_typeck/src/check/method/suggest.rs b/compiler/rustc_typeck/src/check/method/suggest.rs index afe274a2a7..183ebc559a 100644 --- a/compiler/rustc_typeck/src/check/method/suggest.rs +++ b/compiler/rustc_typeck/src/check/method/suggest.rs @@ -6,21 +6,18 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Namespace, Res}; -use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX}; -use rustc_hir::intravisit; +use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_INDEX}; use rustc_hir::lang_items::LangItem; use rustc_hir::{ExprKind, Node, QPath}; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_middle::ty::fast_reject::simplify_type; use rustc_middle::ty::print::with_crate_prefix; -use rustc_middle::ty::{ - self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness, -}; +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, Span}; +use rustc_span::{source_map, FileName, MultiSpan, Span}; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt; -use rustc_trait_selection::traits::Obligation; +use rustc_trait_selection::traits::{FulfillmentError, Obligation}; use std::cmp::Ordering; use std::iter; @@ -54,7 +51,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .into()], ); let trait_ref = ty::TraitRef::new(fn_once, fn_once_substs); - let poly_trait_ref = trait_ref.to_poly_trait_ref(); + let poly_trait_ref = ty::Binder::dummy(trait_ref); let obligation = Obligation::misc( span, self.body_id, @@ -179,6 +176,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { sugg_span, idx, self.tcx.sess.source_map(), + item.fn_has_self_parameter, ); } } @@ -221,6 +219,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { sugg_span, idx, self.tcx.sess.source_map(), + item.fn_has_self_parameter, ); } } @@ -329,48 +328,44 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Applicability::MaybeIncorrect, ); } - ExprKind::Path(ref qpath) => { + ExprKind::Path(QPath::Resolved(_, path)) => { // local binding - if let QPath::Resolved(_, path) = qpath { - if let hir::def::Res::Local(hir_id) = path.res { - let span = tcx.hir().span(hir_id); - let snippet = tcx.sess.source_map().span_to_snippet(span); - let filename = tcx.sess.source_map().span_to_filename(span); + if let hir::def::Res::Local(hir_id) = path.res { + let span = tcx.hir().span(hir_id); + let snippet = tcx.sess.source_map().span_to_snippet(span); + let filename = tcx.sess.source_map().span_to_filename(span); - let parent_node = self - .tcx - .hir() - .get(self.tcx.hir().get_parent_node(hir_id)); - let msg = format!( - "you must specify a type for this binding, like `{}`", - concrete_type, - ); + let parent_node = + self.tcx.hir().get(self.tcx.hir().get_parent_node(hir_id)); + let msg = format!( + "you must specify a type for this binding, like `{}`", + concrete_type, + ); - match (filename, parent_node, snippet) { - ( - FileName::Real(_), - Node::Local(hir::Local { - source: hir::LocalSource::Normal, - ty, - .. - }), - Ok(ref snippet), - ) => { - err.span_suggestion( - // account for `let x: _ = 42;` - // ^^^^ - span.to(ty - .as_ref() - .map(|ty| ty.span) - .unwrap_or(span)), - &msg, - format!("{}: {}", snippet, concrete_type), - Applicability::MaybeIncorrect, - ); - } - _ => { - err.span_label(span, msg); - } + match (filename, parent_node, snippet) { + ( + FileName::Real(_), + Node::Local(hir::Local { + source: hir::LocalSource::Normal, + ty, + .. + }), + Ok(ref snippet), + ) => { + err.span_suggestion( + // account for `let x: _ = 42;` + // ^^^^ + span.to(ty + .as_ref() + .map(|ty| ty.span) + .unwrap_or(span)), + &msg, + format!("{}: {}", snippet, concrete_type), + Applicability::MaybeIncorrect, + ); + } + _ => { + err.span_label(span, msg); } } } @@ -384,11 +379,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Don't show generic arguments when the method can't be found in any implementation (#81576). let mut ty_str_reported = ty_str.clone(); - if let ty::Adt(_, ref generics) = actual.kind() { + if let ty::Adt(_, generics) = actual.kind() { if generics.len() > 0 { let mut autoderef = self.autoderef(span, actual); let candidate_found = autoderef.any(|(ty, _)| { - if let ty::Adt(ref adt_deref, _) = ty.kind() { + if let ty::Adt(adt_deref, _) = ty.kind() { self.tcx .inherent_impls(adt_deref.did) .iter() @@ -435,7 +430,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } if let Some(span) = - tcx.sess.confused_type_with_std_module.borrow().get(&span) + tcx.resolutions(()).confused_type_with_std_module.get(&span) { if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(*span) { err.span_suggestion( @@ -483,7 +478,7 @@ 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}`")); - if let ty::Adt(ref adt, _) = rcvr_ty.kind() { + if let ty::Adt(adt, _) = rcvr_ty.kind() { let mut inherent_impls_candidate = self .tcx .inherent_impls(adt.did) @@ -512,7 +507,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } }) .collect::>(); - if inherent_impls_candidate.len() > 0 { + if !inherent_impls_candidate.is_empty() { inherent_impls_candidate.sort(); inherent_impls_candidate.dedup(); @@ -566,7 +561,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let is_accessible = field.vis.is_accessible_from(scope, self.tcx); if is_accessible { - if self.is_fn_ty(&field_ty, span) { + if self.is_fn_ty(field_ty, span) { let expr_span = expr.span.to(item_name.span); err.multipart_suggestion( &format!( @@ -606,7 +601,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { label_span_not_found(); } - if self.is_fn_ty(&rcvr_ty, span) { + if self.is_fn_ty(rcvr_ty, span) { fn report_function( err: &mut DiagnosticBuilder<'_>, name: T, @@ -619,7 +614,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let SelfSource::MethodCall(expr) = source { if let Ok(expr_string) = tcx.sess.source_map().span_to_snippet(expr.span) { report_function(&mut err, expr_string); - } else if let ExprKind::Path(QPath::Resolved(_, ref path)) = expr.kind { + } else if let ExprKind::Path(QPath::Resolved(_, path)) = expr.kind { if let Some(segment) = path.segments.last() { report_function(&mut err, segment.ident); } @@ -743,7 +738,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let projection_ty = pred.skip_binder().projection_ty; let substs_with_infer_self = tcx.mk_substs( - iter::once(tcx.mk_ty_var(ty::TyVid { index: 0 }).into()) + iter::once(tcx.mk_ty_var(ty::TyVid::from_u32(0)).into()) .chain(projection_ty.substs.iter().skip(1)), ); @@ -809,7 +804,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); } - bound_list.sort_by(|(_, a), (_, b)| a.cmp(&b)); // Sort alphabetically. + bound_list.sort_by(|(_, a), (_, b)| a.cmp(b)); // Sort alphabetically. bound_list.dedup_by(|(_, a), (_, b)| a == b); // #35677 bound_list.sort_by_key(|(pos, _)| *pos); // Keep the original predicate order. bound_spans.sort(); @@ -830,6 +825,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err.note(&format!( "the following trait bounds were not satisfied:\n{bound_list}" )); + self.suggest_derive(&mut err, &unsatisfied_predicates); + unsatisfied_bounds = true; } } @@ -972,6 +969,155 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { None } + crate fn note_unmet_impls_on_type( + &self, + err: &mut rustc_errors::DiagnosticBuilder<'_>, + errors: Vec>, + ) { + let all_local_types_needing_impls = + errors.iter().all(|e| match e.obligation.predicate.kind().skip_binder() { + ty::PredicateKind::Trait(pred) => match pred.self_ty().kind() { + ty::Adt(def, _) => def.did.is_local(), + _ => false, + }, + _ => false, + }); + let mut preds: Vec<_> = errors + .iter() + .filter_map(|e| match e.obligation.predicate.kind().skip_binder() { + ty::PredicateKind::Trait(pred) => Some(pred), + _ => None, + }) + .collect(); + preds.sort_by_key(|pred| (pred.def_id(), pred.self_ty())); + let def_ids = preds + .iter() + .filter_map(|pred| match pred.self_ty().kind() { + ty::Adt(def, _) => Some(def.did), + _ => None, + }) + .collect::>(); + let sm = self.tcx.sess.source_map(); + let mut spans: MultiSpan = def_ids + .iter() + .filter_map(|def_id| { + let span = self.tcx.def_span(*def_id); + if span.is_dummy() { None } else { Some(sm.guess_head_span(span)) } + }) + .collect::>() + .into(); + + for pred in &preds { + match pred.self_ty().kind() { + ty::Adt(def, _) => { + spans.push_span_label( + sm.guess_head_span(self.tcx.def_span(def.did)), + format!("must implement `{}`", pred.trait_ref.print_only_trait_path()), + ); + } + _ => {} + } + } + + if all_local_types_needing_impls && spans.primary_span().is_some() { + let msg = if preds.len() == 1 { + format!( + "an implementation of `{}` might be missing for `{}`", + preds[0].trait_ref.print_only_trait_path(), + preds[0].self_ty() + ) + } else { + format!( + "the following type{} would have to `impl` {} required trait{} for this \ + operation to be valid", + pluralize!(def_ids.len()), + if def_ids.len() == 1 { "its" } else { "their" }, + pluralize!(preds.len()), + ) + }; + err.span_note(spans, &msg); + } + + let preds: Vec<_> = errors.iter().map(|e| (e.obligation.predicate, None)).collect(); + self.suggest_derive(err, &preds); + } + + fn suggest_derive( + &self, + err: &mut DiagnosticBuilder<'_>, + unsatisfied_predicates: &Vec<(ty::Predicate<'tcx>, Option>)>, + ) { + let mut derives = Vec::<(String, Span, String)>::new(); + let mut traits = Vec::::new(); + for (pred, _) in unsatisfied_predicates { + let trait_pred = match pred.kind().skip_binder() { + ty::PredicateKind::Trait(trait_pred) => trait_pred, + _ => continue, + }; + let adt = match trait_pred.self_ty().ty_adt_def() { + Some(adt) if adt.did.is_local() => adt, + _ => continue, + }; + let can_derive = match self.tcx.get_diagnostic_name(trait_pred.def_id()) { + Some(sym::Default) => !adt.is_enum(), + Some( + sym::Eq + | sym::PartialEq + | sym::Ord + | sym::PartialOrd + | sym::Clone + | sym::Copy + | sym::Hash + | sym::Debug, + ) => true, + _ => false, + }; + if can_derive { + derives.push(( + format!("{}", trait_pred.self_ty()), + self.tcx.def_span(adt.did), + format!("{}", trait_pred.trait_ref.print_only_trait_name()), + )); + } else { + traits.push(self.tcx.def_span(trait_pred.def_id())); + } + } + derives.sort(); + let derives_grouped = derives.into_iter().fold( + Vec::<(String, Span, String)>::new(), + |mut acc, (self_name, self_span, trait_name)| { + if let Some((acc_self_name, _, ref mut traits)) = acc.last_mut() { + if acc_self_name == &self_name { + traits.push_str(format!(", {}", trait_name).as_str()); + return acc; + } + } + acc.push((self_name, self_span, trait_name)); + acc + }, + ); + traits.sort(); + traits.dedup(); + + let len = traits.len(); + if len > 0 { + let span: MultiSpan = traits.into(); + err.span_note( + span, + &format!("the following trait{} must be implemented", pluralize!(len),), + ); + } + + for (self_name, self_span, traits) in &derives_grouped { + err.span_suggestion_verbose( + self_span.shrink_to_lo(), + &format!("consider annotating `{}` with `#[derive({})]`", self_name, traits), + format!("#[derive({})]\n", traits), + Applicability::MaybeIncorrect, + ); + } + } + /// Print out the type for use in value namespace. fn ty_to_value_string(&self, ty: Ty<'tcx>) -> String { match ty.kind() { @@ -1011,9 +1157,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { candidates: Vec, ) { let module_did = self.tcx.parent_module(self.body_id); - let module_id = self.tcx.hir().local_def_id_to_hir_id(module_did); - let krate = self.tcx.hir().krate(); - let (span, found_use) = UsePlacementFinder::check(self.tcx, krate, module_id); + let (span, found_use) = find_use_placement(self.tcx, module_did); if let Some(span) = span { let path_strings = candidates.iter().map(|did| { // Produce an additional newline to separate the new use statement @@ -1293,9 +1437,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) }; // Obtain the span for `param` and use it for a structured suggestion. - if let (Some(ref param), Some(ref table)) = - (param_type, self.in_progress_typeck_results) - { + if let (Some(param), Some(table)) = (param_type, self.in_progress_typeck_results) { let table_owner = table.borrow().hir_owner; let generics = self.tcx.generics_of(table_owner.to_def_id()); let type_param = generics.type_param(param, self.tcx); @@ -1306,7 +1448,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // We do this to avoid suggesting code that ends up as `T: FooBar`, // instead we suggest `T: Foo + Bar` in that case. match hir.get(id) { - Node::GenericParam(ref param) => { + Node::GenericParam(param) => { let mut impl_trait = false; let has_bounds = if let hir::GenericParamKind::Type { synthetic: Some(_), .. } = @@ -1480,7 +1622,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { match ty.kind() { ty::Adt(def, _) => def.did.is_local(), ty::Foreign(did) => did.is_local(), - ty::Dynamic(ref tr, ..) => tr.principal().map_or(false, |d| d.def_id().is_local()), + ty::Dynamic(tr, ..) => tr.principal().map_or(false, |d| d.def_id().is_local()), ty::Param(_) => true, // Everything else (primitive types, etc.) is effectively @@ -1568,7 +1710,7 @@ fn compute_all_traits(tcx: TyCtxt<'_>, (): ()) -> &[DefId] { fn visit_foreign_item(&mut self, _foreign_item: &hir::ForeignItem<'_>) {} } - tcx.hir().krate().visit_all_item_likes(&mut Visitor { traits: &mut traits }); + tcx.hir().visit_all_item_likes(&mut Visitor { traits: &mut traits }); // Cross-crate: @@ -1577,7 +1719,7 @@ fn compute_all_traits(tcx: TyCtxt<'_>, (): ()) -> &[DefId] { tcx: TyCtxt<'_>, traits: &mut Vec, external_mods: &mut FxHashSet, - res: Res, + res: Res, ) { match res { Res::Def(DefKind::Trait | DefKind::TraitAlias, def_id) => { @@ -1606,64 +1748,38 @@ pub fn provide(providers: &mut ty::query::Providers) { providers.all_traits = compute_all_traits; } -struct UsePlacementFinder<'tcx> { - target_module: hir::HirId, - span: Option, - found_use: bool, - tcx: TyCtxt<'tcx>, -} +fn find_use_placement<'tcx>(tcx: TyCtxt<'tcx>, target_module: LocalDefId) -> (Option, bool) { + let mut span = None; + let mut found_use = false; + let (module, _, _) = tcx.hir().get_module(target_module); -impl UsePlacementFinder<'tcx> { - fn check( - tcx: TyCtxt<'tcx>, - krate: &'tcx hir::Crate<'tcx>, - target_module: hir::HirId, - ) -> (Option, bool) { - let mut finder = UsePlacementFinder { target_module, span: None, found_use: false, tcx }; - intravisit::walk_crate(&mut finder, krate); - (finder.span, finder.found_use) - } -} - -impl intravisit::Visitor<'tcx> for UsePlacementFinder<'tcx> { - fn visit_mod(&mut self, module: &'tcx hir::Mod<'tcx>, _: Span, hir_id: hir::HirId) { - if self.span.is_some() { - return; - } - if hir_id != self.target_module { - intravisit::walk_mod(self, module, hir_id); - return; - } - // Find a `use` statement. - for &item_id in module.item_ids { - let item = self.tcx.hir().item(item_id); - match item.kind { - hir::ItemKind::Use(..) => { - // Don't suggest placing a `use` before the prelude - // import or other generated ones. - if !item.span.from_expansion() { - self.span = Some(item.span.shrink_to_lo()); - self.found_use = true; - return; - } + // Find a `use` statement. + for &item_id in module.item_ids { + let item = tcx.hir().item(item_id); + match item.kind { + hir::ItemKind::Use(..) => { + // Don't suggest placing a `use` before the prelude + // import or other generated ones. + if !item.span.from_expansion() { + span = Some(item.span.shrink_to_lo()); + found_use = true; + break; } - // Don't place `use` before `extern crate`... - hir::ItemKind::ExternCrate(_) => {} - // ...but do place them before the first other item. - _ => { - if self.span.map_or(true, |span| item.span < span) { - if !item.span.from_expansion() { - self.span = Some(item.span.shrink_to_lo()); - // Don't insert between attributes and an item. - let attrs = self.tcx.hir().attrs(item.hir_id()); - // Find the first attribute on the item. - // FIXME: This is broken for active attributes. - for attr in attrs { - if !attr.span.is_dummy() - && self.span.map_or(true, |span| attr.span < span) - { - self.span = Some(attr.span.shrink_to_lo()); - } + } + // Don't place `use` before `extern crate`... + hir::ItemKind::ExternCrate(_) => {} + // ...but do place them before the first other item. + _ => { + if span.map_or(true, |span| item.span < span) { + if !item.span.from_expansion() { + span = Some(item.span.shrink_to_lo()); + // Don't insert between attributes and an item. + let attrs = tcx.hir().attrs(item.hir_id()); + // Find the first attribute on the item. + // FIXME: This is broken for active attributes. + for attr in attrs { + if !attr.span.is_dummy() && span.map_or(true, |span| attr.span < span) { + span = Some(attr.span.shrink_to_lo()); } } } @@ -1672,11 +1788,7 @@ impl intravisit::Visitor<'tcx> for UsePlacementFinder<'tcx> { } } - type Map = intravisit::ErasedMap<'tcx>; - - fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap { - intravisit::NestedVisitorMap::None - } + (span, found_use) } fn print_disambiguation_help( @@ -1690,6 +1802,7 @@ fn print_disambiguation_help( span: Span, candidate: Option, source_map: &source_map::SourceMap, + fn_has_self_parameter: bool, ) { let mut applicability = Applicability::MachineApplicable; let (span, sugg) = if let (ty::AssocKind::Fn, Some(args)) = (kind, args) { @@ -1708,9 +1821,14 @@ fn print_disambiguation_help( .collect::>() .join(", "), ); + let trait_name = if !fn_has_self_parameter { + format!("<{} as {}>", rcvr_ty, trait_name) + } else { + trait_name + }; (span, format!("{}::{}{}", trait_name, item_name, args)) } else { - (span.with_hi(item_name.span.lo()), format!("{}::", trait_name)) + (span.with_hi(item_name.span.lo()), format!("<{} as {}>::", rcvr_ty, trait_name)) }; err.span_suggestion_verbose( span, diff --git a/compiler/rustc_typeck/src/check/mod.rs b/compiler/rustc_typeck/src/check/mod.rs index 803c440bbc..a037bb6647 100644 --- a/compiler/rustc_typeck/src/check/mod.rs +++ b/compiler/rustc_typeck/src/check/mod.rs @@ -271,22 +271,22 @@ fn primary_body_of( ) -> Option<(hir::BodyId, Option<&hir::Ty<'_>>, Option<&hir::FnSig<'_>>)> { match tcx.hir().get(id) { Node::Item(item) => match item.kind { - hir::ItemKind::Const(ref ty, body) | hir::ItemKind::Static(ref ty, _, body) => { + hir::ItemKind::Const(ty, body) | hir::ItemKind::Static(ty, _, body) => { Some((body, Some(ty), None)) } - hir::ItemKind::Fn(ref sig, .., body) => Some((body, None, Some(&sig))), + hir::ItemKind::Fn(ref sig, .., body) => Some((body, None, Some(sig))), _ => None, }, Node::TraitItem(item) => match item.kind { - hir::TraitItemKind::Const(ref ty, Some(body)) => Some((body, Some(ty), None)), + hir::TraitItemKind::Const(ty, Some(body)) => Some((body, Some(ty), None)), hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(body)) => { - Some((body, None, Some(&sig))) + Some((body, None, Some(sig))) } _ => None, }, Node::ImplItem(item) => match item.kind { - hir::ImplItemKind::Const(ref ty, body) => Some((body, Some(ty), None)), - hir::ImplItemKind::Fn(ref sig, body) => Some((body, None, Some(&sig))), + hir::ImplItemKind::Const(ty, body) => Some((body, Some(ty), None)), + hir::ImplItemKind::Fn(ref sig, body) => Some((body, None, Some(sig))), _ => None, }, Node::AnonConst(constant) => Some((constant.body, None, None)), @@ -388,10 +388,9 @@ fn typeck_with_fallback<'tcx>( // from normalization. We could just discard these, but to align with // compare_method and elsewhere, we just add implied bounds for // these types. - let mut wf_tys = vec![]; + let mut wf_tys = FxHashSet::default(); // Compute the fty from point of view of inside the fn. let fn_sig = tcx.liberate_late_bound_regions(def_id.to_def_id(), fn_sig); - wf_tys.extend(fn_sig.inputs_and_output.iter()); let fn_sig = inh.normalize_associated_types_in( body.value.span, body_id.hir_id, @@ -451,7 +450,7 @@ fn typeck_with_fallback<'tcx>( fcx.write_ty(id, expected_type); - (fcx, vec![]) + (fcx, FxHashSet::default()) }; let fallback_has_occurred = fcx.type_inference_fallback(); @@ -475,7 +474,7 @@ fn typeck_with_fallback<'tcx>( fcx.select_all_obligations_or_error(); if fn_sig.is_some() { - fcx.regionck_fn(id, body, span, &wf_tys); + fcx.regionck_fn(id, body, span, wf_tys); } else { fcx.regionck_expr(body); } @@ -555,16 +554,13 @@ fn maybe_check_static_with_link_section(tcx: TyCtxt<'_>, id: LocalDefId, span: S // `#[link_section]` may contain arbitrary, or even undefined bytes, but it is // the consumer's responsibility to ensure all bytes that have been read // have defined values. - match tcx.eval_static_initializer(id.to_def_id()) { - Ok(alloc) => { - if alloc.relocations().len() != 0 { - let msg = "statics with a custom `#[link_section]` must be a \ + if let Ok(alloc) = tcx.eval_static_initializer(id.to_def_id()) { + if alloc.relocations().len() != 0 { + let msg = "statics with a custom `#[link_section]` must be a \ simple list of bytes on the wasm target with no \ extra levels of indirection such as references"; - tcx.sess.span_err(span, msg); - } + tcx.sess.span_err(span, msg); } - Err(_) => {} } } @@ -631,7 +627,7 @@ fn missing_items_err( let padding: String = " ".repeat(indentation); for trait_item in missing_items { - let snippet = suggestion_signature(&trait_item, tcx); + let snippet = suggestion_signature(trait_item, tcx); let code = format!("{}{}\n{}", padding, snippet, padding); let msg = format!("implement the missing item: `{}`", snippet); let appl = Applicability::HasPlaceholders; @@ -921,9 +917,7 @@ impl ItemLikeVisitor<'tcx> for CheckItemTypesVisitor<'tcx> { } fn typeck_item_bodies(tcx: TyCtxt<'_>, (): ()) { - tcx.par_body_owners(|body_owner_def_id| { - tcx.ensure().typeck(body_owner_def_id); - }); + tcx.hir().par_body_owners(|body_owner_def_id| tcx.ensure().typeck(body_owner_def_id)); } fn fatally_break_rust(sess: &Session) { diff --git a/compiler/rustc_typeck/src/check/op.rs b/compiler/rustc_typeck/src/check/op.rs index 9b495fba19..79e004a47d 100644 --- a/compiler/rustc_typeck/src/check/op.rs +++ b/compiler/rustc_typeck/src/check/op.rs @@ -18,6 +18,7 @@ use rustc_span::source_map::Spanned; use rustc_span::symbol::{sym, Ident}; use rustc_span::Span; use rustc_trait_selection::infer::InferCtxtExt; +use rustc_trait_selection::traits::{FulfillmentError, TraitEngine, TraitEngineExt}; use std::ops::ControlFlow; @@ -257,12 +258,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { method.sig.output() } // error types are considered "builtin" - Err(()) if lhs_ty.references_error() || rhs_ty.references_error() => { - self.tcx.ty_error() - } - Err(()) => { + Err(_) if lhs_ty.references_error() || rhs_ty.references_error() => self.tcx.ty_error(), + Err(errors) => { let source_map = self.tcx.sess.source_map(); - let (mut err, missing_trait, use_output, involves_fn) = match is_assign { + let (mut err, missing_trait, use_output) = match is_assign { IsAssign::Yes => { let mut err = struct_span_err!( self.tcx.sess, @@ -289,7 +288,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { hir::BinOpKind::Shr => Some("std::ops::ShrAssign"), _ => None, }; - (err, missing_trait, false, false) + self.note_unmet_impls_on_type(&mut err, errors); + (err, missing_trait, false) } IsAssign::No => { let (message, missing_trait, use_output) = match op.node { @@ -376,9 +376,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; let mut err = struct_span_err!(self.tcx.sess, op.span, E0369, "{}", message.as_str()); - let mut involves_fn = false; if !lhs_expr.span.eq(&rhs_expr.span) { - involves_fn |= self.add_type_neq_err_label( + self.add_type_neq_err_label( &mut err, lhs_expr.span, lhs_ty, @@ -386,7 +385,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { op, is_assign, ); - involves_fn |= self.add_type_neq_err_label( + self.add_type_neq_err_label( &mut err, rhs_expr.span, rhs_ty, @@ -395,10 +394,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { is_assign, ); } - (err, missing_trait, use_output, involves_fn) + self.note_unmet_impls_on_type(&mut err, errors); + (err, missing_trait, use_output) } }; - let mut suggested_deref = false; if let Ref(_, rty, _) = lhs_ty.kind() { if { self.infcx.type_is_copy_modulo_regions(self.param_env, rty, lhs_expr.span) @@ -423,7 +422,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { "*".to_string(), rustc_errors::Applicability::MachineApplicable, ); - suggested_deref = true; } } } @@ -444,7 +442,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Check if the method would be found if the type param wasn't // involved. If so, it means that adding a trait bound to the param is // enough. Otherwise we do not give the suggestion. - let mut eraser = TypeParamEraser(&self, expr.span); + let mut eraser = TypeParamEraser(self, expr.span); let needs_bound = self .lookup_op_method( eraser.fold_ty(lhs_ty), @@ -474,8 +472,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } else { bug!("type param visitor stored a non type param: {:?}", ty.kind()); } - } else if !suggested_deref && !involves_fn { - suggest_impl_missing(&mut err, lhs_ty, &missing_trait); } } err.emit(); @@ -572,7 +568,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { on the left and may require reallocation. This \ requires ownership of the string on the left"; - let string_type = self.tcx.get_diagnostic_item(sym::string_type); + let string_type = self.tcx.get_diagnostic_item(sym::String); let is_std_string = |ty: Ty<'tcx>| match ty.ty_adt_def() { Some(ty_def) => Some(ty_def.did) == string_type, None => false, @@ -665,7 +661,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.write_method_call(ex.hir_id, method); method.sig.output() } - Err(()) => { + Err(errors) => { let actual = self.resolve_vars_if_possible(operand_ty); if !actual.references_error() { let mut err = struct_span_err!( @@ -680,42 +676,48 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ex.span, format!("cannot apply unary operator `{}`", op.as_str()), ); - match actual.kind() { - Uint(_) if op == hir::UnOp::Neg => { - err.note("unsigned values cannot be negated"); - if let hir::ExprKind::Unary( - _, - hir::Expr { - kind: - hir::ExprKind::Lit(Spanned { - node: ast::LitKind::Int(1, _), - .. - }), - .. - }, - ) = ex.kind - { - err.span_suggestion( - ex.span, - &format!( - "you may have meant the maximum value of `{}`", - actual - ), - format!("{}::MAX", actual), - Applicability::MaybeIncorrect, - ); + let sp = self.tcx.sess.source_map().start_point(ex.span); + if let Some(sp) = + self.tcx.sess.parse_sess.ambiguous_block_expr_parse.borrow().get(&sp) + { + // If the previous expression was a block expression, suggest parentheses + // (turning this into a binary subtraction operation instead.) + // for example, `{2} - 2` -> `({2}) - 2` (see src\test\ui\parser\expr-as-stmt.rs) + self.tcx.sess.parse_sess.expr_parentheses_needed(&mut err, *sp); + } else { + match actual.kind() { + Uint(_) if op == hir::UnOp::Neg => { + err.note("unsigned values cannot be negated"); + + if let hir::ExprKind::Unary( + _, + hir::Expr { + kind: + hir::ExprKind::Lit(Spanned { + node: ast::LitKind::Int(1, _), + .. + }), + .. + }, + ) = ex.kind + { + err.span_suggestion( + ex.span, + &format!( + "you may have meant the maximum value of `{}`", + actual + ), + format!("{}::MAX", actual), + Applicability::MaybeIncorrect, + ); + } + } + Str | Never | Char | Tuple(_) | Array(_, _) => {} + Ref(_, lty, _) if *lty.kind() == Str => {} + _ => { + self.note_unmet_impls_on_type(&mut err, errors); } - } - Str | Never | Char | Tuple(_) | Array(_, _) => {} - Ref(_, ref lty, _) if *lty.kind() == Str => {} - _ => { - let missing_trait = match op { - hir::UnOp::Neg => "std::ops::Neg", - hir::UnOp::Not => "std::ops::Not", - hir::UnOp::Deref => "std::ops::UnDerf", - }; - suggest_impl_missing(&mut err, operand_ty, &missing_trait); } } err.emit(); @@ -730,7 +732,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { lhs_ty: Ty<'tcx>, other_tys: &[Ty<'tcx>], op: Op, - ) -> Result, ()> { + ) -> Result, Vec>> { let lang = self.tcx.lang_items(); let span = match op { @@ -809,22 +811,31 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Op::Unary(..) => 0, }, ) { - return Err(()); + return Err(vec![]); } + let opname = Ident::with_dummy_span(opname); let method = trait_did.and_then(|trait_did| { - let opname = Ident::with_dummy_span(opname); self.lookup_method_in_trait(span, opname, trait_did, lhs_ty, Some(other_tys)) }); - match method { - Some(ok) => { + match (method, trait_did) { + (Some(ok), _) => { let method = self.register_infer_ok_obligations(ok); self.select_obligations_where_possible(false, |_| {}); - Ok(method) } - None => Err(()), + (None, None) => Err(vec![]), + (None, Some(trait_did)) => { + let (obligation, _) = + 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![], + }) + } } } } @@ -951,18 +962,6 @@ fn is_builtin_binop<'tcx>(lhs: Ty<'tcx>, rhs: Ty<'tcx>, op: hir::BinOp) -> bool } } -/// If applicable, note that an implementation of `trait` for `ty` may fix the error. -fn suggest_impl_missing(err: &mut DiagnosticBuilder<'_>, ty: Ty<'_>, missing_trait: &str) { - if let Adt(def, _) = ty.peel_refs().kind() { - if def.did.is_local() { - err.note(&format!( - "an implementation of `{}` might be missing for `{}`", - missing_trait, ty - )); - } - } -} - fn suggest_constraining_param( tcx: TyCtxt<'_>, body_id: hir::HirId, diff --git a/compiler/rustc_typeck/src/check/pat.rs b/compiler/rustc_typeck/src/check/pat.rs index 140a9d1126..635219146d 100644 --- a/compiler/rustc_typeck/src/check/pat.rs +++ b/compiler/rustc_typeck/src/check/pat.rs @@ -11,6 +11,7 @@ use rustc_infer::infer; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_middle::ty::subst::GenericArg; use rustc_middle::ty::{self, Adt, BindingMode, Ty, TypeFoldable}; +use rustc_session::lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS; use rustc_span::hygiene::DesugaringKind; use rustc_span::lev_distance::find_best_match_for_name; use rustc_span::source_map::{Span, Spanned}; @@ -180,8 +181,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.check_pat_tuple_struct(pat, qpath, subpats, ddpos, expected, def_bm, ti) } PatKind::Path(_) => self.check_pat_path(pat, path_res.unwrap(), expected, ti), - PatKind::Struct(ref qpath, fields, etc) => { - self.check_pat_struct(pat, qpath, fields, etc, expected, def_bm, ti) + PatKind::Struct(ref qpath, fields, has_rest_pat) => { + self.check_pat_struct(pat, qpath, fields, has_rest_pat, expected, def_bm, ti) } PatKind::Or(pats) => { let parent_pat = Some(pat); @@ -340,7 +341,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expected: Ty<'tcx>, mut def_bm: BindingMode, ) -> (Ty<'tcx>, BindingMode) { - let mut expected = self.resolve_vars_with_obligations(&expected); + let mut expected = self.resolve_vars_with_obligations(expected); // Peel off as many `&` or `&mut` from the scrutinee type as possible. For example, // for `match &&&mut Some(5)` the loop runs three times, aborting when it reaches @@ -448,16 +449,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ti: TopInfo<'tcx>, ) -> Ty<'tcx> { let calc_side = |opt_expr: Option<&'tcx hir::Expr<'tcx>>| match opt_expr { - None => (None, None), + None => None, Some(expr) => { let ty = self.check_expr(expr); - // Check that the end-point is of numeric or char type. - let fail = !(ty.is_numeric() || ty.is_char() || ty.references_error()); - (Some(ty), Some((fail, ty, expr.span))) + // Check that the end-point is possibly of numeric or char type. + // The early check here is not for correctness, but rather better + // diagnostics (e.g. when `&str` is being matched, `expected` will + // be peeled to `str` while ty here is still `&str`, if we don't + // err ealy here, a rather confusing unification error will be + // emitted instead). + let fail = + !(ty.is_numeric() || ty.is_char() || ty.is_ty_var() || ty.references_error()); + Some((fail, ty, expr.span)) } }; - let (lhs_ty, lhs) = calc_side(lhs); - let (rhs_ty, rhs) = calc_side(rhs); + let mut lhs = calc_side(lhs); + let mut rhs = calc_side(rhs); if let (Some((true, ..)), _) | (_, Some((true, ..))) = (lhs, rhs) { // There exists a side that didn't meet our criteria that the end-point @@ -466,25 +473,42 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return self.tcx.ty_error(); } - // Now that we know the types can be unified we find the unified type - // and use it to type the entire expression. - let common_type = self.resolve_vars_if_possible(lhs_ty.or(rhs_ty).unwrap_or(expected)); - + // Unify each side with `expected`. // Subtyping doesn't matter here, as the value is some kind of scalar. - let demand_eqtype = |x, y| { - if let Some((_, x_ty, x_span)) = x { + let demand_eqtype = |x: &mut _, y| { + if let Some((ref mut fail, x_ty, x_span)) = *x { if let Some(mut err) = self.demand_eqtype_pat_diag(x_span, expected, x_ty, ti) { if let Some((_, y_ty, y_span)) = y { self.endpoint_has_type(&mut err, y_span, y_ty); } err.emit(); + *fail = true; }; } }; - demand_eqtype(lhs, rhs); - demand_eqtype(rhs, lhs); + demand_eqtype(&mut lhs, rhs); + demand_eqtype(&mut rhs, lhs); - common_type + if let (Some((true, ..)), _) | (_, Some((true, ..))) = (lhs, rhs) { + return self.tcx.ty_error(); + } + + // Find the unified type and check if it's of numeric or char type again. + // This check is needed if both sides are inference variables. + // We require types to be resolved here so that we emit inference failure + // rather than "_ is not a char or numeric". + let ty = self.structurally_resolved_type(span, expected); + if !(ty.is_numeric() || ty.is_char() || ty.references_error()) { + if let Some((ref mut fail, _, _)) = lhs { + *fail = true; + } + if let Some((ref mut fail, _, _)) = rhs { + *fail = true; + } + self.emit_err_pat_range(span, lhs, rhs); + return self.tcx.ty_error(); + } + ty } fn endpoint_has_type(&self, err: &mut DiagnosticBuilder<'_>, span: Span, ty: Ty<'_>) { @@ -511,10 +535,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { E0029, "only `char` and numeric types are allowed in range patterns" ); - let msg = |ty| format!("this is of type `{}` but it should be `char` or numeric", ty); + let msg = |ty| { + let ty = self.resolve_vars_if_possible(ty); + format!("this is of type `{}` but it should be `char` or numeric", ty) + }; let mut one_side_err = |first_span, first_ty, second: Option<(bool, Ty<'tcx>, Span)>| { err.span_label(first_span, &msg(first_ty)); if let Some((_, ty, sp)) = second { + let ty = self.resolve_vars_if_possible(ty); self.endpoint_has_type(&mut err, sp, ty); } }; @@ -586,7 +614,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } if let Some(p) = sub { - self.check_pat(&p, expected, def_bm, TopInfo { parent_pat: Some(&pat), ..ti }); + self.check_pat(p, expected, def_bm, TopInfo { parent_pat: Some(pat), ..ti }); } local_ty @@ -684,7 +712,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pat: &'tcx Pat<'tcx>, qpath: &hir::QPath<'_>, fields: &'tcx [hir::PatField<'tcx>], - etc: bool, + has_rest_pat: bool, expected: Ty<'tcx>, def_bm: BindingMode, ti: TopInfo<'tcx>, @@ -696,8 +724,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } else { let err = self.tcx.ty_error(); for field in fields { - let ti = TopInfo { parent_pat: Some(&pat), ..ti }; - self.check_pat(&field.pat, err, def_bm, ti); + let ti = TopInfo { parent_pat: Some(pat), ..ti }; + self.check_pat(field.pat, err, def_bm, ti); } return err; }; @@ -706,7 +734,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.demand_eqtype_pat(pat.span, expected, pat_ty, ti); // Type-check subpatterns. - if self.check_struct_pat_fields(pat_ty, &pat, variant, fields, etc, def_bm, ti) { + if self.check_struct_pat_fields(pat_ty, &pat, variant, fields, has_rest_pat, def_bm, ti) { pat_ty } else { self.tcx.ty_error() @@ -875,7 +903,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let on_error = || { let parent_pat = Some(pat); for pat in subpats { - self.check_pat(&pat, tcx.ty_error(), def_bm, TopInfo { parent_pat, ..ti }); + self.check_pat(pat, tcx.ty_error(), def_bm, TopInfo { parent_pat, ..ti }); } }; let report_unexpected_res = |res: Res| { @@ -960,7 +988,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; for (i, subpat) in subpats.iter().enumerate_and_adjust(variant.fields.len(), ddpos) { let field_ty = self.field_ty(subpat.span, &variant.fields[i], substs); - self.check_pat(&subpat, field_ty, def_bm, TopInfo { parent_pat: Some(&pat), ..ti }); + self.check_pat(subpat, field_ty, def_bm, TopInfo { parent_pat: Some(pat), ..ti }); self.tcx.check_stability( variant.fields[i].did, @@ -1150,7 +1178,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut expected_len = elements.len(); if ddpos.is_some() { // Require known type only when `..` is present. - if let ty::Tuple(ref tys) = self.structurally_resolved_type(span, expected).kind() { + if let ty::Tuple(tys) = self.structurally_resolved_type(span, expected).kind() { expected_len = tys.len(); } } @@ -1171,12 +1199,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // further errors being emitted when using the bindings. #50333 let element_tys_iter = (0..max_len).map(|_| tcx.ty_error()); for (_, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) { - self.check_pat(elem, &tcx.ty_error(), def_bm, ti); + self.check_pat(elem, tcx.ty_error(), def_bm, ti); } tcx.mk_tup(element_tys_iter) } else { for (i, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) { - self.check_pat(elem, &element_tys[i].expect_ty(), def_bm, ti); + self.check_pat(elem, element_tys[i].expect_ty(), def_bm, ti); } pat_ty } @@ -1188,7 +1216,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pat: &'tcx Pat<'tcx>, variant: &'tcx ty::VariantDef, fields: &'tcx [hir::PatField<'tcx>], - etc: bool, + has_rest_pat: bool, def_bm: BindingMode, ti: TopInfo<'tcx>, ) -> bool { @@ -1239,14 +1267,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } }; - self.check_pat(&field.pat, field_ty, def_bm, TopInfo { parent_pat: Some(&pat), ..ti }); + self.check_pat(field.pat, field_ty, def_bm, TopInfo { parent_pat: Some(pat), ..ti }); } let mut unmentioned_fields = variant .fields .iter() .map(|field| (field, field.ident.normalize_to_macros_2_0())) - .filter(|(_, ident)| !used_fields.contains_key(&ident)) + .filter(|(_, ident)| !used_fields.contains_key(ident)) .collect::>(); let inexistent_fields_err = if !(inexistent_fields.is_empty() || variant.is_recovered()) { @@ -1261,7 +1289,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; // Require `..` if struct has non_exhaustive attribute. - if variant.is_field_list_non_exhaustive() && !adt.did.is_local() && !etc { + let non_exhaustive = variant.is_field_list_non_exhaustive() && !adt.did.is_local(); + if non_exhaustive && !has_rest_pat { self.error_foreign_non_exhaustive_spat(pat, adt.variant_descr(), fields.is_empty()); } @@ -1273,10 +1302,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .struct_span_err(pat.span, "union patterns should have exactly one field") .emit(); } - if etc { + if has_rest_pat { tcx.sess.struct_span_err(pat.span, "`..` cannot be used in union patterns").emit(); } - } else if !etc && !unmentioned_fields.is_empty() { + } else if !unmentioned_fields.is_empty() { let accessible_unmentioned_fields: Vec<_> = unmentioned_fields .iter() .copied() @@ -1285,15 +1314,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }) .collect(); - if accessible_unmentioned_fields.is_empty() { - unmentioned_err = Some(self.error_no_accessible_fields(pat, &fields)); - } else { - unmentioned_err = Some(self.error_unmentioned_fields( + if !has_rest_pat { + if accessible_unmentioned_fields.is_empty() { + unmentioned_err = Some(self.error_no_accessible_fields(pat, fields)); + } else { + unmentioned_err = Some(self.error_unmentioned_fields( + pat, + &accessible_unmentioned_fields, + accessible_unmentioned_fields.len() != unmentioned_fields.len(), + fields, + )); + } + } else if non_exhaustive && !accessible_unmentioned_fields.is_empty() { + self.lint_non_exhaustive_omitted_patterns( pat, &accessible_unmentioned_fields, - accessible_unmentioned_fields.len() != unmentioned_fields.len(), - &fields, - )); + adt_ty, + ) } } match (inexistent_fields_err, unmentioned_err) { @@ -1447,7 +1484,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { plural ), ); - if plural == "" { + + if unmentioned_fields.len() == 1 { let input = unmentioned_fields.iter().map(|(_, field)| field.name).collect::>(); let suggested_name = find_best_match_for_name(&input, ident.name, None); @@ -1468,6 +1506,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // We don't want to throw `E0027` in case we have thrown `E0026` for them. unmentioned_fields.retain(|&(_, x)| x.name != suggested_name); } + } else if inexistent_fields.len() == 1 { + let unmentioned_field = unmentioned_fields[0].1.name; + err.span_suggestion_short( + ident.span, + &format!( + "`{}` has a field named `{}`", + tcx.def_path_str(variant.def_id), + unmentioned_field + ), + unmentioned_field.to_string(), + Applicability::MaybeIncorrect, + ); } } } @@ -1604,6 +1654,51 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err } + /// Report that a pattern for a `#[non_exhaustive]` struct marked with `non_exhaustive_omitted_patterns` + /// is not exhaustive enough. + /// + /// Nb: the partner lint for enums lives in `compiler/rustc_mir_build/src/thir/pattern/usefulness.rs`. + fn lint_non_exhaustive_omitted_patterns( + &self, + pat: &Pat<'_>, + unmentioned_fields: &[(&ty::FieldDef, Ident)], + ty: Ty<'tcx>, + ) { + fn joined_uncovered_patterns(witnesses: &[&Ident]) -> String { + const LIMIT: usize = 3; + match witnesses { + [] => bug!(), + [witness] => format!("`{}`", witness), + [head @ .., tail] if head.len() < LIMIT => { + let head: Vec<_> = head.iter().map(<_>::to_string).collect(); + format!("`{}` and `{}`", head.join("`, `"), tail) + } + _ => { + let (head, tail) = witnesses.split_at(LIMIT); + let head: Vec<_> = head.iter().map(<_>::to_string).collect(); + format!("`{}` and {} more", head.join("`, `"), tail.len()) + } + } + } + let joined_patterns = joined_uncovered_patterns( + &unmentioned_fields.iter().map(|(_, i)| i).collect::>(), + ); + + self.tcx.struct_span_lint_hir(NON_EXHAUSTIVE_OMITTED_PATTERNS, pat.hir_id, pat.span, |build| { + let mut lint = build.build("some fields are not explicitly listed"); + lint.span_label(pat.span, format!("field{} {} not listed", rustc_errors::pluralize!(unmentioned_fields.len()), joined_patterns)); + + lint.help( + "ensure that all fields are mentioned explicitly by adding the suggested fields", + ); + lint.note(&format!( + "the pattern is of type `{}` and the `non_exhaustive_omitted_patterns` attribute was found", + ty, + )); + lint.emit(); + }); + } + /// Returns a diagnostic reporting a struct pattern which does not mention some fields. /// /// ```text @@ -1700,7 +1795,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ti: TopInfo<'tcx>, ) -> Ty<'tcx> { let tcx = self.tcx; - let (box_ty, inner_ty) = if self.check_dereferenceable(span, expected, &inner) { + let (box_ty, inner_ty) = if self.check_dereferenceable(span, expected, inner) { // Here, `demand::subtype` is good enough, but I don't // think any errors can be introduced by using `demand::eqtype`. let inner_ty = self.next_ty_var(TypeVariableOrigin { @@ -1714,7 +1809,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let err = tcx.ty_error(); (err, err) }; - self.check_pat(&inner, inner_ty, def_bm, ti); + self.check_pat(inner, inner_ty, def_bm, ti); box_ty } @@ -1729,7 +1824,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) -> Ty<'tcx> { let tcx = self.tcx; let expected = self.shallow_resolve(expected); - let (rptr_ty, inner_ty) = if self.check_dereferenceable(pat.span, expected, &inner) { + let (rptr_ty, inner_ty) = if self.check_dereferenceable(pat.span, expected, inner) { // `demand::subtype` would be good enough, but using `eqtype` turns // out to be equally general. See (note_1) for details. @@ -1751,7 +1846,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Look for a case like `fn foo(&foo: u32)` and suggest // `fn foo(foo: &u32)` if let Some(mut err) = err { - self.borrow_pat_suggestion(&mut err, &pat, &inner, &expected); + self.borrow_pat_suggestion(&mut err, pat, inner, expected); err.emit(); } (rptr_ty, inner_ty) @@ -1761,7 +1856,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let err = tcx.ty_error(); (err, err) }; - self.check_pat(&inner, inner_ty, def_bm, TopInfo { parent_pat: Some(&pat), ..ti }); + self.check_pat(inner, inner_ty, def_bm, TopInfo { parent_pat: Some(pat), ..ti }); rptr_ty } @@ -1817,15 +1912,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Type check all the patterns before `slice`. for elt in before { - self.check_pat(&elt, element_ty, def_bm, ti); + self.check_pat(elt, element_ty, def_bm, ti); } // Type check the `slice`, if present, against its expected type. if let Some(slice) = slice { - self.check_pat(&slice, opt_slice_ty.unwrap(), def_bm, ti); + self.check_pat(slice, opt_slice_ty.unwrap(), def_bm, ti); } // Type check the elements after `slice`, if present. for elt in after { - self.check_pat(&elt, element_ty, def_bm, ti); + self.check_pat(elt, element_ty, def_bm, ti); } inferred } diff --git a/compiler/rustc_typeck/src/check/place_op.rs b/compiler/rustc_typeck/src/check/place_op.rs index 055072d3a1..849bf1e455 100644 --- a/compiler/rustc_typeck/src/check/place_op.rs +++ b/compiler/rustc_typeck/src/check/place_op.rs @@ -1,5 +1,7 @@ use crate::check::method::MethodCallee; use crate::check::{has_expected_num_generic_args, FnCtxt, PlaceOp}; +use rustc_ast as ast; +use rustc_errors::Applicability; use rustc_hir as hir; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::infer::InferOk; @@ -47,6 +49,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expr: &hir::Expr<'_>, base_expr: &'tcx hir::Expr<'tcx>, base_ty: Ty<'tcx>, + index_expr: &'tcx hir::Expr<'tcx>, idx_ty: Ty<'tcx>, ) -> Option<(/*index type*/ Ty<'tcx>, /*element type*/ Ty<'tcx>)> { // FIXME(#18741) -- this is almost but not quite the same as the @@ -56,12 +59,42 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut autoderef = self.autoderef(base_expr.span, base_ty); let mut result = None; while result.is_none() && autoderef.next().is_some() { - result = self.try_index_step(expr, base_expr, &autoderef, idx_ty); + result = self.try_index_step(expr, base_expr, &autoderef, idx_ty, index_expr); } self.register_predicates(autoderef.into_obligations()); result } + fn negative_index( + &self, + ty: Ty<'tcx>, + span: Span, + base_expr: &hir::Expr<'_>, + ) -> Option<(Ty<'tcx>, Ty<'tcx>)> { + let ty = self.resolve_vars_if_possible(ty); + let mut err = self.tcx.sess.struct_span_err( + span, + &format!("negative integers cannot be used to index on a `{}`", ty), + ); + err.span_label(span, &format!("cannot use a negative integer for indexing on `{}`", ty)); + if let (hir::ExprKind::Path(..), Ok(snippet)) = + (&base_expr.kind, self.tcx.sess.source_map().span_to_snippet(base_expr.span)) + { + // `foo[-1]` to `foo[foo.len() - 1]` + err.span_suggestion_verbose( + span.shrink_to_lo(), + &format!( + "to access an element starting from the end of the `{}`, compute the index", + ty, + ), + format!("{}.len() ", snippet), + Applicability::MachineApplicable, + ); + } + err.emit(); + Some((self.tcx.ty_error(), self.tcx.ty_error())) + } + /// To type-check `base_expr[index_expr]`, we progressively autoderef /// (and otherwise adjust) `base_expr`, looking for a type which either /// supports builtin indexing or overloaded indexing. @@ -73,6 +106,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { base_expr: &hir::Expr<'_>, autoderef: &Autoderef<'a, 'tcx>, index_ty: Ty<'tcx>, + index_expr: &hir::Expr<'_>, ) -> Option<(/*index type*/ Ty<'tcx>, /*element type*/ Ty<'tcx>)> { let adjusted_ty = self.structurally_resolved_type(autoderef.span(), autoderef.final_ty(false)); @@ -82,6 +116,27 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expr, base_expr, adjusted_ty, index_ty ); + if let hir::ExprKind::Unary( + hir::UnOp::Neg, + hir::Expr { + kind: hir::ExprKind::Lit(hir::Lit { node: ast::LitKind::Int(..), .. }), + .. + }, + ) = index_expr.kind + { + match adjusted_ty.kind() { + ty::Adt(ty::AdtDef { did, .. }, _) + if self.tcx.is_diagnostic_item(sym::Vec, *did) => + { + return self.negative_index(adjusted_ty, index_expr.span, base_expr); + } + ty::Slice(_) | ty::Array(_, _) => { + return self.negative_index(adjusted_ty, index_expr.span, base_expr); + } + _ => {} + } + } + for unsize in [false, true] { let mut self_ty = adjusted_ty; if unsize { @@ -233,7 +288,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { | hir::ExprKind::Index(ref expr, _) | hir::ExprKind::Unary(hir::UnOp::Deref, ref expr) = exprs.last().unwrap().kind { - exprs.push(&expr); + exprs.push(expr); } debug!("convert_place_derefs_to_mutable: exprs={:?}", exprs); @@ -295,10 +350,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } match expr.kind { - hir::ExprKind::Index(ref base_expr, ..) => { + hir::ExprKind::Index(base_expr, ..) => { self.convert_place_op_to_mutable(PlaceOp::Index, expr, base_expr); } - hir::ExprKind::Unary(hir::UnOp::Deref, ref base_expr) => { + hir::ExprKind::Unary(hir::UnOp::Deref, base_expr) => { self.convert_place_op_to_mutable(PlaceOp::Deref, expr, base_expr); } _ => {} diff --git a/compiler/rustc_typeck/src/check/regionck.rs b/compiler/rustc_typeck/src/check/regionck.rs index 290fa5fc36..7c8b752718 100644 --- a/compiler/rustc_typeck/src/check/regionck.rs +++ b/compiler/rustc_typeck/src/check/regionck.rs @@ -76,18 +76,19 @@ use crate::check::dropck; use crate::check::FnCtxt; use crate::mem_categorization as mc; use crate::middle::region; +use crate::outlives::outlives_bounds::InferCtxtExt as _; +use rustc_data_structures::stable_set::FxHashSet; use rustc_hir as hir; use rustc_hir::def_id::LocalDefId; use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc_hir::PatKind; use rustc_infer::infer::outlives::env::OutlivesEnvironment; -use rustc_infer::infer::{self, RegionObligation, RegionckMode}; +use rustc_infer::infer::{self, InferCtxt, RegionObligation, RegionckMode}; 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::infer::OutlivesEnvironmentExt; -use rustc_trait_selection::opaque_types::InferCtxtExt; +use rustc_trait_selection::opaque_types::InferCtxtExt as _; use std::ops::Deref; // a variation on try that just returns unit @@ -103,6 +104,51 @@ macro_rules! ignore_err { }; } +trait OutlivesEnvironmentExt<'tcx> { + fn add_implied_bounds( + &mut self, + infcx: &InferCtxt<'a, 'tcx>, + fn_sig_tys: FxHashSet>, + body_id: hir::HirId, + span: Span, + ); +} + +impl<'tcx> OutlivesEnvironmentExt<'tcx> for OutlivesEnvironment<'tcx> { + /// This method adds "implied bounds" into the outlives environment. + /// Implied bounds are outlives relationships that we can deduce + /// on the basis that certain types must be well-formed -- these are + /// either the types that appear in the function signature or else + /// the input types to an impl. For example, if you have a function + /// like + /// + /// ``` + /// fn foo<'a, 'b, T>(x: &'a &'b [T]) { } + /// ``` + /// + /// we can assume in the caller's body that `'b: 'a` and that `T: + /// 'b` (and hence, transitively, that `T: 'a`). This method would + /// add those assumptions into the outlives-environment. + /// + /// Tests: `src/test/ui/regions/regions-free-region-ordering-*.rs` + fn add_implied_bounds( + &mut self, + infcx: &InferCtxt<'a, 'tcx>, + fn_sig_tys: FxHashSet>, + body_id: hir::HirId, + span: Span, + ) { + debug!("add_implied_bounds()"); + + for ty in fn_sig_tys { + let ty = infcx.resolve_vars_if_possible(ty); + debug!("add_implied_bounds: ty = {}", ty); + let implied_bounds = infcx.implied_outlives_bounds(self.param_env, body_id, ty, span); + self.add_outlives_bounds(Some(infcx), implied_bounds) + } + } +} + /////////////////////////////////////////////////////////////////////////// // PUBLIC ENTRY POINTS @@ -126,7 +172,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Region checking during the WF phase for items. `wf_tys` are the /// types from which we should derive implied bounds, if any. - pub fn regionck_item(&self, item_id: hir::HirId, span: Span, wf_tys: &[Ty<'tcx>]) { + pub fn regionck_item(&self, item_id: hir::HirId, span: Span, wf_tys: FxHashSet>) { debug!("regionck_item(item.id={:?}, wf_tys={:?})", item_id, wf_tys); let subject = self.tcx.hir().local_def_id(item_id); let mut rcx = RegionCtxt::new(self, item_id, Subject(subject), self.param_env); @@ -149,7 +195,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn_id: hir::HirId, body: &'tcx hir::Body<'tcx>, span: Span, - wf_tys: &[Ty<'tcx>], + wf_tys: FxHashSet>, ) { debug!("regionck_fn(id={})", fn_id); let subject = self.tcx.hir().body_owner_def_id(body.id()); @@ -189,7 +235,7 @@ pub struct RegionCtxt<'a, 'tcx> { impl<'a, 'tcx> Deref for RegionCtxt<'a, 'tcx> { type Target = FnCtxt<'a, 'tcx>; fn deref(&self) -> &Self::Target { - &self.fcx + self.fcx } } @@ -286,17 +332,12 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> { // because it will have no effect. // // FIXME(#27579) return types should not be implied bounds - let fn_sig_tys: Vec<_> = + let fn_sig_tys: FxHashSet<_> = fn_sig.inputs().iter().cloned().chain(Some(fn_sig.output())).collect(); - self.outlives_environment.add_implied_bounds( - self.fcx, - &fn_sig_tys[..], - body_id.hir_id, - span, - ); + self.outlives_environment.add_implied_bounds(self.fcx, fn_sig_tys, body_id.hir_id, span); self.outlives_environment.save_implied_bounds(body_id.hir_id); - self.link_fn_params(&body.params); + self.link_fn_params(body.params); self.visit_body(body); self.visit_region_obligations(body_id.hir_id); @@ -383,13 +424,13 @@ impl<'a, 'tcx> Visitor<'tcx> for RegionCtxt<'a, 'tcx> { fn visit_arm(&mut self, arm: &'tcx hir::Arm<'tcx>) { // see above - self.constrain_bindings_in_pat(&arm.pat); + self.constrain_bindings_in_pat(arm.pat); intravisit::walk_arm(self, arm); } fn visit_local(&mut self, l: &'tcx hir::Local<'tcx>) { // see above - self.constrain_bindings_in_pat(&l.pat); + self.constrain_bindings_in_pat(l.pat); self.link_local(l); intravisit::walk_local(self, l); } @@ -411,13 +452,13 @@ impl<'a, 'tcx> Visitor<'tcx> for RegionCtxt<'a, 'tcx> { match expr.kind { hir::ExprKind::AddrOf(hir::BorrowKind::Ref, m, ref base) => { - self.link_addr_of(expr, m, &base); + self.link_addr_of(expr, m, base); intravisit::walk_expr(self, expr); } - hir::ExprKind::Match(ref discr, ref arms, _) => { - self.link_match(&discr, &arms[..]); + hir::ExprKind::Match(ref discr, arms, _) => { + self.link_match(discr, arms); intravisit::walk_expr(self, expr); } @@ -452,7 +493,7 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> { let mut place = self.with_mc(|mc| mc.cat_expr_unadjusted(expr))?; let typeck_results = self.typeck_results.borrow(); - let adjustments = typeck_results.expr_adjustments(&expr); + let adjustments = typeck_results.expr_adjustments(expr); if adjustments.is_empty() { return Ok(place); } @@ -479,7 +520,7 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> { self.link_autoref(expr, &place, autoref); } - place = self.with_mc(|mc| mc.cat_expr_adjusted(expr, place, &adjustment))?; + place = self.with_mc(|mc| mc.cat_expr_adjusted(expr, place, adjustment))?; } Ok(place) @@ -544,10 +585,10 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> { None => { return; } - Some(ref expr) => &**expr, + Some(expr) => &*expr, }; let discr_cmt = ignore_err!(self.with_mc(|mc| mc.cat_expr(init_expr))); - self.link_pattern(discr_cmt, &local.pat); + self.link_pattern(discr_cmt, local.pat); } /// Computes the guarantors for any ref bindings in a match and @@ -558,7 +599,7 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> { let discr_cmt = ignore_err!(self.with_mc(|mc| mc.cat_expr(discr))); debug!("discr_cmt={:?}", discr_cmt); for arm in arms { - self.link_pattern(discr_cmt.clone(), &arm.pat); + self.link_pattern(discr_cmt.clone(), arm.pat); } } @@ -571,7 +612,7 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> { let param_cmt = self.with_mc(|mc| mc.cat_rvalue(param.hir_id, param.pat.span, param_ty)); debug!("param_ty={:?} param_cmt={:?} param={:?}", param_ty, param_cmt, param); - self.link_pattern(param_cmt, ¶m.pat); + self.link_pattern(param_cmt, param.pat); } } @@ -586,7 +627,7 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> { if let Some(ty::BindByReference(mutbl)) = mc.typeck_results.extract_binding_mode(self.tcx.sess, *hir_id, *span) { - self.link_region_from_node_type(*span, *hir_id, mutbl, &sub_cmt); + self.link_region_from_node_type(*span, *hir_id, mutbl, sub_cmt); } } }) diff --git a/compiler/rustc_typeck/src/check/upvar.rs b/compiler/rustc_typeck/src/check/upvar.rs index 524cda3d09..67c96703f2 100644 --- a/compiler/rustc_typeck/src/check/upvar.rs +++ b/compiler/rustc_typeck/src/check/upvar.rs @@ -86,18 +86,55 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Intermediate format to store the hir_id pointing to the use that resulted in the /// corresponding place being captured and a String which contains the captured value's /// name (i.e: a.b.c) -type CapturesInfo = (Option, String); +#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +enum UpvarMigrationInfo { + /// We previously captured all of `x`, but now we capture some sub-path. + CapturingPrecise { source_expr: Option, var_name: String }, + CapturingNothing { + // where the variable appears in the closure (but is not captured) + use_span: Span, + }, +} -/// Intermediate format to store information needed to generate migration lint. The tuple -/// contains the hir_id pointing to the use that resulted in the -/// corresponding place being captured, a String which contains the captured value's -/// name (i.e: a.b.c) and a String which contains the reason why migration is needed for that -/// capture -type MigrationNeededForCapture = (Option, String, String); +/// Reasons that we might issue a migration warning. +#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] +struct MigrationWarningReason { + /// When we used to capture `x` in its entirety, we implemented the auto-trait(s) + /// in this vec, but now we don't. + auto_traits: Vec<&'static str>, + + /// When we used to capture `x` in its entirety, we would execute some destructors + /// at a different time. + drop_order: bool, +} + +impl MigrationWarningReason { + fn migration_message(&self) -> String { + let base = "changes to closure capture in Rust 2021 will affect"; + if !self.auto_traits.is_empty() && self.drop_order { + format!("{} drop order and which traits the closure implements", base) + } else if self.drop_order { + format!("{} drop order", base) + } else { + format!("{} which traits the closure implements", base) + } + } +} + +/// Intermediate format to store information needed to generate a note in the migration lint. +struct MigrationLintNote { + captures_info: UpvarMigrationInfo, + + /// reasons why migration is needed for this capture + reason: MigrationWarningReason, +} /// Intermediate format to store the hir id of the root variable and a HashSet containing /// information on why the root variable should be fully captured -type MigrationDiagnosticInfo = (hir::HirId, Vec); +struct NeededMigration { + var_hir_id: hir::HirId, + diagnostics_info: Vec, +} struct InferBorrowKindVisitor<'a, 'tcx> { fcx: &'a FnCtxt<'a, 'tcx>, @@ -123,6 +160,7 @@ impl<'a, 'tcx> Visitor<'tcx> for InferBorrowKindVisitor<'a, 'tcx> { impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Analysis starting point. + #[instrument(skip(self, body), level = "debug")] fn analyze_closure( &self, closure_hir_id: hir::HirId, @@ -131,8 +169,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { body: &'tcx hir::Body<'tcx>, capture_clause: hir::CaptureBy, ) { - debug!("analyze_closure(id={:?}, body.id={:?})", closure_hir_id, body.id()); - // Extract the type of the closure. let ty = self.node_ty(closure_hir_id); let (closure_def_id, substs) = match *ty.kind() { @@ -708,47 +744,66 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { closure_head_span, |lint| { let mut diagnostics_builder = lint.build( - format!( - "changes to closure capture in Rust 2021 will affect {}", - reasons - ) - .as_str(), + &reasons.migration_message(), ); - for (var_hir_id, diagnostics_info) in need_migrations.iter() { + for NeededMigration { var_hir_id, diagnostics_info } in &need_migrations { // Labels all the usage of the captured variable and why they are responsible // for migration being needed - for (captured_hir_id, captured_name, reasons) in diagnostics_info.iter() { - if let Some(captured_hir_id) = captured_hir_id { - let cause_span = self.tcx.hir().span(*captured_hir_id); - diagnostics_builder.span_label(cause_span, format!("in Rust 2018, this closure captures all of `{}`, but in Rust 2021, it will only capture `{}`", - self.tcx.hir().name(*var_hir_id), - captured_name, - )); + for lint_note in diagnostics_info.iter() { + match &lint_note.captures_info { + UpvarMigrationInfo::CapturingPrecise { source_expr: Some(capture_expr_id), var_name: captured_name } => { + let cause_span = self.tcx.hir().span(*capture_expr_id); + diagnostics_builder.span_label(cause_span, format!("in Rust 2018, this closure captures all of `{}`, but in Rust 2021, it will only capture `{}`", + self.tcx.hir().name(*var_hir_id), + captured_name, + )); + } + UpvarMigrationInfo::CapturingNothing { use_span } => { + diagnostics_builder.span_label(*use_span, format!("in Rust 2018, this causes the closure to capture `{}`, but in Rust 2021, it has no effect", + self.tcx.hir().name(*var_hir_id), + )); + } + + _ => { } } // Add a label pointing to where a captured variable affected by drop order // is dropped - if reasons.contains("drop order") { + if lint_note.reason.drop_order { let drop_location_span = drop_location_span(self.tcx, &closure_hir_id); - diagnostics_builder.span_label(drop_location_span, format!("in Rust 2018, `{}` is dropped here, but in Rust 2021, only `{}` will be dropped here as part of the closure", - self.tcx.hir().name(*var_hir_id), - captured_name, - )); + match &lint_note.captures_info { + UpvarMigrationInfo::CapturingPrecise { var_name: captured_name, .. } => { + diagnostics_builder.span_label(drop_location_span, format!("in Rust 2018, `{}` is dropped here, but in Rust 2021, only `{}` will be dropped here as part of the closure", + self.tcx.hir().name(*var_hir_id), + captured_name, + )); + } + UpvarMigrationInfo::CapturingNothing { use_span: _ } => { + diagnostics_builder.span_label(drop_location_span, format!("in Rust 2018, `{v}` is dropped here along with the closure, but in Rust 2021 `{v}` is not part of the closure", + v = self.tcx.hir().name(*var_hir_id), + )); + } + } } // Add a label explaining why a closure no longer implements a trait - if reasons.contains("trait implementation") { - let missing_trait = &reasons[..reasons.find("trait implementation").unwrap() - 1]; + for &missing_trait in &lint_note.reason.auto_traits { + // not capturing something anymore cannot cause a trait to fail to be implemented: + match &lint_note.captures_info { + UpvarMigrationInfo::CapturingPrecise { var_name: captured_name, .. } => { + let var_name = self.tcx.hir().name(*var_hir_id); + diagnostics_builder.span_label(closure_head_span, format!("\ + in Rust 2018, this closure implements {missing_trait} \ + as `{var_name}` implements {missing_trait}, but in Rust 2021, \ + this closure will no longer implement {missing_trait} \ + because `{var_name}` is not fully captured \ + and `{captured_name}` does not implement {missing_trait}")); + } - diagnostics_builder.span_label(closure_head_span, format!("in Rust 2018, this closure implements {} as `{}` implements {}, but in Rust 2021, this closure will no longer implement {} as `{}` does not implement {}", - missing_trait, - self.tcx.hir().name(*var_hir_id), - missing_trait, - missing_trait, - captured_name, - missing_trait, - )); + // Cannot happen: if we don't capture a variable, we impl strictly more traits + UpvarMigrationInfo::CapturingNothing { use_span } => span_bug!(*use_span, "missing trait from not capturing something"), + } } } } @@ -792,7 +847,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // This is a multi-line closure with just a `{` on the first line, // so we put the `let` on its own line. // We take the indentation from the next non-empty line. - let line2 = lines.filter(|line| !line.is_empty()).next().unwrap_or_default(); + let line2 = lines.find(|line| !line.is_empty()).unwrap_or_default(); let indent = line2.split_once(|c: char| !c.is_whitespace()).unwrap_or_default().0; diagnostics_builder.span_suggestion( closure_body_span.with_lo(closure_body_span.lo() + BytePos::from_usize(line1.len())).shrink_to_lo(), @@ -841,25 +896,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Combines all the reasons for 2229 migrations fn compute_2229_migrations_reasons( &self, - auto_trait_reasons: FxHashSet<&str>, - drop_reason: bool, - ) -> String { - let mut reasons = String::new(); + auto_trait_reasons: FxHashSet<&'static str>, + drop_order: bool, + ) -> MigrationWarningReason { + let mut reasons = MigrationWarningReason::default(); - if auto_trait_reasons.len() > 0 { - reasons = format!( - "{} trait implementation for closure", - auto_trait_reasons.clone().into_iter().collect::>().join(", ") - ); + for auto_trait in auto_trait_reasons { + reasons.auto_traits.push(auto_trait); } - if auto_trait_reasons.len() > 0 && drop_reason { - reasons = format!("{} and ", reasons); - } - - if drop_reason { - reasons = format!("{}drop order", reasons); - } + reasons.drop_order = drop_order; reasons } @@ -875,11 +921,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { min_captures: Option<&ty::RootVariableMinCaptureList<'tcx>>, var_hir_id: hir::HirId, closure_clause: hir::CaptureBy, - ) -> Option>> { + ) -> Option>> { let auto_traits_def_id = vec![ self.tcx.lang_items().clone_trait(), self.tcx.lang_items().sync_trait(), - self.tcx.get_diagnostic_item(sym::send_trait), + self.tcx.get_diagnostic_item(sym::Send), self.tcx.lang_items().unpin_trait(), self.tcx.get_diagnostic_item(sym::unwind_safe_trait), self.tcx.get_diagnostic_item(sym::ref_unwind_safe_trait), @@ -887,13 +933,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let auto_traits = vec!["`Clone`", "`Sync`", "`Send`", "`Unpin`", "`UnwindSafe`", "`RefUnwindSafe`"]; - let root_var_min_capture_list = if let Some(root_var_min_capture_list) = - min_captures.and_then(|m| m.get(&var_hir_id)) - { - root_var_min_capture_list - } else { - return None; - }; + let root_var_min_capture_list = min_captures.and_then(|m| m.get(&var_hir_id))?; let ty = self.infcx.resolve_vars_if_possible(self.node_ty(var_hir_id)); @@ -968,14 +1008,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - if capture_problems.len() > 0 { + if !capture_problems.is_empty() { problematic_captures.insert( - (capture.info.path_expr_id, capture.to_string(self.tcx)), + UpvarMigrationInfo::CapturingPrecise { + source_expr: capture.info.path_expr_id, + var_name: capture.to_string(self.tcx), + }, capture_problems, ); } } - if problematic_captures.len() > 0 { + if !problematic_captures.is_empty() { return Some(problematic_captures); } None @@ -993,6 +1036,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// /// This function only returns a HashSet of CapturesInfo for significant drops. If there /// are no significant drops than None is returned + #[instrument(level = "debug", skip(self))] fn compute_2229_migrations_for_drop( &self, closure_def_id: DefId, @@ -1000,10 +1044,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { min_captures: Option<&ty::RootVariableMinCaptureList<'tcx>>, closure_clause: hir::CaptureBy, var_hir_id: hir::HirId, - ) -> Option> { + ) -> Option> { let ty = self.infcx.resolve_vars_if_possible(self.node_ty(var_hir_id)); if !ty.has_significant_drop(self.tcx, self.tcx.param_env(closure_def_id.expect_local())) { + debug!("does not have significant drop"); return None; } @@ -1013,16 +1058,31 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { root_var_min_capture_list } else { // The upvar is mentioned within the closure but no path starting from it is - // used. + // used. This occurs when you have (e.g.) + // + // ``` + // let x = move || { + // let _ = y; + // }); + // ``` + debug!("no path starting from it is used"); + match closure_clause { // Only migrate if closure is a move closure - hir::CaptureBy::Value => return Some(FxHashSet::default()), + hir::CaptureBy::Value => { + let mut diagnostics_info = FxHashSet::default(); + let upvars = self.tcx.upvars_mentioned(closure_def_id).expect("must be an upvar"); + let upvar = upvars[&var_hir_id]; + diagnostics_info.insert(UpvarMigrationInfo::CapturingNothing { use_span: upvar.span }); + return Some(diagnostics_info); + } hir::CaptureBy::Ref => {} } return None; }; + debug!(?root_var_min_capture_list); let mut projections_list = Vec::new(); let mut diagnostics_info = FxHashSet::default(); @@ -1032,19 +1092,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Only care about captures that are moved into the closure ty::UpvarCapture::ByValue(..) => { projections_list.push(captured_place.place.projections.as_slice()); - diagnostics_info.insert(( - captured_place.info.path_expr_id, - captured_place.to_string(self.tcx), - )); + diagnostics_info.insert(UpvarMigrationInfo::CapturingPrecise { + source_expr: captured_place.info.path_expr_id, + var_name: captured_place.to_string(self.tcx), + }); } ty::UpvarCapture::ByRef(..) => {} } } + debug!(?projections_list); + debug!(?diagnostics_info); + let is_moved = !projections_list.is_empty(); + debug!(?is_moved); let is_not_completely_captured = - root_var_min_capture_list.iter().any(|capture| capture.place.projections.len() > 0); + root_var_min_capture_list.iter().any(|capture| !capture.place.projections.is_empty()); + debug!(?is_not_completely_captured); if is_moved && is_not_completely_captured @@ -1058,7 +1123,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return Some(diagnostics_info); } - return None; + None } /// Figures out the list of root variables (and their types) that aren't completely @@ -1077,17 +1142,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Returns a tuple containing a vector of MigrationDiagnosticInfo, as well as a String /// containing the reason why root variables whose HirId is contained in the vector should /// be captured + #[instrument(level = "debug", skip(self))] fn compute_2229_migrations( &self, closure_def_id: DefId, closure_span: Span, closure_clause: hir::CaptureBy, min_captures: Option<&ty::RootVariableMinCaptureList<'tcx>>, - ) -> (Vec, String) { + ) -> (Vec, MigrationWarningReason) { let upvars = if let Some(upvars) = self.tcx.upvars_mentioned(closure_def_id) { upvars } else { - return (Vec::new(), format!("")); + return (Vec::new(), MigrationWarningReason::default()); }; let mut need_migrations = Vec::new(); @@ -1096,7 +1162,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Perform auto-trait analysis for (&var_hir_id, _) in upvars.iter() { - let mut responsible_captured_hir_ids = Vec::new(); + let mut diagnostics_info = Vec::new(); let auto_trait_diagnostic = if let Some(diagnostics_info) = self.compute_2229_migrations_for_trait(min_captures, var_hir_id, closure_clause) @@ -1128,34 +1194,33 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut capture_diagnostic = capture_diagnostic.into_iter().collect::>(); capture_diagnostic.sort(); - for captured_info in capture_diagnostic.iter() { + for captures_info in capture_diagnostic { // Get the auto trait reasons of why migration is needed because of that capture, if there are any let capture_trait_reasons = - if let Some(reasons) = auto_trait_diagnostic.get(captured_info) { + if let Some(reasons) = auto_trait_diagnostic.get(&captures_info) { reasons.clone() } else { FxHashSet::default() }; // Check if migration is needed because of drop reorder as a result of that capture - let capture_drop_reorder_reason = drop_reorder_diagnostic.contains(captured_info); + let capture_drop_reorder_reason = drop_reorder_diagnostic.contains(&captures_info); // Combine all the reasons of why the root variable should be captured as a result of // auto trait implementation issues auto_trait_migration_reasons.extend(capture_trait_reasons.clone()); - responsible_captured_hir_ids.push(( - captured_info.0, - captured_info.1.clone(), - self.compute_2229_migrations_reasons( + diagnostics_info.push(MigrationLintNote { + captures_info, + reason: self.compute_2229_migrations_reasons( capture_trait_reasons, capture_drop_reorder_reason, ), - )); + }); } - if capture_diagnostic.len() > 0 { - need_migrations.push((var_hir_id, responsible_captured_hir_ids)); + if !diagnostics_info.is_empty() { + need_migrations.push(NeededMigration { var_hir_id, diagnostics_info }); } } ( @@ -1684,15 +1749,12 @@ struct InferBorrowKind<'a, 'tcx> { } impl<'a, 'tcx> InferBorrowKind<'a, 'tcx> { + #[instrument(skip(self), level = "debug")] fn adjust_upvar_borrow_kind_for_consume( &mut self, place_with_id: &PlaceWithHirId<'tcx>, diag_expr_id: hir::HirId, ) { - debug!( - "adjust_upvar_borrow_kind_for_consume(place_with_id={:?}, diag_expr_id={:?})", - place_with_id, diag_expr_id - ); let tcx = self.fcx.tcx; let upvar_id = if let PlaceBase::Upvar(upvar_id) = place_with_id.place.base { upvar_id @@ -1700,7 +1762,7 @@ impl<'a, 'tcx> InferBorrowKind<'a, 'tcx> { return; }; - debug!("adjust_upvar_borrow_kind_for_consume: upvar={:?}", upvar_id); + debug!(?upvar_id); let usage_span = tcx.hir().span(diag_expr_id); @@ -1719,16 +1781,12 @@ impl<'a, 'tcx> InferBorrowKind<'a, 'tcx> { /// Indicates that `place_with_id` is being directly mutated (e.g., assigned /// to). If the place is based on a by-ref upvar, this implies that /// the upvar must be borrowed using an `&mut` borrow. + #[instrument(skip(self), level = "debug")] fn adjust_upvar_borrow_kind_for_mut( &mut self, place_with_id: &PlaceWithHirId<'tcx>, diag_expr_id: hir::HirId, ) { - debug!( - "adjust_upvar_borrow_kind_for_mut(place_with_id={:?}, diag_expr_id={:?})", - place_with_id, diag_expr_id - ); - if let PlaceBase::Upvar(_) = place_with_id.place.base { // Raw pointers don't inherit mutability if place_with_id.place.deref_tys().any(ty::TyS::is_unsafe_ptr) { @@ -1738,16 +1796,12 @@ impl<'a, 'tcx> InferBorrowKind<'a, 'tcx> { } } + #[instrument(skip(self), level = "debug")] fn adjust_upvar_borrow_kind_for_unique( &mut self, place_with_id: &PlaceWithHirId<'tcx>, diag_expr_id: hir::HirId, ) { - debug!( - "adjust_upvar_borrow_kind_for_unique(place_with_id={:?}, diag_expr_id={:?})", - place_with_id, diag_expr_id - ); - if let PlaceBase::Upvar(_) = place_with_id.place.base { if place_with_id.place.deref_tys().any(ty::TyS::is_unsafe_ptr) { // Raw pointers don't inherit mutability. @@ -1784,6 +1838,7 @@ impl<'a, 'tcx> InferBorrowKind<'a, 'tcx> { /// moving from left to right as needed (but never right to left). /// Here the argument `mutbl` is the borrow_kind that is required by /// some particular use. + #[instrument(skip(self), level = "debug")] fn adjust_upvar_borrow_kind( &mut self, place_with_id: &PlaceWithHirId<'tcx>, @@ -1792,10 +1847,7 @@ impl<'a, 'tcx> InferBorrowKind<'a, 'tcx> { ) { let curr_capture_info = self.capture_information[&place_with_id.place]; - debug!( - "adjust_upvar_borrow_kind(place={:?}, diag_expr_id={:?}, capture_info={:?}, kind={:?})", - place_with_id, diag_expr_id, curr_capture_info, kind - ); + debug!(?curr_capture_info); if let ty::UpvarCapture::ByValue(_) = curr_capture_info.capture_kind { // It's already captured by value, we don't need to do anything here @@ -1815,6 +1867,7 @@ impl<'a, 'tcx> InferBorrowKind<'a, 'tcx> { }; } + #[instrument(skip(self, diag_expr_id), level = "debug")] fn init_capture_info_for_place( &mut self, place_with_id: &PlaceWithHirId<'tcx>, @@ -1841,7 +1894,7 @@ impl<'a, 'tcx> InferBorrowKind<'a, 'tcx> { self.capture_information.insert(place_with_id.place.clone(), capture_info); } else { - debug!("Not upvar: {:?}", place_with_id); + debug!("Not upvar"); } } } @@ -1868,27 +1921,22 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for InferBorrowKind<'a, 'tcx> { } } + #[instrument(skip(self), level = "debug")] fn consume(&mut self, place_with_id: &PlaceWithHirId<'tcx>, diag_expr_id: hir::HirId) { - debug!("consume(place_with_id={:?}, diag_expr_id={:?})", place_with_id, diag_expr_id); - if !self.capture_information.contains_key(&place_with_id.place) { - self.init_capture_info_for_place(&place_with_id, diag_expr_id); + self.init_capture_info_for_place(place_with_id, diag_expr_id); } - self.adjust_upvar_borrow_kind_for_consume(&place_with_id, diag_expr_id); + self.adjust_upvar_borrow_kind_for_consume(place_with_id, diag_expr_id); } + #[instrument(skip(self), level = "debug")] fn borrow( &mut self, place_with_id: &PlaceWithHirId<'tcx>, diag_expr_id: hir::HirId, bk: ty::BorrowKind, ) { - debug!( - "borrow(place_with_id={:?}, diag_expr_id={:?}, bk={:?})", - place_with_id, diag_expr_id, bk - ); - // The region here will get discarded/ignored let dummy_capture_kind = ty::UpvarCapture::ByRef(ty::UpvarBorrow { kind: bk, region: &ty::ReErased }); @@ -1925,9 +1973,8 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for InferBorrowKind<'a, 'tcx> { } } + #[instrument(skip(self), level = "debug")] fn mutate(&mut self, assignee_place: &PlaceWithHirId<'tcx>, diag_expr_id: hir::HirId) { - debug!("mutate(assignee_place={:?}, diag_expr_id={:?})", assignee_place, diag_expr_id); - self.borrow(assignee_place, diag_expr_id, ty::BorrowKind::MutBorrow); } } @@ -2017,7 +2064,7 @@ fn restrict_capture_precision<'tcx>( } } - return (place, curr_mode); + (place, curr_mode) } /// Truncate deref of any reference. @@ -2086,7 +2133,7 @@ fn construct_capture_kind_reason_string( place: &Place<'tcx>, capture_info: &ty::CaptureInfo<'tcx>, ) -> String { - let place_str = construct_place_string(tcx, &place); + let place_str = construct_place_string(tcx, place); let capture_kind_str = match capture_info.capture_kind { ty::UpvarCapture::ByValue(_) => "ByValue".into(), @@ -2097,7 +2144,7 @@ fn construct_capture_kind_reason_string( } fn construct_path_string(tcx: TyCtxt<'_>, place: &Place<'tcx>) -> String { - let place_str = construct_place_string(tcx, &place); + let place_str = construct_place_string(tcx, place); format!("{} used here", place_str) } @@ -2107,7 +2154,7 @@ fn construct_capture_info_string( place: &Place<'tcx>, capture_info: &ty::CaptureInfo<'tcx>, ) -> String { - let place_str = construct_place_string(tcx, &place); + let place_str = construct_place_string(tcx, place); let capture_kind_str = match capture_info.capture_kind { ty::UpvarCapture::ByValue(_) => "ByValue".into(), @@ -2120,6 +2167,7 @@ fn var_name(tcx: TyCtxt<'_>, var_hir_id: hir::HirId) -> Symbol { tcx.hir().name(var_hir_id) } +#[instrument(level = "debug", skip(tcx))] fn should_do_rust_2021_incompatible_closure_captures_analysis( tcx: TyCtxt<'_>, closure_id: hir::HirId, @@ -2135,10 +2183,12 @@ fn should_do_rust_2021_incompatible_closure_captures_analysis( /// - s2: Comma separated names of the variables being migrated. fn migration_suggestion_for_2229( tcx: TyCtxt<'_>, - need_migrations: &Vec, + need_migrations: &Vec, ) -> (String, String) { - let need_migrations_variables = - need_migrations.iter().map(|(v, _)| var_name(tcx, *v)).collect::>(); + let need_migrations_variables = need_migrations + .iter() + .map(|NeededMigration { var_hir_id: v, .. }| var_name(tcx, *v)) + .collect::>(); let migration_ref_concat = need_migrations_variables.iter().map(|v| format!("&{}", v)).collect::>().join(", "); diff --git a/compiler/rustc_typeck/src/check/wfcheck.rs b/compiler/rustc_typeck/src/check/wfcheck.rs index 17716afe32..d737fe9ac8 100644 --- a/compiler/rustc_typeck/src/check/wfcheck.rs +++ b/compiler/rustc_typeck/src/check/wfcheck.rs @@ -2,7 +2,7 @@ use crate::check::{FnCtxt, Inherited}; use crate::constrained_generic_params::{identify_constrained_generic_params, Parameter}; use rustc_ast as ast; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::fx::FxHashSet; use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder}; use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; @@ -12,7 +12,7 @@ use rustc_hir::itemlikevisit::ParItemLikeVisitor; use rustc_hir::lang_items::LangItem; use rustc_hir::ItemKind; use rustc_middle::hir::map as hir_map; -use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts, Subst}; +use rustc_middle::ty::subst::{InternalSubsts, Subst}; use rustc_middle::ty::trait_def::TraitSpecializationKind; use rustc_middle::ty::{ self, AdtKind, GenericParamDefKind, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness, @@ -20,7 +20,6 @@ use rustc_middle::ty::{ use rustc_session::parse::feature_err; use rustc_span::symbol::{sym, Ident, Symbol}; use rustc_span::Span; -use rustc_trait_selection::opaque_types::may_define_opaque_type; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt; use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode, WellFormedLoc}; @@ -44,7 +43,7 @@ struct CheckWfFcxBuilder<'tcx> { impl<'tcx> CheckWfFcxBuilder<'tcx> { fn with_fcx(&mut self, f: F) where - F: for<'b> FnOnce(&FnCtxt<'b, 'tcx>) -> Vec>, + F: for<'b> FnOnce(&FnCtxt<'b, 'tcx>) -> FxHashSet>, { let id = self.id; let span = self.span; @@ -59,7 +58,7 @@ impl<'tcx> CheckWfFcxBuilder<'tcx> { } let wf_tys = f(&fcx); fcx.select_all_obligations_or_error(); - fcx.regionck_item(id, span, &wf_tys); + fcx.regionck_item(id, span, wf_tys); }); } } @@ -77,14 +76,14 @@ impl<'tcx> CheckWfFcxBuilder<'tcx> { /// We do this check as a pre-pass before checking fn bodies because if these constraints are /// not included it frequently leads to confusing errors in fn bodies. So it's better to check /// the types first. +#[instrument(skip(tcx), level = "debug")] pub fn check_item_well_formed(tcx: TyCtxt<'_>, def_id: LocalDefId) { let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); let item = tcx.hir().expect_item(hir_id); debug!( - "check_item_well_formed(it.def_id={:?}, it.name={})", - item.def_id, - tcx.def_path_str(def_id.to_def_id()) + ?item.def_id, + item.name = ? tcx.def_path_str(def_id.to_def_id()) ); match item.kind { @@ -143,23 +142,23 @@ pub fn check_item_well_formed(tcx: TyCtxt<'_>, def_id: LocalDefId) { } } hir::ItemKind::Fn(ref sig, ..) => { - check_item_fn(tcx, item.hir_id(), item.ident, item.span, sig.decl); + check_item_fn(tcx, item.def_id, item.ident, item.span, sig.decl); } - hir::ItemKind::Static(ref ty, ..) => { - check_item_type(tcx, item.hir_id(), ty.span, false); + hir::ItemKind::Static(ty, ..) => { + check_item_type(tcx, item.def_id, ty.span, false); } - hir::ItemKind::Const(ref ty, ..) => { - check_item_type(tcx, item.hir_id(), ty.span, false); + hir::ItemKind::Const(ty, ..) => { + check_item_type(tcx, item.def_id, ty.span, false); } hir::ItemKind::ForeignMod { items, .. } => { for it in items.iter() { let it = tcx.hir().foreign_item(it.id); match it.kind { - hir::ForeignItemKind::Fn(ref decl, ..) => { - check_item_fn(tcx, it.hir_id(), it.ident, it.span, decl) + hir::ForeignItemKind::Fn(decl, ..) => { + check_item_fn(tcx, it.def_id, it.ident, it.span, decl) } - hir::ForeignItemKind::Static(ref ty, ..) => { - check_item_type(tcx, it.hir_id(), ty.span, true) + hir::ForeignItemKind::Static(ty, ..) => { + check_item_type(tcx, it.def_id, ty.span, true) } hir::ForeignItemKind::Type => (), } @@ -199,8 +198,61 @@ pub fn check_trait_item(tcx: TyCtxt<'_>, def_id: LocalDefId) { hir::TraitItemKind::Type(_bounds, Some(ty)) => (None, ty.span), _ => (None, trait_item.span), }; - check_object_unsafe_self_trait_by_name(tcx, &trait_item); - check_associated_item(tcx, trait_item.hir_id(), span, method_sig); + check_object_unsafe_self_trait_by_name(tcx, trait_item); + check_associated_item(tcx, trait_item.def_id, span, method_sig); + + let encl_trait_hir_id = tcx.hir().get_parent_item(hir_id); + let encl_trait = tcx.hir().expect_item(encl_trait_hir_id); + let encl_trait_def_id = encl_trait.def_id.to_def_id(); + let fn_lang_item_name = if Some(encl_trait_def_id) == tcx.lang_items().fn_trait() { + Some("fn") + } else if Some(encl_trait_def_id) == tcx.lang_items().fn_mut_trait() { + Some("fn_mut") + } else { + None + }; + + if let (Some(fn_lang_item_name), "call") = + (fn_lang_item_name, trait_item.ident.name.to_ident_string().as_str()) + { + // We are looking at the `call` function of the `fn` or `fn_mut` lang item. + // Do some rudimentary sanity checking to avoid an ICE later (issue #83471). + if let Some(hir::FnSig { decl, span, .. }) = method_sig { + if let [self_ty, _] = decl.inputs { + if !matches!(self_ty.kind, hir::TyKind::Rptr(_, _)) { + tcx.sess + .struct_span_err( + self_ty.span, + &format!( + "first argument of `call` in `{}` lang item must be a reference", + fn_lang_item_name + ), + ) + .emit(); + } + } else { + tcx.sess + .struct_span_err( + *span, + &format!( + "`call` function in `{}` lang item takes exactly two arguments", + fn_lang_item_name + ), + ) + .emit(); + } + } else { + tcx.sess + .struct_span_err( + trait_item.span, + &format!( + "`call` trait item in `{}` lang item must be a function", + fn_lang_item_name + ), + ) + .emit(); + } + } } fn could_be_self(trait_def_id: LocalDefId, ty: &hir::Ty<'_>) -> bool { @@ -275,7 +327,7 @@ pub fn check_impl_item(tcx: TyCtxt<'_>, def_id: LocalDefId) { _ => (None, impl_item.span), }; - check_associated_item(tcx, impl_item.hir_id(), span, method_sig); + check_associated_item(tcx, impl_item.def_id, span, method_sig); } fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) { @@ -385,16 +437,16 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) { #[tracing::instrument(level = "debug", skip(tcx, span, sig_if_method))] fn check_associated_item( tcx: TyCtxt<'_>, - item_id: hir::HirId, + item_id: LocalDefId, span: Span, sig_if_method: Option<&hir::FnSig<'_>>, ) { - let code = ObligationCauseCode::WellFormed(Some(WellFormedLoc::Ty(item_id.expect_owner()))); + let code = ObligationCauseCode::WellFormed(Some(WellFormedLoc::Ty(item_id))); for_id(tcx, item_id, span).with_fcx(|fcx| { - let item = fcx.tcx.associated_item(fcx.tcx.hir().local_def_id(item_id)); + let item = fcx.tcx.associated_item(item_id); let (mut implied_bounds, self_ty) = match item.container { - ty::TraitContainer(_) => (vec![], fcx.tcx.types.self_param), + ty::TraitContainer(_) => (FxHashSet::default(), fcx.tcx.types.self_param), ty::ImplContainer(def_id) => { (fcx.impl_implied_bounds(def_id, span), fcx.tcx.type_of(def_id)) } @@ -403,11 +455,7 @@ fn check_associated_item( match item.kind { ty::AssocKind::Const => { let ty = fcx.tcx.type_of(item.def_id); - let ty = fcx.normalize_associated_types_in_wf( - span, - ty, - WellFormedLoc::Ty(item_id.expect_owner()), - ); + let ty = fcx.normalize_associated_types_in_wf(span, ty, WellFormedLoc::Ty(item_id)); fcx.register_wf_obligation(ty.into(), span, code.clone()); } ty::AssocKind::Fn => { @@ -421,7 +469,7 @@ fn check_associated_item( item.def_id, &mut implied_bounds, ); - check_method_receiver(fcx, hir_sig, &item, self_ty); + check_method_receiver(fcx, hir_sig, item, self_ty); } ty::AssocKind::Type => { if let ty::AssocItemContainer::TraitContainer(_) = item.container { @@ -429,11 +477,8 @@ fn check_associated_item( } if item.defaultness.has_value() { let ty = fcx.tcx.type_of(item.def_id); - let ty = fcx.normalize_associated_types_in_wf( - span, - ty, - WellFormedLoc::Ty(item_id.expect_owner()), - ); + let ty = + fcx.normalize_associated_types_in_wf(span, ty, WellFormedLoc::Ty(item_id)); fcx.register_wf_obligation(ty.into(), span, code.clone()); } } @@ -444,14 +489,13 @@ fn check_associated_item( } fn for_item<'tcx>(tcx: TyCtxt<'tcx>, item: &hir::Item<'_>) -> CheckWfFcxBuilder<'tcx> { - for_id(tcx, item.hir_id(), item.span) + for_id(tcx, item.def_id, item.span) } -fn for_id(tcx: TyCtxt<'_>, id: hir::HirId, span: Span) -> CheckWfFcxBuilder<'_> { - let def_id = tcx.hir().local_def_id(id); +fn for_id(tcx: TyCtxt<'_>, def_id: LocalDefId, span: Span) -> CheckWfFcxBuilder<'_> { CheckWfFcxBuilder { inherited: Inherited::build(tcx, def_id), - id, + id: hir::HirId::make_owner(def_id), span, param_env: tcx.param_env(def_id), } @@ -541,10 +585,10 @@ fn check_type_defn<'tcx, F>( fcx.register_predicate(traits::Obligation::new( cause, fcx.param_env, - ty::PredicateKind::ConstEvaluatable(ty::Unevaluated::new( + ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(ty::Unevaluated::new( ty::WithOptConstParam::unknown(discr_def_id.to_def_id()), discr_substs, - )) + ))) .to_predicate(tcx), )); } @@ -553,12 +597,13 @@ fn check_type_defn<'tcx, F>( check_where_clauses(fcx, item.span, item.def_id.to_def_id(), None); // No implied bounds in a struct definition. - vec![] + FxHashSet::default() }); } +#[instrument(skip(tcx, item))] fn check_trait(tcx: TyCtxt<'_>, item: &hir::Item<'_>) { - debug!("check_trait: {:?}", item.def_id); + debug!(?item.def_id); let trait_def = tcx.trait_def(item.def_id); if trait_def.is_marker @@ -579,7 +624,7 @@ fn check_trait(tcx: TyCtxt<'_>, item: &hir::Item<'_>) { for_item(tcx, item).with_fcx(|fcx| { check_where_clauses(fcx, item.span, item.def_id.to_def_id(), None); - vec![] + FxHashSet::default() }); } @@ -612,30 +657,25 @@ fn check_associated_type_bounds(fcx: &FnCtxt<'_, '_>, item: &ty::AssocItem, span fn check_item_fn( tcx: TyCtxt<'_>, - item_id: hir::HirId, + def_id: LocalDefId, ident: Ident, span: Span, decl: &hir::FnDecl<'_>, ) { - for_id(tcx, item_id, span).with_fcx(|fcx| { - let def_id = tcx.hir().local_def_id(item_id); + for_id(tcx, def_id, span).with_fcx(|fcx| { let sig = tcx.fn_sig(def_id); - let mut implied_bounds = vec![]; + let mut implied_bounds = FxHashSet::default(); check_fn_or_method(fcx, ident.span, sig, decl, def_id.to_def_id(), &mut implied_bounds); implied_bounds }) } -fn check_item_type(tcx: TyCtxt<'_>, item_id: hir::HirId, ty_span: Span, allow_foreign_ty: bool) { +fn check_item_type(tcx: TyCtxt<'_>, item_id: LocalDefId, ty_span: Span, allow_foreign_ty: bool) { debug!("check_item_type: {:?}", item_id); for_id(tcx, item_id, ty_span).with_fcx(|fcx| { - let ty = tcx.type_of(tcx.hir().local_def_id(item_id)); - let item_ty = fcx.normalize_associated_types_in_wf( - ty_span, - ty, - WellFormedLoc::Ty(item_id.expect_owner()), - ); + let ty = tcx.type_of(item_id); + let item_ty = fcx.normalize_associated_types_in_wf(ty_span, ty, WellFormedLoc::Ty(item_id)); let mut forbid_unsized = true; if allow_foreign_ty { @@ -648,7 +688,7 @@ fn check_item_type(tcx: TyCtxt<'_>, item_id: hir::HirId, ty_span: Span, allow_fo fcx.register_wf_obligation( item_ty.into(), ty_span, - ObligationCauseCode::WellFormed(Some(WellFormedLoc::Ty(item_id.expect_owner()))), + ObligationCauseCode::WellFormed(Some(WellFormedLoc::Ty(item_id))), ); if forbid_unsized { fcx.register_bound( @@ -659,7 +699,7 @@ fn check_item_type(tcx: TyCtxt<'_>, item_id: hir::HirId, ty_span: Span, allow_fo } // No implied bounds in a const, etc. - vec![] + FxHashSet::default() }); } @@ -712,13 +752,13 @@ fn check_impl<'tcx>( } /// Checks where-clauses and inline bounds that are declared on `def_id`. +#[instrument(skip(fcx), level = "debug")] fn check_where_clauses<'tcx, 'fcx>( fcx: &FnCtxt<'fcx, 'tcx>, span: Span, def_id: DefId, return_ty: Option<(Ty<'tcx>, Span)>, ) { - debug!("check_where_clauses(def_id={:?}, return_ty={:?})", def_id, return_ty); let tcx = fcx.tcx; let predicates = tcx.predicates_of(def_id); @@ -741,7 +781,7 @@ fn check_where_clauses<'tcx, 'fcx>( for param in &generics.params { match param.kind { GenericParamDefKind::Type { .. } => { - if is_our_default(¶m) { + if is_our_default(param) { let ty = tcx.type_of(param.def_id); // Ignore dependent defaults -- that is, where the default of one type // parameter includes another (e.g., ``). In those cases, we can't @@ -756,7 +796,7 @@ fn check_where_clauses<'tcx, 'fcx>( } } GenericParamDefKind::Const { .. } => { - if is_our_default(¶m) { + if is_our_default(param) { // FIXME(const_generics_defaults): This // is incorrect when dealing with unused substs, for example // for `struct Foo` @@ -888,17 +928,15 @@ fn check_where_clauses<'tcx, 'fcx>( let predicates = predicates.instantiate_identity(tcx); - if let Some((mut return_ty, span)) = return_ty { + if let Some((return_ty, _)) = return_ty { if return_ty.has_infer_types_or_consts() { fcx.select_obligations_where_possible(false, |_| {}); - return_ty = fcx.resolve_vars_if_possible(return_ty); } - check_opaque_types(fcx, def_id.expect_local(), span, return_ty); } let predicates = fcx.normalize_associated_types_in(span, predicates); - debug!("check_where_clauses: predicates={:?}", predicates.predicates); + debug!(?predicates.predicates); assert_eq!(predicates.predicates.len(), predicates.spans.len()); let wf_obligations = iter::zip(&predicates.predicates, &predicates.spans).flat_map(|(&p, &sp)| { @@ -918,15 +956,10 @@ fn check_fn_or_method<'fcx, 'tcx>( sig: ty::PolyFnSig<'tcx>, hir_decl: &hir::FnDecl<'_>, def_id: DefId, - implied_bounds: &mut Vec>, + implied_bounds: &mut FxHashSet>, ) { let sig = fcx.tcx.liberate_late_bound_regions(def_id, sig); - // Unnormalized types in signature are WF too - implied_bounds.extend(sig.inputs()); - // FIXME(#27579) return types should not be implied bounds - implied_bounds.push(sig.output()); - // Normalize the input and output types one at a time, using a different // `WellFormedLoc` for each. We cannot call `normalize_associated_types` // on the entire `FnSig`, since this would use the same `WellFormedLoc` @@ -977,150 +1010,13 @@ fn check_fn_or_method<'fcx, 'tcx>( ); // FIXME(#27579) return types should not be implied bounds - implied_bounds.push(sig.output()); + implied_bounds.insert(sig.output()); debug!(?implied_bounds); check_where_clauses(fcx, span, def_id, Some((sig.output(), hir_decl.output.span()))); } -/// Checks "defining uses" of opaque `impl Trait` types to ensure that they meet the restrictions -/// laid for "higher-order pattern unification". -/// This ensures that inference is tractable. -/// In particular, definitions of opaque types can only use other generics as arguments, -/// and they cannot repeat an argument. Example: -/// -/// ```rust -/// type Foo = impl Bar; -/// -/// // Okay -- `Foo` is applied to two distinct, generic types. -/// fn a() -> Foo { .. } -/// -/// // Not okay -- `Foo` is applied to `T` twice. -/// fn b() -> Foo { .. } -/// -/// // Not okay -- `Foo` is applied to a non-generic type. -/// fn b() -> Foo { .. } -/// ``` -/// -fn check_opaque_types<'fcx, 'tcx>( - fcx: &FnCtxt<'fcx, 'tcx>, - fn_def_id: LocalDefId, - span: Span, - ty: Ty<'tcx>, -) { - trace!("check_opaque_types(fn_def_id={:?}, ty={:?})", fn_def_id, ty); - let tcx = fcx.tcx; - - ty.fold_with(&mut ty::fold::BottomUpFolder { - tcx, - ty_op: |ty| { - if let ty::Opaque(def_id, substs) = *ty.kind() { - trace!("check_opaque_types: opaque_ty, {:?}, {:?}", def_id, substs); - let generics = tcx.generics_of(def_id); - - let opaque_hir_id = if let Some(local_id) = def_id.as_local() { - tcx.hir().local_def_id_to_hir_id(local_id) - } else { - // Opaque types from other crates won't have defining uses in this crate. - return ty; - }; - if let hir::ItemKind::OpaqueTy(hir::OpaqueTy { impl_trait_fn: Some(_), .. }) = - tcx.hir().expect_item(opaque_hir_id).kind - { - // No need to check return position impl trait (RPIT) - // because for type and const parameters they are correct - // by construction: we convert - // - // fn foo() -> impl Trait - // - // into - // - // type Foo - // fn foo() -> Foo. - // - // For lifetime parameters we convert - // - // fn foo<'l0..'ln>() -> impl Trait<'l0..'lm> - // - // into - // - // type foo::<'p0..'pn>::Foo<'q0..'qm> - // fn foo() -> foo::<'static..'static>::Foo<'l0..'lm>. - // - // which would error here on all of the `'static` args. - return ty; - } - if !may_define_opaque_type(tcx, fn_def_id, opaque_hir_id) { - return ty; - } - trace!("check_opaque_types: may define, generics={:#?}", generics); - let mut seen_params: FxHashMap<_, Vec<_>> = FxHashMap::default(); - for (i, arg) in substs.iter().enumerate() { - let arg_is_param = match arg.unpack() { - GenericArgKind::Type(ty) => matches!(ty.kind(), ty::Param(_)), - - GenericArgKind::Lifetime(region) if let ty::ReStatic = region => { - tcx.sess - .struct_span_err( - span, - "non-defining opaque type use in defining scope", - ) - .span_label( - tcx.def_span(generics.param_at(i, tcx).def_id), - "cannot use static lifetime; use a bound lifetime \ - instead or remove the lifetime parameter from the \ - opaque type", - ) - .emit(); - continue; - } - - GenericArgKind::Lifetime(_) => true, - - GenericArgKind::Const(ct) => matches!(ct.val, ty::ConstKind::Param(_)), - }; - - if arg_is_param { - seen_params.entry(arg).or_default().push(i); - } else { - // Prevent `fn foo() -> Foo` from being defining. - let opaque_param = generics.param_at(i, tcx); - tcx.sess - .struct_span_err(span, "non-defining opaque type use in defining scope") - .span_note( - tcx.def_span(opaque_param.def_id), - &format!( - "used non-generic {} `{}` for generic parameter", - opaque_param.kind.descr(), - arg, - ), - ) - .emit(); - } - } // for (arg, param) - - for (_, indices) in seen_params { - if indices.len() > 1 { - let descr = generics.param_at(indices[0], tcx).kind.descr(); - let spans: Vec<_> = indices - .into_iter() - .map(|i| tcx.def_span(generics.param_at(i, tcx).def_id)) - .collect(); - tcx.sess - .struct_span_err(span, "non-defining opaque type use in defining scope") - .span_note(spans, &format!("{} used multiple times", descr)) - .emit(); - } - } - } // if let Opaque - ty - }, - lt_op: |lt| lt, - ct_op: |ct| ct, - }); -} - const HELP_FOR_SELF_TYPE: &str = "consider changing to `self`, `&self`, `&mut self`, `self: Box`, \ `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one \ of the previous types except `Self`)"; @@ -1290,10 +1186,10 @@ fn receiver_is_implemented( cause: ObligationCause<'tcx>, receiver_ty: Ty<'tcx>, ) -> bool { - let trait_ref = ty::TraitRef { + let trait_ref = ty::Binder::dummy(ty::TraitRef { def_id: receiver_trait_def_id, substs: fcx.tcx.mk_substs_trait(receiver_ty, &[]), - }; + }); let obligation = traits::Obligation::new( cause, @@ -1439,20 +1335,23 @@ impl Visitor<'tcx> for CheckTypeWellFormedVisitor<'tcx> { hir_visit::NestedVisitorMap::OnlyBodies(self.tcx.hir()) } + #[instrument(skip(self, i), level = "debug")] fn visit_item(&mut self, i: &'tcx hir::Item<'tcx>) { - debug!("visit_item: {:?}", i); + trace!(?i); self.tcx.ensure().check_item_well_formed(i.def_id); hir_visit::walk_item(self, i); } + #[instrument(skip(self, trait_item), level = "debug")] fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem<'tcx>) { - debug!("visit_trait_item: {:?}", trait_item); + trace!(?trait_item); self.tcx.ensure().check_trait_item_well_formed(trait_item.def_id); hir_visit::walk_trait_item(self, trait_item); } + #[instrument(skip(self, impl_item), level = "debug")] fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) { - debug!("visit_impl_item: {:?}", impl_item); + trace!(?impl_item); self.tcx.ensure().check_impl_item_well_formed(impl_item.def_id); hir_visit::walk_impl_item(self, impl_item); } @@ -1513,7 +1412,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .collect() } - pub(super) fn impl_implied_bounds(&self, impl_def_id: DefId, span: Span) -> Vec> { + pub(super) fn impl_implied_bounds( + &self, + impl_def_id: DefId, + span: Span, + ) -> FxHashSet> { match self.tcx.impl_trait_ref(impl_def_id) { Some(trait_ref) => { // Trait impl: take implied bounds from all types that @@ -1526,7 +1429,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Inherent impl: take implied bounds from the `self` type. let self_ty = self.tcx.type_of(impl_def_id); let self_ty = self.normalize_associated_types_in(span, self_ty); - vec![self_ty] + std::array::IntoIter::new([self_ty]).collect() } } } diff --git a/compiler/rustc_typeck/src/check/writeback.rs b/compiler/rustc_typeck/src/check/writeback.rs index c57ec9ef78..d951df94dc 100644 --- a/compiler/rustc_typeck/src/check/writeback.rs +++ b/compiler/rustc_typeck/src/check/writeback.rs @@ -140,7 +140,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { // operating on scalars, we clear the overload. fn fix_scalar_builtin_expr(&mut self, e: &hir::Expr<'_>) { match e.kind { - hir::ExprKind::Unary(hir::UnOp::Neg | hir::UnOp::Not, ref inner) => { + hir::ExprKind::Unary(hir::UnOp::Neg | hir::UnOp::Not, inner) => { let inner_ty = self.fcx.node_ty(inner.hir_id); let inner_ty = self.fcx.resolve_vars_if_possible(inner_ty); @@ -150,8 +150,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { typeck_results.node_substs_mut().remove(e.hir_id); } } - hir::ExprKind::Binary(ref op, ref lhs, ref rhs) - | hir::ExprKind::AssignOp(ref op, ref lhs, ref rhs) => { + hir::ExprKind::Binary(ref op, lhs, rhs) | hir::ExprKind::AssignOp(ref op, lhs, rhs) => { let lhs_ty = self.fcx.node_ty(lhs.hir_id); let lhs_ty = self.fcx.resolve_vars_if_possible(lhs_ty); @@ -198,7 +197,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { // All valid indexing looks like this; might encounter non-valid indexes at this point. let base_ty = typeck_results - .expr_ty_adjusted_opt(&base) + .expr_ty_adjusted_opt(base) .map(|t| self.fcx.resolve_vars_if_possible(t).kind()); if base_ty.is_none() { // When encountering `return [0][0]` outside of a `fn` body we can encounter a base @@ -207,7 +206,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { self.tcx().sess.delay_span_bug(e.span, &format!("bad base: `{:?}`", base)); } if let Some(ty::Ref(_, base_ty, _)) = base_ty { - let index_ty = typeck_results.expr_ty_adjusted_opt(&index).unwrap_or_else(|| { + let index_ty = typeck_results.expr_ty_adjusted_opt(index).unwrap_or_else(|| { // When encountering `return [0][0]` outside of a `fn` body we would attempt // to access an unexistend index. We assume that more relevant errors will // already have been emitted, so we only gate on this with an ICE if no @@ -497,6 +496,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { fcx_typeck_results.generator_interior_types.clone(); } + #[instrument(skip(self, span), level = "debug")] fn visit_opaque_types(&mut self, span: Span) { let opaque_types = self.fcx.infcx.inner.borrow().opaque_types.clone(); for (opaque_type_key, opaque_defn) in opaque_types { @@ -564,6 +564,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { } } + #[instrument(skip(self, span), level = "debug")] fn visit_node_id(&mut self, span: Span, hir_id: hir::HirId) { // Export associated path extensions and method resolutions. if let Some(def) = @@ -579,7 +580,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { let n_ty = self.fcx.node_ty(hir_id); let n_ty = self.resolve(n_ty, &span); self.write_ty_to_typeck_results(hir_id, n_ty); - debug!("node {:?} has type {:?}", hir_id, n_ty); + debug!(?n_ty); // Resolve any substitutions if let Some(substs) = self.fcx.typeck_results.borrow().node_substs_opt(hir_id) { @@ -590,31 +591,33 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { } } + #[instrument(skip(self, span), level = "debug")] fn visit_adjustments(&mut self, span: Span, hir_id: hir::HirId) { let adjustment = self.fcx.typeck_results.borrow_mut().adjustments_mut().remove(hir_id); match adjustment { None => { - debug!("no adjustments for node {:?}", hir_id); + debug!("no adjustments for node"); } Some(adjustment) => { let resolved_adjustment = self.resolve(adjustment, &span); - debug!("adjustments for node {:?}: {:?}", hir_id, resolved_adjustment); + debug!(?resolved_adjustment); self.typeck_results.adjustments_mut().insert(hir_id, resolved_adjustment); } } } + #[instrument(skip(self, span), level = "debug")] fn visit_pat_adjustments(&mut self, span: Span, hir_id: hir::HirId) { let adjustment = self.fcx.typeck_results.borrow_mut().pat_adjustments_mut().remove(hir_id); match adjustment { None => { - debug!("no pat_adjustments for node {:?}", hir_id); + debug!("no pat_adjustments for node"); } Some(adjustment) => { let resolved_adjustment = self.resolve(adjustment, &span); - debug!("pat_adjustments for node {:?}: {:?}", hir_id, resolved_adjustment); + debug!(?resolved_adjustment); self.typeck_results.pat_adjustments_mut().insert(hir_id, resolved_adjustment); } } @@ -732,6 +735,26 @@ impl<'cx, 'tcx> Resolver<'cx, 'tcx> { } } +struct EraseEarlyRegions<'tcx> { + tcx: TyCtxt<'tcx>, +} + +impl<'tcx> TypeFolder<'tcx> for EraseEarlyRegions<'tcx> { + fn tcx<'b>(&'b self) -> TyCtxt<'tcx> { + self.tcx + } + fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { + if ty.has_type_flags(ty::TypeFlags::HAS_POTENTIAL_FREE_REGIONS) { + ty.super_fold_with(self) + } else { + ty + } + } + fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { + if let ty::ReLateBound(..) = r { r } else { self.tcx.lifetimes.re_erased } + } +} + impl<'cx, 'tcx> TypeFolder<'tcx> for Resolver<'cx, 'tcx> { fn tcx<'a>(&'a self) -> TyCtxt<'tcx> { self.tcx @@ -739,7 +762,13 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Resolver<'cx, 'tcx> { fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { match self.infcx.fully_resolve(t) { - Ok(t) => self.infcx.tcx.erase_regions(t), + Ok(t) => { + // Do not anonymize late-bound regions + // (e.g. keep `for<'a>` named `for<'a>`). + // This allows NLL to generate error messages that + // refer to the higher-ranked lifetime names written by the user. + EraseEarlyRegions { tcx: self.infcx.tcx }.fold_ty(t) + } Err(_) => { debug!("Resolver::fold_ty: input type `{:?}` not fully resolvable", t); self.report_type_error(t); diff --git a/compiler/rustc_typeck/src/check_unused.rs b/compiler/rustc_typeck/src/check_unused.rs index cb127880c6..89ce3700aa 100644 --- a/compiler/rustc_typeck/src/check_unused.rs +++ b/compiler/rustc_typeck/src/check_unused.rs @@ -9,14 +9,14 @@ use rustc_span::{Span, Symbol}; pub fn check_crate(tcx: TyCtxt<'_>) { let mut used_trait_imports = FxHashSet::default(); - for item_def_id in tcx.body_owners() { + for item_def_id in tcx.hir().body_owners() { let imports = tcx.used_trait_imports(item_def_id); debug!("GatherVisitor: item_def_id={:?} with imports {:#?}", item_def_id, imports); used_trait_imports.extend(imports.iter()); } let mut visitor = CheckVisitor { tcx, used_trait_imports }; - tcx.hir().krate().visit_all_item_likes(&mut visitor); + tcx.hir().visit_all_item_likes(&mut visitor); unused_crates_lint(tcx); } @@ -26,7 +26,7 @@ impl ItemLikeVisitor<'v> for CheckVisitor<'tcx> { if item.vis.node.is_pub() || item.span.is_dummy() { return; } - if let hir::ItemKind::Use(ref path, _) = item.kind { + if let hir::ItemKind::Use(path, _) = item.kind { self.check_import(item.item_id(), path.span); } } @@ -111,7 +111,7 @@ fn unused_crates_lint(tcx: TyCtxt<'_>) { // Collect all the extern crates (in a reliable order). let mut crates_to_lint = vec![]; - tcx.hir().krate().visit_all_item_likes(&mut CollectExternCrateVisitor { + tcx.hir().visit_all_item_likes(&mut CollectExternCrateVisitor { crates_to_lint: &mut crates_to_lint, }); diff --git a/compiler/rustc_typeck/src/coherence/inherent_impls.rs b/compiler/rustc_typeck/src/coherence/inherent_impls.rs index c7be9e2123..6a9ba9d491 100644 --- a/compiler/rustc_typeck/src/coherence/inherent_impls.rs +++ b/compiler/rustc_typeck/src/coherence/inherent_impls.rs @@ -17,9 +17,8 @@ use rustc_span::Span; /// On-demand query: yields a map containing all types mapped to their inherent impls. pub fn crate_inherent_impls(tcx: TyCtxt<'_>, (): ()) -> CrateInherentImpls { - let krate = tcx.hir().krate(); let mut collect = InherentCollect { tcx, impls_map: Default::default() }; - krate.visit_all_item_likes(&mut collect); + tcx.hir().visit_all_item_likes(&mut collect); collect.impls_map } @@ -57,7 +56,7 @@ impl ItemLikeVisitor<'v> for InherentCollect<'tcx> { ty::Foreign(did) => { self.check_def_id(item, did); } - ty::Dynamic(ref data, ..) if data.principal_def_id().is_some() => { + ty::Dynamic(data, ..) if data.principal_def_id().is_some() => { self.check_def_id(item, data.principal_def_id().unwrap()); } ty::Dynamic(..) => { @@ -401,7 +400,7 @@ impl InherentCollect<'tcx> { lang: &str, ty: &str, span: Span, - assoc_items: &[hir::ImplItemRef<'_>], + assoc_items: &[hir::ImplItemRef], ) { match (lang_def_id, lang_def_id2) { (Some(lang_def_id), _) if lang_def_id == impl_def_id.to_def_id() => { @@ -411,7 +410,7 @@ impl InherentCollect<'tcx> { // OK } _ => { - let to_implement = if assoc_items.len() == 0 { + let to_implement = if assoc_items.is_empty() { String::new() } else { let plural = assoc_items.len() > 1; diff --git a/compiler/rustc_typeck/src/coherence/inherent_impls_overlap.rs b/compiler/rustc_typeck/src/coherence/inherent_impls_overlap.rs index 1c36335be8..beacf301ca 100644 --- a/compiler/rustc_typeck/src/coherence/inherent_impls_overlap.rs +++ b/compiler/rustc_typeck/src/coherence/inherent_impls_overlap.rs @@ -3,6 +3,7 @@ use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::itemlikevisit::ItemLikeVisitor; +use rustc_index::vec::IndexVec; use rustc_middle::ty::{self, TyCtxt}; use rustc_span::Symbol; use rustc_trait_selection::traits::{self, SkipLeakCheck}; @@ -10,8 +11,7 @@ use smallvec::SmallVec; use std::collections::hash_map::Entry; pub fn crate_inherent_impls_overlap_check(tcx: TyCtxt<'_>, (): ()) { - let krate = tcx.hir().krate(); - krate.visit_all_item_likes(&mut InherentOverlapChecker { tcx }); + tcx.hir().visit_all_item_likes(&mut InherentOverlapChecker { tcx }); } struct InherentOverlapChecker<'tcx> { @@ -159,14 +159,18 @@ impl ItemLikeVisitor<'v> for InherentOverlapChecker<'tcx> { // This is advantageous to running the algorithm over the // entire graph when there are many connected regions. + rustc_index::newtype_index! { + pub struct RegionId { + ENCODABLE = custom + } + } struct ConnectedRegion { idents: SmallVec<[Symbol; 8]>, impl_blocks: FxHashSet, } - // Highest connected region id - let mut highest_region_id = 0; + let mut connected_regions: IndexVec = Default::default(); + // Reverse map from the Symbol to the connected region id. let mut connected_region_ids = FxHashMap::default(); - let mut connected_regions = FxHashMap::default(); for (i, &(&_impl_def_id, impl_items)) in impls_items.iter().enumerate() { if impl_items.len() == 0 { @@ -174,7 +178,7 @@ impl ItemLikeVisitor<'v> for InherentOverlapChecker<'tcx> { } // First obtain a list of existing connected region ids let mut idents_to_add = SmallVec::<[Symbol; 8]>::new(); - let ids = impl_items + let mut ids = impl_items .in_definition_order() .filter_map(|item| { let entry = connected_region_ids.entry(item.ident.name); @@ -185,62 +189,65 @@ impl ItemLikeVisitor<'v> for InherentOverlapChecker<'tcx> { None } }) - .collect::>(); - match ids.len() { - 0 | 1 => { - let id_to_set = if ids.len() == 0 { - // Create a new connected region - let region = ConnectedRegion { + .collect::>(); + // Sort the id list so that the algorithm is deterministic + ids.sort_unstable(); + ids.dedup(); + let ids = ids; + match &ids[..] { + // Create a new connected region + [] => { + let id_to_set = connected_regions.next_index(); + // Update the connected region ids + for ident in &idents_to_add { + connected_region_ids.insert(*ident, id_to_set); + } + connected_regions.insert( + id_to_set, + ConnectedRegion { idents: idents_to_add, impl_blocks: std::iter::once(i).collect(), - }; - connected_regions.insert(highest_region_id, region); - (highest_region_id, highest_region_id += 1).0 - } else { - // Take the only id inside the list - let id_to_set = *ids.iter().next().unwrap(); - let region = connected_regions.get_mut(&id_to_set).unwrap(); - region.impl_blocks.insert(i); - region.idents.extend_from_slice(&idents_to_add); - id_to_set - }; - let (_id, region) = connected_regions.iter().next().unwrap(); + }, + ); + } + // Take the only id inside the list + &[id_to_set] => { + let region = connected_regions[id_to_set].as_mut().unwrap(); + region.impl_blocks.insert(i); + region.idents.extend_from_slice(&idents_to_add); // Update the connected region ids - for ident in region.idents.iter() { + for ident in &idents_to_add { connected_region_ids.insert(*ident, id_to_set); } } - _ => { - // We have multiple connected regions to merge. - // In the worst case this might add impl blocks - // one by one and can thus be O(n^2) in the size - // of the resulting final connected region, but - // this is no issue as the final step to check - // for overlaps runs in O(n^2) as well. - - // Take the smallest id from the list - let id_to_set = *ids.iter().min().unwrap(); - - // Sort the id list so that the algorithm is deterministic - let mut ids = ids.into_iter().collect::>(); - ids.sort_unstable(); - - let mut region = connected_regions.remove(&id_to_set).unwrap(); - region.idents.extend_from_slice(&idents_to_add); + // We have multiple connected regions to merge. + // In the worst case this might add impl blocks + // one by one and can thus be O(n^2) in the size + // of the resulting final connected region, but + // this is no issue as the final step to check + // for overlaps runs in O(n^2) as well. + &[id_to_set, ..] => { + let mut region = connected_regions.remove(id_to_set).unwrap(); region.impl_blocks.insert(i); + region.idents.extend_from_slice(&idents_to_add); + // Update the connected region ids + for ident in &idents_to_add { + connected_region_ids.insert(*ident, id_to_set); + } + // Remove other regions from ids. for &id in ids.iter() { if id == id_to_set { continue; } - let r = connected_regions.remove(&id).unwrap(); - // Update the connected region ids + let r = connected_regions.remove(id).unwrap(); for ident in r.idents.iter() { connected_region_ids.insert(*ident, id_to_set); } region.idents.extend_from_slice(&r.idents); region.impl_blocks.extend(r.impl_blocks); } + connected_regions.insert(id_to_set, region); } } @@ -255,16 +262,22 @@ impl ItemLikeVisitor<'v> for InherentOverlapChecker<'tcx> { let avg = impls.len() / connected_regions.len(); let s = connected_regions .iter() - .map(|r| r.1.impl_blocks.len() as isize - avg as isize) + .flatten() + .map(|r| r.impl_blocks.len() as isize - avg as isize) .map(|v| v.abs() as usize) .sum::(); s / connected_regions.len() }, - connected_regions.iter().map(|r| r.1.impl_blocks.len()).max().unwrap() + connected_regions + .iter() + .flatten() + .map(|r| r.impl_blocks.len()) + .max() + .unwrap() ); // List of connected regions is built. Now, run the overlap check // for each pair of impl blocks in the same connected region. - for (_id, region) in connected_regions.into_iter() { + for region in connected_regions.into_iter().flatten() { let mut impl_blocks = region.impl_blocks.into_iter().collect::>(); impl_blocks.sort_unstable(); diff --git a/compiler/rustc_typeck/src/coherence/mod.rs b/compiler/rustc_typeck/src/coherence/mod.rs index 7ac26a3187..079604f128 100644 --- a/compiler/rustc_typeck/src/coherence/mod.rs +++ b/compiler/rustc_typeck/src/coherence/mod.rs @@ -221,7 +221,7 @@ fn check_object_overlap<'tcx>( } // check for overlap with the automatic `impl Trait for dyn Trait` - if let ty::Dynamic(ref data, ..) = trait_ref.self_ty().kind() { + if let ty::Dynamic(data, ..) = trait_ref.self_ty().kind() { // This is something like impl Trait1 for Trait2. Illegal // if Trait1 is a supertrait of Trait2 or Trait2 is not object safe. diff --git a/compiler/rustc_typeck/src/coherence/orphan.rs b/compiler/rustc_typeck/src/coherence/orphan.rs index 05932427bc..0326d1fd74 100644 --- a/compiler/rustc_typeck/src/coherence/orphan.rs +++ b/compiler/rustc_typeck/src/coherence/orphan.rs @@ -10,7 +10,7 @@ use rustc_trait_selection::traits; pub fn check(tcx: TyCtxt<'_>) { let mut orphan = OrphanChecker { tcx }; - tcx.hir().krate().visit_all_item_likes(&mut orphan); + tcx.hir().visit_all_item_likes(&mut orphan); } struct OrphanChecker<'tcx> { diff --git a/compiler/rustc_typeck/src/coherence/unsafety.rs b/compiler/rustc_typeck/src/coherence/unsafety.rs index 6b995b9738..e7b03fa3ac 100644 --- a/compiler/rustc_typeck/src/coherence/unsafety.rs +++ b/compiler/rustc_typeck/src/coherence/unsafety.rs @@ -9,7 +9,7 @@ use rustc_middle::ty::TyCtxt; pub fn check(tcx: TyCtxt<'_>) { let mut unsafety = UnsafetyChecker { tcx }; - tcx.hir().krate().visit_all_item_likes(&mut unsafety); + tcx.hir().visit_all_item_likes(&mut unsafety); } struct UnsafetyChecker<'tcx> { diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index 64120510e5..df7f2aea9c 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -14,7 +14,7 @@ //! At present, however, we do run collection across all items in the //! crate as a kind of pass. This should eventually be factored away. -use crate::astconv::{AstConv, SizedByDefault}; +use crate::astconv::AstConv; use crate::bounds::Bounds; use crate::check::intrinsic::intrinsic_operation_unsafety; use crate::constrained_generic_params as cgp; @@ -40,13 +40,13 @@ use rustc_middle::ty::query::Providers; use rustc_middle::ty::subst::InternalSubsts; use rustc_middle::ty::util::Discr; use rustc_middle::ty::util::IntTypeExt; -use rustc_middle::ty::{self, AdtKind, Const, DefIdTree, ToPolyTraitRef, Ty, TyCtxt}; +use rustc_middle::ty::{self, AdtKind, Const, DefIdTree, Ty, TyCtxt}; use rustc_middle::ty::{ReprOptions, ToPredicate, WithConstness}; use rustc_session::lint; use rustc_session::parse::feature_err; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{Span, DUMMY_SP}; -use rustc_target::spec::{abi, SanitizerSet}; +use rustc_target::spec::{abi, PanicStrategy, SanitizerSet}; use rustc_trait_selection::traits::error_reporting::suggestions::NextTypeParamName; use std::iter; @@ -199,20 +199,16 @@ crate fn placeholder_type_error( let parent_id = tcx.hir().get_parent_node(hir_ty.hir_id); let parent_node = tcx.hir().get(parent_id); - is_const_or_static = match parent_node { + is_const_or_static = matches!( + parent_node, Node::Item(&hir::Item { kind: hir::ItemKind::Const(..) | hir::ItemKind::Static(..), .. - }) - | Node::TraitItem(&hir::TraitItem { + }) | Node::TraitItem(&hir::TraitItem { kind: hir::TraitItemKind::Const(..), .. - }) - | Node::ImplItem(&hir::ImplItem { - kind: hir::ImplItemKind::Const(..), .. - }) => true, - _ => false, - }; + }) | Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Const(..), .. }) + ); } } @@ -450,9 +446,9 @@ impl AstConv<'tcx> for ItemCtxt<'tcx> { let suggestions = vec![ (lt_sp, sugg), ( - span, + span.with_hi(item_segment.ident.span.lo()), format!( - "{}::{}", + "{}::", // Replace the existing lifetimes with a new named lifetime. self.tcx .replace_late_bound_regions(poly_trait_ref, |_| { @@ -465,7 +461,6 @@ impl AstConv<'tcx> for ItemCtxt<'tcx> { )) }) .0, - item_segment.ident ), ), ]; @@ -487,14 +482,13 @@ impl AstConv<'tcx> for ItemCtxt<'tcx> { | hir::Node::ForeignItem(_) | hir::Node::TraitItem(_) | hir::Node::ImplItem(_) => { - err.span_suggestion( - span, + err.span_suggestion_verbose( + span.with_hi(item_segment.ident.span.lo()), "use a fully qualified path with inferred lifetimes", format!( - "{}::{}", + "{}::", // Erase named lt, we want `::C`, not `::C`. self.tcx.anonymize_late_bound_regions(poly_trait_ref).skip_binder(), - item_segment.ident ), Applicability::MaybeIncorrect, ); @@ -683,10 +677,10 @@ impl ItemCtxt<'tcx> { _ => None, }) .flat_map(|bp| { - let bt = if is_param(self.tcx, &bp.bounded_ty, param_id) { + let bt = if is_param(self.tcx, bp.bounded_ty, param_id) { Some(ty) } else if !only_self_bounds.0 { - Some(self.to_ty(&bp.bounded_ty)) + Some(self.to_ty(bp.bounded_ty)) } else { None }; @@ -725,7 +719,7 @@ impl ItemCtxt<'tcx> { /// `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, ref path)) = ast_ty.kind { + 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() @@ -778,7 +772,7 @@ fn convert_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) { tcx.ensure().generics_of(def_id); tcx.ensure().type_of(def_id); tcx.ensure().predicates_of(def_id); - convert_enum_variant_types(tcx, def_id.to_def_id(), &enum_definition.variants); + convert_enum_variant_types(tcx, def_id.to_def_id(), enum_definition.variants); } hir::ItemKind::Impl { .. } => { tcx.ensure().generics_of(def_id); @@ -1155,19 +1149,11 @@ fn super_predicates_that_define_assoc_type( >::compute_bounds_that_match_assoc_type( &icx, self_param_ty, - &bounds, - SizedByDefault::No, - item.span, + bounds, assoc_name, ) } else { - >::compute_bounds( - &icx, - self_param_ty, - &bounds, - SizedByDefault::No, - item.span, - ) + >::compute_bounds(&icx, self_param_ty, bounds) }; let superbounds1 = superbounds1.predicates(tcx, self_param_ty); @@ -1344,25 +1330,25 @@ fn has_late_bound_regions<'tcx>(tcx: TyCtxt<'tcx>, node: Node<'tcx>) -> Option match item.kind { hir::TraitItemKind::Fn(ref sig, _) => { - has_late_bound_regions(tcx, &item.generics, &sig.decl) + has_late_bound_regions(tcx, &item.generics, sig.decl) } _ => None, }, Node::ImplItem(item) => match item.kind { hir::ImplItemKind::Fn(ref sig, _) => { - has_late_bound_regions(tcx, &item.generics, &sig.decl) + has_late_bound_regions(tcx, &item.generics, sig.decl) } _ => None, }, Node::ForeignItem(item) => match item.kind { - hir::ForeignItemKind::Fn(ref fn_decl, _, ref generics) => { + hir::ForeignItemKind::Fn(fn_decl, _, ref generics) => { has_late_bound_regions(tcx, generics, fn_decl) } _ => None, }, Node::Item(item) => match item.kind { hir::ItemKind::Fn(ref sig, .., ref generics, _) => { - has_late_bound_regions(tcx, generics, &sig.decl) + has_late_bound_regions(tcx, generics, sig.decl) } _ => None, }, @@ -1384,7 +1370,7 @@ impl<'v> Visitor<'v> for AnonConstInParamTyDetector { } fn visit_generic_param(&mut self, p: &'v hir::GenericParam<'v>) { - if let GenericParamKind::Const { ref ty, default: _ } = p.kind { + if let GenericParamKind::Const { ty, default: _ } = p.kind { let prev = self.in_param_ty; self.in_param_ty = true; self.visit_ty(ty); @@ -1597,7 +1583,7 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics { let mut own_start = has_self as u32; let parent_count = parent_def_id.map_or(0, |def_id| { let generics = tcx.generics_of(def_id); - assert_eq!(has_self, false); + assert!(!has_self); parent_has_self = generics.has_self; own_start = generics.count() as u32; generics.parent_count + generics.params.len() @@ -1748,9 +1734,9 @@ fn is_suggestable_infer_ty(ty: &hir::Ty<'_>) -> bool { } pub fn get_infer_ret_ty(output: &'hir hir::FnRetTy<'hir>) -> Option<&'hir hir::Ty<'hir>> { - if let hir::FnRetTy::Return(ref ty) = output { + if let hir::FnRetTy::Return(ty) = output { if is_suggestable_infer_ty(ty) { - return Some(&**ty); + return Some(&*ty); } } None @@ -1820,8 +1806,8 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> { hir_id, sig.header.unsafety, sig.header.abi, - &sig.decl, - &generics, + sig.decl, + generics, Some(ident.span), None, ), @@ -1839,15 +1825,13 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> { header.unsafety, header.abi, decl, - &generics, + generics, Some(ident.span), None, ), ForeignItem(&hir::ForeignItem { - kind: ForeignItemKind::Fn(ref fn_decl, _, _), - ident, - .. + kind: ForeignItemKind::Fn(fn_decl, _, _), ident, .. }) => { let abi = tcx.hir().get_foreign_abi(hir_id); compute_sig_of_foreign_fn_decl(tcx, def_id.to_def_id(), fn_decl, abi, ident) @@ -2052,7 +2036,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP match item.kind { ItemKind::Impl(ref impl_) => { if impl_.defaultness.is_default() { - is_default_impl_trait = tcx.impl_trait_ref(def_id); + is_default_impl_trait = tcx.impl_trait_ref(def_id).map(ty::Binder::dummy); } &impl_.generics } @@ -2132,10 +2116,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP // (see below). Recall that a default impl is not itself an impl, but rather a // set of defaults that can be incorporated into another impl. if let Some(trait_ref) = is_default_impl_trait { - predicates.insert(( - trait_ref.to_poly_trait_ref().without_const().to_predicate(tcx), - tcx.def_span(def_id), - )); + predicates.insert((trait_ref.without_const().to_predicate(tcx), tcx.def_span(def_id))); } // Collect the region predicates that were declared inline as @@ -2154,7 +2135,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP GenericParamKind::Lifetime { .. } => { param.bounds.iter().for_each(|bound| match bound { hir::GenericBound::Outlives(lt) => { - let bound = >::ast_region_to_region(&icx, <, None); + let bound = >::ast_region_to_region(&icx, lt, None); let outlives = ty::Binder::dummy(ty::OutlivesPredicate(region, bound)); predicates.insert((outlives.to_predicate(tcx), lt.span)); } @@ -2176,12 +2157,13 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP let param_ty = ty::ParamTy::new(index, name).to_ty(tcx); index += 1; - let sized = SizedByDefault::Yes; - let bounds = >::compute_bounds( + let mut bounds = >::compute_bounds(&icx, param_ty, param.bounds); + // Params are implicitly sized unless a `?Sized` bound is found + >::add_implicitly_sized( &icx, - param_ty, - ¶m.bounds, - sized, + &mut bounds, + param.bounds, + Some((param.hir_id, ast_generics.where_clause.predicates)), param.span, ); predicates.extend(bounds.predicates(tcx, param_ty)); @@ -2199,7 +2181,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP for predicate in where_clause.predicates { match predicate { hir::WherePredicate::BoundPredicate(bound_pred) => { - let ty = icx.to_ty(&bound_pred.bounded_ty); + let ty = icx.to_ty(bound_pred.bounded_ty); let bound_vars = icx.tcx.late_bound_vars(bound_pred.bounded_ty.hir_id); // Keep the type around in a dummy predicate, in case of no bounds. @@ -2227,64 +2209,15 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP } } - for bound in bound_pred.bounds.iter() { - match bound { - hir::GenericBound::Trait(poly_trait_ref, modifier) => { - let constness = match modifier { - hir::TraitBoundModifier::None => ty::BoundConstness::NotConst, - hir::TraitBoundModifier::MaybeConst => { - ty::BoundConstness::ConstIfConst - } - // We ignore `where T: ?Sized`, it is already part of - // type parameter `T`. - hir::TraitBoundModifier::Maybe => continue, - }; - - let mut bounds = Bounds::default(); - let _ = >::instantiate_poly_trait_ref( - &icx, - &poly_trait_ref.trait_ref, - poly_trait_ref.span, - constness, - ty, - &mut bounds, - false, - ); - predicates.extend(bounds.predicates(tcx, ty)); - } - - &hir::GenericBound::LangItemTrait(lang_item, span, hir_id, args) => { - let mut bounds = Bounds::default(); - >::instantiate_lang_item_trait_ref( - &icx, - lang_item, - span, - hir_id, - args, - ty, - &mut bounds, - ); - predicates.extend(bounds.predicates(tcx, ty)); - } - - hir::GenericBound::Unsized(_) => {} - - hir::GenericBound::Outlives(lifetime) => { - let region = - >::ast_region_to_region(&icx, lifetime, None); - predicates.insert(( - ty::Binder::bind_with_vars( - ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate( - ty, region, - )), - bound_vars, - ) - .to_predicate(tcx), - lifetime.span, - )); - } - } - } + let mut bounds = Bounds::default(); + >::add_bounds( + &icx, + ty, + bound_pred.bounds.iter(), + &mut bounds, + bound_vars, + ); + predicates.extend(bounds.predicates(tcx, ty)); } hir::WherePredicate::RegionPredicate(region_pred) => { @@ -2296,8 +2229,10 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP } _ => bug!(), }; - let pred = ty::PredicateKind::RegionOutlives(ty::OutlivesPredicate(r1, r2)) - .to_predicate(icx.tcx); + let pred = ty::Binder::dummy(ty::PredicateKind::RegionOutlives( + ty::OutlivesPredicate(r1, r2), + )) + .to_predicate(icx.tcx); (pred, span) })) @@ -2362,7 +2297,8 @@ fn const_evaluatable_predicates_of<'tcx>( assert_eq!(uv.promoted, None); let span = self.tcx.hir().span(c.hir_id); self.preds.insert(( - ty::PredicateKind::ConstEvaluatable(uv.shrink()).to_predicate(self.tcx), + ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(uv.shrink())) + .to_predicate(self.tcx), span, )); } @@ -2466,7 +2402,7 @@ fn explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicat } else { if matches!(def_kind, DefKind::AnonConst) && tcx.lazy_normalization() { let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); - if let Some(_) = tcx.hir().opt_const_param_default_param_hir_id(hir_id) { + if tcx.hir().opt_const_param_default_param_hir_id(hir_id).is_some() { // In `generics_of` we set the generics' parent to be our parent's parent which means that // we lose out on the predicates of our actual parent if we dont return those predicates here. // (See comment in `generics_of` for more information on why the parent shenanigans is necessary) @@ -2498,45 +2434,14 @@ fn predicates_from_bound<'tcx>( param_ty: Ty<'tcx>, bound: &'tcx hir::GenericBound<'tcx>, ) -> Vec<(ty::Predicate<'tcx>, Span)> { - match *bound { - hir::GenericBound::Trait(ref tr, modifier) => { - let constness = match modifier { - hir::TraitBoundModifier::Maybe => return vec![], - hir::TraitBoundModifier::MaybeConst => ty::BoundConstness::ConstIfConst, - hir::TraitBoundModifier::None => ty::BoundConstness::NotConst, - }; - - let mut bounds = Bounds::default(); - let _ = astconv.instantiate_poly_trait_ref( - &tr.trait_ref, - tr.span, - constness, - param_ty, - &mut bounds, - false, - ); - bounds.predicates(astconv.tcx(), param_ty) - } - hir::GenericBound::LangItemTrait(lang_item, span, hir_id, args) => { - let mut bounds = Bounds::default(); - astconv.instantiate_lang_item_trait_ref( - lang_item, - span, - hir_id, - args, - param_ty, - &mut bounds, - ); - bounds.predicates(astconv.tcx(), param_ty) - } - hir::GenericBound::Unsized(_) => vec![], - hir::GenericBound::Outlives(ref lifetime) => { - let region = astconv.ast_region_to_region(lifetime, None); - let pred = ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(param_ty, region)) - .to_predicate(astconv.tcx()); - vec![(pred, lifetime.span)] - } - } + let mut bounds = Bounds::default(); + astconv.add_bounds( + param_ty, + std::array::IntoIter::new([bound]), + &mut bounds, + ty::List::empty(), + ); + bounds.predicates(astconv.tcx(), param_ty) } fn compute_sig_of_foreign_fn_decl<'tcx>( @@ -2590,10 +2495,10 @@ fn compute_sig_of_foreign_fn_decl<'tcx>( } }; for (input, ty) in iter::zip(decl.inputs, fty.inputs().skip_binder()) { - check(&input, ty) + check(input, ty) } if let hir::FnRetTy::Return(ref ty) = decl.output { - check(&ty, fty.output().skip_binder()) + check(ty, fty.output().skip_binder()) } } @@ -2648,7 +2553,7 @@ fn from_target_feature( let msg = "malformed `target_feature` attribute input"; let code = "enable = \"..\"".to_owned(); tcx.sess - .struct_span_err(span, &msg) + .struct_span_err(span, msg) .span_suggestion(span, "must be of the form", code, Applicability::HasPlaceholders) .emit(); }; @@ -2770,6 +2675,13 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs { codegen_fn_attrs.flags |= CodegenFnAttrFlags::TRACK_CALLER; } + // With -Z panic-in-drop=abort, drop_in_place never unwinds. + if tcx.sess.opts.debugging_opts.panic_in_drop == PanicStrategy::Abort { + if Some(id) == tcx.lang_items().drop_in_place_fn() { + codegen_fn_attrs.flags |= CodegenFnAttrFlags::NEVER_UNWIND; + } + } + let supported_target_features = tcx.supported_target_features(LOCAL_CRATE); let mut inline_span = None; @@ -2860,10 +2772,19 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs { } else if attr.has_name(sym::thread_local) { codegen_fn_attrs.flags |= CodegenFnAttrFlags::THREAD_LOCAL; } else if attr.has_name(sym::track_caller) { - if tcx.is_closure(id) || tcx.fn_sig(id).abi() != abi::Abi::Rust { + if !tcx.is_closure(id) && tcx.fn_sig(id).abi() != abi::Abi::Rust { struct_span_err!(tcx.sess, attr.span, E0737, "`#[track_caller]` requires Rust ABI") .emit(); } + if tcx.is_closure(id) && !tcx.features().closure_track_caller { + feature_err( + &tcx.sess.parse_sess, + sym::closure_track_caller, + attr.span, + "`#[track_caller]` on closures is currently unstable", + ) + .emit(); + } codegen_fn_attrs.flags |= CodegenFnAttrFlags::TRACK_CALLER; } else if attr.has_name(sym::export_name) { if let Some(s) = attr.value_str() { @@ -2917,7 +2838,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs { tcx, id, attr, - &supported_target_features, + supported_target_features, &mut codegen_fn_attrs.target_features, ); } else if attr.has_name(sym::linkage) { @@ -2940,6 +2861,14 @@ 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; @@ -3184,7 +3113,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs { codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL; } let check_name = |attr: &Attribute, sym| attr.has_name(sym); - if let Some(name) = weak_lang_items::link_name(check_name, &attrs) { + if let Some(name) = weak_lang_items::link_name(check_name, attrs) { codegen_fn_attrs.export_name = Some(name); codegen_fn_attrs.link_name = Some(name); } @@ -3235,22 +3164,41 @@ fn should_inherit_track_caller(tcx: TyCtxt<'_>, def_id: DefId) -> bool { false } -fn check_link_ordinal(tcx: TyCtxt<'_>, attr: &ast::Attribute) -> Option { +fn check_link_ordinal(tcx: TyCtxt<'_>, attr: &ast::Attribute) -> Option { use rustc_ast::{Lit, LitIntType, LitKind}; let meta_item_list = attr.meta_item_list(); let meta_item_list: Option<&[ast::NestedMetaItem]> = meta_item_list.as_ref().map(Vec::as_ref); let sole_meta_list = match meta_item_list { Some([item]) => item.literal(), + Some(_) => { + tcx.sess + .struct_span_err(attr.span, "incorrect number of arguments to `#[link_ordinal]`") + .note("the attribute requires exactly one argument") + .emit(); + return None; + } _ => None, }; if let Some(Lit { kind: LitKind::Int(ordinal, LitIntType::Unsuffixed), .. }) = sole_meta_list { - if *ordinal <= usize::MAX as u128 { - Some(*ordinal as usize) + // According to the table at https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#import-header, + // the ordinal must fit into 16 bits. Similarly, the Ordinal field in COFFShortExport (defined + // in llvm/include/llvm/Object/COFFImportFile.h), which we use to communicate import information + // to LLVM for `#[link(kind = "raw-dylib"_])`, is also defined to be uint16_t. + // + // FIXME: should we allow an ordinal of 0? The MSVC toolchain has inconsistent support for this: + // both LINK.EXE and LIB.EXE signal errors and abort when given a .DEF file that specifies + // a zero ordinal. However, llvm-dlltool is perfectly happy to generate an import library + // for such a .DEF file, and MSVC's LINK.EXE is also perfectly happy to consume an import + // library produced by LLVM with an ordinal of 0, and it generates an .EXE. (I don't know yet + // if the resulting EXE runs, as I haven't yet built the necessary DLL -- see earlier comment + // about LINK.EXE failing.) + if *ordinal <= u16::MAX as u128 { + Some(*ordinal as u16) } else { let msg = format!("ordinal value in `link_ordinal` is too large: `{}`", &ordinal); tcx.sess .struct_span_err(attr.span, &msg) - .note("the value may not exceed `usize::MAX`") + .note("the value may not exceed `u16::MAX`") .emit(); None } diff --git a/compiler/rustc_typeck/src/collect/item_bounds.rs b/compiler/rustc_typeck/src/collect/item_bounds.rs index 1d08c4450a..26cad8fb18 100644 --- a/compiler/rustc_typeck/src/collect/item_bounds.rs +++ b/compiler/rustc_typeck/src/collect/item_bounds.rs @@ -1,5 +1,5 @@ use super::ItemCtxt; -use crate::astconv::{AstConv, SizedByDefault}; +use crate::astconv::AstConv; use rustc_hir as hir; use rustc_infer::traits::util; use rustc_middle::ty::subst::InternalSubsts; @@ -17,7 +17,7 @@ use rustc_span::Span; fn associated_type_bounds<'tcx>( tcx: TyCtxt<'tcx>, assoc_item_def_id: DefId, - bounds: &'tcx [hir::GenericBound<'tcx>], + ast_bounds: &'tcx [hir::GenericBound<'tcx>], span: Span, ) -> &'tcx [(ty::Predicate<'tcx>, Span)] { let item_ty = tcx.mk_projection( @@ -25,13 +25,10 @@ fn associated_type_bounds<'tcx>( InternalSubsts::identity_for_item(tcx, assoc_item_def_id), ); - let bounds = >::compute_bounds( - &ItemCtxt::new(tcx, assoc_item_def_id), - item_ty, - &bounds, - SizedByDefault::Yes, - span, - ); + let icx = ItemCtxt::new(tcx, assoc_item_def_id); + let mut bounds = >::compute_bounds(&icx, item_ty, ast_bounds); + // Associated types are implicitly sized unless a `?Sized` bound is found + >::add_implicitly_sized(&icx, &mut bounds, ast_bounds, None, span); let trait_def_id = tcx.associated_item(assoc_item_def_id).container.id(); let trait_predicates = tcx.trait_explicit_predicates_and_bounds(trait_def_id.expect_local()); @@ -59,21 +56,18 @@ fn associated_type_bounds<'tcx>( fn opaque_type_bounds<'tcx>( tcx: TyCtxt<'tcx>, opaque_def_id: DefId, - bounds: &'tcx [hir::GenericBound<'tcx>], + ast_bounds: &'tcx [hir::GenericBound<'tcx>], span: Span, ) -> &'tcx [(ty::Predicate<'tcx>, Span)] { ty::print::with_no_queries(|| { let item_ty = tcx.mk_opaque(opaque_def_id, InternalSubsts::identity_for_item(tcx, opaque_def_id)); - let bounds = >::compute_bounds( - &ItemCtxt::new(tcx, opaque_def_id), - item_ty, - &bounds, - SizedByDefault::Yes, - span, - ) - .predicates(tcx, item_ty); + let icx = ItemCtxt::new(tcx, opaque_def_id); + let mut bounds = >::compute_bounds(&icx, item_ty, ast_bounds); + // Opaque types are implicitly sized unless a `?Sized` bound is found + >::add_implicitly_sized(&icx, &mut bounds, ast_bounds, None, span); + let bounds = bounds.predicates(tcx, item_ty); debug!("opaque_type_bounds({}) = {:?}", tcx.def_path_str(opaque_def_id), bounds); diff --git a/compiler/rustc_typeck/src/collect/type_of.rs b/compiler/rustc_typeck/src/collect/type_of.rs index 26a9ce6807..cee3679d0a 100644 --- a/compiler/rustc_typeck/src/collect/type_of.rs +++ b/compiler/rustc_typeck/src/collect/type_of.rs @@ -1,4 +1,3 @@ -use rustc_data_structures::fx::FxHashSet; use rustc_errors::{Applicability, ErrorReported, StashKey}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; @@ -7,7 +6,7 @@ use rustc_hir::intravisit; use rustc_hir::intravisit::Visitor; use rustc_hir::{HirId, Node}; use rustc_middle::hir::map::Map; -use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts, SubstsRef}; +use rustc_middle::ty::subst::{InternalSubsts, SubstsRef}; use rustc_middle::ty::util::IntTypeExt; use rustc_middle::ty::{self, DefIdTree, Ty, TyCtxt, TypeFoldable, TypeFolder}; use rustc_span::symbol::Ident; @@ -313,7 +312,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { let substs = InternalSubsts::identity_for_item(tcx, def_id.to_def_id()); tcx.mk_fn_def(def_id.to_def_id(), substs) } - TraitItemKind::Const(ref ty, body_id) => body_id + TraitItemKind::Const(ty, body_id) => body_id .and_then(|body_id| { if is_suggestable_infer_ty(ty) { Some(infer_placeholder_type( @@ -324,7 +323,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { } }) .unwrap_or_else(|| icx.to_ty(ty)), - TraitItemKind::Type(_, Some(ref ty)) => icx.to_ty(ty), + TraitItemKind::Type(_, Some(ty)) => icx.to_ty(ty), TraitItemKind::Type(_, None) => { span_bug!(item.span, "associated type missing default"); } @@ -335,14 +334,14 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { let substs = InternalSubsts::identity_for_item(tcx, def_id.to_def_id()); tcx.mk_fn_def(def_id.to_def_id(), substs) } - ImplItemKind::Const(ref ty, body_id) => { + ImplItemKind::Const(ty, body_id) => { if is_suggestable_infer_ty(ty) { infer_placeholder_type(tcx, def_id, body_id, ty.span, item.ident, "constant") } else { icx.to_ty(ty) } } - ImplItemKind::TyAlias(ref ty) => { + ImplItemKind::TyAlias(ty) => { if tcx.impl_trait_ref(tcx.hir().get_parent_did(hir_id).to_def_id()).is_none() { check_feature_inherent_assoc_ty(tcx, item.span); } @@ -353,7 +352,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { Node::Item(item) => { match item.kind { - ItemKind::Static(ref ty, .., body_id) => { + ItemKind::Static(ty, .., body_id) => { if is_suggestable_infer_ty(ty) { infer_placeholder_type( tcx, @@ -367,7 +366,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { icx.to_ty(ty) } } - ItemKind::Const(ref ty, body_id) => { + ItemKind::Const(ty, body_id) => { if is_suggestable_infer_ty(ty) { infer_placeholder_type( tcx, def_id, body_id, ty.span, item.ident, "constant", @@ -376,8 +375,8 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { icx.to_ty(ty) } } - ItemKind::TyAlias(ref self_ty, _) - | ItemKind::Impl(hir::Impl { ref self_ty, .. }) => icx.to_ty(self_ty), + ItemKind::TyAlias(self_ty, _) + | ItemKind::Impl(hir::Impl { self_ty, .. }) => icx.to_ty(self_ty), ItemKind::Fn(..) => { let substs = InternalSubsts::identity_for_item(tcx, def_id.to_def_id()); tcx.mk_fn_def(def_id.to_def_id(), substs) @@ -396,7 +395,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { .mir_borrowck(owner.expect_local()) .concrete_opaque_types .get_value_matching(|(key, _)| key.def_id == def_id.to_def_id()) - .map(|concrete_ty| *concrete_ty) + .copied() .unwrap_or_else(|| { tcx.sess.delay_span_bug( DUMMY_SP, @@ -447,7 +446,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { let substs = InternalSubsts::identity_for_item(tcx, def_id.to_def_id()); tcx.mk_fn_def(def_id.to_def_id(), substs) } - ForeignItemKind::Static(ref t, _) => icx.to_ty(t), + ForeignItemKind::Static(t, _) => icx.to_ty(t), ForeignItemKind::Type => tcx.mk_foreign(def_id.to_def_id()), }, @@ -461,7 +460,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { } }, - Node::Field(field) => icx.to_ty(&field.ty), + Node::Field(field) => icx.to_ty(field.ty), Node::Expr(&Expr { kind: ExprKind::Closure(.., gen), .. }) => { let substs = InternalSubsts::identity_for_item(tcx, def_id.to_def_id()); @@ -539,6 +538,25 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { } #[instrument(skip(tcx), level = "debug")] +/// Checks "defining uses" of opaque `impl Trait` types to ensure that they meet the restrictions +/// laid for "higher-order pattern unification". +/// This ensures that inference is tractable. +/// In particular, definitions of opaque types can only use other generics as arguments, +/// and they cannot repeat an argument. Example: +/// +/// ```rust +/// type Foo = impl Bar; +/// +/// // Okay -- `Foo` is applied to two distinct, generic types. +/// fn a() -> Foo { .. } +/// +/// // Not okay -- `Foo` is applied to `T` twice. +/// fn b() -> Foo { .. } +/// +/// // Not okay -- `Foo` is applied to a non-generic type. +/// fn b() -> Foo { .. } +/// ``` +/// fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> { use rustc_hir::{Expr, ImplItem, Item, TraitItem}; @@ -584,50 +602,8 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> { // FIXME(oli-obk): trace the actual span from inference to improve errors. let span = self.tcx.def_span(def_id); - // HACK(eddyb) this check shouldn't be needed, as `wfcheck` - // performs the same checks, in theory, but I've kept it here - // using `delay_span_bug`, just in case `wfcheck` slips up. - let opaque_generics = self.tcx.generics_of(self.def_id); - let mut used_params: FxHashSet<_> = FxHashSet::default(); - for (i, arg) in opaque_type_key.substs.iter().enumerate() { - let arg_is_param = match arg.unpack() { - GenericArgKind::Type(ty) => matches!(ty.kind(), ty::Param(_)), - GenericArgKind::Lifetime(lt) => { - matches!(lt, ty::ReEarlyBound(_) | ty::ReFree(_)) - } - GenericArgKind::Const(ct) => matches!(ct.val, ty::ConstKind::Param(_)), - }; - - if arg_is_param { - if !used_params.insert(arg) { - // There was already an entry for `arg`, meaning a generic parameter - // was used twice. - self.tcx.sess.delay_span_bug( - span, - &format!( - "defining opaque type use restricts opaque \ - type by using the generic parameter `{}` twice", - arg, - ), - ); - } - } else { - let param = opaque_generics.param_at(i, self.tcx); - self.tcx.sess.delay_span_bug( - span, - &format!( - "defining opaque type use does not fully define opaque type: \ - generic parameter `{}` is specified as concrete {} `{}`", - param.name, - param.kind.descr(), - arg, - ), - ); - } - } - if let Some((prev_span, prev_ty)) = self.found { - if *concrete_type != prev_ty { + if *concrete_type != prev_ty && !(*concrete_type, prev_ty).references_error() { debug!(?span); // Found different concrete types for the opaque type. let mut err = self.tcx.sess.struct_span_err( @@ -691,7 +667,7 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> { debug!("find_opaque_ty_constraints: scope={:?}", scope); if scope == hir::CRATE_HIR_ID { - intravisit::walk_crate(&mut locator, tcx.hir().krate()); + tcx.hir().walk_toplevel_module(&mut locator); } else { debug!("find_opaque_ty_constraints: scope={:?}", tcx.hir().get(scope)); match tcx.hir().get(scope) { @@ -709,9 +685,9 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> { // // requires us to explicitly process `foo()` in order // to notice the defining usage of `Blah`. - Node::Item(ref it) => locator.visit_item(it), - Node::ImplItem(ref it) => locator.visit_impl_item(it), - Node::TraitItem(ref it) => locator.visit_trait_item(it), + Node::Item(it) => locator.visit_item(it), + Node::ImplItem(it) => locator.visit_impl_item(it), + Node::TraitItem(it) => locator.visit_trait_item(it), other => bug!("{:?} is not a valid scope for an opaque type item", other), } } diff --git a/compiler/rustc_typeck/src/constrained_generic_params.rs b/compiler/rustc_typeck/src/constrained_generic_params.rs index 9b6f0be47c..88877ad785 100644 --- a/compiler/rustc_typeck/src/constrained_generic_params.rs +++ b/compiler/rustc_typeck/src/constrained_generic_params.rs @@ -206,7 +206,7 @@ pub fn setup_constraining_predicates<'tcx>( // Then the projection only applies if `T` is known, but it still // does not determine `U`. let inputs = parameters_for(tcx, &projection.projection_ty, true); - let relies_only_on_inputs = inputs.iter().all(|p| input_parameters.contains(&p)); + let relies_only_on_inputs = inputs.iter().all(|p| input_parameters.contains(p)); if !relies_only_on_inputs { continue; } diff --git a/compiler/rustc_typeck/src/errors.rs b/compiler/rustc_typeck/src/errors.rs index 1e6a240b2f..4707777961 100644 --- a/compiler/rustc_typeck/src/errors.rs +++ b/compiler/rustc_typeck/src/errors.rs @@ -121,14 +121,6 @@ pub struct AssocTypeBindingNotAllowed { pub span: Span, } -#[derive(SessionDiagnostic)] -#[error = "E0439"] -pub struct SimdShuffleMissingLength { - #[message = "invalid `simd_shuffle`, needs length: `{name}`"] - pub span: Span, - pub name: Symbol, -} - #[derive(SessionDiagnostic)] #[error = "E0436"] pub struct FunctionalRecordUpdateOnNonStruct { diff --git a/compiler/rustc_typeck/src/expr_use_visitor.rs b/compiler/rustc_typeck/src/expr_use_visitor.rs index b5c4d6ac26..7d0600b99e 100644 --- a/compiler/rustc_typeck/src/expr_use_visitor.rs +++ b/compiler/rustc_typeck/src/expr_use_visitor.rs @@ -124,12 +124,12 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { #[instrument(skip(self), level = "debug")] pub fn consume_body(&mut self, body: &hir::Body<'_>) { for param in body.params { - let param_ty = return_if_err!(self.mc.pat_ty_adjusted(¶m.pat)); + let param_ty = return_if_err!(self.mc.pat_ty_adjusted(param.pat)); debug!("consume_body: param_ty = {:?}", param_ty); let param_place = self.mc.cat_rvalue(param.hir_id, param.pat.span, param_ty); - self.walk_irrefutable_pat(¶m_place, ¶m.pat); + self.walk_irrefutable_pat(¶m_place, param.pat); } self.consume_expr(&body.value); @@ -145,7 +145,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { fn consume_exprs(&mut self, exprs: &[hir::Expr<'_>]) { for expr in exprs { - self.consume_expr(&expr); + self.consume_expr(expr); } } @@ -184,57 +184,57 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { match expr.kind { hir::ExprKind::Path(_) => {} - hir::ExprKind::Type(ref subexpr, _) => self.walk_expr(subexpr), + hir::ExprKind::Type(subexpr, _) => self.walk_expr(subexpr), - hir::ExprKind::Unary(hir::UnOp::Deref, ref base) => { + hir::ExprKind::Unary(hir::UnOp::Deref, base) => { // *base self.select_from_expr(base); } - hir::ExprKind::Field(ref base, _) => { + hir::ExprKind::Field(base, _) => { // base.f self.select_from_expr(base); } - hir::ExprKind::Index(ref lhs, ref rhs) => { + hir::ExprKind::Index(lhs, rhs) => { // lhs[rhs] self.select_from_expr(lhs); self.consume_expr(rhs); } - hir::ExprKind::Call(ref callee, ref args) => { + hir::ExprKind::Call(callee, args) => { // callee(args) self.consume_expr(callee); self.consume_exprs(args); } - hir::ExprKind::MethodCall(.., ref args, _) => { + hir::ExprKind::MethodCall(.., args, _) => { // callee.m(args) self.consume_exprs(args); } - hir::ExprKind::Struct(_, ref fields, ref opt_with) => { + hir::ExprKind::Struct(_, fields, ref opt_with) => { self.walk_struct_expr(fields, opt_with); } - hir::ExprKind::Tup(ref exprs) => { + hir::ExprKind::Tup(exprs) => { self.consume_exprs(exprs); } hir::ExprKind::If(ref cond_expr, ref then_expr, ref opt_else_expr) => { - self.consume_expr(&cond_expr); - self.consume_expr(&then_expr); + self.consume_expr(cond_expr); + self.consume_expr(then_expr); if let Some(ref else_expr) = *opt_else_expr { - self.consume_expr(&else_expr); + self.consume_expr(else_expr); } } - hir::ExprKind::Let(ref pat, ref expr, _) => { - self.walk_local(expr, pat, |t| t.borrow_expr(&expr, ty::ImmBorrow)); + hir::ExprKind::Let(pat, ref expr, _) => { + self.walk_local(expr, pat, |t| t.borrow_expr(expr, ty::ImmBorrow)); } hir::ExprKind::Match(ref discr, arms, _) => { - let discr_place = return_if_err!(self.mc.cat_expr(&discr)); + let discr_place = return_if_err!(self.mc.cat_expr(discr)); // Matching should not always be considered a use of the place, hence // discr does not necessarily need to be borrowed. @@ -243,7 +243,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { let ExprUseVisitor { ref mc, body_owner: _, delegate: _ } = *self; let mut needs_to_be_read = false; for arm in arms.iter() { - return_if_err!(mc.cat_pattern(discr_place.clone(), &arm.pat, |place, pat| { + return_if_err!(mc.cat_pattern(discr_place.clone(), arm.pat, |place, pat| { match &pat.kind { PatKind::Binding(.., opt_sub_pat) => { // If the opt_sub_pat is None, than the binding does not count as @@ -303,7 +303,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { } if needs_to_be_read { - self.borrow_expr(&discr, ty::ImmBorrow); + self.borrow_expr(discr, ty::ImmBorrow); } else { let closure_def_id = match discr_place.place.base { PlaceBase::Upvar(upvar_id) => Some(upvar_id.closure_expr_id.to_def_id()), @@ -318,7 +318,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { // We always want to walk the discriminant. We want to make sure, for instance, // that the discriminant has been initialized. - self.walk_expr(&discr); + self.walk_expr(discr); } // treatment of the discriminant is handled while walking the arms. @@ -327,7 +327,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { } } - hir::ExprKind::Array(ref exprs) => { + hir::ExprKind::Array(exprs) => { self.consume_exprs(exprs); } @@ -336,10 +336,10 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { // make sure that the thing we are pointing out stays valid // for the lifetime `scope_r` of the resulting ptr: let bk = ty::BorrowKind::from_mutbl(m); - self.borrow_expr(&base, bk); + self.borrow_expr(base, bk); } - hir::ExprKind::InlineAsm(ref asm) => { + hir::ExprKind::InlineAsm(asm) => { for (op, _op_sp) in asm.operands { match op { hir::InlineAsmOperand::In { expr, .. } @@ -360,7 +360,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { } } - hir::ExprKind::LlvmInlineAsm(ref ia) => { + hir::ExprKind::LlvmInlineAsm(ia) => { for (o, output) in iter::zip(&ia.inner.outputs, ia.outputs_exprs) { if o.is_indirect { self.consume_expr(output); @@ -368,7 +368,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { self.mutate_expr(output); } } - self.consume_exprs(&ia.inputs_exprs); + self.consume_exprs(ia.inputs_exprs); } hir::ExprKind::Continue(..) @@ -376,43 +376,43 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { | hir::ExprKind::ConstBlock(..) | hir::ExprKind::Err => {} - hir::ExprKind::Loop(ref blk, ..) => { + hir::ExprKind::Loop(blk, ..) => { self.walk_block(blk); } - hir::ExprKind::Unary(_, ref lhs) => { + hir::ExprKind::Unary(_, lhs) => { self.consume_expr(lhs); } - hir::ExprKind::Binary(_, ref lhs, ref rhs) => { + hir::ExprKind::Binary(_, lhs, rhs) => { self.consume_expr(lhs); self.consume_expr(rhs); } - hir::ExprKind::Block(ref blk, _) => { + hir::ExprKind::Block(blk, _) => { self.walk_block(blk); } hir::ExprKind::Break(_, ref opt_expr) | hir::ExprKind::Ret(ref opt_expr) => { - if let Some(ref expr) = *opt_expr { + if let Some(expr) = *opt_expr { self.consume_expr(expr); } } - hir::ExprKind::Assign(ref lhs, ref rhs, _) => { + hir::ExprKind::Assign(lhs, rhs, _) => { self.mutate_expr(lhs); self.consume_expr(rhs); } - hir::ExprKind::Cast(ref base, _) => { + hir::ExprKind::Cast(base, _) => { self.consume_expr(base); } - hir::ExprKind::DropTemps(ref expr) => { + hir::ExprKind::DropTemps(expr) => { self.consume_expr(expr); } - hir::ExprKind::AssignOp(_, ref lhs, ref rhs) => { + hir::ExprKind::AssignOp(_, lhs, rhs) => { if self.mc.typeck_results.is_method_call(expr) { self.consume_expr(lhs); } else { @@ -421,7 +421,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { self.consume_expr(rhs); } - hir::ExprKind::Repeat(ref base, _) => { + hir::ExprKind::Repeat(base, _) => { self.consume_expr(base); } @@ -433,7 +433,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { self.consume_expr(base); } - hir::ExprKind::Yield(ref value, _) => { + hir::ExprKind::Yield(value, _) => { self.consume_expr(value); } } @@ -441,7 +441,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { fn walk_stmt(&mut self, stmt: &hir::Stmt<'_>) { match stmt.kind { - hir::StmtKind::Local(hir::Local { pat, init: Some(ref expr), .. }) => { + hir::StmtKind::Local(hir::Local { pat, init: Some(expr), .. }) => { self.walk_local(expr, pat, |_| {}); } @@ -453,7 +453,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { } hir::StmtKind::Expr(ref expr) | hir::StmtKind::Semi(ref expr) => { - self.consume_expr(&expr); + self.consume_expr(expr); } } } @@ -462,8 +462,8 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { where F: FnMut(&mut Self), { - self.walk_expr(&expr); - let expr_place = return_if_err!(self.mc.cat_expr(&expr)); + self.walk_expr(expr); + let expr_place = return_if_err!(self.mc.cat_expr(expr)); f(self); self.walk_irrefutable_pat(&expr_place, &pat); } @@ -478,7 +478,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { } if let Some(ref tail_expr) = blk.expr { - self.consume_expr(&tail_expr); + self.consume_expr(tail_expr); } } @@ -489,17 +489,17 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { ) { // Consume the expressions supplying values for each field. for field in fields { - self.consume_expr(&field.expr); + self.consume_expr(field.expr); } let with_expr = match *opt_with { - Some(ref w) => &**w, + Some(w) => &*w, None => { return; } }; - let with_place = return_if_err!(self.mc.cat_expr(&with_expr)); + let with_place = return_if_err!(self.mc.cat_expr(with_expr)); // Select just those fields of the `with` // expression that will actually be used @@ -569,7 +569,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { } } place_with_id = - return_if_err!(self.mc.cat_expr_adjusted(expr, place_with_id, &adjustment)); + return_if_err!(self.mc.cat_expr_adjusted(expr, place_with_id, adjustment)); } } @@ -615,15 +615,15 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { FakeReadCause::ForMatchedPlace(closure_def_id), discr_place.hir_id, ); - self.walk_pat(discr_place, &arm.pat); + self.walk_pat(discr_place, arm.pat); - if let Some(hir::Guard::If(ref e)) = arm.guard { + if let Some(hir::Guard::If(e)) = arm.guard { self.consume_expr(e) } else if let Some(hir::Guard::IfLet(_, ref e)) = arm.guard { self.consume_expr(e) } - self.consume_expr(&arm.body); + self.consume_expr(arm.body); } /// Walks a pat that occurs in isolation (i.e., top-level of fn argument or @@ -836,7 +836,7 @@ fn delegate_consume<'a, 'tcx>( ) { debug!("delegate_consume(place_with_id={:?})", place_with_id); - let mode = copy_or_move(&mc, place_with_id); + let mode = copy_or_move(mc, place_with_id); match mode { ConsumeMode::Move => delegate.consume(place_with_id, diag_expr_id), diff --git a/compiler/rustc_typeck/src/hir_wf_check.rs b/compiler/rustc_typeck/src/hir_wf_check.rs index b7ede0e4bf..39bcf89993 100644 --- a/compiler/rustc_typeck/src/hir_wf_check.rs +++ b/compiler/rustc_typeck/src/hir_wf_check.rs @@ -83,7 +83,8 @@ fn diagnostic_hir_wf_check<'tcx>( traits::Obligation::new( cause, self.param_env, - ty::PredicateKind::WellFormed(tcx_ty.into()).to_predicate(self.tcx), + ty::Binder::dummy(ty::PredicateKind::WellFormed(tcx_ty.into())) + .to_predicate(self.tcx), ), ); diff --git a/compiler/rustc_typeck/src/impl_wf_check.rs b/compiler/rustc_typeck/src/impl_wf_check.rs index 194c4efdbb..5d2f8fc424 100644 --- a/compiler/rustc_typeck/src/impl_wf_check.rs +++ b/compiler/rustc_typeck/src/impl_wf_check.rs @@ -58,9 +58,7 @@ pub fn impl_wf_check(tcx: TyCtxt<'_>) { // We will tag this as part of the WF check -- logically, it is, // but it's one that we must perform earlier than the rest of // WfCheck. - for &module in tcx.hir().krate().modules.keys() { - tcx.ensure().check_mod_impl_wf(module); - } + tcx.hir().for_each_module(|module| tcx.ensure().check_mod_impl_wf(module)) } fn check_mod_impl_wf(tcx: TyCtxt<'_>, module_def_id: LocalDefId) { @@ -99,7 +97,7 @@ impl ItemLikeVisitor<'tcx> for ImplWfCheck<'tcx> { fn enforce_impl_params_are_constrained( tcx: TyCtxt<'_>, impl_def_id: LocalDefId, - impl_item_refs: &[hir::ImplItemRef<'_>], + impl_item_refs: &[hir::ImplItemRef], ) { // Every lifetime used in an associated type must be constrained. let impl_self_ty = tcx.type_of(impl_def_id); @@ -230,7 +228,7 @@ fn report_unused_parameter(tcx: TyCtxt<'_>, span: Span, kind: &str, name: &str) } /// Enforce that we do not have two items in an impl with the same name. -fn enforce_impl_items_are_distinct(tcx: TyCtxt<'_>, impl_item_refs: &[hir::ImplItemRef<'_>]) { +fn enforce_impl_items_are_distinct(tcx: TyCtxt<'_>, impl_item_refs: &[hir::ImplItemRef]) { let mut seen_type_items = FxHashMap::default(); let mut seen_value_items = FxHashMap::default(); for impl_item_ref in impl_item_refs { 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 8ecd6034ad..f4bb5761c1 100644 --- a/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs +++ b/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs @@ -74,7 +74,7 @@ use rustc_infer::infer::{InferCtxt, RegionckMode, TyCtxtInferExt}; use rustc_infer::traits::specialization_graph::Node; use rustc_middle::ty::subst::{GenericArg, InternalSubsts, SubstsRef}; use rustc_middle::ty::trait_def::TraitSpecializationKind; -use rustc_middle::ty::{self, InstantiatedPredicates, TyCtxt, TypeFoldable}; +use rustc_middle::ty::{self, TyCtxt, TypeFoldable}; use rustc_span::Span; use rustc_trait_selection::traits::{self, translate_substs, wf}; @@ -294,13 +294,27 @@ fn check_predicates<'tcx>( span: Span, ) { let tcx = infcx.tcx; - let impl1_predicates = tcx.predicates_of(impl1_def_id).instantiate(tcx, impl1_substs); + let impl1_predicates: Vec<_> = traits::elaborate_predicates( + tcx, + tcx.predicates_of(impl1_def_id).instantiate(tcx, impl1_substs).predicates.into_iter(), + ) + .map(|obligation| obligation.predicate) + .collect(); + let mut impl2_predicates = if impl2_node.is_from_trait() { // Always applicable traits have to be always applicable without any // assumptions. - InstantiatedPredicates::empty() + Vec::new() } else { - tcx.predicates_of(impl2_node.def_id()).instantiate(tcx, impl2_substs) + traits::elaborate_predicates( + tcx, + tcx.predicates_of(impl2_node.def_id()) + .instantiate(tcx, impl2_substs) + .predicates + .into_iter(), + ) + .map(|obligation| obligation.predicate) + .collect() }; debug!( "check_always_applicable(\nimpl1_predicates={:?},\nimpl2_predicates={:?}\n)", @@ -322,13 +336,12 @@ fn check_predicates<'tcx>( // which is sound because we forbid impls like the following // // impl AlwaysApplicable for D { } - let always_applicable_traits = - impl1_predicates.predicates.iter().copied().filter(|&predicate| { - matches!( - trait_predicate_kind(tcx, predicate), - Some(TraitSpecializationKind::AlwaysApplicable) - ) - }); + let always_applicable_traits = impl1_predicates.iter().copied().filter(|&predicate| { + matches!( + trait_predicate_kind(tcx, predicate), + Some(TraitSpecializationKind::AlwaysApplicable) + ) + }); // Include the well-formed predicates of the type parameters of the impl. for arg in tcx.impl_trait_ref(impl1_def_id).unwrap().substs { @@ -340,18 +353,19 @@ fn check_predicates<'tcx>( arg, span, ) { - impl2_predicates - .predicates - .extend(obligations.into_iter().map(|obligation| obligation.predicate)) + impl2_predicates.extend( + traits::elaborate_obligations(tcx, obligations) + .map(|obligation| obligation.predicate), + ) } } - impl2_predicates.predicates.extend( + impl2_predicates.extend( traits::elaborate_predicates(tcx, always_applicable_traits) .map(|obligation| obligation.predicate), ); - for predicate in impl1_predicates.predicates { - if !impl2_predicates.predicates.contains(&predicate) { + for predicate in impl1_predicates { + if !impl2_predicates.contains(&predicate) { check_specialization_on(tcx, predicate, span) } } diff --git a/compiler/rustc_typeck/src/lib.rs b/compiler/rustc_typeck/src/lib.rs index 749f681e92..971776c882 100644 --- a/compiler/rustc_typeck/src/lib.rs +++ b/compiler/rustc_typeck/src/lib.rs @@ -56,7 +56,6 @@ This API is completely unstable and subject to change. */ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] -#![cfg_attr(bootstrap, feature(bindings_after_at))] #![feature(bool_to_option)] #![feature(crate_visibility_modifier)] #![feature(format_args_capture)] @@ -64,12 +63,12 @@ This API is completely unstable and subject to change. #![feature(in_band_lifetimes)] #![feature(is_sorted)] #![feature(iter_zip)] +#![feature(min_specialization)] #![feature(nll)] #![feature(try_blocks)] #![feature(never_type)] #![feature(slice_partition_dedup)] #![feature(control_flow_enum)] -#![cfg_attr(bootstrap, allow(incomplete_features))] // if_let_guard #![recursion_limit = "256"] #[macro_use] @@ -109,6 +108,7 @@ use rustc_middle::util; use rustc_session::config::EntryFnType; use rustc_span::{symbol::sym, Span, DUMMY_SP}; use rustc_target::spec::abi::Abi; +use rustc_trait_selection::infer::InferCtxtExt; use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _; use rustc_trait_selection::traits::{ self, ObligationCause, ObligationCauseCode, TraitEngine, TraitEngineExt as _, @@ -145,7 +145,7 @@ fn require_same_types<'tcx>( tcx.infer_ctxt().enter(|ref infcx| { let param_env = ty::ParamEnv::empty(); let mut fulfill_cx = >::new(infcx.tcx); - match infcx.at(&cause, param_env).eq(expected, actual) { + match infcx.at(cause, param_env).eq(expected, actual) { Ok(InferOk { obligations, .. }) => { fulfill_cx.register_predicate_obligations(infcx, obligations); } @@ -189,9 +189,11 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) { let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); match tcx.hir().find(hir_id) { Some(Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, ref generics, _), .. })) => { - let generics_param_span = - if !generics.params.is_empty() { Some(generics.span) } else { None }; - generics_param_span + if !generics.params.is_empty() { + Some(generics.span) + } else { + None + } } _ => { span_bug!(tcx.def_span(def_id), "main has a non-function type"); @@ -328,7 +330,26 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) { ObligationCauseCode::MainFunctionType, ); let mut fulfillment_cx = traits::FulfillmentContext::new(); - fulfillment_cx.register_bound(&infcx, ty::ParamEnv::empty(), return_ty, term_id, cause); + // normalize any potential projections in the return type, then add + // any possible obligations to the fulfillment context. + // HACK(ThePuzzlemaker) this feels symptomatic of a problem within + // checking trait fulfillment, not this here. I'm not sure why it + // works in the example in `fn test()` given in #88609? This also + // probably isn't the best way to do this. + let InferOk { value: norm_return_ty, obligations } = infcx + .partially_normalize_associated_types_in( + cause.clone(), + ty::ParamEnv::empty(), + return_ty, + ); + fulfillment_cx.register_predicate_obligations(&infcx, obligations); + fulfillment_cx.register_bound( + &infcx, + ty::ParamEnv::empty(), + norm_return_ty, + term_id, + cause, + ); if let Err(err) = fulfillment_cx.select_all_or_error(&infcx) { infcx.report_fulfillment_errors(&err, None, false); error = true; @@ -475,9 +496,7 @@ pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorReported> { // FIXME(matthewjasper) We shouldn't need to use `track_errors`. tcx.sess.track_errors(|| { tcx.sess.time("type_collecting", || { - for &module in tcx.hir().krate().modules.keys() { - tcx.ensure().collect_mod_item_types(module); - } + tcx.hir().for_each_module(|module| tcx.ensure().collect_mod_item_types(module)) }); })?; @@ -507,9 +526,7 @@ pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorReported> { // NOTE: This is copy/pasted in librustdoc/core.rs and should be kept in sync. tcx.sess.time("item_types_checking", || { - for &module in tcx.hir().krate().modules.keys() { - tcx.ensure().check_mod_item_types(module); - } + tcx.hir().for_each_module(|module| tcx.ensure().check_mod_item_types(module)) }); tcx.sess.time("item_bodies_checking", || tcx.typeck_item_bodies(())); diff --git a/compiler/rustc_typeck/src/mem_categorization.rs b/compiler/rustc_typeck/src/mem_categorization.rs index f876d0f251..440ce04e61 100644 --- a/compiler/rustc_typeck/src/mem_categorization.rs +++ b/compiler/rustc_typeck/src/mem_categorization.rs @@ -307,13 +307,13 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { if self.typeck_results.is_method_call(expr) { self.cat_overloaded_place(expr, e_base) } else { - let base = self.cat_expr(&e_base)?; + let base = self.cat_expr(e_base)?; self.cat_deref(expr, base) } } hir::ExprKind::Field(ref base, _) => { - let base = self.cat_expr(&base)?; + let base = self.cat_expr(base)?; debug!("cat_expr(cat_field): id={} expr={:?} base={:?}", expr.hir_id, expr, base); let field_idx = self @@ -340,7 +340,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { // dereferencing. self.cat_overloaded_place(expr, base) } else { - let base = self.cat_expr(&base)?; + let base = self.cat_expr(base)?; Ok(self.cat_projection(expr, base, expr_ty, ProjectionKind::Index)) } } @@ -350,7 +350,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { self.cat_res(expr.hir_id, expr.span, expr_ty, res) } - hir::ExprKind::Type(ref e, _) => self.cat_expr(&e), + hir::ExprKind::Type(ref e, _) => self.cat_expr(e), hir::ExprKind::AddrOf(..) | hir::ExprKind::Call(..) @@ -674,31 +674,31 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { op(&place_with_id, pat); match pat.kind { - PatKind::Tuple(ref subpats, dots_pos) => { + PatKind::Tuple(subpats, dots_pos) => { // (p1, ..., pN) let total_fields = self.total_fields_in_tuple(pat.hir_id, pat.span)?; for (i, subpat) in subpats.iter().enumerate_and_adjust(total_fields, dots_pos) { - let subpat_ty = self.pat_ty_adjusted(&subpat)?; + let subpat_ty = self.pat_ty_adjusted(subpat)?; let projection_kind = ProjectionKind::Field(i as u32, VariantIdx::new(0)); let sub_place = self.cat_projection(pat, place_with_id.clone(), subpat_ty, projection_kind); - self.cat_pattern_(sub_place, &subpat, op)?; + self.cat_pattern_(sub_place, subpat, op)?; } } - PatKind::TupleStruct(ref qpath, ref subpats, dots_pos) => { + PatKind::TupleStruct(ref qpath, subpats, dots_pos) => { // S(p1, ..., pN) let variant_index = self.variant_index_for_adt(qpath, pat.hir_id, pat.span)?; let total_fields = self.total_fields_in_adt_variant(pat.hir_id, variant_index, pat.span)?; for (i, subpat) in subpats.iter().enumerate_and_adjust(total_fields, dots_pos) { - let subpat_ty = self.pat_ty_adjusted(&subpat)?; + let subpat_ty = self.pat_ty_adjusted(subpat)?; let projection_kind = ProjectionKind::Field(i as u32, variant_index); let sub_place = self.cat_projection(pat, place_with_id.clone(), subpat_ty, projection_kind); - self.cat_pattern_(sub_place, &subpat, op)?; + self.cat_pattern_(sub_place, subpat, op)?; } } @@ -708,7 +708,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { let variant_index = self.variant_index_for_adt(qpath, pat.hir_id, pat.span)?; for fp in field_pats { - let field_ty = self.pat_ty_adjusted(&fp.pat)?; + let field_ty = self.pat_ty_adjusted(fp.pat)?; let field_index = self .typeck_results .field_indices() @@ -722,18 +722,18 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { field_ty, ProjectionKind::Field(field_index as u32, variant_index), ); - self.cat_pattern_(field_place, &fp.pat, op)?; + self.cat_pattern_(field_place, fp.pat, op)?; } } PatKind::Or(pats) => { for pat in pats { - self.cat_pattern_(place_with_id.clone(), &pat, op)?; + self.cat_pattern_(place_with_id.clone(), pat, op)?; } } PatKind::Binding(.., Some(ref subpat)) => { - self.cat_pattern_(place_with_id, &subpat, op)?; + self.cat_pattern_(place_with_id, subpat, op)?; } PatKind::Box(ref subpat) | PatKind::Ref(ref subpat, _) => { @@ -741,7 +741,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { // PatKind::Ref since that information is already contained // in the type. let subplace = self.cat_deref(pat, place_with_id)?; - self.cat_pattern_(subplace, &subpat, op)?; + self.cat_pattern_(subplace, subpat, op)?; } PatKind::Slice(before, ref slice, after) => { @@ -759,20 +759,20 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { ProjectionKind::Index, ); for before_pat in before { - self.cat_pattern_(elt_place.clone(), &before_pat, op)?; + self.cat_pattern_(elt_place.clone(), before_pat, op)?; } if let Some(ref slice_pat) = *slice { - let slice_pat_ty = self.pat_ty_adjusted(&slice_pat)?; + let slice_pat_ty = self.pat_ty_adjusted(slice_pat)?; let slice_place = self.cat_projection( pat, place_with_id, slice_pat_ty, ProjectionKind::Subslice, ); - self.cat_pattern_(slice_place, &slice_pat, op)?; + self.cat_pattern_(slice_place, slice_pat, op)?; } for after_pat in after { - self.cat_pattern_(elt_place.clone(), &after_pat, op)?; + self.cat_pattern_(elt_place.clone(), after_pat, op)?; } } diff --git a/compiler/rustc_typeck/src/outlives/explicit.rs b/compiler/rustc_typeck/src/outlives/explicit.rs index 2ac1a18cff..bbf31de527 100644 --- a/compiler/rustc_typeck/src/outlives/explicit.rs +++ b/compiler/rustc_typeck/src/outlives/explicit.rs @@ -30,20 +30,20 @@ impl<'tcx> ExplicitPredicatesMap<'tcx> { // process predicates and convert to `RequiredPredicates` entry, see below for &(predicate, span) in predicates.predicates { match predicate.kind().skip_binder() { - ty::PredicateKind::TypeOutlives(OutlivesPredicate(ref ty, ref reg)) => { + ty::PredicateKind::TypeOutlives(OutlivesPredicate(ty, reg)) => { insert_outlives_predicate( tcx, - (*ty).into(), + ty.into(), reg, span, &mut required_predicates, ) } - ty::PredicateKind::RegionOutlives(OutlivesPredicate(ref reg1, ref reg2)) => { + ty::PredicateKind::RegionOutlives(OutlivesPredicate(reg1, reg2)) => { insert_outlives_predicate( tcx, - (*reg1).into(), + reg1.into(), reg2, span, &mut required_predicates, diff --git a/compiler/rustc_typeck/src/outlives/implicit_infer.rs b/compiler/rustc_typeck/src/outlives/implicit_infer.rs index 0e96601d89..86d712e2d7 100644 --- a/compiler/rustc_typeck/src/outlives/implicit_infer.rs +++ b/compiler/rustc_typeck/src/outlives/implicit_infer.rs @@ -37,7 +37,7 @@ pub fn infer_predicates<'tcx>( }; // Visit all the crates and infer predicates - tcx.hir().krate().visit_all_item_likes(&mut visitor); + tcx.hir().visit_all_item_likes(&mut visitor); } global_inferred_outlives diff --git a/compiler/rustc_typeck/src/outlives/mod.rs b/compiler/rustc_typeck/src/outlives/mod.rs index 70a2ba7fcd..eb3853b6b3 100644 --- a/compiler/rustc_typeck/src/outlives/mod.rs +++ b/compiler/rustc_typeck/src/outlives/mod.rs @@ -9,6 +9,7 @@ use rustc_span::Span; mod explicit; mod implicit_infer; +crate mod outlives_bounds; /// Code to write unit test for outlives. pub mod test; mod utils; @@ -22,7 +23,7 @@ fn inferred_outlives_of(tcx: TyCtxt<'_>, item_def_id: DefId) -> &[(ty::Predicate if matches!(tcx.def_kind(item_def_id), hir::def::DefKind::AnonConst) && tcx.lazy_normalization() { - if let Some(_) = tcx.hir().opt_const_param_default_param_hir_id(id) { + if tcx.hir().opt_const_param_default_param_hir_id(id).is_some() { // In `generics_of` we set the generics' parent to be our parent's parent which means that // we lose out on the predicates of our actual parent if we dont return those predicates here. // (See comment in `generics_of` for more information on why the parent shenanigans is necessary) @@ -104,13 +105,15 @@ fn inferred_outlives_crate(tcx: TyCtxt<'_>, (): ()) -> CratePredicatesMap<'_> { |(ty::OutlivesPredicate(kind1, region2), &span)| { match kind1.unpack() { GenericArgKind::Type(ty1) => Some(( - ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(ty1, region2)) - .to_predicate(tcx), + ty::Binder::dummy(ty::PredicateKind::TypeOutlives( + ty::OutlivesPredicate(ty1, region2), + )) + .to_predicate(tcx), span, )), GenericArgKind::Lifetime(region1) => Some(( - ty::PredicateKind::RegionOutlives(ty::OutlivesPredicate( - region1, region2, + ty::Binder::dummy(ty::PredicateKind::RegionOutlives( + ty::OutlivesPredicate(region1, region2), )) .to_predicate(tcx), span, diff --git a/compiler/rustc_trait_selection/src/traits/query/outlives_bounds.rs b/compiler/rustc_typeck/src/outlives/outlives_bounds.rs similarity index 93% rename from compiler/rustc_trait_selection/src/traits/query/outlives_bounds.rs rename to compiler/rustc_typeck/src/outlives/outlives_bounds.rs index f5fa52c915..4ab5fe26ab 100644 --- a/compiler/rustc_trait_selection/src/traits/query/outlives_bounds.rs +++ b/compiler/rustc_typeck/src/outlives/outlives_bounds.rs @@ -1,11 +1,11 @@ -use crate::infer::canonical::OriginalQueryValues; -use crate::infer::InferCtxt; -use crate::traits::query::NoSolution; -use crate::traits::{FulfillmentContext, ObligationCause, TraitEngine}; use rustc_hir as hir; use rustc_infer::traits::TraitEngineExt as _; use rustc_middle::ty::{self, Ty}; use rustc_span::source_map::Span; +use rustc_trait_selection::infer::canonical::OriginalQueryValues; +use rustc_trait_selection::infer::InferCtxt; +use rustc_trait_selection::traits::query::NoSolution; +use rustc_trait_selection::traits::{FulfillmentContext, ObligationCause, TraitEngine}; pub use rustc_middle::traits::query::OutlivesBound; diff --git a/compiler/rustc_typeck/src/outlives/test.rs b/compiler/rustc_typeck/src/outlives/test.rs index d4bef0c409..ec4fa9cd4b 100644 --- a/compiler/rustc_typeck/src/outlives/test.rs +++ b/compiler/rustc_typeck/src/outlives/test.rs @@ -5,7 +5,7 @@ use rustc_middle::ty::TyCtxt; use rustc_span::symbol::sym; pub fn test_inferred_outlives(tcx: TyCtxt<'_>) { - tcx.hir().krate().visit_all_item_likes(&mut OutlivesTest { tcx }); + tcx.hir().visit_all_item_likes(&mut OutlivesTest { tcx }); } struct OutlivesTest<'tcx> { diff --git a/compiler/rustc_typeck/src/outlives/utils.rs b/compiler/rustc_typeck/src/outlives/utils.rs index 8b06967879..76ae2ee435 100644 --- a/compiler/rustc_typeck/src/outlives/utils.rs +++ b/compiler/rustc_typeck/src/outlives/utils.rs @@ -1,4 +1,4 @@ -use rustc_middle::ty::outlives::Component; +use rustc_infer::infer::outlives::components::{push_outlives_components, Component}; use rustc_middle::ty::subst::{GenericArg, GenericArgKind}; use rustc_middle::ty::{self, Region, RegionKind, Ty, TyCtxt}; use rustc_span::Span; @@ -35,7 +35,7 @@ pub fn insert_outlives_predicate<'tcx>( // Or if within `struct Foo` you had `T = Vec`, then // we would want to add `U: 'outlived_region` let mut components = smallvec![]; - tcx.push_outlives_components(ty, &mut components); + push_outlives_components(tcx, ty, &mut components); for component in components { match component { Component::Region(r) => { 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 bccc19774e..8d3862ffc8 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 @@ -1,6 +1,7 @@ use crate::structured_errors::StructuredDiagnostic; use rustc_errors::{pluralize, Applicability, DiagnosticBuilder, DiagnosticId}; use rustc_hir as hir; +use rustc_middle::hir::map::fn_sig; use rustc_middle::middle::resolve_lifetime::LifetimeScopeForPath; use rustc_middle::ty::{self as ty, TyCtxt}; use rustc_session::Session; @@ -136,10 +137,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> { AngleBrackets::Missing => 0, // Only lifetime arguments can be implied AngleBrackets::Implied => self.gen_args.args.len(), - AngleBrackets::Available => self.gen_args.args.iter().fold(0, |acc, arg| match arg { - hir::GenericArg::Lifetime(_) => acc + 1, - _ => acc, - }), + AngleBrackets::Available => self.gen_args.num_lifetime_params(), } } @@ -148,10 +146,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> { AngleBrackets::Missing => 0, // Only lifetime arguments can be implied AngleBrackets::Implied => 0, - AngleBrackets::Available => self.gen_args.args.iter().fold(0, |acc, arg| match arg { - hir::GenericArg::Type(_) | hir::GenericArg::Const(_) => acc + 1, - _ => acc, - }), + AngleBrackets::Available => self.gen_args.num_generic_params(), } } @@ -298,12 +293,30 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> { &self, num_params_to_take: usize, ) -> String { + let fn_sig = self.tcx.hir().get_if_local(self.def_id).and_then(fn_sig); + let is_used_in_input = |def_id| { + fn_sig.map_or(false, |fn_sig| { + fn_sig.decl.inputs.iter().any(|ty| match ty.kind { + hir::TyKind::Path(hir::QPath::Resolved( + None, + hir::Path { res: hir::def::Res::Def(_, id), .. }, + )) if *id == def_id => true, + _ => false, + }) + }) + }; self.gen_params .params .iter() .skip(self.params_offset + self.num_provided_type_or_const_args()) .take(num_params_to_take) - .map(|param| param.name.to_string()) + .map(|param| match param.kind { + // This is being infered from the item's inputs, no need to set it. + ty::GenericParamDefKind::Type { .. } if is_used_in_input(param.def_id) => { + "_".to_string() + } + _ => param.name.to_string(), + }) .collect::>() .join(", ") } @@ -651,7 +664,9 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> { let mut found_redundant = false; for arg in self.gen_args.args { match arg { - hir::GenericArg::Type(_) | hir::GenericArg::Const(_) => { + hir::GenericArg::Type(_) + | hir::GenericArg::Const(_) + | hir::GenericArg::Infer(_) => { gen_arg_spans.push(arg.span()); if gen_arg_spans.len() > self.num_expected_type_or_const_args() { found_redundant = true; @@ -716,7 +731,11 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> { /// Builds the `type defined here` message. fn show_definition(&self, err: &mut DiagnosticBuilder<'_>) { let mut spans: MultiSpan = if let Some(def_span) = self.tcx.def_ident_span(self.def_id) { - def_span.into() + if self.tcx.sess.source_map().span_to_snippet(def_span).is_ok() { + def_span.into() + } else { + return; + } } else { return; }; diff --git a/compiler/rustc_typeck/src/variance/constraints.rs b/compiler/rustc_typeck/src/variance/constraints.rs index f5355ea042..1c8ac10818 100644 --- a/compiler/rustc_typeck/src/variance/constraints.rs +++ b/compiler/rustc_typeck/src/variance/constraints.rs @@ -62,7 +62,7 @@ pub fn add_constraints_from_crate<'a, 'tcx>( constraints: Vec::new(), }; - tcx.hir().krate().visit_all_item_likes(&mut constraint_cx); + tcx.hir().visit_all_item_likes(&mut constraint_cx); constraint_cx } @@ -293,7 +293,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { self.add_constraints_from_invariant_substs(current, substs, variance); } - ty::Dynamic(ref data, r) => { + ty::Dynamic(data, r) => { // The type `Foo` is contravariant w/r/t `'a`: let contra = self.contravariant(variance); self.add_constraints_from_region(current, r, contra); diff --git a/compiler/rustc_typeck/src/variance/terms.rs b/compiler/rustc_typeck/src/variance/terms.rs index 5d5baf78d3..d7f9df668b 100644 --- a/compiler/rustc_typeck/src/variance/terms.rs +++ b/compiler/rustc_typeck/src/variance/terms.rs @@ -79,7 +79,7 @@ pub fn determine_parameters_to_be_inferred<'a, 'tcx>( // // - https://rustc-dev-guide.rust-lang.org/query.html // - https://rustc-dev-guide.rust-lang.org/variance.html - tcx.hir().krate().visit_all_item_likes(&mut terms_cx); + tcx.hir().visit_all_item_likes(&mut terms_cx); terms_cx } diff --git a/compiler/rustc_typeck/src/variance/test.rs b/compiler/rustc_typeck/src/variance/test.rs index 2a0d950c87..7be3c68e8f 100644 --- a/compiler/rustc_typeck/src/variance/test.rs +++ b/compiler/rustc_typeck/src/variance/test.rs @@ -5,7 +5,7 @@ use rustc_middle::ty::TyCtxt; use rustc_span::symbol::sym; pub fn test_variance(tcx: TyCtxt<'_>) { - tcx.hir().krate().visit_all_item_likes(&mut VarianceTest { tcx }); + tcx.hir().visit_all_item_likes(&mut VarianceTest { tcx }); } struct VarianceTest<'tcx> { diff --git a/config.toml.example b/config.toml.example index c2d51c140b..61e57eee78 100644 --- a/config.toml.example +++ b/config.toml.example @@ -103,7 +103,7 @@ changelog-seen = 2 # the same format as above, but since these targets are experimental, they are # not built by default and the experimental Rust compilation targets that depend # on them will not work unless the user opts in to building them. -#experimental-targets = "AVR" +#experimental-targets = "AVR;M68k" # Cap the number of parallel linker invocations when compiling LLVM. # This can be useful when building LLVM with debug info, which significantly @@ -202,15 +202,15 @@ changelog-seen = 2 # You can use "$ROOT" to indicate the root of the git repository. #build-dir = "build" -# Instead of downloading the src/stage0.txt version of Cargo specified, use +# Instead of downloading the src/stage0.json version of Cargo specified, use # this Cargo binary instead to build all Rust code #cargo = "/path/to/cargo" -# Instead of downloading the src/stage0.txt version of the compiler +# Instead of downloading the src/stage0.json version of the compiler # specified, use this rustc binary instead as the stage0 snapshot compiler. #rustc = "/path/to/rustc" -# Instead of download the src/stage0.txt version of rustfmt specified, +# Instead of download the src/stage0.json version of rustfmt specified, # use this rustfmt binary instead as the stage0 snapshot rustfmt. #rustfmt = "/path/to/rustfmt" @@ -313,6 +313,12 @@ changelog-seen = 2 # this setting's very existence, are all subject to change.) #print-step-rusage = false +# Always patch binaries for usage with Nix toolchains. If `true` then binaries +# will be patched unconditionally. If `false` or unset, binaries will be patched +# only if the current distribution is NixOS. This option is useful when using +# a Nix toolchain on non-NixOS distributions. +#patch-binaries-for-nix = false + # ============================================================================= # General install configuration options # ============================================================================= @@ -417,6 +423,18 @@ changelog-seen = 2 # set this value to `true`. #debug-logging = rust.debug-assertions (boolean) +# Whether or not overflow checks are enabled for the compiler and standard +# library. +# +# Defaults to rust.debug value +#overflow-checks = rust.debug (boolean) + +# Whether or not overflow checks are enabled for the standard library. +# Overrides the `overflow-checks` option, if defined. +# +# Defaults to rust.overflow-checks value +#overflow-checks-std = rust.overflow-checks (boolean) + # Debuginfo level for most of Rust code, corresponds to the `-C debuginfo=N` option of `rustc`. # `0` - no debug info # `1` - line tables only - sufficient to generate backtraces that include line diff --git a/git-commit-hash b/git-commit-hash index 8e28fd5005..5a7b097227 100644 --- a/git-commit-hash +++ b/git-commit-hash @@ -1 +1 @@ -09c42c45858d5f3aedfa670698275303a3d19afa \ No newline at end of file +f1edd0429582dd29cccacaf50fd134b05593bd9c \ No newline at end of file diff --git a/library/alloc/benches/btree/map.rs b/library/alloc/benches/btree/map.rs index 920a5ca7db..c304f74884 100644 --- a/library/alloc/benches/btree/map.rs +++ b/library/alloc/benches/btree/map.rs @@ -54,6 +54,50 @@ macro_rules! map_insert_seq_bench { }; } +macro_rules! map_from_iter_rand_bench { + ($name: ident, $n: expr, $map: ident) => { + #[bench] + pub fn $name(b: &mut Bencher) { + let n: usize = $n; + // setup + let mut rng = thread_rng(); + let mut vec = Vec::with_capacity(n); + + for _ in 0..n { + let i = rng.gen::() % n; + vec.push((i, i)); + } + + // measure + b.iter(|| { + let map: $map<_, _> = vec.iter().copied().collect(); + black_box(map); + }); + } + }; +} + +macro_rules! map_from_iter_seq_bench { + ($name: ident, $n: expr, $map: ident) => { + #[bench] + pub fn $name(b: &mut Bencher) { + let n: usize = $n; + // setup + let mut vec = Vec::with_capacity(n); + + for i in 0..n { + vec.push((i, i)); + } + + // measure + b.iter(|| { + let map: $map<_, _> = vec.iter().copied().collect(); + black_box(map); + }); + } + }; +} + macro_rules! map_find_rand_bench { ($name: ident, $n: expr, $map: ident) => { #[bench] @@ -111,6 +155,12 @@ map_insert_rand_bench! {insert_rand_10_000, 10_000, BTreeMap} map_insert_seq_bench! {insert_seq_100, 100, BTreeMap} map_insert_seq_bench! {insert_seq_10_000, 10_000, BTreeMap} +map_from_iter_rand_bench! {from_iter_rand_100, 100, BTreeMap} +map_from_iter_rand_bench! {from_iter_rand_10_000, 10_000, BTreeMap} + +map_from_iter_seq_bench! {from_iter_seq_100, 100, BTreeMap} +map_from_iter_seq_bench! {from_iter_seq_10_000, 10_000, BTreeMap} + map_find_rand_bench! {find_rand_100, 100, BTreeMap} map_find_rand_bench! {find_rand_10_000, 10_000, BTreeMap} diff --git a/library/alloc/benches/vec.rs b/library/alloc/benches/vec.rs index c93a493cad..8e1d374b5d 100644 --- a/library/alloc/benches/vec.rs +++ b/library/alloc/benches/vec.rs @@ -732,3 +732,18 @@ fn bench_flat_map_collect(b: &mut Bencher) { let v = vec![777u32; 500000]; b.iter(|| v.iter().flat_map(|color| color.rotate_left(8).to_be_bytes()).collect::>()); } + +#[bench] +fn bench_retain_100000(b: &mut Bencher) { + let v = (1..=100000).collect::>(); + b.iter(|| { + let mut v = v.clone(); + v.retain(|x| x & 1 == 0) + }); +} + +#[bench] +fn bench_retain_whole_100000(b: &mut Bencher) { + let mut v = black_box(vec![826u32; 100000]); + b.iter(|| v.retain(|x| *x == 826u32)); +} diff --git a/library/alloc/benches/vec_deque.rs b/library/alloc/benches/vec_deque.rs index bf2dffd1e9..404cfa6add 100644 --- a/library/alloc/benches/vec_deque.rs +++ b/library/alloc/benches/vec_deque.rs @@ -52,3 +52,18 @@ fn bench_try_fold(b: &mut Bencher) { b.iter(|| black_box(ring.iter().try_fold(0, |a, b| Some(a + b)))) } + +#[bench] +fn bench_from_array_1000(b: &mut Bencher) { + const N: usize = 1000; + let mut array: [usize; N] = [0; N]; + + for i in 0..N { + array[i] = i; + } + + b.iter(|| { + let deq: VecDeque<_> = array.into(); + black_box(deq); + }) +} diff --git a/library/alloc/src/alloc.rs b/library/alloc/src/alloc.rs index 3ed3c2382c..4a5b0fcf03 100644 --- a/library/alloc/src/alloc.rs +++ b/library/alloc/src/alloc.rs @@ -307,7 +307,6 @@ unsafe impl Allocator for Global { } /// The allocator for unique pointers. -// This function must not unwind. If it does, MIR codegen will fail. #[cfg(all(not(no_global_oom_handling), not(test)))] #[lang = "exchange_malloc"] #[inline] diff --git a/library/alloc/src/borrow.rs b/library/alloc/src/borrow.rs index 482a497201..9ecbf05823 100644 --- a/library/alloc/src/borrow.rs +++ b/library/alloc/src/borrow.rs @@ -330,7 +330,11 @@ impl Cow<'_, B> { } #[stable(feature = "rust1", since = "1.0.0")] -impl Deref for Cow<'_, B> { +#[rustc_const_unstable(feature = "const_deref", issue = "88955")] +impl const Deref for Cow<'_, B> +where + B::Owned: ~const Borrow, +{ type Target = B; fn deref(&self) -> &B { diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index 7221685237..bd4f525604 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -187,6 +187,7 @@ impl Box { #[cfg(not(no_global_oom_handling))] #[inline(always)] #[stable(feature = "rust1", since = "1.0.0")] + #[must_use] pub fn new(x: T) -> Self { box x } @@ -211,6 +212,7 @@ impl Box { /// ``` #[cfg(not(no_global_oom_handling))] #[unstable(feature = "new_uninit", issue = "63291")] + #[must_use] #[inline] pub fn new_uninit() -> Box> { Self::new_uninit_in(Global) @@ -237,6 +239,7 @@ impl Box { #[cfg(not(no_global_oom_handling))] #[inline] #[unstable(feature = "new_uninit", issue = "63291")] + #[must_use] pub fn new_zeroed() -> Box> { Self::new_zeroed_in(Global) } @@ -245,6 +248,7 @@ impl Box { /// `x` will be pinned in memory and unable to be moved. #[cfg(not(no_global_oom_handling))] #[stable(feature = "pin", since = "1.33.0")] + #[must_use] #[inline(always)] pub fn pin(x: T) -> Pin> { (box x).into() @@ -339,6 +343,7 @@ impl Box { /// ``` #[cfg(not(no_global_oom_handling))] #[unstable(feature = "allocator_api", issue = "32838")] + #[must_use] #[inline] pub fn new_in(x: T, alloc: A) -> Self { let mut boxed = Self::new_uninit_in(alloc); @@ -395,6 +400,7 @@ impl Box { /// ``` #[unstable(feature = "allocator_api", issue = "32838")] #[cfg(not(no_global_oom_handling))] + #[must_use] // #[unstable(feature = "new_uninit", issue = "63291")] pub fn new_uninit_in(alloc: A) -> Box, A> { let layout = Layout::new::>(); @@ -459,6 +465,7 @@ impl Box { #[unstable(feature = "allocator_api", issue = "32838")] #[cfg(not(no_global_oom_handling))] // #[unstable(feature = "new_uninit", issue = "63291")] + #[must_use] pub fn new_zeroed_in(alloc: A) -> Box, A> { let layout = Layout::new::>(); // NOTE: Prefer match over unwrap_or_else since closure sometimes not inlineable. @@ -503,6 +510,7 @@ impl Box { /// `x` will be pinned in memory and unable to be moved. #[cfg(not(no_global_oom_handling))] #[unstable(feature = "allocator_api", issue = "32838")] + #[must_use] #[inline(always)] pub fn pin_in(x: T, alloc: A) -> Pin where @@ -561,6 +569,7 @@ impl Box<[T]> { /// ``` #[cfg(not(no_global_oom_handling))] #[unstable(feature = "new_uninit", issue = "63291")] + #[must_use] pub fn new_uninit_slice(len: usize) -> Box<[mem::MaybeUninit]> { unsafe { RawVec::with_capacity(len).into_box(len) } } @@ -585,6 +594,7 @@ impl Box<[T]> { /// [zeroed]: mem::MaybeUninit::zeroed #[cfg(not(no_global_oom_handling))] #[unstable(feature = "new_uninit", issue = "63291")] + #[must_use] pub fn new_zeroed_slice(len: usize) -> Box<[mem::MaybeUninit]> { unsafe { RawVec::with_capacity_zeroed(len).into_box(len) } } @@ -681,6 +691,7 @@ impl Box<[T], A> { #[cfg(not(no_global_oom_handling))] #[unstable(feature = "allocator_api", issue = "32838")] // #[unstable(feature = "new_uninit", issue = "63291")] + #[must_use] pub fn new_uninit_slice_in(len: usize, alloc: A) -> Box<[mem::MaybeUninit], A> { unsafe { RawVec::with_capacity_in(len, alloc).into_box(len) } } @@ -708,6 +719,7 @@ impl Box<[T], A> { #[cfg(not(no_global_oom_handling))] #[unstable(feature = "allocator_api", issue = "32838")] // #[unstable(feature = "new_uninit", issue = "63291")] + #[must_use] pub fn new_zeroed_slice_in(len: usize, alloc: A) -> Box<[mem::MaybeUninit], A> { unsafe { RawVec::with_capacity_zeroed_in(len, alloc).into_box(len) } } @@ -1086,6 +1098,7 @@ unsafe impl<#[may_dangle] T: ?Sized, A: Allocator> Drop for Box { } } +#[cfg(not(no_global_oom_handling))] #[stable(feature = "rust1", since = "1.0.0")] impl Default for Box { /// Creates a `Box`, with the `Default` value for T. @@ -1276,6 +1289,7 @@ impl From for Box { /// from the stack into it. /// /// # Examples + /// /// ```rust /// let x = 5; /// let boxed = Box::new(5); @@ -1329,6 +1343,12 @@ impl From<&[T]> for Box<[T]> { #[cfg(not(no_global_oom_handling))] #[stable(feature = "box_from_cow", since = "1.45.0")] impl From> for Box<[T]> { + /// Converts a `Cow<'_, [T]>` into a `Box<[T]>` + /// + /// When `cow` is the `Cow::Borrowed` variant, this + /// conversion allocates on the heap and copies the + /// underlying slice. Otherwise, it will try to reuse the owned + /// `Vec`'s allocation. #[inline] fn from(cow: Cow<'_, [T]>) -> Box<[T]> { match cow { @@ -1347,6 +1367,7 @@ impl From<&str> for Box { /// and performs a copy of `s`. /// /// # Examples + /// /// ```rust /// let boxed: Box = Box::from("hello"); /// println!("{}", boxed); @@ -1360,6 +1381,29 @@ impl From<&str> for Box { #[cfg(not(no_global_oom_handling))] #[stable(feature = "box_from_cow", since = "1.45.0")] impl From> for Box { + /// Converts a `Cow<'_, str>` into a `Box` + /// + /// When `cow` is the `Cow::Borrowed` variant, this + /// conversion allocates on the heap and copies the + /// underlying `str`. Otherwise, it will try to reuse the owned + /// `String`'s allocation. + /// + /// # Examples + /// + /// ```rust + /// use std::borrow::Cow; + /// + /// let unboxed = Cow::Borrowed("hello"); + /// let boxed: Box = Box::from(unboxed); + /// println!("{}", boxed); + /// ``` + /// + /// ```rust + /// # use std::borrow::Cow; + /// let unboxed = Cow::Owned("hello".to_string()); + /// let boxed: Box = Box::from(unboxed); + /// println!("{}", boxed); + /// ``` #[inline] fn from(cow: Cow<'_, str>) -> Box { match cow { @@ -1394,6 +1438,7 @@ impl From> for Box<[u8], A> { } } +#[cfg(not(no_global_oom_handling))] #[stable(feature = "box_from_array", since = "1.45.0")] impl From<[T; N]> for Box<[T]> { /// Converts a `[T; N]` into a `Box<[T]>` @@ -1401,6 +1446,7 @@ impl From<[T; N]> for Box<[T]> { /// This conversion moves the array to newly heap-allocated memory. /// /// # Examples + /// /// ```rust /// let boxed: Box<[u8]> = Box::from([4, 2]); /// println!("{:?}", boxed); @@ -1414,6 +1460,15 @@ impl From<[T; N]> for Box<[T]> { impl TryFrom> for Box<[T; N]> { type Error = Box<[T]>; + /// Attempts to convert a `Box<[T]>` into a `Box<[T; N]>`. + /// + /// The conversion occurs in-place and does not require a + /// new memory allocation. + /// + /// # Errors + /// + /// Returns the old `Box<[T]>` in the `Err` variant if + /// `boxed_slice.len()` does not equal `N`. fn try_from(boxed_slice: Box<[T]>) -> Result { if boxed_slice.len() == N { Ok(unsafe { Box::from_raw(Box::into_raw(boxed_slice) as *mut [T; N]) }) diff --git a/library/alloc/src/collections/binary_heap.rs b/library/alloc/src/collections/binary_heap.rs index 28e4f8bba0..9bded6c0f1 100644 --- a/library/alloc/src/collections/binary_heap.rs +++ b/library/alloc/src/collections/binary_heap.rs @@ -3,7 +3,7 @@ //! Insertion and popping the largest element have *O*(log(*n*)) time complexity. //! Checking the largest element is *O*(1). Converting a vector to a binary heap //! can be done in-place, and has *O*(*n*) complexity. A binary heap can also be -//! converted to a sorted vector in-place, allowing it to be used for an *O*(*n* \* log(*n*)) +//! converted to a sorted vector in-place, allowing it to be used for an *O*(*n* * log(*n*)) //! in-place heapsort. //! //! # Examples @@ -159,9 +159,9 @@ use super::SpecExtend; /// This will be a max-heap. /// /// 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` +/// 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 +/// 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. @@ -219,7 +219,7 @@ use super::SpecExtend; /// /// ## Min-heap /// -/// Either `std::cmp::Reverse` or a custom `Ord` implementation can be used to +/// Either [`core::cmp::Reverse`] or a custom [`Ord`] implementation can be used to /// make `BinaryHeap` a min-heap. This makes `heap.pop()` return the smallest /// value instead of the greatest one. /// @@ -243,13 +243,17 @@ use super::SpecExtend; /// /// # Time complexity /// -/// | [push] | [pop] | [peek]/[peek\_mut] | -/// |--------|-----------|--------------------| -/// | O(1)~ | *O*(log(*n*)) | *O*(1) | +/// | [push] | [pop] | [peek]/[peek\_mut] | +/// |---------|---------------|--------------------| +/// | *O*(1)~ | *O*(log(*n*)) | *O*(1) | /// /// The value for `push` is an expected cost; the method documentation gives a /// more detailed analysis. /// +/// [`core::cmp::Reverse`]: core::cmp::Reverse +/// [`Ord`]: core::cmp::Ord +/// [`Cell`]: core::cell::Cell +/// [`RefCell`]: core::cell::RefCell /// [push]: BinaryHeap::push /// [pop]: BinaryHeap::pop /// [peek]: BinaryHeap::peek @@ -360,6 +364,7 @@ impl BinaryHeap { /// heap.push(4); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[must_use] pub fn new() -> BinaryHeap { BinaryHeap { data: vec![] } } @@ -379,6 +384,7 @@ impl BinaryHeap { /// heap.push(4); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[must_use] pub fn with_capacity(capacity: usize) -> BinaryHeap { BinaryHeap { data: Vec::with_capacity(capacity) } } @@ -844,6 +850,7 @@ 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 } @@ -1002,6 +1009,7 @@ impl BinaryHeap { /// /// io::sink().write(heap.as_slice()).unwrap(); /// ``` + #[must_use] #[unstable(feature = "binary_heap_as_slice", issue = "83659")] pub fn as_slice(&self) -> &[T] { self.data.as_slice() @@ -1024,6 +1032,7 @@ impl BinaryHeap { /// println!("{}", x); /// } /// ``` + #[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_vec(self) -> Vec { self.into() @@ -1255,9 +1264,10 @@ impl FusedIterator for Iter<'_, T> {} /// An owning iterator over the elements of a `BinaryHeap`. /// /// This `struct` is created by [`BinaryHeap::into_iter()`] -/// (provided by the `IntoIterator` trait). See its documentation for more. +/// (provided by the [`IntoIterator`] trait). See its documentation for more. /// /// [`into_iter`]: BinaryHeap::into_iter +/// [`IntoIterator`]: core::iter::IntoIterator #[stable(feature = "rust1", since = "1.0.0")] #[derive(Clone)] pub struct IntoIter { diff --git a/library/alloc/src/collections/btree/dedup_sorted_iter.rs b/library/alloc/src/collections/btree/dedup_sorted_iter.rs new file mode 100644 index 0000000000..60bf83b838 --- /dev/null +++ b/library/alloc/src/collections/btree/dedup_sorted_iter.rs @@ -0,0 +1,47 @@ +use core::iter::Peekable; + +/// A iterator for deduping the key of a sorted iterator. +/// When encountering the duplicated key, only the last key-value pair is yielded. +/// +/// Used by [`BTreeMap::bulk_build_from_sorted_iter`]. +pub struct DedupSortedIter +where + I: Iterator, +{ + iter: Peekable, +} + +impl DedupSortedIter +where + I: Iterator, +{ + pub fn new(iter: I) -> Self { + Self { iter: iter.peekable() } + } +} + +impl Iterator for DedupSortedIter +where + K: Eq, + I: Iterator, +{ + type Item = (K, V); + + fn next(&mut self) -> Option<(K, V)> { + loop { + let next = match self.iter.next() { + Some(next) => next, + None => return None, + }; + + let peeked = match self.iter.peek() { + Some(peeked) => peeked, + None => return Some(next), + }; + + if next.0 != peeked.0 { + return Some(next); + } + } + } +} diff --git a/library/alloc/src/collections/btree/map.rs b/library/alloc/src/collections/btree/map.rs index 406150b144..fa86e61156 100644 --- a/library/alloc/src/collections/btree/map.rs +++ b/library/alloc/src/collections/btree/map.rs @@ -1,3 +1,4 @@ +use crate::vec::Vec; use core::borrow::Borrow; use core::cmp::Ordering; use core::fmt::{self, Debug}; @@ -9,6 +10,7 @@ use core::ops::{Index, RangeBounds}; use core::ptr; use super::borrow::DormantMutRef; +use super::dedup_sorted_iter::DedupSortedIter; use super::navigate::{LazyLeafRange, LeafRange}; use super::node::{self, marker, ForceResult::*, Handle, NodeRef, Root}; use super::search::SearchResult::*; @@ -17,16 +19,16 @@ mod entry; pub use entry::{Entry, OccupiedEntry, OccupiedError, VacantEntry}; use Entry::*; -/// Minimum number of elements in nodes that are not a root. +/// Minimum number of elements in a node that is not a root. /// We might temporarily have fewer elements during methods. pub(super) const MIN_LEN: usize = node::MIN_LEN_AFTER_SPLIT; // A tree in a `BTreeMap` is a tree in the `node` module with additional invariants: // - Keys must appear in ascending order (according to the key's type). -// - If the root node is internal, it must contain at least 1 element. +// - Every non-leaf node contains at least 1 element (has at least 2 children). // - Every non-root node contains at least MIN_LEN elements. // -// An empty map may be represented both by the absence of a root node or by a +// An empty map is represented either by the absence of a root node or by a // root node that is an empty leaf. /// A map based on a [B-Tree]. @@ -325,9 +327,10 @@ impl fmt::Debug for IterMut<'_, K, V> { /// An owning iterator over the entries of a `BTreeMap`. /// /// This `struct` is created by the [`into_iter`] method on [`BTreeMap`] -/// (provided by the `IntoIterator` trait). See its documentation for more. +/// (provided by the [`IntoIterator`] trait). See its documentation for more. /// /// [`into_iter`]: IntoIterator::into_iter +/// [`IntoIterator`]: core::iter::IntoIterator #[stable(feature = "rust1", since = "1.0.0")] #[rustc_insignificant_dtor] pub struct IntoIter { @@ -499,6 +502,7 @@ impl BTreeMap { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_btree_new", issue = "71835")] + #[must_use] pub const fn new() -> BTreeMap { BTreeMap { root: None, length: 0 } } @@ -1261,6 +1265,7 @@ 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() } @@ -1283,10 +1288,23 @@ 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() } } + + /// Makes a `BTreeMap` from a sorted iterator. + pub(crate) fn bulk_build_from_sorted_iter(iter: I) -> Self + where + K: Ord, + I: Iterator, + { + let mut root = Root::new(); + let mut length = 0; + root.bulk_push(DedupSortedIter::new(iter), &mut length); + BTreeMap { root: Some(root), length } + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -1720,8 +1738,8 @@ impl<'a, K: 'a, V: 'a> DrainFilterInner<'a, K, V> { pub(super) fn size_hint(&self) -> (usize, Option) { // In most of the btree iterators, `self.length` is the number of elements // yet to be visited. Here, it includes elements that were visited and that - // the predicate decided not to drain. Making this upper bound more accurate - // requires maintaining an extra field and is not worth while. + // the predicate decided not to drain. Making this upper bound more tight + // during iteration would require an extra field. (0, Some(*self.length)) } } @@ -1911,9 +1929,15 @@ impl FusedIterator for RangeMut<'_, K, V> {} #[stable(feature = "rust1", since = "1.0.0")] impl FromIterator<(K, V)> for BTreeMap { fn from_iter>(iter: T) -> BTreeMap { - let mut map = BTreeMap::new(); - map.extend(iter); - map + let mut inputs: Vec<_> = iter.into_iter().collect(); + + if inputs.is_empty() { + return BTreeMap::new(); + } + + // use stable sort to preserve the insertion order. + inputs.sort_by(|a, b| a.0.cmp(&b.0)); + BTreeMap::bulk_build_from_sorted_iter(inputs.into_iter()) } } @@ -1947,6 +1971,7 @@ impl<'a, K: Ord + Copy, V: Copy> Extend<(&'a K, &'a V)> for BTreeMap { #[stable(feature = "rust1", since = "1.0.0")] impl Hash for BTreeMap { fn hash(&self, state: &mut H) { + self.len().hash(state); for elt in self { elt.hash(state); } @@ -2022,8 +2047,14 @@ impl From<[(K, V); N]> for BTreeMap { /// let map2: BTreeMap<_, _> = [(1, 2), (3, 4)].into(); /// assert_eq!(map1, map2); /// ``` - fn from(arr: [(K, V); N]) -> Self { - core::array::IntoIter::new(arr).collect() + fn from(mut arr: [(K, V); N]) -> Self { + if N == 0 { + return BTreeMap::new(); + } + + // use stable sort to preserve the insertion order. + arr.sort_by(|a, b| a.0.cmp(&b.0)); + BTreeMap::bulk_build_from_sorted_iter(core::array::IntoIter::new(arr)) } } diff --git a/library/alloc/src/collections/btree/map/entry.rs b/library/alloc/src/collections/btree/map/entry.rs index 5fec8dc2d1..3e9048b176 100644 --- a/library/alloc/src/collections/btree/map/entry.rs +++ b/library/alloc/src/collections/btree/map/entry.rs @@ -448,6 +448,7 @@ impl<'a, K: Ord, V> OccupiedEntry<'a, K, V> { /// } /// assert_eq!(map["poneyland"], 22); /// ``` + #[must_use = "`self` will be dropped if the result is not used"] #[stable(feature = "rust1", since = "1.0.0")] pub fn into_mut(self) -> &'a mut V { self.handle.into_val_mut() diff --git a/library/alloc/src/collections/btree/map/tests.rs b/library/alloc/src/collections/btree/map/tests.rs index a99d6c49ab..173960341f 100644 --- a/library/alloc/src/collections/btree/map/tests.rs +++ b/library/alloc/src/collections/btree/map/tests.rs @@ -1494,33 +1494,40 @@ fn test_clone() { map.check(); } +fn test_clone_panic_leak(size: usize) { + for i in 0..size { + let dummies: Vec = (0..size).map(|id| CrashTestDummy::new(id)).collect(); + let map: BTreeMap<_, ()> = dummies + .iter() + .map(|dummy| { + let panic = if dummy.id == i { Panic::InClone } else { Panic::Never }; + (dummy.spawn(panic), ()) + }) + .collect(); + + catch_unwind(|| map.clone()).unwrap_err(); + for d in &dummies { + assert_eq!(d.cloned(), if d.id <= i { 1 } else { 0 }, "id={}/{}", d.id, i); + assert_eq!(d.dropped(), if d.id < i { 1 } else { 0 }, "id={}/{}", d.id, i); + } + assert_eq!(map.len(), size); + + drop(map); + for d in &dummies { + assert_eq!(d.cloned(), if d.id <= i { 1 } else { 0 }, "id={}/{}", d.id, i); + assert_eq!(d.dropped(), if d.id < i { 2 } else { 1 }, "id={}/{}", d.id, i); + } + } +} + #[test] -fn test_clone_panic_leak() { - let a = CrashTestDummy::new(0); - let b = CrashTestDummy::new(1); - let c = CrashTestDummy::new(2); +fn test_clone_panic_leak_height_0() { + test_clone_panic_leak(3) +} - let mut map = BTreeMap::new(); - map.insert(a.spawn(Panic::Never), ()); - map.insert(b.spawn(Panic::InClone), ()); - map.insert(c.spawn(Panic::Never), ()); - - catch_unwind(|| map.clone()).unwrap_err(); - assert_eq!(a.cloned(), 1); - assert_eq!(b.cloned(), 1); - assert_eq!(c.cloned(), 0); - assert_eq!(a.dropped(), 1); - assert_eq!(b.dropped(), 0); - assert_eq!(c.dropped(), 0); - assert_eq!(map.len(), 3); - - drop(map); - assert_eq!(a.cloned(), 1); - assert_eq!(b.cloned(), 1); - assert_eq!(c.cloned(), 0); - assert_eq!(a.dropped(), 2); - assert_eq!(b.dropped(), 1); - assert_eq!(c.dropped(), 1); +#[test] +fn test_clone_panic_leak_height_1() { + test_clone_panic_leak(MIN_INSERTS_HEIGHT_1) } #[test] @@ -1748,20 +1755,20 @@ fn test_send() { #[test] fn test_ord_absence() { fn map(mut map: BTreeMap) { - map.is_empty(); - map.len(); + let _ = map.is_empty(); + let _ = map.len(); map.clear(); - map.iter(); - map.iter_mut(); - map.keys(); - map.values(); - map.values_mut(); + let _ = map.iter(); + let _ = map.iter_mut(); + let _ = map.keys(); + let _ = map.values(); + let _ = map.values_mut(); if true { - map.into_values(); + let _ = map.into_values(); } else if true { - map.into_iter(); + let _ = map.into_iter(); } else { - map.into_keys(); + let _ = map.into_keys(); } } diff --git a/library/alloc/src/collections/btree/mod.rs b/library/alloc/src/collections/btree/mod.rs index f74172c7d9..9571b3d594 100644 --- a/library/alloc/src/collections/btree/mod.rs +++ b/library/alloc/src/collections/btree/mod.rs @@ -1,5 +1,6 @@ mod append; mod borrow; +mod dedup_sorted_iter; mod fix; pub mod map; mod mem; diff --git a/library/alloc/src/collections/btree/navigate.rs b/library/alloc/src/collections/btree/navigate.rs index 7b1d4d68c4..9d0db34500 100644 --- a/library/alloc/src/collections/btree/navigate.rs +++ b/library/alloc/src/collections/btree/navigate.rs @@ -440,8 +440,7 @@ impl Handle, marker::Edge> { /// - The given edge must not have been previously returned by counterpart /// `deallocating_next_back`. /// - The returned KV handle is only valid to access the key and value, - /// and only valid until the next call to this method or counterpart - /// `deallocating_next_back`. + /// and only valid until the next call to a `deallocating_` method. unsafe fn deallocating_next( self, ) -> Option<(Self, Handle, marker::KV>)> @@ -470,8 +469,7 @@ impl Handle, marker::Edge> { /// - The given edge must not have been previously returned by counterpart /// `deallocating_next`. /// - The returned KV handle is only valid to access the key and value, - /// and only valid until the next call to this method or counterpart - /// `deallocating_next`. + /// and only valid until the next call to a `deallocating_` method. unsafe fn deallocating_next_back( self, ) -> Option<(Self, Handle, marker::KV>)> diff --git a/library/alloc/src/collections/btree/node.rs b/library/alloc/src/collections/btree/node.rs index 8f6a2ec9eb..dfce98f97b 100644 --- a/library/alloc/src/collections/btree/node.rs +++ b/library/alloc/src/collections/btree/node.rs @@ -574,7 +574,7 @@ impl NodeRef { /// no cleanup is done on any of the keys, values and other children. /// This decreases the height by 1 and is the opposite of `push_internal_level`. /// - /// Requires exclusive access to the `Root` object but not to the root node; + /// Requires exclusive access to the `NodeRef` object but not to the root node; /// it will not invalidate other handles or references to the root node. /// /// Panics if there is no internal level, i.e., if the root node is a leaf. @@ -1663,7 +1663,7 @@ pub mod marker { const PERMITS_TRAVERSAL: bool = true; } impl BorrowType for Owned { - // Traversal isn't needede, it happens using the result of `borrow_mut`. + // Traversal isn't needed, it happens using the result of `borrow_mut`. // By disabling traversal, and only creating new references to roots, // we know that every reference of the `Owned` type is to a root node. const PERMITS_TRAVERSAL: bool = false; diff --git a/library/alloc/src/collections/btree/set.rs b/library/alloc/src/collections/btree/set.rs index ff0db22e0c..d732f65b0d 100644 --- a/library/alloc/src/collections/btree/set.rs +++ b/library/alloc/src/collections/btree/set.rs @@ -1,6 +1,7 @@ // This is pretty much entirely stolen from TreeSet, since BTreeMap has an identical interface // to TreeMap +use crate::vec::Vec; use core::borrow::Borrow; use core::cmp::Ordering::{Equal, Greater, Less}; use core::cmp::{max, min}; @@ -106,9 +107,10 @@ impl fmt::Debug for Iter<'_, T> { /// An owning iterator over the items of a `BTreeSet`. /// /// This `struct` is created by the [`into_iter`] method on [`BTreeSet`] -/// (provided by the `IntoIterator` trait). See its documentation for more. +/// (provided by the [`IntoIterator`] trait). See its documentation for more. /// /// [`into_iter`]: BTreeSet#method.into_iter +/// [`IntoIterator`]: core::iter::IntoIterator #[stable(feature = "rust1", since = "1.0.0")] #[derive(Debug)] pub struct IntoIter { @@ -246,6 +248,7 @@ impl BTreeSet { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_btree_new", issue = "71835")] + #[must_use] pub const fn new() -> BTreeSet { BTreeSet { map: BTreeMap::new() } } @@ -532,6 +535,7 @@ impl BTreeSet { /// b.insert(1); /// assert_eq!(a.is_disjoint(&b), false); /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] pub fn is_disjoint(&self, other: &BTreeSet) -> bool where @@ -557,6 +561,7 @@ impl BTreeSet { /// set.insert(4); /// assert_eq!(set.is_subset(&sup), false); /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] pub fn is_subset(&self, other: &BTreeSet) -> bool where @@ -636,6 +641,7 @@ impl BTreeSet { /// set.insert(2); /// assert_eq!(set.is_superset(&sub), true); /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] pub fn is_superset(&self, other: &BTreeSet) -> bool where @@ -1056,9 +1062,17 @@ impl BTreeSet { #[stable(feature = "rust1", since = "1.0.0")] impl FromIterator for BTreeSet { fn from_iter>(iter: I) -> BTreeSet { - let mut set = BTreeSet::new(); - set.extend(iter); - set + let mut inputs: Vec<_> = iter.into_iter().collect(); + + if inputs.is_empty() { + return BTreeSet::new(); + } + + // use stable sort to preserve the insertion order. + inputs.sort(); + let iter = inputs.into_iter().map(|k| (k, ())); + let map = BTreeMap::bulk_build_from_sorted_iter(iter); + BTreeSet { map } } } @@ -1071,8 +1085,16 @@ impl From<[T; N]> for BTreeSet { /// let set2: BTreeSet<_> = [1, 2, 3, 4].into(); /// assert_eq!(set1, set2); /// ``` - fn from(arr: [T; N]) -> Self { - core::array::IntoIter::new(arr).collect() + fn from(mut arr: [T; N]) -> Self { + if N == 0 { + return BTreeSet::new(); + } + + // use stable sort to preserve the insertion order. + arr.sort(); + let iter = core::array::IntoIter::new(arr).map(|k| (k, ())); + let map = BTreeMap::bulk_build_from_sorted_iter(iter); + BTreeSet { map } } } diff --git a/library/alloc/src/collections/btree/testing/crash_test.rs b/library/alloc/src/collections/btree/testing/crash_test.rs index b2527b95f5..488eaa07a9 100644 --- a/library/alloc/src/collections/btree/testing/crash_test.rs +++ b/library/alloc/src/collections/btree/testing/crash_test.rs @@ -11,7 +11,7 @@ use std::sync::atomic::{AtomicUsize, Ordering::SeqCst}; /// on anything defined in the crate, apart from the `Debug` trait. #[derive(Debug)] pub struct CrashTestDummy { - id: usize, + pub id: usize, cloned: AtomicUsize, dropped: AtomicUsize, queried: AtomicUsize, diff --git a/library/alloc/src/collections/linked_list.rs b/library/alloc/src/collections/linked_list.rs index cef9bb60b8..ea010c1f89 100644 --- a/library/alloc/src/collections/linked_list.rs +++ b/library/alloc/src/collections/linked_list.rs @@ -38,9 +38,12 @@ mod tests; /// let list = LinkedList::from([1, 2, 3]); /// ``` /// -/// NOTE: It is almost always better to use `Vec` or `VecDeque` because +/// NOTE: It is almost always better to use [`Vec`] or [`VecDeque`] because /// array-based containers are generally faster, /// more memory efficient, and make better use of CPU cache. +/// +/// [`Vec`]: crate::vec::Vec +/// [`VecDeque`]: super::vec_deque::VecDeque #[stable(feature = "rust1", since = "1.0.0")] #[cfg_attr(not(test), rustc_diagnostic_item = "LinkedList")] #[rustc_insignificant_dtor] @@ -122,9 +125,10 @@ impl fmt::Debug for IterMut<'_, T> { /// An owning iterator over the elements of a `LinkedList`. /// /// This `struct` is created by the [`into_iter`] method on [`LinkedList`] -/// (provided by the `IntoIterator` trait). See its documentation for more. +/// (provided by the [`IntoIterator`] trait). See its documentation for more. /// /// [`into_iter`]: LinkedList::into_iter +/// [`IntoIterator`]: core::iter::IntoIterator #[derive(Clone)] #[stable(feature = "rust1", since = "1.0.0")] pub struct IntoIter { @@ -413,6 +417,7 @@ impl LinkedList { #[inline] #[rustc_const_stable(feature = "const_linked_list_new", since = "1.32.0")] #[stable(feature = "rust1", since = "1.0.0")] + #[must_use] pub const fn new() -> Self { LinkedList { head: None, tail: None, len: 0, marker: PhantomData } } @@ -632,6 +637,8 @@ impl LinkedList { /// Returns `true` if the `LinkedList` contains an element equal to the /// given value. /// + /// This operation should compute in *O*(*n*) time. + /// /// # Examples /// /// ``` @@ -657,6 +664,8 @@ impl LinkedList { /// Provides a reference to the front element, or `None` if the list is /// empty. /// + /// This operation should compute in *O*(1) time. + /// /// # Examples /// /// ``` @@ -677,6 +686,8 @@ impl LinkedList { /// Provides a mutable reference to the front element, or `None` if the list /// is empty. /// + /// This operation should compute in *O*(1) time. + /// /// # Examples /// /// ``` @@ -703,6 +714,8 @@ impl LinkedList { /// Provides a reference to the back element, or `None` if the list is /// empty. /// + /// This operation should compute in *O*(1) time. + /// /// # Examples /// /// ``` @@ -723,6 +736,8 @@ impl LinkedList { /// Provides a mutable reference to the back element, or `None` if the list /// is empty. /// + /// This operation should compute in *O*(1) time. + /// /// # Examples /// /// ``` @@ -1370,6 +1385,7 @@ impl<'a, T> CursorMut<'a, T> { /// The lifetime of the returned `Cursor` is bound to that of the /// `CursorMut`, which means it cannot outlive the `CursorMut` and that the /// `CursorMut` is frozen for the lifetime of the `Cursor`. + #[must_use] #[unstable(feature = "linked_list_cursors", issue = "58533")] pub fn as_cursor(&self) -> Cursor<'_, T> { Cursor { list: self.list, current: self.current, index: self.index } diff --git a/library/alloc/src/collections/mod.rs b/library/alloc/src/collections/mod.rs index 4e31df8b4b..77d28bdfe6 100644 --- a/library/alloc/src/collections/mod.rs +++ b/library/alloc/src/collections/mod.rs @@ -57,7 +57,7 @@ use core::fmt::Display; /// The error type for `try_reserve` methods. #[derive(Clone, PartialEq, Eq, Debug)] -#[unstable(feature = "try_reserve", reason = "new API", issue = "48043")] +#[stable(feature = "try_reserve", since = "1.57.0")] pub struct TryReserveError { kind: TryReserveErrorKind, } @@ -126,7 +126,7 @@ impl From for TryReserveErrorKind { } } -#[unstable(feature = "try_reserve", reason = "new API", issue = "48043")] +#[stable(feature = "try_reserve", since = "1.57.0")] impl Display for TryReserveError { fn fmt( &self, diff --git a/library/alloc/src/collections/vec_deque/drain.rs b/library/alloc/src/collections/vec_deque/drain.rs index dfa0227dea..05f94da6de 100644 --- a/library/alloc/src/collections/vec_deque/drain.rs +++ b/library/alloc/src/collections/vec_deque/drain.rs @@ -18,10 +18,21 @@ pub struct Drain< T: 'a, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, > { - pub(crate) after_tail: usize, - pub(crate) after_head: usize, - pub(crate) iter: Iter<'a, T>, - pub(crate) deque: NonNull>, + after_tail: usize, + after_head: usize, + iter: Iter<'a, T>, + deque: NonNull>, +} + +impl<'a, T, A: Allocator> Drain<'a, T, A> { + pub(super) unsafe fn new( + after_tail: usize, + after_head: usize, + iter: Iter<'a, T>, + deque: NonNull>, + ) -> Self { + Drain { after_tail, after_head, iter, deque } + } } #[stable(feature = "collection_debug", since = "1.17.0")] diff --git a/library/alloc/src/collections/vec_deque/into_iter.rs b/library/alloc/src/collections/vec_deque/into_iter.rs index 5f13c3bf30..55f6138cd0 100644 --- a/library/alloc/src/collections/vec_deque/into_iter.rs +++ b/library/alloc/src/collections/vec_deque/into_iter.rs @@ -8,16 +8,23 @@ use super::VecDeque; /// An owning iterator over the elements of a `VecDeque`. /// /// This `struct` is created by the [`into_iter`] method on [`VecDeque`] -/// (provided by the `IntoIterator` trait). See its documentation for more. +/// (provided by the [`IntoIterator`] trait). See its documentation for more. /// /// [`into_iter`]: VecDeque::into_iter +/// [`IntoIterator`]: core::iter::IntoIterator #[derive(Clone)] #[stable(feature = "rust1", since = "1.0.0")] pub struct IntoIter< T, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, > { - pub(crate) inner: VecDeque, + inner: VecDeque, +} + +impl IntoIter { + pub(super) fn new(inner: VecDeque) -> Self { + IntoIter { inner } + } } #[stable(feature = "collection_debug", since = "1.17.0")] diff --git a/library/alloc/src/collections/vec_deque/iter_mut.rs b/library/alloc/src/collections/vec_deque/iter_mut.rs index 7700b31cf5..31e6e3b06a 100644 --- a/library/alloc/src/collections/vec_deque/iter_mut.rs +++ b/library/alloc/src/collections/vec_deque/iter_mut.rs @@ -13,10 +13,21 @@ use super::{count, wrap_index, RingSlices}; #[stable(feature = "rust1", since = "1.0.0")] pub struct IterMut<'a, T: 'a> { // Internal safety invariant: the entire slice is dereferencable. - pub(crate) ring: *mut [T], - pub(crate) tail: usize, - pub(crate) head: usize, - pub(crate) phantom: PhantomData<&'a mut [T]>, + ring: *mut [T], + tail: usize, + head: usize, + phantom: PhantomData<&'a mut [T]>, +} + +impl<'a, T> IterMut<'a, T> { + pub(super) unsafe fn new( + ring: *mut [T], + tail: usize, + head: usize, + phantom: PhantomData<&'a mut [T]>, + ) -> Self { + IterMut { ring, tail, head, phantom } + } } // SAFETY: we do nothing thread-local and there is no interior mutability, diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs index e5f7c45a54..c890ff4ac5 100644 --- a/library/alloc/src/collections/vec_deque/mod.rs +++ b/library/alloc/src/collections/vec_deque/mod.rs @@ -88,7 +88,7 @@ const MAXIMUM_ZST_CAPACITY: usize = 1 << (usize::BITS - 1); // Largest possible /// [`extend`]: VecDeque::extend /// [`append`]: VecDeque::append /// [`make_contiguous`]: VecDeque::make_contiguous -#[cfg_attr(not(test), rustc_diagnostic_item = "vecdeque_type")] +#[cfg_attr(not(test), rustc_diagnostic_item = "VecDeque")] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_insignificant_dtor] pub struct VecDeque< @@ -418,6 +418,25 @@ impl VecDeque { } } + /// Copies all values from `src` to `dst`, wrapping around if needed. + /// Assumes capacity is sufficient. + #[inline] + unsafe fn copy_slice(&mut self, dst: usize, src: &[T]) { + debug_assert!(src.len() <= self.cap()); + let head_room = self.cap() - dst; + if src.len() <= head_room { + unsafe { + ptr::copy_nonoverlapping(src.as_ptr(), self.ptr().add(dst), src.len()); + } + } else { + let (left, right) = src.split_at(head_room); + unsafe { + ptr::copy_nonoverlapping(left.as_ptr(), self.ptr().add(dst), left.len()); + ptr::copy_nonoverlapping(right.as_ptr(), self.ptr(), right.len()); + } + } + } + /// Frobs the head and tail sections around to handle the fact that we /// just reallocated. Unsafe because it trusts old_capacity. #[inline] @@ -475,6 +494,7 @@ impl VecDeque { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[must_use] pub fn new() -> VecDeque { VecDeque::new_in(Global) } @@ -490,6 +510,7 @@ impl VecDeque { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[must_use] pub fn with_capacity(capacity: usize) -> VecDeque { Self::with_capacity_in(capacity, Global) } @@ -711,7 +732,6 @@ impl VecDeque { /// # Examples /// /// ``` - /// #![feature(try_reserve)] /// use std::collections::TryReserveError; /// use std::collections::VecDeque; /// @@ -730,7 +750,7 @@ impl VecDeque { /// } /// # process_data(&[1, 2, 3]).expect("why is the test harness OOMing on 12 bytes?"); /// ``` - #[unstable(feature = "try_reserve", reason = "new API", issue = "48043")] + #[stable(feature = "try_reserve", since = "1.57.0")] pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> { self.try_reserve(additional) } @@ -749,7 +769,6 @@ impl VecDeque { /// # Examples /// /// ``` - /// #![feature(try_reserve)] /// use std::collections::TryReserveError; /// use std::collections::VecDeque; /// @@ -768,7 +787,7 @@ impl VecDeque { /// } /// # process_data(&[1, 2, 3]).expect("why is the test harness OOMing on 12 bytes?"); /// ``` - #[unstable(feature = "try_reserve", reason = "new API", issue = "48043")] + #[stable(feature = "try_reserve", since = "1.57.0")] pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> { let old_cap = self.cap(); let used_cap = self.len() + 1; @@ -1002,12 +1021,9 @@ impl VecDeque { pub fn iter_mut(&mut self) -> IterMut<'_, T> { // SAFETY: The internal `IterMut` safety invariant is established because the // `ring` we create is a dereferencable slice for lifetime '_. - IterMut { - tail: self.tail, - head: self.head, - ring: ptr::slice_from_raw_parts_mut(self.ptr(), self.cap()), - phantom: PhantomData, - } + let ring = ptr::slice_from_raw_parts_mut(self.ptr(), self.cap()); + + unsafe { IterMut::new(ring, self.tail, self.head, PhantomData) } } /// Returns a pair of slices which contain, in order, the contents of the @@ -1194,12 +1210,9 @@ impl VecDeque { // SAFETY: The internal `IterMut` safety invariant is established because the // `ring` we create is a dereferencable slice for lifetime '_. - IterMut { - tail, - head, - ring: ptr::slice_from_raw_parts_mut(self.ptr(), self.cap()), - phantom: PhantomData, - } + let ring = ptr::slice_from_raw_parts_mut(self.ptr(), self.cap()); + + unsafe { IterMut::new(ring, tail, head, PhantomData) } } /// Creates a draining iterator that removes the specified range in the @@ -1271,19 +1284,17 @@ impl VecDeque { // the drain is complete and the Drain destructor is run. self.head = drain_tail; - Drain { - deque: NonNull::from(&mut *self), - after_tail: drain_head, - after_head: head, - iter: Iter { - tail: drain_tail, - head: drain_head, - // Crucially, we only create shared references from `self` here and read from - // it. We do not write to `self` nor reborrow to a mutable reference. - // Hence the raw pointer we created above, for `deque`, remains valid. - ring: unsafe { self.buffer_as_slice() }, - }, - } + let deque = NonNull::from(&mut *self); + let iter = Iter { + tail: drain_tail, + head: drain_head, + // Crucially, we only create shared references from `self` here and read from + // it. We do not write to `self` nor reborrow to a mutable reference. + // Hence the raw pointer we created above, for `deque`, remains valid. + ring: unsafe { self.buffer_as_slice() }, + }; + + unsafe { Drain::new(drain_head, head, iter, deque) } } /// Clears the `VecDeque`, removing all values. @@ -2089,8 +2100,17 @@ impl VecDeque { #[inline] #[stable(feature = "append", since = "1.4.0")] pub fn append(&mut self, other: &mut Self) { - // naive impl - self.extend(other.drain(..)); + self.reserve(other.len()); + unsafe { + let (left, right) = other.as_slices(); + self.copy_slice(self.head, left); + self.copy_slice(self.wrap_add(self.head, left.len()), right); + } + // SAFETY: Update pointers after copying to avoid leaving doppelganger + // in case of panics. + self.head = self.wrap_add(self.head, other.len()); + // Silently drop values in `other`. + other.tail = other.head; } /// Retains only the elements specified by the predicate. @@ -2828,7 +2848,7 @@ impl IntoIterator for VecDeque { /// Consumes the `VecDeque` into a front-to-back iterator yielding elements by /// value. fn into_iter(self) -> IntoIter { - IntoIter { inner: self } + IntoIter::new(self) } } @@ -3004,6 +3024,16 @@ impl From<[T; N]> for VecDeque { /// assert_eq!(deq1, deq2); /// ``` fn from(arr: [T; N]) -> Self { - core::array::IntoIter::new(arr).collect() + let mut deq = VecDeque::with_capacity(N); + let arr = ManuallyDrop::new(arr); + if mem::size_of::() != 0 { + // SAFETY: VecDeque::with_capacity ensures that there is enough capacity. + unsafe { + ptr::copy_nonoverlapping(arr.as_ptr(), deq.ptr(), N); + } + } + deq.tail = 0; + deq.head = N; + deq } } diff --git a/library/alloc/src/collections/vec_deque/pair_slices.rs b/library/alloc/src/collections/vec_deque/pair_slices.rs index 8e3ac9cfd1..6735424a3e 100644 --- a/library/alloc/src/collections/vec_deque/pair_slices.rs +++ b/library/alloc/src/collections/vec_deque/pair_slices.rs @@ -20,10 +20,10 @@ use super::VecDeque; /// /// and the uneven remainder of either A or B is skipped. pub struct PairSlices<'a, 'b, T> { - pub(crate) a0: &'a mut [T], - pub(crate) a1: &'a mut [T], - pub(crate) b0: &'b [T], - pub(crate) b1: &'b [T], + a0: &'a mut [T], + a1: &'a mut [T], + b0: &'b [T], + b1: &'b [T], } impl<'a, 'b, T> PairSlices<'a, 'b, T> { diff --git a/library/alloc/src/collections/vec_deque/tests.rs b/library/alloc/src/collections/vec_deque/tests.rs index 56257e4346..2be83f68f0 100644 --- a/library/alloc/src/collections/vec_deque/tests.rs +++ b/library/alloc/src/collections/vec_deque/tests.rs @@ -507,6 +507,36 @@ fn test_from_vec_zst_overflow() { assert_eq!(vd.len(), vec.len()); } +#[test] +fn test_from_array() { + fn test() { + let mut array: [usize; N] = [0; N]; + + for i in 0..N { + array[i] = i; + } + + let deq: VecDeque<_> = array.into(); + + for i in 0..N { + assert_eq!(deq[i], i); + } + + assert!(deq.cap().is_power_of_two()); + assert_eq!(deq.len(), N); + } + test::<0>(); + test::<1>(); + test::<2>(); + test::<32>(); + test::<35>(); + + let array = [(); MAXIMUM_ZST_CAPACITY - 1]; + let deq = VecDeque::from(array); + assert!(deq.cap().is_power_of_two()); + assert_eq!(deq.len(), MAXIMUM_ZST_CAPACITY - 1); +} + #[test] fn test_vec_from_vecdeque() { use crate::vec::Vec; diff --git a/library/alloc/src/fmt.rs b/library/alloc/src/fmt.rs index 8c5125d208..878d8dc550 100644 --- a/library/alloc/src/fmt.rs +++ b/library/alloc/src/fmt.rs @@ -348,7 +348,7 @@ //! provides some helper methods. //! //! Additionally, the return value of this function is [`fmt::Result`] which is a -//! type alias of [`Result`]`<(), `[`std::fmt::Error`]`>`. Formatting implementations +//! type alias of [Result]<(), [std::fmt::Error]>. Formatting implementations //! should ensure that they propagate errors from the [`Formatter`] (e.g., when //! calling [`write!`]). However, they should never return errors spuriously. That //! is, a formatting implementation must and may only return an error if the @@ -505,23 +505,19 @@ //! it would internally pass around this structure until it has been determined //! where output should go to. //! -//! [`fmt::Result`]: Result -//! [`Result`]: core::result::Result -//! [`std::fmt::Error`]: Error -//! [`write!`]: core::write -//! [`write`]: core::write -//! [`format!`]: crate::format -//! [`to_string`]: crate::string::ToString -//! [`writeln!`]: core::writeln +//! [`fmt::Result`]: Result "fmt::Result" +//! [Result]: core::result::Result "std::result::Result" +//! [std::fmt::Error]: Error "fmt::Error" +//! [`write`]: write() "fmt::write" +//! [`to_string`]: crate::string::ToString::to_string "ToString::to_string" //! [`write_fmt`]: ../../std/io/trait.Write.html#method.write_fmt //! [`std::io::Write`]: ../../std/io/trait.Write.html -//! [`print!`]: ../../std/macro.print.html -//! [`println!`]: ../../std/macro.println.html -//! [`eprint!`]: ../../std/macro.eprint.html -//! [`eprintln!`]: ../../std/macro.eprintln.html -//! [`format_args!`]: core::format_args -//! [`fmt::Arguments`]: Arguments -//! [`format`]: crate::format +//! [`print!`]: ../../std/macro.print.html "print!" +//! [`println!`]: ../../std/macro.println.html "println!" +//! [`eprint!`]: ../../std/macro.eprint.html "eprint!" +//! [`eprintln!`]: ../../std/macro.eprintln.html "eprintln!" +//! [`fmt::Arguments`]: Arguments "fmt::Arguments" +//! [`format`]: format() "fmt::format" #![stable(feature = "rust1", since = "1.0.0")] diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index 1a387f291c..635708fd4c 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -67,6 +67,17 @@ issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/", test(no_crate_inject, attr(allow(unused_variables), deny(warnings))) )] +#![cfg_attr( + not(bootstrap), + doc(cfg_hide( + not(test), + not(any(test, bootstrap)), + any(not(feature = "miri-test-libstd"), test, doctest), + no_global_oom_handling, + not(no_global_oom_handling), + target_has_atomic = "ptr" + )) +)] #![no_std] #![needs_allocator] #![warn(deprecated_in_future)] @@ -85,7 +96,6 @@ #![feature(allow_internal_unstable)] #![feature(arbitrary_self_types)] #![feature(async_stream)] -#![cfg_attr(bootstrap, feature(bindings_after_at))] #![feature(box_patterns)] #![feature(box_syntax)] #![feature(cfg_sanitize)] @@ -112,6 +122,7 @@ // 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)] @@ -143,11 +154,11 @@ #![feature(alloc_layout_extra)] #![feature(trusted_random_access)] #![feature(try_trait_v2)] -#![cfg_attr(bootstrap, feature(min_type_alias_impl_trait))] -#![cfg_attr(not(bootstrap), feature(type_alias_impl_trait))] #![feature(associated_type_bounds)] #![feature(slice_group_by)] #![feature(decl_macro)] +#![feature(doc_cfg)] +#![cfg_attr(not(bootstrap), feature(doc_cfg_hide))] // Allow testing this library #[cfg(test)] @@ -178,7 +189,6 @@ mod boxed { pub mod borrow; pub mod collections; pub mod fmt; -pub mod prelude; pub mod raw_vec; pub mod rc; pub mod slice; diff --git a/library/alloc/src/prelude/mod.rs b/library/alloc/src/prelude/mod.rs deleted file mode 100644 index 0534ad3edc..0000000000 --- a/library/alloc/src/prelude/mod.rs +++ /dev/null @@ -1,15 +0,0 @@ -//! The alloc Prelude -//! -//! The purpose of this module is to alleviate imports of commonly-used -//! items of the `alloc` crate by adding a glob import to the top of modules: -//! -//! ``` -//! # #![allow(unused_imports)] -//! #![feature(alloc_prelude)] -//! extern crate alloc; -//! use alloc::prelude::v1::*; -//! ``` - -#![unstable(feature = "alloc_prelude", issue = "58935")] - -pub mod v1; diff --git a/library/alloc/src/prelude/v1.rs b/library/alloc/src/prelude/v1.rs deleted file mode 100644 index 6a53b4ca1f..0000000000 --- a/library/alloc/src/prelude/v1.rs +++ /dev/null @@ -1,14 +0,0 @@ -//! The first version of the prelude of `alloc` crate. -//! -//! See the [module-level documentation](../index.html) for more. - -#![unstable(feature = "alloc_prelude", issue = "58935")] - -#[unstable(feature = "alloc_prelude", issue = "58935")] -pub use crate::borrow::ToOwned; -#[unstable(feature = "alloc_prelude", issue = "58935")] -pub use crate::boxed::Box; -#[unstable(feature = "alloc_prelude", issue = "58935")] -pub use crate::string::{String, ToString}; -#[unstable(feature = "alloc_prelude", issue = "58935")] -pub use crate::vec::Vec; diff --git a/library/alloc/src/raw_vec.rs b/library/alloc/src/raw_vec.rs index 3caada06f6..75dbd4678b 100644 --- a/library/alloc/src/raw_vec.rs +++ b/library/alloc/src/raw_vec.rs @@ -69,6 +69,7 @@ impl RawVec { /// `RawVec` with capacity `0`. If `T` is zero-sized, then it makes a /// `RawVec` with capacity `usize::MAX`. Useful for implementing /// delayed allocation. + #[must_use] pub const fn new() -> Self { Self::new_in(Global) } @@ -87,6 +88,7 @@ impl RawVec { /// /// Aborts on OOM. #[cfg(not(no_global_oom_handling))] + #[must_use] #[inline] pub fn with_capacity(capacity: usize) -> Self { Self::with_capacity_in(capacity, Global) @@ -94,6 +96,7 @@ impl RawVec { /// Like `with_capacity`, but guarantees the buffer is zeroed. #[cfg(not(no_global_oom_handling))] + #[must_use] #[inline] pub fn with_capacity_zeroed(capacity: usize) -> Self { Self::with_capacity_zeroed_in(capacity, Global) @@ -323,7 +326,7 @@ impl RawVec { pub fn reserve(&mut self, len: usize, additional: usize) { // Callers expect this function to be very cheap when there is already sufficient capacity. // Therefore, we move all the resizing and error-handling logic from grow_amortized and - // handle_reserve behind a call, while making sure that the this function is likely to be + // handle_reserve behind a call, while making sure that this function is likely to be // inlined as just a comparison and a call if the comparison fails. #[cold] fn do_reserve_and_handle( diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index 78356f7a48..493cf3117e 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -452,6 +452,7 @@ impl Rc { /// ``` #[cfg(not(no_global_oom_handling))] #[unstable(feature = "new_uninit", issue = "63291")] + #[must_use] pub fn new_uninit() -> Rc> { unsafe { Rc::from_ptr(Rc::allocate_for_layout( @@ -484,6 +485,7 @@ impl Rc { /// [zeroed]: mem::MaybeUninit::zeroed #[cfg(not(no_global_oom_handling))] #[unstable(feature = "new_uninit", issue = "63291")] + #[must_use] pub fn new_zeroed() -> Rc> { unsafe { Rc::from_ptr(Rc::allocate_for_layout( @@ -587,6 +589,7 @@ impl Rc { /// `value` will be pinned in memory and unable to be moved. #[cfg(not(no_global_oom_handling))] #[stable(feature = "pin", since = "1.33.0")] + #[must_use] pub fn pin(value: T) -> Pin> { unsafe { Pin::new_unchecked(Rc::new(value)) } } @@ -658,6 +661,7 @@ impl Rc<[T]> { /// ``` #[cfg(not(no_global_oom_handling))] #[unstable(feature = "new_uninit", issue = "63291")] + #[must_use] pub fn new_uninit_slice(len: usize) -> Rc<[mem::MaybeUninit]> { unsafe { Rc::from_ptr(Rc::allocate_for_slice(len)) } } @@ -684,6 +688,7 @@ impl Rc<[T]> { /// [zeroed]: mem::MaybeUninit::zeroed #[cfg(not(no_global_oom_handling))] #[unstable(feature = "new_uninit", issue = "63291")] + #[must_use] pub fn new_zeroed_slice(len: usize) -> Rc<[mem::MaybeUninit]> { unsafe { Rc::from_ptr(Rc::allocate_for_layout( @@ -782,9 +787,7 @@ impl Rc { /// Consumes the `Rc`, returning the wrapped pointer. /// /// To avoid a memory leak the pointer must be converted back to an `Rc` using - /// [`Rc::from_raw`][from_raw]. - /// - /// [from_raw]: Rc::from_raw + /// [`Rc::from_raw`]. /// /// # Examples /// @@ -835,7 +838,7 @@ impl Rc { /// and alignment as `T`. This is trivially true if `U` is `T`. /// Note that if `U` is not `T` but has the same size and alignment, this is /// basically like transmuting references of different types. See - /// [`mem::transmute`][transmute] for more information on what + /// [`mem::transmute`] for more information on what /// restrictions apply in this case. /// /// The user of `from_raw` has to make sure a specific value of `T` is only @@ -845,7 +848,6 @@ impl Rc { /// even if the returned `Rc` is never accessed. /// /// [into_raw]: Rc::into_raw - /// [transmute]: core::mem::transmute /// /// # Examples /// @@ -1087,8 +1089,6 @@ impl Rc { /// assert!(Rc::ptr_eq(&five, &same_five)); /// assert!(!Rc::ptr_eq(&five, &other_five)); /// ``` - /// - /// [`ptr::eq`]: core::ptr::eq pub fn ptr_eq(this: &Self, other: &Self) -> bool { this.ptr.as_ptr() == other.ptr.as_ptr() } @@ -1994,7 +1994,7 @@ impl> ToRcSlice for I { /// `Weak` is a version of [`Rc`] that holds a non-owning reference to the /// managed allocation. The allocation is accessed by calling [`upgrade`] on the `Weak` -/// pointer, which returns an [`Option`]`<`[`Rc`]`>`. +/// pointer, which returns an [Option]<[Rc]\>. /// /// Since a `Weak` reference does not count towards ownership, it will not /// prevent the value stored in the allocation from being dropped, and `Weak` itself makes no @@ -2049,6 +2049,7 @@ impl Weak { /// assert!(empty.upgrade().is_none()); /// ``` #[stable(feature = "downgraded_weak", since = "1.10.0")] + #[must_use] pub fn new() -> Weak { Weak { ptr: NonNull::new(usize::MAX as *mut RcBox).expect("MAX is not 0") } } @@ -2091,7 +2092,8 @@ impl Weak { /// // assert_eq!("hello", unsafe { &*weak.as_ptr() }); /// ``` /// - /// [`null`]: core::ptr::null + /// [`null`]: ptr::null + #[must_use] #[stable(feature = "rc_as_ptr", since = "1.45.0")] pub fn as_ptr(&self) -> *const T { let ptr: *mut RcBox = NonNull::as_ptr(self.ptr); @@ -2135,6 +2137,7 @@ impl Weak { /// /// [`from_raw`]: Weak::from_raw /// [`as_ptr`]: Weak::as_ptr + #[must_use = "`self` will be dropped if the result is not used"] #[stable(feature = "weak_into_raw", since = "1.45.0")] pub fn into_raw(self) -> *const T { let result = self.as_ptr(); @@ -2227,6 +2230,8 @@ impl Weak { /// /// assert!(weak_five.upgrade().is_none()); /// ``` + #[must_use = "this returns a new `Rc`, \ + without modifying the original weak pointer"] #[stable(feature = "rc_weak", since = "1.4.0")] pub fn upgrade(&self) -> Option> { let inner = self.inner()?; @@ -2318,8 +2323,6 @@ impl Weak { /// let third = Rc::downgrade(&third_rc); /// assert!(!first.ptr_eq(&third)); /// ``` - /// - /// [`ptr::eq`]: core::ptr::eq #[inline] #[stable(feature = "weak_ptr_eq", since = "1.39.0")] pub fn ptr_eq(&self, other: &Self) -> bool { @@ -2401,7 +2404,6 @@ impl Default for Weak { /// Constructs a new `Weak`, without allocating any memory. /// Calling [`upgrade`] on the return value always gives [`None`]. /// - /// [`None`]: Option /// [`upgrade`]: Weak::upgrade /// /// # Examples diff --git a/library/alloc/src/slice.rs b/library/alloc/src/slice.rs index 4c8ea6902f..860f21085f 100644 --- a/library/alloc/src/slice.rs +++ b/library/alloc/src/slice.rs @@ -662,6 +662,8 @@ impl [u8] { /// /// [`make_ascii_uppercase`]: slice::make_ascii_uppercase #[cfg(not(no_global_oom_handling))] + #[must_use = "this returns the uppercase bytes as a new Vec, \ + without modifying the original"] #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] #[inline] pub fn to_ascii_uppercase(&self) -> Vec { @@ -680,6 +682,8 @@ impl [u8] { /// /// [`make_ascii_lowercase`]: slice::make_ascii_lowercase #[cfg(not(no_global_oom_handling))] + #[must_use = "this returns the lowercase bytes as a new Vec, \ + without modifying the original"] #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] #[inline] pub fn to_ascii_lowercase(&self) -> Vec { diff --git a/library/alloc/src/str.rs b/library/alloc/src/str.rs index 62ba2e5765..e1d0ee42f4 100644 --- a/library/alloc/src/str.rs +++ b/library/alloc/src/str.rs @@ -367,6 +367,8 @@ impl str { /// assert_eq!(new_year, new_year.to_lowercase()); /// ``` #[cfg(not(no_global_oom_handling))] + #[must_use = "this returns the lowercase string as a new String, \ + without modifying the original"] #[stable(feature = "unicode_case_mapping", since = "1.2.0")] pub fn to_lowercase(&self) -> String { let mut s = String::with_capacity(self.len()); @@ -447,6 +449,8 @@ impl str { /// assert_eq!("TSCHÜSS", s.to_uppercase()); /// ``` #[cfg(not(no_global_oom_handling))] + #[must_use = "this returns the uppercase string as a new String, \ + without modifying the original"] #[stable(feature = "unicode_case_mapping", since = "1.2.0")] pub fn to_uppercase(&self) -> String { let mut s = String::with_capacity(self.len()); @@ -534,6 +538,7 @@ impl str { /// [`make_ascii_uppercase`]: str::make_ascii_uppercase /// [`to_uppercase`]: #method.to_uppercase #[cfg(not(no_global_oom_handling))] + #[must_use = "to uppercase the value in-place, use `make_ascii_uppercase()`"] #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] #[inline] pub fn to_ascii_uppercase(&self) -> String { @@ -565,6 +570,7 @@ impl str { /// [`make_ascii_lowercase`]: str::make_ascii_lowercase /// [`to_lowercase`]: #method.to_lowercase #[cfg(not(no_global_oom_handling))] + #[must_use = "to lowercase the value in-place, use `make_ascii_lowercase()`"] #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] #[inline] pub fn to_ascii_lowercase(&self) -> String { @@ -589,6 +595,7 @@ impl str { /// assert_eq!("☺", &*smile); /// ``` #[stable(feature = "str_box_extras", since = "1.20.0")] +#[must_use] #[inline] pub unsafe fn from_boxed_utf8_unchecked(v: Box<[u8]>) -> Box { unsafe { Box::from_raw(Box::into_raw(v) as *mut str) } diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs index 6568d9f990..f479bf231b 100644 --- a/library/alloc/src/string.rs +++ b/library/alloc/src/string.rs @@ -79,7 +79,7 @@ use crate::vec::Vec; /// /// # Examples /// -/// You can create a `String` from [a literal string][`str`] with [`String::from`]: +/// You can create a `String` from [a literal string][`&str`] with [`String::from`]: /// /// [`String::from`]: From::from /// @@ -128,7 +128,7 @@ use crate::vec::Vec; /// println!("The first letter of s is {}", s[0]); // ERROR!!! /// ``` /// -/// [`OsString`]: ../../std/ffi/struct.OsString.html +/// [`OsString`]: ../../std/ffi/struct.OsString.html "ffi::OsString" /// /// Indexing is intended to be a constant-time operation, but UTF-8 encoding /// does not allow us to do this. Furthermore, it's not clear what sort of @@ -141,7 +141,7 @@ use crate::vec::Vec; /// /// # Deref /// -/// `String`s implement [`Deref`]``, and so inherit all of [`str`]'s +/// `String` implements [Deref], and so inherits all of [`str`]'s /// methods. In addition, this means that you can pass a `String` to a /// function which takes a [`&str`] by using an ampersand (`&`): /// @@ -182,7 +182,7 @@ use crate::vec::Vec; /// to explicitly extract the string slice containing the string. The second /// way changes `example_func(&example_string);` to /// `example_func(&*example_string);`. In this case we are dereferencing a -/// `String` to a [`str`][`&str`], then referencing the [`str`][`&str`] back to +/// `String` to a [`str`], then referencing the [`str`] back to /// [`&str`]. The second way is more idiomatic, however both work to do the /// conversion explicitly rather than relying on the implicit conversion. /// @@ -282,12 +282,14 @@ use crate::vec::Vec; /// /// Here, there's no need to allocate more memory inside the loop. /// -/// [`str`]: prim@str -/// [`&str`]: prim@str -/// [`Deref`]: core::ops::Deref +/// [str]: prim@str "str" +/// [`str`]: prim@str "str" +/// [`&str`]: prim@str "&str" +/// [Deref]: core::ops::Deref "ops::Deref" +/// [`Deref`]: core::ops::Deref "ops::Deref" /// [`as_str()`]: String::as_str #[derive(PartialOrd, Eq, Ord)] -#[cfg_attr(not(test), rustc_diagnostic_item = "string_type")] +#[cfg_attr(not(test), rustc_diagnostic_item = "String")] #[stable(feature = "rust1", since = "1.0.0")] pub struct String { vec: Vec, @@ -308,10 +310,10 @@ pub struct String { /// an analogue to `FromUtf8Error`, and you can get one from a `FromUtf8Error` /// through the [`utf8_error`] method. /// -/// [`Utf8Error`]: core::str::Utf8Error -/// [`std::str`]: core::str -/// [`&str`]: prim@str -/// [`utf8_error`]: Self::utf8_error +/// [`Utf8Error`]: str::Utf8Error "std::str::Utf8Error" +/// [`std::str`]: core::str "std::str" +/// [`&str`]: prim@str "&str" +/// [`utf8_error`]: FromUtf8Error::utf8_error /// /// # Examples /// @@ -376,6 +378,7 @@ impl String { #[inline] #[rustc_const_stable(feature = "const_string_new", since = "1.39.0")] #[stable(feature = "rust1", since = "1.0.0")] + #[must_use] pub const fn new() -> String { String { vec: Vec::new() } } @@ -420,6 +423,7 @@ impl String { #[cfg(not(no_global_oom_handling))] #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[must_use] pub fn with_capacity(capacity: usize) -> String { String { vec: Vec::with_capacity(capacity) } } @@ -487,8 +491,8 @@ impl String { /// with this error. /// /// [`from_utf8_unchecked`]: String::from_utf8_unchecked - /// [`Vec`]: crate::vec::Vec - /// [`&str`]: prim@str + /// [`Vec`]: crate::vec::Vec "Vec" + /// [`&str`]: prim@str "&str" /// [`into_bytes`]: String::into_bytes #[inline] #[stable(feature = "rust1", since = "1.0.0")] @@ -524,7 +528,7 @@ impl String { /// it's already valid UTF-8, we don't need a new allocation. This return /// type allows us to handle both cases. /// - /// [`Cow<'a, str>`]: crate::borrow::Cow + /// [`Cow<'a, str>`]: crate::borrow::Cow "borrow::Cow" /// /// # Examples /// @@ -625,7 +629,7 @@ impl String { /// conversion requires a memory allocation. /// /// [`from_utf8_lossy`]: String::from_utf8_lossy - /// [`Cow<'a, str>`]: crate::borrow::Cow + /// [`Cow<'a, str>`]: crate::borrow::Cow "borrow::Cow" /// [U+FFFD]: core::char::REPLACEMENT_CHARACTER /// /// # Examples @@ -674,6 +678,7 @@ impl String { /// let rebuilt = unsafe { String::from_raw_parts(ptr, len, cap) }; /// assert_eq!(rebuilt, "hello"); /// ``` + #[must_use = "`self` will be dropped if the result is not used"] #[unstable(feature = "vec_into_raw_parts", reason = "new API", issue = "65816")] pub fn into_raw_parts(self) -> (*mut u8, usize, usize) { self.vec.into_raw_parts() @@ -759,6 +764,7 @@ impl String { /// assert_eq!("💖", sparkle_heart); /// ``` #[inline] + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] pub unsafe fn from_utf8_unchecked(bytes: Vec) -> String { String { vec: bytes } @@ -779,6 +785,7 @@ impl String { /// assert_eq!(&[104, 101, 108, 108, 111][..], &bytes[..]); /// ``` #[inline] + #[must_use = "`self` will be dropped if the result is not used"] #[stable(feature = "rust1", since = "1.0.0")] pub fn into_bytes(self) -> Vec { self.vec @@ -796,6 +803,7 @@ impl String { /// assert_eq!("foo", s.as_str()); /// ``` #[inline] + #[must_use] #[stable(feature = "string_as_str", since = "1.7.0")] pub fn as_str(&self) -> &str { self @@ -816,6 +824,7 @@ impl String { /// assert_eq!("FOOBAR", s_mut_str); /// ``` #[inline] + #[must_use] #[stable(feature = "string_as_str", since = "1.7.0")] pub fn as_mut_str(&mut self) -> &mut str { self @@ -1007,7 +1016,6 @@ impl String { /// # Examples /// /// ``` - /// #![feature(try_reserve)] /// use std::collections::TryReserveError; /// /// fn process_data(data: &str) -> Result { @@ -1023,7 +1031,7 @@ impl String { /// } /// # process_data("rust").expect("why is the test harness OOMing on 4 bytes?"); /// ``` - #[unstable(feature = "try_reserve", reason = "new API", issue = "48043")] + #[stable(feature = "try_reserve", since = "1.57.0")] pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> { self.vec.try_reserve(additional) } @@ -1047,7 +1055,6 @@ impl String { /// # Examples /// /// ``` - /// #![feature(try_reserve)] /// use std::collections::TryReserveError; /// /// fn process_data(data: &str) -> Result { @@ -1063,7 +1070,7 @@ impl String { /// } /// # process_data("rust").expect("why is the test harness OOMing on 4 bytes?"); /// ``` - #[unstable(feature = "try_reserve", reason = "new API", issue = "48043")] + #[stable(feature = "try_reserve", since = "1.57.0")] pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> { self.vec.try_reserve_exact(additional) } @@ -1158,6 +1165,7 @@ impl String { /// assert_eq!(&[104, 101, 108, 108, 111], s.as_bytes()); /// ``` #[inline] + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] pub fn as_bytes(&self) -> &[u8] { &self.vec @@ -1721,11 +1729,11 @@ impl String { unsafe { self.as_mut_vec() }.splice((start, end), replace_with.bytes()); } - /// Converts this `String` into a [`Box`]`<`[`str`]`>`. + /// Converts this `String` into a [Box]<[str]>. /// /// This will drop any excess capacity. /// - /// [`str`]: prim@str + /// [str]: prim@str "str" /// /// # Examples /// @@ -1738,6 +1746,7 @@ impl String { /// ``` #[cfg(not(no_global_oom_handling))] #[stable(feature = "box_str", since = "1.4.0")] + #[must_use = "`self` will be dropped if the result is not used"] #[inline] pub fn into_boxed_str(self) -> Box { let slice = self.vec.into_boxed_slice(); @@ -1760,6 +1769,7 @@ impl FromUtf8Error { /// /// assert_eq!(&[0, 159], value.unwrap_err().as_bytes()); /// ``` + #[must_use] #[stable(feature = "from_utf8_error_as_bytes", since = "1.26.0")] pub fn as_bytes(&self) -> &[u8] { &self.bytes[..] @@ -1783,6 +1793,7 @@ impl FromUtf8Error { /// /// assert_eq!(vec![0, 159], value.unwrap_err().into_bytes()); /// ``` + #[must_use = "`self` will be dropped if the result is not used"] #[stable(feature = "rust1", since = "1.0.0")] pub fn into_bytes(self) -> Vec { self.bytes @@ -1795,8 +1806,8 @@ impl FromUtf8Error { /// an analogue to `FromUtf8Error`. See its documentation for more details /// on using it. /// - /// [`std::str`]: core::str - /// [`&str`]: prim@str + /// [`std::str`]: core::str "std::str" + /// [`&str`]: prim@str "&str" /// /// # Examples /// @@ -2319,7 +2330,7 @@ impl ops::DerefMut for String { /// /// This alias exists for backwards compatibility, and may be eventually deprecated. /// -/// [`Infallible`]: core::convert::Infallible +/// [`Infallible`]: core::convert::Infallible "convert::Infallible" #[stable(feature = "str_parse_error", since = "1.5.0")] pub type ParseError = core::convert::Infallible; @@ -2606,7 +2617,7 @@ impl<'a> From<&'a str> for Cow<'a, str> { /// assert_eq!(Cow::from("eggplant"), Cow::Borrowed("eggplant")); /// ``` /// - /// [`Borrowed`]: crate::borrow::Cow::Borrowed + /// [`Borrowed`]: crate::borrow::Cow::Borrowed "borrow::Cow::Borrowed" #[inline] fn from(s: &'a str) -> Cow<'a, str> { Cow::Borrowed(s) @@ -2629,7 +2640,7 @@ impl<'a> From for Cow<'a, str> { /// assert_eq!(Cow::from(s), Cow::<'static, str>::Owned(s2)); /// ``` /// - /// [`Owned`]: crate::borrow::Cow::Owned + /// [`Owned`]: crate::borrow::Cow::Owned "borrow::Cow::Owned" #[inline] fn from(s: String) -> Cow<'a, str> { Cow::Owned(s) @@ -2651,7 +2662,7 @@ impl<'a> From<&'a String> for Cow<'a, str> { /// assert_eq!(Cow::from(&s), Cow::Borrowed("eggplant")); /// ``` /// - /// [`Borrowed`]: crate::borrow::Cow::Borrowed + /// [`Borrowed`]: crate::borrow::Cow::Borrowed "borrow::Cow::Borrowed" #[inline] fn from(s: &'a String) -> Cow<'a, str> { Cow::Borrowed(s.as_str()) @@ -2775,6 +2786,7 @@ impl<'a> Drain<'a> { /// let _ = drain.next().unwrap(); /// assert_eq!(drain.as_str(), "bc"); /// ``` + #[must_use] #[stable(feature = "string_drain_as_str", since = "1.55.0")] pub fn as_str(&self) -> &str { self.iter.as_str() diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index a066e0b49e..b75e9a2f3c 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -99,8 +99,8 @@ macro_rules! acquire { /// first: after all, isn't the point of `Arc` thread safety? The key is /// this: `Arc` makes it thread safe to have multiple ownership of the same /// data, but it doesn't add thread safety to its data. Consider -/// `Arc<`[`RefCell`]`>`. [`RefCell`] isn't [`Sync`], and if `Arc` was always -/// [`Send`], `Arc<`[`RefCell`]`>` would be as well. But then we'd have a problem: +/// Arc<[RefCell\]>. [`RefCell`] isn't [`Sync`], and if `Arc` was always +/// [`Send`], Arc<[RefCell\]> would be as well. But then we'd have a problem: /// [`RefCell`] is not thread safe; it keeps track of the borrowing count using /// non-atomic operations. /// @@ -146,7 +146,7 @@ macro_rules! acquire { /// use std::sync::Arc; /// /// let my_arc = Arc::new(()); -/// Arc::downgrade(&my_arc); +/// let my_weak = Arc::downgrade(&my_arc); /// ``` /// /// `Arc`'s implementations of traits like `Clone` may also be called using @@ -176,6 +176,7 @@ macro_rules! acquire { /// [deref]: core::ops::Deref /// [downgrade]: Arc::downgrade /// [upgrade]: Weak::upgrade +/// [RefCell\]: core::cell::RefCell /// [`RefCell`]: core::cell::RefCell /// [`std::sync`]: ../../std/sync/index.html /// [`Arc::clone(&from)`]: Arc::clone @@ -206,7 +207,7 @@ macro_rules! acquire { /// /// Sharing a mutable [`AtomicUsize`]: /// -/// [`AtomicUsize`]: core::sync::atomic::AtomicUsize +/// [`AtomicUsize`]: core::sync::atomic::AtomicUsize "sync::atomic::AtomicUsize" /// /// ```no_run /// use std::sync::Arc; @@ -262,7 +263,7 @@ impl Arc { /// `Weak` is a version of [`Arc`] that holds a non-owning reference to the /// managed allocation. The allocation is accessed by calling [`upgrade`] on the `Weak` -/// pointer, which returns an [`Option`]`<`[`Arc`]`>`. +/// pointer, which returns an [Option]<[Arc]\>. /// /// Since a `Weak` reference does not count towards ownership, it will not /// prevent the value stored in the allocation from being dropped, and `Weak` itself makes no @@ -447,6 +448,7 @@ impl Arc { /// ``` #[cfg(not(no_global_oom_handling))] #[unstable(feature = "new_uninit", issue = "63291")] + #[must_use] pub fn new_uninit() -> Arc> { unsafe { Arc::from_ptr(Arc::allocate_for_layout( @@ -476,9 +478,10 @@ impl Arc { /// assert_eq!(*zero, 0) /// ``` /// - /// [zeroed]: ../../std/mem/union.MaybeUninit.html#method.zeroed + /// [zeroed]: mem::MaybeUninit::zeroed #[cfg(not(no_global_oom_handling))] #[unstable(feature = "new_uninit", issue = "63291")] + #[must_use] pub fn new_zeroed() -> Arc> { unsafe { Arc::from_ptr(Arc::allocate_for_layout( @@ -493,6 +496,7 @@ impl Arc { /// `data` will be pinned in memory and unable to be moved. #[cfg(not(no_global_oom_handling))] #[stable(feature = "pin", since = "1.33.0")] + #[must_use] pub fn pin(data: T) -> Pin> { unsafe { Pin::new_unchecked(Arc::new(data)) } } @@ -661,6 +665,7 @@ impl Arc<[T]> { /// ``` #[cfg(not(no_global_oom_handling))] #[unstable(feature = "new_uninit", issue = "63291")] + #[must_use] pub fn new_uninit_slice(len: usize) -> Arc<[mem::MaybeUninit]> { unsafe { Arc::from_ptr(Arc::allocate_for_slice(len)) } } @@ -684,9 +689,10 @@ impl Arc<[T]> { /// assert_eq!(*values, [0, 0, 0]) /// ``` /// - /// [zeroed]: ../../std/mem/union.MaybeUninit.html#method.zeroed + /// [zeroed]: mem::MaybeUninit::zeroed #[cfg(not(no_global_oom_handling))] #[unstable(feature = "new_uninit", issue = "63291")] + #[must_use] pub fn new_zeroed_slice(len: usize) -> Arc<[mem::MaybeUninit]> { unsafe { Arc::from_ptr(Arc::allocate_for_layout( @@ -712,7 +718,7 @@ impl Arc> { /// Calling this when the content is not yet fully initialized /// causes immediate undefined behavior. /// - /// [`MaybeUninit::assume_init`]: ../../std/mem/union.MaybeUninit.html#method.assume_init + /// [`MaybeUninit::assume_init`]: mem::MaybeUninit::assume_init /// /// # Examples /// @@ -734,6 +740,7 @@ impl Arc> { /// assert_eq!(*five, 5) /// ``` #[unstable(feature = "new_uninit", issue = "63291")] + #[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()) @@ -751,7 +758,7 @@ impl Arc<[mem::MaybeUninit]> { /// Calling this when the content is not yet fully initialized /// causes immediate undefined behavior. /// - /// [`MaybeUninit::assume_init`]: ../../std/mem/union.MaybeUninit.html#method.assume_init + /// [`MaybeUninit::assume_init`]: mem::MaybeUninit::assume_init /// /// # Examples /// @@ -775,6 +782,7 @@ impl Arc<[mem::MaybeUninit]> { /// assert_eq!(*values, [1, 2, 3]) /// ``` #[unstable(feature = "new_uninit", issue = "63291")] + #[must_use = "`self` will be dropped if the result is not used"] #[inline] pub unsafe fn assume_init(self) -> Arc<[T]> { unsafe { Arc::from_ptr(mem::ManuallyDrop::new(self).ptr.as_ptr() as _) } @@ -819,6 +827,7 @@ impl Arc { /// assert_eq!(x_ptr, Arc::as_ptr(&y)); /// assert_eq!(unsafe { &*x_ptr }, "hello"); /// ``` + #[must_use] #[stable(feature = "rc_as_ptr", since = "1.45.0")] pub fn as_ptr(this: &Self) -> *const T { let ptr: *mut ArcInner = NonNull::as_ptr(this.ptr); @@ -889,6 +898,8 @@ impl Arc { /// /// let weak_five = Arc::downgrade(&five); /// ``` + #[must_use = "this returns a new `Weak` pointer, \ + without modifying the original `Arc`"] #[stable(feature = "arc_weak", since = "1.4.0")] pub fn downgrade(this: &Self) -> Weak { // This Relaxed is OK because we're checking the value in the CAS @@ -1086,7 +1097,7 @@ impl Arc { /// assert!(!Arc::ptr_eq(&five, &other_five)); /// ``` /// - /// [`ptr::eq`]: core::ptr::eq + /// [`ptr::eq`]: core::ptr::eq "ptr::eq" pub fn ptr_eq(this: &Self, other: &Self) -> bool { this.ptr.as_ptr() == other.ptr.as_ptr() } @@ -1677,6 +1688,7 @@ impl Weak { /// assert!(empty.upgrade().is_none()); /// ``` #[stable(feature = "downgraded_weak", since = "1.10.0")] + #[must_use] pub fn new() -> Weak { Weak { ptr: NonNull::new(usize::MAX as *mut ArcInner).expect("MAX is not 0") } } @@ -1714,7 +1726,8 @@ impl Weak { /// // assert_eq!("hello", unsafe { &*weak.as_ptr() }); /// ``` /// - /// [`null`]: core::ptr::null + /// [`null`]: core::ptr::null "ptr::null" + #[must_use] #[stable(feature = "weak_into_raw", since = "1.45.0")] pub fn as_ptr(&self) -> *const T { let ptr: *mut ArcInner = NonNull::as_ptr(self.ptr); @@ -1758,6 +1771,7 @@ impl Weak { /// /// [`from_raw`]: Weak::from_raw /// [`as_ptr`]: Weak::as_ptr + #[must_use = "`self` will be dropped if the result is not used"] #[stable(feature = "weak_into_raw", since = "1.45.0")] pub fn into_raw(self) -> *const T { let result = self.as_ptr(); @@ -1806,7 +1820,6 @@ impl Weak { /// [`new`]: Weak::new /// [`into_raw`]: Weak::into_raw /// [`upgrade`]: Weak::upgrade - /// [`forget`]: std::mem::forget #[stable(feature = "weak_into_raw", since = "1.45.0")] pub unsafe fn from_raw(ptr: *const T) -> Self { // See Weak::as_ptr for context on how the input pointer is derived. @@ -1852,6 +1865,8 @@ impl Weak { /// /// assert!(weak_five.upgrade().is_none()); /// ``` + #[must_use = "this returns a new `Arc`, \ + without modifying the original weak pointer"] #[stable(feature = "arc_weak", since = "1.4.0")] pub fn upgrade(&self) -> Option> { // We use a CAS loop to increment the strong count instead of a @@ -1982,7 +1997,7 @@ impl Weak { /// assert!(!first.ptr_eq(&third)); /// ``` /// - /// [`ptr::eq`]: core::ptr::eq + /// [`ptr::eq`]: core::ptr::eq "ptr::eq" #[inline] #[stable(feature = "weak_ptr_eq", since = "1.39.0")] pub fn ptr_eq(&self, other: &Self) -> bool { diff --git a/library/alloc/src/vec/drain.rs b/library/alloc/src/vec/drain.rs index fb32d144f8..e643940d01 100644 --- a/library/alloc/src/vec/drain.rs +++ b/library/alloc/src/vec/drain.rs @@ -52,6 +52,7 @@ impl<'a, T, A: Allocator> Drain<'a, T, A> { /// let _ = drain.next().unwrap(); /// assert_eq!(drain.as_slice(), &['b', 'c']); /// ``` + #[must_use] #[stable(feature = "vec_drain_as_slice", since = "1.46.0")] pub fn as_slice(&self) -> &[T] { self.iter.as_slice() diff --git a/library/alloc/src/vec/into_iter.rs b/library/alloc/src/vec/into_iter.rs index 4cb0a4b10b..18e191f2b5 100644 --- a/library/alloc/src/vec/into_iter.rs +++ b/library/alloc/src/vec/into_iter.rs @@ -161,6 +161,29 @@ impl Iterator for IntoIter { (exact, Some(exact)) } + #[inline] + fn advance_by(&mut self, n: usize) -> Result<(), usize> { + let step_size = self.len().min(n); + let to_drop = ptr::slice_from_raw_parts_mut(self.ptr as *mut T, step_size); + if mem::size_of::() == 0 { + // SAFETY: due to unchecked casts of unsigned amounts to signed offsets the wraparound + // effectively results in unsigned pointers representing positions 0..usize::MAX, + // which is valid for ZSTs. + self.ptr = unsafe { arith_offset(self.ptr as *const i8, step_size as isize) as *mut T } + } else { + // SAFETY: the min() above ensures that step_size is in bounds + self.ptr = unsafe { self.ptr.add(step_size) }; + } + // SAFETY: the min() above ensures that step_size is in bounds + unsafe { + ptr::drop_in_place(to_drop); + } + if step_size < n { + return Err(step_size); + } + Ok(()) + } + #[inline] fn count(self) -> usize { self.len() @@ -203,6 +226,29 @@ impl DoubleEndedIterator for IntoIter { Some(unsafe { ptr::read(self.end) }) } } + + #[inline] + fn advance_back_by(&mut self, n: usize) -> Result<(), usize> { + let step_size = self.len().min(n); + if mem::size_of::() == 0 { + // SAFETY: same as for advance_by() + self.end = unsafe { + arith_offset(self.end as *const i8, step_size.wrapping_neg() as isize) as *mut T + } + } else { + // SAFETY: same as for advance_by() + self.end = unsafe { self.end.offset(step_size.wrapping_neg() as isize) }; + } + let to_drop = ptr::slice_from_raw_parts_mut(self.end as *mut T, step_size); + // SAFETY: same as for advance_by() + unsafe { + ptr::drop_in_place(to_drop); + } + if step_size < n { + return Err(step_size); + } + Ok(()) + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -220,14 +266,21 @@ unsafe impl TrustedLen for IntoIter {} #[doc(hidden)] #[unstable(issue = "none", feature = "std_internals")] +#[rustc_unsafe_specialization_marker] +pub trait NonDrop {} + // T: Copy as approximation for !Drop since get_unchecked does not advance self.ptr // and thus we can't implement drop-handling -// +#[unstable(issue = "none", feature = "std_internals")] +impl NonDrop for T {} + +#[doc(hidden)] +#[unstable(issue = "none", feature = "std_internals")] // TrustedRandomAccess (without NoCoerce) must not be implemented because -// subtypes/supertypes of `T` might not be `Copy` +// subtypes/supertypes of `T` might not be `NonDrop` unsafe impl TrustedRandomAccessNoCoerce for IntoIter where - T: Copy, + T: NonDrop, { const MAY_HAVE_SIDE_EFFECT: bool = false; } diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index cfbf207aee..20a16869cb 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -1,8 +1,8 @@ //! A contiguous growable array type with heap-allocated contents, written //! `Vec`. //! -//! Vectors have `O(1)` indexing, amortized `O(1)` push (to the end) and -//! `O(1)` pop (from the end). +//! Vectors have *O*(1) indexing, amortized *O*(1) push (to the end) and +//! *O*(1) pop (from the end). //! //! Vectors ensure they never allocate more than `isize::MAX` bytes. //! @@ -296,8 +296,8 @@ mod spec_extend; /// on an empty Vec, it will not allocate memory. Similarly, if you store zero-sized /// types inside a `Vec`, it will not allocate space for them. *Note that in this case /// the `Vec` might not report a [`capacity`] of 0*. `Vec` will allocate if and only -/// if [`mem::size_of::`]`() * capacity() > 0`. In general, `Vec`'s allocation -/// details are very subtle — if you intend to allocate memory using a `Vec` +/// if [mem::size_of::\]\() * [capacity]\() > 0. In general, `Vec`'s allocation +/// details are very subtle --- if you intend to allocate memory using a `Vec` /// and use it for something else (either to pass to unsafe code, or to build your /// own memory-backed collection), be sure to deallocate this memory by using /// `from_raw_parts` to recover the `Vec` and then dropping it. @@ -305,8 +305,8 @@ mod spec_extend; /// If a `Vec` *has* allocated memory, then the memory it points to is on the heap /// (as defined by the allocator Rust is configured to use by default), and its /// pointer points to [`len`] initialized, contiguous elements in order (what -/// you would see if you coerced it to a slice), followed by [`capacity`]` - -/// `[`len`] logically uninitialized, contiguous elements. +/// you would see if you coerced it to a slice), followed by [capacity] - [len] +/// logically uninitialized, contiguous elements. /// /// A vector containing the elements `'a'` and `'b'` with capacity 4 can be /// visualized as below. The top part is the `Vec` struct, it contains a @@ -348,7 +348,7 @@ mod spec_extend; /// /// [`push`] and [`insert`] will never (re)allocate if the reported capacity is /// sufficient. [`push`] and [`insert`] *will* (re)allocate if -/// [`len`]` == `[`capacity`]. That is, the reported capacity is completely +/// [len] == [capacity]. That is, the reported capacity is completely /// accurate, and can be relied on. It can even be used to manually free the memory /// allocated by a `Vec` if desired. Bulk insertion methods *may* reallocate, even /// when not necessary. @@ -360,7 +360,7 @@ mod spec_extend; /// /// `vec![x; n]`, `vec![a, b, c, d]`, and /// [`Vec::with_capacity(n)`][`Vec::with_capacity`], will all produce a `Vec` -/// with exactly the requested capacity. If [`len`]` == `[`capacity`], +/// with exactly the requested capacity. If [len] == [capacity], /// (as is the case for the [`vec!`] macro), then a `Vec` can be converted to /// and from a [`Box<[T]>`][owned slice] without reallocating or moving the elements. /// @@ -369,7 +369,7 @@ mod spec_extend; /// scratch space that it may use however it wants. It will generally just do /// whatever is most efficient or otherwise easy to implement. Do not rely on /// removed data to be erased for security purposes. Even if you drop a `Vec`, its -/// buffer may simply be reused by another `Vec`. Even if you zero a `Vec`'s memory +/// buffer may simply be reused by another allocation. Even if you zero a `Vec`'s memory /// first, that might not actually happen because the optimizer does not consider /// this a side-effect that must be preserved. There is one case which we will /// not break, however: using `unsafe` code to write to the excess capacity, @@ -384,8 +384,10 @@ mod spec_extend; /// [`&str`]: type@str /// [`shrink_to_fit`]: Vec::shrink_to_fit /// [`shrink_to`]: Vec::shrink_to +/// [capacity]: Vec::capacity /// [`capacity`]: Vec::capacity -/// [`mem::size_of::`]: core::mem::size_of +/// [mem::size_of::\]: core::mem::size_of +/// [len]: Vec::len /// [`len`]: Vec::len /// [`push`]: Vec::push /// [`insert`]: Vec::insert @@ -393,7 +395,7 @@ mod spec_extend; /// [`MaybeUninit`]: core::mem::MaybeUninit /// [owned slice]: Box #[stable(feature = "rust1", since = "1.0.0")] -#[cfg_attr(not(test), rustc_diagnostic_item = "vec_type")] +#[cfg_attr(not(test), rustc_diagnostic_item = "Vec")] #[rustc_insignificant_dtor] pub struct Vec { buf: RawVec, @@ -418,6 +420,7 @@ impl Vec { #[inline] #[rustc_const_stable(feature = "const_vec_new", since = "1.39.0")] #[stable(feature = "rust1", since = "1.0.0")] + #[must_use] pub const fn new() -> Self { Vec { buf: RawVec::NEW, len: 0 } } @@ -462,6 +465,7 @@ impl Vec { #[cfg(not(no_global_oom_handling))] #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[must_use] pub fn with_capacity(capacity: usize) -> Self { Self::with_capacity_in(capacity, Global) } @@ -847,7 +851,6 @@ impl Vec { /// # Examples /// /// ``` - /// #![feature(try_reserve)] /// use std::collections::TryReserveError; /// /// fn process_data(data: &[u32]) -> Result, TryReserveError> { @@ -865,7 +868,7 @@ impl Vec { /// } /// # process_data(&[1, 2, 3]).expect("why is the test harness OOMing on 12 bytes?"); /// ``` - #[unstable(feature = "try_reserve", reason = "new API", issue = "48043")] + #[stable(feature = "try_reserve", since = "1.57.0")] pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> { self.buf.try_reserve(self.len, additional) } @@ -890,7 +893,6 @@ impl Vec { /// # Examples /// /// ``` - /// #![feature(try_reserve)] /// use std::collections::TryReserveError; /// /// fn process_data(data: &[u32]) -> Result, TryReserveError> { @@ -908,7 +910,7 @@ impl Vec { /// } /// # process_data(&[1, 2, 3]).expect("why is the test harness OOMing on 12 bytes?"); /// ``` - #[unstable(feature = "try_reserve", reason = "new API", issue = "48043")] + #[stable(feature = "try_reserve", since = "1.57.0")] pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> { self.buf.try_reserve_exact(self.len, additional) } @@ -1269,7 +1271,7 @@ impl Vec { /// /// The removed element is replaced by the last element of the vector. /// - /// This does not preserve ordering, but is O(1). + /// This does not preserve ordering, but is *O*(1). /// /// # Panics /// @@ -1486,7 +1488,15 @@ impl Vec { let mut g = BackshiftOnDrop { v: self, processed_len: 0, deleted_cnt: 0, original_len }; - while g.processed_len < original_len { + // process_one return a bool indicates whether the processing element should be retained. + #[inline(always)] + fn process_one( + f: &mut F, + g: &mut BackshiftOnDrop<'_, T, A>, + ) -> bool + where + F: FnMut(&T) -> bool, + { // SAFETY: Unchecked element must be valid. let cur = unsafe { &mut *g.v.as_mut_ptr().add(g.processed_len) }; if !f(cur) { @@ -1496,9 +1506,9 @@ impl Vec { // SAFETY: We never touch this element again after dropped. unsafe { ptr::drop_in_place(cur) }; // We already advanced the counter. - continue; + return false; } - if g.deleted_cnt > 0 { + if DELETED { // SAFETY: `deleted_cnt` > 0, so the hole slot must not overlap with current element. // We use copy for move, and never touch this element again. unsafe { @@ -1507,6 +1517,19 @@ impl Vec { } } g.processed_len += 1; + return true; + } + + // Stage 1: Nothing was deleted. + while g.processed_len != original_len { + if !process_one::(&mut f, &mut g) { + break; + } + } + + // Stage 2: Some elements were deleted. + while g.processed_len != original_len { + process_one::(&mut f, &mut g); } // All item are processed. This can be optimized to `set_len` by LLVM. @@ -1950,8 +1973,9 @@ impl Vec { /// `'a`. If the type has only static references, or none at all, then this /// may be chosen to be `'static`. /// - /// This function is similar to the [`leak`][Box::leak] function on [`Box`] - /// except that there is no way to recover the leaked memory. + /// As of Rust 1.57, this method does not reallocate or shrink the `Vec`, + /// so the leaked allocation may include unused capacity that is not part + /// of the returned slice. /// /// This function is mainly useful for data that lives for the remainder of /// the program's life. Dropping the returned reference will cause a memory @@ -1974,7 +1998,8 @@ impl Vec { where A: 'a, { - Box::leak(self.into_boxed_slice()) + let mut me = ManuallyDrop::new(self); + unsafe { slice::from_raw_parts_mut(me.as_mut_ptr(), me.len) } } /// Returns the remaining spare capacity of the vector as a slice of @@ -2114,6 +2139,7 @@ impl Vec { /// in order to be able to clone the passed value. /// If you need more flexibility (or want to rely on [`Default`] instead of /// [`Clone`]), use [`Vec::resize_with`]. + /// If you only need to resize to a smaller size, use [`Vec::truncate`]. /// /// # Examples /// @@ -2165,7 +2191,12 @@ impl Vec { /// Copies elements from `src` range to the end of the vector. /// - /// ## Examples + /// # Panics + /// + /// Panics if the starting point is greater than the end point or if + /// the end point is greater than the length of the vector. + /// + /// # Examples /// /// ``` /// let mut vec = vec![0, 1, 2, 3, 4]; @@ -2842,6 +2873,7 @@ impl From<&mut [T]> for Vec { } } +#[cfg(not(no_global_oom_handling))] #[stable(feature = "vec_from_array", since = "1.44.0")] impl From<[T; N]> for Vec { #[cfg(not(test))] diff --git a/library/alloc/src/vec/source_iter_marker.rs b/library/alloc/src/vec/source_iter_marker.rs index e05788d99c..6e78534cf5 100644 --- a/library/alloc/src/vec/source_iter_marker.rs +++ b/library/alloc/src/vec/source_iter_marker.rs @@ -6,24 +6,14 @@ use super::{AsIntoIter, InPlaceDrop, SpecFromIter, SpecFromIterNested, Vec}; /// Specialization marker for collecting an iterator pipeline into a Vec while reusing the /// source allocation, i.e. executing the pipeline in place. -/// -/// The SourceIter parent trait is necessary for the specializing function to access the allocation -/// which is to be reused. But it is not sufficient for the specialization to be valid. See -/// additional bounds on the impl. #[rustc_unsafe_specialization_marker] -pub(super) trait SourceIterMarker: SourceIter {} +pub(super) trait InPlaceIterableMarker {} -// The std-internal SourceIter/InPlaceIterable traits are only implemented by chains of -// Adapter>> (all owned by core/std). Additional bounds -// on the adapter implementations (beyond `impl Trait for Adapter`) only depend on other -// traits already marked as specialization traits (Copy, TrustedRandomAccess, FusedIterator). -// I.e. the marker does not depend on lifetimes of user-supplied types. Modulo the Copy hole, which -// several other specializations already depend on. -impl SourceIterMarker for T where T: SourceIter + InPlaceIterable {} +impl InPlaceIterableMarker for T where T: InPlaceIterable {} impl SpecFromIter for Vec where - I: Iterator + SourceIterMarker, + I: Iterator + SourceIter + InPlaceIterableMarker, { default fn from_iter(mut iterator: I) -> Self { // Additional requirements which cannot expressed via trait bounds. We rely on const eval diff --git a/library/alloc/tests/btree_set_hash.rs b/library/alloc/tests/btree_set_hash.rs index e06a95ded9..ab275ac435 100644 --- a/library/alloc/tests/btree_set_hash.rs +++ b/library/alloc/tests/btree_set_hash.rs @@ -1,9 +1,8 @@ +use crate::hash; use std::collections::BTreeSet; #[test] fn test_hash() { - use crate::hash; - let mut x = BTreeSet::new(); let mut y = BTreeSet::new(); @@ -17,3 +16,14 @@ fn test_hash() { assert_eq!(hash(&x), hash(&y)); } + +#[test] +fn test_prefix_free() { + let x = BTreeSet::from([1, 2, 3]); + let y = BTreeSet::::new(); + + // If hashed by iteration alone, `(x, y)` and `(y, x)` would visit the same + // order of elements, resulting in the same hash. But now that we also hash + // the length, they get distinct sequences of hashed data. + assert_ne!(hash(&(&x, &y)), hash(&(&y, &x))); +} diff --git a/library/alloc/tests/lib.rs b/library/alloc/tests/lib.rs index 5767108d42..8c57c804ad 100644 --- a/library/alloc/tests/lib.rs +++ b/library/alloc/tests/lib.rs @@ -8,7 +8,6 @@ #![feature(new_uninit)] #![feature(pattern)] #![feature(trusted_len)] -#![feature(try_reserve)] #![feature(try_reserve_kind)] #![feature(unboxed_closures)] #![feature(associated_type_bounds)] @@ -18,7 +17,7 @@ #![feature(binary_heap_retain)] #![feature(binary_heap_as_slice)] #![feature(inplace_iteration)] -#![feature(iter_map_while)] +#![feature(iter_advance_by)] #![feature(slice_group_by)] #![feature(slice_partition_dedup)] #![feature(vec_spare_capacity)] diff --git a/library/alloc/tests/vec.rs b/library/alloc/tests/vec.rs index c2df50b48f..00a878c079 100644 --- a/library/alloc/tests/vec.rs +++ b/library/alloc/tests/vec.rs @@ -970,6 +970,24 @@ fn test_into_iter_leak() { assert_eq!(unsafe { DROPS }, 3); } +#[test] +fn test_into_iter_advance_by() { + let mut i = vec![1, 2, 3, 4, 5].into_iter(); + i.advance_by(0).unwrap(); + i.advance_back_by(0).unwrap(); + assert_eq!(i.as_slice(), [1, 2, 3, 4, 5]); + + i.advance_by(1).unwrap(); + i.advance_back_by(1).unwrap(); + assert_eq!(i.as_slice(), [2, 3, 4]); + + assert_eq!(i.advance_back_by(usize::MAX), Err(3)); + + assert_eq!(i.advance_by(usize::MAX), Err(0)); + + assert_eq!(i.len(), 0); +} + #[test] fn test_from_iter_specialization() { let src: Vec = vec![0usize; 1]; diff --git a/library/backtrace/src/symbolize/gimli.rs b/library/backtrace/src/symbolize/gimli.rs index 8e2dbc4d92..a9495cce75 100644 --- a/library/backtrace/src/symbolize/gimli.rs +++ b/library/backtrace/src/symbolize/gimli.rs @@ -177,6 +177,7 @@ cfg_if::cfg_if! { target_os = "linux", target_os = "fuchsia", target_os = "freebsd", + target_os = "openbsd", all(target_os = "android", feature = "dl_iterate_phdr"), ), not(target_env = "uclibc"), diff --git a/library/core/benches/lib.rs b/library/core/benches/lib.rs index de4ef7949f..d5e1ec083f 100644 --- a/library/core/benches/lib.rs +++ b/library/core/benches/lib.rs @@ -1,6 +1,7 @@ // wasm32 does not support benches (no time). #![cfg(not(target_arch = "wasm32"))] #![feature(flt2dec)] +#![feature(int_log)] #![feature(test)] extern crate test; @@ -15,3 +16,4 @@ mod num; mod ops; mod pattern; mod slice; +mod str; diff --git a/library/core/benches/num/int_log/mod.rs b/library/core/benches/num/int_log/mod.rs new file mode 100644 index 0000000000..6a219bcdd5 --- /dev/null +++ b/library/core/benches/num/int_log/mod.rs @@ -0,0 +1,58 @@ +use rand::Rng; +use test::{black_box, Bencher}; + +macro_rules! int_log_bench { + ($t:ty, $predictable:ident, $random:ident, $random_small:ident) => { + #[bench] + fn $predictable(bench: &mut Bencher) { + bench.iter(|| { + for n in 0..(<$t>::BITS / 8) { + for i in 1..=(100 as $t) { + let x = black_box(i << (n * 8)); + black_box(x.log10()); + } + } + }); + } + + #[bench] + fn $random(bench: &mut Bencher) { + let mut rng = rand::thread_rng(); + /* Exponentially distributed random numbers from the whole range of the type. */ + let numbers: Vec<$t> = (0..256) + .map(|_| { + let x = rng.gen::<$t>() >> rng.gen_range(0, <$t>::BITS); + if x != 0 { x } else { 1 } + }) + .collect(); + bench.iter(|| { + for x in &numbers { + black_box(black_box(x).log10()); + } + }); + } + + #[bench] + fn $random_small(bench: &mut Bencher) { + let mut rng = rand::thread_rng(); + /* Exponentially distributed random numbers from the range 0..256. */ + let numbers: Vec<$t> = (0..256) + .map(|_| { + let x = (rng.gen::() >> rng.gen_range(0, u8::BITS)) as $t; + if x != 0 { x } else { 1 } + }) + .collect(); + bench.iter(|| { + for x in &numbers { + black_box(black_box(x).log10()); + } + }); + } + }; +} + +int_log_bench! {u8, u8_log10_predictable, u8_log10_random, u8_log10_random_small} +int_log_bench! {u16, u16_log10_predictable, u16_log10_random, u16_log10_random_small} +int_log_bench! {u32, u32_log10_predictable, u32_log10_random, u32_log10_random_small} +int_log_bench! {u64, u64_log10_predictable, u64_log10_random, u64_log10_random_small} +int_log_bench! {u128, u128_log10_predictable, u128_log10_random, u128_log10_random_small} diff --git a/library/core/benches/num/mod.rs b/library/core/benches/num/mod.rs index 852d4e481e..2f9cad2725 100644 --- a/library/core/benches/num/mod.rs +++ b/library/core/benches/num/mod.rs @@ -1,5 +1,6 @@ mod dec2flt; mod flt2dec; +mod int_log; use std::str::FromStr; use test::Bencher; diff --git a/library/core/benches/str.rs b/library/core/benches/str.rs new file mode 100644 index 0000000000..1527aa0bd6 --- /dev/null +++ b/library/core/benches/str.rs @@ -0,0 +1,33 @@ +use std::str; +use test::{black_box, Bencher}; + +const LOREM_SHORT: &str = "Lorem ipsum"; + +const LOREM: &str = "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur"; + +const EMOJI: &str = "😀😃😄😁😆😅🤣😂🙂🙃😉😊😇🥰😍🤩😘😗☺😚😙🥲😋😛😜🤪😝🤑🤗🤭🤫🤔🤐🤨😐😑😶😶‍🌫️😏😒🙄😬😮‍💨🤥😌😔😪🤤😴😷🤒🤕🤢🤮🤧🥵🥶🥴😵😵‍💫🤯🤠🥳🥸😎🤓🧐😕😟🙁☹😮😯😲😳🥺😦😧😨😰😥😢😭😱😖😣😞😓😩😫🥱😤😡😠🤬😈👿💀☠💩🤡👹👺👻👽👾🤖😺😸😹😻😼😽🙀😿😾🙈🙉🙊💋💌💘💝💖💗💓💞💕💟❣💔❤️‍🔥❤️‍🩹❤🧡💛💚💙💜🤎🖤🤍💯💢💥💫💦💨🕳💣💬👁️‍🗨️🗨🗯💭💤👋🤚🖐✋🖖👌🤌🤏✌🤞🤟🤘🤙👈👉👆🖕👇☝👍👎✊👊🤛🤜👏🙌👐🤲🤝🙏✍💅🤳💪🦾🦿🦵🦶👂🦻👃🧠🫀🫁🦷🦴👀👁👅👄👶🧒👦👧🧑👱👨🧔🧔‍♂️🧔‍♀️👨‍🦰👨‍🦱👨‍🦳👨‍🦲👩👩‍🦰🧑‍🦰👩‍🦱🧑‍🦱👩‍🦳🧑‍🦳👩‍🦲🧑‍🦲👱‍♀️👱‍♂️🧓👴👵🙍🙍‍♂️🙍‍♀️🙎🙎‍♂️🙎‍♀️🙅🙅‍♂️🙅‍♀️🙆🙆‍♂️🙆‍♀️💁💁‍♂️💁‍♀️🙋🙋‍♂️🙋‍♀️🧏🧏‍♂️🧏‍♀️🙇🙇‍♂️🙇‍♀️🤦🤦‍♂️🤦‍♀️🤷🤷‍♂️🤷‍♀️🧑‍⚕️👨‍⚕️👩‍⚕️🧑‍🎓👨‍🎓👩‍🎓🧑‍🏫👨‍🏫👩‍🏫🧑‍⚖️👨‍⚖️👩‍⚖️🧑‍🌾👨‍🌾👩‍🌾🧑‍🍳👨‍🍳👩‍🍳🧑‍🔧👨‍🔧👩‍🔧🧑‍🏭👨‍🏭👩‍🏭🧑‍💼👨‍💼👩‍💼🧑‍🔬👨‍🔬👩‍🔬🧑‍💻👨‍💻👩‍💻🧑‍🎤👨‍🎤👩‍🎤🧑‍🎨👨‍🎨👩‍🎨🧑‍✈️👨‍✈️👩‍✈️🧑‍🚀👨‍🚀👩‍🚀🧑‍🚒👨‍🚒👩‍🚒👮👮‍♂️👮‍♀️🕵🕵️‍♂️🕵️‍♀️💂💂‍♂️💂‍♀️🥷👷👷‍♂️👷‍♀️🤴👸👳👳‍♂️👳‍♀️👲🧕🤵🤵‍♂️🤵‍♀️👰👰‍♂️👰‍♀️🤰🤱👩‍🍼👨‍🍼🧑‍🍼👼🎅🤶🧑‍🎄🦸🦸‍♂️🦸‍♀️🦹🦹‍♂️🦹‍♀️🧙🧙‍♂️🧙‍♀️🧚🧚‍♂️🧚‍♀️🧛🧛‍♂️🧛‍♀️🧜🧜‍♂️🧜‍♀️🧝🧝‍♂️🧝‍♀️🧞🧞‍♂️🧞‍♀️🧟🧟‍♂️🧟‍♀️💆💆‍♂️💆‍♀️💇💇‍♂️💇‍♀️🚶🚶‍♂️🚶‍♀️🧍🧍‍♂️🧍‍♀️🧎🧎‍♂️🧎‍♀️🧑‍🦯👨‍🦯👩‍🦯🧑‍🦼👨‍🦼👩‍🦼🧑‍🦽👨‍🦽👩‍🦽🏃🏃‍♂️🏃‍♀️💃🕺🕴👯👯‍♂️👯‍♀️🧖🧖‍♂️🧖‍♀️🧗🧗‍♂️🧗‍♀️🤺🏇⛷🏂🏌🏌️‍♂️🏌️‍♀️🏄🏄‍♂️🏄‍♀️🚣🚣‍♂️🚣‍♀️🏊🏊‍♂️🏊‍♀️⛹⛹️‍♂️⛹️‍♀️🏋🏋️‍♂️🏋️‍♀️🚴🚴‍♂️🚴‍♀️🚵🚵‍♂️🚵‍♀️🤸🤸‍♂️🤸‍♀️🤼🤼‍♂️🤼‍♀️🤽🤽‍♂️🤽‍♀️🤾🤾‍♂️🤾‍♀️🤹🤹‍♂️🤹‍♀️🧘🧘‍♂️🧘‍♀️🛀🛌🧑‍🤝‍🧑👭👫👬💏👩‍❤️‍💋‍👨👨‍❤️‍💋‍👨👩‍❤️‍💋‍👩💑👩‍❤️‍👨👨‍❤️‍👨👩‍❤️‍👩👪👨‍👩‍👦👨‍👩‍👧👨‍👩‍👧‍👦👨‍👩‍👦‍👦👨‍👩‍👧‍👧👨‍👨‍👦👨‍👨‍👧👨‍👨‍👧‍👦👨‍👨‍👦‍👦👨‍👨‍👧‍👧👩‍👩‍👦👩‍👩‍👧👩‍👩‍👧‍👦👩‍👩‍👦‍👦👩‍👩‍👧‍👧👨‍👦👨‍👦‍👦👨‍👧👨‍👧‍👦👨‍👧‍👧👩‍👦👩‍👦‍👦👩‍👧👩‍👧‍👦👩‍👧‍👧🗣👤👥🫂👣🦰🦱🦳🦲🐵🐒🦍🦧🐶🐕🦮🐕‍🦺🐩🐺🦊🦝🐱🐈🐈‍⬛🦁🐯🐅🐆🐴🐎🦄🦓🦌🦬🐮🐂🐃🐄🐷🐖🐗🐽🐏🐑🐐🐪🐫🦙🦒🐘🦣🦏🦛🐭🐁🐀🐹🐰🐇🐿🦫🦔🦇🐻🐻‍❄️🐨🐼🦥🦦🦨🦘🦡🐾🦃🐔🐓🐣🐤🐥🐦🐧🕊🦅🦆🦢🦉🦤🪶🦩🦚🦜🐸🐊🐢🦎🐍🐲🐉🦕🦖🐳🐋🐬🦭🐟🐠🐡🦈🐙🐚🐌🦋🐛🐜🐝🪲🐞🦗🪳🕷🕸🦂🦟🪰🪱🦠💐🌸💮🏵🌹🥀🌺🌻🌼🌷🌱🪴🌲🌳🌴🌵🌾🌿☘🍀🍁🍂🍃🍇🍈🍉🍊🍋🍌🍍🥭🍎🍏🍐🍑🍒🍓🫐🥝🍅🫒🥥🥑🍆🥔🥕🌽🌶🫑🥒🥬🥦🧄🧅🍄🥜🌰🍞🥐🥖🫓🥨🥯🥞🧇🧀🍖🍗🥩🥓🍔🍟🍕🌭🥪🌮🌯🫔🥙🧆🥚🍳🥘🍲🫕🥣🥗🍿🧈🧂🥫🍱🍘🍙🍚🍛🍜🍝🍠🍢🍣🍤🍥🥮🍡🥟🥠🥡🦀🦞🦐🦑🦪🍦🍧🍨🍩🍪🎂🍰🧁🥧🍫🍬🍭🍮🍯🍼🥛☕🫖🍵🍶🍾🍷🍸🍹🍺🍻🥂🥃🥤🧋🧃🧉🧊🥢🍽🍴🥄🔪🏺🌍🌎🌏🌐🗺🗾🧭🏔⛰🌋🗻🏕🏖🏜🏝🏞🏟🏛🏗🧱🪨🪵🛖🏘🏚🏠🏡🏢🏣🏤🏥🏦🏨🏩🏪🏫🏬🏭🏯🏰💒🗼🗽⛪🕌🛕🕍⛩🕋⛲⛺🌁🌃🏙🌄🌅🌆🌇🌉♨🎠🎡🎢💈🎪🚂🚃🚄🚅🚆🚇🚈🚉🚊🚝🚞🚋🚌🚍🚎🚐🚑🚒🚓🚔🚕🚖🚗🚘🚙🛻🚚🚛🚜🏎🏍🛵🦽🦼🛺🚲🛴🛹🛼🚏🛣🛤🛢⛽🚨🚥🚦🛑🚧⚓⛵🛶🚤🛳⛴🛥🚢✈🛩🛫🛬🪂💺🚁🚟🚠🚡🛰🚀🛸🛎🧳⌛⏳⌚⏰⏱⏲🕰🕛🕧🕐🕜🕑🕝🕒🕞🕓🕟🕔🕠🕕🕡🕖🕢🕗🕣🕘🕤🕙🕥🕚🕦🌑🌒🌓🌔🌕🌖🌗🌘🌙🌚🌛🌜🌡☀🌝🌞🪐⭐🌟🌠🌌☁⛅⛈🌤🌥🌦🌧🌨🌩🌪🌫🌬🌀🌈🌂☂☔⛱⚡❄☃⛄☄🔥💧🌊🎃🎄🎆🎇🧨✨🎈🎉🎊🎋🎍🎎🎏🎐🎑🧧🎀🎁🎗🎟🎫🎖🏆🏅🥇🥈🥉⚽⚾🥎🏀🏐🏈🏉🎾🥏🎳🏏🏑🏒🥍🏓🏸🥊🥋🥅⛳⛸🎣🤿🎽🎿🛷🥌🎯🪀🪁🎱🔮🪄🧿🎮🕹🎰🎲🧩🧸🪅🪆♠♥♦♣♟🃏🀄🎴🎭🖼🎨🧵🪡🧶🪢👓🕶🥽🥼🦺👔👕👖🧣🧤🧥🧦👗👘🥻🩱🩲🩳👙👚👛👜👝🛍🎒🩴👞👟🥾🥿👠👡🩰👢👑👒🎩🎓🧢🪖⛑📿💄💍💎🔇🔈🔉🔊📢📣📯🔔🔕🎼🎵🎶🎙🎚🎛🎤🎧📻🎷🪗🎸🎹🎺🎻🪕🥁"; + +#[bench] +fn str_char_count_lorem(b: &mut Bencher) { + b.iter(|| black_box(LOREM).chars().count()); +} + +#[bench] +fn str_char_count_lorem_short(b: &mut Bencher) { + b.iter(|| black_box(LOREM_SHORT).chars().count()); +} + +#[bench] +fn str_char_count_emoji(b: &mut Bencher) { + b.iter(|| black_box(EMOJI).chars().count()); +} + +#[bench] +fn str_validate_emoji(b: &mut Bencher) { + b.iter(|| str::from_utf8(black_box(EMOJI.as_bytes()))); +} diff --git a/library/core/primitive_docs/box_into_raw.md b/library/core/primitive_docs/box_into_raw.md new file mode 100644 index 0000000000..9dd0344c7c --- /dev/null +++ b/library/core/primitive_docs/box_into_raw.md @@ -0,0 +1 @@ +../std/boxed/struct.Box.html#method.into_raw diff --git a/library/core/primitive_docs/fs_file.md b/library/core/primitive_docs/fs_file.md new file mode 100644 index 0000000000..4023e340a5 --- /dev/null +++ b/library/core/primitive_docs/fs_file.md @@ -0,0 +1 @@ +../std/fs/struct.File.html diff --git a/library/core/primitive_docs/io_bufread.md b/library/core/primitive_docs/io_bufread.md new file mode 100644 index 0000000000..7beda2cd39 --- /dev/null +++ b/library/core/primitive_docs/io_bufread.md @@ -0,0 +1 @@ +../std/io/trait.BufRead.html diff --git a/library/core/primitive_docs/io_read.md b/library/core/primitive_docs/io_read.md new file mode 100644 index 0000000000..b7ecf5e273 --- /dev/null +++ b/library/core/primitive_docs/io_read.md @@ -0,0 +1 @@ +../std/io/trait.Read.html diff --git a/library/core/primitive_docs/io_seek.md b/library/core/primitive_docs/io_seek.md new file mode 100644 index 0000000000..db0274d291 --- /dev/null +++ b/library/core/primitive_docs/io_seek.md @@ -0,0 +1 @@ +../std/io/trait.Seek.html diff --git a/library/core/primitive_docs/io_write.md b/library/core/primitive_docs/io_write.md new file mode 100644 index 0000000000..92a3b88a79 --- /dev/null +++ b/library/core/primitive_docs/io_write.md @@ -0,0 +1 @@ +../std/io/trait.Write.html diff --git a/library/core/primitive_docs/net_tosocketaddrs.md b/library/core/primitive_docs/net_tosocketaddrs.md new file mode 100644 index 0000000000..4daa10ddbe --- /dev/null +++ b/library/core/primitive_docs/net_tosocketaddrs.md @@ -0,0 +1 @@ +../std/net/trait.ToSocketAddrs.html diff --git a/library/core/primitive_docs/process_exit.md b/library/core/primitive_docs/process_exit.md new file mode 100644 index 0000000000..cae34d12d5 --- /dev/null +++ b/library/core/primitive_docs/process_exit.md @@ -0,0 +1 @@ +../std/process/fn.exit.html diff --git a/library/core/primitive_docs/string_string.md b/library/core/primitive_docs/string_string.md new file mode 100644 index 0000000000..303dc07b18 --- /dev/null +++ b/library/core/primitive_docs/string_string.md @@ -0,0 +1 @@ +../std/string/struct.String.html diff --git a/library/core/src/alloc/layout.rs b/library/core/src/alloc/layout.rs index ccf6e420de..780f82d8af 100644 --- a/library/core/src/alloc/layout.rs +++ b/library/core/src/alloc/layout.rs @@ -94,6 +94,7 @@ impl Layout { /// [`Layout::from_size_align`]. #[stable(feature = "alloc_layout", since = "1.28.0")] #[rustc_const_stable(feature = "alloc_layout", since = "1.36.0")] + #[must_use] #[inline] pub const unsafe fn from_size_align_unchecked(size: usize, align: usize) -> Self { // SAFETY: the caller must ensure that `align` is greater than zero. @@ -111,6 +112,8 @@ impl Layout { /// The minimum byte alignment 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 = "this returns the minimum alignment, \ + without modifying the layout"] #[inline] pub const fn align(&self) -> usize { self.align_.get() @@ -119,6 +122,7 @@ impl Layout { /// Constructs a `Layout` suitable for holding a value of type `T`. #[stable(feature = "alloc_layout", since = "1.28.0")] #[rustc_const_stable(feature = "alloc_layout_const_new", since = "1.42.0")] + #[must_use] #[inline] pub const fn new() -> Self { let (size, align) = size_align::(); @@ -227,6 +231,8 @@ impl Layout { /// satisfy this constraint is to ensure `align <= self.align()`. #[unstable(feature = "alloc_layout_extra", issue = "55724")] #[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")] + #[must_use = "this returns the padding needed, \ + without modifying the `Layout`"] #[inline] pub const fn padding_needed_for(&self, align: usize) -> usize { let len = self.size(); @@ -260,6 +266,8 @@ impl Layout { /// This is equivalent to adding the result of `padding_needed_for` /// to the layout's current size. #[stable(feature = "alloc_layout_manipulation", since = "1.44.0")] + #[must_use = "this returns a new `Layout`, \ + without modifying the original"] #[inline] pub fn pad_to_align(&self) -> Layout { let pad = self.padding_needed_for(self.align()); diff --git a/library/core/src/array/iter.rs b/library/core/src/array/iter.rs index 4a77fe3581..5d63cf03fc 100644 --- a/library/core/src/array/iter.rs +++ b/library/core/src/array/iter.rs @@ -10,7 +10,7 @@ use crate::{ /// A by-value [array] iterator. #[stable(feature = "array_value_iter", since = "1.51.0")] -#[cfg_attr(not(bootstrap), rustc_insignificant_dtor)] +#[rustc_insignificant_dtor] pub struct IntoIter { /// This is the array we are iterating over. /// @@ -135,19 +135,12 @@ impl Iterator for IntoIter { Fold: FnMut(Acc, Self::Item) -> Acc, { let data = &mut self.data; - // FIXME: This uses try_fold(&mut iter) instead of fold(iter) because the latter - // would go through the blanket `impl Iterator for &mut I` implementation - // which lacks inline annotations on its methods and adding those would be a larger - // perturbation than using try_fold here. - // Whether it would be beneficial to add those annotations should be investigated separately. - (&mut self.alive) - .try_fold::<_, _, Result<_, !>>(init, |acc, idx| { - // SAFETY: idx is obtained by folding over the `alive` range, which implies the - // value is currently considered alive but as the range is being consumed each value - // we read here will only be read once and then considered dead. - Ok(fold(acc, unsafe { data.get_unchecked(idx).assume_init_read() })) - }) - .unwrap() + self.alive.by_ref().fold(init, |acc, idx| { + // SAFETY: idx is obtained by folding over the `alive` range, which implies the + // value is currently considered alive but as the range is being consumed each value + // we read here will only be read once and then considered dead. + fold(acc, unsafe { data.get_unchecked(idx).assume_init_read() }) + }) } fn count(self) -> usize { diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs index 70cccd31b9..8d5c051040 100644 --- a/library/core/src/array/mod.rs +++ b/library/core/src/array/mod.rs @@ -20,6 +20,69 @@ mod iter; #[stable(feature = "array_value_iter", since = "1.51.0")] pub use iter::IntoIter; +/// Creates an array `[T; N]` where each array element `T` is returned by the `cb` call. +/// +/// # Arguments +/// +/// * `cb`: Callback where the passed argument is the current array index. +/// +/// # Example +/// +/// ```rust +/// #![feature(array_from_fn)] +/// +/// let array = core::array::from_fn(|i| i); +/// assert_eq!(array, [0, 1, 2, 3, 4]); +/// ``` +#[inline] +#[unstable(feature = "array_from_fn", issue = "89379")] +pub fn from_fn(mut cb: F) -> [T; N] +where + F: FnMut(usize) -> T, +{ + let mut idx = 0; + [(); N].map(|_| { + let res = cb(idx); + idx += 1; + res + }) +} + +/// Creates an array `[T; N]` where each fallible array element `T` is returned by the `cb` call. +/// Unlike `core::array::from_fn`, where the element creation can't fail, this version will return an error +/// if any element creation was unsuccessful. +/// +/// # Arguments +/// +/// * `cb`: Callback where the passed argument is the current array index. +/// +/// # Example +/// +/// ```rust +/// #![feature(array_from_fn)] +/// +/// #[derive(Debug, PartialEq)] +/// enum SomeError { +/// Foo, +/// } +/// +/// let array = core::array::try_from_fn(|i| Ok::<_, SomeError>(i)); +/// assert_eq!(array, Ok([0, 1, 2, 3, 4])); +/// +/// let another_array = core::array::try_from_fn::(|_| Err(SomeError::Foo)); +/// assert_eq!(another_array, Err(SomeError::Foo)); +/// ``` +#[inline] +#[unstable(feature = "array_from_fn", issue = "89379")] +pub fn try_from_fn(cb: F) -> Result<[T; N], E> +where + F: FnMut(usize) -> Result, +{ + // SAFETY: we know for certain that this iterator will yield exactly `N` + // items. + unsafe { collect_into_array_rslt_unchecked(&mut (0..N).map(cb)) } +} + /// 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] { @@ -368,14 +431,14 @@ impl [T; N] { } /// Returns a slice containing the entire array. Equivalent to `&s[..]`. - #[unstable(feature = "array_methods", issue = "76118")] - pub fn as_slice(&self) -> &[T] { + #[stable(feature = "array_as_slice", since = "1.57.0")] + pub const fn as_slice(&self) -> &[T] { self } /// Returns a mutable slice containing the entire array. Equivalent to /// `&mut s[..]`. - #[unstable(feature = "array_methods", issue = "76118")] + #[stable(feature = "array_as_slice", since = "1.57.0")] pub fn as_mut_slice(&mut self) -> &mut [T] { self } @@ -396,7 +459,7 @@ impl [T; N] { /// /// This method is particularly useful if combined with other methods, like /// [`map`](#method.map). This way, you can avoid moving the original - /// array if its elements are not `Copy`. + /// array if its elements are not [`Copy`]. /// /// ``` /// #![feature(array_methods)] @@ -448,13 +511,15 @@ impl [T; N] { /// /// It is up to the caller to guarantee that `iter` yields at least `N` items. /// Violating this condition causes undefined behavior. -unsafe fn collect_into_array_unchecked(iter: &mut I) -> [I::Item; N] +unsafe fn collect_into_array_rslt_unchecked( + iter: &mut I, +) -> Result<[T; N], E> where // Note: `TrustedLen` here is somewhat of an experiment. This is just an // internal function, so feel free to remove if this bound turns out to be a // bad idea. In that case, remember to also remove the lower bound // `debug_assert!` below! - I: Iterator + TrustedLen, + I: Iterator> + TrustedLen, { debug_assert!(N <= iter.size_hint().1.unwrap_or(usize::MAX)); debug_assert!(N <= iter.size_hint().0); @@ -463,6 +528,21 @@ where unsafe { collect_into_array(iter).unwrap_unchecked() } } +// Infallible version of `collect_into_array_rslt_unchecked`. +unsafe fn collect_into_array_unchecked(iter: &mut I) -> [I::Item; N] +where + I: Iterator + TrustedLen, +{ + let mut map = iter.map(Ok::<_, Infallible>); + + // SAFETY: The same safety considerations w.r.t. the iterator length + // apply for `collect_into_array_rslt_unchecked` as for + // `collect_into_array_unchecked` + match unsafe { collect_into_array_rslt_unchecked(&mut map) } { + Ok(array) => array, + } +} + /// Pulls `N` items from `iter` and returns them as an array. If the iterator /// yields fewer than `N` items, `None` is returned and all already yielded /// items are dropped. @@ -473,43 +553,49 @@ where /// /// If `iter.next()` panicks, all items already yielded by the iterator are /// dropped. -fn collect_into_array(iter: &mut I) -> Option<[I::Item; N]> +fn collect_into_array(iter: &mut I) -> Option> where - I: Iterator, + I: Iterator>, { if N == 0 { // SAFETY: An empty array is always inhabited and has no validity invariants. - return unsafe { Some(mem::zeroed()) }; + return unsafe { Some(Ok(mem::zeroed())) }; } - struct Guard { - ptr: *mut T, + struct Guard<'a, T, const N: usize> { + array_mut: &'a mut [MaybeUninit; N], initialized: usize, } - impl Drop for Guard { + impl Drop for Guard<'_, T, N> { fn drop(&mut self) { debug_assert!(self.initialized <= N); - let initialized_part = crate::ptr::slice_from_raw_parts_mut(self.ptr, self.initialized); - - // SAFETY: this raw slice will contain only initialized objects. + // SAFETY: this slice will contain only initialized objects. unsafe { - crate::ptr::drop_in_place(initialized_part); + crate::ptr::drop_in_place(MaybeUninit::slice_assume_init_mut( + &mut self.array_mut.get_unchecked_mut(..self.initialized), + )); } } } let mut array = MaybeUninit::uninit_array::(); - let mut guard: Guard<_, N> = - Guard { ptr: MaybeUninit::slice_as_mut_ptr(&mut array), initialized: 0 }; + let mut guard = Guard { array_mut: &mut array, initialized: 0 }; + + while let Some(item_rslt) = iter.next() { + let item = match item_rslt { + Err(err) => { + return Some(Err(err)); + } + Ok(elem) => elem, + }; - while let Some(item) = iter.next() { // SAFETY: `guard.initialized` starts at 0, is increased by one in the // loop and the loop is aborted once it reaches N (which is // `array.len()`). unsafe { - array.get_unchecked_mut(guard.initialized).write(item); + guard.array_mut.get_unchecked_mut(guard.initialized).write(item); } guard.initialized += 1; @@ -520,7 +606,7 @@ where // SAFETY: the condition above asserts that all elements are // initialized. let out = unsafe { MaybeUninit::array_assume_init(array) }; - return Some(out); + return Some(Ok(out)); } } diff --git a/library/core/src/ascii.rs b/library/core/src/ascii.rs index 4780d8dc78..0a456ee1eb 100644 --- a/library/core/src/ascii.rs +++ b/library/core/src/ascii.rs @@ -21,7 +21,7 @@ use crate::str::from_utf8_unchecked; #[stable(feature = "rust1", since = "1.0.0")] #[derive(Clone)] pub struct EscapeDefault { - range: Range, + range: Range, data: [u8; 4], } @@ -114,7 +114,7 @@ pub fn escape_default(c: u8) -> EscapeDefault { impl Iterator for EscapeDefault { type Item = u8; fn next(&mut self) -> Option { - self.range.next().map(|i| self.data[i]) + self.range.next().map(|i| self.data[i as usize]) } fn size_hint(&self) -> (usize, Option) { self.range.size_hint() @@ -126,7 +126,7 @@ impl Iterator for EscapeDefault { #[stable(feature = "rust1", since = "1.0.0")] impl DoubleEndedIterator for EscapeDefault { fn next_back(&mut self) -> Option { - self.range.next_back().map(|i| self.data[i]) + self.range.next_back().map(|i| self.data[i as usize]) } } #[stable(feature = "rust1", since = "1.0.0")] @@ -138,7 +138,9 @@ impl FusedIterator for EscapeDefault {} impl fmt::Display for EscapeDefault { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { // SAFETY: ok because `escape_default` created only valid utf-8 data - f.write_str(unsafe { from_utf8_unchecked(&self.data[self.range.clone()]) }) + f.write_str(unsafe { + from_utf8_unchecked(&self.data[(self.range.start as usize)..(self.range.end as usize)]) + }) } } diff --git a/library/core/src/bool.rs b/library/core/src/bool.rs index dcafaae2f5..f14c2a4641 100644 --- a/library/core/src/bool.rs +++ b/library/core/src/bool.rs @@ -2,7 +2,8 @@ #[lang = "bool"] impl bool { - /// Returns `Some(t)` if the `bool` is `true`, or `None` otherwise. + /// Returns `Some(t)` if the `bool` is [`true`](../std/keyword.true.html), + /// or `None` otherwise. /// /// # Examples /// @@ -18,7 +19,8 @@ impl bool { if self { Some(t) } else { None } } - /// Returns `Some(f())` if the `bool` is `true`, or `None` otherwise. + /// Returns `Some(f())` if the `bool` is [`true`](../std/keyword.true.html), + /// or `None` otherwise. /// /// # Examples /// diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index 2adf6a549e..2ca077a98f 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -349,7 +349,7 @@ impl Cell { drop(old); } - /// Swaps the values of two Cells. + /// Swaps the values of two `Cell`s. /// Difference with `std::mem::swap` is that this function doesn't require `&mut` reference. /// /// # Examples @@ -1303,6 +1303,11 @@ impl Clone for BorrowRef<'_> { /// /// See the [module-level documentation](self) for more. #[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr( + not(bootstrap), + must_not_suspend = "holding a Ref across suspend \ + points can cause BorrowErrors" +)] pub struct Ref<'b, T: ?Sized + 'b> { value: &'b T, borrow: BorrowRef<'b>, @@ -1679,6 +1684,11 @@ impl<'b> BorrowRefMut<'b> { /// /// See the [module-level documentation](self) for more. #[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr( + not(bootstrap), + must_not_suspend = "holding a RefMut across suspend \ + points can cause BorrowErrors" +)] pub struct RefMut<'b, T: ?Sized + 'b> { value: &'b mut T, borrow: BorrowRefMut<'b>, @@ -1916,7 +1926,8 @@ impl UnsafeCell { /// ``` #[inline(always)] #[stable(feature = "unsafe_cell_get_mut", since = "1.50.0")] - pub fn get_mut(&mut self) -> &mut T { + #[rustc_const_unstable(feature = "const_unsafecell_get_mut", issue = "88836")] + pub const fn get_mut(&mut self) -> &mut T { &mut self.value } diff --git a/library/core/src/char/convert.rs b/library/core/src/char/convert.rs index 7a0ec32cc6..72921414fb 100644 --- a/library/core/src/char/convert.rs +++ b/library/core/src/char/convert.rs @@ -48,6 +48,7 @@ use super::MAX; /// assert_eq!(None, c); /// ``` #[doc(alias = "chr")] +#[must_use] #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn from_u32(i: u32) -> Option { @@ -88,6 +89,7 @@ pub fn from_u32(i: u32) -> Option { /// assert_eq!('❤', c); /// ``` #[inline] +#[must_use] #[stable(feature = "char_from_unchecked", since = "1.5.0")] pub unsafe fn from_u32_unchecked(i: u32) -> char { // SAFETY: the caller must guarantee that `i` is a valid char value. @@ -319,6 +321,7 @@ impl fmt::Display for CharTryFromError { /// let c = char::from_digit(1, 37); /// ``` #[inline] +#[must_use] #[stable(feature = "rust1", since = "1.0.0")] pub fn from_digit(num: u32, radix: u32) -> Option { if radix > 36 { diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs index 0dadbdd1bd..3c4972bd3c 100644 --- a/library/core/src/char/methods.rs +++ b/library/core/src/char/methods.rs @@ -24,7 +24,7 @@ impl char { /// decoding error. /// /// It can occur, for example, when giving ill-formed UTF-8 bytes to - /// [`String::from_utf8_lossy`](string/struct.String.html#method.from_utf8_lossy). + /// [`String::from_utf8_lossy`](../std/string/struct.String.html#method.from_utf8_lossy). #[stable(feature = "assoc_char_consts", since = "1.52.0")] pub const REPLACEMENT_CHARACTER: char = '\u{FFFD}'; @@ -96,7 +96,7 @@ impl char { /// Converts a `u32` to a `char`. /// /// Note that all `char`s are valid [`u32`]s, and can be cast to one with - /// `as`: + /// [`as`](../std/keyword.as.html): /// /// ``` /// let c = '💯'; @@ -136,6 +136,7 @@ impl char { /// assert_eq!(None, c); /// ``` #[stable(feature = "assoc_char_funcs", since = "1.52.0")] + #[must_use] #[inline] pub fn from_u32(i: u32) -> Option { super::convert::from_u32(i) @@ -177,6 +178,7 @@ impl char { /// assert_eq!('❤', c); /// ``` #[stable(feature = "assoc_char_funcs", since = "1.52.0")] + #[must_use] #[inline] pub unsafe fn from_u32_unchecked(i: u32) -> char { // SAFETY: the safety contract must be upheld by the caller. @@ -230,9 +232,10 @@ impl char { /// use std::char; /// /// // this panics - /// char::from_digit(1, 37); + /// let _c = char::from_digit(1, 37); /// ``` #[stable(feature = "assoc_char_funcs", since = "1.52.0")] + #[must_use] #[inline] pub fn from_digit(num: u32, radix: u32) -> Option { super::convert::from_digit(num, radix) @@ -325,9 +328,11 @@ impl char { /// /// ```should_panic /// // this panics - /// '1'.to_digit(37); + /// let _ = '1'.to_digit(37); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[inline] pub fn to_digit(self, radix: u32) -> Option { assert!(radix <= 36, "to_digit: radix is too high (maximum 36)"); @@ -372,11 +377,13 @@ impl char { /// println!("\\u{{2764}}"); /// ``` /// - /// Using `to_string`: + /// Using [`to_string`](../std/string/trait.ToString.html#tymethod.to_string): /// /// ``` /// assert_eq!('❤'.escape_unicode().to_string(), "\\u{2764}"); /// ``` + #[must_use = "this returns the escaped char as an iterator, \ + without modifying the original"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn escape_unicode(self) -> EscapeUnicode { @@ -422,7 +429,7 @@ impl char { /// Returns an iterator that yields the literal escape code of a character /// as `char`s. /// - /// This will escape the characters similar to the `Debug` implementations + /// This will escape the characters similar to the [`Debug`](core::fmt::Debug) implementations /// of `str` or `char`. /// /// # Examples @@ -448,11 +455,13 @@ impl char { /// println!("\\n"); /// ``` /// - /// Using `to_string`: + /// Using [`to_string`](../std/string/trait.ToString.html#tymethod.to_string): /// /// ``` /// assert_eq!('\n'.escape_debug().to_string(), "\\n"); /// ``` + #[must_use = "this returns the escaped char as an iterator, \ + without modifying the original"] #[stable(feature = "char_escape_debug", since = "1.20.0")] #[inline] pub fn escape_debug(self) -> EscapeDebug { @@ -502,11 +511,13 @@ impl char { /// println!("\\\""); /// ``` /// - /// Using `to_string`: + /// Using [`to_string`](../std/string/trait.ToString.html#tymethod.to_string): /// /// ``` /// assert_eq!('"'.escape_default().to_string(), "\\\""); /// ``` + #[must_use = "this returns the escaped char as an iterator, \ + without modifying the original"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn escape_default(self) -> EscapeDefault { @@ -692,6 +703,7 @@ impl char { /// // love is many things, but it is not alphabetic /// assert!(!c.is_alphabetic()); /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn is_alphabetic(self) -> bool { @@ -724,6 +736,7 @@ impl char { /// assert!(!'中'.is_lowercase()); /// assert!(!' '.is_lowercase()); /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn is_lowercase(self) -> bool { @@ -756,6 +769,7 @@ impl char { /// assert!(!'中'.is_uppercase()); /// assert!(!' '.is_uppercase()); /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn is_uppercase(self) -> bool { @@ -784,6 +798,7 @@ impl char { /// /// assert!(!'越'.is_whitespace()); /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn is_whitespace(self) -> bool { @@ -812,6 +827,7 @@ impl char { /// assert!('و'.is_alphanumeric()); /// assert!('藏'.is_alphanumeric()); /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn is_alphanumeric(self) -> bool { @@ -837,6 +853,7 @@ impl char { /// assert!('œ'.is_control()); /// assert!(!'q'.is_control()); /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn is_control(self) -> bool { @@ -852,6 +869,7 @@ impl char { /// [uax29]: https://www.unicode.org/reports/tr29/ /// [ucd]: https://www.unicode.org/reports/tr44/ /// [`DerivedCoreProperties.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/DerivedCoreProperties.txt + #[must_use] #[inline] pub(crate) fn is_grapheme_extended(self) -> bool { unicode::Grapheme_Extend(self) @@ -881,6 +899,7 @@ impl char { /// assert!(!'و'.is_numeric()); /// assert!(!'藏'.is_numeric()); /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn is_numeric(self) -> bool { @@ -937,7 +956,7 @@ impl char { /// println!("i\u{307}"); /// ``` /// - /// Using `to_string`: + /// Using [`to_string`](../std/string/trait.ToString.html#tymethod.to_string): /// /// ``` /// assert_eq!('C'.to_lowercase().to_string(), "c"); @@ -949,6 +968,8 @@ impl char { /// // convert into themselves. /// assert_eq!('山'.to_lowercase().to_string(), "山"); /// ``` + #[must_use = "this returns the lowercase character as a new iterator, \ + without modifying the original"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn to_lowercase(self) -> ToLowercase { @@ -1002,7 +1023,7 @@ impl char { /// println!("SS"); /// ``` /// - /// Using `to_string`: + /// Using [`to_string`](../std/string/trait.ToString.html#tymethod.to_string): /// /// ``` /// assert_eq!('c'.to_uppercase().to_string(), "C"); @@ -1039,6 +1060,8 @@ impl char { /// ``` /// /// holds across languages. + #[must_use = "this returns the uppercase character as a new iterator, \ + without modifying the original"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn to_uppercase(self) -> ToUppercase { @@ -1056,6 +1079,7 @@ impl char { /// assert!(ascii.is_ascii()); /// assert!(!non_ascii.is_ascii()); /// ``` + #[must_use] #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] #[rustc_const_stable(feature = "const_ascii_methods_on_intrinsics", since = "1.32.0")] #[inline] @@ -1085,6 +1109,7 @@ impl char { /// /// [`make_ascii_uppercase()`]: #method.make_ascii_uppercase /// [`to_uppercase()`]: #method.to_uppercase + #[must_use = "to uppercase the value in-place, use `make_ascii_uppercase()`"] #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] #[rustc_const_stable(feature = "const_ascii_methods_on_intrinsics", since = "1.52.0")] #[inline] @@ -1118,6 +1143,7 @@ impl char { /// /// [`make_ascii_lowercase()`]: #method.make_ascii_lowercase /// [`to_lowercase()`]: #method.to_lowercase + #[must_use = "to lowercase the value in-place, use `make_ascii_lowercase()`"] #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] #[rustc_const_stable(feature = "const_ascii_methods_on_intrinsics", since = "1.52.0")] #[inline] @@ -1131,7 +1157,7 @@ impl char { /// Checks that two values are an ASCII case-insensitive match. /// - /// Equivalent to `to_ascii_lowercase(a) == to_ascii_lowercase(b)`. + /// Equivalent to [to_ascii_lowercase]\(a) == [to_ascii_lowercase]\(b). /// /// # Examples /// @@ -1144,6 +1170,8 @@ impl char { /// assert!(upper_a.eq_ignore_ascii_case(&upper_a)); /// assert!(!upper_a.eq_ignore_ascii_case(&lower_z)); /// ``` + /// + /// [to_ascii_lowercase]: #method.to_ascii_lowercase #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] #[rustc_const_stable(feature = "const_ascii_methods_on_intrinsics", since = "1.52.0")] #[inline] @@ -1229,6 +1257,7 @@ impl char { /// assert!(!lf.is_ascii_alphabetic()); /// assert!(!esc.is_ascii_alphabetic()); /// ``` + #[must_use] #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")] #[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")] #[inline] @@ -1262,6 +1291,7 @@ impl char { /// assert!(!lf.is_ascii_uppercase()); /// assert!(!esc.is_ascii_uppercase()); /// ``` + #[must_use] #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")] #[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")] #[inline] @@ -1295,6 +1325,7 @@ impl char { /// assert!(!lf.is_ascii_lowercase()); /// assert!(!esc.is_ascii_lowercase()); /// ``` + #[must_use] #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")] #[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")] #[inline] @@ -1331,6 +1362,7 @@ impl char { /// assert!(!lf.is_ascii_alphanumeric()); /// assert!(!esc.is_ascii_alphanumeric()); /// ``` + #[must_use] #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")] #[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")] #[inline] @@ -1364,6 +1396,7 @@ impl char { /// assert!(!lf.is_ascii_digit()); /// assert!(!esc.is_ascii_digit()); /// ``` + #[must_use] #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")] #[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")] #[inline] @@ -1400,6 +1433,7 @@ impl char { /// assert!(!lf.is_ascii_hexdigit()); /// assert!(!esc.is_ascii_hexdigit()); /// ``` + #[must_use] #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")] #[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")] #[inline] @@ -1437,6 +1471,7 @@ impl char { /// assert!(!lf.is_ascii_punctuation()); /// assert!(!esc.is_ascii_punctuation()); /// ``` + #[must_use] #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")] #[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")] #[inline] @@ -1470,6 +1505,7 @@ impl char { /// assert!(!lf.is_ascii_graphic()); /// assert!(!esc.is_ascii_graphic()); /// ``` + #[must_use] #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")] #[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")] #[inline] @@ -1520,6 +1556,7 @@ impl char { /// assert!(lf.is_ascii_whitespace()); /// assert!(!esc.is_ascii_whitespace()); /// ``` + #[must_use] #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")] #[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")] #[inline] @@ -1555,6 +1592,7 @@ impl char { /// assert!(lf.is_ascii_control()); /// assert!(esc.is_ascii_control()); /// ``` + #[must_use] #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")] #[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")] #[inline] diff --git a/library/core/src/clone.rs b/library/core/src/clone.rs index 19faf9cdda..b02333b028 100644 --- a/library/core/src/clone.rs +++ b/library/core/src/clone.rs @@ -105,6 +105,7 @@ #[stable(feature = "rust1", since = "1.0.0")] #[lang = "clone"] #[rustc_diagnostic_item = "Clone"] +#[cfg_attr(not(bootstrap), rustc_trivial_field_reads)] pub trait Clone: Sized { /// Returns a copy of the value. /// diff --git a/library/core/src/cmp.rs b/library/core/src/cmp.rs index 4e82b65539..7456f886ea 100644 --- a/library/core/src/cmp.rs +++ b/library/core/src/cmp.rs @@ -203,6 +203,7 @@ use self::Ordering::*; message = "can't compare `{Self}` with `{Rhs}`", label = "no implementation for `{Self} == {Rhs}`" )] +#[rustc_diagnostic_item = "PartialEq"] pub trait PartialEq { /// This method tests for `self` and `other` values to be equal, and is used /// by `==`. @@ -269,6 +270,7 @@ pub macro PartialEq($item:item) { #[doc(alias = "==")] #[doc(alias = "!=")] #[stable(feature = "rust1", since = "1.0.0")] +#[rustc_diagnostic_item = "Eq"] pub trait Eq: PartialEq { // this method is used solely by #[deriving] to assert // that every component of a type implements #[deriving] @@ -321,6 +323,7 @@ pub struct AssertParamIsEq { /// ``` #[derive(Clone, Copy, PartialEq, Debug, Hash)] #[stable(feature = "rust1", since = "1.0.0")] +#[repr(i8)] pub enum Ordering { /// An ordering where a compared value is less than another. #[stable(feature = "rust1", since = "1.0.0")] @@ -728,6 +731,7 @@ impl Clone for Reverse { #[doc(alias = "<=")] #[doc(alias = ">=")] #[stable(feature = "rust1", since = "1.0.0")] +#[rustc_diagnostic_item = "Ord"] pub trait Ord: Eq + PartialOrd { /// This method returns an [`Ordering`] between `self` and `other`. /// @@ -984,6 +988,7 @@ impl PartialOrd for Ordering { message = "can't compare `{Self}` with `{Rhs}`", label = "no implementation for `{Self} < {Rhs}` and `{Self} > {Rhs}`" )] +#[rustc_diagnostic_item = "PartialOrd"] pub trait PartialOrd: PartialEq { /// This method returns an ordering between `self` and `other` values if one exists. /// diff --git a/library/core/src/convert/mod.rs b/library/core/src/convert/mod.rs index 1e512af480..fb8305273a 100644 --- a/library/core/src/convert/mod.rs +++ b/library/core/src/convert/mod.rs @@ -269,10 +269,11 @@ pub trait AsMut { /// /// [`String`]: ../../std/string/struct.String.html /// [`Vec`]: ../../std/vec/struct.Vec.html -#[rustc_diagnostic_item = "into_trait"] +#[rustc_diagnostic_item = "Into"] #[stable(feature = "rust1", since = "1.0.0")] pub trait Into: Sized { /// Performs the conversion. + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] fn into(self) -> T; } @@ -358,7 +359,7 @@ pub trait Into: Sized { /// [`String`]: ../../std/string/struct.String.html /// [`from`]: From::from /// [book]: ../../book/ch09-00-error-handling.html -#[rustc_diagnostic_item = "from_trait"] +#[rustc_diagnostic_item = "From"] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_on_unimplemented(on( all(_Self = "&str", T = "std::string::String"), @@ -367,6 +368,7 @@ pub trait Into: Sized { pub trait From: Sized { /// Performs the conversion. #[lang = "from"] + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] fn from(_: T) -> Self; } @@ -385,7 +387,7 @@ pub trait From: Sized { /// /// This suffers the same restrictions and reasoning as implementing /// [`Into`], see there for details. -#[rustc_diagnostic_item = "try_into_trait"] +#[rustc_diagnostic_item = "TryInto"] #[stable(feature = "try_from", since = "1.34.0")] pub trait TryInto: Sized { /// The type returned in the event of a conversion error. @@ -465,7 +467,7 @@ pub trait TryInto: Sized { /// ``` /// /// [`try_from`]: TryFrom::try_from -#[rustc_diagnostic_item = "try_from_trait"] +#[rustc_diagnostic_item = "TryFrom"] #[stable(feature = "try_from", since = "1.34.0")] pub trait TryFrom: Sized { /// The type returned in the event of a conversion error. @@ -662,7 +664,7 @@ impl AsMut for str { /// /// However there is one case where `!` syntax can be used /// before `!` is stabilized as a full-fledged type: in the position of a function’s return type. -/// Specifically, it is possible implementations for two different function pointer types: +/// Specifically, it is possible to have implementations for two different function pointer types: /// /// ``` /// trait MyTrait {} diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs index aff789f2af..b8ad7720e0 100644 --- a/library/core/src/fmt/mod.rs +++ b/library/core/src/fmt/mod.rs @@ -265,6 +265,27 @@ pub struct ArgumentV1<'a> { formatter: fn(&Opaque, &mut Formatter<'_>) -> Result, } +/// This struct represents the unsafety of constructing an `Arguments`. +/// It exists, rather than an unsafe function, in order to simplify the expansion +/// of `format_args!(..)` and reduce the scope of the `unsafe` block. +#[allow(missing_debug_implementations)] +#[doc(hidden)] +#[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")] +pub struct UnsafeArg { + _private: (), +} + +impl UnsafeArg { + /// See documentation where `UnsafeArg` is required to know when it is safe to + /// create and use `UnsafeArg`. + #[doc(hidden)] + #[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")] + #[inline(always)] + pub unsafe fn new() -> Self { + Self { _private: () } + } +} + // This guarantees a single stable value for the function pointer associated with // indices/counts in the formatting infrastructure. // @@ -333,21 +354,6 @@ enum FlagV1 { impl<'a> Arguments<'a> { /// When using the format_args!() macro, this function is used to generate the /// Arguments structure. - #[cfg(not(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( - pieces: &'a [&'static str], - args: &'a [ArgumentV1<'a>], - ) -> Arguments<'a> { - if pieces.len() < args.len() || pieces.len() > args.len() + 1 { - panic!("invalid args"); - } - Arguments { pieces, fmt: None, args } - } - #[cfg(bootstrap)] #[doc(hidden)] #[inline] #[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")] @@ -360,29 +366,34 @@ impl<'a> Arguments<'a> { } /// This function is used to specify nonstandard formatting parameters. - /// The `pieces` array must be at least as long as `fmt` to construct - /// a valid Arguments structure. Also, any `Count` within `fmt` that is - /// `CountIsParam` or `CountIsNextParam` has to point to an argument - /// created with `argumentusize`. However, failing to do so doesn't cause - /// unsafety, but will ignore invalid . + /// + /// An `UnsafeArg` is required because the following invariants must be held + /// in order for this function to be safe: + /// 1. The `pieces` slice must be at least as long as `fmt`. + /// 2. Every [`rt::v1::Argument::position`] value within `fmt` must be 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")] #[rustc_const_unstable(feature = "const_fmt_arguments_new", issue = "none")] - pub const unsafe fn new_v1_formatted( + pub const fn new_v1_formatted( pieces: &'a [&'static str], args: &'a [ArgumentV1<'a>], fmt: &'a [rt::v1::Argument], + _unsafe_arg: UnsafeArg, ) -> 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 fn new_v1_formatted( + pub const unsafe fn new_v1_formatted( pieces: &'a [&'static str], args: &'a [ArgumentV1<'a>], fmt: &'a [rt::v1::Argument], @@ -480,6 +491,7 @@ impl<'a> Arguments<'a> { /// ``` #[stable(feature = "fmt_as_str", since = "1.52.0")] #[rustc_const_unstable(feature = "const_arguments_as_str", issue = "none")] + #[must_use] #[inline] pub const fn as_str(&self) -> Option<&'static str> { match (self.pieces, self.args) { @@ -606,7 +618,8 @@ impl Display for Arguments<'_> { label = "`{Self}` cannot be formatted using `{{:?}}` because it doesn't implement `{Debug}`" )] #[doc(alias = "{:?}")] -#[rustc_diagnostic_item = "debug_trait"] +#[rustc_diagnostic_item = "Debug"] +#[cfg_attr(not(bootstrap), rustc_trivial_field_reads)] pub trait Debug { /// Formats the value using the given formatter. /// @@ -698,7 +711,7 @@ pub use macros::Debug; note = "in format strings you may be able to use `{{:?}}` (or {{:#?}} for pretty-print) instead" )] #[doc(alias = "{}")] -#[rustc_diagnostic_item = "display_trait"] +#[rustc_diagnostic_item = "Display"] #[stable(feature = "rust1", since = "1.0.0")] pub trait Display { /// Formats the value using the given formatter. @@ -991,7 +1004,7 @@ pub trait UpperHex { /// assert_eq!(&l_ptr[..2], "0x"); /// ``` #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_diagnostic_item = "pointer_trait"] +#[rustc_diagnostic_item = "Pointer"] pub trait Pointer { /// Formats the value using the given formatter. #[stable(feature = "rust1", since = "1.0.0")] @@ -1213,7 +1226,7 @@ unsafe fn getcount(args: &[ArgumentV1<'_>], cnt: &rt::v1::Count) -> Option Result { + pub(crate) fn write(self, f: &mut Formatter<'_>) -> Result { for _ in 0..self.padding { - buf.write_char(self.fill)?; + f.buf.write_char(self.fill)?; } Ok(()) } @@ -1349,7 +1362,7 @@ impl<'a> Formatter<'a> { write_prefix(self, sign, prefix)?; let post_padding = self.padding(min - width, rt::v1::Alignment::Right)?; self.buf.write_str(buf)?; - post_padding.write(self.buf)?; + post_padding.write(self)?; self.fill = old_fill; self.align = old_align; Ok(()) @@ -1359,7 +1372,7 @@ impl<'a> Formatter<'a> { let post_padding = self.padding(min - width, rt::v1::Alignment::Right)?; write_prefix(self, sign, prefix)?; self.buf.write_str(buf)?; - post_padding.write(self.buf) + post_padding.write(self) } } } @@ -1434,7 +1447,7 @@ impl<'a> Formatter<'a> { let align = rt::v1::Alignment::Left; let post_padding = self.padding(width - chars_count, align)?; self.buf.write_str(s)?; - post_padding.write(self.buf) + post_padding.write(self) } } } @@ -1443,7 +1456,7 @@ impl<'a> Formatter<'a> { /// Write the pre-padding and return the unwritten post-padding. Callers are /// responsible for ensuring post-padding is written after the thing that is /// being padded. - fn padding( + pub(crate) fn padding( &mut self, padding: usize, default: rt::v1::Alignment, @@ -1498,7 +1511,7 @@ impl<'a> Formatter<'a> { } else { let post_padding = self.padding(width - len, align)?; self.write_formatted_parts(&formatted)?; - post_padding.write(self.buf) + post_padding.write(self) }; self.fill = old_fill; self.align = old_align; diff --git a/library/core/src/fmt/num.rs b/library/core/src/fmt/num.rs index db45640df4..05ca50a97a 100644 --- a/library/core/src/fmt/num.rs +++ b/library/core/src/fmt/num.rs @@ -305,7 +305,6 @@ macro_rules! impl_Exp { n /= 10; exponent += 1; } - let trailing_zeros = exponent; let (added_precision, subtracted_precision) = match f.precision() { Some(fmt_prec) => { @@ -333,7 +332,7 @@ macro_rules! impl_Exp { n += 1; } } - (n, exponent, trailing_zeros, added_precision) + (n, exponent, exponent, added_precision) }; // 39 digits (worst case u128) + . = 40 diff --git a/library/core/src/hash/mod.rs b/library/core/src/hash/mod.rs index 77161e961e..540160bc4c 100644 --- a/library/core/src/hash/mod.rs +++ b/library/core/src/hash/mod.rs @@ -153,10 +153,23 @@ mod sip; /// Thankfully, you won't need to worry about upholding this property when /// deriving both [`Eq`] and `Hash` with `#[derive(PartialEq, Eq, Hash)]`. /// +/// ## Prefix collisions +/// +/// Implementations of `hash` should ensure that the data they +/// pass to the `Hasher` are prefix-free. That is, +/// unequal values should cause two different sequences of values to be written, +/// and neither of the two sequences should be a prefix of the other. +/// +/// For example, the standard implementation of [`Hash` for `&str`][impl] passes an extra +/// `0xFF` byte to the `Hasher` so that the values `("ab", "c")` and `("a", +/// "bc")` hash differently. +/// /// [`HashMap`]: ../../std/collections/struct.HashMap.html /// [`HashSet`]: ../../std/collections/struct.HashSet.html /// [`hash`]: Hash::hash +/// [impl]: ../../std/primitive.str.html#impl-Hash #[stable(feature = "rust1", since = "1.0.0")] +#[rustc_diagnostic_item = "Hash"] pub trait Hash { /// Feeds this value into the given [`Hasher`]. /// diff --git a/library/core/src/hash/sip.rs b/library/core/src/hash/sip.rs index 6178b0af13..b9443e3007 100644 --- a/library/core/src/hash/sip.rs +++ b/library/core/src/hash/sip.rs @@ -157,6 +157,7 @@ impl SipHasher { since = "1.13.0", reason = "use `std::collections::hash_map::DefaultHasher` instead" )] + #[must_use] pub fn new() -> SipHasher { SipHasher::new_with_keys(0, 0) } @@ -168,6 +169,7 @@ impl SipHasher { since = "1.13.0", reason = "use `std::collections::hash_map::DefaultHasher` instead" )] + #[must_use] pub fn new_with_keys(key0: u64, key1: u64) -> SipHasher { SipHasher(SipHasher24 { hasher: Hasher::new_with_keys(key0, key1) }) } diff --git a/library/core/src/hint.rs b/library/core/src/hint.rs index ba878ff66a..9579887915 100644 --- a/library/core/src/hint.rs +++ b/library/core/src/hint.rs @@ -44,7 +44,7 @@ use crate::intrinsics; /// ``` #[inline] #[stable(feature = "unreachable", since = "1.27.0")] -#[rustc_const_unstable(feature = "const_unreachable_unchecked", issue = "53188")] +#[rustc_const_stable(feature = "const_unreachable_unchecked", since = "1.57.0")] pub const unsafe fn unreachable_unchecked() -> ! { // SAFETY: the safety contract for `intrinsics::unreachable` must // be upheld by the caller. @@ -154,18 +154,6 @@ pub fn spin_loop() { /// [`std::convert::identity`]: crate::convert::identity #[inline] #[unstable(feature = "bench_black_box", issue = "64102")] -#[cfg_attr(not(bootstrap), allow(unused_mut))] -#[cfg_attr(bootstrap, allow(deprecated))] -pub fn black_box(mut dummy: T) -> T { - #[cfg(bootstrap)] - // SAFETY: the inline assembly is a no-op. - unsafe { - llvm_asm!("" : : "r"(&mut dummy) : "memory" : "volatile"); - dummy - } - - #[cfg(not(bootstrap))] - { - crate::intrinsics::black_box(dummy) - } +pub fn black_box(dummy: T) -> T { + crate::intrinsics::black_box(dummy) } diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index 9278dbb549..1aeb83931e 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -735,7 +735,7 @@ extern "rust-intrinsic" { /// reach code marked with this function. /// /// The stabilized version of this intrinsic is [`core::hint::unreachable_unchecked`]. - #[rustc_const_unstable(feature = "const_unreachable_unchecked", issue = "53188")] + #[rustc_const_stable(feature = "const_unreachable_unchecked", since = "1.57.0")] pub fn unreachable() -> !; /// Informs the optimizer that a condition is always true. @@ -1937,7 +1937,6 @@ extern "rust-intrinsic" { /// See documentation of [`std::hint::black_box`] for details. /// /// [`std::hint::black_box`]: crate::hint::black_box - #[cfg(not(bootstrap))] pub fn black_box(dummy: T) -> T; } @@ -2222,3 +2221,74 @@ pub unsafe fn write_bytes(dst: *mut T, val: u8, count: usize) { // SAFETY: the safety contract for `write_bytes` must be upheld by the caller. unsafe { write_bytes(dst, val, count) } } + +/// Selects which function to call depending on the context. +/// +/// If this function is evaluated at compile-time, then a call to this +/// intrinsic will be replaced with a call to `called_in_const`. It gets +/// replaced with a call to `called_at_rt` otherwise. +/// +/// # Type Requirements +/// +/// The two functions must be both function items. They cannot be function +/// pointers or closures. +/// +/// `arg` will be the arguments that will be passed to either one of the +/// two functions, therefore, both functions must accept the same type of +/// arguments. Both functions must return RET. +/// +/// # Safety +/// +/// This intrinsic allows breaking [referential transparency] in `const fn` +/// and is therefore `unsafe`. +/// +/// Code that uses this intrinsic must be extremely careful to ensure that +/// `const fn`s remain referentially-transparent independently of when they +/// are evaluated. +/// +/// The Rust compiler assumes that it is sound to replace a call to a `const +/// fn` with the result produced by evaluating it at compile-time. If +/// evaluating the function at run-time were to produce a different result, +/// 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", + reason = "const_eval_select will never be stable" +)] +#[rustc_const_unstable(feature = "const_eval_select", issue = "none")] +#[lang = "const_eval_select"] +#[rustc_do_not_const_check] +pub const unsafe fn const_eval_select( + arg: ARG, + _called_in_const: F, + called_at_rt: G, +) -> RET +where + F: ~const FnOnce, + G: FnOnce + ~const Drop, +{ + called_at_rt.call_once(arg) +} + +#[cfg(not(bootstrap))] +#[unstable( + feature = "const_eval_select", + issue = "none", + reason = "const_eval_select will never be stable" +)] +#[rustc_const_unstable(feature = "const_eval_select", issue = "none")] +#[lang = "const_eval_select_ct"] +pub const unsafe fn const_eval_select_ct( + arg: ARG, + called_in_const: F, + _called_at_rt: G, +) -> RET +where + F: ~const FnOnce, + G: FnOnce + ~const Drop, +{ + called_in_const.call_once(arg) +} diff --git a/library/core/src/iter/adapters/copied.rs b/library/core/src/iter/adapters/copied.rs index 3d3c8da678..e5f2886dca 100644 --- a/library/core/src/iter/adapters/copied.rs +++ b/library/core/src/iter/adapters/copied.rs @@ -76,6 +76,11 @@ where self.it.count() } + #[inline] + fn advance_by(&mut self, n: usize) -> Result<(), usize> { + self.it.advance_by(n) + } + #[doc(hidden)] unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> T where @@ -112,6 +117,11 @@ where { self.it.rfold(init, copy_fold(f)) } + + #[inline] + fn advance_back_by(&mut self, n: usize) -> Result<(), usize> { + self.it.advance_back_by(n) + } } #[stable(feature = "iter_copied", since = "1.36.0")] diff --git a/library/core/src/iter/adapters/cycle.rs b/library/core/src/iter/adapters/cycle.rs index 815e708f9e..02b5939072 100644 --- a/library/core/src/iter/adapters/cycle.rs +++ b/library/core/src/iter/adapters/cycle.rs @@ -79,6 +79,27 @@ where } } + #[inline] + #[rustc_inherit_overflow_checks] + fn advance_by(&mut self, n: usize) -> Result<(), usize> { + let mut rem = n; + match self.iter.advance_by(rem) { + ret @ Ok(_) => return ret, + Err(advanced) => rem -= advanced, + } + + while rem > 0 { + self.iter = self.orig.clone(); + match self.iter.advance_by(rem) { + ret @ Ok(_) => return ret, + Err(0) => return Err(n - rem), + Err(advanced) => rem -= advanced, + } + } + + Ok(()) + } + // No `fold` override, because `fold` doesn't make much sense for `Cycle`, // and we can't do anything better than the default. } diff --git a/library/core/src/iter/adapters/enumerate.rs b/library/core/src/iter/adapters/enumerate.rs index 3478a0cd40..84e4618844 100644 --- a/library/core/src/iter/adapters/enumerate.rs +++ b/library/core/src/iter/adapters/enumerate.rs @@ -112,6 +112,21 @@ where self.iter.fold(init, enumerate(self.count, fold)) } + #[inline] + #[rustc_inherit_overflow_checks] + fn advance_by(&mut self, n: usize) -> Result<(), usize> { + match self.iter.advance_by(n) { + ret @ Ok(_) => { + self.count += n; + ret + } + ret @ Err(advanced) => { + self.count += advanced; + ret + } + } + } + #[rustc_inherit_overflow_checks] #[doc(hidden)] unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> ::Item @@ -191,6 +206,13 @@ where let count = self.count + self.iter.len(); self.iter.rfold(init, enumerate(count, fold)) } + + #[inline] + fn advance_back_by(&mut self, n: usize) -> Result<(), usize> { + // we do not need to update the count since that only tallies the number of items + // consumed from the front. consuming items from the back can never reduce that. + self.iter.advance_back_by(n) + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -227,14 +249,14 @@ impl FusedIterator for Enumerate where I: FusedIterator {} unsafe impl TrustedLen for Enumerate where I: TrustedLen {} #[unstable(issue = "none", feature = "inplace_iteration")] -unsafe impl SourceIter for Enumerate +unsafe impl SourceIter for Enumerate where - I: SourceIter, + I: SourceIter, { - type Source = S; + type Source = I::Source; #[inline] - unsafe fn as_inner(&mut self) -> &mut S { + unsafe fn as_inner(&mut self) -> &mut I::Source { // SAFETY: unsafe function forwarding to unsafe function with the same requirements unsafe { SourceIter::as_inner(&mut self.iter) } } diff --git a/library/core/src/iter/adapters/filter.rs b/library/core/src/iter/adapters/filter.rs index d5f19f1274..a0afaa326a 100644 --- a/library/core/src/iter/adapters/filter.rs +++ b/library/core/src/iter/adapters/filter.rs @@ -135,15 +135,14 @@ where impl FusedIterator for Filter where P: FnMut(&I::Item) -> bool {} #[unstable(issue = "none", feature = "inplace_iteration")] -unsafe impl SourceIter for Filter +unsafe impl SourceIter for Filter where - P: FnMut(&I::Item) -> bool, - I: SourceIter, + I: SourceIter, { - type Source = S; + type Source = I::Source; #[inline] - unsafe fn as_inner(&mut self) -> &mut S { + unsafe fn as_inner(&mut self) -> &mut I::Source { // SAFETY: unsafe function forwarding to unsafe function with the same requirements unsafe { SourceIter::as_inner(&mut self.iter) } } diff --git a/library/core/src/iter/adapters/filter_map.rs b/library/core/src/iter/adapters/filter_map.rs index 01b7be9d52..e0d665c9e1 100644 --- a/library/core/src/iter/adapters/filter_map.rs +++ b/library/core/src/iter/adapters/filter_map.rs @@ -129,15 +129,14 @@ where impl FusedIterator for FilterMap where F: FnMut(I::Item) -> Option {} #[unstable(issue = "none", feature = "inplace_iteration")] -unsafe impl SourceIter for FilterMap +unsafe impl SourceIter for FilterMap where - F: FnMut(I::Item) -> Option, - I: SourceIter, + I: SourceIter, { - type Source = S; + type Source = I::Source; #[inline] - unsafe fn as_inner(&mut self) -> &mut S { + unsafe fn as_inner(&mut self) -> &mut I::Source { // SAFETY: unsafe function forwarding to unsafe function with the same requirements unsafe { SourceIter::as_inner(&mut self.iter) } } diff --git a/library/core/src/iter/adapters/flatten.rs b/library/core/src/iter/adapters/flatten.rs index 48880a4d91..351fd569d8 100644 --- a/library/core/src/iter/adapters/flatten.rs +++ b/library/core/src/iter/adapters/flatten.rs @@ -391,6 +391,41 @@ where init } + + #[inline] + #[rustc_inherit_overflow_checks] + fn advance_by(&mut self, n: usize) -> Result<(), usize> { + let mut rem = n; + loop { + if let Some(ref mut front) = self.frontiter { + match front.advance_by(rem) { + ret @ Ok(_) => return ret, + Err(advanced) => rem -= advanced, + } + } + self.frontiter = match self.iter.next() { + Some(iterable) => Some(iterable.into_iter()), + _ => break, + } + } + + self.frontiter = None; + + if let Some(ref mut back) = self.backiter { + match back.advance_by(rem) { + ret @ Ok(_) => return ret, + Err(advanced) => rem -= advanced, + } + } + + if rem > 0 { + return Err(n - rem); + } + + self.backiter = None; + + Ok(()) + } } impl DoubleEndedIterator for FlattenCompat @@ -486,6 +521,41 @@ where init } + + #[inline] + #[rustc_inherit_overflow_checks] + fn advance_back_by(&mut self, n: usize) -> Result<(), usize> { + let mut rem = n; + loop { + if let Some(ref mut back) = self.backiter { + match back.advance_back_by(rem) { + ret @ Ok(_) => return ret, + Err(advanced) => rem -= advanced, + } + } + match self.iter.next_back() { + Some(iterable) => self.backiter = Some(iterable.into_iter()), + _ => break, + } + } + + self.backiter = None; + + if let Some(ref mut front) = self.frontiter { + match front.advance_back_by(rem) { + ret @ Ok(_) => return ret, + Err(advanced) => rem -= advanced, + } + } + + if rem > 0 { + return Err(n - rem); + } + + self.frontiter = None; + + Ok(()) + } } trait ConstSizeIntoIterator: IntoIterator { diff --git a/library/core/src/iter/adapters/inspect.rs b/library/core/src/iter/adapters/inspect.rs index 36835d12e5..19839fdfe5 100644 --- a/library/core/src/iter/adapters/inspect.rs +++ b/library/core/src/iter/adapters/inspect.rs @@ -149,15 +149,14 @@ where impl FusedIterator for Inspect where F: FnMut(&I::Item) {} #[unstable(issue = "none", feature = "inplace_iteration")] -unsafe impl SourceIter for Inspect +unsafe impl SourceIter for Inspect where - F: FnMut(&I::Item), - I: SourceIter, + I: SourceIter, { - type Source = S; + type Source = I::Source; #[inline] - unsafe fn as_inner(&mut self) -> &mut S { + unsafe fn as_inner(&mut self) -> &mut I::Source { // SAFETY: unsafe function forwarding to unsafe function with the same requirements unsafe { SourceIter::as_inner(&mut self.iter) } } diff --git a/library/core/src/iter/adapters/map.rs b/library/core/src/iter/adapters/map.rs index 763e253e75..449650a22f 100644 --- a/library/core/src/iter/adapters/map.rs +++ b/library/core/src/iter/adapters/map.rs @@ -201,15 +201,14 @@ where } #[unstable(issue = "none", feature = "inplace_iteration")] -unsafe impl SourceIter for Map +unsafe impl SourceIter for Map where - F: FnMut(I::Item) -> B, - I: SourceIter, + I: SourceIter, { - type Source = S; + type Source = I::Source; #[inline] - unsafe fn as_inner(&mut self) -> &mut S { + unsafe fn as_inner(&mut self) -> &mut I::Source { // SAFETY: unsafe function forwarding to unsafe function with the same requirements unsafe { SourceIter::as_inner(&mut self.iter) } } diff --git a/library/core/src/iter/adapters/map_while.rs b/library/core/src/iter/adapters/map_while.rs index 8f89e15880..1e8d6bf3e0 100644 --- a/library/core/src/iter/adapters/map_while.rs +++ b/library/core/src/iter/adapters/map_while.rs @@ -10,7 +10,7 @@ use crate::ops::{ControlFlow, Try}; /// [`map_while`]: Iterator::map_while /// [`Iterator`]: trait.Iterator.html #[must_use = "iterators are lazy and do nothing unless consumed"] -#[unstable(feature = "iter_map_while", reason = "recently added", issue = "68537")] +#[stable(feature = "iter_map_while", since = "1.57.0")] #[derive(Clone)] pub struct MapWhile { iter: I, @@ -23,14 +23,14 @@ impl MapWhile { } } -#[unstable(feature = "iter_map_while", reason = "recently added", issue = "68537")] +#[stable(feature = "iter_map_while", since = "1.57.0")] impl fmt::Debug for MapWhile { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("MapWhile").field("iter", &self.iter).finish() } } -#[unstable(feature = "iter_map_while", reason = "recently added", issue = "68537")] +#[stable(feature = "iter_map_while", since = "1.57.0")] impl Iterator for MapWhile where P: FnMut(I::Item) -> Option, @@ -80,15 +80,14 @@ where } #[unstable(issue = "none", feature = "inplace_iteration")] -unsafe impl SourceIter for MapWhile +unsafe impl SourceIter for MapWhile where - P: FnMut(I::Item) -> Option, - I: SourceIter, + I: SourceIter, { - type Source = S; + type Source = I::Source; #[inline] - unsafe fn as_inner(&mut self) -> &mut S { + unsafe fn as_inner(&mut self) -> &mut I::Source { // SAFETY: unsafe function forwarding to unsafe function with the same requirements unsafe { SourceIter::as_inner(&mut self.iter) } } diff --git a/library/core/src/iter/adapters/mod.rs b/library/core/src/iter/adapters/mod.rs index 056ccca1d0..9e1f4e425f 100644 --- a/library/core/src/iter/adapters/mod.rs +++ b/library/core/src/iter/adapters/mod.rs @@ -45,7 +45,7 @@ pub use self::copied::Copied; #[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")] pub use self::intersperse::{Intersperse, IntersperseWith}; -#[unstable(feature = "iter_map_while", reason = "recently added", issue = "68537")] +#[stable(feature = "iter_map_while", since = "1.57.0")] pub use self::map_while::MapWhile; #[unstable(feature = "trusted_random_access", issue = "none")] @@ -92,9 +92,10 @@ pub use self::zip::zip; /// [`as_inner`]: SourceIter::as_inner #[unstable(issue = "none", feature = "inplace_iteration")] #[doc(hidden)] +#[rustc_specialization_trait] pub unsafe trait SourceIter { /// A source stage in an iterator pipeline. - type Source: Iterator; + type Source; /// Retrieve the source of an iterator pipeline. /// @@ -200,14 +201,14 @@ where } #[unstable(issue = "none", feature = "inplace_iteration")] -unsafe impl SourceIter for ResultShunt<'_, I, E> +unsafe impl SourceIter for ResultShunt<'_, I, E> where - I: SourceIter, + I: SourceIter, { - type Source = S; + type Source = I::Source; #[inline] - unsafe fn as_inner(&mut self) -> &mut S { + unsafe fn as_inner(&mut self) -> &mut Self::Source { // SAFETY: unsafe function forwarding to unsafe function with the same requirements unsafe { SourceIter::as_inner(&mut self.iter) } } diff --git a/library/core/src/iter/adapters/peekable.rs b/library/core/src/iter/adapters/peekable.rs index 91fa1a9ad3..20aca323ba 100644 --- a/library/core/src/iter/adapters/peekable.rs +++ b/library/core/src/iter/adapters/peekable.rs @@ -321,14 +321,14 @@ impl Peekable { unsafe impl TrustedLen for Peekable where I: TrustedLen {} #[unstable(issue = "none", feature = "inplace_iteration")] -unsafe impl SourceIter for Peekable +unsafe impl SourceIter for Peekable where - I: SourceIter, + I: SourceIter, { - type Source = S; + type Source = I::Source; #[inline] - unsafe fn as_inner(&mut self) -> &mut S { + unsafe fn as_inner(&mut self) -> &mut I::Source { // SAFETY: unsafe function forwarding to unsafe function with the same requirements unsafe { SourceIter::as_inner(&mut self.iter) } } diff --git a/library/core/src/iter/adapters/scan.rs b/library/core/src/iter/adapters/scan.rs index 96705b01f6..80bfd22312 100644 --- a/library/core/src/iter/adapters/scan.rs +++ b/library/core/src/iter/adapters/scan.rs @@ -90,15 +90,14 @@ where } #[unstable(issue = "none", feature = "inplace_iteration")] -unsafe impl SourceIter for Scan +unsafe impl SourceIter for Scan where - I: SourceIter, - F: FnMut(&mut St, I::Item) -> Option, + I: SourceIter, { - type Source = S; + type Source = I::Source; #[inline] - unsafe fn as_inner(&mut self) -> &mut S { + unsafe fn as_inner(&mut self) -> &mut I::Source { // SAFETY: unsafe function forwarding to unsafe function with the same requirements unsafe { SourceIter::as_inner(&mut self.iter) } } diff --git a/library/core/src/iter/adapters/skip.rs b/library/core/src/iter/adapters/skip.rs index c358a6d12b..565fc224f5 100644 --- a/library/core/src/iter/adapters/skip.rs +++ b/library/core/src/iter/adapters/skip.rs @@ -114,6 +114,38 @@ where } self.iter.fold(init, fold) } + + #[inline] + #[rustc_inherit_overflow_checks] + fn advance_by(&mut self, n: usize) -> Result<(), usize> { + let mut rem = n; + + let step_one = self.n.saturating_add(rem); + match self.iter.advance_by(step_one) { + Ok(_) => { + rem -= step_one - self.n; + self.n = 0; + } + Err(advanced) => { + let advanced_without_skip = advanced.saturating_sub(self.n); + self.n = self.n.saturating_sub(advanced); + return Err(advanced_without_skip); + } + } + + // step_one calculation may have saturated + if unlikely(rem > 0) { + return match self.iter.advance_by(rem) { + ret @ Ok(_) => ret, + Err(advanced) => { + rem -= advanced; + Err(n - rem) + } + }; + } + + Ok(()) + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -174,20 +206,30 @@ where self.try_rfold(init, ok(fold)).unwrap() } + + #[inline] + fn advance_back_by(&mut self, n: usize) -> Result<(), usize> { + let min = crate::cmp::min(self.len(), n); + return match self.iter.advance_back_by(min) { + ret @ Ok(_) if n <= min => ret, + Ok(_) => Err(min), + _ => panic!("ExactSizeIterator contract violation"), + }; + } } #[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for Skip where I: FusedIterator {} #[unstable(issue = "none", feature = "inplace_iteration")] -unsafe impl SourceIter for Skip +unsafe impl SourceIter for Skip where - I: SourceIter, + I: SourceIter, { - type Source = S; + type Source = I::Source; #[inline] - unsafe fn as_inner(&mut self) -> &mut S { + unsafe fn as_inner(&mut self) -> &mut I::Source { // SAFETY: unsafe function forwarding to unsafe function with the same requirements unsafe { SourceIter::as_inner(&mut self.iter) } } diff --git a/library/core/src/iter/adapters/skip_while.rs b/library/core/src/iter/adapters/skip_while.rs index 93e29edc8d..f29661779c 100644 --- a/library/core/src/iter/adapters/skip_while.rs +++ b/library/core/src/iter/adapters/skip_while.rs @@ -105,15 +105,14 @@ where } #[unstable(issue = "none", feature = "inplace_iteration")] -unsafe impl SourceIter for SkipWhile +unsafe impl SourceIter for SkipWhile where - P: FnMut(&I::Item) -> bool, - I: SourceIter, + I: SourceIter, { - type Source = S; + type Source = I::Source; #[inline] - unsafe fn as_inner(&mut self) -> &mut S { + unsafe fn as_inner(&mut self) -> &mut I::Source { // SAFETY: unsafe function forwarding to unsafe function with the same requirements unsafe { SourceIter::as_inner(&mut self.iter) } } diff --git a/library/core/src/iter/adapters/take.rs b/library/core/src/iter/adapters/take.rs index beda8c32c6..81f6c294fa 100644 --- a/library/core/src/iter/adapters/take.rs +++ b/library/core/src/iter/adapters/take.rs @@ -111,17 +111,33 @@ where self.try_fold(init, ok(fold)).unwrap() } + + #[inline] + #[rustc_inherit_overflow_checks] + fn advance_by(&mut self, n: usize) -> Result<(), usize> { + let min = self.n.min(n); + match self.iter.advance_by(min) { + Ok(_) => { + self.n -= min; + if min < n { Err(min) } else { Ok(()) } + } + ret @ Err(advanced) => { + self.n -= advanced; + ret + } + } + } } #[unstable(issue = "none", feature = "inplace_iteration")] -unsafe impl SourceIter for Take +unsafe impl SourceIter for Take where - I: SourceIter, + I: SourceIter, { - type Source = S; + type Source = I::Source; #[inline] - unsafe fn as_inner(&mut self) -> &mut S { + unsafe fn as_inner(&mut self) -> &mut I::Source { // SAFETY: unsafe function forwarding to unsafe function with the same requirements unsafe { SourceIter::as_inner(&mut self.iter) } } @@ -197,6 +213,24 @@ where } } } + + #[inline] + fn advance_back_by(&mut self, n: usize) -> Result<(), usize> { + let inner_len = self.iter.len(); + let len = self.n; + let remainder = len.saturating_sub(n); + let to_advance = inner_len - remainder; + match self.iter.advance_back_by(to_advance) { + Ok(_) => { + self.n = remainder; + if n > len { + return Err(len); + } + return Ok(()); + } + _ => panic!("ExactSizeIterator contract violation"), + } + } } #[stable(feature = "rust1", since = "1.0.0")] diff --git a/library/core/src/iter/adapters/take_while.rs b/library/core/src/iter/adapters/take_while.rs index 93457d20f7..ded216da95 100644 --- a/library/core/src/iter/adapters/take_while.rs +++ b/library/core/src/iter/adapters/take_while.rs @@ -118,15 +118,14 @@ where } #[unstable(issue = "none", feature = "inplace_iteration")] -unsafe impl SourceIter for TakeWhile +unsafe impl SourceIter for TakeWhile where - P: FnMut(&I::Item) -> bool, - I: SourceIter, + I: SourceIter, { - type Source = S; + type Source = I::Source; #[inline] - unsafe fn as_inner(&mut self) -> &mut S { + unsafe fn as_inner(&mut self) -> &mut I::Source { // SAFETY: unsafe function forwarding to unsafe function with the same requirements unsafe { SourceIter::as_inner(&mut self.iter) } } diff --git a/library/core/src/iter/adapters/zip.rs b/library/core/src/iter/adapters/zip.rs index 17697fa0e0..2b7287a413 100644 --- a/library/core/src/iter/adapters/zip.rs +++ b/library/core/src/iter/adapters/zip.rs @@ -414,16 +414,14 @@ where // Arbitrarily selects the left side of the zip iteration as extractable "source" // it would require negative trait bounds to be able to try both #[unstable(issue = "none", feature = "inplace_iteration")] -unsafe impl SourceIter for Zip +unsafe impl SourceIter for Zip where - A: SourceIter, - B: Iterator, - S: Iterator, + A: SourceIter, { - type Source = S; + type Source = A::Source; #[inline] - unsafe fn as_inner(&mut self) -> &mut S { + unsafe fn as_inner(&mut self) -> &mut A::Source { // SAFETY: unsafe function forwarding to unsafe function with the same requirements unsafe { SourceIter::as_inner(&mut self.a) } } diff --git a/library/core/src/iter/mod.rs b/library/core/src/iter/mod.rs index 7fb80f954f..dc32df4e2b 100644 --- a/library/core/src/iter/mod.rs +++ b/library/core/src/iter/mod.rs @@ -39,7 +39,7 @@ //! ``` //! //! An iterator has a method, [`next`], which when called, returns an -//! [`Option`]``. [`next`] will return [`Some(Item)`] as long as there +//! [Option]\. Calling [`next`] will return [`Some(Item)`] as long as there //! are elements, and once they've all been exhausted, will return `None` to //! indicate that iteration is finished. Individual iterators may choose to //! resume iteration, and so calling [`next`] again may or may not eventually @@ -399,7 +399,7 @@ pub use self::adapters::Cloned; pub use self::adapters::Copied; #[stable(feature = "iterator_flatten", since = "1.29.0")] pub use self::adapters::Flatten; -#[unstable(feature = "iter_map_while", reason = "recently added", issue = "68537")] +#[stable(feature = "iter_map_while", since = "1.57.0")] pub use self::adapters::MapWhile; #[unstable(feature = "inplace_iteration", issue = "none")] pub use self::adapters::SourceIter; diff --git a/library/core/src/iter/range.rs b/library/core/src/iter/range.rs index f7ed811e44..06733a1b50 100644 --- a/library/core/src/iter/range.rs +++ b/library/core/src/iter/range.rs @@ -521,10 +521,12 @@ trait RangeIteratorImpl { // Iterator fn spec_next(&mut self) -> Option; fn spec_nth(&mut self, n: usize) -> Option; + fn spec_advance_by(&mut self, n: usize) -> Result<(), usize>; // DoubleEndedIterator fn spec_next_back(&mut self) -> Option; fn spec_nth_back(&mut self, n: usize) -> Option; + fn spec_advance_back_by(&mut self, n: usize) -> Result<(), usize>; } impl RangeIteratorImpl for ops::Range { @@ -555,6 +557,22 @@ impl RangeIteratorImpl for ops::Range { None } + #[inline] + default fn spec_advance_by(&mut self, n: usize) -> Result<(), usize> { + let available = if self.start <= self.end { + Step::steps_between(&self.start, &self.end).unwrap_or(usize::MAX) + } else { + 0 + }; + + let taken = available.min(n); + + self.start = + Step::forward_checked(self.start.clone(), taken).expect("`Step` invariants not upheld"); + + if taken < n { Err(taken) } else { Ok(()) } + } + #[inline] default fn spec_next_back(&mut self) -> Option { if self.start < self.end { @@ -579,6 +597,22 @@ impl RangeIteratorImpl for ops::Range { self.end = self.start.clone(); None } + + #[inline] + default fn spec_advance_back_by(&mut self, n: usize) -> Result<(), usize> { + let available = if self.start <= self.end { + Step::steps_between(&self.start, &self.end).unwrap_or(usize::MAX) + } else { + 0 + }; + + let taken = available.min(n); + + self.end = + Step::backward_checked(self.end.clone(), taken).expect("`Step` invariants not upheld"); + + if taken < n { Err(taken) } else { Ok(()) } + } } impl RangeIteratorImpl for ops::Range { @@ -607,6 +641,25 @@ impl RangeIteratorImpl for ops::Range { None } + #[inline] + fn spec_advance_by(&mut self, n: usize) -> Result<(), usize> { + let available = if self.start <= self.end { + Step::steps_between(&self.start, &self.end).unwrap_or(usize::MAX) + } else { + 0 + }; + + let taken = available.min(n); + + // SAFETY: the conditions above ensure that the count is in bounds. If start <= end + // then steps_between either returns a bound to which we clamp or returns None which + // together with the initial inequality implies more than usize::MAX steps. + // Otherwise 0 is returned which always safe to use. + self.start = unsafe { Step::forward_unchecked(self.start.clone(), taken) }; + + if taken < n { Err(taken) } else { Ok(()) } + } + #[inline] fn spec_next_back(&mut self) -> Option { if self.start < self.end { @@ -631,6 +684,22 @@ impl RangeIteratorImpl for ops::Range { self.end = self.start.clone(); None } + + #[inline] + fn spec_advance_back_by(&mut self, n: usize) -> Result<(), usize> { + let available = if self.start <= self.end { + Step::steps_between(&self.start, &self.end).unwrap_or(usize::MAX) + } else { + 0 + }; + + let taken = available.min(n); + + // SAFETY: same as the spec_advance_by() implementation + self.end = unsafe { Step::backward_unchecked(self.end.clone(), taken) }; + + if taken < n { Err(taken) } else { Ok(()) } + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -672,6 +741,16 @@ impl Iterator for ops::Range { self.next_back() } + #[inline] + fn is_sorted(self) -> bool { + true + } + + #[inline] + fn advance_by(&mut self, n: usize) -> Result<(), usize> { + self.spec_advance_by(n) + } + #[inline] #[doc(hidden)] unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item @@ -745,6 +824,11 @@ impl DoubleEndedIterator for ops::Range { fn nth_back(&mut self, n: usize) -> Option { self.spec_nth_back(n) } + + #[inline] + fn advance_back_by(&mut self, n: usize) -> Result<(), usize> { + self.spec_advance_back_by(n) + } } // Safety: @@ -1095,6 +1179,11 @@ impl Iterator for ops::RangeInclusive { fn max(mut self) -> Option { self.next_back() } + + #[inline] + fn is_sorted(self) -> bool { + true + } } #[stable(feature = "inclusive_range", since = "1.26.0")] diff --git a/library/core/src/iter/traits/double_ended.rs b/library/core/src/iter/traits/double_ended.rs index 9a9cf20077..9a589c1f3b 100644 --- a/library/core/src/iter/traits/double_ended.rs +++ b/library/core/src/iter/traits/double_ended.rs @@ -103,9 +103,15 @@ pub trait DoubleEndedIterator: Iterator { /// elements the iterator is advanced by before running out of elements (i.e. the length /// of the iterator). Note that `k` is always less than `n`. /// - /// Calling `advance_back_by(0)` does not consume any elements and always returns [`Ok(())`]. + /// Calling `advance_back_by(0)` can do meaningful work, for example [`Flatten`] can advance its + /// outer iterator until it finds an inner iterator that is not empty, which then often + /// allows it to return a more accurate `size_hint()` than in its initial state. + /// `advance_back_by(0)` may either return `Ok()` or `Err(0)`. The former conveys no information + /// whether the iterator is or is not exhausted, the latter can be treated as if [`next_back`] + /// had returned `None`. Replacing a `Err(0)` with `Ok` is only correct for `n = 0`. /// /// [`advance_by`]: Iterator::advance_by + /// [`Flatten`]: crate::iter::Flatten /// [`next_back`]: DoubleEndedIterator::next_back /// /// # Examples diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index 850435b53c..f53d6cac7e 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -96,7 +96,7 @@ pub trait Iterator { /// Specifically, `size_hint()` returns a tuple where the first element /// is the lower bound, and the second element is the upper bound. /// - /// The second half of the tuple that is returned is an [`Option`]`<`[`usize`]`>`. + /// The second half of the tuple that is returned is an [Option]<[usize]>. /// A [`None`] here means that either there is no known upper bound, or the /// upper bound is larger than [`usize`]. /// @@ -115,11 +115,9 @@ pub trait Iterator { /// That said, the implementation should provide a correct estimation, /// because otherwise it would be a violation of the trait's protocol. /// - /// The default implementation returns `(0, `[`None`]`)` which is correct for any + /// The default implementation returns (0, [None]) which is correct for any /// iterator. /// - /// [`usize`]: type@usize - /// /// # Examples /// /// Basic usage: @@ -248,8 +246,14 @@ pub trait Iterator { /// of elements the iterator is advanced by before running out of elements (i.e. the /// length of the iterator). Note that `k` is always less than `n`. /// - /// Calling `advance_by(0)` does not consume any elements and always returns [`Ok(())`][Ok]. + /// Calling `advance_by(0)` can do meaningful work, for example [`Flatten`] + /// can advance its outer iterator until it finds an inner iterator that is not empty, which + /// then often allows it to return a more accurate `size_hint()` than in its initial state. + /// `advance_by(0)` may either return `Ok()` or `Err(0)`. The former conveys no information + /// whether the iterator is or is not exhausted, the latter can be treated as if [`next`] + /// had returned `None`. Replacing a `Err(0)` with `Ok` is only correct for `n = 0`. /// + /// [`Flatten`]: crate::iter::Flatten /// [`next`]: Iterator::next /// /// # Examples @@ -870,7 +874,6 @@ pub trait Iterator { /// The returned iterator might panic if the to-be-returned index would /// overflow a [`usize`]. /// - /// [`usize`]: type@usize /// [`zip`]: Iterator::zip /// /// # Examples @@ -1122,7 +1125,6 @@ pub trait Iterator { /// Basic usage: /// /// ``` - /// #![feature(iter_map_while)] /// let a = [-1i32, 4, 0, 1]; /// /// let mut iter = a.iter().map_while(|x| 16i32.checked_div(*x)); @@ -1153,7 +1155,6 @@ pub trait Iterator { /// Stopping after an initial [`None`]: /// /// ``` - /// #![feature(iter_map_while)] /// use std::convert::TryFrom; /// /// let a = [0, 1, 2, -3, 4, 5, -6]; @@ -1171,7 +1172,6 @@ pub trait Iterator { /// removed: /// /// ``` - /// #![feature(iter_map_while)] /// use std::convert::TryFrom; /// /// let a = [1, 2, -3, 4]; @@ -1197,7 +1197,7 @@ pub trait Iterator { /// /// [`fuse`]: Iterator::fuse #[inline] - #[unstable(feature = "iter_map_while", reason = "recently added", issue = "68537")] + #[stable(feature = "iter_map_while", since = "1.57.0")] fn map_while(self, predicate: P) -> MapWhile where Self: Sized, @@ -1807,10 +1807,11 @@ pub trait Iterator { /// The relative order of partitioned items is not maintained. /// /// # Current implementation + /// /// Current algorithms tries finding the first element for which the predicate evaluates /// to false, and the last element for which it evaluates to true and repeatedly swaps them. /// - /// Time Complexity: *O*(*N*) + /// Time complexity: *O*(*n*) /// /// See also [`is_partitioned()`] and [`partition()`]. /// @@ -2178,8 +2179,9 @@ pub trait Iterator { /// If the iterator is empty, returns [`None`]; otherwise, returns the /// result of the reduction. /// + /// The reducing function is a closure with two arguments: an 'accumulator', and an element. /// For iterators with at least one element, this is the same as [`fold()`] - /// with the first element of the iterator as the initial value, folding + /// with the first element of the iterator as the initial accumulator value, folding /// every subsequent element into it. /// /// [`fold()`]: Iterator::fold @@ -2193,8 +2195,8 @@ pub trait Iterator { /// where I: Iterator, /// I::Item: Ord, /// { - /// iter.reduce(|a, b| { - /// if a >= b { a } else { b } + /// iter.reduce(|accum, item| { + /// if accum >= item { accum } else { item } /// }) /// } /// let a = [10, 20, 5, -23, 0]; @@ -3458,6 +3460,7 @@ pub trait Iterator { #[stable(feature = "rust1", since = "1.0.0")] impl Iterator for &mut I { type Item = I::Item; + #[inline] fn next(&mut self) -> Option { (**self).next() } diff --git a/library/core/src/lazy.rs b/library/core/src/lazy.rs index 2c517371c2..d109141216 100644 --- a/library/core/src/lazy.rs +++ b/library/core/src/lazy.rs @@ -83,6 +83,7 @@ impl From for OnceCell { impl OnceCell { /// Creates a new empty cell. #[unstable(feature = "once_cell", issue = "74465")] + #[must_use] pub const fn new() -> OnceCell { OnceCell { inner: UnsafeCell::new(None) } } @@ -214,7 +215,16 @@ impl OnceCell { if let Some(val) = self.get() { return Ok(val); } - let val = f()?; + /// Avoid inlining the initialization closure into the common path that fetches + /// the already initialized value + #[cold] + fn outlined_call(f: F) -> Result + where + F: FnOnce() -> Result, + { + f() + } + let val = outlined_call(f)?; // Note that *some* forms of reentrant initialization might lead to // UB (see `reentrant_init` test). I believe that just removing this // `assert`, while keeping `set/get` would be sound, but it seems diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index d667fff4b8..13b80c05db 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -60,6 +60,32 @@ test(no_crate_inject, attr(deny(warnings))), test(attr(allow(dead_code, deprecated, unused_variables, unused_mut))) )] +#![cfg_attr( + not(bootstrap), + doc(cfg_hide( + not(test), + any(not(feature = "miri-test-libstd"), test, doctest), + no_fp_fmt_parse, + target_pointer_width = "16", + target_pointer_width = "32", + target_pointer_width = "64", + target_has_atomic = "8", + target_has_atomic = "16", + target_has_atomic = "32", + target_has_atomic = "64", + target_has_atomic = "ptr", + target_has_atomic_equal_alignment = "8", + target_has_atomic_equal_alignment = "16", + target_has_atomic_equal_alignment = "32", + target_has_atomic_equal_alignment = "64", + target_has_atomic_equal_alignment = "ptr", + target_has_atomic_load_store = "8", + target_has_atomic_load_store = "16", + target_has_atomic_load_store = "32", + target_has_atomic_load_store = "64", + target_has_atomic_load_store = "ptr", + )) +)] #![no_core] // // Lints: @@ -69,7 +95,6 @@ #![warn(missing_debug_implementations)] #![warn(missing_docs)] #![allow(explicit_outlives_requirements)] -#![cfg_attr(bootstrap, allow(incomplete_features))] // if_let_guard // // Library features for const fns: #![feature(const_align_of_val)] @@ -92,6 +117,7 @@ #![feature(const_maybe_uninit_assume_init)] #![feature(const_option)] #![feature(const_pin)] +#![feature(const_replace)] #![feature(const_ptr_offset)] #![feature(const_ptr_offset_from)] #![feature(const_ptr_read)] @@ -104,7 +130,6 @@ #![feature(const_trait_impl)] #![feature(const_type_id)] #![feature(const_type_name)] -#![feature(const_unreachable_unchecked)] #![feature(const_default_impls)] #![feature(duration_consts_2)] #![feature(ptr_metadata)] @@ -122,18 +147,18 @@ #![feature(const_fn_floating_point_arithmetic)] #![feature(const_fn_fn_ptr_basics)] #![feature(const_fn_trait_bound)] -#![cfg_attr(bootstrap, feature(const_fn_transmute))] -#![cfg_attr(bootstrap, feature(const_fn_union))] #![feature(const_impl_trait)] #![feature(const_mut_refs)] -#![feature(const_panic)] +#![cfg_attr(bootstrap, feature(const_panic))] #![feature(const_precise_live_drops)] #![feature(const_raw_ptr_deref)] #![feature(const_refs_to_cell)] #![feature(decl_macro)] #![feature(doc_cfg)] #![feature(doc_notable_trait)] +#![feature(doc_primitive)] #![feature(exhaustive_patterns)] +#![cfg_attr(not(bootstrap), feature(doc_cfg_hide))] #![feature(extern_types)] #![feature(fundamental)] #![feature(if_let_guard)] @@ -143,6 +168,8 @@ #![feature(link_llvm_intrinsics)] #![feature(llvm_asm)] #![feature(min_specialization)] +#![feature(mixed_integer_ops)] +#![cfg_attr(not(bootstrap), feature(must_not_suspend))] #![feature(negative_impls)] #![feature(never_type)] #![feature(no_core)] @@ -358,3 +385,5 @@ pub mod arch { /* compiler built-in */ } } + +include!("primitive_docs.rs"); diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs index 6f94e945d7..5b3e988caa 100644 --- a/library/core/src/macros/mod.rs +++ b/library/core/src/macros/mod.rs @@ -843,7 +843,6 @@ pub(crate) mod builtin { /// This macro is used by the panic macros for the `const_panic` feature. /// /// This macro will be removed once `format_args` is allowed in const contexts. - #[cfg(not(bootstrap))] #[unstable(feature = "const_format_args", issue = "none")] #[allow_internal_unstable(fmt_internals, const_fmt_arguments_new)] #[rustc_builtin_macro] @@ -853,16 +852,6 @@ pub(crate) mod builtin { ($fmt:expr, $($args:tt)*) => {{ /* compiler built-in */ }}; } - /// Same as `format_args`, but can be used in some const contexts. - #[cfg(bootstrap)] - #[unstable(feature = "const_format_args", issue = "none")] - #[macro_export] - macro_rules! const_format_args { - ($($t:tt)*) => { - $crate::format_args!($($t)*) - } - } - /// Same as `format_args`, but adds a newline in the end. #[unstable( feature = "format_args_nl", diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index 333f81ce4c..e5c3fafe5f 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -30,7 +30,8 @@ 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(not(test), rustc_diagnostic_item = "send_trait")] +#[cfg_attr(all(not(test), bootstrap), rustc_diagnostic_item = "send_trait")] +#[cfg_attr(all(not(test), not(bootstrap)), rustc_diagnostic_item = "Send")] #[rustc_on_unimplemented( message = "`{Self}` cannot be sent between threads safely", label = "`{Self}` cannot be sent between threads safely" @@ -99,17 +100,15 @@ pub trait Sized { /// `Unsize`. /// /// All implementations of `Unsize` are provided automatically by the compiler. +/// Those implementations are: /// -/// `Unsize` is implemented for: -/// -/// - `[T; N]` is `Unsize<[T]>` -/// - `T` is `Unsize` when `T: Trait` -/// - `Foo<..., T, ...>` is `Unsize>` if: -/// - `T: Unsize` -/// - Foo is a struct -/// - Only the last field of `Foo` has a type involving `T` -/// - `T` is not part of the type of any other fields -/// - `Bar: Unsize>`, if the last field of `Foo` has type `Bar` +/// - Arrays `[T; N]` implement `Unsize<[T]>`. +/// - Types implementing a trait `Trait` also implement `Unsize`. +/// - Structs `Foo<..., T, ...>` implement `Unsize>` if all of these conditions +/// are met: +/// - `T: Unsize`. +/// - Only the last field of `Foo` has a type involving `T`. +/// - `Bar: Unsize>`, where `Bar` stands for the actual type of that last field. /// /// `Unsize` is used along with [`ops::CoerceUnsized`] to allow /// "user-defined" containers such as [`Rc`] to contain dynamically-sized @@ -382,6 +381,7 @@ pub trait StructuralEq { // existing specializations on `Copy` that already exist in the standard // library, and there's no way to safely have this behavior right now. #[rustc_unsafe_specialization_marker] +#[rustc_diagnostic_item = "Copy"] pub trait Copy: Clone { // Empty. } @@ -460,7 +460,7 @@ pub macro Copy($item:item) { /// [transmute]: crate::mem::transmute /// [nomicon-send-and-sync]: ../../nomicon/send-and-sync.html #[stable(feature = "rust1", since = "1.0.0")] -#[cfg_attr(not(test), rustc_diagnostic_item = "sync_trait")] +#[cfg_attr(not(test), rustc_diagnostic_item = "Sync")] #[lang = "sync"] #[rustc_on_unimplemented( message = "`{Self}` cannot be shared between threads safely", diff --git a/library/core/src/mem/manually_drop.rs b/library/core/src/mem/manually_drop.rs index d86939454b..20b6453990 100644 --- a/library/core/src/mem/manually_drop.rs +++ b/library/core/src/mem/manually_drop.rs @@ -145,7 +145,8 @@ impl ManuallyDrop { } #[stable(feature = "manually_drop", since = "1.20.0")] -impl Deref for ManuallyDrop { +#[rustc_const_unstable(feature = "const_deref", issue = "88955")] +impl const Deref for ManuallyDrop { type Target = T; #[inline(always)] fn deref(&self) -> &T { @@ -154,7 +155,8 @@ impl Deref for ManuallyDrop { } #[stable(feature = "manually_drop", since = "1.20.0")] -impl DerefMut for ManuallyDrop { +#[rustc_const_unstable(feature = "const_deref", issue = "88955")] +impl const DerefMut for ManuallyDrop { #[inline(always)] fn deref_mut(&mut self) -> &mut T { &mut self.value diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs index 9c88a62336..624e879550 100644 --- a/library/core/src/mem/maybe_uninit.rs +++ b/library/core/src/mem/maybe_uninit.rs @@ -291,6 +291,7 @@ impl MaybeUninit { /// [`assume_init`]: MaybeUninit::assume_init #[stable(feature = "maybe_uninit", since = "1.36.0")] #[rustc_const_stable(feature = "const_maybe_uninit", since = "1.36.0")] + #[must_use = "use `forget` to avoid running Drop code"] #[inline(always)] pub const fn new(val: T) -> MaybeUninit { MaybeUninit { value: ManuallyDrop::new(val) } @@ -312,6 +313,7 @@ impl MaybeUninit { /// ``` #[stable(feature = "maybe_uninit", since = "1.36.0")] #[rustc_const_stable(feature = "const_maybe_uninit", since = "1.36.0")] + #[must_use] #[inline(always)] #[rustc_diagnostic_item = "maybe_uninit_uninit"] pub const fn uninit() -> MaybeUninit { @@ -349,6 +351,7 @@ impl MaybeUninit { /// ``` #[unstable(feature = "maybe_uninit_uninit_array", issue = "none")] #[rustc_const_unstable(feature = "maybe_uninit_uninit_array", issue = "none")] + #[must_use] #[inline(always)] pub const fn uninit_array() -> [Self; LEN] { // SAFETY: An uninitialized `[MaybeUninit<_>; LEN]` is valid. @@ -391,6 +394,7 @@ impl MaybeUninit { /// // This is undefined behavior. ⚠️ /// ``` #[stable(feature = "maybe_uninit", since = "1.36.0")] + #[must_use] #[inline] #[rustc_diagnostic_item = "maybe_uninit_zeroed"] pub fn zeroed() -> MaybeUninit { diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs index 84fd1a532c..894ae10e1b 100644 --- a/library/core/src/mem/mod.rs +++ b/library/core/src/mem/mod.rs @@ -1053,6 +1053,7 @@ pub const fn discriminant(v: &T) -> Discriminant { #[inline(always)] #[unstable(feature = "variant_count", issue = "73662")] #[rustc_const_unstable(feature = "variant_count", issue = "73662")] +#[rustc_diagnostic_item = "mem_variant_count"] pub const fn variant_count() -> usize { intrinsics::variant_count::() } diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs index c47a2e8b05..ad8106df19 100644 --- a/library/core/src/num/f32.rs +++ b/library/core/src/num/f32.rs @@ -436,6 +436,7 @@ impl f32 { /// assert!(nan.is_nan()); /// assert!(!f.is_nan()); /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")] #[inline] @@ -467,6 +468,7 @@ impl f32 { /// assert!(inf.is_infinite()); /// assert!(neg_inf.is_infinite()); /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")] #[inline] @@ -488,6 +490,7 @@ impl f32 { /// assert!(!inf.is_finite()); /// assert!(!neg_inf.is_finite()); /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")] #[inline] @@ -515,6 +518,7 @@ impl f32 { /// assert!(lower_than_min.is_subnormal()); /// ``` /// [subnormal]: https://en.wikipedia.org/wiki/Denormal_number + #[must_use] #[stable(feature = "is_subnormal", since = "1.53.0")] #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")] #[inline] @@ -541,6 +545,7 @@ impl f32 { /// assert!(!lower_than_min.is_normal()); /// ``` /// [subnormal]: https://en.wikipedia.org/wiki/Denormal_number + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")] #[inline] @@ -587,6 +592,7 @@ impl f32 { /// assert!(f.is_sign_positive()); /// assert!(!g.is_sign_positive()); /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")] #[inline] @@ -604,6 +610,7 @@ impl f32 { /// assert!(!f.is_sign_negative()); /// assert!(g.is_sign_negative()); /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")] #[inline] @@ -636,6 +643,8 @@ impl f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[stable(feature = "f32_deg_rad_conversions", since = "1.7.0")] #[inline] pub fn to_degrees(self) -> f32 { @@ -653,6 +662,8 @@ impl f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[stable(feature = "f32_deg_rad_conversions", since = "1.7.0")] #[inline] pub fn to_radians(self) -> f32 { @@ -712,6 +723,8 @@ impl f32 { /// * Not be `NaN` /// * Not be infinite /// * Be representable in the return type `Int`, after truncating off its fractional part + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[stable(feature = "float_approx_unchecked_to", since = "1.44.0")] #[inline] pub unsafe fn to_int_unchecked(self) -> Int @@ -740,6 +753,8 @@ impl f32 { /// assert_eq!((12.5f32).to_bits(), 0x41480000); /// /// ``` + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[stable(feature = "float_bits_conv", since = "1.20.0")] #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")] #[inline] @@ -786,6 +801,7 @@ impl f32 { /// ``` #[stable(feature = "float_bits_conv", since = "1.20.0")] #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")] + #[must_use] #[inline] pub const fn from_bits(v: u32) -> Self { // SAFETY: `u32` is a plain old datatype so we can always transmute from it @@ -802,6 +818,8 @@ impl f32 { /// let bytes = 12.5f32.to_be_bytes(); /// assert_eq!(bytes, [0x41, 0x48, 0x00, 0x00]); /// ``` + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[stable(feature = "float_to_from_bytes", since = "1.40.0")] #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")] #[inline] @@ -818,6 +836,8 @@ impl f32 { /// let bytes = 12.5f32.to_le_bytes(); /// assert_eq!(bytes, [0x00, 0x00, 0x48, 0x41]); /// ``` + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[stable(feature = "float_to_from_bytes", since = "1.40.0")] #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")] #[inline] @@ -847,6 +867,8 @@ impl f32 { /// } /// ); /// ``` + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[stable(feature = "float_to_from_bytes", since = "1.40.0")] #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")] #[inline] @@ -864,6 +886,7 @@ impl f32 { /// ``` #[stable(feature = "float_to_from_bytes", since = "1.40.0")] #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")] + #[must_use] #[inline] pub const fn from_be_bytes(bytes: [u8; 4]) -> Self { Self::from_bits(u32::from_be_bytes(bytes)) @@ -879,6 +902,7 @@ impl f32 { /// ``` #[stable(feature = "float_to_from_bytes", since = "1.40.0")] #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")] + #[must_use] #[inline] pub const fn from_le_bytes(bytes: [u8; 4]) -> Self { Self::from_bits(u32::from_le_bytes(bytes)) @@ -905,6 +929,7 @@ impl f32 { /// ``` #[stable(feature = "float_to_from_bytes", since = "1.40.0")] #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")] + #[must_use] #[inline] pub const fn from_ne_bytes(bytes: [u8; 4]) -> Self { Self::from_bits(u32::from_ne_bytes(bytes)) diff --git a/library/core/src/num/f64.rs b/library/core/src/num/f64.rs index cfcc08b9ad..6a48101e04 100644 --- a/library/core/src/num/f64.rs +++ b/library/core/src/num/f64.rs @@ -435,6 +435,7 @@ impl f64 { /// assert!(nan.is_nan()); /// assert!(!f.is_nan()); /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")] #[inline] @@ -466,6 +467,7 @@ impl f64 { /// assert!(inf.is_infinite()); /// assert!(neg_inf.is_infinite()); /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")] #[inline] @@ -487,6 +489,7 @@ impl f64 { /// assert!(!inf.is_finite()); /// assert!(!neg_inf.is_finite()); /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")] #[inline] @@ -514,6 +517,7 @@ impl f64 { /// assert!(lower_than_min.is_subnormal()); /// ``` /// [subnormal]: https://en.wikipedia.org/wiki/Denormal_number + #[must_use] #[stable(feature = "is_subnormal", since = "1.53.0")] #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")] #[inline] @@ -540,6 +544,7 @@ impl f64 { /// assert!(!lower_than_min.is_normal()); /// ``` /// [subnormal]: https://en.wikipedia.org/wiki/Denormal_number + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")] #[inline] @@ -586,6 +591,7 @@ impl f64 { /// assert!(f.is_sign_positive()); /// assert!(!g.is_sign_positive()); /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")] #[inline] @@ -593,6 +599,7 @@ impl f64 { !self.is_sign_negative() } + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_deprecated(since = "1.0.0", reason = "renamed to is_sign_positive")] #[inline] @@ -611,6 +618,7 @@ impl f64 { /// assert!(!f.is_sign_negative()); /// assert!(g.is_sign_negative()); /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")] #[inline] @@ -618,6 +626,7 @@ impl f64 { self.to_bits() & 0x8000_0000_0000_0000 != 0 } + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_deprecated(since = "1.0.0", reason = "renamed to is_sign_negative")] #[inline] @@ -649,6 +658,8 @@ impl f64 { /// /// assert!(abs_difference < 1e-10); /// ``` + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn to_degrees(self) -> f64 { @@ -667,6 +678,8 @@ impl f64 { /// /// assert!(abs_difference < 1e-10); /// ``` + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn to_radians(self) -> f64 { @@ -726,6 +739,8 @@ impl f64 { /// * Not be `NaN` /// * Not be infinite /// * Be representable in the return type `Int`, after truncating off its fractional part + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[stable(feature = "float_approx_unchecked_to", since = "1.44.0")] #[inline] pub unsafe fn to_int_unchecked(self) -> Int @@ -754,6 +769,8 @@ impl f64 { /// assert_eq!((12.5f64).to_bits(), 0x4029000000000000); /// /// ``` + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[stable(feature = "float_bits_conv", since = "1.20.0")] #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")] #[inline] @@ -800,6 +817,7 @@ impl f64 { /// ``` #[stable(feature = "float_bits_conv", since = "1.20.0")] #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")] + #[must_use] #[inline] pub const fn from_bits(v: u64) -> Self { // SAFETY: `u64` is a plain old datatype so we can always transmute from it @@ -816,6 +834,8 @@ impl f64 { /// let bytes = 12.5f64.to_be_bytes(); /// assert_eq!(bytes, [0x40, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]); /// ``` + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[stable(feature = "float_to_from_bytes", since = "1.40.0")] #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")] #[inline] @@ -832,6 +852,8 @@ impl f64 { /// let bytes = 12.5f64.to_le_bytes(); /// assert_eq!(bytes, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x40]); /// ``` + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[stable(feature = "float_to_from_bytes", since = "1.40.0")] #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")] #[inline] @@ -861,6 +883,8 @@ impl f64 { /// } /// ); /// ``` + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[stable(feature = "float_to_from_bytes", since = "1.40.0")] #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")] #[inline] @@ -878,6 +902,7 @@ impl f64 { /// ``` #[stable(feature = "float_to_from_bytes", since = "1.40.0")] #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")] + #[must_use] #[inline] pub const fn from_be_bytes(bytes: [u8; 8]) -> Self { Self::from_bits(u64::from_be_bytes(bytes)) @@ -893,6 +918,7 @@ impl f64 { /// ``` #[stable(feature = "float_to_from_bytes", since = "1.40.0")] #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")] + #[must_use] #[inline] pub const fn from_le_bytes(bytes: [u8; 8]) -> Self { Self::from_bits(u64::from_le_bytes(bytes)) @@ -919,6 +945,7 @@ impl f64 { /// ``` #[stable(feature = "float_to_from_bytes", since = "1.40.0")] #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")] + #[must_use] #[inline] pub const fn from_ne_bytes(bytes: [u8; 8]) -> Self { Self::from_bits(u64::from_ne_bytes(bytes)) diff --git a/library/core/src/num/fmt.rs b/library/core/src/num/fmt.rs index 578288bda2..8cff266642 100644 --- a/library/core/src/num/fmt.rs +++ b/library/core/src/num/fmt.rs @@ -31,8 +31,10 @@ impl<'a> Part<'a> { } else { 3 } + } else if v < 10_000 { + 4 } else { - if v < 10_000 { 4 } else { 5 } + 5 } } Part::Copy(buf) => buf.len(), diff --git a/library/core/src/num/int_log10.rs b/library/core/src/num/int_log10.rs index a23ca51ef8..a8455fb355 100644 --- a/library/core/src/num/int_log10.rs +++ b/library/core/src/num/int_log10.rs @@ -1,114 +1,120 @@ mod unchecked { // 0 < val <= u8::MAX + #[inline] pub const fn u8(val: u8) -> u32 { - if val >= 100 { - 2 - } else if val >= 10 { - 1 - } else { - 0 - } + let val = val as u32; + + // For better performance, avoid branches by assembling the solution + // in the bits above the low 8 bits. + + // Adding c1 to val gives 10 in the top bits for val < 10, 11 for val >= 10 + const C1: u32 = 0b11_00000000 - 10; // 758 + // Adding c2 to val gives 01 in the top bits for val < 100, 10 for val >= 100 + const C2: u32 = 0b10_00000000 - 100; // 412 + + // Value of top bits: + // +c1 +c2 1&2 + // 0..=9 10 01 00 = 0 + // 10..=99 11 01 01 = 1 + // 100..=255 11 10 10 = 2 + ((val + C1) & (val + C2)) >> 8 + } + + // 0 < val < 100_000 + #[inline] + const fn less_than_5(val: u32) -> u32 { + // Similar to u8, when adding one of these constants to val, + // we get two possible bit patterns above the low 17 bits, + // depending on whether val is below or above the threshold. + const C1: u32 = 0b011_00000000000000000 - 10; // 393206 + const C2: u32 = 0b100_00000000000000000 - 100; // 524188 + const C3: u32 = 0b111_00000000000000000 - 1000; // 916504 + const C4: u32 = 0b100_00000000000000000 - 10000; // 514288 + + // Value of top bits: + // +c1 +c2 1&2 +c3 +c4 3&4 ^ + // 0..=9 010 011 010 110 011 010 000 = 0 + // 10..=99 011 011 011 110 011 010 001 = 1 + // 100..=999 011 100 000 110 011 010 010 = 2 + // 1000..=9999 011 100 000 111 011 011 011 = 3 + // 10000..=99999 011 100 000 111 100 100 100 = 4 + (((val + C1) & (val + C2)) ^ ((val + C3) & (val + C4))) >> 17 } // 0 < val <= u16::MAX + #[inline] pub const fn u16(val: u16) -> u32 { - if val >= 10_000 { - 4 - } else if val >= 1000 { - 3 - } else if val >= 100 { - 2 - } else if val >= 10 { - 1 - } else { - 0 - } - } - - // 0 < val < 100_000_000 - const fn less_than_8(mut val: u32) -> u32 { - let mut log = 0; - if val >= 10_000 { - val /= 10_000; - log += 4; - } - log + if val >= 1000 { - 3 - } else if val >= 100 { - 2 - } else if val >= 10 { - 1 - } else { - 0 - } + less_than_5(val as u32) } // 0 < val <= u32::MAX + #[inline] pub const fn u32(mut val: u32) -> u32 { let mut log = 0; - if val >= 100_000_000 { - val /= 100_000_000; - log += 8; + if val >= 100_000 { + val /= 100_000; + log += 5; } - log + less_than_8(val) - } - - // 0 < val < 10_000_000_000_000_000 - const fn less_than_16(mut val: u64) -> u32 { - let mut log = 0; - if val >= 100_000_000 { - val /= 100_000_000; - log += 8; - } - log + less_than_8(val as u32) + log + less_than_5(val) } // 0 < val <= u64::MAX + #[inline] pub const fn u64(mut val: u64) -> u32 { let mut log = 0; - if val >= 10_000_000_000_000_000 { - val /= 10_000_000_000_000_000; - log += 16; + if val >= 10_000_000_000 { + val /= 10_000_000_000; + log += 10; } - log + less_than_16(val) + if val >= 100_000 { + val /= 100_000; + log += 5; + } + log + less_than_5(val as u32) } // 0 < val <= u128::MAX + #[inline] pub const fn u128(mut val: u128) -> u32 { let mut log = 0; if val >= 100_000_000_000_000_000_000_000_000_000_000 { val /= 100_000_000_000_000_000_000_000_000_000_000; log += 32; - return log + less_than_8(val as u32); + return log + u32(val as u32); } if val >= 10_000_000_000_000_000 { val /= 10_000_000_000_000_000; log += 16; } - log + less_than_16(val as u64) + log + u64(val as u64) } // 0 < val <= i8::MAX + #[inline] pub const fn i8(val: i8) -> u32 { u8(val as u8) } // 0 < val <= i16::MAX + #[inline] pub const fn i16(val: i16) -> u32 { u16(val as u16) } // 0 < val <= i32::MAX + #[inline] pub const fn i32(val: i32) -> u32 { u32(val as u32) } // 0 < val <= i64::MAX + #[inline] pub const fn i64(val: i64) -> u32 { u64(val as u64) } // 0 < val <= i128::MAX + #[inline] pub const fn i128(val: i128) -> u32 { u128(val as u128) } @@ -116,8 +122,9 @@ mod unchecked { macro_rules! impl_checked { ($T:ident) => { - pub const fn $T(val: $T) -> Option<$T> { - if val > 0 { Some(unchecked::$T(val) as $T) } else { None } + #[inline] + pub const fn $T(val: $T) -> Option { + if val > 0 { Some(unchecked::$T(val)) } else { None } } }; } diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs index 81209e9750..0bdc933013 100644 --- a/library/core/src/num/int_macros.rs +++ b/library/core/src/num/int_macros.rs @@ -81,6 +81,8 @@ macro_rules! int_impl { #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] #[doc(alias = "popcount")] #[doc(alias = "popcnt")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[inline(always)] pub const fn count_ones(self) -> u32 { (self as $UnsignedT).count_ones() } @@ -95,6 +97,8 @@ macro_rules! int_impl { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[inline(always)] pub const fn count_zeros(self) -> u32 { (!self).count_ones() @@ -113,6 +117,8 @@ macro_rules! int_impl { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[inline(always)] pub const fn leading_zeros(self) -> u32 { (self as $UnsignedT).leading_zeros() @@ -131,6 +137,8 @@ macro_rules! int_impl { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[inline(always)] pub const fn trailing_zeros(self) -> u32 { (self as $UnsignedT).trailing_zeros() @@ -149,6 +157,8 @@ macro_rules! int_impl { /// ``` #[stable(feature = "leading_trailing_ones", since = "1.46.0")] #[rustc_const_stable(feature = "leading_trailing_ones", since = "1.46.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[inline(always)] pub const fn leading_ones(self) -> u32 { (self as $UnsignedT).leading_ones() @@ -167,6 +177,8 @@ macro_rules! int_impl { /// ``` #[stable(feature = "leading_trailing_ones", since = "1.46.0")] #[rustc_const_stable(feature = "leading_trailing_ones", since = "1.46.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[inline(always)] pub const fn trailing_ones(self) -> u32 { (self as $UnsignedT).trailing_ones() @@ -236,6 +248,8 @@ macro_rules! int_impl { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[inline(always)] pub const fn swap_bytes(self) -> Self { (self as $UnsignedT).swap_bytes() as Self @@ -257,8 +271,9 @@ macro_rules! int_impl { /// ``` #[stable(feature = "reverse_bits", since = "1.37.0")] #[rustc_const_stable(feature = "const_int_methods", since = "1.37.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[inline(always)] - #[must_use] pub const fn reverse_bits(self) -> Self { (self as $UnsignedT).reverse_bits() as Self } @@ -282,6 +297,7 @@ macro_rules! int_impl { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_int_conversions", since = "1.32.0")] + #[must_use] #[inline] pub const fn from_be(x: Self) -> Self { #[cfg(target_endian = "big")] @@ -313,6 +329,7 @@ macro_rules! int_impl { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_int_conversions", since = "1.32.0")] + #[must_use] #[inline] pub const fn from_le(x: Self) -> Self { #[cfg(target_endian = "little")] @@ -344,6 +361,8 @@ macro_rules! int_impl { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_int_conversions", since = "1.32.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[inline] pub const fn to_be(self) -> Self { // or not to be? #[cfg(target_endian = "big")] @@ -375,6 +394,8 @@ macro_rules! int_impl { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_int_conversions", since = "1.32.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[inline] pub const fn to_le(self) -> Self { #[cfg(target_endian = "little")] @@ -433,6 +454,28 @@ macro_rules! int_impl { unsafe { intrinsics::unchecked_add(self, rhs) } } + /// Checked addition with an unsigned integer. Computes `self + rhs`, + /// returning `None` if overflow occurred. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// # #![feature(mixed_integer_ops)] + #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".checked_add_unsigned(2), Some(3));")] + #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX - 2).checked_add_unsigned(3), None);")] + /// ``` + #[unstable(feature = "mixed_integer_ops", issue = "87840")] + #[rustc_const_unstable(feature = "mixed_integer_ops", issue = "87840")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn checked_add_unsigned(self, rhs: $UnsignedT) -> Option { + let (a, b) = self.overflowing_add_unsigned(rhs); + if unlikely!(b) {None} else {Some(a)} + } + /// Checked integer subtraction. Computes `self - rhs`, returning `None` if /// overflow occurred. /// @@ -479,6 +522,28 @@ macro_rules! int_impl { unsafe { intrinsics::unchecked_sub(self, rhs) } } + /// Checked subtraction with an unsigned integer. Computes `self - rhs`, + /// returning `None` if overflow occurred. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// # #![feature(mixed_integer_ops)] + #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".checked_sub_unsigned(2), Some(-1));")] + #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MIN + 2).checked_sub_unsigned(3), None);")] + /// ``` + #[unstable(feature = "mixed_integer_ops", issue = "87840")] + #[rustc_const_unstable(feature = "mixed_integer_ops", issue = "87840")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn checked_sub_unsigned(self, rhs: $UnsignedT) -> Option { + let (a, b) = self.overflowing_sub_unsigned(rhs); + if unlikely!(b) {None} else {Some(a)} + } + /// Checked integer multiplication. Computes `self * rhs`, returning `None` if /// overflow occurred. /// @@ -543,7 +608,8 @@ macro_rules! int_impl { without modifying the original"] #[inline] pub const fn checked_div(self, rhs: Self) -> Option { - if unlikely!(rhs == 0 || (self == Self::MIN && rhs == -1)) { + // Using `&` helps LLVM see that it is the same check made in division. + if unlikely!(rhs == 0 || ((self == Self::MIN) & (rhs == -1))) { None } else { // SAFETY: div by zero and by INT_MIN have been checked above @@ -569,7 +635,8 @@ macro_rules! int_impl { without modifying the original"] #[inline] pub const fn checked_div_euclid(self, rhs: Self) -> Option { - if unlikely!(rhs == 0 || (self == Self::MIN && rhs == -1)) { + // Using `&` helps LLVM see that it is the same check made in division. + if unlikely!(rhs == 0 || ((self == Self::MIN) & (rhs == -1))) { None } else { Some(self.div_euclid(rhs)) @@ -595,7 +662,8 @@ macro_rules! int_impl { without modifying the original"] #[inline] pub const fn checked_rem(self, rhs: Self) -> Option { - if unlikely!(rhs == 0 || (self == Self::MIN && rhs == -1)) { + // Using `&` helps LLVM see that it is the same check made in division. + if unlikely!(rhs == 0 || ((self == Self::MIN) & (rhs == -1))) { None } else { // SAFETY: div by zero and by INT_MIN have been checked above @@ -621,7 +689,8 @@ macro_rules! int_impl { without modifying the original"] #[inline] pub const fn checked_rem_euclid(self, rhs: Self) -> Option { - if unlikely!(rhs == 0 || (self == Self::MIN && rhs == -1)) { + // Using `&` helps LLVM see that it is the same check made in division. + if unlikely!(rhs == 0 || ((self == Self::MIN) & (rhs == -1))) { None } else { Some(self.rem_euclid(rhs)) @@ -641,6 +710,8 @@ macro_rules! int_impl { /// ``` #[stable(feature = "wrapping", since = "1.7.0")] #[rustc_const_stable(feature = "const_checked_int_methods", since = "1.47.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[inline] pub const fn checked_neg(self) -> Option { let (a, b) = self.overflowing_neg(); @@ -753,6 +824,8 @@ macro_rules! int_impl { /// ``` #[stable(feature = "no_panic_abs", since = "1.13.0")] #[rustc_const_stable(feature = "const_checked_int_methods", since = "1.47.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[inline] pub const fn checked_abs(self) -> Option { if self.is_negative() { @@ -822,6 +895,32 @@ macro_rules! int_impl { intrinsics::saturating_add(self, rhs) } + /// Saturating addition with an unsigned integer. Computes `self + rhs`, + /// saturating at the numeric bounds instead of overflowing. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// # #![feature(mixed_integer_ops)] + #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".saturating_add_unsigned(2), 3);")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.saturating_add_unsigned(100), ", stringify!($SelfT), "::MAX);")] + /// ``` + #[unstable(feature = "mixed_integer_ops", issue = "87840")] + #[rustc_const_unstable(feature = "mixed_integer_ops", issue = "87840")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn saturating_add_unsigned(self, rhs: $UnsignedT) -> Self { + // Overflow can only happen at the upper bound + // We cannot use `unwrap_or` here because it is not `const` + match self.checked_add_unsigned(rhs) { + Some(x) => x, + None => Self::MAX, + } + } + /// Saturating integer subtraction. Computes `self - rhs`, saturating at the /// numeric bounds instead of overflowing. /// @@ -843,6 +942,32 @@ macro_rules! int_impl { intrinsics::saturating_sub(self, rhs) } + /// Saturating subtraction with an unsigned integer. Computes `self - rhs`, + /// saturating at the numeric bounds instead of overflowing. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// # #![feature(mixed_integer_ops)] + #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".saturating_sub_unsigned(127), -27);")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.saturating_sub_unsigned(100), ", stringify!($SelfT), "::MIN);")] + /// ``` + #[unstable(feature = "mixed_integer_ops", issue = "87840")] + #[rustc_const_unstable(feature = "mixed_integer_ops", issue = "87840")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn saturating_sub_unsigned(self, rhs: $UnsignedT) -> Self { + // Overflow can only happen at the lower bound + // We cannot use `unwrap_or` here because it is not `const` + match self.checked_sub_unsigned(rhs) { + Some(x) => x, + None => Self::MIN, + } + } + /// Saturating integer negation. Computes `-self`, returning `MAX` if `self == MIN` /// instead of overflowing. /// @@ -859,6 +984,8 @@ macro_rules! int_impl { #[stable(feature = "saturating_neg", since = "1.45.0")] #[rustc_const_stable(feature = "const_saturating_int_methods", since = "1.47.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[inline(always)] pub const fn saturating_neg(self) -> Self { intrinsics::saturating_sub(0, self) @@ -880,6 +1007,8 @@ macro_rules! int_impl { #[stable(feature = "saturating_neg", since = "1.45.0")] #[rustc_const_stable(feature = "const_saturating_int_methods", since = "1.47.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[inline] pub const fn saturating_abs(self) -> Self { if self.is_negative() { @@ -998,6 +1127,27 @@ macro_rules! int_impl { intrinsics::wrapping_add(self, rhs) } + /// Wrapping (modular) addition with an unsigned integer. Computes + /// `self + rhs`, wrapping around at the boundary of the type. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// # #![feature(mixed_integer_ops)] + #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".wrapping_add_unsigned(27), 127);")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.wrapping_add_unsigned(2), ", stringify!($SelfT), "::MIN + 1);")] + /// ``` + #[unstable(feature = "mixed_integer_ops", issue = "87840")] + #[rustc_const_unstable(feature = "mixed_integer_ops", issue = "87840")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline(always)] + pub const fn wrapping_add_unsigned(self, rhs: $UnsignedT) -> Self { + self.wrapping_add(rhs as Self) + } + /// Wrapping (modular) subtraction. Computes `self - rhs`, wrapping around at the /// boundary of the type. /// @@ -1018,6 +1168,27 @@ macro_rules! int_impl { intrinsics::wrapping_sub(self, rhs) } + /// Wrapping (modular) subtraction with an unsigned integer. Computes + /// `self - rhs`, wrapping around at the boundary of the type. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// # #![feature(mixed_integer_ops)] + #[doc = concat!("assert_eq!(0", stringify!($SelfT), ".wrapping_sub_unsigned(127), -127);")] + #[doc = concat!("assert_eq!((-2", stringify!($SelfT), ").wrapping_sub_unsigned(", stringify!($UnsignedT), "::MAX), -1);")] + /// ``` + #[unstable(feature = "mixed_integer_ops", issue = "87840")] + #[rustc_const_unstable(feature = "mixed_integer_ops", issue = "87840")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline(always)] + pub const fn wrapping_sub_unsigned(self, rhs: $UnsignedT) -> Self { + self.wrapping_sub(rhs as Self) + } + /// Wrapping (modular) multiplication. Computes `self * rhs`, wrapping around at /// the boundary of the type. /// @@ -1166,6 +1337,8 @@ macro_rules! int_impl { /// ``` #[stable(feature = "num_wrapping", since = "1.2.0")] #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[inline(always)] pub const fn wrapping_neg(self) -> Self { (0 as $SelfT).wrapping_sub(self) @@ -1248,6 +1421,8 @@ macro_rules! int_impl { /// ``` #[stable(feature = "no_panic_abs", since = "1.13.0")] #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[allow(unused_attributes)] #[inline] pub const fn wrapping_abs(self) -> Self { @@ -1273,6 +1448,8 @@ macro_rules! int_impl { /// ``` #[stable(feature = "unsigned_abs", since = "1.51.0")] #[rustc_const_stable(feature = "unsigned_abs", since = "1.51.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[inline] pub const fn unsigned_abs(self) -> $UnsignedT { self.wrapping_abs() as $UnsignedT @@ -1368,6 +1545,33 @@ macro_rules! int_impl { (sum as $SelfT, carry) } + /// Calculates `self` + `rhs` with an unsigned `rhs` + /// + /// Returns a tuple of the addition along with a boolean indicating + /// whether an arithmetic overflow would occur. If an overflow would + /// have occurred then the wrapped value is returned. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// # #![feature(mixed_integer_ops)] + #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".overflowing_add_unsigned(2), (3, false));")] + #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MIN).overflowing_add_unsigned(", stringify!($UnsignedT), "::MAX), (", stringify!($SelfT), "::MAX, false));")] + #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX - 2).overflowing_add_unsigned(3), (", stringify!($SelfT), "::MIN, true));")] + /// ``` + #[unstable(feature = "mixed_integer_ops", issue = "87840")] + #[rustc_const_unstable(feature = "mixed_integer_ops", issue = "87840")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn overflowing_add_unsigned(self, rhs: $UnsignedT) -> (Self, bool) { + let rhs = rhs as Self; + let (res, overflowed) = self.overflowing_add(rhs); + (res, overflowed ^ (rhs < 0)) + } + /// Calculates `self` - `rhs` /// /// Returns a tuple of the subtraction along with a boolean indicating whether an arithmetic overflow @@ -1419,6 +1623,33 @@ macro_rules! int_impl { (sum as $SelfT, borrow) } + /// Calculates `self` - `rhs` with an unsigned `rhs` + /// + /// Returns a tuple of the subtraction along with a boolean indicating + /// whether an arithmetic overflow would occur. If an overflow would + /// have occurred then the wrapped value is returned. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// # #![feature(mixed_integer_ops)] + #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".overflowing_sub_unsigned(2), (-1, false));")] + #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX).overflowing_sub_unsigned(", stringify!($UnsignedT), "::MAX), (", stringify!($SelfT), "::MIN, false));")] + #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MIN + 2).overflowing_sub_unsigned(3), (", stringify!($SelfT), "::MAX, true));")] + /// ``` + #[unstable(feature = "mixed_integer_ops", issue = "87840")] + #[rustc_const_unstable(feature = "mixed_integer_ops", issue = "87840")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn overflowing_sub_unsigned(self, rhs: $UnsignedT) -> (Self, bool) { + let rhs = rhs as Self; + let (res, overflowed) = self.overflowing_sub(rhs); + (res, overflowed ^ (rhs < 0)) + } + /// Calculates the multiplication of `self` and `rhs`. /// /// Returns a tuple of the multiplication along with a boolean indicating whether an arithmetic overflow @@ -1466,7 +1697,8 @@ macro_rules! int_impl { #[must_use = "this returns the result of the operation, \ without modifying the original"] pub const fn overflowing_div(self, rhs: Self) -> (Self, bool) { - if unlikely!(self == Self::MIN && rhs == -1) { + // Using `&` helps LLVM see that it is the same check made in division. + if unlikely!((self == Self::MIN) & (rhs == -1)) { (self, true) } else { (self / rhs, false) @@ -1496,7 +1728,8 @@ macro_rules! int_impl { #[must_use = "this returns the result of the operation, \ without modifying the original"] pub const fn overflowing_div_euclid(self, rhs: Self) -> (Self, bool) { - if unlikely!(self == Self::MIN && rhs == -1) { + // Using `&` helps LLVM see that it is the same check made in division. + if unlikely!((self == Self::MIN) & (rhs == -1)) { (self, true) } else { (self.div_euclid(rhs), false) @@ -1527,8 +1760,8 @@ macro_rules! int_impl { #[must_use = "this returns the result of the operation, \ without modifying the original"] pub const fn overflowing_rem(self, rhs: Self) -> (Self, bool) { - if unlikely!(self == Self::MIN && rhs == -1) { - (0, true) + if unlikely!(rhs == -1) { + (0, self == Self::MIN) } else { (self % rhs, false) } @@ -1558,8 +1791,8 @@ macro_rules! int_impl { without modifying the original"] #[inline] pub const fn overflowing_rem_euclid(self, rhs: Self) -> (Self, bool) { - if unlikely!(self == Self::MIN && rhs == -1) { - (0, true) + if unlikely!(rhs == -1) { + (0, self == Self::MIN) } else { (self.rem_euclid(rhs), false) } @@ -1583,6 +1816,8 @@ macro_rules! int_impl { #[inline] #[stable(feature = "wrapping", since = "1.7.0")] #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[allow(unused_attributes)] pub const fn overflowing_neg(self) -> (Self, bool) { if unlikely!(self == Self::MIN) { @@ -1657,6 +1892,8 @@ macro_rules! int_impl { /// ``` #[stable(feature = "no_panic_abs", since = "1.13.0")] #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[inline] pub const fn overflowing_abs(self) -> (Self, bool) { (self.wrapping_abs(), self == Self::MIN) @@ -2001,7 +2238,8 @@ macro_rules! int_impl { } } - /// Returns the logarithm of the number with respect to an arbitrary base. + /// Returns the logarithm of the number with respect to an arbitrary base, + /// rounded down. /// /// This method might not be optimized owing to implementation details; /// `log2` can produce results more efficiently for base 2, and `log10` @@ -2010,8 +2248,8 @@ macro_rules! int_impl { /// # Panics /// /// When the number is zero, or if the base is not at least 2; it - /// panics in debug mode and the return value is wrapped to 0 in release - /// mode (the only situation in which the method can return 0). + /// panics in debug mode and the return value is 0 in release + /// mode. /// /// # Examples /// @@ -2021,12 +2259,12 @@ macro_rules! int_impl { /// ``` #[unstable(feature = "int_log", issue = "70887")] #[must_use = "this returns the result of the operation, \ - without modifying the original"] + without modifying the original"] #[inline] #[track_caller] #[rustc_inherit_overflow_checks] #[allow(arithmetic_overflow)] - pub const fn log(self, base: Self) -> Self { + pub const fn log(self, base: Self) -> u32 { match self.checked_log(base) { Some(n) => n, None => { @@ -2039,13 +2277,12 @@ macro_rules! int_impl { } } - /// Returns the base 2 logarithm of the number. + /// Returns the base 2 logarithm of the number, rounded down. /// /// # Panics /// /// When the number is zero it panics in debug mode and the return value - /// is wrapped to 0 in release mode (the only situation in which the - /// method can return 0). + /// is 0 in release mode. /// /// # Examples /// @@ -2055,12 +2292,12 @@ macro_rules! int_impl { /// ``` #[unstable(feature = "int_log", issue = "70887")] #[must_use = "this returns the result of the operation, \ - without modifying the original"] + without modifying the original"] #[inline] #[track_caller] #[rustc_inherit_overflow_checks] #[allow(arithmetic_overflow)] - pub const fn log2(self) -> Self { + pub const fn log2(self) -> u32 { match self.checked_log2() { Some(n) => n, None => { @@ -2073,13 +2310,12 @@ macro_rules! int_impl { } } - /// Returns the base 10 logarithm of the number. + /// Returns the base 10 logarithm of the number, rounded down. /// /// # Panics /// /// When the number is zero it panics in debug mode and the return value - /// is wrapped to 0 in release mode (the only situation in which the - /// method can return 0). + /// is 0 in release mode. /// /// # Example /// @@ -2089,12 +2325,12 @@ macro_rules! int_impl { /// ``` #[unstable(feature = "int_log", issue = "70887")] #[must_use = "this returns the result of the operation, \ - without modifying the original"] + without modifying the original"] #[inline] #[track_caller] #[rustc_inherit_overflow_checks] #[allow(arithmetic_overflow)] - pub const fn log10(self) -> Self { + pub const fn log10(self) -> u32 { match self.checked_log10() { Some(n) => n, None => { @@ -2107,7 +2343,8 @@ macro_rules! int_impl { } } - /// Returns the logarithm of the number with respect to an arbitrary base. + /// Returns the logarithm of the number with respect to an arbitrary base, + /// rounded down. /// /// Returns `None` if the number is negative or zero, or if the base is not at least 2. /// @@ -2123,9 +2360,9 @@ macro_rules! int_impl { /// ``` #[unstable(feature = "int_log", issue = "70887")] #[must_use = "this returns the result of the operation, \ - without modifying the original"] + without modifying the original"] #[inline] - pub const fn checked_log(self, base: Self) -> Option { + pub const fn checked_log(self, base: Self) -> Option { if self <= 0 || base <= 1 { None } else { @@ -2147,7 +2384,7 @@ macro_rules! int_impl { } } - /// Returns the base 2 logarithm of the number. + /// Returns the base 2 logarithm of the number, rounded down. /// /// Returns `None` if the number is negative or zero. /// @@ -2159,19 +2396,19 @@ macro_rules! int_impl { /// ``` #[unstable(feature = "int_log", issue = "70887")] #[must_use = "this returns the result of the operation, \ - without modifying the original"] + without modifying the original"] #[inline] - pub const fn checked_log2(self) -> Option { + pub const fn checked_log2(self) -> Option { if self <= 0 { None } else { // SAFETY: We just checked that this number is positive - let log = (Self::BITS - 1) as Self - unsafe { intrinsics::ctlz_nonzero(self) }; + let log = (Self::BITS - 1) - unsafe { intrinsics::ctlz_nonzero(self) as u32 }; Some(log) } } - /// Returns the base 10 logarithm of the number. + /// Returns the base 10 logarithm of the number, rounded down. /// /// Returns `None` if the number is negative or zero. /// @@ -2183,13 +2420,10 @@ macro_rules! int_impl { /// ``` #[unstable(feature = "int_log", issue = "70887")] #[must_use = "this returns the result of the operation, \ - without modifying the original"] + without modifying the original"] #[inline] - pub const fn checked_log10(self) -> Option { - match int_log10::$ActualT(self as $ActualT) { - Some(s) => Some(s as Self), - None => None, - } + pub const fn checked_log10(self) -> Option { + int_log10::$ActualT(self as $ActualT) } /// Computes the absolute value of `self`. @@ -2217,6 +2451,8 @@ macro_rules! int_impl { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] #[allow(unused_attributes)] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[inline] #[rustc_inherit_overflow_checks] pub const fn abs(self) -> Self { @@ -2230,6 +2466,48 @@ macro_rules! int_impl { } } + /// Computes the absolute difference between `self` and `other`. + /// + /// This function always returns the correct answer without overflow or + /// panics by returning an unsigned integer. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(int_abs_diff)] + #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".abs_diff(80), 20", stringify!($UnsignedT), ");")] + #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".abs_diff(110), 10", stringify!($UnsignedT), ");")] + #[doc = concat!("assert_eq!((-100", stringify!($SelfT), ").abs_diff(80), 180", stringify!($UnsignedT), ");")] + #[doc = concat!("assert_eq!((-100", stringify!($SelfT), ").abs_diff(-120), 20", stringify!($UnsignedT), ");")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.abs_diff(", stringify!($SelfT), "::MAX), ", stringify!($UnsignedT), "::MAX);")] + /// ``` + #[unstable(feature = "int_abs_diff", issue = "89492")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn abs_diff(self, other: Self) -> $UnsignedT { + if self < other { + // Converting a non-negative x from signed to unsigned by using + // `x as U` is left unchanged, but a negative x is converted + // to value x + 2^N. Thus if `s` and `o` are binary variables + // respectively indicating whether `self` and `other` are + // negative, we are computing the mathematical value: + // + // (other + o*2^N) - (self + s*2^N) mod 2^N + // other - self + (o-s)*2^N mod 2^N + // other - self mod 2^N + // + // Finally, taking the mod 2^N of the mathematical value of + // `other - self` does not change it as it already is + // in the range [0, 2^N). + (other as $UnsignedT).wrapping_sub(self as $UnsignedT) + } else { + (self as $UnsignedT).wrapping_sub(other as $UnsignedT) + } + } + /// Returns a number representing sign of `self`. /// /// - `0` if the number is zero @@ -2247,6 +2525,8 @@ macro_rules! int_impl { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_int_sign", since = "1.47.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[inline(always)] pub const fn signum(self) -> Self { match self { @@ -2267,6 +2547,7 @@ macro_rules! int_impl { #[doc = concat!("assert!(10", stringify!($SelfT), ".is_positive());")] #[doc = concat!("assert!(!(-10", stringify!($SelfT), ").is_positive());")] /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] #[inline(always)] @@ -2283,6 +2564,7 @@ macro_rules! int_impl { #[doc = concat!("assert!((-10", stringify!($SelfT), ").is_negative());")] #[doc = concat!("assert!(!10", stringify!($SelfT), ".is_negative());")] /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] #[inline(always)] @@ -2301,6 +2583,8 @@ macro_rules! int_impl { /// ``` #[stable(feature = "int_to_from_bytes", since = "1.32.0")] #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[inline] pub const fn to_be_bytes(self) -> [u8; mem::size_of::()] { self.to_be().to_ne_bytes() @@ -2319,6 +2603,8 @@ macro_rules! int_impl { /// ``` #[stable(feature = "int_to_from_bytes", since = "1.32.0")] #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[inline] pub const fn to_le_bytes(self) -> [u8; mem::size_of::()] { self.to_le().to_ne_bytes() @@ -2353,7 +2639,8 @@ macro_rules! int_impl { #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")] // SAFETY: const sound because integers are plain old datatypes so we can always // transmute them to arrays of bytes - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_fn_transmute))] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[inline] pub const fn to_ne_bytes(self) -> [u8; mem::size_of::()] { // SAFETY: integers are plain old datatypes so we can always transmute them to @@ -2386,6 +2673,7 @@ macro_rules! int_impl { /// ``` #[stable(feature = "int_to_from_bytes", since = "1.32.0")] #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")] + #[must_use] #[inline] pub const fn from_be_bytes(bytes: [u8; mem::size_of::()]) -> Self { Self::from_be(Self::from_ne_bytes(bytes)) @@ -2416,6 +2704,7 @@ macro_rules! int_impl { /// ``` #[stable(feature = "int_to_from_bytes", since = "1.32.0")] #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")] + #[must_use] #[inline] pub const fn from_le_bytes(bytes: [u8; mem::size_of::()]) -> Self { Self::from_le(Self::from_ne_bytes(bytes)) @@ -2457,9 +2746,9 @@ macro_rules! int_impl { /// ``` #[stable(feature = "int_to_from_bytes", since = "1.32.0")] #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")] + #[must_use] // SAFETY: const sound because integers are plain old datatypes so we can always // transmute to them - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_fn_transmute))] #[inline] pub const fn from_ne_bytes(bytes: [u8; mem::size_of::()]) -> Self { // SAFETY: integers are plain old datatypes so we can always transmute to them diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs index 59b68cbe9c..18ebf1cbb1 100644 --- a/library/core/src/num/mod.rs +++ b/library/core/src/num/mod.rs @@ -245,7 +245,7 @@ const ASCII_CASE_MASK: u8 = 0b0010_0000; #[lang = "u8"] impl u8 { widening_impl! { u8, u16, 8 } - uint_impl! { u8, u8, 8, 255, 2, "0x82", "0xa", "0x12", "0x12", "0x48", "[0x12]", + uint_impl! { u8, u8, i8, 8, 255, 2, "0x82", "0xa", "0x12", "0x12", "0x48", "[0x12]", "[0x12]", "", "" } /// Checks if the value is within the ASCII range. @@ -259,6 +259,7 @@ impl u8 { /// assert!(ascii.is_ascii()); /// assert!(!non_ascii.is_ascii()); /// ``` + #[must_use] #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] #[rustc_const_stable(feature = "const_ascii_methods_on_intrinsics", since = "1.43.0")] #[inline] @@ -282,6 +283,7 @@ impl u8 { /// ``` /// /// [`make_ascii_uppercase`]: Self::make_ascii_uppercase + #[must_use = "to uppercase the value in-place, use `make_ascii_uppercase()`"] #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] #[rustc_const_stable(feature = "const_ascii_methods_on_intrinsics", since = "1.52.0")] #[inline] @@ -306,6 +308,7 @@ impl u8 { /// ``` /// /// [`make_ascii_lowercase`]: Self::make_ascii_lowercase + #[must_use = "to lowercase the value in-place, use `make_ascii_lowercase()`"] #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] #[rustc_const_stable(feature = "const_ascii_methods_on_intrinsics", since = "1.52.0")] #[inline] @@ -417,6 +420,7 @@ impl u8 { /// assert!(!lf.is_ascii_alphabetic()); /// assert!(!esc.is_ascii_alphabetic()); /// ``` + #[must_use] #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")] #[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")] #[inline] @@ -450,6 +454,7 @@ impl u8 { /// assert!(!lf.is_ascii_uppercase()); /// assert!(!esc.is_ascii_uppercase()); /// ``` + #[must_use] #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")] #[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")] #[inline] @@ -483,6 +488,7 @@ impl u8 { /// assert!(!lf.is_ascii_lowercase()); /// assert!(!esc.is_ascii_lowercase()); /// ``` + #[must_use] #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")] #[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")] #[inline] @@ -519,6 +525,7 @@ impl u8 { /// assert!(!lf.is_ascii_alphanumeric()); /// assert!(!esc.is_ascii_alphanumeric()); /// ``` + #[must_use] #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")] #[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")] #[inline] @@ -552,6 +559,7 @@ impl u8 { /// assert!(!lf.is_ascii_digit()); /// assert!(!esc.is_ascii_digit()); /// ``` + #[must_use] #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")] #[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")] #[inline] @@ -588,6 +596,7 @@ impl u8 { /// assert!(!lf.is_ascii_hexdigit()); /// assert!(!esc.is_ascii_hexdigit()); /// ``` + #[must_use] #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")] #[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")] #[inline] @@ -625,6 +634,7 @@ impl u8 { /// assert!(!lf.is_ascii_punctuation()); /// assert!(!esc.is_ascii_punctuation()); /// ``` + #[must_use] #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")] #[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")] #[inline] @@ -658,6 +668,7 @@ impl u8 { /// assert!(!lf.is_ascii_graphic()); /// assert!(!esc.is_ascii_graphic()); /// ``` + #[must_use] #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")] #[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")] #[inline] @@ -708,6 +719,7 @@ impl u8 { /// assert!(lf.is_ascii_whitespace()); /// assert!(!esc.is_ascii_whitespace()); /// ``` + #[must_use] #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")] #[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")] #[inline] @@ -743,6 +755,7 @@ impl u8 { /// assert!(lf.is_ascii_control()); /// assert!(esc.is_ascii_control()); /// ``` + #[must_use] #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")] #[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")] #[inline] @@ -769,6 +782,8 @@ impl u8 { /// assert_eq!("\\\\", b'\\'.escape_ascii().to_string()); /// assert_eq!("\\x9d", b'\x9d'.escape_ascii().to_string()); /// ``` + #[must_use = "this returns the escaped byte as an iterator, \ + without modifying the original"] #[unstable(feature = "inherent_ascii_escape", issue = "77174")] #[inline] pub fn escape_ascii(&self) -> ascii::EscapeDefault { @@ -779,21 +794,21 @@ impl u8 { #[lang = "u16"] impl u16 { widening_impl! { u16, u32, 16 } - uint_impl! { u16, u16, 16, 65535, 4, "0xa003", "0x3a", "0x1234", "0x3412", "0x2c48", + uint_impl! { u16, u16, i16, 16, 65535, 4, "0xa003", "0x3a", "0x1234", "0x3412", "0x2c48", "[0x34, 0x12]", "[0x12, 0x34]", "", "" } } #[lang = "u32"] impl u32 { widening_impl! { u32, u64, 32 } - uint_impl! { u32, u32, 32, 4294967295, 8, "0x10000b3", "0xb301", "0x12345678", + uint_impl! { u32, u32, i32, 32, 4294967295, 8, "0x10000b3", "0xb301", "0x12345678", "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]", "[0x12, 0x34, 0x56, 0x78]", "", "" } } #[lang = "u64"] impl u64 { widening_impl! { u64, u128, 64 } - uint_impl! { u64, u64, 64, 18446744073709551615, 12, "0xaa00000000006e1", "0x6e10aa", + 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]", @@ -802,7 +817,7 @@ impl u64 { #[lang = "u128"] impl u128 { - uint_impl! { u128, u128, 128, 340282366920938463463374607431768211455, 16, + uint_impl! { u128, u128, i128, 128, 340282366920938463463374607431768211455, 16, "0x13f40000000000000000000000004f76", "0x4f7613f4", "0x12345678901234567890123456789012", "0x12907856341290785634129078563412", "0x48091e6a2c48091e6a2c48091e6a2c48", "[0x12, 0x90, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78, \ @@ -816,7 +831,7 @@ impl u128 { #[lang = "usize"] impl usize { widening_impl! { usize, u32, 16 } - uint_impl! { usize, u16, 16, 65535, 4, "0xa003", "0x3a", "0x1234", "0x3412", "0x2c48", + 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!() } } @@ -824,7 +839,7 @@ impl usize { #[lang = "usize"] impl usize { widening_impl! { usize, u64, 32 } - uint_impl! { usize, u32, 32, 4294967295, 8, "0x10000b3", "0xb301", "0x12345678", + 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!() } } @@ -833,7 +848,7 @@ impl usize { #[lang = "usize"] impl usize { widening_impl! { usize, u128, 64 } - uint_impl! { usize, u64, 64, 18446744073709551615, 12, "0xaa00000000006e1", "0x6e10aa", + 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]", @@ -865,23 +880,41 @@ impl usize { #[derive(Copy, Clone, PartialEq, Eq, Debug)] #[stable(feature = "rust1", since = "1.0.0")] pub enum FpCategory { - /// "Not a Number", often obtained by dividing by zero. + /// NaN (not a number): this value results from calculations like `(-1.0).sqrt()`. + /// + /// See [the documentation for `f32`](f32) for more information on the unusual properties + /// of NaN. #[stable(feature = "rust1", since = "1.0.0")] Nan, - /// Positive or negative infinity. + /// Positive or negative infinity, which often results from dividing a nonzero number + /// by zero. #[stable(feature = "rust1", since = "1.0.0")] Infinite, /// Positive or negative zero. + /// + /// See [the documentation for `f32`](f32) for more information on the signedness of zeroes. #[stable(feature = "rust1", since = "1.0.0")] Zero, - /// De-normalized floating point representation (less precise than `Normal`). + /// “Subnormal” or “denormal” floating point representation (less precise, relative to + /// their magnitude, than [`Normal`]). + /// + /// Subnormal numbers are larger in magnitude than [`Zero`] but smaller in magnitude than all + /// [`Normal`] numbers. + /// + /// [`Normal`]: Self::Normal + /// [`Zero`]: Self::Zero #[stable(feature = "rust1", since = "1.0.0")] Subnormal, - /// A regular floating point number. + /// A regular floating point number, not any of the exceptional categories. + /// + /// The smallest positive normal numbers are [`f32::MIN_POSITIVE`] and [`f64::MIN_POSITIVE`], + /// and the largest positive normal numbers are [`f32::MAX`] and [`f64::MAX`]. (Unlike signed + /// integers, floating point numbers are symmetric in their range, so negating any of these + /// constants will produce their negative counterpart.) #[stable(feature = "rust1", since = "1.0.0")] Normal, } diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index dd9b9330ae..89fd9fbaf4 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -50,6 +50,7 @@ macro_rules! nonzero_integers { /// The value must not be zero. #[$stability] #[$const_new_unchecked_stability] + #[must_use] #[inline] pub const unsafe fn new_unchecked(n: $Int) -> Self { // SAFETY: this is guaranteed to be safe by the caller. @@ -59,6 +60,7 @@ macro_rules! nonzero_integers { /// Creates a non-zero if the given value is not zero. #[$stability] #[rustc_const_stable(feature = "const_nonzero_int_methods", since = "1.47.0")] + #[must_use] #[inline] pub const fn new(n: $Int) -> Option { if n != 0 { @@ -198,6 +200,8 @@ macro_rules! nonzero_leading_trailing_zeros { /// ``` #[stable(feature = "nonzero_leading_trailing_zeros", since = "1.53.0")] #[rustc_const_stable(feature = "nonzero_leading_trailing_zeros", since = "1.53.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[inline] pub const fn leading_zeros(self) -> u32 { // SAFETY: since `self` can not be zero it is safe to call ctlz_nonzero @@ -220,6 +224,8 @@ macro_rules! nonzero_leading_trailing_zeros { /// ``` #[stable(feature = "nonzero_leading_trailing_zeros", since = "1.53.0")] #[rustc_const_stable(feature = "nonzero_leading_trailing_zeros", since = "1.53.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[inline] pub const fn trailing_zeros(self) -> u32 { // SAFETY: since `self` can not be zero it is safe to call cttz_nonzero @@ -315,6 +321,8 @@ macro_rules! nonzero_unsigned_operations { /// # } /// ``` #[unstable(feature = "nonzero_ops", issue = "84186")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[inline] pub const fn checked_add(self, other: $Int) -> Option<$Ty> { if let Some(result) = self.get().checked_add(other) { @@ -348,6 +356,8 @@ macro_rules! nonzero_unsigned_operations { /// # } /// ``` #[unstable(feature = "nonzero_ops", issue = "84186")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[inline] pub const fn saturating_add(self, other: $Int) -> $Ty { // SAFETY: $Int::saturating_add returns $Int::MAX on overflow @@ -378,8 +388,10 @@ macro_rules! nonzero_unsigned_operations { /// # } /// ``` #[unstable(feature = "nonzero_ops", issue = "84186")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[inline] - pub unsafe fn unchecked_add(self, other: $Int) -> $Ty { + pub const unsafe fn unchecked_add(self, other: $Int) -> $Ty { // SAFETY: The caller ensures there is no overflow. unsafe { $Ty::new_unchecked(self.get().unchecked_add(other)) } } @@ -410,6 +422,8 @@ macro_rules! nonzero_unsigned_operations { /// # } /// ``` #[unstable(feature = "nonzero_ops", issue = "84186")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[inline] pub const fn checked_next_power_of_two(self) -> Option<$Ty> { if let Some(nz) = self.get().checked_next_power_of_two() { @@ -460,6 +474,8 @@ macro_rules! nonzero_signed_operations { /// # } /// ``` #[unstable(feature = "nonzero_ops", issue = "84186")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[inline] pub const fn abs(self) -> $Ty { // SAFETY: This cannot overflow to zero. @@ -490,6 +506,8 @@ macro_rules! nonzero_signed_operations { /// # } /// ``` #[unstable(feature = "nonzero_ops", issue = "84186")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[inline] pub const fn checked_abs(self) -> Option<$Ty> { if let Some(nz) = self.get().checked_abs() { @@ -524,6 +542,8 @@ macro_rules! nonzero_signed_operations { /// # } /// ``` #[unstable(feature = "nonzero_ops", issue = "84186")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[inline] pub const fn overflowing_abs(self) -> ($Ty, bool) { let (nz, flag) = self.get().overflowing_abs(); @@ -562,6 +582,8 @@ macro_rules! nonzero_signed_operations { /// # } /// ``` #[unstable(feature = "nonzero_ops", issue = "84186")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[inline] pub const fn saturating_abs(self) -> $Ty { // SAFETY: absolute value of nonzero cannot yield zero values. @@ -595,6 +617,8 @@ macro_rules! nonzero_signed_operations { /// # } /// ``` #[unstable(feature = "nonzero_ops", issue = "84186")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[inline] pub const fn wrapping_abs(self) -> $Ty { // SAFETY: absolute value of nonzero cannot yield zero values. @@ -628,6 +652,8 @@ macro_rules! nonzero_signed_operations { /// # } /// ``` #[unstable(feature = "nonzero_ops", issue = "84186")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[inline] pub const fn unsigned_abs(self) -> $Uty { // SAFETY: absolute value of nonzero cannot yield zero values. @@ -675,6 +701,8 @@ macro_rules! nonzero_unsigned_signed_operations { /// # } /// ``` #[unstable(feature = "nonzero_ops", issue = "84186")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[inline] pub const fn checked_mul(self, other: $Ty) -> Option<$Ty> { if let Some(result) = self.get().checked_mul(other.get()) { @@ -709,6 +737,8 @@ macro_rules! nonzero_unsigned_signed_operations { /// # } /// ``` #[unstable(feature = "nonzero_ops", issue = "84186")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[inline] pub const fn saturating_mul(self, other: $Ty) -> $Ty { // SAFETY: saturating_mul returns u*::MAX on overflow @@ -749,8 +779,10 @@ macro_rules! nonzero_unsigned_signed_operations { /// # } /// ``` #[unstable(feature = "nonzero_ops", issue = "84186")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[inline] - pub unsafe fn unchecked_mul(self, other: $Ty) -> $Ty { + pub const unsafe fn unchecked_mul(self, other: $Ty) -> $Ty { // SAFETY: The caller ensures there is no overflow. unsafe { $Ty::new_unchecked(self.get().unchecked_mul(other.get())) } } @@ -778,6 +810,8 @@ macro_rules! nonzero_unsigned_signed_operations { /// # } /// ``` #[unstable(feature = "nonzero_ops", issue = "84186")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[inline] pub const fn checked_pow(self, other: u32) -> Option<$Ty> { if let Some(result) = self.get().checked_pow(other) { @@ -820,6 +854,8 @@ macro_rules! nonzero_unsigned_signed_operations { /// # } /// ``` #[unstable(feature = "nonzero_ops", issue = "84186")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[inline] pub const fn saturating_pow(self, other: u32) -> $Ty { // SAFETY: saturating_pow returns u*::MAX on overflow @@ -878,6 +914,7 @@ macro_rules! nonzero_unsigned_is_power_of_two { #[doc = concat!("let ten = std::num::", stringify!($Ty), "::new(10).unwrap();")] /// assert!(!ten.is_power_of_two()); /// ``` + #[must_use] #[unstable(feature = "nonzero_is_power_of_two", issue = "81106")] #[inline] pub const fn is_power_of_two(self) -> bool { diff --git a/library/core/src/num/saturating.rs b/library/core/src/num/saturating.rs index f6dd3603c4..c764f420e2 100644 --- a/library/core/src/num/saturating.rs +++ b/library/core/src/num/saturating.rs @@ -474,6 +474,8 @@ macro_rules! saturating_int_impl { #[inline] #[doc(alias = "popcount")] #[doc(alias = "popcnt")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[unstable(feature = "saturating_int_impl", issue = "87920")] pub const fn count_ones(self) -> u32 { self.0.count_ones() @@ -492,6 +494,8 @@ macro_rules! saturating_int_impl { #[doc = concat!("assert_eq!(Saturating(!0", stringify!($t), ").count_zeros(), 0);")] /// ``` #[inline] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[unstable(feature = "saturating_int_impl", issue = "87920")] pub const fn count_zeros(self) -> u32 { self.0.count_zeros() @@ -512,6 +516,8 @@ macro_rules! saturating_int_impl { /// assert_eq!(n.trailing_zeros(), 3); /// ``` #[inline] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[unstable(feature = "saturating_int_impl", issue = "87920")] pub const fn trailing_zeros(self) -> u32 { self.0.trailing_zeros() @@ -538,6 +544,8 @@ macro_rules! saturating_int_impl { /// assert_eq!(n.rotate_left(32), m); /// ``` #[inline] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[unstable(feature = "saturating_int_impl", issue = "87920")] pub const fn rotate_left(self, n: u32) -> Self { Saturating(self.0.rotate_left(n)) @@ -564,6 +572,8 @@ macro_rules! saturating_int_impl { /// assert_eq!(n.rotate_right(4), m); /// ``` #[inline] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[unstable(feature = "saturating_int_impl", issue = "87920")] pub const fn rotate_right(self, n: u32) -> Self { Saturating(self.0.rotate_right(n)) @@ -588,6 +598,8 @@ macro_rules! saturating_int_impl { /// assert_eq!(m, Saturating(21760)); /// ``` #[inline] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[unstable(feature = "saturating_int_impl", issue = "87920")] pub const fn swap_bytes(self) -> Self { Saturating(self.0.swap_bytes()) @@ -614,10 +626,11 @@ macro_rules! saturating_int_impl { /// assert_eq!(m.0 as u16, 0b10101010_00000000); /// assert_eq!(m, Saturating(-22016)); /// ``` + #[inline] #[unstable(feature = "saturating_int_impl", issue = "87920")] #[rustc_const_stable(feature = "const_reverse_bits", since = "1.37.0")] - #[inline] - #[must_use] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] pub const fn reverse_bits(self) -> Self { Saturating(self.0.reverse_bits()) } @@ -644,6 +657,7 @@ macro_rules! saturating_int_impl { /// } /// ``` #[inline] + #[must_use] #[unstable(feature = "saturating_int_impl", issue = "87920")] pub const fn from_be(x: Self) -> Self { Saturating(<$t>::from_be(x.0)) @@ -671,6 +685,7 @@ macro_rules! saturating_int_impl { /// } /// ``` #[inline] + #[must_use] #[unstable(feature = "saturating_int_impl", issue = "87920")] pub const fn from_le(x: Self) -> Self { Saturating(<$t>::from_le(x.0)) @@ -699,6 +714,8 @@ macro_rules! saturating_int_impl { /// ``` #[inline] #[unstable(feature = "saturating_int_impl", issue = "87920")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] pub const fn to_be(self) -> Self { Saturating(self.0.to_be()) } @@ -726,6 +743,8 @@ macro_rules! saturating_int_impl { /// ``` #[inline] #[unstable(feature = "saturating_int_impl", issue = "87920")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] pub const fn to_le(self) -> Self { Saturating(self.0.to_le()) } @@ -754,6 +773,8 @@ macro_rules! saturating_int_impl { /// ``` #[inline] #[unstable(feature = "saturating_int_impl", issue = "87920")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] pub fn pow(self, exp: u32) -> Self { Saturating(self.0.saturating_pow(exp)) } @@ -782,6 +803,8 @@ macro_rules! saturating_int_impl_signed { /// ``` #[inline] #[unstable(feature = "saturating_int_impl", issue = "87920")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] pub const fn leading_zeros(self) -> u32 { self.0.leading_zeros() } @@ -805,6 +828,8 @@ macro_rules! saturating_int_impl_signed { /// ``` #[inline] #[unstable(feature = "saturating_int_impl", issue = "87920")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] pub fn abs(self) -> Saturating<$t> { Saturating(self.0.saturating_abs()) } @@ -829,6 +854,8 @@ macro_rules! saturating_int_impl_signed { /// ``` #[inline] #[unstable(feature = "saturating_int_impl", issue = "87920")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] pub fn signum(self) -> Saturating<$t> { Saturating(self.0.signum()) } @@ -847,6 +874,7 @@ macro_rules! saturating_int_impl_signed { #[doc = concat!("assert!(Saturating(10", stringify!($t), ").is_positive());")] #[doc = concat!("assert!(!Saturating(-10", stringify!($t), ").is_positive());")] /// ``` + #[must_use] #[inline] #[unstable(feature = "saturating_int_impl", issue = "87920")] pub const fn is_positive(self) -> bool { @@ -867,6 +895,7 @@ macro_rules! saturating_int_impl_signed { #[doc = concat!("assert!(Saturating(-10", stringify!($t), ").is_negative());")] #[doc = concat!("assert!(!Saturating(10", stringify!($t), ").is_negative());")] /// ``` + #[must_use] #[inline] #[unstable(feature = "saturating_int_impl", issue = "87920")] pub const fn is_negative(self) -> bool { @@ -908,6 +937,8 @@ macro_rules! saturating_int_impl_unsigned { /// ``` #[inline] #[unstable(feature = "saturating_int_impl", issue = "87920")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] pub const fn leading_zeros(self) -> u32 { self.0.leading_zeros() } @@ -925,6 +956,7 @@ macro_rules! saturating_int_impl_unsigned { #[doc = concat!("assert!(Saturating(16", stringify!($t), ").is_power_of_two());")] #[doc = concat!("assert!(!Saturating(10", stringify!($t), ").is_power_of_two());")] /// ``` + #[must_use] #[inline] #[unstable(feature = "saturating_int_impl", issue = "87920")] pub fn is_power_of_two(self) -> bool { diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index e79bf7bd7f..c3b2ecdb30 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -1,5 +1,5 @@ macro_rules! uint_impl { - ($SelfT:ty, $ActualT:ident, $BITS:expr, $MaxV:expr, + ($SelfT:ty, $ActualT:ident, $SignedT:ident, $BITS:expr, $MaxV:expr, $rot:expr, $rot_op:expr, $rot_result:expr, $swap_op:expr, $swapped:expr, $reversed:expr, $le_bytes:expr, $be_bytes:expr, $to_xe_bytes_doc:expr, $from_xe_bytes_doc:expr) => { @@ -80,6 +80,8 @@ macro_rules! uint_impl { #[rustc_const_stable(feature = "const_math", since = "1.32.0")] #[doc(alias = "popcount")] #[doc(alias = "popcnt")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[inline(always)] pub const fn count_ones(self) -> u32 { intrinsics::ctpop(self as $ActualT) as u32 @@ -96,6 +98,8 @@ macro_rules! uint_impl { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_math", since = "1.32.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[inline(always)] pub const fn count_zeros(self) -> u32 { (!self).count_ones() @@ -114,6 +118,8 @@ macro_rules! uint_impl { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_math", since = "1.32.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[inline(always)] pub const fn leading_zeros(self) -> u32 { intrinsics::ctlz(self as $ActualT) as u32 @@ -133,6 +139,8 @@ macro_rules! uint_impl { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_math", since = "1.32.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[inline(always)] pub const fn trailing_zeros(self) -> u32 { intrinsics::cttz(self) as u32 @@ -151,6 +159,8 @@ macro_rules! uint_impl { /// ``` #[stable(feature = "leading_trailing_ones", since = "1.46.0")] #[rustc_const_stable(feature = "leading_trailing_ones", since = "1.46.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[inline(always)] pub const fn leading_ones(self) -> u32 { (!self).leading_zeros() @@ -170,6 +180,8 @@ macro_rules! uint_impl { /// ``` #[stable(feature = "leading_trailing_ones", since = "1.46.0")] #[rustc_const_stable(feature = "leading_trailing_ones", since = "1.46.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[inline(always)] pub const fn trailing_ones(self) -> u32 { (!self).trailing_zeros() @@ -238,6 +250,8 @@ macro_rules! uint_impl { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_math", since = "1.32.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[inline(always)] pub const fn swap_bytes(self) -> Self { intrinsics::bswap(self as $ActualT) as Self @@ -259,8 +273,9 @@ macro_rules! uint_impl { /// ``` #[stable(feature = "reverse_bits", since = "1.37.0")] #[rustc_const_stable(feature = "const_math", since = "1.37.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[inline(always)] - #[must_use] pub const fn reverse_bits(self) -> Self { intrinsics::bitreverse(self as $ActualT) as Self } @@ -285,6 +300,7 @@ macro_rules! uint_impl { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_math", since = "1.32.0")] + #[must_use] #[inline(always)] pub const fn from_be(x: Self) -> Self { #[cfg(target_endian = "big")] @@ -317,6 +333,7 @@ macro_rules! uint_impl { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_math", since = "1.32.0")] + #[must_use] #[inline(always)] pub const fn from_le(x: Self) -> Self { #[cfg(target_endian = "little")] @@ -349,6 +366,8 @@ macro_rules! uint_impl { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_math", since = "1.32.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[inline(always)] pub const fn to_be(self) -> Self { // or not to be? #[cfg(target_endian = "big")] @@ -381,6 +400,8 @@ macro_rules! uint_impl { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_math", since = "1.32.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[inline(always)] pub const fn to_le(self) -> Self { #[cfg(target_endian = "little")] @@ -442,6 +463,29 @@ macro_rules! uint_impl { unsafe { intrinsics::unchecked_add(self, rhs) } } + /// Checked addition with a signed integer. Computes `self + rhs`, + /// returning `None` if overflow occurred. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// # #![feature(mixed_integer_ops)] + #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".checked_add_signed(2), Some(3));")] + #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".checked_add_signed(-2), None);")] + #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX - 2).checked_add_signed(3), None);")] + /// ``` + #[unstable(feature = "mixed_integer_ops", issue = "87840")] + #[rustc_const_unstable(feature = "mixed_integer_ops", issue = "87840")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn checked_add_signed(self, rhs: $SignedT) -> Option { + let (a, b) = self.overflowing_add_signed(rhs); + if unlikely!(b) {None} else {Some(a)} + } + /// Checked integer subtraction. Computes `self - rhs`, returning /// `None` if overflow occurred. /// @@ -635,7 +679,8 @@ macro_rules! uint_impl { } } - /// Returns the logarithm of the number with respect to an arbitrary base. + /// Returns the logarithm of the number with respect to an arbitrary base, + /// rounded down. /// /// This method might not be optimized owing to implementation details; /// `log2` can produce results more efficiently for base 2, and `log10` @@ -644,8 +689,7 @@ macro_rules! uint_impl { /// # Panics /// /// When the number is negative, zero, or if the base is not at least 2; - /// it panics in debug mode and the return value is wrapped to 0 in - /// release mode (the only situation in which the method can return 0). + /// it panics in debug mode and the return value is 0 in release mode. /// /// # Examples /// @@ -655,12 +699,12 @@ macro_rules! uint_impl { /// ``` #[unstable(feature = "int_log", issue = "70887")] #[must_use = "this returns the result of the operation, \ - without modifying the original"] + without modifying the original"] #[inline] #[track_caller] #[rustc_inherit_overflow_checks] #[allow(arithmetic_overflow)] - pub const fn log(self, base: Self) -> Self { + pub const fn log(self, base: Self) -> u32 { match self.checked_log(base) { Some(n) => n, None => { @@ -673,13 +717,12 @@ macro_rules! uint_impl { } } - /// Returns the base 2 logarithm of the number. + /// Returns the base 2 logarithm of the number, rounded down. /// /// # Panics /// /// When the number is negative or zero it panics in debug mode and - /// the return value is wrapped to 0 in release mode (the only situation in - /// which the method can return 0). + /// the return value is 0 in release mode. /// /// # Examples /// @@ -689,12 +732,12 @@ macro_rules! uint_impl { /// ``` #[unstable(feature = "int_log", issue = "70887")] #[must_use = "this returns the result of the operation, \ - without modifying the original"] + without modifying the original"] #[inline] #[track_caller] #[rustc_inherit_overflow_checks] #[allow(arithmetic_overflow)] - pub const fn log2(self) -> Self { + pub const fn log2(self) -> u32 { match self.checked_log2() { Some(n) => n, None => { @@ -707,13 +750,12 @@ macro_rules! uint_impl { } } - /// Returns the base 10 logarithm of the number. + /// Returns the base 10 logarithm of the number, rounded down. /// /// # Panics /// /// When the number is negative or zero it panics in debug mode and the - /// return value is wrapped to 0 in release mode (the only situation in - /// which the method can return 0). + /// return value is 0 in release mode. /// /// # Example /// @@ -723,12 +765,12 @@ macro_rules! uint_impl { /// ``` #[unstable(feature = "int_log", issue = "70887")] #[must_use = "this returns the result of the operation, \ - without modifying the original"] + without modifying the original"] #[inline] #[track_caller] #[rustc_inherit_overflow_checks] #[allow(arithmetic_overflow)] - pub const fn log10(self) -> Self { + pub const fn log10(self) -> u32 { match self.checked_log10() { Some(n) => n, None => { @@ -741,7 +783,8 @@ macro_rules! uint_impl { } } - /// Returns the logarithm of the number with respect to an arbitrary base. + /// Returns the logarithm of the number with respect to an arbitrary base, + /// rounded down. /// /// Returns `None` if the number is zero, or if the base is not at least 2. /// @@ -757,9 +800,9 @@ macro_rules! uint_impl { /// ``` #[unstable(feature = "int_log", issue = "70887")] #[must_use = "this returns the result of the operation, \ - without modifying the original"] + without modifying the original"] #[inline] - pub const fn checked_log(self, base: Self) -> Option { + pub const fn checked_log(self, base: Self) -> Option { if self <= 0 || base <= 1 { None } else { @@ -781,7 +824,7 @@ macro_rules! uint_impl { } } - /// Returns the base 2 logarithm of the number. + /// Returns the base 2 logarithm of the number, rounded down. /// /// Returns `None` if the number is zero. /// @@ -793,19 +836,19 @@ macro_rules! uint_impl { /// ``` #[unstable(feature = "int_log", issue = "70887")] #[must_use = "this returns the result of the operation, \ - without modifying the original"] + without modifying the original"] #[inline] - pub const fn checked_log2(self) -> Option { + pub const fn checked_log2(self) -> Option { if self <= 0 { None } else { // SAFETY: We just checked that this number is positive - let log = (Self::BITS - 1) as Self - unsafe { intrinsics::ctlz_nonzero(self) }; + let log = (Self::BITS - 1) - unsafe { intrinsics::ctlz_nonzero(self) as u32 }; Some(log) } } - /// Returns the base 10 logarithm of the number. + /// Returns the base 10 logarithm of the number, rounded down. /// /// Returns `None` if the number is zero. /// @@ -817,13 +860,10 @@ macro_rules! uint_impl { /// ``` #[unstable(feature = "int_log", issue = "70887")] #[must_use = "this returns the result of the operation, \ - without modifying the original"] + without modifying the original"] #[inline] - pub const fn checked_log10(self) -> Option { - match int_log10::$ActualT(self as $ActualT) { - Some(s) => Some(s as Self), - None => None, - } + pub const fn checked_log10(self) -> Option { + int_log10::$ActualT(self as $ActualT) } /// Checked negation. Computes `-self`, returning `None` unless `self == @@ -841,6 +881,8 @@ macro_rules! uint_impl { /// ``` #[stable(feature = "wrapping", since = "1.7.0")] #[rustc_const_stable(feature = "const_checked_int_methods", since = "1.47.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[inline] pub const fn checked_neg(self) -> Option { let (a, b) = self.overflowing_neg(); @@ -998,6 +1040,35 @@ macro_rules! uint_impl { intrinsics::saturating_add(self, rhs) } + /// Saturating addition with a signed integer. Computes `self + rhs`, + /// saturating at the numeric bounds instead of overflowing. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// # #![feature(mixed_integer_ops)] + #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".saturating_add_signed(2), 3);")] + #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".saturating_add_signed(-2), 0);")] + #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX - 2).saturating_add_signed(4), ", stringify!($SelfT), "::MAX);")] + /// ``` + #[unstable(feature = "mixed_integer_ops", issue = "87840")] + #[rustc_const_unstable(feature = "mixed_integer_ops", issue = "87840")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn saturating_add_signed(self, rhs: $SignedT) -> Self { + let (res, overflow) = self.overflowing_add(rhs as Self); + if overflow == (rhs < 0) { + res + } else if overflow { + Self::MAX + } else { + 0 + } + } + /// Saturating integer subtraction. Computes `self - rhs`, saturating /// at the numeric bounds instead of overflowing. /// @@ -1114,6 +1185,28 @@ macro_rules! uint_impl { intrinsics::wrapping_add(self, rhs) } + /// Wrapping (modular) addition with a signed integer. Computes + /// `self + rhs`, wrapping around at the boundary of the type. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// # #![feature(mixed_integer_ops)] + #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".wrapping_add_signed(2), 3);")] + #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".wrapping_add_signed(-2), ", stringify!($SelfT), "::MAX);")] + #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX - 2).wrapping_add_signed(4), 1);")] + /// ``` + #[unstable(feature = "mixed_integer_ops", issue = "87840")] + #[rustc_const_unstable(feature = "mixed_integer_ops", issue = "87840")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn wrapping_add_signed(self, rhs: $SignedT) -> Self { + self.wrapping_add(rhs as Self) + } + /// Wrapping (modular) subtraction. Computes `self - rhs`, /// wrapping around at the boundary of the type. /// @@ -1151,7 +1244,7 @@ macro_rules! uint_impl { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_wrapping_math", since = "1.32.0")] #[must_use = "this returns the result of the operation, \ - without modifying the original"] + without modifying the original"] #[inline(always)] pub const fn wrapping_mul(self, rhs: Self) -> Self { intrinsics::wrapping_mul(self, rhs) @@ -1276,6 +1369,8 @@ macro_rules! uint_impl { /// ``` #[stable(feature = "num_wrapping", since = "1.2.0")] #[rustc_const_stable(feature = "const_wrapping_math", since = "1.32.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[inline(always)] pub const fn wrapping_neg(self) -> Self { (0 as $SelfT).wrapping_sub(self) @@ -1438,6 +1533,32 @@ macro_rules! uint_impl { (c, b | d) } + /// Calculates `self` + `rhs` with a signed `rhs` + /// + /// Returns a tuple of the addition along with a boolean indicating + /// whether an arithmetic overflow would occur. If an overflow would + /// have occurred then the wrapped value is returned. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// # #![feature(mixed_integer_ops)] + #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".overflowing_add_signed(2), (3, false));")] + #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".overflowing_add_signed(-2), (", stringify!($SelfT), "::MAX, true));")] + #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX - 2).overflowing_add_signed(4), (1, true));")] + /// ``` + #[unstable(feature = "mixed_integer_ops", issue = "87840")] + #[rustc_const_unstable(feature = "mixed_integer_ops", issue = "87840")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn overflowing_add_signed(self, rhs: $SignedT) -> (Self, bool) { + let (res, overflowed) = self.overflowing_add(rhs as Self); + (res, overflowed ^ (rhs < 0)) + } + /// Calculates `self` - `rhs` /// /// Returns a tuple of the subtraction along with a boolean indicating @@ -1493,6 +1614,35 @@ macro_rules! uint_impl { (c, b | d) } + /// Computes the absolute difference between `self` and `other`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(int_abs_diff)] + #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".abs_diff(80), 20", stringify!($SelfT), ");")] + #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".abs_diff(110), 10", stringify!($SelfT), ");")] + /// ``` + #[unstable(feature = "int_abs_diff", issue = "89492")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn abs_diff(self, other: Self) -> Self { + if mem::size_of::() == 1 { + // Trick LLVM into generating the psadbw instruction when SSE2 + // is available and this function is autovectorized for u8's. + (self as i32).wrapping_sub(other as i32).abs() as Self + } else { + if self < other { + other - self + } else { + self - other + } + } + } + /// Calculates the multiplication of `self` and `rhs`. /// /// Returns a tuple of the multiplication along with a boolean @@ -1652,6 +1802,8 @@ macro_rules! uint_impl { #[inline(always)] #[stable(feature = "wrapping", since = "1.7.0")] #[rustc_const_stable(feature = "const_wrapping_math", since = "1.32.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] pub const fn overflowing_neg(self) -> (Self, bool) { ((!self).wrapping_add(1), self != 0) } @@ -1768,7 +1920,7 @@ macro_rules! uint_impl { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")] #[must_use = "this returns the result of the operation, \ - without modifying the original"] + without modifying the original"] #[inline] #[rustc_inherit_overflow_checks] pub const fn pow(self, mut exp: u32) -> Self { @@ -1865,6 +2017,8 @@ macro_rules! uint_impl { #[doc = concat!("assert_eq!(7_", stringify!($SelfT), ".unstable_div_floor(4), 1);")] /// ``` #[unstable(feature = "int_roundings", issue = "88581")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[inline(always)] #[rustc_inherit_overflow_checks] pub const fn unstable_div_floor(self, rhs: Self) -> Self { @@ -1886,6 +2040,8 @@ macro_rules! uint_impl { #[doc = concat!("assert_eq!(7_", stringify!($SelfT), ".unstable_div_ceil(4), 2);")] /// ``` #[unstable(feature = "int_roundings", issue = "88581")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[inline] #[rustc_inherit_overflow_checks] pub const fn unstable_div_ceil(self, rhs: Self) -> Self { @@ -1927,7 +2083,8 @@ macro_rules! uint_impl { } /// Calculates the smallest value greater than or equal to `self` that - /// is a multiple of `rhs`. If `rhs` is negative, + /// is a multiple of `rhs`. Returns `None` is `rhs` is zero or the + /// operation would result in overflow. /// /// # Examples /// @@ -1962,6 +2119,7 @@ macro_rules! uint_impl { #[doc = concat!("assert!(16", stringify!($SelfT), ".is_power_of_two());")] #[doc = concat!("assert!(!10", stringify!($SelfT), ".is_power_of_two());")] /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_is_power_of_two", since = "1.32.0")] #[inline(always)] @@ -1995,7 +2153,7 @@ macro_rules! uint_impl { /// Returns the smallest power of two greater than or equal to `self`. /// /// When return value overflows (i.e., `self > (1 << (N-1))` for type - /// `uN`), it panics in debug mode and return value is wrapped to 0 in + /// `uN`), it panics in debug mode and the return value is wrapped to 0 in /// release mode (the only situation in which method can return 0). /// /// # Examples @@ -2008,6 +2166,8 @@ macro_rules! uint_impl { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[inline] #[rustc_inherit_overflow_checks] pub const fn next_power_of_two(self) -> Self { @@ -2030,6 +2190,8 @@ macro_rules! uint_impl { #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] pub const fn checked_next_power_of_two(self) -> Option { self.one_less_than_next_power_of_two().checked_add(1) } @@ -2052,6 +2214,8 @@ macro_rules! uint_impl { #[unstable(feature = "wrapping_next_power_of_two", issue = "32463", reason = "needs decision on wrapping behaviour")] #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] pub const fn wrapping_next_power_of_two(self) -> Self { self.one_less_than_next_power_of_two().wrapping_add(1) } @@ -2069,6 +2233,8 @@ macro_rules! uint_impl { /// ``` #[stable(feature = "int_to_from_bytes", since = "1.32.0")] #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[inline] pub const fn to_be_bytes(self) -> [u8; mem::size_of::()] { self.to_be().to_ne_bytes() @@ -2087,6 +2253,8 @@ macro_rules! uint_impl { /// ``` #[stable(feature = "int_to_from_bytes", since = "1.32.0")] #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[inline] pub const fn to_le_bytes(self) -> [u8; mem::size_of::()] { self.to_le().to_ne_bytes() @@ -2119,9 +2287,10 @@ macro_rules! uint_impl { /// ``` #[stable(feature = "int_to_from_bytes", since = "1.32.0")] #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] // SAFETY: const sound because integers are plain old datatypes so we can always // transmute them to arrays of bytes - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_fn_transmute))] #[inline] pub const fn to_ne_bytes(self) -> [u8; mem::size_of::()] { // SAFETY: integers are plain old datatypes so we can always transmute them to @@ -2154,6 +2323,7 @@ macro_rules! uint_impl { /// ``` #[stable(feature = "int_to_from_bytes", since = "1.32.0")] #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")] + #[must_use] #[inline] pub const fn from_be_bytes(bytes: [u8; mem::size_of::()]) -> Self { Self::from_be(Self::from_ne_bytes(bytes)) @@ -2184,6 +2354,7 @@ macro_rules! uint_impl { /// ``` #[stable(feature = "int_to_from_bytes", since = "1.32.0")] #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")] + #[must_use] #[inline] pub const fn from_le_bytes(bytes: [u8; mem::size_of::()]) -> Self { Self::from_le(Self::from_ne_bytes(bytes)) @@ -2225,9 +2396,9 @@ macro_rules! uint_impl { /// ``` #[stable(feature = "int_to_from_bytes", since = "1.32.0")] #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")] + #[must_use] // SAFETY: const sound because integers are plain old datatypes so we can always // transmute to them - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_fn_transmute))] #[inline] pub const fn from_ne_bytes(bytes: [u8; mem::size_of::()]) -> Self { // SAFETY: integers are plain old datatypes so we can always transmute to them diff --git a/library/core/src/num/wrapping.rs b/library/core/src/num/wrapping.rs index be6d70320d..f387bd5b41 100644 --- a/library/core/src/num/wrapping.rs +++ b/library/core/src/num/wrapping.rs @@ -32,6 +32,10 @@ use crate::ops::{Shl, ShlAssign, Shr, ShrAssign, Sub, SubAssign}; /// /// assert_eq!(u32::MAX, (zero - one).0); /// ``` +/// +/// # Layout +/// +/// `Wrapping` is guaranteed to have the same layout and ABI as `T`. #[stable(feature = "rust1", since = "1.0.0")] #[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Default, Hash)] #[repr(transparent)] @@ -465,6 +469,8 @@ macro_rules! wrapping_int_impl { #[inline] #[doc(alias = "popcount")] #[doc(alias = "popcnt")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[unstable(feature = "wrapping_int_impl", issue = "32463")] pub const fn count_ones(self) -> u32 { self.0.count_ones() @@ -483,6 +489,8 @@ macro_rules! wrapping_int_impl { #[doc = concat!("assert_eq!(Wrapping(!0", stringify!($t), ").count_zeros(), 0);")] /// ``` #[inline] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[unstable(feature = "wrapping_int_impl", issue = "32463")] pub const fn count_zeros(self) -> u32 { self.0.count_zeros() @@ -503,6 +511,8 @@ macro_rules! wrapping_int_impl { /// assert_eq!(n.trailing_zeros(), 3); /// ``` #[inline] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[unstable(feature = "wrapping_int_impl", issue = "32463")] pub const fn trailing_zeros(self) -> u32 { self.0.trailing_zeros() @@ -529,6 +539,8 @@ macro_rules! wrapping_int_impl { /// assert_eq!(n.rotate_left(32), m); /// ``` #[inline] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[unstable(feature = "wrapping_int_impl", issue = "32463")] pub const fn rotate_left(self, n: u32) -> Self { Wrapping(self.0.rotate_left(n)) @@ -555,6 +567,8 @@ macro_rules! wrapping_int_impl { /// assert_eq!(n.rotate_right(4), m); /// ``` #[inline] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[unstable(feature = "wrapping_int_impl", issue = "32463")] pub const fn rotate_right(self, n: u32) -> Self { Wrapping(self.0.rotate_right(n)) @@ -579,6 +593,8 @@ macro_rules! wrapping_int_impl { /// assert_eq!(m, Wrapping(21760)); /// ``` #[inline] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[unstable(feature = "wrapping_int_impl", issue = "32463")] pub const fn swap_bytes(self) -> Self { Wrapping(self.0.swap_bytes()) @@ -606,8 +622,9 @@ macro_rules! wrapping_int_impl { /// ``` #[stable(feature = "reverse_bits", since = "1.37.0")] #[rustc_const_stable(feature = "const_reverse_bits", since = "1.37.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[inline] - #[must_use] pub const fn reverse_bits(self) -> Self { Wrapping(self.0.reverse_bits()) } @@ -634,6 +651,7 @@ macro_rules! wrapping_int_impl { /// } /// ``` #[inline] + #[must_use] #[unstable(feature = "wrapping_int_impl", issue = "32463")] pub const fn from_be(x: Self) -> Self { Wrapping(<$t>::from_be(x.0)) @@ -661,6 +679,7 @@ macro_rules! wrapping_int_impl { /// } /// ``` #[inline] + #[must_use] #[unstable(feature = "wrapping_int_impl", issue = "32463")] pub const fn from_le(x: Self) -> Self { Wrapping(<$t>::from_le(x.0)) @@ -688,6 +707,8 @@ macro_rules! wrapping_int_impl { /// } /// ``` #[inline] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[unstable(feature = "wrapping_int_impl", issue = "32463")] pub const fn to_be(self) -> Self { Wrapping(self.0.to_be()) @@ -715,6 +736,8 @@ macro_rules! wrapping_int_impl { /// } /// ``` #[inline] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[unstable(feature = "wrapping_int_impl", issue = "32463")] pub const fn to_le(self) -> Self { Wrapping(self.0.to_le()) @@ -743,6 +766,8 @@ macro_rules! wrapping_int_impl { /// assert_eq!(Wrapping(3i8).pow(6), Wrapping(-39)); /// ``` #[inline] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[unstable(feature = "wrapping_int_impl", issue = "32463")] pub fn pow(self, exp: u32) -> Self { Wrapping(self.0.wrapping_pow(exp)) @@ -771,6 +796,8 @@ macro_rules! wrapping_int_impl_signed { /// assert_eq!(n.leading_zeros(), 3); /// ``` #[inline] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[unstable(feature = "wrapping_int_impl", issue = "32463")] pub const fn leading_zeros(self) -> u32 { self.0.leading_zeros() @@ -797,6 +824,8 @@ macro_rules! wrapping_int_impl_signed { /// assert_eq!(Wrapping(-128i8).abs().0 as u8, 128u8); /// ``` #[inline] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[unstable(feature = "wrapping_int_impl", issue = "32463")] pub fn abs(self) -> Wrapping<$t> { Wrapping(self.0.wrapping_abs()) @@ -821,6 +850,8 @@ macro_rules! wrapping_int_impl_signed { #[doc = concat!("assert_eq!(Wrapping(-10", stringify!($t), ").signum(), Wrapping(-1));")] /// ``` #[inline] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[unstable(feature = "wrapping_int_impl", issue = "32463")] pub fn signum(self) -> Wrapping<$t> { Wrapping(self.0.signum()) @@ -840,6 +871,7 @@ macro_rules! wrapping_int_impl_signed { #[doc = concat!("assert!(Wrapping(10", stringify!($t), ").is_positive());")] #[doc = concat!("assert!(!Wrapping(-10", stringify!($t), ").is_positive());")] /// ``` + #[must_use] #[inline] #[unstable(feature = "wrapping_int_impl", issue = "32463")] pub const fn is_positive(self) -> bool { @@ -860,6 +892,7 @@ macro_rules! wrapping_int_impl_signed { #[doc = concat!("assert!(Wrapping(-10", stringify!($t), ").is_negative());")] #[doc = concat!("assert!(!Wrapping(10", stringify!($t), ").is_negative());")] /// ``` + #[must_use] #[inline] #[unstable(feature = "wrapping_int_impl", issue = "32463")] pub const fn is_negative(self) -> bool { @@ -889,6 +922,8 @@ macro_rules! wrapping_int_impl_unsigned { /// assert_eq!(n.leading_zeros(), 2); /// ``` #[inline] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[unstable(feature = "wrapping_int_impl", issue = "32463")] pub const fn leading_zeros(self) -> u32 { self.0.leading_zeros() @@ -907,6 +942,7 @@ macro_rules! wrapping_int_impl_unsigned { #[doc = concat!("assert!(Wrapping(16", stringify!($t), ").is_power_of_two());")] #[doc = concat!("assert!(!Wrapping(10", stringify!($t), ").is_power_of_two());")] /// ``` + #[must_use] #[inline] #[unstable(feature = "wrapping_int_impl", issue = "32463")] pub fn is_power_of_two(self) -> bool { @@ -931,6 +967,8 @@ macro_rules! wrapping_int_impl_unsigned { #[doc = concat!("assert_eq!(Wrapping(200_u8).next_power_of_two(), Wrapping(0));")] /// ``` #[inline] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[unstable(feature = "wrapping_next_power_of_two", issue = "32463", reason = "needs decision on wrapping behaviour")] pub fn next_power_of_two(self) -> Self { diff --git a/library/core/src/ops/bit.rs b/library/core/src/ops/bit.rs index 51f8043817..92f45ac9e7 100644 --- a/library/core/src/ops/bit.rs +++ b/library/core/src/ops/bit.rs @@ -30,6 +30,7 @@ /// ``` #[lang = "not"] #[stable(feature = "rust1", since = "1.0.0")] +#[doc(alias = "!")] pub trait Not { /// The resulting type after applying the `!` operator. #[stable(feature = "rust1", since = "1.0.0")] diff --git a/library/core/src/ops/deref.rs b/library/core/src/ops/deref.rs index dcf3ce070e..fb4ec83bc2 100644 --- a/library/core/src/ops/deref.rs +++ b/library/core/src/ops/deref.rs @@ -76,7 +76,8 @@ pub trait Deref { } #[stable(feature = "rust1", since = "1.0.0")] -impl Deref for &T { +#[rustc_const_unstable(feature = "const_deref", issue = "88955")] +impl const Deref for &T { type Target = T; #[rustc_diagnostic_item = "noop_method_deref"] @@ -89,7 +90,8 @@ impl Deref for &T { impl !DerefMut for &T {} #[stable(feature = "rust1", since = "1.0.0")] -impl Deref for &mut T { +#[rustc_const_unstable(feature = "const_deref", issue = "88955")] +impl const Deref for &mut T { type Target = T; fn deref(&self) -> &T { diff --git a/library/core/src/option.rs b/library/core/src/option.rs index 9d5e03dd0d..8850583215 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -47,9 +47,9 @@ //! //! Rust's pointer types must always point to a valid location; there are //! no "null" references. Instead, Rust has *optional* pointers, like -//! the optional owned box, [`Option`]`<`[`Box`]`>`. +//! the optional owned box, [Option]<[Box\]>. //! -//! [`Box`]: ../../std/boxed/struct.Box.html +//! [Box\]: ../../std/boxed/struct.Box.html //! //! The following example uses [`Option`] to create an optional box of //! [`i32`]. Notice that in order to use the inner [`i32`] value, the @@ -111,16 +111,20 @@ //! //! ## Adapters for working with references //! -//! * [`as_ref`] converts from `&Option` to `Option<&T>` -//! * [`as_mut`] converts from `&mut Option` to `Option<&mut T>` -//! * [`as_deref`] converts from `&Option` to `Option<&T::Target>` -//! * [`as_deref_mut`] converts from `&mut Option` to -//! `Option<&mut T::Target>` -//! * [`as_pin_ref`] converts from [`Pin`]`<&Option>` to -//! `Option<`[`Pin`]`<&T>>` -//! * [`as_pin_mut`] converts from [`Pin`]`<&mut Option>` to -//! `Option<`[`Pin`]`<&mut T>>` +//! * [`as_ref`] converts from [&][][Option]\ to [Option]<[&]T> +//! * [`as_mut`] converts from [&mut] [Option]\ to [Option]<[&mut] T> +//! * [`as_deref`] converts from [&][][Option]\ to +//! [Option]<[&]T::[Target]> +//! * [`as_deref_mut`] converts from [&mut] [Option]\ to +//! [Option]<[&mut] T::[Target]> +//! * [`as_pin_ref`] converts from [Pin]<[&][][Option]\> to +//! [Option]<[Pin]<[&]T>> +//! * [`as_pin_mut`] converts from [Pin]<[&mut] [Option]\> to +//! [Option]<[Pin]<[&mut] T>> //! +//! [&]: reference "shared reference" +//! [&mut]: reference "mutable reference" +//! [Target]: Deref::Target "ops::Deref::Target" //! [`as_deref`]: Option::as_deref //! [`as_deref_mut`]: Option::as_deref_mut //! [`as_mut`]: Option::as_mut @@ -505,7 +509,7 @@ use crate::{ /// The `Option` type. See [the module level documentation](self) for more. #[derive(Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)] -#[rustc_diagnostic_item = "option_type"] +#[rustc_diagnostic_item = "Option"] #[stable(feature = "rust1", since = "1.0.0")] pub enum Option { /// No value @@ -540,8 +544,8 @@ impl Option { /// ``` #[must_use = "if you intended to assert that this has a value, consider `.unwrap()` instead"] #[inline] - #[rustc_const_stable(feature = "const_option", since = "1.48.0")] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_option", since = "1.48.0")] pub const fn is_some(&self) -> bool { matches!(*self, Some(_)) } @@ -560,8 +564,8 @@ impl Option { #[must_use = "if you intended to assert that this doesn't have a value, consider \ `.and_then(|_| panic!(\"`Option` had a value when expected `None`\"))` instead"] #[inline] - #[rustc_const_stable(feature = "const_option", since = "1.48.0")] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "const_option", since = "1.48.0")] pub const fn is_none(&self) -> bool { !self.is_some() } @@ -603,13 +607,13 @@ impl Option { /// /// # Examples /// - /// Converts an `Option<`[`String`]`>` into an `Option<`[`usize`]`>`, preserving the original. - /// The [`map`] method takes the `self` argument by value, consuming the original, + /// Converts an Option<[String]> into an Option<[usize]>, preserving + /// the original. The [`map`] method takes the `self` argument by value, consuming the original, /// so this technique uses `as_ref` to first take an `Option` to a reference /// to the value inside the original. /// /// [`map`]: Option::map - /// [`String`]: ../../std/string/struct.String.html + /// [String]: ../../std/string/struct.String.html "String" /// /// ``` /// let text: Option = Some("Hello, world!".to_string()); @@ -642,15 +646,19 @@ impl Option { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - pub fn as_mut(&mut self) -> Option<&mut T> { + #[rustc_const_unstable(feature = "const_option", issue = "67441")] + pub const fn as_mut(&mut self) -> Option<&mut T> { match *self { Some(ref mut x) => Some(x), None => None, } } - /// Converts from [`Pin`]`<&Option>` to `Option<`[`Pin`]`<&T>>`. + /// Converts from [Pin]<[&]Option\> to Option<[Pin]<[&]T>>. + /// + /// [&]: reference "shared reference" #[inline] + #[must_use] #[stable(feature = "pin", since = "1.33.0")] pub fn as_pin_ref(self: Pin<&Self>) -> Option> { // SAFETY: `x` is guaranteed to be pinned because it comes from `self` @@ -658,8 +666,11 @@ impl Option { unsafe { Pin::get_ref(self).as_ref().map(|x| Pin::new_unchecked(x)) } } - /// Converts from [`Pin`]`<&mut Option>` to `Option<`[`Pin`]`<&mut T>>`. + /// Converts from [Pin]<[&mut] Option\> to Option<[Pin]<[&mut] T>>. + /// + /// [&mut]: reference "mutable reference" #[inline] + #[must_use] #[stable(feature = "pin", since = "1.33.0")] pub fn as_pin_mut(self: Pin<&mut Self>) -> Option> { // SAFETY: `get_unchecked_mut` is never used to move the `Option` inside `self`. @@ -819,9 +830,10 @@ impl Option { /// /// # Examples /// - /// Converts an `Option<`[`String`]`>` into an `Option<`[`usize`]`>`, consuming the original: + /// Converts an Option<[String]> into an Option<[usize]>, consuming + /// the original: /// - /// [`String`]: ../../std/string/struct.String.html + /// [String]: ../../std/string/struct.String.html "String" /// ``` /// let maybe_some_string = Some(String::from("Hello, World!")); /// // `Option::map` takes self *by value*, consuming `maybe_some_string` @@ -1173,7 +1185,7 @@ impl Option { // Entry-like operations to insert a value and return a reference ///////////////////////////////////////////////////////////////////////// - /// Inserts `value` into the option then returns a mutable reference to it. + /// Inserts `value` into the option, then returns a mutable reference to it. /// /// If the option already contains a value, the old value is dropped. /// @@ -1309,8 +1321,10 @@ impl Option { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - pub fn take(&mut self) -> Option { - mem::take(self) + #[rustc_const_unstable(feature = "const_option", issue = "67441")] + pub const fn take(&mut self) -> Option { + // FIXME replace `mem::replace` by `mem::take` when the latter is const ready + mem::replace(self, None) } /// Replaces the actual value in the option by the value given in parameter, @@ -1331,8 +1345,9 @@ impl Option { /// assert_eq!(old, None); /// ``` #[inline] + #[rustc_const_unstable(feature = "const_option", issue = "67441")] #[stable(feature = "option_replace", since = "1.31.0")] - pub fn replace(&mut self, value: T) -> Option { + pub const fn replace(&mut self, value: T) -> Option { mem::replace(self, Some(value)) } @@ -1397,7 +1412,7 @@ impl Option { } impl Option<(T, U)> { - /// Unzips an option containing a tuple of two options + /// Unzips an option containing a tuple of two options. /// /// If `self` is `Some((a, b))` this method returns `(Some(a), Some(b))`. /// Otherwise, `(None, None)` is returned. @@ -1437,8 +1452,14 @@ impl Option<&T> { /// assert_eq!(copied, Some(12)); /// ``` #[stable(feature = "copied", since = "1.35.0")] - pub fn copied(self) -> Option { - self.map(|&t| t) + #[rustc_const_unstable(feature = "const_option", issue = "67441")] + pub const fn copied(self) -> Option { + // FIXME: this implementation, which sidesteps using `Option::map` since it's not const + // ready yet, should be reverted when possible to avoid code repetition + match self { + Some(&v) => Some(v), + None => None, + } } } @@ -1455,6 +1476,7 @@ impl Option<&mut 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")] pub fn copied(self) -> Option { self.map(|&mut t| t) @@ -1474,6 +1496,7 @@ impl Option<&T> { /// let cloned = opt_x.cloned(); /// assert_eq!(cloned, Some(12)); /// ``` + #[must_use = "`self` will be dropped if the result is not used"] #[stable(feature = "rust1", since = "1.0.0")] pub fn cloned(self) -> Option { self.map(|t| t.clone()) @@ -1500,7 +1523,7 @@ impl Option<&mut T> { } impl Option { - /// Returns the contained [`Some`] value or a default + /// Returns the contained [`Some`] value or a default. /// /// Consumes the `self` argument then, if [`Some`], returns the contained /// value, otherwise if [`None`], returns the [default value] for that @@ -1561,7 +1584,7 @@ impl Option { /// Converts from `Option` (or `&mut Option`) to `Option<&mut T::Target>`. /// /// Leaves the original `Option` in-place, creating a new one containing a mutable reference to - /// the inner type's `Deref::Target` type. + /// the inner type's [`Deref::Target`] type. /// /// # Examples /// @@ -1581,9 +1604,9 @@ impl Option { impl Option> { /// Transposes an `Option` of a [`Result`] into a [`Result`] of an `Option`. /// - /// [`None`] will be mapped to [`Ok`]`(`[`None`]`)`. - /// [`Some`]`(`[`Ok`]`(_))` and [`Some`]`(`[`Err`]`(_))` will be mapped to - /// [`Ok`]`(`[`Some`]`(_))` and [`Err`]`(_)`. + /// [`None`] will be mapped to [Ok]\([None]). + /// [Some]\([Ok]\(\_)) and [Some]\([Err]\(\_)) will be mapped to + /// [Ok]\([Some]\(\_)) and [Err]\(\_). /// /// # Examples /// @@ -1701,7 +1724,7 @@ impl<'a, T> IntoIterator for &'a mut Option { #[stable(since = "1.12.0", feature = "option_from")] impl From for Option { - /// Copies `val` into a new `Some`. + /// Moves `val` into a new [`Some`]. /// /// # Examples /// @@ -1721,13 +1744,13 @@ impl<'a, T> From<&'a Option> for Option<&'a T> { /// /// # Examples /// - /// Converts an `Option<`[`String`]`>` into an `Option<`[`usize`]`>`, preserving the original. - /// The [`map`] method takes the `self` argument by value, consuming the original, - /// so this technique uses `from` to first take an `Option` to a reference + /// Converts an [Option]<[String]> into an [Option]<[usize]>, preserving + /// the original. The [`map`] method takes the `self` argument by value, consuming the original, + /// so this technique uses `from` to first take an [`Option`] to a reference /// to the value inside the original. /// /// [`map`]: Option::map - /// [`String`]: ../../std/string/struct.String.html + /// [String]: ../../std/string/struct.String.html "String" /// /// ``` /// let s: Option = Some(String::from("Hello, Rustaceans!")); @@ -1942,8 +1965,8 @@ unsafe impl TrustedLen for IntoIter {} impl> FromIterator> for Option { /// Takes each element in the [`Iterator`]: if it is [`None`][Option::None], /// no further elements are taken, and the [`None`][Option::None] is - /// returned. Should no [`None`][Option::None] occur, a container with the - /// values of each [`Option`] is returned. + /// returned. Should no [`None`][Option::None] occur, a container of type + /// `V` containing the values of each [`Option`] is returned. /// /// # Examples /// @@ -2039,7 +2062,7 @@ impl ops::FromResidual for Option { } impl Option> { - /// Converts from `Option>` to `Option` + /// Converts from `Option>` to `Option`. /// /// # Examples /// diff --git a/library/core/src/panic.rs b/library/core/src/panic.rs index 463bec3726..7a8b04d6f3 100644 --- a/library/core/src/panic.rs +++ b/library/core/src/panic.rs @@ -27,9 +27,14 @@ pub macro panic_2015 { ($msg:literal $(,)?) => ( $crate::panicking::panic($msg) ), + // Use `panic_str` instead of `panic_display::<&str>` for non_fmt_panic lint. ($msg:expr $(,)?) => ( $crate::panicking::panic_str($msg) ), + // Special-case the single-argument case for const_panic. + ("{}", $arg:expr $(,)?) => ( + $crate::panicking::panic_display(&$arg) + ), ($fmt:expr, $($arg:tt)+) => ( $crate::panicking::panic_fmt($crate::const_format_args!($fmt, $($arg)+)) ), @@ -44,6 +49,10 @@ pub macro panic_2021 { () => ( $crate::panicking::panic("explicit panic") ), + // Special-case the single-argument case for const_panic. + ("{}", $arg:expr $(,)?) => ( + $crate::panicking::panic_display(&$arg) + ), ($($t:tt)+) => ( $crate::panicking::panic_fmt($crate::const_format_args!($($t)+)) ), diff --git a/library/core/src/panicking.rs b/library/core/src/panicking.rs index 85728551f5..6d3ec6ae86 100644 --- a/library/core/src/panicking.rs +++ b/library/core/src/panicking.rs @@ -47,15 +47,7 @@ pub fn panic(expr: &'static str) -> ! { // truncation and padding (even though none is used here). Using // Arguments::new_v1 may allow the compiler to omit Formatter::pad from the // output binary, saving up to a few kilobytes. - panic_fmt( - #[cfg(bootstrap)] - fmt::Arguments::new_v1(&[expr], &[]), - #[cfg(not(bootstrap))] - // SAFETY: Arguments::new_v1 is safe with exactly one str and zero args - unsafe { - fmt::Arguments::new_v1(&[expr], &[]) - }, - ); + panic_fmt(fmt::Arguments::new_v1(&[expr], &[])); } #[inline] @@ -65,6 +57,13 @@ pub fn panic_str(expr: &str) -> ! { panic_fmt(format_args!("{}", expr)); } +#[inline] +#[track_caller] +#[cfg_attr(not(bootstrap), lang = "panic_display")] // needed for const-evaluated panics +pub fn panic_display(x: &T) -> ! { + panic_fmt(format_args!("{}", *x)); +} + #[cold] #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))] #[track_caller] @@ -82,7 +81,7 @@ fn panic_bounds_check(index: usize, len: usize) -> ! { #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))] #[cfg_attr(feature = "panic_immediate_abort", inline)] #[track_caller] -#[cfg_attr(not(bootstrap), lang = "panic_fmt")] // needed for const-evaluated panics +#[lang = "panic_fmt"] // needed for const-evaluated panics pub fn panic_fmt(fmt: fmt::Arguments<'_>) -> ! { if cfg!(feature = "panic_immediate_abort") { super::intrinsics::abort() @@ -102,7 +101,6 @@ pub fn panic_fmt(fmt: fmt::Arguments<'_>) -> ! { } /// This function is used instead of panic_fmt in const eval. -#[cfg(not(bootstrap))] #[lang = "const_panic_fmt"] pub const fn const_panic_fmt(fmt: fmt::Arguments<'_>) -> ! { if let Some(msg) = fmt.as_str() { diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs index 6a1a84bafa..34fc874ada 100644 --- a/library/core/src/pin.rs +++ b/library/core/src/pin.rs @@ -368,15 +368,15 @@ //! [Vec::push]: ../../std/vec/struct.Vec.html#method.push "Vec::push" //! [Rc]: ../../std/rc/struct.Rc.html "rc::Rc" //! [RefCell]: crate::cell::RefCell "cell::RefCell" -//! [`drop`]: Drop::drop "Drop::drop" +//! [`drop`]: Drop::drop //! [VecDeque]: ../../std/collections/struct.VecDeque.html "collections::VecDeque" //! [`ptr::write`]: crate::ptr::write "ptr::write" //! [`Future`]: crate::future::Future "future::Future" //! [drop-impl]: #drop-implementation //! [drop-guarantee]: #drop-guarantee //! [`poll`]: crate::future::Future::poll "future::Future::poll" -//! [&]: ../../std/primitive.reference.html "shared reference" -//! [&mut]: ../../std/primitive.reference.html "mutable reference" +//! [&]: reference "shared reference" +//! [&mut]: reference "mutable reference" //! [`unsafe`]: ../../std/keyword.unsafe.html "keyword unsafe" #![stable(feature = "pin", since = "1.33.0")] @@ -715,6 +715,7 @@ impl<'a, T: ?Sized> Pin<&'a T> { impl<'a, T: ?Sized> Pin<&'a mut T> { /// Converts this `Pin<&mut T>` into a `Pin<&T>` with the same lifetime. #[inline(always)] + #[must_use = "`self` will be dropped if the result is not used"] #[rustc_const_unstable(feature = "const_pin", issue = "76654")] #[stable(feature = "pin", since = "1.33.0")] pub const fn into_ref(self) -> Pin<&'a T> { @@ -731,6 +732,7 @@ impl<'a, T: ?Sized> Pin<&'a mut T> { /// the `Pin` itself. This method allows turning the `Pin` into a reference /// with the same lifetime as the original `Pin`. #[inline(always)] + #[must_use = "`self` will be dropped if the result is not used"] #[stable(feature = "pin", since = "1.33.0")] #[rustc_const_unstable(feature = "const_pin", issue = "76654")] pub const fn get_mut(self) -> &'a mut T @@ -751,6 +753,7 @@ impl<'a, T: ?Sized> Pin<&'a mut T> { /// If the underlying data is `Unpin`, `Pin::get_mut` should be used /// instead. #[inline(always)] + #[must_use = "`self` will be dropped if the result is not used"] #[stable(feature = "pin", since = "1.33.0")] #[rustc_const_unstable(feature = "const_pin", issue = "76654")] pub const unsafe fn get_unchecked_mut(self) -> &'a mut T { @@ -772,6 +775,7 @@ impl<'a, T: ?Sized> Pin<&'a mut T> { /// not move out of the argument you receive to the interior function. /// /// [`pin` module]: self#projections-and-structural-pinning + #[must_use = "`self` will be dropped if the result is not used"] #[stable(feature = "pin", since = "1.33.0")] pub unsafe fn map_unchecked_mut(self, func: F) -> Pin<&'a mut U> where @@ -811,6 +815,7 @@ impl<'a, P: DerefMut> Pin<&'a mut Pin

> { /// implementations of `P::DerefMut` are likewise ruled out by the contract of /// `Pin::new_unchecked`. #[unstable(feature = "pin_deref_mut", issue = "86918")] + #[must_use = "`self` will be dropped if the result is not used"] #[inline(always)] pub fn as_deref_mut(self) -> Pin<&'a mut P::Target> { // SAFETY: What we're asserting here is that going from diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs new file mode 100644 index 0000000000..0de9126dab --- /dev/null +++ b/library/core/src/primitive_docs.rs @@ -0,0 +1,1307 @@ +// `library/{std,core}/src/primitive_docs.rs` should have the same contents. +// These are different files so that relative links work properly without +// having to have `CARGO_PKG_NAME` set, but conceptually they should always be the same. +#[doc(primitive = "bool")] +#[doc(alias = "true")] +#[doc(alias = "false")] +/// The boolean type. +/// +/// The `bool` represents a value, which could only be either [`true`] or [`false`]. If you cast +/// a `bool` into an integer, [`true`] will be 1 and [`false`] will be 0. +/// +/// # Basic usage +/// +/// `bool` implements various traits, such as [`BitAnd`], [`BitOr`], [`Not`], etc., +/// which allow us to perform boolean operations using `&`, `|` and `!`. +/// +/// [`if`] requires a `bool` value as its conditional. [`assert!`], which is an +/// important macro in testing, checks whether an expression is [`true`] and panics +/// if it isn't. +/// +/// ``` +/// let bool_val = true & false | false; +/// assert!(!bool_val); +/// ``` +/// +/// [`true`]: ../std/keyword.true.html +/// [`false`]: ../std/keyword.false.html +/// [`BitAnd`]: ops::BitAnd +/// [`BitOr`]: ops::BitOr +/// [`Not`]: ops::Not +/// [`if`]: ../std/keyword.if.html +/// +/// # Examples +/// +/// A trivial example of the usage of `bool`: +/// +/// ``` +/// let praise_the_borrow_checker = true; +/// +/// // using the `if` conditional +/// if praise_the_borrow_checker { +/// println!("oh, yeah!"); +/// } else { +/// println!("what?!!"); +/// } +/// +/// // ... or, a match pattern +/// match praise_the_borrow_checker { +/// true => println!("keep praising!"), +/// false => println!("you should praise!"), +/// } +/// ``` +/// +/// Also, since `bool` implements the [`Copy`] trait, we don't +/// have to worry about the move semantics (just like the integer and float primitives). +/// +/// Now an example of `bool` cast to integer type: +/// +/// ``` +/// assert_eq!(true as i32, 1); +/// assert_eq!(false as i32, 0); +/// ``` +#[stable(feature = "rust1", since = "1.0.0")] +mod prim_bool {} + +#[doc(primitive = "never")] +#[doc(alias = "!")] +// +/// The `!` type, also called "never". +/// +/// `!` represents the type of computations which never resolve to any value at all. For example, +/// the [`exit`] function `fn exit(code: i32) -> !` exits the process without ever returning, and +/// so returns `!`. +/// +/// `break`, `continue` and `return` expressions also have type `!`. For example we are allowed to +/// write: +/// +/// ``` +/// #![feature(never_type)] +/// # fn foo() -> u32 { +/// let x: ! = { +/// return 123 +/// }; +/// # } +/// ``` +/// +/// Although the `let` is pointless here, it illustrates the meaning of `!`. Since `x` is never +/// assigned a value (because `return` returns from the entire function), `x` can be given type +/// `!`. We could also replace `return 123` with a `panic!` or a never-ending `loop` and this code +/// would still be valid. +/// +/// A more realistic usage of `!` is in this code: +/// +/// ``` +/// # fn get_a_number() -> Option { None } +/// # loop { +/// let num: u32 = match get_a_number() { +/// Some(num) => num, +/// None => break, +/// }; +/// # } +/// ``` +/// +/// Both match arms must produce values of type [`u32`], but since `break` never produces a value +/// at all we know it can never produce a value which isn't a [`u32`]. This illustrates another +/// behaviour of the `!` type - expressions with type `!` will coerce into any other type. +/// +/// [`u32`]: prim@u32 +#[doc = concat!("[`exit`]: ", include_str!("../primitive_docs/process_exit.md"))] +/// +/// # `!` and generics +/// +/// ## Infallible errors +/// +/// The main place you'll see `!` used explicitly is in generic code. Consider the [`FromStr`] +/// trait: +/// +/// ``` +/// trait FromStr: Sized { +/// type Err; +/// fn from_str(s: &str) -> Result; +/// } +/// ``` +/// +/// When implementing this trait for [`String`] we need to pick a type for [`Err`]. And since +/// converting a string into a string will never result in an error, the appropriate type is `!`. +/// (Currently the type actually used is an enum with no variants, though this is only because `!` +/// was added to Rust at a later date and it may change in the future.) With an [`Err`] type of +/// `!`, if we have to call [`String::from_str`] for some reason the result will be a +/// [`Result`] which we can unpack like this: +/// +/// ``` +/// #![feature(exhaustive_patterns)] +/// use std::str::FromStr; +/// let Ok(s) = String::from_str("hello"); +/// ``` +/// +/// Since the [`Err`] variant contains a `!`, it can never occur. If the `exhaustive_patterns` +/// feature is present this means we can exhaustively match on [`Result`] by just taking the +/// [`Ok`] variant. This illustrates another behaviour of `!` - it can be used to "delete" certain +/// enum variants from generic types like `Result`. +/// +/// ## Infinite loops +/// +/// While [`Result`] is very useful for removing errors, `!` can also be used to remove +/// successes as well. If we think of [`Result`] as "if this function returns, it has not +/// errored," we get a very intuitive idea of [`Result`] as well: if the function returns, it +/// *has* errored. +/// +/// For example, consider the case of a simple web server, which can be simplified to: +/// +/// ```ignore (hypothetical-example) +/// loop { +/// let (client, request) = get_request().expect("disconnected"); +/// let response = request.process(); +/// response.send(client); +/// } +/// ``` +/// +/// Currently, this isn't ideal, because we simply panic whenever we fail to get a new connection. +/// Instead, we'd like to keep track of this error, like this: +/// +/// ```ignore (hypothetical-example) +/// loop { +/// match get_request() { +/// Err(err) => break err, +/// Ok((client, request)) => { +/// let response = request.process(); +/// response.send(client); +/// }, +/// } +/// } +/// ``` +/// +/// Now, when the server disconnects, we exit the loop with an error instead of panicking. While it +/// might be intuitive to simply return the error, we might want to wrap it in a [`Result`] +/// instead: +/// +/// ```ignore (hypothetical-example) +/// fn server_loop() -> Result { +/// loop { +/// let (client, request) = get_request()?; +/// let response = request.process(); +/// response.send(client); +/// } +/// } +/// ``` +/// +/// Now, we can use `?` instead of `match`, and the return type makes a lot more sense: if the loop +/// ever stops, it means that an error occurred. We don't even have to wrap the loop in an `Ok` +/// because `!` coerces to `Result` automatically. +/// +/// [`String::from_str`]: str::FromStr::from_str +#[doc = concat!("[`String`]: ", include_str!("../primitive_docs/string_string.md"))] +/// [`FromStr`]: str::FromStr +/// +/// # `!` and traits +/// +/// When writing your own traits, `!` should have an `impl` whenever there is an obvious `impl` +/// which doesn't `panic!`. The reason is that functions returning an `impl Trait` where `!` +/// does not have an `impl` of `Trait` cannot diverge as their only possible code path. In other +/// words, they can't return `!` from every code path. As an example, this code doesn't compile: +/// +/// ```compile_fail +/// use std::ops::Add; +/// +/// fn foo() -> impl Add { +/// unimplemented!() +/// } +/// ``` +/// +/// But this code does: +/// +/// ``` +/// use std::ops::Add; +/// +/// fn foo() -> impl Add { +/// if true { +/// unimplemented!() +/// } else { +/// 0 +/// } +/// } +/// ``` +/// +/// The reason is that, in the first example, there are many possible types that `!` could coerce +/// to, because many types implement `Add`. However, in the second example, +/// the `else` branch returns a `0`, which the compiler infers from the return type to be of type +/// `u32`. Since `u32` is a concrete type, `!` can and will be coerced to it. See issue [#36375] +/// for more information on this quirk of `!`. +/// +/// [#36375]: https://github.com/rust-lang/rust/issues/36375 +/// +/// As it turns out, though, most traits can have an `impl` for `!`. Take [`Debug`] +/// for example: +/// +/// ``` +/// #![feature(never_type)] +/// # use std::fmt; +/// # trait Debug { +/// # fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result; +/// # } +/// impl Debug for ! { +/// fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { +/// *self +/// } +/// } +/// ``` +/// +/// Once again we're using `!`'s ability to coerce into any other type, in this case +/// [`fmt::Result`]. Since this method takes a `&!` as an argument we know that it can never be +/// called (because there is no value of type `!` for it to be called with). Writing `*self` +/// essentially tells the compiler "We know that this code can never be run, so just treat the +/// entire function body as having type [`fmt::Result`]". This pattern can be used a lot when +/// implementing traits for `!`. Generally, any trait which only has methods which take a `self` +/// parameter should have such an impl. +/// +/// On the other hand, one trait which would not be appropriate to implement is [`Default`]: +/// +/// ``` +/// trait Default { +/// fn default() -> Self; +/// } +/// ``` +/// +/// Since `!` has no values, it has no default value either. It's true that we could write an +/// `impl` for this which simply panics, but the same is true for any type (we could `impl +/// Default` for (eg.) [`File`] by just making [`default()`] panic.) +/// +#[doc = concat!("[`File`]: ", include_str!("../primitive_docs/fs_file.md"))] +/// [`Debug`]: fmt::Debug +/// [`default()`]: Default::default +/// +#[unstable(feature = "never_type", issue = "35121")] +mod prim_never {} + +#[doc(primitive = "char")] +/// A character type. +/// +/// The `char` type represents a single character. More specifically, since +/// 'character' isn't a well-defined concept in Unicode, `char` is a '[Unicode +/// scalar value]', which is similar to, but not the same as, a '[Unicode code +/// point]'. +/// +/// [Unicode scalar value]: https://www.unicode.org/glossary/#unicode_scalar_value +/// [Unicode code point]: https://www.unicode.org/glossary/#code_point +/// +/// This documentation describes a number of methods and trait implementations on the +/// `char` type. For technical reasons, there is additional, separate +/// documentation in [the `std::char` module](char/index.html) as well. +/// +/// # Representation +/// +/// `char` is always four bytes in size. This is a different representation than +/// a given character would have as part of a [`String`]. For example: +/// +/// ``` +/// let v = vec!['h', 'e', 'l', 'l', 'o']; +/// +/// // five elements times four bytes for each element +/// assert_eq!(20, v.len() * std::mem::size_of::()); +/// +/// let s = String::from("hello"); +/// +/// // five elements times one byte per element +/// assert_eq!(5, s.len() * std::mem::size_of::()); +/// ``` +/// +#[doc = concat!("[`String`]: ", include_str!("../primitive_docs/string_string.md"))] +/// +/// As always, remember that a human intuition for 'character' might not map to +/// Unicode's definitions. For example, despite looking similar, the 'é' +/// character is one Unicode code point while 'é' is two Unicode code points: +/// +/// ``` +/// let mut chars = "é".chars(); +/// // U+00e9: 'latin small letter e with acute' +/// assert_eq!(Some('\u{00e9}'), chars.next()); +/// assert_eq!(None, chars.next()); +/// +/// let mut chars = "é".chars(); +/// // U+0065: 'latin small letter e' +/// assert_eq!(Some('\u{0065}'), chars.next()); +/// // U+0301: 'combining acute accent' +/// assert_eq!(Some('\u{0301}'), chars.next()); +/// assert_eq!(None, chars.next()); +/// ``` +/// +/// This means that the contents of the first string above _will_ fit into a +/// `char` while the contents of the second string _will not_. Trying to create +/// a `char` literal with the contents of the second string gives an error: +/// +/// ```text +/// error: character literal may only contain one codepoint: 'é' +/// let c = 'é'; +/// ^^^ +/// ``` +/// +/// Another implication of the 4-byte fixed size of a `char` is that +/// per-`char` processing can end up using a lot more memory: +/// +/// ``` +/// let s = String::from("love: ❤️"); +/// let v: Vec = s.chars().collect(); +/// +/// assert_eq!(12, std::mem::size_of_val(&s[..])); +/// assert_eq!(32, std::mem::size_of_val(&v[..])); +/// ``` +#[stable(feature = "rust1", since = "1.0.0")] +mod prim_char {} + +#[doc(primitive = "unit")] +#[doc(alias = "(")] +#[doc(alias = ")")] +#[doc(alias = "()")] +// +/// The `()` type, also called "unit". +/// +/// The `()` type has exactly one value `()`, and is used when there +/// is no other meaningful value that could be returned. `()` is most +/// commonly seen implicitly: functions without a `-> ...` implicitly +/// have return type `()`, that is, these are equivalent: +/// +/// ```rust +/// fn long() -> () {} +/// +/// fn short() {} +/// ``` +/// +/// The semicolon `;` can be used to discard the result of an +/// expression at the end of a block, making the expression (and thus +/// the block) evaluate to `()`. For example, +/// +/// ```rust +/// fn returns_i64() -> i64 { +/// 1i64 +/// } +/// fn returns_unit() { +/// 1i64; +/// } +/// +/// let is_i64 = { +/// returns_i64() +/// }; +/// let is_unit = { +/// returns_i64(); +/// }; +/// ``` +/// +#[stable(feature = "rust1", since = "1.0.0")] +mod prim_unit {} + +#[doc(primitive = "pointer")] +#[doc(alias = "ptr")] +#[doc(alias = "*")] +#[doc(alias = "*const")] +#[doc(alias = "*mut")] +// +/// Raw, unsafe pointers, `*const T`, and `*mut T`. +/// +/// *[See also the `std::ptr` module](ptr).* +/// +/// Working with raw pointers in Rust is uncommon, typically limited to a few patterns. +/// Raw pointers can be unaligned or [`null`]. However, when a raw pointer is +/// dereferenced (using the `*` operator), it must be non-null and aligned. +/// +/// Storing through a raw pointer using `*ptr = data` calls `drop` on the old value, so +/// [`write`] must be used if the type has drop glue and memory is not already +/// initialized - otherwise `drop` would be called on the uninitialized memory. +/// +/// Use the [`null`] and [`null_mut`] functions to create null pointers, and the +/// [`is_null`] method of the `*const T` and `*mut T` types to check for null. +/// The `*const T` and `*mut T` types also define the [`offset`] method, for +/// pointer math. +/// +/// # Common ways to create raw pointers +/// +/// ## 1. Coerce a reference (`&T`) or mutable reference (`&mut T`). +/// +/// ``` +/// let my_num: i32 = 10; +/// let my_num_ptr: *const i32 = &my_num; +/// let mut my_speed: i32 = 88; +/// let my_speed_ptr: *mut i32 = &mut my_speed; +/// ``` +/// +/// To get a pointer to a boxed value, dereference the box: +/// +/// ``` +/// let my_num: Box = Box::new(10); +/// let my_num_ptr: *const i32 = &*my_num; +/// let mut my_speed: Box = Box::new(88); +/// let my_speed_ptr: *mut i32 = &mut *my_speed; +/// ``` +/// +/// This does not take ownership of the original allocation +/// and requires no resource management later, +/// but you must not use the pointer after its lifetime. +/// +/// ## 2. Consume a box (`Box`). +/// +/// The [`into_raw`] function consumes a box and returns +/// the raw pointer. It doesn't destroy `T` or deallocate any memory. +/// +/// ``` +/// let my_speed: Box = Box::new(88); +/// let my_speed: *mut i32 = Box::into_raw(my_speed); +/// +/// // By taking ownership of the original `Box` though +/// // we are obligated to put it together later to be destroyed. +/// unsafe { +/// drop(Box::from_raw(my_speed)); +/// } +/// ``` +/// +/// Note that here the call to [`drop`] is for clarity - it indicates +/// that we are done with the given value and it should be destroyed. +/// +/// ## 3. Create it using `ptr::addr_of!` +/// +/// Instead of coercing a reference to a raw pointer, you can use the macros +/// [`ptr::addr_of!`] (for `*const T`) and [`ptr::addr_of_mut!`] (for `*mut T`). +/// These macros allow you to create raw pointers to fields to which you cannot +/// create a reference (without causing undefined behaviour), such as an +/// unaligned field. This might be necessary if packed structs or uninitialized +/// memory is involved. +/// +/// ``` +/// #[derive(Debug, Default, Copy, Clone)] +/// #[repr(C, packed)] +/// struct S { +/// aligned: u8, +/// unaligned: u32, +/// } +/// let s = S::default(); +/// let p = std::ptr::addr_of!(s.unaligned); // not allowed with coercion +/// ``` +/// +/// ## 4. Get it from C. +/// +/// ``` +/// # #![feature(rustc_private)] +/// extern crate libc; +/// +/// use std::mem; +/// +/// unsafe { +/// let my_num: *mut i32 = libc::malloc(mem::size_of::()) as *mut i32; +/// if my_num.is_null() { +/// panic!("failed to allocate memory"); +/// } +/// libc::free(my_num as *mut libc::c_void); +/// } +/// ``` +/// +/// Usually you wouldn't literally use `malloc` and `free` from Rust, +/// but C APIs hand out a lot of pointers generally, so are a common source +/// of raw pointers in Rust. +/// +/// [`null`]: ptr::null +/// [`null_mut`]: ptr::null_mut +/// [`is_null`]: pointer::is_null +/// [`offset`]: pointer::offset +#[doc = concat!("[`into_raw`]: ", include_str!("../primitive_docs/box_into_raw.md"))] +/// [`drop`]: mem::drop +/// [`write`]: ptr::write +#[stable(feature = "rust1", since = "1.0.0")] +mod prim_pointer {} + +#[doc(primitive = "array")] +#[doc(alias = "[]")] +#[doc(alias = "[T;N]")] // unfortunately, rustdoc doesn't have fuzzy search for aliases +#[doc(alias = "[T; N]")] +/// A fixed-size array, denoted `[T; N]`, for the element type, `T`, and the +/// non-negative compile-time constant size, `N`. +/// +/// There are two syntactic forms for creating an array: +/// +/// * A list with each element, i.e., `[x, y, z]`. +/// * A repeat expression `[x; N]`, which produces an array with `N` copies of `x`. +/// The type of `x` must be [`Copy`]. +/// +/// Note that `[expr; 0]` is allowed, and produces an empty array. +/// This will still evaluate `expr`, however, and immediately drop the resulting value, so +/// be mindful of side effects. +/// +/// Arrays of *any* size implement the following traits if the element type allows it: +/// +/// - [`Copy`] +/// - [`Clone`] +/// - [`Debug`] +/// - [`IntoIterator`] (implemented for `[T; N]`, `&[T; N]` and `&mut [T; N]`) +/// - [`PartialEq`], [`PartialOrd`], [`Eq`], [`Ord`] +/// - [`Hash`] +/// - [`AsRef`], [`AsMut`] +/// - [`Borrow`], [`BorrowMut`] +/// +/// Arrays of sizes from 0 to 32 (inclusive) implement the [`Default`] trait +/// if the element type allows it. As a stopgap, trait implementations are +/// statically generated up to size 32. +/// +/// Arrays coerce to [slices (`[T]`)][slice], so a slice method may be called on +/// an array. Indeed, this provides most of the API for working with arrays. +/// Slices have a dynamic size and do not coerce to arrays. +/// +/// You can move elements out of an array with a [slice pattern]. If you want +/// one element, see [`mem::replace`]. +/// +/// # Examples +/// +/// ``` +/// let mut array: [i32; 3] = [0; 3]; +/// +/// array[1] = 1; +/// array[2] = 2; +/// +/// assert_eq!([1, 2], &array[1..]); +/// +/// // This loop prints: 0 1 2 +/// for x in array { +/// print!("{} ", x); +/// } +/// ``` +/// +/// You can also iterate over reference to the array's elements: +/// +/// ``` +/// let array: [i32; 3] = [0; 3]; +/// +/// for x in &array { } +/// ``` +/// +/// You can use a [slice pattern] to move elements out of an array: +/// +/// ``` +/// fn move_away(_: String) { /* Do interesting things. */ } +/// +/// let [john, roa] = ["John".to_string(), "Roa".to_string()]; +/// move_away(john); +/// move_away(roa); +/// ``` +/// +/// # Editions +/// +/// Prior to Rust 1.53, arrays did not implement [`IntoIterator`] by value, so the method call +/// `array.into_iter()` auto-referenced into a [slice iterator](slice::iter). Right now, the old +/// behavior is preserved in the 2015 and 2018 editions of Rust for compatibility, ignoring +/// [`IntoIterator`] by value. In the future, the behavior on the 2015 and 2018 edition +/// might be made consistent to the behavior of later editions. +/// +/// ```rust,edition2018 +/// // Rust 2015 and 2018: +/// +/// # #![allow(array_into_iter)] // override our `deny(warnings)` +/// let array: [i32; 3] = [0; 3]; +/// +/// // This creates a slice iterator, producing references to each value. +/// for item in array.into_iter().enumerate() { +/// let (i, x): (usize, &i32) = item; +/// println!("array[{}] = {}", i, x); +/// } +/// +/// // The `array_into_iter` lint suggests this change for future compatibility: +/// for item in array.iter().enumerate() { +/// let (i, x): (usize, &i32) = item; +/// println!("array[{}] = {}", i, x); +/// } +/// +/// // You can explicitly iterate an array by value using +/// // `IntoIterator::into_iter` or `std::array::IntoIter::new`: +/// for item in IntoIterator::into_iter(array).enumerate() { +/// let (i, x): (usize, i32) = item; +/// println!("array[{}] = {}", i, x); +/// } +/// ``` +/// +/// Starting in the 2021 edition, `array.into_iter()` uses `IntoIterator` normally to iterate +/// by value, and `iter()` should be used to iterate by reference like previous editions. +/// +/// ```rust,edition2021 +/// // Rust 2021: +/// +/// let array: [i32; 3] = [0; 3]; +/// +/// // This iterates by reference: +/// for item in array.iter().enumerate() { +/// let (i, x): (usize, &i32) = item; +/// println!("array[{}] = {}", i, x); +/// } +/// +/// // This iterates by value: +/// for item in array.into_iter().enumerate() { +/// let (i, x): (usize, i32) = item; +/// println!("array[{}] = {}", i, x); +/// } +/// ``` +/// +/// Future language versions might start treating the `array.into_iter()` +/// syntax on editions 2015 and 2018 the same as on edition 2021. So code using +/// those older editions should still be written with this change in mind, to +/// prevent breakage in the future. The safest way to accomplish this is to +/// avoid the `into_iter` syntax on those editions. If an edition update is not +/// viable/desired, there are multiple alternatives: +/// * use `iter`, equivalent to the old behavior, creating references +/// * use [`IntoIterator::into_iter`], equivalent to the post-2021 behavior (Rust 1.53+) +/// * replace `for ... in array.into_iter() {` with `for ... in array {`, +/// equivalent to the post-2021 behavior (Rust 1.53+) +/// +/// ```rust,edition2018 +/// // Rust 2015 and 2018: +/// +/// let array: [i32; 3] = [0; 3]; +/// +/// // This iterates by reference: +/// for item in array.iter() { +/// let x: &i32 = item; +/// println!("{}", x); +/// } +/// +/// // This iterates by value: +/// for item in IntoIterator::into_iter(array) { +/// let x: i32 = item; +/// println!("{}", x); +/// } +/// +/// // This iterates by value: +/// for item in array { +/// let x: i32 = item; +/// println!("{}", x); +/// } +/// +/// // IntoIter can also start a chain. +/// // This iterates by value: +/// for item in IntoIterator::into_iter(array).enumerate() { +/// let (i, x): (usize, i32) = item; +/// println!("array[{}] = {}", i, x); +/// } +/// ``` +/// +/// [slice]: prim@slice +/// [`Debug`]: fmt::Debug +/// [`Hash`]: hash::Hash +/// [`Borrow`]: borrow::Borrow +/// [`BorrowMut`]: borrow::BorrowMut +/// [slice pattern]: ../reference/patterns.html#slice-patterns +#[stable(feature = "rust1", since = "1.0.0")] +mod prim_array {} + +#[doc(primitive = "slice")] +#[doc(alias = "[")] +#[doc(alias = "]")] +#[doc(alias = "[]")] +/// A dynamically-sized view into a contiguous sequence, `[T]`. Contiguous here +/// means that elements are laid out so that every element is the same +/// distance from its neighbors. +/// +/// *[See also the `std::slice` module](crate::slice).* +/// +/// Slices are a view into a block of memory represented as a pointer and a +/// length. +/// +/// ``` +/// // slicing a Vec +/// let vec = vec![1, 2, 3]; +/// let int_slice = &vec[..]; +/// // coercing an array to a slice +/// let str_slice: &[&str] = &["one", "two", "three"]; +/// ``` +/// +/// Slices are either mutable or shared. The shared slice type is `&[T]`, +/// while the mutable slice type is `&mut [T]`, where `T` represents the element +/// type. For example, you can mutate the block of memory that a mutable slice +/// points to: +/// +/// ``` +/// let mut x = [1, 2, 3]; +/// let x = &mut x[..]; // Take a full slice of `x`. +/// x[1] = 7; +/// assert_eq!(x, &[1, 7, 3]); +/// ``` +/// +/// As slices store the length of the sequence they refer to, they have twice +/// the size of pointers to [`Sized`](marker/trait.Sized.html) types. +/// Also see the reference on +/// [dynamically sized types](../reference/dynamically-sized-types.html). +/// +/// ``` +/// # use std::rc::Rc; +/// let pointer_size = std::mem::size_of::<&u8>(); +/// assert_eq!(2 * pointer_size, std::mem::size_of::<&[u8]>()); +/// assert_eq!(2 * pointer_size, std::mem::size_of::<*const [u8]>()); +/// assert_eq!(2 * pointer_size, std::mem::size_of::>()); +/// assert_eq!(2 * pointer_size, std::mem::size_of::>()); +/// ``` +#[stable(feature = "rust1", since = "1.0.0")] +mod prim_slice {} + +#[doc(primitive = "str")] +// +/// String slices. +/// +/// *[See also the `std::str` module](crate::str).* +/// +/// The `str` type, also called a 'string slice', is the most primitive string +/// type. It is usually seen in its borrowed form, `&str`. It is also the type +/// of string literals, `&'static str`. +/// +/// String slices are always valid UTF-8. +/// +/// # Examples +/// +/// String literals are string slices: +/// +/// ``` +/// let hello = "Hello, world!"; +/// +/// // with an explicit type annotation +/// let hello: &'static str = "Hello, world!"; +/// ``` +/// +/// They are `'static` because they're stored directly in the final binary, and +/// so will be valid for the `'static` duration. +/// +/// # Representation +/// +/// A `&str` is made up of two components: a pointer to some bytes, and a +/// length. You can look at these with the [`as_ptr`] and [`len`] methods: +/// +/// ``` +/// use std::slice; +/// use std::str; +/// +/// let story = "Once upon a time..."; +/// +/// let ptr = story.as_ptr(); +/// let len = story.len(); +/// +/// // story has nineteen bytes +/// assert_eq!(19, len); +/// +/// // We can re-build a str out of ptr and len. This is all unsafe because +/// // we are responsible for making sure the two components are valid: +/// let s = unsafe { +/// // First, we build a &[u8]... +/// let slice = slice::from_raw_parts(ptr, len); +/// +/// // ... and then convert that slice into a string slice +/// str::from_utf8(slice) +/// }; +/// +/// assert_eq!(s, Ok(story)); +/// ``` +/// +/// [`as_ptr`]: str::as_ptr +/// [`len`]: str::len +/// +/// Note: This example shows the internals of `&str`. `unsafe` should not be +/// used to get a string slice under normal circumstances. Use `as_str` +/// instead. +#[stable(feature = "rust1", since = "1.0.0")] +mod prim_str {} + +#[doc(primitive = "tuple")] +#[doc(alias = "(")] +#[doc(alias = ")")] +#[doc(alias = "()")] +// +/// A finite heterogeneous sequence, `(T, U, ..)`. +/// +/// Let's cover each of those in turn: +/// +/// Tuples are *finite*. In other words, a tuple has a length. Here's a tuple +/// of length `3`: +/// +/// ``` +/// ("hello", 5, 'c'); +/// ``` +/// +/// 'Length' is also sometimes called 'arity' here; each tuple of a different +/// length is a different, distinct type. +/// +/// Tuples are *heterogeneous*. This means that each element of the tuple can +/// have a different type. In that tuple above, it has the type: +/// +/// ``` +/// # let _: +/// (&'static str, i32, char) +/// # = ("hello", 5, 'c'); +/// ``` +/// +/// Tuples are a *sequence*. This means that they can be accessed by position; +/// this is called 'tuple indexing', and it looks like this: +/// +/// ```rust +/// let tuple = ("hello", 5, 'c'); +/// +/// assert_eq!(tuple.0, "hello"); +/// assert_eq!(tuple.1, 5); +/// assert_eq!(tuple.2, 'c'); +/// ``` +/// +/// The sequential nature of the tuple applies to its implementations of various +/// traits. For example, in [`PartialOrd`] and [`Ord`], the elements are compared +/// sequentially until the first non-equal set is found. +/// +/// For more about tuples, see [the book](../book/ch03-02-data-types.html#the-tuple-type). +/// +/// # Trait implementations +/// +/// If every type inside a tuple implements one of the following traits, then a +/// tuple itself also implements it. +/// +/// * [`Clone`] +/// * [`Copy`] +/// * [`PartialEq`] +/// * [`Eq`] +/// * [`PartialOrd`] +/// * [`Ord`] +/// * [`Debug`] +/// * [`Default`] +/// * [`Hash`] +/// +/// [`Debug`]: fmt::Debug +/// [`Hash`]: hash::Hash +/// +/// Due to a temporary restriction in Rust's type system, these traits are only +/// implemented on tuples of arity 12 or less. In the future, this may change. +/// +/// # Examples +/// +/// Basic usage: +/// +/// ``` +/// let tuple = ("hello", 5, 'c'); +/// +/// assert_eq!(tuple.0, "hello"); +/// ``` +/// +/// Tuples are often used as a return type when you want to return more than +/// one value: +/// +/// ``` +/// fn calculate_point() -> (i32, i32) { +/// // Don't do a calculation, that's not the point of the example +/// (4, 5) +/// } +/// +/// let point = calculate_point(); +/// +/// assert_eq!(point.0, 4); +/// assert_eq!(point.1, 5); +/// +/// // Combining this with patterns can be nicer. +/// +/// let (x, y) = calculate_point(); +/// +/// assert_eq!(x, 4); +/// assert_eq!(y, 5); +/// ``` +/// +#[stable(feature = "rust1", since = "1.0.0")] +mod prim_tuple {} + +#[doc(primitive = "f32")] +/// A 32-bit floating point type (specifically, the "binary32" type defined in IEEE 754-2008). +/// +/// This type can represent a wide range of decimal numbers, like `3.5`, `27`, +/// `-113.75`, `0.0078125`, `34359738368`, `0`, `-1`. So unlike integer types +/// (such as `i32`), floating point types can represent non-integer numbers, +/// too. +/// +/// However, being able to represent this wide range of numbers comes at the +/// cost of precision: floats can only represent some of the real numbers and +/// calculation with floats round to a nearby representable number. For example, +/// `5.0` and `1.0` can be exactly represented as `f32`, but `1.0 / 5.0` results +/// in `0.20000000298023223876953125` since `0.2` cannot be exactly represented +/// as `f32`. Note, however, that printing floats with `println` and friends will +/// often discard insignificant digits: `println!("{}", 1.0f32 / 5.0f32)` will +/// print `0.2`. +/// +/// Additionally, `f32` can represent some special values: +/// +/// - −0.0: IEEE 754 floating point numbers have a bit that indicates their sign, so −0.0 is a +/// possible value. For comparison −0.0 = +0.0, but floating point operations can carry +/// the sign bit through arithmetic operations. This means −0.0 × +0.0 produces −0.0 and +/// a negative number rounded to a value smaller than a float can represent also produces −0.0. +/// - [∞](#associatedconstant.INFINITY) and +/// [−∞](#associatedconstant.NEG_INFINITY): these result from calculations +/// like `1.0 / 0.0`. +/// - [NaN (not a number)](#associatedconstant.NAN): this value results from +/// calculations like `(-1.0).sqrt()`. NaN has some potentially unexpected +/// behavior: it is unequal to any float, including itself! It is also neither +/// smaller nor greater than any float, making it impossible to sort. Lastly, +/// it is considered infectious as almost all calculations where one of the +/// operands is NaN will also result in NaN. +/// +/// For more information on floating point numbers, see [Wikipedia][wikipedia]. +/// +/// *[See also the `std::f32::consts` module](crate::f32::consts).* +/// +/// [wikipedia]: https://en.wikipedia.org/wiki/Single-precision_floating-point_format +#[stable(feature = "rust1", since = "1.0.0")] +mod prim_f32 {} + +#[doc(primitive = "f64")] +/// A 64-bit floating point type (specifically, the "binary64" type defined in IEEE 754-2008). +/// +/// This type is very similar to [`f32`], but has increased +/// precision by using twice as many bits. Please see [the documentation for +/// `f32`][`f32`] or [Wikipedia on double precision +/// values][wikipedia] for more information. +/// +/// *[See also the `std::f64::consts` module](crate::f64::consts).* +/// +/// [`f32`]: prim@f32 +/// [wikipedia]: https://en.wikipedia.org/wiki/Double-precision_floating-point_format +#[stable(feature = "rust1", since = "1.0.0")] +mod prim_f64 {} + +#[doc(primitive = "i8")] +// +/// The 8-bit signed integer type. +#[stable(feature = "rust1", since = "1.0.0")] +mod prim_i8 {} + +#[doc(primitive = "i16")] +// +/// The 16-bit signed integer type. +#[stable(feature = "rust1", since = "1.0.0")] +mod prim_i16 {} + +#[doc(primitive = "i32")] +// +/// The 32-bit signed integer type. +#[stable(feature = "rust1", since = "1.0.0")] +mod prim_i32 {} + +#[doc(primitive = "i64")] +// +/// The 64-bit signed integer type. +#[stable(feature = "rust1", since = "1.0.0")] +mod prim_i64 {} + +#[doc(primitive = "i128")] +// +/// The 128-bit signed integer type. +#[stable(feature = "i128", since = "1.26.0")] +mod prim_i128 {} + +#[doc(primitive = "u8")] +// +/// The 8-bit unsigned integer type. +#[stable(feature = "rust1", since = "1.0.0")] +mod prim_u8 {} + +#[doc(primitive = "u16")] +// +/// The 16-bit unsigned integer type. +#[stable(feature = "rust1", since = "1.0.0")] +mod prim_u16 {} + +#[doc(primitive = "u32")] +// +/// The 32-bit unsigned integer type. +#[stable(feature = "rust1", since = "1.0.0")] +mod prim_u32 {} + +#[doc(primitive = "u64")] +// +/// The 64-bit unsigned integer type. +#[stable(feature = "rust1", since = "1.0.0")] +mod prim_u64 {} + +#[doc(primitive = "u128")] +// +/// The 128-bit unsigned integer type. +#[stable(feature = "i128", since = "1.26.0")] +mod prim_u128 {} + +#[doc(primitive = "isize")] +// +/// The pointer-sized signed integer type. +/// +/// The size of this primitive is how many bytes it takes to reference any +/// location in memory. For example, on a 32 bit target, this is 4 bytes +/// and on a 64 bit target, this is 8 bytes. +#[stable(feature = "rust1", since = "1.0.0")] +mod prim_isize {} + +#[doc(primitive = "usize")] +// +/// The pointer-sized unsigned integer type. +/// +/// The size of this primitive is how many bytes it takes to reference any +/// location in memory. For example, on a 32 bit target, this is 4 bytes +/// and on a 64 bit target, this is 8 bytes. +#[stable(feature = "rust1", since = "1.0.0")] +mod prim_usize {} + +#[doc(primitive = "reference")] +#[doc(alias = "&")] +#[doc(alias = "&mut")] +// +/// References, both shared and mutable. +/// +/// A reference represents a borrow of some owned value. You can get one by using the `&` or `&mut` +/// operators on a value, or by using a [`ref`](../std/keyword.ref.html) or +/// [ref](../std/keyword.ref.html) [mut](../std/keyword.mut.html) pattern. +/// +/// For those familiar with pointers, a reference is just a pointer that is assumed to be +/// aligned, not null, and pointing to memory containing a valid value of `T` - for example, +/// &[bool] can only point to an allocation containing the integer values `1` +/// ([`true`](../std/keyword.true.html)) or `0` ([`false`](../std/keyword.false.html)), but +/// creating a &[bool] that points to an allocation containing +/// the value `3` causes undefined behaviour. +/// In fact, [Option]\<&T> has the same memory representation as a +/// nullable but aligned pointer, and can be passed across FFI boundaries as such. +/// +/// In most cases, references can be used much like the original value. Field access, method +/// calling, and indexing work the same (save for mutability rules, of course). In addition, the +/// comparison operators transparently defer to the referent's implementation, allowing references +/// to be compared the same as owned values. +/// +/// References have a lifetime attached to them, which represents the scope for which the borrow is +/// valid. A lifetime is said to "outlive" another one if its representative scope is as long or +/// longer than the other. The `'static` lifetime is the longest lifetime, which represents the +/// total life of the program. For example, string literals have a `'static` lifetime because the +/// text data is embedded into the binary of the program, rather than in an allocation that needs +/// to be dynamically managed. +/// +/// `&mut T` references can be freely coerced into `&T` references with the same referent type, and +/// references with longer lifetimes can be freely coerced into references with shorter ones. +/// +/// Reference equality by address, instead of comparing the values pointed to, is accomplished via +/// implicit reference-pointer coercion and raw pointer equality via [`ptr::eq`], while +/// [`PartialEq`] compares values. +/// +/// ``` +/// use std::ptr; +/// +/// let five = 5; +/// let other_five = 5; +/// let five_ref = &five; +/// let same_five_ref = &five; +/// let other_five_ref = &other_five; +/// +/// assert!(five_ref == same_five_ref); +/// assert!(five_ref == other_five_ref); +/// +/// assert!(ptr::eq(five_ref, same_five_ref)); +/// assert!(!ptr::eq(five_ref, other_five_ref)); +/// ``` +/// +/// For more information on how to use references, see [the book's section on "References and +/// Borrowing"][book-refs]. +/// +/// [book-refs]: ../book/ch04-02-references-and-borrowing.html +/// +/// # Trait implementations +/// +/// The following traits are implemented for all `&T`, regardless of the type of its referent: +/// +/// * [`Copy`] +/// * [`Clone`] \(Note that this will not defer to `T`'s `Clone` implementation if it exists!) +/// * [`Deref`] +/// * [`Borrow`] +/// * [`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 +/// referent: +/// +/// * [`DerefMut`] +/// * [`BorrowMut`] +/// +/// [`DerefMut`]: ops::DerefMut +/// [`BorrowMut`]: borrow::BorrowMut +/// [bool]: prim@bool +/// +/// 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`] +/// * [`PartialOrd`] +/// * [`Ord`] +/// * [`PartialEq`] +/// * [`Eq`] +/// * [`AsRef`] +/// * [`Fn`] \(in addition, `&T` references get [`FnMut`] and [`FnOnce`] if `T: Fn`) +/// * [`Hash`] +/// * [`ToSocketAddrs`] +/// +/// [`std::fmt`]: fmt +/// ['Pointer`]: fmt::Pointer +/// [`Hash`]: hash::Hash +#[doc = concat!("[`ToSocketAddrs`]: ", include_str!("../primitive_docs/net_tosocketaddrs.md"))] +/// +/// `&mut T` references get all of the above except `ToSocketAddrs`, plus the following, if `T` +/// implements that trait: +/// +/// * [`AsMut`] +/// * [`FnMut`] \(in addition, `&mut T` references get [`FnOnce`] if `T: FnMut`) +/// * [`fmt::Write`] +/// * [`Iterator`] +/// * [`DoubleEndedIterator`] +/// * [`ExactSizeIterator`] +/// * [`FusedIterator`] +/// * [`TrustedLen`] +/// * [`Send`] \(note that `&T` references only get `Send` if T: [Sync]) +/// * [`io::Write`] +/// * [`Read`] +/// * [`Seek`] +/// * [`BufRead`] +/// +/// [`FusedIterator`]: iter::FusedIterator +/// [`TrustedLen`]: iter::TrustedLen +#[doc = concat!("[`Seek`]: ", include_str!("../primitive_docs/io_seek.md"))] +#[doc = concat!("[`BufRead`]: ", include_str!("../primitive_docs/io_bufread.md"))] +#[doc = concat!("[`Read`]: ", include_str!("../primitive_docs/io_read.md"))] +#[doc = concat!("[`io::Write`]: ", include_str!("../primitive_docs/io_write.md"))] +/// +/// Note that due to method call deref coercion, simply calling a trait method will act like they +/// work on references as well as they do on owned values! The implementations described here are +/// meant for generic contexts, where the final type `T` is a type parameter or otherwise not +/// locally known. +#[stable(feature = "rust1", since = "1.0.0")] +mod prim_ref {} + +#[doc(primitive = "fn")] +// +/// Function pointers, like `fn(usize) -> bool`. +/// +/// *See also the traits [`Fn`], [`FnMut`], and [`FnOnce`].* +/// +/// [`Fn`]: ops::Fn +/// [`FnMut`]: ops::FnMut +/// [`FnOnce`]: ops::FnOnce +/// +/// Function pointers are pointers that point to *code*, not data. They can be called +/// just like functions. Like references, function pointers are, among other things, assumed to +/// not be null, so if you want to pass a function pointer over FFI and be able to accommodate null +/// pointers, make your type [`Option`](core::option#options-and-pointers-nullable-pointers) +/// with your required signature. +/// +/// ### Safety +/// +/// Plain function pointers are obtained by casting either plain functions, or closures that don't +/// capture an environment: +/// +/// ``` +/// fn add_one(x: usize) -> usize { +/// x + 1 +/// } +/// +/// let ptr: fn(usize) -> usize = add_one; +/// assert_eq!(ptr(5), 6); +/// +/// let clos: fn(usize) -> usize = |x| x + 5; +/// assert_eq!(clos(5), 10); +/// ``` +/// +/// In addition to varying based on their signature, function pointers come in two flavors: safe +/// and unsafe. Plain `fn()` function pointers can only point to safe functions, +/// while `unsafe fn()` function pointers can point to safe or unsafe functions. +/// +/// ``` +/// fn add_one(x: usize) -> usize { +/// x + 1 +/// } +/// +/// unsafe fn add_one_unsafely(x: usize) -> usize { +/// x + 1 +/// } +/// +/// let safe_ptr: fn(usize) -> usize = add_one; +/// +/// //ERROR: mismatched types: expected normal fn, found unsafe fn +/// //let bad_ptr: fn(usize) -> usize = add_one_unsafely; +/// +/// let unsafe_ptr: unsafe fn(usize) -> usize = add_one_unsafely; +/// let really_safe_ptr: unsafe fn(usize) -> usize = add_one; +/// ``` +/// +/// ### ABI +/// +/// On top of that, function pointers can vary based on what ABI they use. This +/// is achieved by adding the `extern` keyword before the type, followed by the +/// ABI in question. The default ABI is "Rust", i.e., `fn()` is the exact same +/// type as `extern "Rust" fn()`. A pointer to a function with C ABI would have +/// type `extern "C" fn()`. +/// +/// `extern "ABI" { ... }` blocks declare functions with ABI "ABI". The default +/// here is "C", i.e., functions declared in an `extern {...}` block have "C" +/// ABI. +/// +/// For more information and a list of supported ABIs, see [the nomicon's +/// section on foreign calling conventions][nomicon-abi]. +/// +/// [nomicon-abi]: ../nomicon/ffi.html#foreign-calling-conventions +/// +/// ### Variadic functions +/// +/// Extern function declarations with the "C" or "cdecl" ABIs can also be *variadic*, allowing them +/// to be called with a variable number of arguments. Normal Rust functions, even those with an +/// `extern "ABI"`, cannot be variadic. For more information, see [the nomicon's section on +/// variadic functions][nomicon-variadic]. +/// +/// [nomicon-variadic]: ../nomicon/ffi.html#variadic-functions +/// +/// ### Creating function pointers +/// +/// When `bar` is the name of a function, then the expression `bar` is *not* a +/// function pointer. Rather, it denotes a value of an unnameable type that +/// uniquely identifies the function `bar`. The value is zero-sized because the +/// type already identifies the function. This has the advantage that "calling" +/// the value (it implements the `Fn*` traits) does not require dynamic +/// dispatch. +/// +/// This zero-sized type *coerces* to a regular function pointer. For example: +/// +/// ```rust +/// use std::mem; +/// +/// fn bar(x: i32) {} +/// +/// let not_bar_ptr = bar; // `not_bar_ptr` is zero-sized, uniquely identifying `bar` +/// assert_eq!(mem::size_of_val(¬_bar_ptr), 0); +/// +/// let bar_ptr: fn(i32) = not_bar_ptr; // force coercion to function pointer +/// assert_eq!(mem::size_of_val(&bar_ptr), mem::size_of::()); +/// +/// let footgun = &bar; // this is a shared reference to the zero-sized type identifying `bar` +/// ``` +/// +/// The last line shows that `&bar` is not a function pointer either. Rather, it +/// is a reference to the function-specific ZST. `&bar` is basically never what you +/// want when `bar` is a function. +/// +/// ### Traits +/// +/// Function pointers implement the following traits: +/// +/// * [`Clone`] +/// * [`PartialEq`] +/// * [`Eq`] +/// * [`PartialOrd`] +/// * [`Ord`] +/// * [`Hash`] +/// * [`Pointer`] +/// * [`Debug`] +/// +/// [`Hash`]: hash::Hash +/// [`Pointer`]: fmt::Pointer +/// +/// Due to a temporary restriction in Rust's type system, these traits are only implemented on +/// functions that take 12 arguments or less, with the `"Rust"` and `"C"` ABIs. In the future, this +/// may change. +/// +/// In addition, function pointers of *any* signature, ABI, or safety are [`Copy`], and all *safe* +/// function pointers implement [`Fn`], [`FnMut`], and [`FnOnce`]. This works because these traits +/// are specially known to the compiler. +#[stable(feature = "rust1", since = "1.0.0")] +mod prim_fn {} diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs index 87c8674af0..ee93f00a7f 100644 --- a/library/core/src/ptr/non_null.rs +++ b/library/core/src/ptr/non_null.rs @@ -119,6 +119,7 @@ impl NonNull { /// /// [the module documentation]: crate::ptr#safety #[inline] + #[must_use] #[unstable(feature = "ptr_as_uninit", issue = "75402")] pub unsafe fn as_uninit_ref<'a>(&self) -> &'a MaybeUninit { // SAFETY: the caller must guarantee that `self` meets all the @@ -151,6 +152,7 @@ impl NonNull { /// /// [the module documentation]: crate::ptr#safety #[inline] + #[must_use] #[unstable(feature = "ptr_as_uninit", issue = "75402")] pub unsafe fn as_uninit_mut<'a>(&mut self) -> &'a mut MaybeUninit { // SAFETY: the caller must guarantee that `self` meets all the @@ -240,6 +242,8 @@ impl NonNull { /// The pointer can be later reconstructed with [`NonNull::from_raw_parts`]. #[unstable(feature = "ptr_metadata", issue = "81513")] #[rustc_const_unstable(feature = "ptr_metadata", issue = "81513")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[inline] pub const fn to_raw_parts(self) -> (NonNull<()>, ::Metadata) { (self.cast(), super::metadata(self.as_ptr())) @@ -264,6 +268,7 @@ impl NonNull { /// ``` #[stable(feature = "nonnull", since = "1.25.0")] #[rustc_const_stable(feature = "const_nonnull_as_ptr", since = "1.32.0")] + #[must_use] #[inline] pub const fn as_ptr(self) -> *mut T { self.pointer as *mut T @@ -310,6 +315,7 @@ impl NonNull { /// /// [the module documentation]: crate::ptr#safety #[stable(feature = "nonnull", since = "1.25.0")] + #[must_use] #[inline] pub unsafe fn as_ref<'a>(&self) -> &'a T { // SAFETY: the caller must guarantee that `self` meets all the @@ -359,6 +365,7 @@ impl NonNull { /// /// [the module documentation]: crate::ptr#safety #[stable(feature = "nonnull", since = "1.25.0")] + #[must_use] #[inline] pub unsafe fn as_mut<'a>(&mut self) -> &'a mut T { // SAFETY: the caller must guarantee that `self` meets all the @@ -381,6 +388,8 @@ impl NonNull { /// ``` #[stable(feature = "nonnull_cast", since = "1.27.0")] #[rustc_const_stable(feature = "const_nonnull_cast", since = "1.36.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[inline] pub const fn cast(self) -> NonNull { // SAFETY: `self` is a `NonNull` pointer which is necessarily non-null @@ -455,6 +464,7 @@ impl NonNull<[T]> { /// assert_eq!(slice.as_non_null_ptr(), NonNull::new(1 as *mut i8).unwrap()); /// ``` #[inline] + #[must_use] #[unstable(feature = "slice_ptr_get", issue = "74265")] #[rustc_const_unstable(feature = "slice_ptr_get", issue = "74265")] pub const fn as_non_null_ptr(self) -> NonNull { @@ -474,6 +484,7 @@ impl NonNull<[T]> { /// assert_eq!(slice.as_mut_ptr(), 1 as *mut i8); /// ``` #[inline] + #[must_use] #[unstable(feature = "slice_ptr_get", issue = "74265")] #[rustc_const_unstable(feature = "slice_ptr_get", issue = "74265")] pub const fn as_mut_ptr(self) -> *mut T { @@ -518,6 +529,7 @@ impl NonNull<[T]> { /// /// [valid]: crate::ptr#safety #[inline] + #[must_use] #[unstable(feature = "ptr_as_uninit", issue = "75402")] pub unsafe fn as_uninit_slice<'a>(&self) -> &'a [MaybeUninit] { // SAFETY: the caller must uphold the safety contract for `as_uninit_slice`. @@ -579,6 +591,7 @@ impl NonNull<[T]> { /// # Ok::<_, std::alloc::AllocError>(()) /// ``` #[inline] + #[must_use] #[unstable(feature = "ptr_as_uninit", issue = "75402")] pub unsafe fn as_uninit_slice_mut<'a>(&self) -> &'a mut [MaybeUninit] { // SAFETY: the caller must uphold the safety contract for `as_uninit_slice_mut`. diff --git a/library/core/src/ptr/unique.rs b/library/core/src/ptr/unique.rs index cd6afdccc2..5baceefb50 100644 --- a/library/core/src/ptr/unique.rs +++ b/library/core/src/ptr/unique.rs @@ -101,6 +101,7 @@ impl Unique { } /// Acquires the underlying `*mut` pointer. + #[must_use = "`self` will be dropped if the result is not used"] #[inline] pub const fn as_ptr(self) -> *mut T { self.pointer as *mut T @@ -111,6 +112,7 @@ impl Unique { /// The resulting lifetime is bound to self so this behaves "as if" /// it were actually an instance of T that is getting borrowed. If a longer /// (unbound) lifetime is needed, use `&*my_ptr.as_ptr()`. + #[must_use] #[inline] pub unsafe fn as_ref(&self) -> &T { // SAFETY: the caller must guarantee that `self` meets all the @@ -123,6 +125,7 @@ impl Unique { /// The resulting lifetime is bound to self so this behaves "as if" /// it were actually an instance of T that is getting borrowed. If a longer /// (unbound) lifetime is needed, use `&mut *my_ptr.as_ptr()`. + #[must_use] #[inline] pub unsafe fn as_mut(&mut self) -> &mut T { // SAFETY: the caller must guarantee that `self` meets all the @@ -131,6 +134,7 @@ impl Unique { } /// Casts to a pointer of another type. + #[must_use = "`self` will be dropped if the result is not used"] #[inline] pub const fn cast(self) -> Unique { // SAFETY: Unique::new_unchecked() creates a new unique and needs diff --git a/library/core/src/result.rs b/library/core/src/result.rs index 092e654434..dda827900d 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs @@ -88,7 +88,7 @@ //! ``` //! //! *Note: The actual definition of [`Write`] uses [`io::Result`], which -//! is just a synonym for [`Result`]``.* +//! is just a synonym for [Result].* //! //! This method doesn't produce a value, but the write may //! fail. It's crucial to handle the error case, and *not* write @@ -217,13 +217,13 @@ //! early return of [`Err`] that it provides. //! //! [`expect`]: Result::expect -//! [`Write`]: ../../std/io/trait.Write.html -//! [`write_all`]: ../../std/io/trait.Write.html#method.write_all -//! [`io::Result`]: ../../std/io/type.Result.html +//! [`Write`]: ../../std/io/trait.Write.html "io::Write" +//! [`write_all`]: ../../std/io/trait.Write.html#method.write_all "io::Write::write_all" +//! [`io::Result`]: ../../std/io/type.Result.html "io::Result" //! [`?`]: crate::ops::Try //! [`Ok(T)`]: Ok //! [`Err(E)`]: Err -//! [`io::Error`]: ../../std/io/struct.Error.html +//! [io::Error]: ../../std/io/struct.Error.html "io::Error" //! //! # Method overview //! @@ -329,8 +329,8 @@ //! [`Ok`], or returns the provided default value if the [`Result`] is //! [`Err`] //! * [`map_or_else`] applies the provided function to the contained value -//! of [`Ok`], or applies the provided fallback function to the contained -//! value of [`Err`] +//! of [`Ok`], or applies the provided default fallback function to the +//! contained value of [`Err`] //! //! [`map_or`]: Result::map_or //! [`map_or_else`]: Result::map_or_else @@ -498,7 +498,7 @@ use crate::{convert, fmt, hint}; /// See the [module documentation](self) for details. #[derive(Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)] #[must_use = "this `Result` may be an `Err` variant, which should be handled"] -#[rustc_diagnostic_item = "result_type"] +#[rustc_diagnostic_item = "Result"] #[stable(feature = "rust1", since = "1.0.0")] pub enum Result { /// Contains the success value @@ -795,9 +795,8 @@ impl Result { } } - /// Maps a `Result` to `U` by applying a fallback function to a - /// contained [`Err`] value, or a default function to a - /// contained [`Ok`] value. + /// Maps a `Result` to `U` by applying fallback function `default` to + /// a contained [`Err`] value, or function `f` to a contained [`Ok`] value. /// /// This function can be used to unpack a successful result /// while handling an error. diff --git a/library/core/src/slice/ascii.rs b/library/core/src/slice/ascii.rs index b92ab7e347..cbb5627cef 100644 --- a/library/core/src/slice/ascii.rs +++ b/library/core/src/slice/ascii.rs @@ -72,6 +72,8 @@ impl [u8] { /// let escaped = s.escape_ascii().to_string(); /// assert_eq!(escaped, "0\\t\\r\\n\\'\\\"\\\\\\x9d"); /// ``` + #[must_use = "this returns the escaped bytes as an iterator, \ + without modifying the original"] #[unstable(feature = "inherent_ascii_escape", issue = "77174")] pub fn escape_ascii(&self) -> EscapeAscii<'_> { EscapeAscii { inner: self.iter().flat_map(EscapeByte) } diff --git a/library/core/src/slice/iter.rs b/library/core/src/slice/iter.rs index c0dfba490e..dbf97851b0 100644 --- a/library/core/src/slice/iter.rs +++ b/library/core/src/slice/iter.rs @@ -124,6 +124,7 @@ impl<'a, T> Iter<'a, T> { /// // Now `as_slice` returns "[2, 3]": /// println!("{:?}", iter.as_slice()); /// ``` + #[must_use] #[stable(feature = "iter_to_slice", since = "1.4.0")] pub fn as_slice(&self) -> &'a [T] { self.make_slice() @@ -267,6 +268,7 @@ impl<'a, T> IterMut<'a, T> { /// // Now slice is "[2, 2, 3]": /// println!("{:?}", slice); /// ``` + #[must_use = "`self` will be dropped if the result is not used"] #[stable(feature = "iter_to_slice", since = "1.4.0")] pub fn into_slice(self) -> &'a mut [T] { // SAFETY: the iterator was created from a mutable slice with pointer @@ -297,6 +299,7 @@ impl<'a, T> IterMut<'a, T> { /// // Now `as_slice` returns "[2, 3]": /// assert_eq!(iter.as_slice(), &[2, 3]); /// ``` + #[must_use] #[stable(feature = "slice_iter_mut_as_slice", since = "1.53.0")] pub fn as_slice(&self) -> &[T] { self.make_slice() @@ -1869,6 +1872,7 @@ impl<'a, T> ChunksExactMut<'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 = "`self` will be dropped if the result is not used"] #[stable(feature = "chunks_exact", since = "1.31.0")] pub fn into_remainder(self) -> &'a mut [T] { self.rem @@ -2264,6 +2268,7 @@ impl<'a, T, const N: usize> ArrayChunksMut<'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 = "`self` will be dropped if the result is not used"] #[unstable(feature = "array_chunks", issue = "74985")] pub fn into_remainder(self) -> &'a mut [T] { self.rem @@ -2875,6 +2880,7 @@ impl<'a, T> RChunksExactMut<'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 = "`self` will be dropped if the result is not used"] #[stable(feature = "rchunks", since = "1.31.0")] pub fn into_remainder(self) -> &'a mut [T] { self.rem diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 361a9b03ae..c0e0589d5e 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -98,7 +98,6 @@ impl [T] { #[rustc_const_stable(feature = "const_slice_len", since = "1.39.0")] #[inline] // SAFETY: const sound because we transmute out the length field as a usize (which it must be) - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_fn_union))] pub const fn len(&self) -> usize { // FIXME: Replace with `crate::ptr::metadata(self)` when that is const-stable. // As of this writing this causes a "Const-stable functions can only call other @@ -561,15 +560,52 @@ impl [T] { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn swap(&mut self, a: usize, b: usize) { - // Can't take two mutable loans from one vector, so instead use raw pointers. - let pa = ptr::addr_of_mut!(self[a]); - let pb = ptr::addr_of_mut!(self[b]); - // SAFETY: `pa` and `pb` have been created from safe mutable references and refer - // to elements in the slice and therefore are guaranteed to be valid and aligned. - // Note that accessing the elements behind `a` and `b` is checked and will - // panic when out of bounds. + let _ = &self[a]; + let _ = &self[b]; + + // SAFETY: we just checked that both `a` and `b` are in bounds + unsafe { self.swap_unchecked(a, b) } + } + + /// Swaps two elements in the slice, without doing bounds checking. + /// + /// For a safe alternative see [`swap`]. + /// + /// # Arguments + /// + /// * a - The index of the first element + /// * b - The index of the second element + /// + /// # Safety + /// + /// Calling this method with an out-of-bounds index is *[undefined behavior]*. + /// The caller has to ensure that `a < self.len()` and `b < self.len()`. + /// + /// # Examples + /// + /// ``` + /// #![feature(slice_swap_unchecked)] + /// + /// let mut v = ["a", "b", "c", "d"]; + /// // SAFETY: we know that 1 and 3 are both indices of the slice + /// unsafe { v.swap_unchecked(1, 3) }; + /// assert!(v == ["a", "d", "c", "b"]); + /// ``` + /// + /// [`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) { + #[cfg(debug_assertions)] + { + let _ = &self[a]; + let _ = &self[b]; + } + + let ptr = self.as_mut_ptr(); + // SAFETY: caller has to guarantee that `a < self.len()` and `b < self.len()` unsafe { - ptr::swap(pa, pb); + ptr::swap(ptr.add(a), ptr.add(b)); } } @@ -676,11 +712,7 @@ impl [T] { // The resulting pointers `pa` and `pb` are therefore valid and // aligned, and can be read from and written to. unsafe { - // Unsafe swap to avoid the bounds check in safe swap. - let ptr = self.as_mut_ptr(); - let pa = ptr.add(i); - let pb = ptr.add(ln - i - 1); - ptr::swap(pa, pb); + self.swap_unchecked(i, ln - i - 1); } i += 1; } @@ -1557,7 +1589,7 @@ impl [T] { /// /// # Examples /// - /// ```compile_fail + /// ``` /// #![feature(slice_split_at_unchecked)] /// /// let v = [1, 2, 3, 4, 5, 6]; @@ -1582,7 +1614,7 @@ impl [T] { /// ``` #[unstable(feature = "slice_split_at_unchecked", reason = "new API", issue = "76014")] #[inline] - unsafe fn split_at_unchecked(&self, mid: usize) -> (&[T], &[T]) { + pub unsafe fn split_at_unchecked(&self, mid: usize) -> (&[T], &[T]) { // SAFETY: Caller has to check that `0 <= mid <= self.len()` unsafe { (self.get_unchecked(..mid), self.get_unchecked(mid..)) } } @@ -1606,7 +1638,7 @@ impl [T] { /// /// # Examples /// - /// ```compile_fail + /// ``` /// #![feature(slice_split_at_unchecked)] /// /// let mut v = [1, 0, 3, 0, 5, 6]; @@ -1622,7 +1654,7 @@ impl [T] { /// ``` #[unstable(feature = "slice_split_at_unchecked", reason = "new API", issue = "76014")] #[inline] - unsafe fn split_at_mut_unchecked(&mut self, mid: usize) -> (&mut [T], &mut [T]) { + pub unsafe fn split_at_mut_unchecked(&mut self, mid: usize) -> (&mut [T], &mut [T]) { let len = self.len(); let ptr = self.as_mut_ptr(); @@ -2258,9 +2290,9 @@ impl [T] { /// assert!(match r { Ok(1..=4) => true, _ => false, }); /// ``` // Lint rustdoc::broken_intra_doc_links is allowed as `slice::sort_by_key` is - // in crate `alloc`, and as such doesn't exists yet when building `core`. - // links to downstream crate: #74481. Since primitives are only documented in - // libstd (#73423), this never leads to broken links in practice. + // in crate `alloc`, and as such doesn't exists yet when building `core`: #74481. + // This breaks links when slice is displayed in core, but changing it to use relative links + // would break when the item is re-exported. So allow the core links to be broken for now. #[allow(rustdoc::broken_intra_doc_links)] #[stable(feature = "slice_binary_search_by_key", since = "1.10.0")] #[inline] diff --git a/library/core/src/slice/sort.rs b/library/core/src/slice/sort.rs index 8a31388fbd..60b39295ca 100644 --- a/library/core/src/slice/sort.rs +++ b/library/core/src/slice/sort.rs @@ -6,8 +6,6 @@ //! Unstable sorting is compatible with libcore because it doesn't allocate memory, unlike our //! stable sorting implementation. -// ignore-tidy-undocumented-unsafe - use crate::cmp; use crate::mem::{self, MaybeUninit}; use crate::ptr; @@ -291,6 +289,9 @@ where } else if start_r < end_r { block_l = rem; } else { + // There were the same number of elements to switch on both blocks during the last + // iteration, so there are no remaining elements on either block. Cover the remaining + // items with roughly equally-sized blocks. block_l = rem / 2; block_r = rem - block_l; } @@ -437,6 +438,17 @@ where // Move its remaining out-of-order elements to the far right. debug_assert_eq!(width(l, r), block_l); while start_l < end_l { + // remaining-elements-safety + // SAFETY: while the loop condition holds there are still elements in `offsets_l`, so it + // is safe to point `end_l` to the previous element. + // + // The `ptr::swap` is safe if both its arguments are valid for reads and writes: + // - Per the debug assert above, the distance between `l` and `r` is `block_l` + // elements, so there can be at most `block_l` remaining offsets between `start_l` + // and `end_l`. This means `r` will be moved at most `block_l` steps back, which + // makes the `r.offset` calls valid (at that point `l == r`). + // - `offsets_l` contains valid offsets into `v` collected during the partitioning of + // the last block, so the `l.offset` calls are valid. unsafe { end_l = end_l.offset(-1); ptr::swap(l.offset(*end_l as isize), r.offset(-1)); @@ -449,6 +461,7 @@ where // Move its remaining out-of-order elements to the far left. debug_assert_eq!(width(l, r), block_r); while start_r < end_r { + // SAFETY: See the reasoning in [remaining-elements-safety]. unsafe { end_r = end_r.offset(-1); ptr::swap(l, r.offset(-(*end_r as isize) - 1)); @@ -481,6 +494,8 @@ where // Read the pivot into a stack-allocated variable for efficiency. If a following comparison // operation panics, the pivot will be automatically written back into the slice. + + // SAFETY: `pivot` is a reference to the first element of `v`, so `ptr::read` is safe. let mut tmp = mem::ManuallyDrop::new(unsafe { ptr::read(pivot) }); let _pivot_guard = CopyOnDrop { src: &mut *tmp, dest: pivot }; let pivot = &*tmp; @@ -646,6 +661,12 @@ where if len >= 8 { // Swaps indices so that `v[a] <= v[b]`. + // SAFETY: `len >= 8` so there are at least two elements in the neighborhoods of + // `a`, `b` and `c`. This means the three calls to `sort_adjacent` result in + // corresponding calls to `sort3` with valid 3-item neighborhoods around each + // pointer, which in turn means the calls to `sort2` are done with valid + // references. Thus the `v.get_unchecked` calls are safe, as is the `ptr::swap` + // call. let mut sort2 = |a: &mut usize, b: &mut usize| unsafe { if is_less(v.get_unchecked(*b), v.get_unchecked(*a)) { ptr::swap(a, b); diff --git a/library/core/src/str/converts.rs b/library/core/src/str/converts.rs index e67c0d6487..ed9f49f159 100644 --- a/library/core/src/str/converts.rs +++ b/library/core/src/str/converts.rs @@ -155,9 +155,9 @@ pub fn from_utf8_mut(v: &mut [u8]) -> Result<&mut str, Utf8Error> { /// assert_eq!("💖", sparkle_heart); /// ``` #[inline] +#[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_str_from_utf8_unchecked", since = "1.55.0")] -#[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_fn_transmute))] pub const unsafe fn from_utf8_unchecked(v: &[u8]) -> &str { // SAFETY: the caller must guarantee that the bytes `v` are valid UTF-8. // Also relies on `&str` and `&[u8]` having the same layout. @@ -182,6 +182,7 @@ pub const unsafe fn from_utf8_unchecked(v: &[u8]) -> &str { /// assert_eq!("💖", heart); /// ``` #[inline] +#[must_use] #[stable(feature = "str_mut_extras", since = "1.20.0")] pub unsafe fn from_utf8_unchecked_mut(v: &mut [u8]) -> &mut str { // SAFETY: the caller must guarantee that the bytes `v` diff --git a/library/core/src/str/iter.rs b/library/core/src/str/iter.rs index 8db9edc614..94cb81e9d4 100644 --- a/library/core/src/str/iter.rs +++ b/library/core/src/str/iter.rs @@ -109,6 +109,7 @@ impl<'a> Chars<'a> { /// assert_eq!(chars.as_str(), ""); /// ``` #[stable(feature = "iter_to_slice", since = "1.4.0")] + #[must_use] #[inline] pub fn as_str(&self) -> &'a str { // SAFETY: `Chars` is only made from a str, which guarantees the iter is valid UTF-8. @@ -185,6 +186,7 @@ impl<'a> CharIndices<'a> { /// This has the same lifetime as the original slice, and so the /// iterator can continue to be used while this exists. #[stable(feature = "iter_to_slice", since = "1.4.0")] + #[must_use] #[inline] pub fn as_str(&self) -> &'a str { self.iter.as_str() @@ -1247,6 +1249,7 @@ impl<'a> SplitWhitespace<'a> { /// assert_eq!(split.as_str(), ""); /// ``` #[inline] + #[must_use] #[unstable(feature = "str_split_whitespace_as_str", issue = "77998")] pub fn as_str(&self) -> &'a str { self.inner.iter.as_str() @@ -1302,6 +1305,7 @@ impl<'a> SplitAsciiWhitespace<'a> { /// assert_eq!(split.as_str(), ""); /// ``` #[inline] + #[must_use] #[unstable(feature = "str_split_whitespace_as_str", issue = "77998")] pub fn as_str(&self) -> &'a str { if self.inner.iter.iter.finished { diff --git a/library/core/src/str/lossy.rs b/library/core/src/str/lossy.rs index 720a35bbc8..d3c9d21c3c 100644 --- a/library/core/src/str/lossy.rs +++ b/library/core/src/str/lossy.rs @@ -12,10 +12,12 @@ pub struct Utf8Lossy { } impl Utf8Lossy { + #[must_use] pub fn from_str(s: &str) -> &Utf8Lossy { Utf8Lossy::from_bytes(s.as_bytes()) } + #[must_use] pub fn from_bytes(bytes: &[u8]) -> &Utf8Lossy { // SAFETY: Both use the same memory layout, and UTF-8 correctness isn't required. unsafe { mem::transmute(bytes) } diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs index ca4e2e6b7f..607a0179ff 100644 --- a/library/core/src/str/mod.rs +++ b/library/core/src/str/mod.rs @@ -188,6 +188,7 @@ impl str { /// // third byte of `老` /// assert!(!s.is_char_boundary(8)); /// ``` + #[must_use] #[stable(feature = "is_char_boundary", since = "1.9.0")] #[inline] pub fn is_char_boundary(&self, index: usize) -> bool { @@ -229,9 +230,9 @@ impl str { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "str_as_bytes", since = "1.39.0")] + #[must_use] #[inline(always)] #[allow(unused_attributes)] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_fn_transmute))] pub const fn as_bytes(&self) -> &[u8] { // SAFETY: const sound because we transmute two types with the same layout unsafe { mem::transmute(self) } @@ -274,6 +275,7 @@ impl str { /// assert_eq!("🍔∈🌏", s); /// ``` #[stable(feature = "str_mut_extras", since = "1.20.0")] + #[must_use] #[inline(always)] pub unsafe fn as_bytes_mut(&mut self) -> &mut [u8] { // SAFETY: the cast from `&str` to `&[u8]` is safe since `str` @@ -304,6 +306,7 @@ impl str { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "rustc_str_as_ptr", since = "1.32.0")] + #[must_use] #[inline] pub const fn as_ptr(&self) -> *const u8 { self as *const str as *const u8 @@ -318,6 +321,7 @@ impl str { /// It is your responsibility to make sure that the string slice only gets /// modified in a way that it remains valid UTF-8. #[stable(feature = "str_as_mut_ptr", since = "1.36.0")] + #[must_use] #[inline] pub fn as_mut_ptr(&mut self) -> *mut u8 { self as *mut str as *mut u8 @@ -799,6 +803,8 @@ impl str { /// /// assert_eq!(None, iter.next()); /// ``` + #[must_use = "this returns the split string as an iterator, \ + without modifying the original"] #[stable(feature = "split_whitespace", since = "1.1.0")] #[inline] pub fn split_whitespace(&self) -> SplitWhitespace<'_> { @@ -840,6 +846,8 @@ impl str { /// /// assert_eq!(None, iter.next()); /// ``` + #[must_use = "this returns the split string as an iterator, \ + without modifying the original"] #[stable(feature = "split_ascii_whitespace", since = "1.34.0")] #[inline] pub fn split_ascii_whitespace(&self) -> SplitAsciiWhitespace<'_> { @@ -915,6 +923,8 @@ impl str { /// /// assert!(utf16_len <= utf8_len); /// ``` + #[must_use = "this returns the encoded string as an iterator, \ + without modifying the original"] #[stable(feature = "encode_utf16", since = "1.8.0")] pub fn encode_utf16(&self) -> EncodeUtf16<'_> { EncodeUtf16 { chars: self.chars(), extra: 0 } @@ -1354,6 +1364,9 @@ impl str { /// /// let v: Vec<&str> = "A..B..".split_terminator(".").collect(); /// assert_eq!(v, ["A", "", "B", ""]); + /// + /// let v: Vec<&str> = "A.B:C.D".split_terminator(&['.', ':'][..]).collect(); + /// assert_eq!(v, ["A", "B", "C", "D"]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -1397,6 +1410,9 @@ impl str { /// /// let v: Vec<&str> = "A..B..".rsplit_terminator(".").collect(); /// assert_eq!(v, ["", "B", "", "A"]); + /// + /// let v: Vec<&str> = "A.B:C.D".rsplit_terminator(&['.', ':'][..]).collect(); + /// assert_eq!(v, ["D", "C", "B", "A"]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -1525,7 +1541,8 @@ impl str { #[inline] pub fn split_once<'a, P: Pattern<'a>>(&'a self, delimiter: P) -> Option<(&'a str, &'a str)> { let (start, end) = delimiter.into_searcher(self).next_match()?; - Some((&self[..start], &self[end..])) + // SAFETY: `Searcher` is known to return valid indices. + unsafe { Some((self.get_unchecked(..start), self.get_unchecked(end..))) } } /// Splits the string on the last occurrence of the specified delimiter and @@ -1545,7 +1562,8 @@ impl str { P: Pattern<'a, Searcher: ReverseSearcher<'a>>, { let (start, end) = delimiter.into_searcher(self).next_match_back()?; - Some((&self[..start], &self[end..])) + // SAFETY: `Searcher` is known to return valid indices. + unsafe { Some((self.get_unchecked(..start), self.get_unchecked(end..))) } } /// An iterator over the disjoint matches of a pattern within the given string @@ -1841,6 +1859,8 @@ impl str { /// let s = " עברית"; /// assert!(Some('ע') == s.trim_left().chars().next()); /// ``` + #[must_use = "this returns the trimmed string as a new slice, \ + without modifying the original"] #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_deprecated( @@ -1883,6 +1903,8 @@ impl str { /// let s = "עברית "; /// assert!(Some('ת') == s.trim_right().chars().rev().next()); /// ``` + #[must_use = "this returns the trimmed string as a new slice, \ + without modifying the original"] #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_deprecated( @@ -2347,6 +2369,8 @@ impl str { /// ``` /// assert_eq!("❤\n!".escape_debug().to_string(), "❤\\n!"); /// ``` + #[must_use = "this returns the escaped string as an iterator, \ + without modifying the original"] #[stable(feature = "str_escape", since = "1.34.0")] pub fn escape_debug(&self) -> EscapeDebug<'_> { let mut chars = self.chars(); @@ -2391,6 +2415,8 @@ impl str { /// ``` /// assert_eq!("❤\n!".escape_default().to_string(), "\\u{2764}\\n!"); /// ``` + #[must_use = "this returns the escaped string as an iterator, \ + without modifying the original"] #[stable(feature = "str_escape", since = "1.34.0")] pub fn escape_default(&self) -> EscapeDefault<'_> { EscapeDefault { inner: self.chars().flat_map(CharEscapeDefault) } @@ -2427,6 +2453,8 @@ impl str { /// ``` /// assert_eq!("❤\n!".escape_unicode().to_string(), "\\u{2764}\\u{a}\\u{21}"); /// ``` + #[must_use = "this returns the escaped string as an iterator, \ + without modifying the original"] #[stable(feature = "str_escape", since = "1.34.0")] pub fn escape_unicode(&self) -> EscapeUnicode<'_> { EscapeUnicode { inner: self.chars().flat_map(CharEscapeUnicode) } diff --git a/library/core/src/str/traits.rs b/library/core/src/str/traits.rs index 12d79a56a5..e225776bc6 100644 --- a/library/core/src/str/traits.rs +++ b/library/core/src/str/traits.rs @@ -536,7 +536,7 @@ pub trait FromStr: Sized { /// /// If parsing succeeds, return the value inside [`Ok`], otherwise /// when the string is ill-formatted return an error specific to the - /// inside [`Err`]. The error type is specific to implementation of the trait. + /// inside [`Err`]. The error type is specific to the implementation of the trait. /// /// # Examples /// diff --git a/library/core/src/str/validations.rs b/library/core/src/str/validations.rs index 373a821242..093c9c37b6 100644 --- a/library/core/src/str/validations.rs +++ b/library/core/src/str/validations.rs @@ -22,7 +22,7 @@ fn utf8_acc_cont_byte(ch: u32, byte: u8) -> u32 { /// bits `10`). #[inline] pub(super) fn utf8_is_cont_byte(byte: u8) -> bool { - (byte & !CONT_MASK) == TAG_CONT_U8 + (byte as i8) < -64 } #[inline] @@ -163,7 +163,7 @@ pub(super) fn run_utf8_validation(v: &[u8]) -> Result<(), Utf8Error> { // %xF4 %x80-8F 2( UTF8-tail ) match w { 2 => { - if next!() & !CONT_MASK != TAG_CONT_U8 { + if next!() as i8 >= -64 { err!(Some(1)) } } @@ -175,7 +175,7 @@ pub(super) fn run_utf8_validation(v: &[u8]) -> Result<(), Utf8Error> { | (0xEE..=0xEF, 0x80..=0xBF) => {} _ => err!(Some(1)), } - if next!() & !CONT_MASK != TAG_CONT_U8 { + if next!() as i8 >= -64 { err!(Some(2)) } } @@ -184,10 +184,10 @@ pub(super) fn run_utf8_validation(v: &[u8]) -> Result<(), Utf8Error> { (0xF0, 0x90..=0xBF) | (0xF1..=0xF3, 0x80..=0xBF) | (0xF4, 0x80..=0x8F) => {} _ => err!(Some(1)), } - if next!() & !CONT_MASK != TAG_CONT_U8 { + if next!() as i8 >= -64 { err!(Some(2)) } - if next!() & !CONT_MASK != TAG_CONT_U8 { + if next!() as i8 >= -64 { err!(Some(3)) } } @@ -258,8 +258,6 @@ pub fn utf8_char_width(b: u8) -> usize { /// Mask of the value bits of a continuation byte. const CONT_MASK: u8 = 0b0011_1111; -/// Value of the tag bits (tag mask is !CONT_MASK) of a continuation byte. -const TAG_CONT_U8: u8 = 0b1000_0000; // truncate `&str` to length at most equal to `max` // return `true` if it were truncated, and the new str. diff --git a/library/core/src/stream/stream/mod.rs b/library/core/src/stream/stream/mod.rs index e37902dae1..d102619b8e 100644 --- a/library/core/src/stream/stream/mod.rs +++ b/library/core/src/stream/stream/mod.rs @@ -52,7 +52,7 @@ pub trait Stream { /// Specifically, `size_hint()` returns a tuple where the first element /// is the lower bound, and the second element is the upper bound. /// - /// The second half of the tuple that is returned is an [`Option`]`<`[`usize`]`>`. + /// The second half of the tuple that is returned is an [Option]<[usize]>. /// A [`None`] here means that either there is no known upper bound, or the /// upper bound is larger than [`usize`]. /// @@ -71,7 +71,7 @@ pub trait Stream { /// That said, the implementation should provide a correct estimation, /// because otherwise it would be a violation of the trait's protocol. /// - /// The default implementation returns `(0, `[`None`]`)` which is correct for any + /// The default implementation returns (0, [None]) which is correct for any /// stream. #[inline] fn size_hint(&self) -> (usize, Option) { diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index d9de37e9c5..1247f33087 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs @@ -62,7 +62,7 @@ //! some atomic operations. Maximally portable code will want to be careful //! about which atomic types are used. `AtomicUsize` and `AtomicIsize` are //! generally the most portable, but even then they're not available everywhere. -//! For reference, the `std` library requires pointer-sized atomics, although +//! For reference, the `std` library requires `AtomicBool`s and pointer-sized atomics, although //! `core` does not. //! //! Currently you'll need to use `#[cfg(target_arch)]` primarily to @@ -290,6 +290,7 @@ impl AtomicBool { #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_atomic_new", since = "1.24.0")] + #[must_use] pub const fn new(v: bool) -> AtomicBool { AtomicBool { v: UnsafeCell::new(v as u8) } } @@ -1392,6 +1393,7 @@ macro_rules! atomic_int { #[inline] #[$stable] #[$const_stable] + #[must_use] pub const fn new(v: $int_type) -> Self { Self {v: UnsafeCell::new(v)} } diff --git a/library/core/src/task/mod.rs b/library/core/src/task/mod.rs index 3d6f4f5971..71a67a2793 100644 --- a/library/core/src/task/mod.rs +++ b/library/core/src/task/mod.rs @@ -13,3 +13,5 @@ pub use self::wake::{Context, RawWaker, RawWakerVTable, Waker}; mod ready; #[unstable(feature = "ready_macro", issue = "70922")] pub use ready::ready; +#[unstable(feature = "poll_ready", issue = "89780")] +pub use ready::Ready; diff --git a/library/core/src/task/poll.rs b/library/core/src/task/poll.rs index 2507046099..80e1458dc9 100644 --- a/library/core/src/task/poll.rs +++ b/library/core/src/task/poll.rs @@ -3,6 +3,7 @@ use crate::convert; use crate::ops::{self, ControlFlow}; use crate::result::Result; +use crate::task::Ready; /// Indicates whether a value is available or if the current task has been /// scheduled to receive a wakeup instead. @@ -30,9 +31,10 @@ impl Poll { /// /// # Examples /// - /// Converts a `Poll<`[`String`]`>` into an `Poll<`[`usize`]`>`, consuming the original: + /// Converts a Poll<[String]> into a Poll<[usize]>, consuming + /// the original: /// - /// [`String`]: ../../std/string/struct.String.html + /// [String]: ../../std/string/struct.String.html "String" /// ``` /// # use core::task::Poll; /// let poll_some_string = Poll::Ready(String::from("Hello, World!")); @@ -91,6 +93,38 @@ impl Poll { pub const fn is_pending(&self) -> bool { !self.is_ready() } + + /// Extracts the successful type of a [`Poll`]. + /// + /// When combined with the `?` operator, this function will + /// propagate any [`Poll::Pending`] values to the caller, and + /// extract the `T` from [`Poll::Ready`]. + /// + /// # Examples + /// + /// ```rust + /// #![feature(poll_ready)] + /// + /// use std::task::{Context, Poll}; + /// use std::future::{self, Future}; + /// use std::pin::Pin; + /// + /// pub fn do_poll(cx: &mut Context<'_>) -> Poll<()> { + /// let mut fut = future::ready(42); + /// let fut = Pin::new(&mut fut); + /// + /// let num = fut.poll(cx).ready()?; + /// # drop(num); + /// // ... use num + /// + /// Poll::Ready(()) + /// } + /// ``` + #[inline] + #[unstable(feature = "poll_ready", issue = "89780")] + pub fn ready(self) -> Ready { + Ready(self) + } } impl Poll> { diff --git a/library/core/src/task/ready.rs b/library/core/src/task/ready.rs index 8fd6560a51..174ca67546 100644 --- a/library/core/src/task/ready.rs +++ b/library/core/src/task/ready.rs @@ -1,3 +1,8 @@ +use core::convert; +use core::fmt; +use core::ops::{ControlFlow, FromResidual, Try}; +use core::task::Poll; + /// Extracts the successful type of a [`Poll`]. /// /// This macro bakes in propagation of [`Pending`] signals by returning early. @@ -58,3 +63,55 @@ pub macro ready($e:expr) { } } } + +/// Extracts the successful type of a [`Poll`]. +/// +/// See [`Poll::ready`] for details. +#[unstable(feature = "poll_ready", issue = "89780")] +pub struct Ready(pub(crate) Poll); + +#[unstable(feature = "poll_ready", issue = "89780")] +impl Try for Ready { + type Output = T; + type Residual = Ready; + + #[inline] + fn from_output(output: Self::Output) -> Self { + Ready(Poll::Ready(output)) + } + + #[inline] + fn branch(self) -> ControlFlow { + match self.0 { + Poll::Ready(v) => ControlFlow::Continue(v), + Poll::Pending => ControlFlow::Break(Ready(Poll::Pending)), + } + } +} + +#[unstable(feature = "poll_ready", issue = "89780")] +impl FromResidual for Ready { + #[inline] + fn from_residual(residual: Ready) -> Self { + match residual.0 { + Poll::Pending => Ready(Poll::Pending), + } + } +} + +#[unstable(feature = "poll_ready", issue = "89780")] +impl FromResidual> for Poll { + #[inline] + fn from_residual(residual: Ready) -> Self { + match residual.0 { + Poll::Pending => Poll::Pending, + } + } +} + +#[unstable(feature = "poll_ready", issue = "89780")] +impl fmt::Debug for Ready { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("Ready").finish() + } +} diff --git a/library/core/src/task/wake.rs b/library/core/src/task/wake.rs index b775e022a5..620bff5387 100644 --- a/library/core/src/task/wake.rs +++ b/library/core/src/task/wake.rs @@ -39,6 +39,7 @@ impl RawWaker { #[rustc_promotable] #[stable(feature = "futures_api", since = "1.36.0")] #[rustc_const_stable(feature = "futures_api", since = "1.36.0")] + #[must_use] pub const fn new(data: *const (), vtable: &'static RawWakerVTable) -> RawWaker { RawWaker { data, vtable } } @@ -158,6 +159,7 @@ pub struct Context<'a> { impl<'a> Context<'a> { /// Create a new `Context` from a `&Waker`. #[stable(feature = "futures_api", since = "1.36.0")] + #[must_use] #[inline] pub fn from_waker(waker: &'a Waker) -> Self { Context { waker, _marker: PhantomData } @@ -251,6 +253,7 @@ impl Waker { /// in [`RawWaker`]'s and [`RawWakerVTable`]'s documentation is not upheld. /// Therefore this method is unsafe. #[inline] + #[must_use] #[stable(feature = "futures_api", since = "1.36.0")] pub unsafe fn from_raw(waker: RawWaker) -> Waker { Waker { waker } diff --git a/library/core/src/time.rs b/library/core/src/time.rs index 35b740cd74..5a74f39e8b 100644 --- a/library/core/src/time.rs +++ b/library/core/src/time.rs @@ -181,6 +181,7 @@ impl Duration { #[stable(feature = "duration", since = "1.3.0")] #[inline] #[rustc_const_unstable(feature = "duration_consts_2", issue = "72440")] + #[must_use] pub const fn new(secs: u64, nanos: u32) -> Duration { let secs = match secs.checked_add((nanos / NANOS_PER_SEC) as u64) { Some(secs) => secs, @@ -203,6 +204,7 @@ impl Duration { /// assert_eq!(0, duration.subsec_nanos()); /// ``` #[stable(feature = "duration", since = "1.3.0")] + #[must_use] #[inline] #[rustc_const_stable(feature = "duration_consts", since = "1.32.0")] pub const fn from_secs(secs: u64) -> Duration { @@ -222,6 +224,7 @@ impl Duration { /// assert_eq!(569_000_000, duration.subsec_nanos()); /// ``` #[stable(feature = "duration", since = "1.3.0")] + #[must_use] #[inline] #[rustc_const_stable(feature = "duration_consts", since = "1.32.0")] pub const fn from_millis(millis: u64) -> Duration { @@ -244,6 +247,7 @@ impl Duration { /// assert_eq!(2000, duration.subsec_nanos()); /// ``` #[stable(feature = "duration_from_micros", since = "1.27.0")] + #[must_use] #[inline] #[rustc_const_stable(feature = "duration_consts", since = "1.32.0")] pub const fn from_micros(micros: u64) -> Duration { @@ -266,6 +270,7 @@ impl Duration { /// assert_eq!(123, duration.subsec_nanos()); /// ``` #[stable(feature = "duration_extras", since = "1.27.0")] + #[must_use] #[inline] #[rustc_const_stable(feature = "duration_consts", since = "1.32.0")] pub const fn from_nanos(nanos: u64) -> Duration { @@ -291,6 +296,7 @@ impl Duration { /// assert!(!Duration::from_nanos(1).is_zero()); /// assert!(!Duration::from_secs(1).is_zero()); /// ``` + #[must_use] #[stable(feature = "duration_zero", since = "1.53.0")] #[rustc_const_stable(feature = "duration_zero", since = "1.53.0")] #[inline] @@ -328,6 +334,7 @@ impl Duration { /// [`subsec_nanos`]: Duration::subsec_nanos #[stable(feature = "duration", since = "1.3.0")] #[rustc_const_stable(feature = "duration", since = "1.32.0")] + #[must_use] #[inline] pub const fn as_secs(&self) -> u64 { self.secs @@ -411,6 +418,7 @@ impl Duration { /// ``` #[stable(feature = "duration_as_u128", since = "1.33.0")] #[rustc_const_stable(feature = "duration_as_u128", since = "1.33.0")] + #[must_use] #[inline] pub const fn as_millis(&self) -> u128 { self.secs as u128 * MILLIS_PER_SEC as u128 + (self.nanos / NANOS_PER_MILLI) as u128 @@ -428,6 +436,7 @@ impl Duration { /// ``` #[stable(feature = "duration_as_u128", since = "1.33.0")] #[rustc_const_stable(feature = "duration_as_u128", since = "1.33.0")] + #[must_use] #[inline] pub const fn as_micros(&self) -> u128 { self.secs as u128 * MICROS_PER_SEC as u128 + (self.nanos / NANOS_PER_MICRO) as u128 @@ -445,6 +454,7 @@ impl Duration { /// ``` #[stable(feature = "duration_as_u128", since = "1.33.0")] #[rustc_const_stable(feature = "duration_as_u128", since = "1.33.0")] + #[must_use] #[inline] pub const fn as_nanos(&self) -> u128 { self.secs as u128 * NANOS_PER_SEC as u128 + self.nanos as u128 @@ -464,6 +474,8 @@ impl Duration { /// assert_eq!(Duration::new(1, 0).checked_add(Duration::new(u64::MAX, 0)), None); /// ``` #[stable(feature = "duration_checked_ops", since = "1.16.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[inline] #[rustc_const_unstable(feature = "duration_consts_2", issue = "72440")] pub const fn checked_add(self, rhs: Duration) -> Option { @@ -497,6 +509,8 @@ impl Duration { /// assert_eq!(Duration::new(1, 0).saturating_add(Duration::new(u64::MAX, 0)), Duration::MAX); /// ``` #[stable(feature = "duration_saturating_ops", since = "1.53.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[inline] #[rustc_const_unstable(feature = "duration_consts_2", issue = "72440")] pub const fn saturating_add(self, rhs: Duration) -> Duration { @@ -520,6 +534,8 @@ impl Duration { /// assert_eq!(Duration::new(0, 0).checked_sub(Duration::new(0, 1)), None); /// ``` #[stable(feature = "duration_checked_ops", since = "1.16.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[inline] #[rustc_const_unstable(feature = "duration_consts_2", issue = "72440")] pub const fn checked_sub(self, rhs: Duration) -> Option { @@ -551,6 +567,8 @@ impl Duration { /// assert_eq!(Duration::new(0, 0).saturating_sub(Duration::new(0, 1)), Duration::ZERO); /// ``` #[stable(feature = "duration_saturating_ops", since = "1.53.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[inline] #[rustc_const_unstable(feature = "duration_consts_2", issue = "72440")] pub const fn saturating_sub(self, rhs: Duration) -> Duration { @@ -574,6 +592,8 @@ impl Duration { /// assert_eq!(Duration::new(u64::MAX - 1, 0).checked_mul(2), None); /// ``` #[stable(feature = "duration_checked_ops", since = "1.16.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[inline] #[rustc_const_unstable(feature = "duration_consts_2", issue = "72440")] pub const fn checked_mul(self, rhs: u32) -> Option { @@ -603,6 +623,8 @@ impl Duration { /// assert_eq!(Duration::new(u64::MAX - 1, 0).saturating_mul(2), Duration::MAX); /// ``` #[stable(feature = "duration_saturating_ops", since = "1.53.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[inline] #[rustc_const_unstable(feature = "duration_consts_2", issue = "72440")] pub const fn saturating_mul(self, rhs: u32) -> Duration { @@ -627,6 +649,8 @@ impl Duration { /// assert_eq!(Duration::new(2, 0).checked_div(0), None); /// ``` #[stable(feature = "duration_checked_ops", since = "1.16.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[inline] #[rustc_const_unstable(feature = "duration_consts_2", issue = "72440")] pub const fn checked_div(self, rhs: u32) -> Option { @@ -654,6 +678,7 @@ impl Duration { /// assert_eq!(dur.as_secs_f64(), 2.7); /// ``` #[stable(feature = "duration_float", since = "1.38.0")] + #[must_use] #[inline] #[rustc_const_unstable(feature = "duration_consts_2", issue = "72440")] pub const fn as_secs_f64(&self) -> f64 { @@ -672,6 +697,7 @@ impl Duration { /// assert_eq!(dur.as_secs_f32(), 2.7); /// ``` #[stable(feature = "duration_float", since = "1.38.0")] + #[must_use] #[inline] #[rustc_const_unstable(feature = "duration_consts_2", issue = "72440")] pub const fn as_secs_f32(&self) -> f32 { @@ -692,6 +718,7 @@ impl Duration { /// assert_eq!(dur, Duration::new(2, 700_000_000)); /// ``` #[stable(feature = "duration_float", since = "1.38.0")] + #[must_use] #[inline] #[rustc_const_unstable(feature = "duration_consts_2", issue = "72440")] pub const fn from_secs_f64(secs: f64) -> Duration { @@ -753,6 +780,7 @@ impl Duration { /// assert_eq!(dur, Duration::new(2, 700_000_000)); /// ``` #[stable(feature = "duration_float", since = "1.38.0")] + #[must_use] #[inline] #[rustc_const_unstable(feature = "duration_consts_2", issue = "72440")] pub const fn from_secs_f32(secs: f32) -> Duration { @@ -814,6 +842,8 @@ impl Duration { /// assert_eq!(dur.mul_f64(3.14e5), Duration::new(847_800, 0)); /// ``` #[stable(feature = "duration_float", since = "1.38.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[inline] #[rustc_const_unstable(feature = "duration_consts_2", issue = "72440")] pub const fn mul_f64(self, rhs: f64) -> Duration { @@ -836,6 +866,8 @@ impl Duration { /// assert_eq!(dur.mul_f32(3.14e5), Duration::new(847799, 969_120_256)); /// ``` #[stable(feature = "duration_float", since = "1.38.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[inline] #[rustc_const_unstable(feature = "duration_consts_2", issue = "72440")] pub const fn mul_f32(self, rhs: f32) -> Duration { @@ -857,6 +889,8 @@ impl Duration { /// assert_eq!(dur.div_f64(3.14e5), Duration::new(0, 8_598)); /// ``` #[stable(feature = "duration_float", since = "1.38.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[inline] #[rustc_const_unstable(feature = "duration_consts_2", issue = "72440")] pub const fn div_f64(self, rhs: f64) -> Duration { @@ -880,6 +914,8 @@ impl Duration { /// assert_eq!(dur.div_f32(3.14e5), Duration::new(0, 8_598)); /// ``` #[stable(feature = "duration_float", since = "1.38.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[inline] #[rustc_const_unstable(feature = "duration_consts_2", issue = "72440")] pub const fn div_f32(self, rhs: f32) -> Duration { @@ -898,6 +934,8 @@ impl Duration { /// assert_eq!(dur1.div_duration_f64(dur2), 0.5); /// ``` #[unstable(feature = "div_duration", issue = "63139")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[inline] #[rustc_const_unstable(feature = "duration_consts_2", issue = "72440")] pub const fn div_duration_f64(self, rhs: Duration) -> f64 { @@ -916,6 +954,8 @@ impl Duration { /// assert_eq!(dur1.div_duration_f32(dur2), 0.5); /// ``` #[unstable(feature = "div_duration", issue = "63139")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[inline] #[rustc_const_unstable(feature = "duration_consts_2", issue = "72440")] pub const fn div_duration_f32(self, rhs: Duration) -> f32 { @@ -1049,11 +1089,16 @@ impl fmt::Debug for Duration { /// `divisor` must not be above 100_000_000. It also should be a power /// of 10, everything else doesn't make sense. `fractional_part` has /// to be less than `10 * divisor`! + /// + /// A prefix and postfix may be added. The whole thing is padded + /// to the formatter's `width`, if specified. fn fmt_decimal( f: &mut fmt::Formatter<'_>, mut integer_part: u64, mut fractional_part: u32, mut divisor: u32, + prefix: &str, + postfix: &str, ) -> fmt::Result { // Encode the fractional part into a temporary buffer. The buffer // only need to hold 9 elements, because `fractional_part` has to @@ -1114,48 +1159,91 @@ impl fmt::Debug for Duration { // set, we only use all digits up to the last non-zero one. let end = f.precision().map(|p| crate::cmp::min(p, 9)).unwrap_or(pos); - // If we haven't emitted a single fractional digit and the precision - // wasn't set to a non-zero value, we don't print the decimal point. - if end == 0 { - write!(f, "{}", integer_part) - } else { - // SAFETY: We are only writing ASCII digits into the buffer and it was - // initialized with '0's, so it contains valid UTF8. - let s = unsafe { crate::str::from_utf8_unchecked(&buf[..end]) }; + // This closure emits the formatted duration without emitting any + // padding (padding is calculated below). + let emit_without_padding = |f: &mut fmt::Formatter<'_>| { + write!(f, "{}{}", prefix, integer_part)?; - // If the user request a precision > 9, we pad '0's at the end. - let w = f.precision().unwrap_or(pos); - write!(f, "{}.{:0 0 { + // SAFETY: We are only writing ASCII digits into the buffer and + // it was initialized with '0's, so it contains valid UTF8. + let s = unsafe { crate::str::from_utf8_unchecked(&buf[..end]) }; + + // If the user request a precision > 9, we pad '0's at the end. + let w = f.precision().unwrap_or(pos); + write!(f, ".{:0 { + // No `width` specified. There's no need to calculate the + // length of the output in this case, just emit it. + emit_without_padding(f) + } + Some(requested_w) => { + // A `width` was specified. Calculate the actual width of + // the output in order to calculate the required padding. + // It consists of 4 parts: + // 1. The prefix: is either "+" or "", so we can just use len(). + // 2. The postfix: can be "µs" so we have to count UTF8 characters. + let mut actual_w = prefix.len() + postfix.chars().count(); + // 3. The integer part: + if let Some(log) = integer_part.checked_log10() { + // integer_part is > 0, so has length log10(x)+1 + actual_w += 1 + log as usize; + } else { + // integer_part is 0, so has length 1. + actual_w += 1; + } + // 4. The fractional part (if any): + if end > 0 { + let frac_part_w = f.precision().unwrap_or(pos); + actual_w += 1 + frac_part_w; + } + + if requested_w <= actual_w { + // Output is already longer than `width`, so don't pad. + emit_without_padding(f) + } else { + // We need to add padding. Use the `Formatter::padding` helper function. + let default_align = crate::fmt::rt::v1::Alignment::Left; + let post_padding = f.padding(requested_w - actual_w, default_align)?; + emit_without_padding(f)?; + post_padding.write(f) + } + } } } // Print leading '+' sign if requested - if f.sign_plus() { - write!(f, "+")?; - } + let prefix = if f.sign_plus() { "+" } else { "" }; if self.secs > 0 { - fmt_decimal(f, self.secs, self.nanos, NANOS_PER_SEC / 10)?; - f.write_str("s") + fmt_decimal(f, self.secs, self.nanos, NANOS_PER_SEC / 10, prefix, "s") } else if self.nanos >= NANOS_PER_MILLI { fmt_decimal( f, (self.nanos / NANOS_PER_MILLI) as u64, self.nanos % NANOS_PER_MILLI, NANOS_PER_MILLI / 10, - )?; - f.write_str("ms") + prefix, + "ms", + ) } else if self.nanos >= NANOS_PER_MICRO { fmt_decimal( f, (self.nanos / NANOS_PER_MICRO) as u64, self.nanos % NANOS_PER_MICRO, NANOS_PER_MICRO / 10, - )?; - f.write_str("µs") + prefix, + "µs", + ) } else { - fmt_decimal(f, self.nanos as u64, 0, 1)?; - f.write_str("ns") + fmt_decimal(f, self.nanos as u64, 0, 1, prefix, "ns") } } } diff --git a/library/core/src/unicode/printable.rs b/library/core/src/unicode/printable.rs index 9680aa14d3..1502b3160b 100644 --- a/library/core/src/unicode/printable.rs +++ b/library/core/src/unicode/printable.rs @@ -44,10 +44,10 @@ pub(crate) fn is_printable(x: char) -> bool { } else if x < 0x20000 { check(lower, SINGLETONS1U, SINGLETONS1L, NORMAL1) } else { - if 0x2a6de <= x && x < 0x2a700 { + if 0x2a6e0 <= x && x < 0x2a700 { return false; } - if 0x2b735 <= x && x < 0x2b740 { + if 0x2b739 <= x && x < 0x2b740 { return false; } if 0x2b81e <= x && x < 0x2b820 { @@ -77,13 +77,13 @@ const SINGLETONS0U: &[(u8, u8)] = &[ (0x00, 1), (0x03, 5), (0x05, 6), - (0x06, 3), + (0x06, 2), (0x07, 6), - (0x08, 8), + (0x08, 7), (0x09, 17), (0x0a, 28), (0x0b, 25), - (0x0c, 20), + (0x0c, 26), (0x0d, 16), (0x0e, 13), (0x0f, 4), @@ -91,16 +91,15 @@ const SINGLETONS0U: &[(u8, u8)] = &[ (0x12, 18), (0x13, 9), (0x16, 1), - (0x17, 5), - (0x18, 2), + (0x17, 4), + (0x18, 1), (0x19, 3), (0x1a, 7), + (0x1b, 1), (0x1c, 2), - (0x1d, 1), (0x1f, 22), (0x20, 3), (0x2b, 3), - (0x2c, 2), (0x2d, 11), (0x2e, 1), (0x30, 3), @@ -112,49 +111,48 @@ const SINGLETONS0U: &[(u8, u8)] = &[ (0xab, 8), (0xfa, 2), (0xfb, 5), - (0xfd, 4), + (0xfd, 2), (0xfe, 3), (0xff, 9), ]; #[rustfmt::skip] const SINGLETONS0L: &[u8] = &[ 0xad, 0x78, 0x79, 0x8b, 0x8d, 0xa2, 0x30, 0x57, - 0x58, 0x8b, 0x8c, 0x90, 0x1c, 0x1d, 0xdd, 0x0e, - 0x0f, 0x4b, 0x4c, 0xfb, 0xfc, 0x2e, 0x2f, 0x3f, - 0x5c, 0x5d, 0x5f, 0xb5, 0xe2, 0x84, 0x8d, 0x8e, - 0x91, 0x92, 0xa9, 0xb1, 0xba, 0xbb, 0xc5, 0xc6, - 0xc9, 0xca, 0xde, 0xe4, 0xe5, 0xff, 0x00, 0x04, - 0x11, 0x12, 0x29, 0x31, 0x34, 0x37, 0x3a, 0x3b, - 0x3d, 0x49, 0x4a, 0x5d, 0x84, 0x8e, 0x92, 0xa9, - 0xb1, 0xb4, 0xba, 0xbb, 0xc6, 0xca, 0xce, 0xcf, - 0xe4, 0xe5, 0x00, 0x04, 0x0d, 0x0e, 0x11, 0x12, - 0x29, 0x31, 0x34, 0x3a, 0x3b, 0x45, 0x46, 0x49, - 0x4a, 0x5e, 0x64, 0x65, 0x84, 0x91, 0x9b, 0x9d, - 0xc9, 0xce, 0xcf, 0x0d, 0x11, 0x29, 0x45, 0x49, - 0x57, 0x64, 0x65, 0x8d, 0x91, 0xa9, 0xb4, 0xba, - 0xbb, 0xc5, 0xc9, 0xdf, 0xe4, 0xe5, 0xf0, 0x0d, - 0x11, 0x45, 0x49, 0x64, 0x65, 0x80, 0x84, 0xb2, - 0xbc, 0xbe, 0xbf, 0xd5, 0xd7, 0xf0, 0xf1, 0x83, - 0x85, 0x8b, 0xa4, 0xa6, 0xbe, 0xbf, 0xc5, 0xc7, - 0xce, 0xcf, 0xda, 0xdb, 0x48, 0x98, 0xbd, 0xcd, - 0xc6, 0xce, 0xcf, 0x49, 0x4e, 0x4f, 0x57, 0x59, - 0x5e, 0x5f, 0x89, 0x8e, 0x8f, 0xb1, 0xb6, 0xb7, - 0xbf, 0xc1, 0xc6, 0xc7, 0xd7, 0x11, 0x16, 0x17, - 0x5b, 0x5c, 0xf6, 0xf7, 0xfe, 0xff, 0x80, 0x0d, - 0x6d, 0x71, 0xde, 0xdf, 0x0e, 0x0f, 0x1f, 0x6e, - 0x6f, 0x1c, 0x1d, 0x5f, 0x7d, 0x7e, 0xae, 0xaf, - 0xbb, 0xbc, 0xfa, 0x16, 0x17, 0x1e, 0x1f, 0x46, - 0x47, 0x4e, 0x4f, 0x58, 0x5a, 0x5c, 0x5e, 0x7e, - 0x7f, 0xb5, 0xc5, 0xd4, 0xd5, 0xdc, 0xf0, 0xf1, - 0xf5, 0x72, 0x73, 0x8f, 0x74, 0x75, 0x96, 0x2f, - 0x5f, 0x26, 0x2e, 0x2f, 0xa7, 0xaf, 0xb7, 0xbf, + 0x58, 0x8b, 0x8c, 0x90, 0x1c, 0xdd, 0x0e, 0x0f, + 0x4b, 0x4c, 0xfb, 0xfc, 0x2e, 0x2f, 0x3f, 0x5c, + 0x5d, 0x5f, 0xe2, 0x84, 0x8d, 0x8e, 0x91, 0x92, + 0xa9, 0xb1, 0xba, 0xbb, 0xc5, 0xc6, 0xc9, 0xca, + 0xde, 0xe4, 0xe5, 0xff, 0x00, 0x04, 0x11, 0x12, + 0x29, 0x31, 0x34, 0x37, 0x3a, 0x3b, 0x3d, 0x49, + 0x4a, 0x5d, 0x84, 0x8e, 0x92, 0xa9, 0xb1, 0xb4, + 0xba, 0xbb, 0xc6, 0xca, 0xce, 0xcf, 0xe4, 0xe5, + 0x00, 0x04, 0x0d, 0x0e, 0x11, 0x12, 0x29, 0x31, + 0x34, 0x3a, 0x3b, 0x45, 0x46, 0x49, 0x4a, 0x5e, + 0x64, 0x65, 0x84, 0x91, 0x9b, 0x9d, 0xc9, 0xce, + 0xcf, 0x0d, 0x11, 0x29, 0x3a, 0x3b, 0x45, 0x49, + 0x57, 0x5b, 0x5c, 0x5e, 0x5f, 0x64, 0x65, 0x8d, + 0x91, 0xa9, 0xb4, 0xba, 0xbb, 0xc5, 0xc9, 0xdf, + 0xe4, 0xe5, 0xf0, 0x0d, 0x11, 0x45, 0x49, 0x64, + 0x65, 0x80, 0x84, 0xb2, 0xbc, 0xbe, 0xbf, 0xd5, + 0xd7, 0xf0, 0xf1, 0x83, 0x85, 0x8b, 0xa4, 0xa6, + 0xbe, 0xbf, 0xc5, 0xc7, 0xce, 0xcf, 0xda, 0xdb, + 0x48, 0x98, 0xbd, 0xcd, 0xc6, 0xce, 0xcf, 0x49, + 0x4e, 0x4f, 0x57, 0x59, 0x5e, 0x5f, 0x89, 0x8e, + 0x8f, 0xb1, 0xb6, 0xb7, 0xbf, 0xc1, 0xc6, 0xc7, + 0xd7, 0x11, 0x16, 0x17, 0x5b, 0x5c, 0xf6, 0xf7, + 0xfe, 0xff, 0x80, 0x6d, 0x71, 0xde, 0xdf, 0x0e, + 0x1f, 0x6e, 0x6f, 0x1c, 0x1d, 0x5f, 0x7d, 0x7e, + 0xae, 0xaf, 0x7f, 0xbb, 0xbc, 0x16, 0x17, 0x1e, + 0x1f, 0x46, 0x47, 0x4e, 0x4f, 0x58, 0x5a, 0x5c, + 0x5e, 0x7e, 0x7f, 0xb5, 0xc5, 0xd4, 0xd5, 0xdc, + 0xf0, 0xf1, 0xf5, 0x72, 0x73, 0x8f, 0x74, 0x75, + 0x96, 0x26, 0x2e, 0x2f, 0xa7, 0xaf, 0xb7, 0xbf, 0xc7, 0xcf, 0xd7, 0xdf, 0x9a, 0x40, 0x97, 0x98, - 0x30, 0x8f, 0x1f, 0xc0, 0xc1, 0xce, 0xff, 0x4e, + 0x30, 0x8f, 0x1f, 0xd2, 0xd4, 0xce, 0xff, 0x4e, 0x4f, 0x5a, 0x5b, 0x07, 0x08, 0x0f, 0x10, 0x27, 0x2f, 0xee, 0xef, 0x6e, 0x6f, 0x37, 0x3d, 0x3f, - 0x42, 0x45, 0x90, 0x91, 0xfe, 0xff, 0x53, 0x67, - 0x75, 0xc8, 0xc9, 0xd0, 0xd1, 0xd8, 0xd9, 0xe7, - 0xfe, 0xff, + 0x42, 0x45, 0x90, 0x91, 0x53, 0x67, 0x75, 0xc8, + 0xc9, 0xd0, 0xd1, 0xd8, 0xd9, 0xe7, 0xfe, 0xff, ]; #[rustfmt::skip] const SINGLETONS1U: &[(u8, u8)] = &[ @@ -162,6 +160,8 @@ const SINGLETONS1U: &[(u8, u8)] = &[ (0x01, 1), (0x03, 1), (0x04, 2), + (0x05, 7), + (0x07, 2), (0x08, 8), (0x09, 2), (0x0a, 5), @@ -178,9 +178,11 @@ const SINGLETONS1U: &[(u8, u8)] = &[ (0x1c, 5), (0x1d, 8), (0x24, 1), - (0x6a, 3), + (0x6a, 4), (0x6b, 2), + (0xaf, 3), (0xbc, 2), + (0xcf, 2), (0xd1, 2), (0xd4, 12), (0xd5, 9), @@ -189,38 +191,40 @@ const SINGLETONS1U: &[(u8, u8)] = &[ (0xda, 1), (0xe0, 5), (0xe1, 2), + (0xe7, 4), (0xe8, 2), (0xee, 32), (0xf0, 4), (0xf8, 2), - (0xf9, 2), (0xfa, 2), (0xfb, 1), ]; #[rustfmt::skip] const SINGLETONS1L: &[u8] = &[ 0x0c, 0x27, 0x3b, 0x3e, 0x4e, 0x4f, 0x8f, 0x9e, - 0x9e, 0x9f, 0x06, 0x07, 0x09, 0x36, 0x3d, 0x3e, - 0x56, 0xf3, 0xd0, 0xd1, 0x04, 0x14, 0x18, 0x36, - 0x37, 0x56, 0x57, 0x7f, 0xaa, 0xae, 0xaf, 0xbd, - 0x35, 0xe0, 0x12, 0x87, 0x89, 0x8e, 0x9e, 0x04, - 0x0d, 0x0e, 0x11, 0x12, 0x29, 0x31, 0x34, 0x3a, - 0x45, 0x46, 0x49, 0x4a, 0x4e, 0x4f, 0x64, 0x65, - 0x5c, 0xb6, 0xb7, 0x1b, 0x1c, 0x07, 0x08, 0x0a, - 0x0b, 0x14, 0x17, 0x36, 0x39, 0x3a, 0xa8, 0xa9, - 0xd8, 0xd9, 0x09, 0x37, 0x90, 0x91, 0xa8, 0x07, - 0x0a, 0x3b, 0x3e, 0x66, 0x69, 0x8f, 0x92, 0x6f, - 0x5f, 0xee, 0xef, 0x5a, 0x62, 0x9a, 0x9b, 0x27, - 0x28, 0x55, 0x9d, 0xa0, 0xa1, 0xa3, 0xa4, 0xa7, - 0xa8, 0xad, 0xba, 0xbc, 0xc4, 0x06, 0x0b, 0x0c, - 0x15, 0x1d, 0x3a, 0x3f, 0x45, 0x51, 0xa6, 0xa7, - 0xcc, 0xcd, 0xa0, 0x07, 0x19, 0x1a, 0x22, 0x25, - 0x3e, 0x3f, 0xc5, 0xc6, 0x04, 0x20, 0x23, 0x25, - 0x26, 0x28, 0x33, 0x38, 0x3a, 0x48, 0x4a, 0x4c, - 0x50, 0x53, 0x55, 0x56, 0x58, 0x5a, 0x5c, 0x5e, - 0x60, 0x63, 0x65, 0x66, 0x6b, 0x73, 0x78, 0x7d, - 0x7f, 0x8a, 0xa4, 0xaa, 0xaf, 0xb0, 0xc0, 0xd0, - 0xae, 0xaf, 0x79, 0xcc, 0x6e, 0x6f, 0x93, + 0x9e, 0x9f, 0x7b, 0x8b, 0x93, 0x96, 0xa2, 0xb2, + 0xba, 0x86, 0xb1, 0x06, 0x07, 0x09, 0x36, 0x3d, + 0x3e, 0x56, 0xf3, 0xd0, 0xd1, 0x04, 0x14, 0x18, + 0x36, 0x37, 0x56, 0x57, 0x7f, 0xaa, 0xae, 0xaf, + 0xbd, 0x35, 0xe0, 0x12, 0x87, 0x89, 0x8e, 0x9e, + 0x04, 0x0d, 0x0e, 0x11, 0x12, 0x29, 0x31, 0x34, + 0x3a, 0x45, 0x46, 0x49, 0x4a, 0x4e, 0x4f, 0x64, + 0x65, 0x5c, 0xb6, 0xb7, 0x1b, 0x1c, 0x07, 0x08, + 0x0a, 0x0b, 0x14, 0x17, 0x36, 0x39, 0x3a, 0xa8, + 0xa9, 0xd8, 0xd9, 0x09, 0x37, 0x90, 0x91, 0xa8, + 0x07, 0x0a, 0x3b, 0x3e, 0x66, 0x69, 0x8f, 0x92, + 0x6f, 0x5f, 0xbf, 0xee, 0xef, 0x5a, 0x62, 0xf4, + 0xfc, 0xff, 0x9a, 0x9b, 0x2e, 0x2f, 0x27, 0x28, + 0x55, 0x9d, 0xa0, 0xa1, 0xa3, 0xa4, 0xa7, 0xa8, + 0xad, 0xba, 0xbc, 0xc4, 0x06, 0x0b, 0x0c, 0x15, + 0x1d, 0x3a, 0x3f, 0x45, 0x51, 0xa6, 0xa7, 0xcc, + 0xcd, 0xa0, 0x07, 0x19, 0x1a, 0x22, 0x25, 0x3e, + 0x3f, 0xe7, 0xec, 0xef, 0xff, 0xc5, 0xc6, 0x04, + 0x20, 0x23, 0x25, 0x26, 0x28, 0x33, 0x38, 0x3a, + 0x48, 0x4a, 0x4c, 0x50, 0x53, 0x55, 0x56, 0x58, + 0x5a, 0x5c, 0x5e, 0x60, 0x63, 0x65, 0x66, 0x6b, + 0x73, 0x78, 0x7d, 0x7f, 0x8a, 0xa4, 0xaa, 0xaf, + 0xb0, 0xc0, 0xd0, 0xae, 0xaf, 0x6e, 0x6f, 0x93, ]; #[rustfmt::skip] const NORMAL0: &[u8] = &[ @@ -231,9 +235,9 @@ const NORMAL0: &[u8] = &[ 0x1b, 0x04, 0x06, 0x11, 0x81, 0xac, 0x0e, - 0x80, 0xab, 0x35, - 0x28, 0x0b, - 0x80, 0xe0, 0x03, + 0x80, 0xab, 0x05, + 0x1f, 0x09, + 0x81, 0x1b, 0x03, 0x19, 0x08, 0x01, 0x04, 0x2f, 0x04, @@ -257,13 +261,11 @@ const NORMAL0: &[u8] = &[ 0x0b, 0x06, 0x01, 0x0e, 0x15, 0x05, - 0x3a, 0x03, - 0x11, 0x07, - 0x06, 0x05, - 0x10, 0x07, + 0x4e, 0x07, + 0x1b, 0x07, 0x57, 0x07, - 0x02, 0x07, - 0x15, 0x0d, + 0x02, 0x06, + 0x16, 0x0d, 0x50, 0x04, 0x43, 0x03, 0x2d, 0x03, @@ -280,8 +282,8 @@ const NORMAL0: &[u8] = &[ 0x1a, 0x06, 0x82, 0xfd, 0x03, 0x59, 0x07, - 0x15, 0x0b, - 0x17, 0x09, + 0x16, 0x09, + 0x18, 0x09, 0x14, 0x0c, 0x14, 0x0c, 0x6a, 0x06, @@ -299,10 +301,9 @@ const NORMAL0: &[u8] = &[ 0x0b, 0x03, 0x80, 0xac, 0x06, 0x0a, 0x06, - 0x21, 0x3f, - 0x4c, 0x04, - 0x2d, 0x03, - 0x74, 0x08, + 0x2f, 0x31, + 0x4d, 0x03, + 0x80, 0xa4, 0x08, 0x3c, 0x03, 0x0f, 0x03, 0x3c, 0x07, @@ -312,7 +313,7 @@ const NORMAL0: &[u8] = &[ 0x18, 0x08, 0x2f, 0x11, 0x2d, 0x03, - 0x20, 0x10, + 0x21, 0x0f, 0x21, 0x0f, 0x80, 0x8c, 0x04, 0x82, 0x97, 0x19, @@ -322,19 +323,19 @@ const NORMAL0: &[u8] = &[ 0x3b, 0x07, 0x02, 0x0e, 0x18, 0x09, - 0x80, 0xb3, 0x2d, + 0x80, 0xbe, 0x22, 0x74, 0x0c, 0x80, 0xd6, 0x1a, 0x0c, 0x05, 0x80, 0xff, 0x05, 0x80, 0xdf, 0x0c, - 0xee, 0x0d, 0x03, - 0x84, 0x8d, 0x03, + 0xf2, 0x9d, 0x03, 0x37, 0x09, 0x81, 0x5c, 0x14, 0x80, 0xb8, 0x08, - 0x80, 0xcb, 0x2a, - 0x38, 0x03, + 0x80, 0xcb, 0x05, + 0x0a, 0x18, + 0x3b, 0x03, 0x0a, 0x06, 0x38, 0x08, 0x46, 0x08, @@ -354,9 +355,9 @@ const NORMAL0: &[u8] = &[ 0x81, 0xda, 0x26, 0x07, 0x0c, 0x05, 0x05, - 0x80, 0xa5, 0x11, - 0x81, 0x6d, 0x10, - 0x78, 0x28, + 0x80, 0xa6, 0x10, + 0x81, 0xf5, 0x07, + 0x01, 0x20, 0x2a, 0x06, 0x4c, 0x04, 0x80, 0x8d, 0x04, @@ -386,10 +387,11 @@ const NORMAL1: &[u8] = &[ 0x24, 0x04, 0x28, 0x08, 0x34, 0x0b, - 0x01, 0x80, 0x90, + 0x4e, 0x43, 0x81, 0x37, 0x09, 0x16, 0x0a, - 0x08, 0x80, 0x98, + 0x08, 0x18, + 0x3b, 0x45, 0x39, 0x03, 0x63, 0x08, 0x09, 0x30, @@ -417,12 +419,13 @@ const NORMAL1: &[u8] = &[ 0x0a, 0x81, 0x26, 0x52, 0x4e, 0x28, 0x08, - 0x2a, 0x56, + 0x2a, 0x16, + 0x1a, 0x26, 0x1c, 0x14, 0x17, 0x09, 0x4e, 0x04, - 0x1e, 0x0f, - 0x43, 0x0e, + 0x24, 0x09, + 0x44, 0x0d, 0x19, 0x07, 0x0a, 0x06, 0x48, 0x08, @@ -443,18 +446,18 @@ const NORMAL1: &[u8] = &[ 0x45, 0x0b, 0x0a, 0x06, 0x0d, 0x13, - 0x39, 0x07, + 0x3a, 0x06, 0x0a, 0x36, 0x2c, 0x04, - 0x10, 0x80, 0xc0, + 0x17, 0x80, 0xb9, 0x3c, 0x64, 0x53, 0x0c, 0x48, 0x09, 0x0a, 0x46, 0x45, 0x1b, 0x48, 0x08, - 0x53, 0x1d, - 0x39, 0x81, 0x07, + 0x53, 0x0d, + 0x49, 0x81, 0x07, 0x46, 0x0a, 0x1d, 0x03, 0x47, 0x49, @@ -468,12 +471,13 @@ const NORMAL1: &[u8] = &[ 0x32, 0x0d, 0x83, 0x9b, 0x66, 0x75, 0x0b, - 0x80, 0xc4, 0x8a, 0xbc, + 0x80, 0xc4, 0x8a, 0x4c, + 0x63, 0x0d, 0x84, 0x2f, 0x8f, 0xd1, 0x82, 0x47, 0xa1, 0xb9, 0x82, 0x39, 0x07, 0x2a, 0x04, - 0x02, 0x60, + 0x5c, 0x06, 0x26, 0x0a, 0x46, 0x0a, 0x28, 0x05, @@ -486,32 +490,36 @@ const NORMAL1: &[u8] = &[ 0x02, 0x0e, 0x97, 0xf8, 0x08, 0x84, 0xd6, 0x2a, - 0x09, 0xa2, 0xf7, - 0x81, 0x1f, 0x31, + 0x09, 0xa2, 0xe7, + 0x81, 0x33, 0x2d, 0x03, 0x11, 0x04, 0x08, 0x81, 0x8c, 0x89, 0x04, 0x6b, 0x05, 0x0d, 0x03, 0x09, 0x07, - 0x10, 0x93, 0x60, + 0x10, 0x92, 0x60, + 0x47, 0x09, + 0x74, 0x3c, 0x80, 0xf6, 0x0a, 0x73, 0x08, - 0x6e, 0x17, + 0x70, 0x15, 0x46, 0x80, 0x9a, 0x14, 0x0c, 0x57, 0x09, 0x19, 0x80, 0x87, 0x81, 0x47, 0x03, 0x85, 0x42, 0x0f, - 0x15, 0x85, 0x50, + 0x15, 0x84, 0x50, + 0x1f, 0x80, 0xe1, 0x2b, 0x80, 0xd5, 0x2d, 0x03, 0x1a, 0x04, - 0x02, 0x81, 0x70, + 0x02, 0x81, 0x40, + 0x1f, 0x11, 0x3a, 0x05, - 0x01, 0x85, 0x00, - 0x80, 0xd7, 0x29, + 0x01, 0x84, 0xe0, + 0x80, 0xf7, 0x29, 0x4c, 0x04, 0x0a, 0x04, 0x02, 0x83, 0x11, @@ -531,12 +539,13 @@ const NORMAL1: &[u8] = &[ 0x09, 0x07, 0x02, 0x0e, 0x06, 0x80, 0x9a, - 0x83, 0xd8, 0x08, - 0x0d, 0x03, + 0x83, 0xd8, 0x05, + 0x10, 0x03, 0x0d, 0x03, 0x74, 0x0c, 0x59, 0x07, - 0x0c, 0x14, + 0x0c, 0x04, + 0x01, 0x0f, 0x0c, 0x04, 0x38, 0x08, 0x0a, 0x06, @@ -544,12 +553,14 @@ const NORMAL1: &[u8] = &[ 0x22, 0x4e, 0x81, 0x54, 0x0c, 0x15, 0x03, - 0x03, 0x05, + 0x05, 0x03, 0x07, 0x09, - 0x19, 0x07, + 0x1d, 0x03, + 0x0b, 0x05, + 0x06, 0x0a, + 0x0a, 0x06, + 0x08, 0x08, 0x07, 0x09, - 0x03, 0x0d, - 0x07, 0x29, 0x80, 0xcb, 0x25, 0x0a, 0x84, 0x06, ]; diff --git a/library/core/src/unicode/unicode_data.rs b/library/core/src/unicode/unicode_data.rs index 16803bf2e8..d2073f86c0 100644 --- a/library/core/src/unicode/unicode_data.rs +++ b/library/core/src/unicode/unicode_data.rs @@ -94,72 +94,74 @@ fn skip_search( offset_idx % 2 == 1 } -pub const UNICODE_VERSION: (u8, u8, u8) = (13, 0, 0); +pub const UNICODE_VERSION: (u8, u8, u8) = (14, 0, 0); #[rustfmt::skip] pub mod alphabetic { - static SHORT_OFFSET_RUNS: [u32; 52] = [ - 706, 33559113, 868226669, 947920662, 1157637302, 1306536960, 1310732293, 1398813696, - 1449151936, 1451270141, 1455465613, 1459660301, 1468061604, 1648425216, 1658911342, - 1661009214, 1707147904, 1793132343, 1853951616, 1994464256, 2330009312, 2418090906, - 2428579840, 2439066671, 2441167872, 2443265607, 2445371392, 2447469113, 2449567296, - 2476836856, 2508295382, 2512498688, 2518790431, 2520888060, 2533473280, 2535576576, - 2556548774, 2634145792, 2682380992, 2715936768, 2720132608, 2736910640, 2875326464, - 2887952094, 2890053429, 2894253730, 2902649825, 2906847232, 2908944926, 2911043584, - 2913145675, 2916356939, + static SHORT_OFFSET_RUNS: [u32; 51] = [ + 706, 33559113, 876615277, 956309270, 1166025910, 1314925568, 1319120901, 1398813696, + 1449151936, 1451271309, 1455465997, 1463867300, 1652619520, 1663105646, 1665203518, + 1711342208, 1797326647, 1891700352, 2044795904, 2397118176, 2485199770, 2495688592, + 2506175535, 2512471040, 2514568775, 2516674560, 2518772281, 2520870464, 2552334328, + 2583792854, 2587996144, 2594287907, 2608968444, 2621553664, 2623656960, 2644629158, + 2722225920, 2770461328, 2808211424, 2816601600, 2850156848, 2988572672, 3001198304, + 3003299641, 3007499938, 3015896033, 3020093440, 3022191134, 3024289792, 3026391883, + 3029603147, ]; - static OFFSETS: [u8; 1391] = [ + static OFFSETS: [u8; 1445] = [ 65, 26, 6, 26, 47, 1, 10, 1, 4, 1, 5, 23, 1, 31, 1, 0, 4, 12, 14, 5, 7, 1, 1, 1, 86, 1, 42, 5, 1, 2, 2, 4, 1, 1, 6, 1, 1, 3, 1, 1, 1, 20, 1, 83, 1, 139, 8, 166, 1, 38, 2, 1, 6, 41, 39, 14, 1, 1, 1, 2, 1, 2, 1, 1, 8, 27, 4, 4, 29, 11, 5, 56, 1, 7, 14, 102, 1, 8, 4, 8, 4, 3, 10, - 3, 2, 1, 16, 48, 13, 101, 24, 33, 9, 2, 4, 1, 5, 24, 2, 19, 19, 25, 7, 11, 53, 21, 1, 18, - 12, 12, 3, 7, 6, 76, 1, 16, 1, 3, 4, 15, 13, 19, 1, 8, 2, 2, 2, 22, 1, 7, 1, 1, 3, 4, 3, 8, - 2, 2, 2, 2, 1, 1, 8, 1, 4, 2, 1, 5, 12, 2, 10, 1, 4, 3, 1, 6, 4, 2, 2, 22, 1, 7, 1, 2, 1, 2, - 1, 2, 4, 5, 4, 2, 2, 2, 4, 1, 7, 4, 1, 1, 17, 6, 11, 3, 1, 9, 1, 3, 1, 22, 1, 7, 1, 2, 1, 5, - 3, 9, 1, 3, 1, 2, 3, 1, 15, 4, 21, 4, 4, 3, 1, 8, 2, 2, 2, 22, 1, 7, 1, 2, 1, 5, 3, 8, 2, 2, - 2, 2, 9, 2, 4, 2, 1, 5, 13, 1, 16, 2, 1, 6, 3, 3, 1, 4, 3, 2, 1, 1, 1, 2, 3, 2, 3, 3, 3, 12, - 4, 5, 3, 3, 1, 3, 3, 1, 6, 1, 40, 4, 1, 8, 1, 3, 1, 23, 1, 16, 3, 8, 1, 3, 1, 3, 8, 2, 1, 3, - 5, 4, 28, 4, 1, 8, 1, 3, 1, 23, 1, 10, 1, 5, 3, 8, 1, 3, 1, 3, 8, 2, 7, 1, 1, 4, 13, 2, 13, - 13, 1, 3, 1, 41, 2, 8, 1, 3, 1, 3, 1, 1, 5, 4, 7, 5, 22, 6, 1, 3, 1, 18, 3, 24, 1, 9, 1, 1, - 2, 7, 8, 6, 1, 1, 1, 8, 18, 2, 13, 58, 5, 7, 6, 1, 51, 2, 1, 1, 1, 5, 1, 24, 1, 1, 1, 19, 1, - 3, 2, 5, 1, 1, 6, 1, 14, 4, 32, 1, 63, 8, 1, 36, 4, 17, 6, 16, 1, 36, 67, 55, 1, 1, 2, 5, - 16, 64, 10, 4, 2, 38, 1, 1, 5, 1, 2, 43, 1, 0, 1, 4, 2, 7, 1, 1, 1, 4, 2, 41, 1, 4, 2, 33, - 1, 4, 2, 7, 1, 1, 1, 4, 2, 15, 1, 57, 1, 4, 2, 67, 37, 16, 16, 86, 2, 6, 3, 0, 2, 17, 1, 26, - 5, 75, 3, 11, 7, 13, 1, 6, 12, 20, 12, 20, 12, 13, 1, 3, 1, 2, 12, 52, 2, 19, 14, 1, 4, 1, - 67, 89, 7, 43, 5, 70, 10, 31, 1, 12, 4, 9, 23, 30, 2, 5, 11, 44, 4, 26, 54, 28, 4, 63, 2, - 20, 50, 1, 23, 2, 63, 52, 1, 15, 1, 7, 52, 42, 2, 4, 10, 44, 1, 11, 14, 55, 22, 3, 10, 36, - 2, 9, 7, 43, 2, 3, 41, 4, 1, 6, 1, 2, 3, 1, 5, 192, 39, 14, 11, 0, 2, 6, 2, 38, 2, 6, 2, 8, - 1, 1, 1, 1, 1, 1, 1, 31, 2, 53, 1, 7, 1, 1, 3, 3, 1, 7, 3, 4, 2, 6, 4, 13, 5, 3, 1, 7, 116, - 1, 13, 1, 16, 13, 101, 1, 4, 1, 2, 10, 1, 1, 3, 5, 6, 1, 1, 1, 1, 1, 1, 4, 1, 11, 2, 4, 5, - 5, 4, 1, 17, 41, 0, 52, 0, 47, 1, 47, 1, 133, 6, 4, 3, 2, 12, 38, 1, 1, 5, 1, 2, 56, 7, 1, - 16, 23, 9, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 32, 47, 1, 0, 3, 25, 9, 7, 5, 2, - 5, 4, 86, 6, 3, 1, 90, 1, 4, 5, 43, 1, 94, 17, 32, 48, 16, 0, 0, 64, 0, 3, 0, 67, 46, 2, 0, - 3, 16, 10, 2, 20, 47, 5, 8, 3, 113, 39, 9, 2, 103, 2, 53, 2, 9, 42, 17, 1, 33, 24, 52, 12, + 3, 2, 1, 16, 48, 13, 101, 24, 33, 9, 2, 4, 1, 5, 24, 2, 19, 19, 25, 7, 11, 5, 24, 1, 6, 17, + 42, 10, 12, 3, 7, 6, 76, 1, 16, 1, 3, 4, 15, 13, 19, 1, 8, 2, 2, 2, 22, 1, 7, 1, 1, 3, 4, 3, + 8, 2, 2, 2, 2, 1, 1, 8, 1, 4, 2, 1, 5, 12, 2, 10, 1, 4, 3, 1, 6, 4, 2, 2, 22, 1, 7, 1, 2, 1, + 2, 1, 2, 4, 5, 4, 2, 2, 2, 4, 1, 7, 4, 1, 1, 17, 6, 11, 3, 1, 9, 1, 3, 1, 22, 1, 7, 1, 2, 1, + 5, 3, 9, 1, 3, 1, 2, 3, 1, 15, 4, 21, 4, 4, 3, 1, 8, 2, 2, 2, 22, 1, 7, 1, 2, 1, 5, 3, 8, 2, + 2, 2, 2, 9, 2, 4, 2, 1, 5, 13, 1, 16, 2, 1, 6, 3, 3, 1, 4, 3, 2, 1, 1, 1, 2, 3, 2, 3, 3, 3, + 12, 4, 5, 3, 3, 1, 3, 3, 1, 6, 1, 40, 4, 1, 8, 1, 3, 1, 23, 1, 16, 3, 8, 1, 3, 1, 3, 8, 2, + 1, 3, 2, 1, 2, 4, 28, 4, 1, 8, 1, 3, 1, 23, 1, 10, 1, 5, 3, 8, 1, 3, 1, 3, 8, 2, 6, 2, 1, 4, + 13, 2, 13, 13, 1, 3, 1, 41, 2, 8, 1, 3, 1, 3, 1, 1, 5, 4, 7, 5, 22, 6, 1, 3, 1, 18, 3, 24, + 1, 9, 1, 1, 2, 7, 8, 6, 1, 1, 1, 8, 18, 2, 13, 58, 5, 7, 6, 1, 51, 2, 1, 1, 1, 5, 1, 24, 1, + 1, 1, 19, 1, 3, 2, 5, 1, 1, 6, 1, 14, 4, 32, 1, 63, 8, 1, 36, 4, 17, 6, 16, 1, 36, 67, 55, + 1, 1, 2, 5, 16, 64, 10, 4, 2, 38, 1, 1, 5, 1, 2, 43, 1, 0, 1, 4, 2, 7, 1, 1, 1, 4, 2, 41, 1, + 4, 2, 33, 1, 4, 2, 7, 1, 1, 1, 4, 2, 15, 1, 57, 1, 4, 2, 67, 37, 16, 16, 86, 2, 6, 3, 0, 2, + 17, 1, 26, 5, 75, 3, 11, 7, 20, 11, 21, 12, 20, 12, 13, 1, 3, 1, 2, 12, 52, 2, 19, 14, 1, 4, + 1, 67, 89, 7, 43, 5, 70, 10, 31, 1, 12, 4, 9, 23, 30, 2, 5, 11, 44, 4, 26, 54, 28, 4, 63, 2, + 20, 50, 1, 23, 2, 11, 3, 49, 52, 1, 15, 1, 8, 51, 42, 2, 4, 10, 44, 1, 11, 14, 55, 22, 3, + 10, 36, 2, 9, 7, 43, 2, 3, 41, 4, 1, 6, 1, 2, 3, 1, 5, 192, 39, 14, 11, 0, 2, 6, 2, 38, 2, + 6, 2, 8, 1, 1, 1, 1, 1, 1, 1, 31, 2, 53, 1, 7, 1, 1, 3, 3, 1, 7, 3, 4, 2, 6, 4, 13, 5, 3, 1, + 7, 116, 1, 13, 1, 16, 13, 101, 1, 4, 1, 2, 10, 1, 1, 3, 5, 6, 1, 1, 1, 1, 1, 1, 4, 1, 11, 2, + 4, 5, 5, 4, 1, 17, 41, 0, 52, 0, 229, 6, 4, 3, 2, 12, 38, 1, 1, 5, 1, 2, 56, 7, 1, 16, 23, + 9, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 32, 47, 1, 0, 3, 25, 9, 7, 5, 2, 5, 4, + 86, 6, 3, 1, 90, 1, 4, 5, 43, 1, 94, 17, 32, 48, 16, 0, 0, 64, 0, 67, 46, 2, 0, 3, 16, 10, + 2, 20, 47, 5, 8, 3, 113, 39, 9, 2, 103, 2, 64, 5, 2, 1, 1, 1, 5, 24, 20, 1, 33, 24, 52, 12, 68, 1, 1, 44, 6, 3, 1, 1, 3, 10, 33, 5, 35, 13, 29, 3, 51, 1, 12, 15, 1, 16, 16, 10, 5, 1, 55, 9, 14, 18, 23, 3, 69, 1, 1, 1, 1, 24, 3, 2, 16, 2, 4, 11, 6, 2, 6, 2, 6, 9, 7, 1, 7, 1, 43, 1, 14, 6, 123, 21, 0, 12, 23, 4, 49, 0, 0, 2, 106, 38, 7, 12, 5, 5, 12, 1, 13, 1, 5, 1, 1, 1, 2, 1, 2, 1, 108, 33, 0, 18, 64, 2, 54, 40, 12, 116, 5, 1, 135, 36, 26, 6, 26, 11, 89, 3, 6, 2, 6, 2, 6, 2, 3, 35, 12, 1, 26, 1, 19, 1, 2, 1, 15, 2, 14, 34, 123, 69, 53, 0, 29, 3, 49, 47, 32, 13, 30, 5, 43, 5, 30, 2, 36, 4, 8, 1, 5, 42, 158, 18, 36, 4, 36, 4, 40, 8, 52, - 156, 0, 9, 22, 10, 8, 152, 6, 2, 1, 1, 44, 1, 2, 3, 1, 2, 23, 10, 23, 9, 31, 65, 19, 1, 2, - 10, 22, 10, 26, 70, 56, 6, 2, 64, 4, 1, 2, 5, 8, 1, 3, 1, 29, 42, 29, 3, 29, 35, 8, 1, 28, - 27, 54, 10, 22, 10, 19, 13, 18, 110, 73, 55, 51, 13, 51, 13, 40, 0, 42, 1, 2, 3, 2, 78, 29, - 10, 1, 8, 22, 106, 21, 27, 23, 9, 70, 60, 55, 23, 25, 23, 51, 17, 4, 8, 35, 3, 1, 9, 64, 1, - 4, 9, 2, 10, 1, 1, 1, 35, 18, 1, 34, 2, 1, 6, 1, 65, 7, 1, 1, 1, 4, 1, 15, 1, 10, 7, 57, 23, - 4, 1, 8, 2, 2, 2, 22, 1, 7, 1, 2, 1, 5, 3, 8, 2, 2, 2, 2, 3, 1, 6, 1, 5, 7, 156, 66, 1, 3, - 1, 4, 20, 3, 30, 66, 2, 2, 1, 1, 184, 54, 2, 7, 25, 6, 34, 63, 1, 1, 3, 1, 59, 54, 2, 1, 71, - 27, 2, 14, 213, 57, 103, 64, 31, 8, 2, 1, 2, 8, 1, 2, 1, 30, 1, 2, 2, 2, 2, 4, 93, 8, 2, 46, - 2, 6, 1, 1, 1, 2, 27, 51, 2, 10, 17, 72, 5, 1, 34, 57, 0, 9, 1, 45, 1, 7, 1, 1, 49, 30, 2, - 22, 1, 14, 73, 7, 1, 2, 1, 44, 3, 1, 1, 2, 1, 3, 1, 1, 2, 2, 24, 6, 1, 2, 1, 37, 1, 2, 1, 4, - 1, 1, 0, 23, 185, 1, 79, 0, 102, 111, 17, 196, 0, 0, 0, 0, 0, 0, 7, 31, 113, 30, 18, 48, 16, - 4, 31, 21, 5, 19, 0, 64, 128, 75, 4, 57, 7, 17, 64, 2, 1, 1, 12, 2, 14, 0, 8, 0, 42, 9, 0, - 0, 49, 3, 17, 4, 8, 0, 0, 107, 5, 13, 3, 9, 7, 10, 4, 1, 0, 85, 1, 71, 1, 2, 2, 1, 2, 2, 2, - 4, 1, 12, 1, 1, 1, 7, 1, 65, 1, 4, 2, 8, 1, 7, 1, 28, 1, 4, 1, 5, 1, 1, 3, 7, 1, 0, 2, 25, - 1, 25, 1, 31, 1, 25, 1, 31, 1, 25, 1, 31, 1, 25, 1, 31, 1, 25, 1, 8, 0, 7, 1, 17, 2, 7, 1, - 2, 1, 5, 213, 45, 10, 7, 16, 1, 0, 44, 0, 197, 59, 68, 3, 1, 3, 1, 0, 4, 1, 27, 1, 2, 1, 1, - 2, 1, 1, 10, 1, 4, 1, 1, 1, 1, 6, 1, 4, 1, 1, 1, 1, 1, 1, 3, 1, 2, 1, 1, 2, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 2, 1, 1, 2, 4, 1, 7, 1, 4, 1, 4, 1, 1, 1, 10, 1, 17, 5, 3, 1, 5, 1, 17, 0, - 26, 6, 26, 6, 26, 0, 0, 34, 0, 11, 222, 2, 0, 14, 0, 0, 0, 0, 0, 0, + 12, 11, 1, 15, 1, 7, 1, 2, 1, 11, 1, 15, 1, 7, 1, 2, 67, 0, 9, 22, 10, 8, 24, 6, 1, 42, 1, + 9, 69, 6, 2, 1, 1, 44, 1, 2, 3, 1, 2, 23, 10, 23, 9, 31, 65, 19, 1, 2, 10, 22, 10, 26, 70, + 56, 6, 2, 64, 4, 1, 2, 5, 8, 1, 3, 1, 29, 42, 29, 3, 29, 35, 8, 1, 28, 27, 54, 10, 22, 10, + 19, 13, 18, 110, 73, 55, 51, 13, 51, 13, 40, 0, 42, 1, 2, 3, 2, 78, 29, 10, 1, 8, 22, 42, + 18, 46, 21, 27, 23, 9, 70, 43, 5, 12, 55, 9, 1, 13, 25, 23, 51, 17, 4, 8, 35, 3, 1, 9, 64, + 1, 4, 9, 2, 10, 1, 1, 1, 35, 18, 1, 34, 2, 1, 6, 1, 65, 7, 1, 1, 1, 4, 1, 15, 1, 10, 7, 57, + 23, 4, 1, 8, 2, 2, 2, 22, 1, 7, 1, 2, 1, 5, 3, 8, 2, 2, 2, 2, 3, 1, 6, 1, 5, 7, 156, 66, 1, + 3, 1, 4, 20, 3, 30, 66, 2, 2, 1, 1, 184, 54, 2, 7, 25, 6, 34, 63, 1, 1, 3, 1, 59, 54, 2, 1, + 71, 27, 2, 14, 21, 7, 185, 57, 103, 64, 31, 8, 2, 1, 2, 8, 1, 2, 1, 30, 1, 2, 2, 2, 2, 4, + 93, 8, 2, 46, 2, 6, 1, 1, 1, 2, 27, 51, 2, 10, 17, 72, 5, 1, 18, 73, 0, 9, 1, 45, 1, 7, 1, + 1, 49, 30, 2, 22, 1, 14, 73, 7, 1, 2, 1, 44, 3, 1, 1, 2, 1, 3, 1, 1, 2, 2, 24, 6, 1, 2, 1, + 37, 1, 2, 1, 4, 1, 1, 0, 23, 185, 1, 79, 0, 102, 111, 17, 196, 0, 97, 15, 0, 0, 0, 0, 0, 7, + 31, 17, 79, 17, 30, 18, 48, 16, 4, 31, 21, 5, 19, 0, 64, 128, 75, 4, 57, 7, 17, 64, 2, 1, 1, + 12, 2, 14, 0, 8, 0, 42, 9, 0, 4, 1, 7, 1, 2, 1, 0, 45, 3, 17, 4, 8, 0, 0, 107, 5, 13, 3, 9, + 7, 10, 4, 1, 0, 85, 1, 71, 1, 2, 2, 1, 2, 2, 2, 4, 1, 12, 1, 1, 1, 7, 1, 65, 1, 4, 2, 8, 1, + 7, 1, 28, 1, 4, 1, 5, 1, 1, 3, 7, 1, 0, 2, 25, 1, 25, 1, 31, 1, 25, 1, 31, 1, 25, 1, 31, 1, + 25, 1, 31, 1, 25, 1, 8, 0, 31, 225, 7, 1, 17, 2, 7, 1, 2, 1, 5, 213, 45, 10, 7, 16, 1, 0, + 30, 18, 44, 0, 7, 1, 4, 1, 2, 1, 15, 1, 197, 59, 68, 3, 1, 3, 1, 0, 4, 1, 27, 1, 2, 1, 1, 2, + 1, 1, 10, 1, 4, 1, 1, 1, 1, 6, 1, 4, 1, 1, 1, 1, 1, 1, 3, 1, 2, 1, 1, 2, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 2, 1, 1, 2, 4, 1, 7, 1, 4, 1, 4, 1, 1, 1, 10, 1, 17, 5, 3, 1, 5, 1, 17, 0, 26, + 6, 26, 6, 26, 0, 0, 32, 0, 7, 222, 2, 0, 14, 0, 0, 0, 0, 0, 0, ]; pub fn lookup(c: char) -> bool { super::skip_search( @@ -172,44 +174,45 @@ pub mod alphabetic { #[rustfmt::skip] pub mod case_ignorable { - static SHORT_OFFSET_RUNS: [u32; 32] = [ - 688, 44045149, 555751186, 559947709, 794831996, 866136069, 891330581, 916497656, 920692236, - 924908318, 1122041344, 1130430973, 1193347585, 1205931300, 1231097515, 1235294255, - 1445009723, 1453399088, 1512120051, 1575040048, 1579248368, 1583443791, 1596046493, - 1612829031, 1621219840, 1642192896, 1667359024, 1688330988, 1692526800, 1696723963, - 1705902081, 1711210992, + static SHORT_OFFSET_RUNS: [u32; 35] = [ + 688, 44045149, 572528402, 576724925, 807414908, 878718981, 903913493, 929080568, 933275148, + 937491230, 1138818560, 1147208189, 1210124160, 1222707713, 1235291428, 1260457643, + 1264654383, 1491147067, 1499536432, 1558257395, 1621177392, 1625385712, 1629581135, + 1642180592, 1658961053, 1671548672, 1679937895, 1688328704, 1709301760, 1734467888, + 1755439790, 1759635664, 1768027131, 1777205249, 1782514160, ]; - static OFFSETS: [u8; 821] = [ + static OFFSETS: [u8; 855] = [ 39, 1, 6, 1, 11, 1, 35, 1, 1, 1, 71, 1, 4, 1, 1, 1, 4, 1, 2, 2, 0, 192, 4, 2, 4, 1, 9, 2, 1, 1, 251, 7, 207, 1, 5, 1, 49, 45, 1, 1, 1, 2, 1, 2, 1, 1, 44, 1, 11, 6, 10, 11, 1, 1, 35, 1, 10, 21, 16, 1, 101, 8, 1, 10, 1, 4, 33, 1, 1, 1, 30, 27, 91, 11, 58, 11, 4, 1, 2, 1, 24, - 24, 43, 3, 119, 48, 55, 1, 1, 1, 4, 8, 4, 1, 3, 7, 10, 2, 13, 1, 15, 1, 58, 1, 4, 4, 8, 1, - 20, 2, 26, 1, 2, 2, 57, 1, 4, 2, 4, 2, 2, 3, 3, 1, 30, 2, 3, 1, 11, 2, 57, 1, 4, 5, 1, 2, 4, - 1, 20, 2, 22, 6, 1, 1, 58, 1, 2, 1, 1, 4, 8, 1, 7, 2, 11, 2, 30, 1, 61, 1, 12, 1, 50, 1, 3, - 1, 57, 3, 5, 3, 1, 4, 7, 2, 11, 2, 29, 1, 58, 1, 2, 1, 6, 1, 5, 2, 20, 2, 28, 2, 57, 2, 4, - 4, 8, 1, 20, 2, 29, 1, 72, 1, 7, 3, 1, 1, 90, 1, 2, 7, 11, 9, 98, 1, 2, 9, 9, 1, 1, 6, 74, - 2, 27, 1, 1, 1, 1, 1, 55, 14, 1, 5, 1, 2, 5, 11, 1, 36, 9, 1, 102, 4, 1, 6, 1, 2, 2, 2, 25, - 2, 4, 3, 16, 4, 13, 1, 2, 2, 6, 1, 15, 1, 94, 1, 0, 3, 0, 3, 29, 3, 29, 2, 30, 2, 64, 2, 1, - 7, 8, 1, 2, 11, 3, 1, 5, 1, 45, 4, 52, 1, 65, 2, 34, 1, 118, 3, 4, 2, 9, 1, 6, 3, 219, 2, 2, - 1, 58, 1, 1, 7, 1, 1, 1, 1, 2, 8, 6, 10, 2, 1, 39, 1, 8, 17, 63, 4, 48, 1, 1, 5, 1, 1, 5, 1, - 40, 9, 12, 2, 32, 4, 2, 2, 1, 3, 56, 1, 1, 2, 3, 1, 1, 3, 58, 8, 2, 2, 64, 6, 82, 3, 1, 13, - 1, 7, 4, 1, 6, 1, 3, 2, 50, 63, 13, 1, 34, 95, 1, 5, 0, 1, 1, 3, 11, 3, 13, 3, 13, 3, 13, 2, - 12, 5, 8, 2, 10, 1, 2, 1, 2, 5, 49, 5, 1, 10, 1, 1, 13, 1, 16, 13, 51, 33, 0, 2, 113, 3, - 125, 1, 15, 1, 96, 32, 47, 1, 0, 1, 36, 4, 3, 5, 5, 1, 93, 6, 93, 3, 0, 1, 0, 6, 0, 1, 98, - 4, 1, 10, 1, 1, 28, 4, 80, 2, 14, 34, 78, 1, 23, 3, 109, 2, 8, 1, 3, 1, 4, 1, 25, 2, 5, 1, - 151, 2, 26, 18, 13, 1, 38, 8, 25, 11, 46, 3, 48, 1, 2, 4, 2, 2, 17, 1, 21, 2, 66, 6, 2, 2, - 2, 2, 12, 1, 8, 1, 35, 1, 11, 1, 51, 1, 1, 3, 2, 2, 5, 2, 1, 1, 27, 1, 14, 2, 5, 2, 1, 1, - 100, 5, 9, 3, 121, 1, 2, 1, 4, 1, 0, 1, 147, 16, 0, 16, 3, 1, 12, 16, 34, 1, 2, 1, 169, 1, - 7, 1, 6, 1, 11, 1, 35, 1, 1, 1, 47, 1, 45, 2, 67, 1, 21, 3, 0, 1, 226, 1, 149, 5, 0, 3, 1, - 2, 5, 4, 40, 3, 4, 1, 165, 2, 0, 4, 0, 2, 153, 11, 176, 1, 54, 15, 56, 3, 49, 4, 2, 2, 2, 1, - 15, 1, 50, 3, 36, 5, 1, 8, 62, 1, 12, 2, 52, 9, 10, 4, 2, 1, 95, 3, 2, 1, 1, 2, 6, 1, 160, - 1, 3, 8, 21, 2, 57, 2, 3, 1, 37, 7, 3, 5, 195, 8, 2, 3, 1, 1, 23, 1, 84, 6, 1, 1, 4, 2, 1, - 2, 238, 4, 6, 2, 1, 2, 27, 2, 85, 8, 2, 1, 1, 2, 106, 1, 1, 1, 2, 6, 1, 1, 101, 3, 2, 4, 1, - 5, 0, 9, 1, 2, 0, 2, 1, 1, 4, 1, 144, 4, 2, 2, 4, 1, 32, 10, 40, 6, 2, 4, 8, 1, 9, 6, 2, 3, - 46, 13, 1, 2, 0, 7, 1, 6, 1, 1, 82, 22, 2, 7, 1, 2, 1, 2, 122, 6, 3, 1, 1, 2, 1, 7, 1, 1, - 72, 2, 3, 1, 1, 1, 0, 2, 0, 9, 0, 5, 59, 7, 9, 4, 0, 1, 63, 17, 64, 2, 1, 2, 0, 2, 1, 4, 0, - 3, 9, 16, 2, 7, 30, 4, 148, 3, 0, 55, 4, 50, 8, 1, 14, 1, 22, 5, 1, 15, 0, 7, 1, 17, 2, 7, - 1, 2, 1, 5, 0, 14, 0, 4, 0, 7, 109, 8, 0, 5, 0, 1, 30, 96, 128, 240, 0, + 24, 43, 3, 44, 1, 7, 2, 6, 8, 41, 58, 55, 1, 1, 1, 4, 8, 4, 1, 3, 7, 10, 2, 13, 1, 15, 1, + 58, 1, 4, 4, 8, 1, 20, 2, 26, 1, 2, 2, 57, 1, 4, 2, 4, 2, 2, 3, 3, 1, 30, 2, 3, 1, 11, 2, + 57, 1, 4, 5, 1, 2, 4, 1, 20, 2, 22, 6, 1, 1, 58, 1, 2, 1, 1, 4, 8, 1, 7, 2, 11, 2, 30, 1, + 61, 1, 12, 1, 50, 1, 3, 1, 55, 1, 1, 3, 5, 3, 1, 4, 7, 2, 11, 2, 29, 1, 58, 1, 2, 1, 6, 1, + 5, 2, 20, 2, 28, 2, 57, 2, 4, 4, 8, 1, 20, 2, 29, 1, 72, 1, 7, 3, 1, 1, 90, 1, 2, 7, 11, 9, + 98, 1, 2, 9, 9, 1, 1, 6, 74, 2, 27, 1, 1, 1, 1, 1, 55, 14, 1, 5, 1, 2, 5, 11, 1, 36, 9, 1, + 102, 4, 1, 6, 1, 2, 2, 2, 25, 2, 4, 3, 16, 4, 13, 1, 2, 2, 6, 1, 15, 1, 94, 1, 0, 3, 0, 3, + 29, 2, 30, 2, 30, 2, 64, 2, 1, 7, 8, 1, 2, 11, 3, 1, 5, 1, 45, 5, 51, 1, 65, 2, 34, 1, 118, + 3, 4, 2, 9, 1, 6, 3, 219, 2, 2, 1, 58, 1, 1, 7, 1, 1, 1, 1, 2, 8, 6, 10, 2, 1, 39, 1, 8, 31, + 49, 4, 48, 1, 1, 5, 1, 1, 5, 1, 40, 9, 12, 2, 32, 4, 2, 2, 1, 3, 56, 1, 1, 2, 3, 1, 1, 3, + 58, 8, 2, 2, 64, 6, 82, 3, 1, 13, 1, 7, 4, 1, 6, 1, 3, 2, 50, 63, 13, 1, 34, 101, 0, 1, 1, + 3, 11, 3, 13, 3, 13, 3, 13, 2, 12, 5, 8, 2, 10, 1, 2, 1, 2, 5, 49, 5, 1, 10, 1, 1, 13, 1, + 16, 13, 51, 33, 0, 2, 113, 3, 125, 1, 15, 1, 96, 32, 47, 1, 0, 1, 36, 4, 3, 5, 5, 1, 93, 6, + 93, 3, 0, 1, 0, 6, 0, 1, 98, 4, 1, 10, 1, 1, 28, 4, 80, 2, 14, 34, 78, 1, 23, 3, 103, 3, 3, + 2, 8, 1, 3, 1, 4, 1, 25, 2, 5, 1, 151, 2, 26, 18, 13, 1, 38, 8, 25, 11, 46, 3, 48, 1, 2, 4, + 2, 2, 17, 1, 21, 2, 66, 6, 2, 2, 2, 2, 12, 1, 8, 1, 35, 1, 11, 1, 51, 1, 1, 3, 2, 2, 5, 2, + 1, 1, 27, 1, 14, 2, 5, 2, 1, 1, 100, 5, 9, 3, 121, 1, 2, 1, 4, 1, 0, 1, 147, 17, 0, 16, 3, + 1, 12, 16, 34, 1, 2, 1, 169, 1, 7, 1, 6, 1, 11, 1, 35, 1, 1, 1, 47, 1, 45, 2, 67, 1, 21, 3, + 0, 1, 226, 1, 149, 5, 0, 6, 1, 42, 1, 9, 0, 3, 1, 2, 5, 4, 40, 3, 4, 1, 165, 2, 0, 4, 0, 2, + 153, 11, 49, 4, 123, 1, 54, 15, 41, 1, 2, 2, 10, 3, 49, 4, 2, 2, 2, 1, 4, 1, 10, 1, 50, 3, + 36, 5, 1, 8, 62, 1, 12, 2, 52, 9, 10, 4, 2, 1, 95, 3, 2, 1, 1, 2, 6, 1, 160, 1, 3, 8, 21, 2, + 57, 2, 3, 1, 37, 7, 3, 5, 195, 8, 2, 3, 1, 1, 23, 1, 84, 6, 1, 1, 4, 2, 1, 2, 238, 4, 6, 2, + 1, 2, 27, 2, 85, 8, 2, 1, 1, 2, 106, 1, 1, 1, 2, 6, 1, 1, 101, 3, 2, 4, 1, 5, 0, 9, 1, 2, 0, + 2, 1, 1, 4, 1, 144, 4, 2, 2, 4, 1, 32, 10, 40, 6, 2, 4, 8, 1, 9, 6, 2, 3, 46, 13, 1, 2, 0, + 7, 1, 6, 1, 1, 82, 22, 2, 7, 1, 2, 1, 2, 122, 6, 3, 1, 1, 2, 1, 7, 1, 1, 72, 2, 3, 1, 1, 1, + 0, 2, 0, 9, 0, 5, 59, 7, 9, 4, 0, 1, 63, 17, 64, 2, 1, 2, 0, 4, 1, 7, 1, 2, 0, 2, 1, 4, 0, + 46, 2, 23, 0, 3, 9, 16, 2, 7, 30, 4, 148, 3, 0, 55, 4, 50, 8, 1, 14, 1, 22, 5, 1, 15, 0, 7, + 1, 17, 2, 7, 1, 2, 1, 5, 0, 14, 0, 1, 61, 4, 0, 7, 109, 8, 0, 5, 0, 1, 30, 96, 128, 240, 0, ]; pub fn lookup(c: char) -> bool { super::skip_search( @@ -222,23 +225,24 @@ pub mod case_ignorable { #[rustfmt::skip] pub mod cased { - static SHORT_OFFSET_RUNS: [u32; 19] = [ - 4256, 115348384, 136322176, 144711446, 163587254, 320875520, 325101120, 358656816, - 392231680, 404815649, 413205504, 421596288, 434182304, 442592832, 446813184, 451008166, - 528607488, 576844080, 582152586, + static SHORT_OFFSET_RUNS: [u32; 21] = [ + 4256, 115348384, 136322176, 144711446, 163587254, 320875520, 325101120, 350268208, + 392231680, 404815649, 413205504, 421595008, 467733632, 484513952, 492924480, 497144832, + 501339814, 578936576, 627173632, 635564336, 640872842, ]; - static OFFSETS: [u8; 283] = [ + static OFFSETS: [u8; 311] = [ 65, 26, 6, 26, 47, 1, 10, 1, 4, 1, 5, 23, 1, 31, 1, 195, 1, 4, 4, 208, 1, 36, 7, 2, 30, 5, 96, 1, 42, 4, 2, 2, 2, 4, 1, 1, 6, 1, 1, 3, 1, 1, 1, 20, 1, 83, 1, 139, 8, 166, 1, 38, 9, 41, 0, 38, 1, 1, 5, 1, 2, 43, 2, 3, 0, 86, 2, 6, 0, 9, 7, 43, 2, 3, 64, 192, 64, 0, 2, 6, 2, 38, 2, 6, 2, 8, 1, 1, 1, 1, 1, 1, 1, 31, 2, 53, 1, 7, 1, 1, 3, 3, 1, 7, 3, 4, 2, 6, 4, 13, 5, 3, 1, 7, 116, 1, 13, 1, 16, 13, 101, 1, 4, 1, 2, 10, 1, 1, 3, 5, 6, 1, 1, 1, 1, 1, 1, 4, - 1, 6, 4, 1, 2, 4, 5, 5, 4, 1, 17, 32, 3, 2, 0, 52, 0, 47, 1, 47, 1, 133, 6, 4, 3, 2, 12, 38, - 1, 1, 5, 1, 0, 46, 18, 30, 132, 102, 3, 4, 1, 48, 2, 9, 42, 2, 1, 3, 0, 43, 1, 13, 7, 80, 0, - 7, 12, 5, 0, 26, 6, 26, 0, 80, 96, 36, 4, 36, 0, 51, 13, 51, 0, 64, 0, 64, 0, 85, 1, 71, 1, - 2, 2, 1, 2, 2, 2, 4, 1, 12, 1, 1, 1, 7, 1, 65, 1, 4, 2, 8, 1, 7, 1, 28, 1, 4, 1, 5, 1, 1, 3, - 7, 1, 0, 2, 25, 1, 25, 1, 31, 1, 25, 1, 31, 1, 25, 1, 31, 1, 25, 1, 31, 1, 25, 1, 8, 0, 68, - 0, 26, 6, 26, 6, 26, 0, + 1, 6, 4, 1, 2, 4, 5, 5, 4, 1, 17, 32, 3, 2, 0, 52, 0, 229, 6, 4, 3, 2, 12, 38, 1, 1, 5, 1, + 0, 46, 18, 30, 132, 102, 3, 4, 1, 59, 5, 2, 1, 1, 1, 5, 27, 2, 1, 3, 0, 43, 1, 13, 7, 80, 0, + 7, 12, 5, 0, 26, 6, 26, 0, 80, 96, 36, 4, 36, 116, 11, 1, 15, 1, 7, 1, 2, 1, 11, 1, 15, 1, + 7, 1, 2, 0, 1, 2, 3, 1, 42, 1, 9, 0, 51, 13, 51, 0, 64, 0, 64, 0, 85, 1, 71, 1, 2, 2, 1, 2, + 2, 2, 4, 1, 12, 1, 1, 1, 7, 1, 65, 1, 4, 2, 8, 1, 7, 1, 28, 1, 4, 1, 5, 1, 1, 3, 7, 1, 0, 2, + 25, 1, 25, 1, 31, 1, 25, 1, 31, 1, 25, 1, 31, 1, 25, 1, 31, 1, 25, 1, 8, 0, 10, 1, 20, 0, + 68, 0, 26, 6, 26, 6, 26, 0, ]; pub fn lookup(c: char) -> bool { super::skip_search( @@ -268,38 +272,40 @@ pub mod cc { #[rustfmt::skip] pub mod grapheme_extend { - static SHORT_OFFSET_RUNS: [u32; 31] = [ - 768, 2098307, 6292881, 10490717, 513808146, 518004748, 723528943, 731918378, 744531567, - 752920578, 769719070, 899743232, 903937950, 912327165, 916523521, 929107236, 954273451, - 958470191, 1180769328, 1252073203, 1315007216, 1319202639, 1327611037, 1340199269, - 1344395776, 1373757440, 1398923568, 1419895532, 1424091344, 1429078048, 1438581232, + static SHORT_OFFSET_RUNS: [u32; 32] = [ + 768, 2098307, 6292881, 10490717, 522196754, 526393356, 731917551, 740306986, 752920175, + 761309186, 778107678, 908131840, 912326558, 920715773, 924912129, 937495844, 962662059, + 966858799, 1205935152, 1277239027, 1340173040, 1344368463, 1352776861, 1365364480, + 1369559397, 1377950208, 1407311872, 1432478000, 1453449902, 1457645776, 1466826784, + 1476329968, ]; - static OFFSETS: [u8; 689] = [ + static OFFSETS: [u8; 707] = [ 0, 112, 0, 7, 0, 45, 1, 1, 1, 2, 1, 2, 1, 1, 72, 11, 48, 21, 16, 1, 101, 7, 2, 6, 2, 2, 1, - 4, 35, 1, 30, 27, 91, 11, 58, 9, 9, 1, 24, 4, 1, 9, 1, 3, 1, 5, 43, 3, 119, 15, 1, 32, 55, - 1, 1, 1, 4, 8, 4, 1, 3, 7, 10, 2, 29, 1, 58, 1, 1, 1, 2, 4, 8, 1, 9, 1, 10, 2, 26, 1, 2, 2, - 57, 1, 4, 2, 4, 2, 2, 3, 3, 1, 30, 2, 3, 1, 11, 2, 57, 1, 4, 5, 1, 2, 4, 1, 20, 2, 22, 6, 1, - 1, 58, 1, 1, 2, 1, 4, 8, 1, 7, 3, 10, 2, 30, 1, 59, 1, 1, 1, 12, 1, 9, 1, 40, 1, 3, 1, 57, - 3, 5, 3, 1, 4, 7, 2, 11, 2, 29, 1, 58, 1, 2, 1, 2, 1, 3, 1, 5, 2, 7, 2, 11, 2, 28, 2, 57, 2, - 1, 1, 2, 4, 8, 1, 9, 1, 10, 2, 29, 1, 72, 1, 4, 1, 2, 3, 1, 1, 8, 1, 81, 1, 2, 7, 12, 8, 98, - 1, 2, 9, 11, 6, 74, 2, 27, 1, 1, 1, 1, 1, 55, 14, 1, 5, 1, 2, 5, 11, 1, 36, 9, 1, 102, 4, 1, - 6, 1, 2, 2, 2, 25, 2, 4, 3, 16, 4, 13, 1, 2, 2, 6, 1, 15, 1, 0, 3, 0, 3, 29, 3, 29, 2, 30, - 2, 64, 2, 1, 7, 8, 1, 2, 11, 9, 1, 45, 3, 119, 2, 34, 1, 118, 3, 4, 2, 9, 1, 6, 3, 219, 2, - 2, 1, 58, 1, 1, 7, 1, 1, 1, 1, 2, 8, 6, 10, 2, 1, 48, 17, 63, 4, 48, 7, 1, 1, 5, 1, 40, 9, - 12, 2, 32, 4, 2, 2, 1, 3, 56, 1, 1, 2, 3, 1, 1, 3, 58, 8, 2, 2, 152, 3, 1, 13, 1, 7, 4, 1, - 6, 1, 3, 2, 198, 58, 1, 5, 0, 1, 195, 33, 0, 3, 141, 1, 96, 32, 0, 6, 105, 2, 0, 4, 1, 10, - 32, 2, 80, 2, 0, 1, 3, 1, 4, 1, 25, 2, 5, 1, 151, 2, 26, 18, 13, 1, 38, 8, 25, 11, 46, 3, - 48, 1, 2, 4, 2, 2, 39, 1, 67, 6, 2, 2, 2, 2, 12, 1, 8, 1, 47, 1, 51, 1, 1, 3, 2, 2, 5, 2, 1, - 1, 42, 2, 8, 1, 238, 1, 2, 1, 4, 1, 0, 1, 0, 16, 16, 16, 0, 2, 0, 1, 226, 1, 149, 5, 0, 3, - 1, 2, 5, 4, 40, 3, 4, 1, 165, 2, 0, 4, 0, 2, 153, 11, 176, 1, 54, 15, 56, 3, 49, 4, 2, 2, - 69, 3, 36, 5, 1, 8, 62, 1, 12, 2, 52, 9, 10, 4, 2, 1, 95, 3, 2, 1, 1, 2, 6, 1, 160, 1, 3, 8, - 21, 2, 57, 2, 1, 1, 1, 1, 22, 1, 14, 7, 3, 5, 195, 8, 2, 3, 1, 1, 23, 1, 81, 1, 2, 6, 1, 1, - 2, 1, 1, 2, 1, 2, 235, 1, 2, 4, 6, 2, 1, 2, 27, 2, 85, 8, 2, 1, 1, 2, 106, 1, 1, 1, 2, 6, 1, - 1, 101, 3, 2, 4, 1, 5, 0, 9, 1, 2, 245, 1, 10, 2, 1, 1, 4, 1, 144, 4, 2, 2, 4, 1, 32, 10, - 40, 6, 2, 4, 8, 1, 9, 6, 2, 3, 46, 13, 1, 2, 0, 7, 1, 6, 1, 1, 82, 22, 2, 7, 1, 2, 1, 2, - 122, 6, 3, 1, 1, 2, 1, 7, 1, 1, 72, 2, 3, 1, 1, 1, 0, 2, 0, 5, 59, 7, 0, 1, 63, 4, 81, 1, 0, - 2, 0, 1, 1, 3, 4, 5, 8, 8, 2, 7, 30, 4, 148, 3, 0, 55, 4, 50, 8, 1, 14, 1, 22, 5, 1, 15, 0, - 7, 1, 17, 2, 7, 1, 2, 1, 5, 0, 7, 0, 4, 0, 7, 109, 7, 0, 96, 128, 240, 0, + 4, 35, 1, 30, 27, 91, 11, 58, 9, 9, 1, 24, 4, 1, 9, 1, 3, 1, 5, 43, 3, 60, 8, 42, 24, 1, 32, + 55, 1, 1, 1, 4, 8, 4, 1, 3, 7, 10, 2, 29, 1, 58, 1, 1, 1, 2, 4, 8, 1, 9, 1, 10, 2, 26, 1, 2, + 2, 57, 1, 4, 2, 4, 2, 2, 3, 3, 1, 30, 2, 3, 1, 11, 2, 57, 1, 4, 5, 1, 2, 4, 1, 20, 2, 22, 6, + 1, 1, 58, 1, 1, 2, 1, 4, 8, 1, 7, 3, 10, 2, 30, 1, 59, 1, 1, 1, 12, 1, 9, 1, 40, 1, 3, 1, + 55, 1, 1, 3, 5, 3, 1, 4, 7, 2, 11, 2, 29, 1, 58, 1, 2, 1, 2, 1, 3, 1, 5, 2, 7, 2, 11, 2, 28, + 2, 57, 2, 1, 1, 2, 4, 8, 1, 9, 1, 10, 2, 29, 1, 72, 1, 4, 1, 2, 3, 1, 1, 8, 1, 81, 1, 2, 7, + 12, 8, 98, 1, 2, 9, 11, 6, 74, 2, 27, 1, 1, 1, 1, 1, 55, 14, 1, 5, 1, 2, 5, 11, 1, 36, 9, 1, + 102, 4, 1, 6, 1, 2, 2, 2, 25, 2, 4, 3, 16, 4, 13, 1, 2, 2, 6, 1, 15, 1, 0, 3, 0, 3, 29, 2, + 30, 2, 30, 2, 64, 2, 1, 7, 8, 1, 2, 11, 9, 1, 45, 3, 1, 1, 117, 2, 34, 1, 118, 3, 4, 2, 9, + 1, 6, 3, 219, 2, 2, 1, 58, 1, 1, 7, 1, 1, 1, 1, 2, 8, 6, 10, 2, 1, 48, 31, 49, 4, 48, 7, 1, + 1, 5, 1, 40, 9, 12, 2, 32, 4, 2, 2, 1, 3, 56, 1, 1, 2, 3, 1, 1, 3, 58, 8, 2, 2, 152, 3, 1, + 13, 1, 7, 4, 1, 6, 1, 3, 2, 198, 64, 0, 1, 195, 33, 0, 3, 141, 1, 96, 32, 0, 6, 105, 2, 0, + 4, 1, 10, 32, 2, 80, 2, 0, 1, 3, 1, 4, 1, 25, 2, 5, 1, 151, 2, 26, 18, 13, 1, 38, 8, 25, 11, + 46, 3, 48, 1, 2, 4, 2, 2, 39, 1, 67, 6, 2, 2, 2, 2, 12, 1, 8, 1, 47, 1, 51, 1, 1, 3, 2, 2, + 5, 2, 1, 1, 42, 2, 8, 1, 238, 1, 2, 1, 4, 1, 0, 1, 0, 16, 16, 16, 0, 2, 0, 1, 226, 1, 149, + 5, 0, 3, 1, 2, 5, 4, 40, 3, 4, 1, 165, 2, 0, 4, 0, 2, 153, 11, 49, 4, 123, 1, 54, 15, 41, 1, + 2, 2, 10, 3, 49, 4, 2, 2, 7, 1, 61, 3, 36, 5, 1, 8, 62, 1, 12, 2, 52, 9, 10, 4, 2, 1, 95, 3, + 2, 1, 1, 2, 6, 1, 160, 1, 3, 8, 21, 2, 57, 2, 1, 1, 1, 1, 22, 1, 14, 7, 3, 5, 195, 8, 2, 3, + 1, 1, 23, 1, 81, 1, 2, 6, 1, 1, 2, 1, 1, 2, 1, 2, 235, 1, 2, 4, 6, 2, 1, 2, 27, 2, 85, 8, 2, + 1, 1, 2, 106, 1, 1, 1, 2, 6, 1, 1, 101, 3, 2, 4, 1, 5, 0, 9, 1, 2, 245, 1, 10, 2, 1, 1, 4, + 1, 144, 4, 2, 2, 4, 1, 32, 10, 40, 6, 2, 4, 8, 1, 9, 6, 2, 3, 46, 13, 1, 2, 0, 7, 1, 6, 1, + 1, 82, 22, 2, 7, 1, 2, 1, 2, 122, 6, 3, 1, 1, 2, 1, 7, 1, 1, 72, 2, 3, 1, 1, 1, 0, 2, 0, 5, + 59, 7, 0, 1, 63, 4, 81, 1, 0, 2, 0, 46, 2, 23, 0, 1, 1, 3, 4, 5, 8, 8, 2, 7, 30, 4, 148, 3, + 0, 55, 4, 50, 8, 1, 14, 1, 22, 5, 1, 15, 0, 7, 1, 17, 2, 7, 1, 2, 1, 5, 0, 7, 0, 1, 61, 4, + 0, 7, 109, 7, 0, 96, 128, 240, 0, ]; pub fn lookup(c: char) -> bool { super::skip_search( @@ -313,33 +319,34 @@ pub mod grapheme_extend { #[rustfmt::skip] pub mod lowercase { static BITSET_CHUNKS_MAP: [u8; 123] = [ - 13, 16, 0, 0, 8, 0, 0, 11, 12, 9, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 3, 1, 0, 14, 0, 7, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, - 0, 0, 6, + 14, 17, 0, 0, 9, 0, 0, 12, 13, 10, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 4, 1, 0, 15, 0, 8, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, + 3, 0, 0, 7, ]; - static BITSET_INDEX_CHUNKS: [[u8; 16]; 18] = [ + static BITSET_INDEX_CHUNKS: [[u8; 16]; 19] = [ [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0], - [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 14, 52, 0], - [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 59, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 14, 55, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 43, 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, 62, 39, 0, 47, 43, 45, 30], - [0, 0, 0, 0, 10, 53, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 65, 42, 0, 50, 46, 48, 32], + [0, 0, 0, 0, 10, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [0, 0, 0, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26], - [0, 0, 0, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [0, 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [0, 0, 54, 0, 52, 52, 52, 0, 21, 21, 64, 21, 33, 24, 23, 34], - [0, 5, 71, 0, 28, 15, 69, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [0, 61, 31, 17, 22, 48, 49, 44, 42, 8, 32, 38, 0, 27, 13, 29], - [11, 55, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [16, 25, 21, 35, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [16, 46, 2, 20, 63, 9, 54, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [60, 37, 51, 12, 70, 58, 18, 1, 6, 59, 68, 19, 65, 66, 3, 41], + [0, 0, 0, 53, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26], + [0, 0, 0, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 57, 0, 55, 55, 55, 0, 21, 21, 67, 21, 35, 24, 23, 36], + [0, 5, 74, 0, 28, 15, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 64, 33, 17, 22, 51, 52, 47, 45, 8, 34, 40, 0, 27, 13, 30], + [11, 58, 0, 4, 0, 0, 29, 0, 0, 0, 0, 0, 0, 0, 31, 0], + [16, 25, 21, 37, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [16, 49, 2, 20, 66, 9, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [63, 39, 54, 12, 73, 61, 18, 1, 6, 62, 71, 19, 68, 69, 3, 44], ]; - static BITSET_CANONICAL: [u64; 52] = [ + static BITSET_CANONICAL: [u64; 55] = [ 0b0000000000000000000000000000000000000000000000000000000000000000, 0b1111111111111111110000000000000000000000000011111111111111111111, 0b1010101010101010101010101010101010101010101010101010100000000010, @@ -365,12 +372,14 @@ pub mod lowercase { 0b0101010110101010101010101010101010101010101010101010101010101010, 0b0100000011011111000000001111111100000000111111110000000011111111, 0b0011111111111111000000001111111100000000111111110000000000111111, - 0b0011111111011010000101010110001001111111111111111111111111111111, + 0b0011111111011010000101010110001011111111111111111111111111111111, 0b0011111100000000000000000000000000000000000000000000000000000000, 0b0011110010001010000000000000000000000000000000000000000000100000, 0b0011001000010000100000000000000000000000000010001100010000000000, + 0b0001101111111011111111111111101111111111100000000000000000000000, 0b0001100100101111101010101010101010101010111000110111111111111111, - 0b0000011101000000000000000000000000000000000000000000010100001000, + 0b0000011111111101111111111111111111111111111111111111111110111001, + 0b0000011101000000000000000000000000000010101010100000010100001010, 0b0000010000100000000001000000000000000000000000000000000000000000, 0b0000000111111111111111111111111111111111111011111111111111111111, 0b0000000011111111000000001111111100000000001111110000000011111111, @@ -379,6 +388,7 @@ pub mod lowercase { 0b0000000000000000001000001011111111111111111111111111111111111111, 0b0000000000000000000000001111111111111111110111111100000000000000, 0b0000000000000000000000000001111100000000000000000000000000000011, + 0b0000000000000000000000000000000001111111111111111111101111111111, 0b0000000000000000000000000000000000111010101010101010101010101010, 0b0000000000000000000000000000000000000000111110000000000001111111, 0b0000000000000000000000000000000000000000000000000000101111110111, @@ -416,10 +426,10 @@ pub mod n { 1632, 18876774, 31461440, 102765417, 111154926, 115349830, 132128880, 165684320, 186656630, 195046653, 199241735, 203436434, 216049184, 241215536, 249605104, 274792208, 278987015, 283181793, 295766104, 320933114, 383848032, 392238160, 434181712, 442570976, 455154768, - 463544256, 476128256, 480340576, 484535936, 497144544, 501340110, 509731136, 513925872, - 518121671, 522316913, 530706688, 551681008, 556989434, + 463544256, 476128256, 480340576, 484535936, 501338848, 505534414, 513925440, 518120176, + 522315975, 526511217, 534900992, 555875312, 561183738, ]; - static OFFSETS: [u8; 267] = [ + static OFFSETS: [u8; 269] = [ 48, 10, 120, 2, 5, 1, 2, 3, 0, 10, 134, 10, 198, 10, 0, 10, 118, 10, 4, 6, 108, 10, 118, 10, 118, 10, 2, 6, 110, 13, 115, 10, 8, 7, 103, 10, 104, 7, 7, 19, 109, 10, 96, 10, 118, 10, 70, 20, 0, 10, 70, 10, 0, 20, 0, 3, 239, 10, 6, 10, 22, 10, 0, 10, 128, 11, 165, 10, 6, 10, @@ -429,8 +439,9 @@ pub mod n { 29, 1, 8, 1, 134, 5, 202, 10, 0, 8, 25, 7, 39, 9, 75, 5, 22, 6, 160, 2, 2, 16, 2, 46, 64, 9, 52, 2, 30, 3, 75, 5, 104, 8, 24, 8, 41, 7, 0, 6, 48, 10, 0, 31, 158, 10, 42, 4, 112, 7, 134, 30, 128, 10, 60, 10, 144, 10, 7, 20, 251, 10, 0, 10, 118, 10, 0, 10, 102, 10, 102, 12, 0, - 19, 93, 10, 0, 29, 227, 10, 70, 10, 0, 21, 0, 111, 0, 10, 230, 10, 1, 7, 0, 23, 0, 20, 108, - 25, 0, 50, 0, 10, 0, 10, 0, 9, 128, 10, 0, 59, 1, 3, 1, 4, 76, 45, 1, 15, 0, 13, 0, 10, 0, + 19, 93, 10, 0, 29, 227, 10, 70, 10, 0, 21, 0, 111, 0, 10, 86, 10, 134, 10, 1, 7, 0, 23, 0, + 20, 108, 25, 0, 50, 0, 10, 0, 10, 0, 9, 128, 10, 0, 59, 1, 3, 1, 4, 76, 45, 1, 15, 0, 13, 0, + 10, 0, ]; pub fn lookup(c: char) -> bool { super::skip_search( @@ -444,37 +455,37 @@ pub mod n { #[rustfmt::skip] pub mod uppercase { static BITSET_CHUNKS_MAP: [u8; 125] = [ - 12, 15, 5, 5, 0, 5, 5, 2, 4, 11, 5, 14, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 8, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 6, 5, 13, 5, 10, 5, 5, 1, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 7, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 16, 5, 5, - 5, 5, 9, 5, 3, + 12, 15, 6, 6, 0, 6, 6, 2, 4, 11, 6, 16, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 8, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 5, 6, 14, 6, 10, 6, 6, 1, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 13, 6, 6, + 6, 6, 9, 6, 3, ]; static BITSET_INDEX_CHUNKS: [[u8; 16]; 17] = [ - [41, 41, 5, 33, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 5, 0], - [41, 41, 5, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41], - [41, 41, 38, 41, 41, 41, 41, 41, 17, 17, 61, 17, 40, 29, 24, 23], - [41, 41, 41, 41, 9, 8, 42, 41, 41, 41, 41, 41, 41, 41, 41, 41], - [41, 41, 41, 41, 35, 28, 65, 41, 41, 41, 41, 41, 41, 41, 41, 41], - [41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41], - [41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 56, 41, 41, 41], - [41, 41, 41, 41, 41, 41, 41, 41, 41, 46, 41, 41, 41, 41, 41, 41], - [41, 41, 41, 41, 41, 41, 41, 41, 41, 60, 59, 41, 20, 14, 16, 4], - [41, 41, 41, 41, 47, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41], - [41, 41, 51, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41], - [41, 41, 52, 43, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41], - [41, 53, 41, 31, 34, 21, 22, 15, 13, 32, 41, 41, 41, 11, 30, 37], - [48, 41, 9, 44, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41], - [49, 36, 17, 27, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41], - [50, 19, 2, 18, 10, 45, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41], - [57, 1, 26, 54, 12, 7, 25, 55, 39, 58, 6, 3, 64, 63, 62, 66], + [43, 43, 5, 34, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 5, 1], + [43, 43, 5, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43], + [43, 43, 39, 43, 43, 43, 43, 43, 17, 17, 62, 17, 42, 29, 24, 23], + [43, 43, 43, 43, 9, 8, 44, 43, 43, 43, 43, 43, 43, 43, 43, 43], + [43, 43, 43, 43, 36, 28, 66, 43, 43, 43, 43, 43, 43, 43, 43, 43], + [43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 0, 43, 43, 43], + [43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43], + [43, 43, 43, 43, 43, 43, 43, 43, 43, 54, 43, 43, 43, 43, 43, 43], + [43, 43, 43, 43, 43, 43, 43, 43, 43, 61, 60, 43, 20, 14, 16, 4], + [43, 43, 43, 43, 55, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43], + [43, 43, 58, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43], + [43, 43, 59, 45, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43], + [43, 48, 43, 31, 35, 21, 22, 15, 13, 33, 43, 43, 43, 11, 30, 38], + [51, 53, 26, 49, 12, 7, 25, 50, 40, 52, 6, 3, 65, 64, 63, 67], + [56, 43, 9, 46, 43, 41, 32, 43, 43, 43, 43, 43, 43, 43, 43, 43], + [57, 19, 2, 18, 10, 47, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43], + [57, 37, 17, 27, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43], ]; - static BITSET_CANONICAL: [u64; 41] = [ + static BITSET_CANONICAL: [u64; 43] = [ + 0b0000011111111111111111111111111000000000000000000000000000000000, 0b0000000000111111111111111111111111111111111111111111111111111111, - 0b1111111111111111111111110000000000000000000000000011111111111111, 0b0101010101010101010101010101010101010101010101010101010000000001, 0b0000011111111111111111111111110000000000000000000000000000000001, - 0b0000000000100000000000000000000000000000000000000000001011110100, + 0b0000000000100000000000000000000000000001010000010000001011110101, 0b1111111111111111111111111111111100000000000000000000000000000000, 0b1111111111111111111111110000000000000000000000000000001111111111, 0b1111111111111111111100000000000000000000000000011111110001011111, @@ -502,6 +513,7 @@ pub mod uppercase { 0b0000000000000000111111110000000010101010000000000011111100000000, 0b0000000000000000000011111111101111111111111111101101011101000000, 0b0000000000000000000000000000000001111111011111111111111111111111, + 0b0000000000000000000000000000000000000000001101111111011111111111, 0b0000000000000000000000000000000000000000000000000101010101111010, 0b0000000000000000000000000000000000000000000000000010000010111111, 0b1010101001010101010101010101010101010101010101010101010101010101, @@ -510,11 +522,12 @@ pub mod uppercase { 0b1110011010010000010101010101010101010101000111001000000000000000, 0b1110011111111111111111111111111111111111111111110000000000000000, 0b1111000000000000000000000000001111111111111111111111111100000000, + 0b1111011111111111000000000000000000000000000000000000000000000000, 0b1111111100000000111111110000000000111111000000001111111100000000, ]; - static BITSET_MAPPING: [(u8, u8); 26] = [ - (0, 182), (0, 74), (0, 166), (0, 162), (0, 159), (0, 150), (0, 148), (0, 142), (0, 135), - (0, 134), (0, 131), (0, 64), (1, 115), (1, 66), (1, 70), (1, 83), (1, 12), (1, 8), (2, 164), + static BITSET_MAPPING: [(u8, u8); 25] = [ + (0, 187), (0, 177), (0, 171), (0, 167), (0, 164), (0, 32), (0, 47), (0, 51), (0, 121), + (0, 117), (0, 109), (1, 150), (1, 148), (1, 142), (1, 134), (1, 131), (1, 64), (2, 164), (2, 146), (2, 20), (3, 146), (3, 140), (3, 134), (4, 178), (4, 171), ]; @@ -1051,113 +1064,116 @@ pub mod conversions { ('\u{2c28}', ['\u{2c58}', '\u{0}', '\u{0}']), ('\u{2c29}', ['\u{2c59}', '\u{0}', '\u{0}']), ('\u{2c2a}', ['\u{2c5a}', '\u{0}', '\u{0}']), ('\u{2c2b}', ['\u{2c5b}', '\u{0}', '\u{0}']), ('\u{2c2c}', ['\u{2c5c}', '\u{0}', '\u{0}']), ('\u{2c2d}', ['\u{2c5d}', '\u{0}', '\u{0}']), - ('\u{2c2e}', ['\u{2c5e}', '\u{0}', '\u{0}']), ('\u{2c60}', ['\u{2c61}', '\u{0}', '\u{0}']), - ('\u{2c62}', ['\u{26b}', '\u{0}', '\u{0}']), ('\u{2c63}', ['\u{1d7d}', '\u{0}', '\u{0}']), - ('\u{2c64}', ['\u{27d}', '\u{0}', '\u{0}']), ('\u{2c67}', ['\u{2c68}', '\u{0}', '\u{0}']), - ('\u{2c69}', ['\u{2c6a}', '\u{0}', '\u{0}']), ('\u{2c6b}', ['\u{2c6c}', '\u{0}', '\u{0}']), - ('\u{2c6d}', ['\u{251}', '\u{0}', '\u{0}']), ('\u{2c6e}', ['\u{271}', '\u{0}', '\u{0}']), - ('\u{2c6f}', ['\u{250}', '\u{0}', '\u{0}']), ('\u{2c70}', ['\u{252}', '\u{0}', '\u{0}']), - ('\u{2c72}', ['\u{2c73}', '\u{0}', '\u{0}']), ('\u{2c75}', ['\u{2c76}', '\u{0}', '\u{0}']), - ('\u{2c7e}', ['\u{23f}', '\u{0}', '\u{0}']), ('\u{2c7f}', ['\u{240}', '\u{0}', '\u{0}']), - ('\u{2c80}', ['\u{2c81}', '\u{0}', '\u{0}']), ('\u{2c82}', ['\u{2c83}', '\u{0}', '\u{0}']), - ('\u{2c84}', ['\u{2c85}', '\u{0}', '\u{0}']), ('\u{2c86}', ['\u{2c87}', '\u{0}', '\u{0}']), - ('\u{2c88}', ['\u{2c89}', '\u{0}', '\u{0}']), ('\u{2c8a}', ['\u{2c8b}', '\u{0}', '\u{0}']), - ('\u{2c8c}', ['\u{2c8d}', '\u{0}', '\u{0}']), ('\u{2c8e}', ['\u{2c8f}', '\u{0}', '\u{0}']), - ('\u{2c90}', ['\u{2c91}', '\u{0}', '\u{0}']), ('\u{2c92}', ['\u{2c93}', '\u{0}', '\u{0}']), - ('\u{2c94}', ['\u{2c95}', '\u{0}', '\u{0}']), ('\u{2c96}', ['\u{2c97}', '\u{0}', '\u{0}']), - ('\u{2c98}', ['\u{2c99}', '\u{0}', '\u{0}']), ('\u{2c9a}', ['\u{2c9b}', '\u{0}', '\u{0}']), - ('\u{2c9c}', ['\u{2c9d}', '\u{0}', '\u{0}']), ('\u{2c9e}', ['\u{2c9f}', '\u{0}', '\u{0}']), - ('\u{2ca0}', ['\u{2ca1}', '\u{0}', '\u{0}']), ('\u{2ca2}', ['\u{2ca3}', '\u{0}', '\u{0}']), - ('\u{2ca4}', ['\u{2ca5}', '\u{0}', '\u{0}']), ('\u{2ca6}', ['\u{2ca7}', '\u{0}', '\u{0}']), - ('\u{2ca8}', ['\u{2ca9}', '\u{0}', '\u{0}']), ('\u{2caa}', ['\u{2cab}', '\u{0}', '\u{0}']), - ('\u{2cac}', ['\u{2cad}', '\u{0}', '\u{0}']), ('\u{2cae}', ['\u{2caf}', '\u{0}', '\u{0}']), - ('\u{2cb0}', ['\u{2cb1}', '\u{0}', '\u{0}']), ('\u{2cb2}', ['\u{2cb3}', '\u{0}', '\u{0}']), - ('\u{2cb4}', ['\u{2cb5}', '\u{0}', '\u{0}']), ('\u{2cb6}', ['\u{2cb7}', '\u{0}', '\u{0}']), - ('\u{2cb8}', ['\u{2cb9}', '\u{0}', '\u{0}']), ('\u{2cba}', ['\u{2cbb}', '\u{0}', '\u{0}']), - ('\u{2cbc}', ['\u{2cbd}', '\u{0}', '\u{0}']), ('\u{2cbe}', ['\u{2cbf}', '\u{0}', '\u{0}']), - ('\u{2cc0}', ['\u{2cc1}', '\u{0}', '\u{0}']), ('\u{2cc2}', ['\u{2cc3}', '\u{0}', '\u{0}']), - ('\u{2cc4}', ['\u{2cc5}', '\u{0}', '\u{0}']), ('\u{2cc6}', ['\u{2cc7}', '\u{0}', '\u{0}']), - ('\u{2cc8}', ['\u{2cc9}', '\u{0}', '\u{0}']), ('\u{2cca}', ['\u{2ccb}', '\u{0}', '\u{0}']), - ('\u{2ccc}', ['\u{2ccd}', '\u{0}', '\u{0}']), ('\u{2cce}', ['\u{2ccf}', '\u{0}', '\u{0}']), - ('\u{2cd0}', ['\u{2cd1}', '\u{0}', '\u{0}']), ('\u{2cd2}', ['\u{2cd3}', '\u{0}', '\u{0}']), - ('\u{2cd4}', ['\u{2cd5}', '\u{0}', '\u{0}']), ('\u{2cd6}', ['\u{2cd7}', '\u{0}', '\u{0}']), - ('\u{2cd8}', ['\u{2cd9}', '\u{0}', '\u{0}']), ('\u{2cda}', ['\u{2cdb}', '\u{0}', '\u{0}']), - ('\u{2cdc}', ['\u{2cdd}', '\u{0}', '\u{0}']), ('\u{2cde}', ['\u{2cdf}', '\u{0}', '\u{0}']), - ('\u{2ce0}', ['\u{2ce1}', '\u{0}', '\u{0}']), ('\u{2ce2}', ['\u{2ce3}', '\u{0}', '\u{0}']), - ('\u{2ceb}', ['\u{2cec}', '\u{0}', '\u{0}']), ('\u{2ced}', ['\u{2cee}', '\u{0}', '\u{0}']), - ('\u{2cf2}', ['\u{2cf3}', '\u{0}', '\u{0}']), ('\u{a640}', ['\u{a641}', '\u{0}', '\u{0}']), - ('\u{a642}', ['\u{a643}', '\u{0}', '\u{0}']), ('\u{a644}', ['\u{a645}', '\u{0}', '\u{0}']), - ('\u{a646}', ['\u{a647}', '\u{0}', '\u{0}']), ('\u{a648}', ['\u{a649}', '\u{0}', '\u{0}']), - ('\u{a64a}', ['\u{a64b}', '\u{0}', '\u{0}']), ('\u{a64c}', ['\u{a64d}', '\u{0}', '\u{0}']), - ('\u{a64e}', ['\u{a64f}', '\u{0}', '\u{0}']), ('\u{a650}', ['\u{a651}', '\u{0}', '\u{0}']), - ('\u{a652}', ['\u{a653}', '\u{0}', '\u{0}']), ('\u{a654}', ['\u{a655}', '\u{0}', '\u{0}']), - ('\u{a656}', ['\u{a657}', '\u{0}', '\u{0}']), ('\u{a658}', ['\u{a659}', '\u{0}', '\u{0}']), - ('\u{a65a}', ['\u{a65b}', '\u{0}', '\u{0}']), ('\u{a65c}', ['\u{a65d}', '\u{0}', '\u{0}']), - ('\u{a65e}', ['\u{a65f}', '\u{0}', '\u{0}']), ('\u{a660}', ['\u{a661}', '\u{0}', '\u{0}']), - ('\u{a662}', ['\u{a663}', '\u{0}', '\u{0}']), ('\u{a664}', ['\u{a665}', '\u{0}', '\u{0}']), - ('\u{a666}', ['\u{a667}', '\u{0}', '\u{0}']), ('\u{a668}', ['\u{a669}', '\u{0}', '\u{0}']), - ('\u{a66a}', ['\u{a66b}', '\u{0}', '\u{0}']), ('\u{a66c}', ['\u{a66d}', '\u{0}', '\u{0}']), - ('\u{a680}', ['\u{a681}', '\u{0}', '\u{0}']), ('\u{a682}', ['\u{a683}', '\u{0}', '\u{0}']), - ('\u{a684}', ['\u{a685}', '\u{0}', '\u{0}']), ('\u{a686}', ['\u{a687}', '\u{0}', '\u{0}']), - ('\u{a688}', ['\u{a689}', '\u{0}', '\u{0}']), ('\u{a68a}', ['\u{a68b}', '\u{0}', '\u{0}']), - ('\u{a68c}', ['\u{a68d}', '\u{0}', '\u{0}']), ('\u{a68e}', ['\u{a68f}', '\u{0}', '\u{0}']), - ('\u{a690}', ['\u{a691}', '\u{0}', '\u{0}']), ('\u{a692}', ['\u{a693}', '\u{0}', '\u{0}']), - ('\u{a694}', ['\u{a695}', '\u{0}', '\u{0}']), ('\u{a696}', ['\u{a697}', '\u{0}', '\u{0}']), - ('\u{a698}', ['\u{a699}', '\u{0}', '\u{0}']), ('\u{a69a}', ['\u{a69b}', '\u{0}', '\u{0}']), - ('\u{a722}', ['\u{a723}', '\u{0}', '\u{0}']), ('\u{a724}', ['\u{a725}', '\u{0}', '\u{0}']), - ('\u{a726}', ['\u{a727}', '\u{0}', '\u{0}']), ('\u{a728}', ['\u{a729}', '\u{0}', '\u{0}']), - ('\u{a72a}', ['\u{a72b}', '\u{0}', '\u{0}']), ('\u{a72c}', ['\u{a72d}', '\u{0}', '\u{0}']), - ('\u{a72e}', ['\u{a72f}', '\u{0}', '\u{0}']), ('\u{a732}', ['\u{a733}', '\u{0}', '\u{0}']), - ('\u{a734}', ['\u{a735}', '\u{0}', '\u{0}']), ('\u{a736}', ['\u{a737}', '\u{0}', '\u{0}']), - ('\u{a738}', ['\u{a739}', '\u{0}', '\u{0}']), ('\u{a73a}', ['\u{a73b}', '\u{0}', '\u{0}']), - ('\u{a73c}', ['\u{a73d}', '\u{0}', '\u{0}']), ('\u{a73e}', ['\u{a73f}', '\u{0}', '\u{0}']), - ('\u{a740}', ['\u{a741}', '\u{0}', '\u{0}']), ('\u{a742}', ['\u{a743}', '\u{0}', '\u{0}']), - ('\u{a744}', ['\u{a745}', '\u{0}', '\u{0}']), ('\u{a746}', ['\u{a747}', '\u{0}', '\u{0}']), - ('\u{a748}', ['\u{a749}', '\u{0}', '\u{0}']), ('\u{a74a}', ['\u{a74b}', '\u{0}', '\u{0}']), - ('\u{a74c}', ['\u{a74d}', '\u{0}', '\u{0}']), ('\u{a74e}', ['\u{a74f}', '\u{0}', '\u{0}']), - ('\u{a750}', ['\u{a751}', '\u{0}', '\u{0}']), ('\u{a752}', ['\u{a753}', '\u{0}', '\u{0}']), - ('\u{a754}', ['\u{a755}', '\u{0}', '\u{0}']), ('\u{a756}', ['\u{a757}', '\u{0}', '\u{0}']), - ('\u{a758}', ['\u{a759}', '\u{0}', '\u{0}']), ('\u{a75a}', ['\u{a75b}', '\u{0}', '\u{0}']), - ('\u{a75c}', ['\u{a75d}', '\u{0}', '\u{0}']), ('\u{a75e}', ['\u{a75f}', '\u{0}', '\u{0}']), - ('\u{a760}', ['\u{a761}', '\u{0}', '\u{0}']), ('\u{a762}', ['\u{a763}', '\u{0}', '\u{0}']), - ('\u{a764}', ['\u{a765}', '\u{0}', '\u{0}']), ('\u{a766}', ['\u{a767}', '\u{0}', '\u{0}']), - ('\u{a768}', ['\u{a769}', '\u{0}', '\u{0}']), ('\u{a76a}', ['\u{a76b}', '\u{0}', '\u{0}']), - ('\u{a76c}', ['\u{a76d}', '\u{0}', '\u{0}']), ('\u{a76e}', ['\u{a76f}', '\u{0}', '\u{0}']), - ('\u{a779}', ['\u{a77a}', '\u{0}', '\u{0}']), ('\u{a77b}', ['\u{a77c}', '\u{0}', '\u{0}']), - ('\u{a77d}', ['\u{1d79}', '\u{0}', '\u{0}']), ('\u{a77e}', ['\u{a77f}', '\u{0}', '\u{0}']), - ('\u{a780}', ['\u{a781}', '\u{0}', '\u{0}']), ('\u{a782}', ['\u{a783}', '\u{0}', '\u{0}']), - ('\u{a784}', ['\u{a785}', '\u{0}', '\u{0}']), ('\u{a786}', ['\u{a787}', '\u{0}', '\u{0}']), - ('\u{a78b}', ['\u{a78c}', '\u{0}', '\u{0}']), ('\u{a78d}', ['\u{265}', '\u{0}', '\u{0}']), - ('\u{a790}', ['\u{a791}', '\u{0}', '\u{0}']), ('\u{a792}', ['\u{a793}', '\u{0}', '\u{0}']), - ('\u{a796}', ['\u{a797}', '\u{0}', '\u{0}']), ('\u{a798}', ['\u{a799}', '\u{0}', '\u{0}']), - ('\u{a79a}', ['\u{a79b}', '\u{0}', '\u{0}']), ('\u{a79c}', ['\u{a79d}', '\u{0}', '\u{0}']), - ('\u{a79e}', ['\u{a79f}', '\u{0}', '\u{0}']), ('\u{a7a0}', ['\u{a7a1}', '\u{0}', '\u{0}']), - ('\u{a7a2}', ['\u{a7a3}', '\u{0}', '\u{0}']), ('\u{a7a4}', ['\u{a7a5}', '\u{0}', '\u{0}']), - ('\u{a7a6}', ['\u{a7a7}', '\u{0}', '\u{0}']), ('\u{a7a8}', ['\u{a7a9}', '\u{0}', '\u{0}']), - ('\u{a7aa}', ['\u{266}', '\u{0}', '\u{0}']), ('\u{a7ab}', ['\u{25c}', '\u{0}', '\u{0}']), - ('\u{a7ac}', ['\u{261}', '\u{0}', '\u{0}']), ('\u{a7ad}', ['\u{26c}', '\u{0}', '\u{0}']), - ('\u{a7ae}', ['\u{26a}', '\u{0}', '\u{0}']), ('\u{a7b0}', ['\u{29e}', '\u{0}', '\u{0}']), - ('\u{a7b1}', ['\u{287}', '\u{0}', '\u{0}']), ('\u{a7b2}', ['\u{29d}', '\u{0}', '\u{0}']), - ('\u{a7b3}', ['\u{ab53}', '\u{0}', '\u{0}']), ('\u{a7b4}', ['\u{a7b5}', '\u{0}', '\u{0}']), - ('\u{a7b6}', ['\u{a7b7}', '\u{0}', '\u{0}']), ('\u{a7b8}', ['\u{a7b9}', '\u{0}', '\u{0}']), - ('\u{a7ba}', ['\u{a7bb}', '\u{0}', '\u{0}']), ('\u{a7bc}', ['\u{a7bd}', '\u{0}', '\u{0}']), - ('\u{a7be}', ['\u{a7bf}', '\u{0}', '\u{0}']), ('\u{a7c2}', ['\u{a7c3}', '\u{0}', '\u{0}']), + ('\u{2c2e}', ['\u{2c5e}', '\u{0}', '\u{0}']), ('\u{2c2f}', ['\u{2c5f}', '\u{0}', '\u{0}']), + ('\u{2c60}', ['\u{2c61}', '\u{0}', '\u{0}']), ('\u{2c62}', ['\u{26b}', '\u{0}', '\u{0}']), + ('\u{2c63}', ['\u{1d7d}', '\u{0}', '\u{0}']), ('\u{2c64}', ['\u{27d}', '\u{0}', '\u{0}']), + ('\u{2c67}', ['\u{2c68}', '\u{0}', '\u{0}']), ('\u{2c69}', ['\u{2c6a}', '\u{0}', '\u{0}']), + ('\u{2c6b}', ['\u{2c6c}', '\u{0}', '\u{0}']), ('\u{2c6d}', ['\u{251}', '\u{0}', '\u{0}']), + ('\u{2c6e}', ['\u{271}', '\u{0}', '\u{0}']), ('\u{2c6f}', ['\u{250}', '\u{0}', '\u{0}']), + ('\u{2c70}', ['\u{252}', '\u{0}', '\u{0}']), ('\u{2c72}', ['\u{2c73}', '\u{0}', '\u{0}']), + ('\u{2c75}', ['\u{2c76}', '\u{0}', '\u{0}']), ('\u{2c7e}', ['\u{23f}', '\u{0}', '\u{0}']), + ('\u{2c7f}', ['\u{240}', '\u{0}', '\u{0}']), ('\u{2c80}', ['\u{2c81}', '\u{0}', '\u{0}']), + ('\u{2c82}', ['\u{2c83}', '\u{0}', '\u{0}']), ('\u{2c84}', ['\u{2c85}', '\u{0}', '\u{0}']), + ('\u{2c86}', ['\u{2c87}', '\u{0}', '\u{0}']), ('\u{2c88}', ['\u{2c89}', '\u{0}', '\u{0}']), + ('\u{2c8a}', ['\u{2c8b}', '\u{0}', '\u{0}']), ('\u{2c8c}', ['\u{2c8d}', '\u{0}', '\u{0}']), + ('\u{2c8e}', ['\u{2c8f}', '\u{0}', '\u{0}']), ('\u{2c90}', ['\u{2c91}', '\u{0}', '\u{0}']), + ('\u{2c92}', ['\u{2c93}', '\u{0}', '\u{0}']), ('\u{2c94}', ['\u{2c95}', '\u{0}', '\u{0}']), + ('\u{2c96}', ['\u{2c97}', '\u{0}', '\u{0}']), ('\u{2c98}', ['\u{2c99}', '\u{0}', '\u{0}']), + ('\u{2c9a}', ['\u{2c9b}', '\u{0}', '\u{0}']), ('\u{2c9c}', ['\u{2c9d}', '\u{0}', '\u{0}']), + ('\u{2c9e}', ['\u{2c9f}', '\u{0}', '\u{0}']), ('\u{2ca0}', ['\u{2ca1}', '\u{0}', '\u{0}']), + ('\u{2ca2}', ['\u{2ca3}', '\u{0}', '\u{0}']), ('\u{2ca4}', ['\u{2ca5}', '\u{0}', '\u{0}']), + ('\u{2ca6}', ['\u{2ca7}', '\u{0}', '\u{0}']), ('\u{2ca8}', ['\u{2ca9}', '\u{0}', '\u{0}']), + ('\u{2caa}', ['\u{2cab}', '\u{0}', '\u{0}']), ('\u{2cac}', ['\u{2cad}', '\u{0}', '\u{0}']), + ('\u{2cae}', ['\u{2caf}', '\u{0}', '\u{0}']), ('\u{2cb0}', ['\u{2cb1}', '\u{0}', '\u{0}']), + ('\u{2cb2}', ['\u{2cb3}', '\u{0}', '\u{0}']), ('\u{2cb4}', ['\u{2cb5}', '\u{0}', '\u{0}']), + ('\u{2cb6}', ['\u{2cb7}', '\u{0}', '\u{0}']), ('\u{2cb8}', ['\u{2cb9}', '\u{0}', '\u{0}']), + ('\u{2cba}', ['\u{2cbb}', '\u{0}', '\u{0}']), ('\u{2cbc}', ['\u{2cbd}', '\u{0}', '\u{0}']), + ('\u{2cbe}', ['\u{2cbf}', '\u{0}', '\u{0}']), ('\u{2cc0}', ['\u{2cc1}', '\u{0}', '\u{0}']), + ('\u{2cc2}', ['\u{2cc3}', '\u{0}', '\u{0}']), ('\u{2cc4}', ['\u{2cc5}', '\u{0}', '\u{0}']), + ('\u{2cc6}', ['\u{2cc7}', '\u{0}', '\u{0}']), ('\u{2cc8}', ['\u{2cc9}', '\u{0}', '\u{0}']), + ('\u{2cca}', ['\u{2ccb}', '\u{0}', '\u{0}']), ('\u{2ccc}', ['\u{2ccd}', '\u{0}', '\u{0}']), + ('\u{2cce}', ['\u{2ccf}', '\u{0}', '\u{0}']), ('\u{2cd0}', ['\u{2cd1}', '\u{0}', '\u{0}']), + ('\u{2cd2}', ['\u{2cd3}', '\u{0}', '\u{0}']), ('\u{2cd4}', ['\u{2cd5}', '\u{0}', '\u{0}']), + ('\u{2cd6}', ['\u{2cd7}', '\u{0}', '\u{0}']), ('\u{2cd8}', ['\u{2cd9}', '\u{0}', '\u{0}']), + ('\u{2cda}', ['\u{2cdb}', '\u{0}', '\u{0}']), ('\u{2cdc}', ['\u{2cdd}', '\u{0}', '\u{0}']), + ('\u{2cde}', ['\u{2cdf}', '\u{0}', '\u{0}']), ('\u{2ce0}', ['\u{2ce1}', '\u{0}', '\u{0}']), + ('\u{2ce2}', ['\u{2ce3}', '\u{0}', '\u{0}']), ('\u{2ceb}', ['\u{2cec}', '\u{0}', '\u{0}']), + ('\u{2ced}', ['\u{2cee}', '\u{0}', '\u{0}']), ('\u{2cf2}', ['\u{2cf3}', '\u{0}', '\u{0}']), + ('\u{a640}', ['\u{a641}', '\u{0}', '\u{0}']), ('\u{a642}', ['\u{a643}', '\u{0}', '\u{0}']), + ('\u{a644}', ['\u{a645}', '\u{0}', '\u{0}']), ('\u{a646}', ['\u{a647}', '\u{0}', '\u{0}']), + ('\u{a648}', ['\u{a649}', '\u{0}', '\u{0}']), ('\u{a64a}', ['\u{a64b}', '\u{0}', '\u{0}']), + ('\u{a64c}', ['\u{a64d}', '\u{0}', '\u{0}']), ('\u{a64e}', ['\u{a64f}', '\u{0}', '\u{0}']), + ('\u{a650}', ['\u{a651}', '\u{0}', '\u{0}']), ('\u{a652}', ['\u{a653}', '\u{0}', '\u{0}']), + ('\u{a654}', ['\u{a655}', '\u{0}', '\u{0}']), ('\u{a656}', ['\u{a657}', '\u{0}', '\u{0}']), + ('\u{a658}', ['\u{a659}', '\u{0}', '\u{0}']), ('\u{a65a}', ['\u{a65b}', '\u{0}', '\u{0}']), + ('\u{a65c}', ['\u{a65d}', '\u{0}', '\u{0}']), ('\u{a65e}', ['\u{a65f}', '\u{0}', '\u{0}']), + ('\u{a660}', ['\u{a661}', '\u{0}', '\u{0}']), ('\u{a662}', ['\u{a663}', '\u{0}', '\u{0}']), + ('\u{a664}', ['\u{a665}', '\u{0}', '\u{0}']), ('\u{a666}', ['\u{a667}', '\u{0}', '\u{0}']), + ('\u{a668}', ['\u{a669}', '\u{0}', '\u{0}']), ('\u{a66a}', ['\u{a66b}', '\u{0}', '\u{0}']), + ('\u{a66c}', ['\u{a66d}', '\u{0}', '\u{0}']), ('\u{a680}', ['\u{a681}', '\u{0}', '\u{0}']), + ('\u{a682}', ['\u{a683}', '\u{0}', '\u{0}']), ('\u{a684}', ['\u{a685}', '\u{0}', '\u{0}']), + ('\u{a686}', ['\u{a687}', '\u{0}', '\u{0}']), ('\u{a688}', ['\u{a689}', '\u{0}', '\u{0}']), + ('\u{a68a}', ['\u{a68b}', '\u{0}', '\u{0}']), ('\u{a68c}', ['\u{a68d}', '\u{0}', '\u{0}']), + ('\u{a68e}', ['\u{a68f}', '\u{0}', '\u{0}']), ('\u{a690}', ['\u{a691}', '\u{0}', '\u{0}']), + ('\u{a692}', ['\u{a693}', '\u{0}', '\u{0}']), ('\u{a694}', ['\u{a695}', '\u{0}', '\u{0}']), + ('\u{a696}', ['\u{a697}', '\u{0}', '\u{0}']), ('\u{a698}', ['\u{a699}', '\u{0}', '\u{0}']), + ('\u{a69a}', ['\u{a69b}', '\u{0}', '\u{0}']), ('\u{a722}', ['\u{a723}', '\u{0}', '\u{0}']), + ('\u{a724}', ['\u{a725}', '\u{0}', '\u{0}']), ('\u{a726}', ['\u{a727}', '\u{0}', '\u{0}']), + ('\u{a728}', ['\u{a729}', '\u{0}', '\u{0}']), ('\u{a72a}', ['\u{a72b}', '\u{0}', '\u{0}']), + ('\u{a72c}', ['\u{a72d}', '\u{0}', '\u{0}']), ('\u{a72e}', ['\u{a72f}', '\u{0}', '\u{0}']), + ('\u{a732}', ['\u{a733}', '\u{0}', '\u{0}']), ('\u{a734}', ['\u{a735}', '\u{0}', '\u{0}']), + ('\u{a736}', ['\u{a737}', '\u{0}', '\u{0}']), ('\u{a738}', ['\u{a739}', '\u{0}', '\u{0}']), + ('\u{a73a}', ['\u{a73b}', '\u{0}', '\u{0}']), ('\u{a73c}', ['\u{a73d}', '\u{0}', '\u{0}']), + ('\u{a73e}', ['\u{a73f}', '\u{0}', '\u{0}']), ('\u{a740}', ['\u{a741}', '\u{0}', '\u{0}']), + ('\u{a742}', ['\u{a743}', '\u{0}', '\u{0}']), ('\u{a744}', ['\u{a745}', '\u{0}', '\u{0}']), + ('\u{a746}', ['\u{a747}', '\u{0}', '\u{0}']), ('\u{a748}', ['\u{a749}', '\u{0}', '\u{0}']), + ('\u{a74a}', ['\u{a74b}', '\u{0}', '\u{0}']), ('\u{a74c}', ['\u{a74d}', '\u{0}', '\u{0}']), + ('\u{a74e}', ['\u{a74f}', '\u{0}', '\u{0}']), ('\u{a750}', ['\u{a751}', '\u{0}', '\u{0}']), + ('\u{a752}', ['\u{a753}', '\u{0}', '\u{0}']), ('\u{a754}', ['\u{a755}', '\u{0}', '\u{0}']), + ('\u{a756}', ['\u{a757}', '\u{0}', '\u{0}']), ('\u{a758}', ['\u{a759}', '\u{0}', '\u{0}']), + ('\u{a75a}', ['\u{a75b}', '\u{0}', '\u{0}']), ('\u{a75c}', ['\u{a75d}', '\u{0}', '\u{0}']), + ('\u{a75e}', ['\u{a75f}', '\u{0}', '\u{0}']), ('\u{a760}', ['\u{a761}', '\u{0}', '\u{0}']), + ('\u{a762}', ['\u{a763}', '\u{0}', '\u{0}']), ('\u{a764}', ['\u{a765}', '\u{0}', '\u{0}']), + ('\u{a766}', ['\u{a767}', '\u{0}', '\u{0}']), ('\u{a768}', ['\u{a769}', '\u{0}', '\u{0}']), + ('\u{a76a}', ['\u{a76b}', '\u{0}', '\u{0}']), ('\u{a76c}', ['\u{a76d}', '\u{0}', '\u{0}']), + ('\u{a76e}', ['\u{a76f}', '\u{0}', '\u{0}']), ('\u{a779}', ['\u{a77a}', '\u{0}', '\u{0}']), + ('\u{a77b}', ['\u{a77c}', '\u{0}', '\u{0}']), ('\u{a77d}', ['\u{1d79}', '\u{0}', '\u{0}']), + ('\u{a77e}', ['\u{a77f}', '\u{0}', '\u{0}']), ('\u{a780}', ['\u{a781}', '\u{0}', '\u{0}']), + ('\u{a782}', ['\u{a783}', '\u{0}', '\u{0}']), ('\u{a784}', ['\u{a785}', '\u{0}', '\u{0}']), + ('\u{a786}', ['\u{a787}', '\u{0}', '\u{0}']), ('\u{a78b}', ['\u{a78c}', '\u{0}', '\u{0}']), + ('\u{a78d}', ['\u{265}', '\u{0}', '\u{0}']), ('\u{a790}', ['\u{a791}', '\u{0}', '\u{0}']), + ('\u{a792}', ['\u{a793}', '\u{0}', '\u{0}']), ('\u{a796}', ['\u{a797}', '\u{0}', '\u{0}']), + ('\u{a798}', ['\u{a799}', '\u{0}', '\u{0}']), ('\u{a79a}', ['\u{a79b}', '\u{0}', '\u{0}']), + ('\u{a79c}', ['\u{a79d}', '\u{0}', '\u{0}']), ('\u{a79e}', ['\u{a79f}', '\u{0}', '\u{0}']), + ('\u{a7a0}', ['\u{a7a1}', '\u{0}', '\u{0}']), ('\u{a7a2}', ['\u{a7a3}', '\u{0}', '\u{0}']), + ('\u{a7a4}', ['\u{a7a5}', '\u{0}', '\u{0}']), ('\u{a7a6}', ['\u{a7a7}', '\u{0}', '\u{0}']), + ('\u{a7a8}', ['\u{a7a9}', '\u{0}', '\u{0}']), ('\u{a7aa}', ['\u{266}', '\u{0}', '\u{0}']), + ('\u{a7ab}', ['\u{25c}', '\u{0}', '\u{0}']), ('\u{a7ac}', ['\u{261}', '\u{0}', '\u{0}']), + ('\u{a7ad}', ['\u{26c}', '\u{0}', '\u{0}']), ('\u{a7ae}', ['\u{26a}', '\u{0}', '\u{0}']), + ('\u{a7b0}', ['\u{29e}', '\u{0}', '\u{0}']), ('\u{a7b1}', ['\u{287}', '\u{0}', '\u{0}']), + ('\u{a7b2}', ['\u{29d}', '\u{0}', '\u{0}']), ('\u{a7b3}', ['\u{ab53}', '\u{0}', '\u{0}']), + ('\u{a7b4}', ['\u{a7b5}', '\u{0}', '\u{0}']), ('\u{a7b6}', ['\u{a7b7}', '\u{0}', '\u{0}']), + ('\u{a7b8}', ['\u{a7b9}', '\u{0}', '\u{0}']), ('\u{a7ba}', ['\u{a7bb}', '\u{0}', '\u{0}']), + ('\u{a7bc}', ['\u{a7bd}', '\u{0}', '\u{0}']), ('\u{a7be}', ['\u{a7bf}', '\u{0}', '\u{0}']), + ('\u{a7c0}', ['\u{a7c1}', '\u{0}', '\u{0}']), ('\u{a7c2}', ['\u{a7c3}', '\u{0}', '\u{0}']), ('\u{a7c4}', ['\u{a794}', '\u{0}', '\u{0}']), ('\u{a7c5}', ['\u{282}', '\u{0}', '\u{0}']), ('\u{a7c6}', ['\u{1d8e}', '\u{0}', '\u{0}']), ('\u{a7c7}', ['\u{a7c8}', '\u{0}', '\u{0}']), - ('\u{a7c9}', ['\u{a7ca}', '\u{0}', '\u{0}']), ('\u{a7f5}', ['\u{a7f6}', '\u{0}', '\u{0}']), - ('\u{ff21}', ['\u{ff41}', '\u{0}', '\u{0}']), ('\u{ff22}', ['\u{ff42}', '\u{0}', '\u{0}']), - ('\u{ff23}', ['\u{ff43}', '\u{0}', '\u{0}']), ('\u{ff24}', ['\u{ff44}', '\u{0}', '\u{0}']), - ('\u{ff25}', ['\u{ff45}', '\u{0}', '\u{0}']), ('\u{ff26}', ['\u{ff46}', '\u{0}', '\u{0}']), - ('\u{ff27}', ['\u{ff47}', '\u{0}', '\u{0}']), ('\u{ff28}', ['\u{ff48}', '\u{0}', '\u{0}']), - ('\u{ff29}', ['\u{ff49}', '\u{0}', '\u{0}']), ('\u{ff2a}', ['\u{ff4a}', '\u{0}', '\u{0}']), - ('\u{ff2b}', ['\u{ff4b}', '\u{0}', '\u{0}']), ('\u{ff2c}', ['\u{ff4c}', '\u{0}', '\u{0}']), - ('\u{ff2d}', ['\u{ff4d}', '\u{0}', '\u{0}']), ('\u{ff2e}', ['\u{ff4e}', '\u{0}', '\u{0}']), - ('\u{ff2f}', ['\u{ff4f}', '\u{0}', '\u{0}']), ('\u{ff30}', ['\u{ff50}', '\u{0}', '\u{0}']), - ('\u{ff31}', ['\u{ff51}', '\u{0}', '\u{0}']), ('\u{ff32}', ['\u{ff52}', '\u{0}', '\u{0}']), - ('\u{ff33}', ['\u{ff53}', '\u{0}', '\u{0}']), ('\u{ff34}', ['\u{ff54}', '\u{0}', '\u{0}']), - ('\u{ff35}', ['\u{ff55}', '\u{0}', '\u{0}']), ('\u{ff36}', ['\u{ff56}', '\u{0}', '\u{0}']), - ('\u{ff37}', ['\u{ff57}', '\u{0}', '\u{0}']), ('\u{ff38}', ['\u{ff58}', '\u{0}', '\u{0}']), - ('\u{ff39}', ['\u{ff59}', '\u{0}', '\u{0}']), ('\u{ff3a}', ['\u{ff5a}', '\u{0}', '\u{0}']), + ('\u{a7c9}', ['\u{a7ca}', '\u{0}', '\u{0}']), ('\u{a7d0}', ['\u{a7d1}', '\u{0}', '\u{0}']), + ('\u{a7d6}', ['\u{a7d7}', '\u{0}', '\u{0}']), ('\u{a7d8}', ['\u{a7d9}', '\u{0}', '\u{0}']), + ('\u{a7f5}', ['\u{a7f6}', '\u{0}', '\u{0}']), ('\u{ff21}', ['\u{ff41}', '\u{0}', '\u{0}']), + ('\u{ff22}', ['\u{ff42}', '\u{0}', '\u{0}']), ('\u{ff23}', ['\u{ff43}', '\u{0}', '\u{0}']), + ('\u{ff24}', ['\u{ff44}', '\u{0}', '\u{0}']), ('\u{ff25}', ['\u{ff45}', '\u{0}', '\u{0}']), + ('\u{ff26}', ['\u{ff46}', '\u{0}', '\u{0}']), ('\u{ff27}', ['\u{ff47}', '\u{0}', '\u{0}']), + ('\u{ff28}', ['\u{ff48}', '\u{0}', '\u{0}']), ('\u{ff29}', ['\u{ff49}', '\u{0}', '\u{0}']), + ('\u{ff2a}', ['\u{ff4a}', '\u{0}', '\u{0}']), ('\u{ff2b}', ['\u{ff4b}', '\u{0}', '\u{0}']), + ('\u{ff2c}', ['\u{ff4c}', '\u{0}', '\u{0}']), ('\u{ff2d}', ['\u{ff4d}', '\u{0}', '\u{0}']), + ('\u{ff2e}', ['\u{ff4e}', '\u{0}', '\u{0}']), ('\u{ff2f}', ['\u{ff4f}', '\u{0}', '\u{0}']), + ('\u{ff30}', ['\u{ff50}', '\u{0}', '\u{0}']), ('\u{ff31}', ['\u{ff51}', '\u{0}', '\u{0}']), + ('\u{ff32}', ['\u{ff52}', '\u{0}', '\u{0}']), ('\u{ff33}', ['\u{ff53}', '\u{0}', '\u{0}']), + ('\u{ff34}', ['\u{ff54}', '\u{0}', '\u{0}']), ('\u{ff35}', ['\u{ff55}', '\u{0}', '\u{0}']), + ('\u{ff36}', ['\u{ff56}', '\u{0}', '\u{0}']), ('\u{ff37}', ['\u{ff57}', '\u{0}', '\u{0}']), + ('\u{ff38}', ['\u{ff58}', '\u{0}', '\u{0}']), ('\u{ff39}', ['\u{ff59}', '\u{0}', '\u{0}']), + ('\u{ff3a}', ['\u{ff5a}', '\u{0}', '\u{0}']), ('\u{10400}', ['\u{10428}', '\u{0}', '\u{0}']), ('\u{10401}', ['\u{10429}', '\u{0}', '\u{0}']), ('\u{10402}', ['\u{1042a}', '\u{0}', '\u{0}']), @@ -1234,6 +1250,41 @@ pub mod conversions { ('\u{104d1}', ['\u{104f9}', '\u{0}', '\u{0}']), ('\u{104d2}', ['\u{104fa}', '\u{0}', '\u{0}']), ('\u{104d3}', ['\u{104fb}', '\u{0}', '\u{0}']), + ('\u{10570}', ['\u{10597}', '\u{0}', '\u{0}']), + ('\u{10571}', ['\u{10598}', '\u{0}', '\u{0}']), + ('\u{10572}', ['\u{10599}', '\u{0}', '\u{0}']), + ('\u{10573}', ['\u{1059a}', '\u{0}', '\u{0}']), + ('\u{10574}', ['\u{1059b}', '\u{0}', '\u{0}']), + ('\u{10575}', ['\u{1059c}', '\u{0}', '\u{0}']), + ('\u{10576}', ['\u{1059d}', '\u{0}', '\u{0}']), + ('\u{10577}', ['\u{1059e}', '\u{0}', '\u{0}']), + ('\u{10578}', ['\u{1059f}', '\u{0}', '\u{0}']), + ('\u{10579}', ['\u{105a0}', '\u{0}', '\u{0}']), + ('\u{1057a}', ['\u{105a1}', '\u{0}', '\u{0}']), + ('\u{1057c}', ['\u{105a3}', '\u{0}', '\u{0}']), + ('\u{1057d}', ['\u{105a4}', '\u{0}', '\u{0}']), + ('\u{1057e}', ['\u{105a5}', '\u{0}', '\u{0}']), + ('\u{1057f}', ['\u{105a6}', '\u{0}', '\u{0}']), + ('\u{10580}', ['\u{105a7}', '\u{0}', '\u{0}']), + ('\u{10581}', ['\u{105a8}', '\u{0}', '\u{0}']), + ('\u{10582}', ['\u{105a9}', '\u{0}', '\u{0}']), + ('\u{10583}', ['\u{105aa}', '\u{0}', '\u{0}']), + ('\u{10584}', ['\u{105ab}', '\u{0}', '\u{0}']), + ('\u{10585}', ['\u{105ac}', '\u{0}', '\u{0}']), + ('\u{10586}', ['\u{105ad}', '\u{0}', '\u{0}']), + ('\u{10587}', ['\u{105ae}', '\u{0}', '\u{0}']), + ('\u{10588}', ['\u{105af}', '\u{0}', '\u{0}']), + ('\u{10589}', ['\u{105b0}', '\u{0}', '\u{0}']), + ('\u{1058a}', ['\u{105b1}', '\u{0}', '\u{0}']), + ('\u{1058c}', ['\u{105b3}', '\u{0}', '\u{0}']), + ('\u{1058d}', ['\u{105b4}', '\u{0}', '\u{0}']), + ('\u{1058e}', ['\u{105b5}', '\u{0}', '\u{0}']), + ('\u{1058f}', ['\u{105b6}', '\u{0}', '\u{0}']), + ('\u{10590}', ['\u{105b7}', '\u{0}', '\u{0}']), + ('\u{10591}', ['\u{105b8}', '\u{0}', '\u{0}']), + ('\u{10592}', ['\u{105b9}', '\u{0}', '\u{0}']), + ('\u{10594}', ['\u{105bb}', '\u{0}', '\u{0}']), + ('\u{10595}', ['\u{105bc}', '\u{0}', '\u{0}']), ('\u{10c80}', ['\u{10cc0}', '\u{0}', '\u{0}']), ('\u{10c81}', ['\u{10cc1}', '\u{0}', '\u{0}']), ('\u{10c82}', ['\u{10cc2}', '\u{0}', '\u{0}']), @@ -1892,154 +1943,157 @@ pub mod conversions { ('\u{2c59}', ['\u{2c29}', '\u{0}', '\u{0}']), ('\u{2c5a}', ['\u{2c2a}', '\u{0}', '\u{0}']), ('\u{2c5b}', ['\u{2c2b}', '\u{0}', '\u{0}']), ('\u{2c5c}', ['\u{2c2c}', '\u{0}', '\u{0}']), ('\u{2c5d}', ['\u{2c2d}', '\u{0}', '\u{0}']), ('\u{2c5e}', ['\u{2c2e}', '\u{0}', '\u{0}']), - ('\u{2c61}', ['\u{2c60}', '\u{0}', '\u{0}']), ('\u{2c65}', ['\u{23a}', '\u{0}', '\u{0}']), - ('\u{2c66}', ['\u{23e}', '\u{0}', '\u{0}']), ('\u{2c68}', ['\u{2c67}', '\u{0}', '\u{0}']), - ('\u{2c6a}', ['\u{2c69}', '\u{0}', '\u{0}']), ('\u{2c6c}', ['\u{2c6b}', '\u{0}', '\u{0}']), - ('\u{2c73}', ['\u{2c72}', '\u{0}', '\u{0}']), ('\u{2c76}', ['\u{2c75}', '\u{0}', '\u{0}']), - ('\u{2c81}', ['\u{2c80}', '\u{0}', '\u{0}']), ('\u{2c83}', ['\u{2c82}', '\u{0}', '\u{0}']), - ('\u{2c85}', ['\u{2c84}', '\u{0}', '\u{0}']), ('\u{2c87}', ['\u{2c86}', '\u{0}', '\u{0}']), - ('\u{2c89}', ['\u{2c88}', '\u{0}', '\u{0}']), ('\u{2c8b}', ['\u{2c8a}', '\u{0}', '\u{0}']), - ('\u{2c8d}', ['\u{2c8c}', '\u{0}', '\u{0}']), ('\u{2c8f}', ['\u{2c8e}', '\u{0}', '\u{0}']), - ('\u{2c91}', ['\u{2c90}', '\u{0}', '\u{0}']), ('\u{2c93}', ['\u{2c92}', '\u{0}', '\u{0}']), - ('\u{2c95}', ['\u{2c94}', '\u{0}', '\u{0}']), ('\u{2c97}', ['\u{2c96}', '\u{0}', '\u{0}']), - ('\u{2c99}', ['\u{2c98}', '\u{0}', '\u{0}']), ('\u{2c9b}', ['\u{2c9a}', '\u{0}', '\u{0}']), - ('\u{2c9d}', ['\u{2c9c}', '\u{0}', '\u{0}']), ('\u{2c9f}', ['\u{2c9e}', '\u{0}', '\u{0}']), - ('\u{2ca1}', ['\u{2ca0}', '\u{0}', '\u{0}']), ('\u{2ca3}', ['\u{2ca2}', '\u{0}', '\u{0}']), - ('\u{2ca5}', ['\u{2ca4}', '\u{0}', '\u{0}']), ('\u{2ca7}', ['\u{2ca6}', '\u{0}', '\u{0}']), - ('\u{2ca9}', ['\u{2ca8}', '\u{0}', '\u{0}']), ('\u{2cab}', ['\u{2caa}', '\u{0}', '\u{0}']), - ('\u{2cad}', ['\u{2cac}', '\u{0}', '\u{0}']), ('\u{2caf}', ['\u{2cae}', '\u{0}', '\u{0}']), - ('\u{2cb1}', ['\u{2cb0}', '\u{0}', '\u{0}']), ('\u{2cb3}', ['\u{2cb2}', '\u{0}', '\u{0}']), - ('\u{2cb5}', ['\u{2cb4}', '\u{0}', '\u{0}']), ('\u{2cb7}', ['\u{2cb6}', '\u{0}', '\u{0}']), - ('\u{2cb9}', ['\u{2cb8}', '\u{0}', '\u{0}']), ('\u{2cbb}', ['\u{2cba}', '\u{0}', '\u{0}']), - ('\u{2cbd}', ['\u{2cbc}', '\u{0}', '\u{0}']), ('\u{2cbf}', ['\u{2cbe}', '\u{0}', '\u{0}']), - ('\u{2cc1}', ['\u{2cc0}', '\u{0}', '\u{0}']), ('\u{2cc3}', ['\u{2cc2}', '\u{0}', '\u{0}']), - ('\u{2cc5}', ['\u{2cc4}', '\u{0}', '\u{0}']), ('\u{2cc7}', ['\u{2cc6}', '\u{0}', '\u{0}']), - ('\u{2cc9}', ['\u{2cc8}', '\u{0}', '\u{0}']), ('\u{2ccb}', ['\u{2cca}', '\u{0}', '\u{0}']), - ('\u{2ccd}', ['\u{2ccc}', '\u{0}', '\u{0}']), ('\u{2ccf}', ['\u{2cce}', '\u{0}', '\u{0}']), - ('\u{2cd1}', ['\u{2cd0}', '\u{0}', '\u{0}']), ('\u{2cd3}', ['\u{2cd2}', '\u{0}', '\u{0}']), - ('\u{2cd5}', ['\u{2cd4}', '\u{0}', '\u{0}']), ('\u{2cd7}', ['\u{2cd6}', '\u{0}', '\u{0}']), - ('\u{2cd9}', ['\u{2cd8}', '\u{0}', '\u{0}']), ('\u{2cdb}', ['\u{2cda}', '\u{0}', '\u{0}']), - ('\u{2cdd}', ['\u{2cdc}', '\u{0}', '\u{0}']), ('\u{2cdf}', ['\u{2cde}', '\u{0}', '\u{0}']), - ('\u{2ce1}', ['\u{2ce0}', '\u{0}', '\u{0}']), ('\u{2ce3}', ['\u{2ce2}', '\u{0}', '\u{0}']), - ('\u{2cec}', ['\u{2ceb}', '\u{0}', '\u{0}']), ('\u{2cee}', ['\u{2ced}', '\u{0}', '\u{0}']), - ('\u{2cf3}', ['\u{2cf2}', '\u{0}', '\u{0}']), ('\u{2d00}', ['\u{10a0}', '\u{0}', '\u{0}']), - ('\u{2d01}', ['\u{10a1}', '\u{0}', '\u{0}']), ('\u{2d02}', ['\u{10a2}', '\u{0}', '\u{0}']), - ('\u{2d03}', ['\u{10a3}', '\u{0}', '\u{0}']), ('\u{2d04}', ['\u{10a4}', '\u{0}', '\u{0}']), - ('\u{2d05}', ['\u{10a5}', '\u{0}', '\u{0}']), ('\u{2d06}', ['\u{10a6}', '\u{0}', '\u{0}']), - ('\u{2d07}', ['\u{10a7}', '\u{0}', '\u{0}']), ('\u{2d08}', ['\u{10a8}', '\u{0}', '\u{0}']), - ('\u{2d09}', ['\u{10a9}', '\u{0}', '\u{0}']), ('\u{2d0a}', ['\u{10aa}', '\u{0}', '\u{0}']), - ('\u{2d0b}', ['\u{10ab}', '\u{0}', '\u{0}']), ('\u{2d0c}', ['\u{10ac}', '\u{0}', '\u{0}']), - ('\u{2d0d}', ['\u{10ad}', '\u{0}', '\u{0}']), ('\u{2d0e}', ['\u{10ae}', '\u{0}', '\u{0}']), - ('\u{2d0f}', ['\u{10af}', '\u{0}', '\u{0}']), ('\u{2d10}', ['\u{10b0}', '\u{0}', '\u{0}']), - ('\u{2d11}', ['\u{10b1}', '\u{0}', '\u{0}']), ('\u{2d12}', ['\u{10b2}', '\u{0}', '\u{0}']), - ('\u{2d13}', ['\u{10b3}', '\u{0}', '\u{0}']), ('\u{2d14}', ['\u{10b4}', '\u{0}', '\u{0}']), - ('\u{2d15}', ['\u{10b5}', '\u{0}', '\u{0}']), ('\u{2d16}', ['\u{10b6}', '\u{0}', '\u{0}']), - ('\u{2d17}', ['\u{10b7}', '\u{0}', '\u{0}']), ('\u{2d18}', ['\u{10b8}', '\u{0}', '\u{0}']), - ('\u{2d19}', ['\u{10b9}', '\u{0}', '\u{0}']), ('\u{2d1a}', ['\u{10ba}', '\u{0}', '\u{0}']), - ('\u{2d1b}', ['\u{10bb}', '\u{0}', '\u{0}']), ('\u{2d1c}', ['\u{10bc}', '\u{0}', '\u{0}']), - ('\u{2d1d}', ['\u{10bd}', '\u{0}', '\u{0}']), ('\u{2d1e}', ['\u{10be}', '\u{0}', '\u{0}']), - ('\u{2d1f}', ['\u{10bf}', '\u{0}', '\u{0}']), ('\u{2d20}', ['\u{10c0}', '\u{0}', '\u{0}']), - ('\u{2d21}', ['\u{10c1}', '\u{0}', '\u{0}']), ('\u{2d22}', ['\u{10c2}', '\u{0}', '\u{0}']), - ('\u{2d23}', ['\u{10c3}', '\u{0}', '\u{0}']), ('\u{2d24}', ['\u{10c4}', '\u{0}', '\u{0}']), - ('\u{2d25}', ['\u{10c5}', '\u{0}', '\u{0}']), ('\u{2d27}', ['\u{10c7}', '\u{0}', '\u{0}']), - ('\u{2d2d}', ['\u{10cd}', '\u{0}', '\u{0}']), ('\u{a641}', ['\u{a640}', '\u{0}', '\u{0}']), - ('\u{a643}', ['\u{a642}', '\u{0}', '\u{0}']), ('\u{a645}', ['\u{a644}', '\u{0}', '\u{0}']), - ('\u{a647}', ['\u{a646}', '\u{0}', '\u{0}']), ('\u{a649}', ['\u{a648}', '\u{0}', '\u{0}']), - ('\u{a64b}', ['\u{a64a}', '\u{0}', '\u{0}']), ('\u{a64d}', ['\u{a64c}', '\u{0}', '\u{0}']), - ('\u{a64f}', ['\u{a64e}', '\u{0}', '\u{0}']), ('\u{a651}', ['\u{a650}', '\u{0}', '\u{0}']), - ('\u{a653}', ['\u{a652}', '\u{0}', '\u{0}']), ('\u{a655}', ['\u{a654}', '\u{0}', '\u{0}']), - ('\u{a657}', ['\u{a656}', '\u{0}', '\u{0}']), ('\u{a659}', ['\u{a658}', '\u{0}', '\u{0}']), - ('\u{a65b}', ['\u{a65a}', '\u{0}', '\u{0}']), ('\u{a65d}', ['\u{a65c}', '\u{0}', '\u{0}']), - ('\u{a65f}', ['\u{a65e}', '\u{0}', '\u{0}']), ('\u{a661}', ['\u{a660}', '\u{0}', '\u{0}']), - ('\u{a663}', ['\u{a662}', '\u{0}', '\u{0}']), ('\u{a665}', ['\u{a664}', '\u{0}', '\u{0}']), - ('\u{a667}', ['\u{a666}', '\u{0}', '\u{0}']), ('\u{a669}', ['\u{a668}', '\u{0}', '\u{0}']), - ('\u{a66b}', ['\u{a66a}', '\u{0}', '\u{0}']), ('\u{a66d}', ['\u{a66c}', '\u{0}', '\u{0}']), - ('\u{a681}', ['\u{a680}', '\u{0}', '\u{0}']), ('\u{a683}', ['\u{a682}', '\u{0}', '\u{0}']), - ('\u{a685}', ['\u{a684}', '\u{0}', '\u{0}']), ('\u{a687}', ['\u{a686}', '\u{0}', '\u{0}']), - ('\u{a689}', ['\u{a688}', '\u{0}', '\u{0}']), ('\u{a68b}', ['\u{a68a}', '\u{0}', '\u{0}']), - ('\u{a68d}', ['\u{a68c}', '\u{0}', '\u{0}']), ('\u{a68f}', ['\u{a68e}', '\u{0}', '\u{0}']), - ('\u{a691}', ['\u{a690}', '\u{0}', '\u{0}']), ('\u{a693}', ['\u{a692}', '\u{0}', '\u{0}']), - ('\u{a695}', ['\u{a694}', '\u{0}', '\u{0}']), ('\u{a697}', ['\u{a696}', '\u{0}', '\u{0}']), - ('\u{a699}', ['\u{a698}', '\u{0}', '\u{0}']), ('\u{a69b}', ['\u{a69a}', '\u{0}', '\u{0}']), - ('\u{a723}', ['\u{a722}', '\u{0}', '\u{0}']), ('\u{a725}', ['\u{a724}', '\u{0}', '\u{0}']), - ('\u{a727}', ['\u{a726}', '\u{0}', '\u{0}']), ('\u{a729}', ['\u{a728}', '\u{0}', '\u{0}']), - ('\u{a72b}', ['\u{a72a}', '\u{0}', '\u{0}']), ('\u{a72d}', ['\u{a72c}', '\u{0}', '\u{0}']), - ('\u{a72f}', ['\u{a72e}', '\u{0}', '\u{0}']), ('\u{a733}', ['\u{a732}', '\u{0}', '\u{0}']), - ('\u{a735}', ['\u{a734}', '\u{0}', '\u{0}']), ('\u{a737}', ['\u{a736}', '\u{0}', '\u{0}']), - ('\u{a739}', ['\u{a738}', '\u{0}', '\u{0}']), ('\u{a73b}', ['\u{a73a}', '\u{0}', '\u{0}']), - ('\u{a73d}', ['\u{a73c}', '\u{0}', '\u{0}']), ('\u{a73f}', ['\u{a73e}', '\u{0}', '\u{0}']), - ('\u{a741}', ['\u{a740}', '\u{0}', '\u{0}']), ('\u{a743}', ['\u{a742}', '\u{0}', '\u{0}']), - ('\u{a745}', ['\u{a744}', '\u{0}', '\u{0}']), ('\u{a747}', ['\u{a746}', '\u{0}', '\u{0}']), - ('\u{a749}', ['\u{a748}', '\u{0}', '\u{0}']), ('\u{a74b}', ['\u{a74a}', '\u{0}', '\u{0}']), - ('\u{a74d}', ['\u{a74c}', '\u{0}', '\u{0}']), ('\u{a74f}', ['\u{a74e}', '\u{0}', '\u{0}']), - ('\u{a751}', ['\u{a750}', '\u{0}', '\u{0}']), ('\u{a753}', ['\u{a752}', '\u{0}', '\u{0}']), - ('\u{a755}', ['\u{a754}', '\u{0}', '\u{0}']), ('\u{a757}', ['\u{a756}', '\u{0}', '\u{0}']), - ('\u{a759}', ['\u{a758}', '\u{0}', '\u{0}']), ('\u{a75b}', ['\u{a75a}', '\u{0}', '\u{0}']), - ('\u{a75d}', ['\u{a75c}', '\u{0}', '\u{0}']), ('\u{a75f}', ['\u{a75e}', '\u{0}', '\u{0}']), - ('\u{a761}', ['\u{a760}', '\u{0}', '\u{0}']), ('\u{a763}', ['\u{a762}', '\u{0}', '\u{0}']), - ('\u{a765}', ['\u{a764}', '\u{0}', '\u{0}']), ('\u{a767}', ['\u{a766}', '\u{0}', '\u{0}']), - ('\u{a769}', ['\u{a768}', '\u{0}', '\u{0}']), ('\u{a76b}', ['\u{a76a}', '\u{0}', '\u{0}']), - ('\u{a76d}', ['\u{a76c}', '\u{0}', '\u{0}']), ('\u{a76f}', ['\u{a76e}', '\u{0}', '\u{0}']), - ('\u{a77a}', ['\u{a779}', '\u{0}', '\u{0}']), ('\u{a77c}', ['\u{a77b}', '\u{0}', '\u{0}']), - ('\u{a77f}', ['\u{a77e}', '\u{0}', '\u{0}']), ('\u{a781}', ['\u{a780}', '\u{0}', '\u{0}']), - ('\u{a783}', ['\u{a782}', '\u{0}', '\u{0}']), ('\u{a785}', ['\u{a784}', '\u{0}', '\u{0}']), - ('\u{a787}', ['\u{a786}', '\u{0}', '\u{0}']), ('\u{a78c}', ['\u{a78b}', '\u{0}', '\u{0}']), - ('\u{a791}', ['\u{a790}', '\u{0}', '\u{0}']), ('\u{a793}', ['\u{a792}', '\u{0}', '\u{0}']), - ('\u{a794}', ['\u{a7c4}', '\u{0}', '\u{0}']), ('\u{a797}', ['\u{a796}', '\u{0}', '\u{0}']), - ('\u{a799}', ['\u{a798}', '\u{0}', '\u{0}']), ('\u{a79b}', ['\u{a79a}', '\u{0}', '\u{0}']), - ('\u{a79d}', ['\u{a79c}', '\u{0}', '\u{0}']), ('\u{a79f}', ['\u{a79e}', '\u{0}', '\u{0}']), - ('\u{a7a1}', ['\u{a7a0}', '\u{0}', '\u{0}']), ('\u{a7a3}', ['\u{a7a2}', '\u{0}', '\u{0}']), - ('\u{a7a5}', ['\u{a7a4}', '\u{0}', '\u{0}']), ('\u{a7a7}', ['\u{a7a6}', '\u{0}', '\u{0}']), - ('\u{a7a9}', ['\u{a7a8}', '\u{0}', '\u{0}']), ('\u{a7b5}', ['\u{a7b4}', '\u{0}', '\u{0}']), - ('\u{a7b7}', ['\u{a7b6}', '\u{0}', '\u{0}']), ('\u{a7b9}', ['\u{a7b8}', '\u{0}', '\u{0}']), - ('\u{a7bb}', ['\u{a7ba}', '\u{0}', '\u{0}']), ('\u{a7bd}', ['\u{a7bc}', '\u{0}', '\u{0}']), - ('\u{a7bf}', ['\u{a7be}', '\u{0}', '\u{0}']), ('\u{a7c3}', ['\u{a7c2}', '\u{0}', '\u{0}']), + ('\u{2c5f}', ['\u{2c2f}', '\u{0}', '\u{0}']), ('\u{2c61}', ['\u{2c60}', '\u{0}', '\u{0}']), + ('\u{2c65}', ['\u{23a}', '\u{0}', '\u{0}']), ('\u{2c66}', ['\u{23e}', '\u{0}', '\u{0}']), + ('\u{2c68}', ['\u{2c67}', '\u{0}', '\u{0}']), ('\u{2c6a}', ['\u{2c69}', '\u{0}', '\u{0}']), + ('\u{2c6c}', ['\u{2c6b}', '\u{0}', '\u{0}']), ('\u{2c73}', ['\u{2c72}', '\u{0}', '\u{0}']), + ('\u{2c76}', ['\u{2c75}', '\u{0}', '\u{0}']), ('\u{2c81}', ['\u{2c80}', '\u{0}', '\u{0}']), + ('\u{2c83}', ['\u{2c82}', '\u{0}', '\u{0}']), ('\u{2c85}', ['\u{2c84}', '\u{0}', '\u{0}']), + ('\u{2c87}', ['\u{2c86}', '\u{0}', '\u{0}']), ('\u{2c89}', ['\u{2c88}', '\u{0}', '\u{0}']), + ('\u{2c8b}', ['\u{2c8a}', '\u{0}', '\u{0}']), ('\u{2c8d}', ['\u{2c8c}', '\u{0}', '\u{0}']), + ('\u{2c8f}', ['\u{2c8e}', '\u{0}', '\u{0}']), ('\u{2c91}', ['\u{2c90}', '\u{0}', '\u{0}']), + ('\u{2c93}', ['\u{2c92}', '\u{0}', '\u{0}']), ('\u{2c95}', ['\u{2c94}', '\u{0}', '\u{0}']), + ('\u{2c97}', ['\u{2c96}', '\u{0}', '\u{0}']), ('\u{2c99}', ['\u{2c98}', '\u{0}', '\u{0}']), + ('\u{2c9b}', ['\u{2c9a}', '\u{0}', '\u{0}']), ('\u{2c9d}', ['\u{2c9c}', '\u{0}', '\u{0}']), + ('\u{2c9f}', ['\u{2c9e}', '\u{0}', '\u{0}']), ('\u{2ca1}', ['\u{2ca0}', '\u{0}', '\u{0}']), + ('\u{2ca3}', ['\u{2ca2}', '\u{0}', '\u{0}']), ('\u{2ca5}', ['\u{2ca4}', '\u{0}', '\u{0}']), + ('\u{2ca7}', ['\u{2ca6}', '\u{0}', '\u{0}']), ('\u{2ca9}', ['\u{2ca8}', '\u{0}', '\u{0}']), + ('\u{2cab}', ['\u{2caa}', '\u{0}', '\u{0}']), ('\u{2cad}', ['\u{2cac}', '\u{0}', '\u{0}']), + ('\u{2caf}', ['\u{2cae}', '\u{0}', '\u{0}']), ('\u{2cb1}', ['\u{2cb0}', '\u{0}', '\u{0}']), + ('\u{2cb3}', ['\u{2cb2}', '\u{0}', '\u{0}']), ('\u{2cb5}', ['\u{2cb4}', '\u{0}', '\u{0}']), + ('\u{2cb7}', ['\u{2cb6}', '\u{0}', '\u{0}']), ('\u{2cb9}', ['\u{2cb8}', '\u{0}', '\u{0}']), + ('\u{2cbb}', ['\u{2cba}', '\u{0}', '\u{0}']), ('\u{2cbd}', ['\u{2cbc}', '\u{0}', '\u{0}']), + ('\u{2cbf}', ['\u{2cbe}', '\u{0}', '\u{0}']), ('\u{2cc1}', ['\u{2cc0}', '\u{0}', '\u{0}']), + ('\u{2cc3}', ['\u{2cc2}', '\u{0}', '\u{0}']), ('\u{2cc5}', ['\u{2cc4}', '\u{0}', '\u{0}']), + ('\u{2cc7}', ['\u{2cc6}', '\u{0}', '\u{0}']), ('\u{2cc9}', ['\u{2cc8}', '\u{0}', '\u{0}']), + ('\u{2ccb}', ['\u{2cca}', '\u{0}', '\u{0}']), ('\u{2ccd}', ['\u{2ccc}', '\u{0}', '\u{0}']), + ('\u{2ccf}', ['\u{2cce}', '\u{0}', '\u{0}']), ('\u{2cd1}', ['\u{2cd0}', '\u{0}', '\u{0}']), + ('\u{2cd3}', ['\u{2cd2}', '\u{0}', '\u{0}']), ('\u{2cd5}', ['\u{2cd4}', '\u{0}', '\u{0}']), + ('\u{2cd7}', ['\u{2cd6}', '\u{0}', '\u{0}']), ('\u{2cd9}', ['\u{2cd8}', '\u{0}', '\u{0}']), + ('\u{2cdb}', ['\u{2cda}', '\u{0}', '\u{0}']), ('\u{2cdd}', ['\u{2cdc}', '\u{0}', '\u{0}']), + ('\u{2cdf}', ['\u{2cde}', '\u{0}', '\u{0}']), ('\u{2ce1}', ['\u{2ce0}', '\u{0}', '\u{0}']), + ('\u{2ce3}', ['\u{2ce2}', '\u{0}', '\u{0}']), ('\u{2cec}', ['\u{2ceb}', '\u{0}', '\u{0}']), + ('\u{2cee}', ['\u{2ced}', '\u{0}', '\u{0}']), ('\u{2cf3}', ['\u{2cf2}', '\u{0}', '\u{0}']), + ('\u{2d00}', ['\u{10a0}', '\u{0}', '\u{0}']), ('\u{2d01}', ['\u{10a1}', '\u{0}', '\u{0}']), + ('\u{2d02}', ['\u{10a2}', '\u{0}', '\u{0}']), ('\u{2d03}', ['\u{10a3}', '\u{0}', '\u{0}']), + ('\u{2d04}', ['\u{10a4}', '\u{0}', '\u{0}']), ('\u{2d05}', ['\u{10a5}', '\u{0}', '\u{0}']), + ('\u{2d06}', ['\u{10a6}', '\u{0}', '\u{0}']), ('\u{2d07}', ['\u{10a7}', '\u{0}', '\u{0}']), + ('\u{2d08}', ['\u{10a8}', '\u{0}', '\u{0}']), ('\u{2d09}', ['\u{10a9}', '\u{0}', '\u{0}']), + ('\u{2d0a}', ['\u{10aa}', '\u{0}', '\u{0}']), ('\u{2d0b}', ['\u{10ab}', '\u{0}', '\u{0}']), + ('\u{2d0c}', ['\u{10ac}', '\u{0}', '\u{0}']), ('\u{2d0d}', ['\u{10ad}', '\u{0}', '\u{0}']), + ('\u{2d0e}', ['\u{10ae}', '\u{0}', '\u{0}']), ('\u{2d0f}', ['\u{10af}', '\u{0}', '\u{0}']), + ('\u{2d10}', ['\u{10b0}', '\u{0}', '\u{0}']), ('\u{2d11}', ['\u{10b1}', '\u{0}', '\u{0}']), + ('\u{2d12}', ['\u{10b2}', '\u{0}', '\u{0}']), ('\u{2d13}', ['\u{10b3}', '\u{0}', '\u{0}']), + ('\u{2d14}', ['\u{10b4}', '\u{0}', '\u{0}']), ('\u{2d15}', ['\u{10b5}', '\u{0}', '\u{0}']), + ('\u{2d16}', ['\u{10b6}', '\u{0}', '\u{0}']), ('\u{2d17}', ['\u{10b7}', '\u{0}', '\u{0}']), + ('\u{2d18}', ['\u{10b8}', '\u{0}', '\u{0}']), ('\u{2d19}', ['\u{10b9}', '\u{0}', '\u{0}']), + ('\u{2d1a}', ['\u{10ba}', '\u{0}', '\u{0}']), ('\u{2d1b}', ['\u{10bb}', '\u{0}', '\u{0}']), + ('\u{2d1c}', ['\u{10bc}', '\u{0}', '\u{0}']), ('\u{2d1d}', ['\u{10bd}', '\u{0}', '\u{0}']), + ('\u{2d1e}', ['\u{10be}', '\u{0}', '\u{0}']), ('\u{2d1f}', ['\u{10bf}', '\u{0}', '\u{0}']), + ('\u{2d20}', ['\u{10c0}', '\u{0}', '\u{0}']), ('\u{2d21}', ['\u{10c1}', '\u{0}', '\u{0}']), + ('\u{2d22}', ['\u{10c2}', '\u{0}', '\u{0}']), ('\u{2d23}', ['\u{10c3}', '\u{0}', '\u{0}']), + ('\u{2d24}', ['\u{10c4}', '\u{0}', '\u{0}']), ('\u{2d25}', ['\u{10c5}', '\u{0}', '\u{0}']), + ('\u{2d27}', ['\u{10c7}', '\u{0}', '\u{0}']), ('\u{2d2d}', ['\u{10cd}', '\u{0}', '\u{0}']), + ('\u{a641}', ['\u{a640}', '\u{0}', '\u{0}']), ('\u{a643}', ['\u{a642}', '\u{0}', '\u{0}']), + ('\u{a645}', ['\u{a644}', '\u{0}', '\u{0}']), ('\u{a647}', ['\u{a646}', '\u{0}', '\u{0}']), + ('\u{a649}', ['\u{a648}', '\u{0}', '\u{0}']), ('\u{a64b}', ['\u{a64a}', '\u{0}', '\u{0}']), + ('\u{a64d}', ['\u{a64c}', '\u{0}', '\u{0}']), ('\u{a64f}', ['\u{a64e}', '\u{0}', '\u{0}']), + ('\u{a651}', ['\u{a650}', '\u{0}', '\u{0}']), ('\u{a653}', ['\u{a652}', '\u{0}', '\u{0}']), + ('\u{a655}', ['\u{a654}', '\u{0}', '\u{0}']), ('\u{a657}', ['\u{a656}', '\u{0}', '\u{0}']), + ('\u{a659}', ['\u{a658}', '\u{0}', '\u{0}']), ('\u{a65b}', ['\u{a65a}', '\u{0}', '\u{0}']), + ('\u{a65d}', ['\u{a65c}', '\u{0}', '\u{0}']), ('\u{a65f}', ['\u{a65e}', '\u{0}', '\u{0}']), + ('\u{a661}', ['\u{a660}', '\u{0}', '\u{0}']), ('\u{a663}', ['\u{a662}', '\u{0}', '\u{0}']), + ('\u{a665}', ['\u{a664}', '\u{0}', '\u{0}']), ('\u{a667}', ['\u{a666}', '\u{0}', '\u{0}']), + ('\u{a669}', ['\u{a668}', '\u{0}', '\u{0}']), ('\u{a66b}', ['\u{a66a}', '\u{0}', '\u{0}']), + ('\u{a66d}', ['\u{a66c}', '\u{0}', '\u{0}']), ('\u{a681}', ['\u{a680}', '\u{0}', '\u{0}']), + ('\u{a683}', ['\u{a682}', '\u{0}', '\u{0}']), ('\u{a685}', ['\u{a684}', '\u{0}', '\u{0}']), + ('\u{a687}', ['\u{a686}', '\u{0}', '\u{0}']), ('\u{a689}', ['\u{a688}', '\u{0}', '\u{0}']), + ('\u{a68b}', ['\u{a68a}', '\u{0}', '\u{0}']), ('\u{a68d}', ['\u{a68c}', '\u{0}', '\u{0}']), + ('\u{a68f}', ['\u{a68e}', '\u{0}', '\u{0}']), ('\u{a691}', ['\u{a690}', '\u{0}', '\u{0}']), + ('\u{a693}', ['\u{a692}', '\u{0}', '\u{0}']), ('\u{a695}', ['\u{a694}', '\u{0}', '\u{0}']), + ('\u{a697}', ['\u{a696}', '\u{0}', '\u{0}']), ('\u{a699}', ['\u{a698}', '\u{0}', '\u{0}']), + ('\u{a69b}', ['\u{a69a}', '\u{0}', '\u{0}']), ('\u{a723}', ['\u{a722}', '\u{0}', '\u{0}']), + ('\u{a725}', ['\u{a724}', '\u{0}', '\u{0}']), ('\u{a727}', ['\u{a726}', '\u{0}', '\u{0}']), + ('\u{a729}', ['\u{a728}', '\u{0}', '\u{0}']), ('\u{a72b}', ['\u{a72a}', '\u{0}', '\u{0}']), + ('\u{a72d}', ['\u{a72c}', '\u{0}', '\u{0}']), ('\u{a72f}', ['\u{a72e}', '\u{0}', '\u{0}']), + ('\u{a733}', ['\u{a732}', '\u{0}', '\u{0}']), ('\u{a735}', ['\u{a734}', '\u{0}', '\u{0}']), + ('\u{a737}', ['\u{a736}', '\u{0}', '\u{0}']), ('\u{a739}', ['\u{a738}', '\u{0}', '\u{0}']), + ('\u{a73b}', ['\u{a73a}', '\u{0}', '\u{0}']), ('\u{a73d}', ['\u{a73c}', '\u{0}', '\u{0}']), + ('\u{a73f}', ['\u{a73e}', '\u{0}', '\u{0}']), ('\u{a741}', ['\u{a740}', '\u{0}', '\u{0}']), + ('\u{a743}', ['\u{a742}', '\u{0}', '\u{0}']), ('\u{a745}', ['\u{a744}', '\u{0}', '\u{0}']), + ('\u{a747}', ['\u{a746}', '\u{0}', '\u{0}']), ('\u{a749}', ['\u{a748}', '\u{0}', '\u{0}']), + ('\u{a74b}', ['\u{a74a}', '\u{0}', '\u{0}']), ('\u{a74d}', ['\u{a74c}', '\u{0}', '\u{0}']), + ('\u{a74f}', ['\u{a74e}', '\u{0}', '\u{0}']), ('\u{a751}', ['\u{a750}', '\u{0}', '\u{0}']), + ('\u{a753}', ['\u{a752}', '\u{0}', '\u{0}']), ('\u{a755}', ['\u{a754}', '\u{0}', '\u{0}']), + ('\u{a757}', ['\u{a756}', '\u{0}', '\u{0}']), ('\u{a759}', ['\u{a758}', '\u{0}', '\u{0}']), + ('\u{a75b}', ['\u{a75a}', '\u{0}', '\u{0}']), ('\u{a75d}', ['\u{a75c}', '\u{0}', '\u{0}']), + ('\u{a75f}', ['\u{a75e}', '\u{0}', '\u{0}']), ('\u{a761}', ['\u{a760}', '\u{0}', '\u{0}']), + ('\u{a763}', ['\u{a762}', '\u{0}', '\u{0}']), ('\u{a765}', ['\u{a764}', '\u{0}', '\u{0}']), + ('\u{a767}', ['\u{a766}', '\u{0}', '\u{0}']), ('\u{a769}', ['\u{a768}', '\u{0}', '\u{0}']), + ('\u{a76b}', ['\u{a76a}', '\u{0}', '\u{0}']), ('\u{a76d}', ['\u{a76c}', '\u{0}', '\u{0}']), + ('\u{a76f}', ['\u{a76e}', '\u{0}', '\u{0}']), ('\u{a77a}', ['\u{a779}', '\u{0}', '\u{0}']), + ('\u{a77c}', ['\u{a77b}', '\u{0}', '\u{0}']), ('\u{a77f}', ['\u{a77e}', '\u{0}', '\u{0}']), + ('\u{a781}', ['\u{a780}', '\u{0}', '\u{0}']), ('\u{a783}', ['\u{a782}', '\u{0}', '\u{0}']), + ('\u{a785}', ['\u{a784}', '\u{0}', '\u{0}']), ('\u{a787}', ['\u{a786}', '\u{0}', '\u{0}']), + ('\u{a78c}', ['\u{a78b}', '\u{0}', '\u{0}']), ('\u{a791}', ['\u{a790}', '\u{0}', '\u{0}']), + ('\u{a793}', ['\u{a792}', '\u{0}', '\u{0}']), ('\u{a794}', ['\u{a7c4}', '\u{0}', '\u{0}']), + ('\u{a797}', ['\u{a796}', '\u{0}', '\u{0}']), ('\u{a799}', ['\u{a798}', '\u{0}', '\u{0}']), + ('\u{a79b}', ['\u{a79a}', '\u{0}', '\u{0}']), ('\u{a79d}', ['\u{a79c}', '\u{0}', '\u{0}']), + ('\u{a79f}', ['\u{a79e}', '\u{0}', '\u{0}']), ('\u{a7a1}', ['\u{a7a0}', '\u{0}', '\u{0}']), + ('\u{a7a3}', ['\u{a7a2}', '\u{0}', '\u{0}']), ('\u{a7a5}', ['\u{a7a4}', '\u{0}', '\u{0}']), + ('\u{a7a7}', ['\u{a7a6}', '\u{0}', '\u{0}']), ('\u{a7a9}', ['\u{a7a8}', '\u{0}', '\u{0}']), + ('\u{a7b5}', ['\u{a7b4}', '\u{0}', '\u{0}']), ('\u{a7b7}', ['\u{a7b6}', '\u{0}', '\u{0}']), + ('\u{a7b9}', ['\u{a7b8}', '\u{0}', '\u{0}']), ('\u{a7bb}', ['\u{a7ba}', '\u{0}', '\u{0}']), + ('\u{a7bd}', ['\u{a7bc}', '\u{0}', '\u{0}']), ('\u{a7bf}', ['\u{a7be}', '\u{0}', '\u{0}']), + ('\u{a7c1}', ['\u{a7c0}', '\u{0}', '\u{0}']), ('\u{a7c3}', ['\u{a7c2}', '\u{0}', '\u{0}']), ('\u{a7c8}', ['\u{a7c7}', '\u{0}', '\u{0}']), ('\u{a7ca}', ['\u{a7c9}', '\u{0}', '\u{0}']), - ('\u{a7f6}', ['\u{a7f5}', '\u{0}', '\u{0}']), ('\u{ab53}', ['\u{a7b3}', '\u{0}', '\u{0}']), - ('\u{ab70}', ['\u{13a0}', '\u{0}', '\u{0}']), ('\u{ab71}', ['\u{13a1}', '\u{0}', '\u{0}']), - ('\u{ab72}', ['\u{13a2}', '\u{0}', '\u{0}']), ('\u{ab73}', ['\u{13a3}', '\u{0}', '\u{0}']), - ('\u{ab74}', ['\u{13a4}', '\u{0}', '\u{0}']), ('\u{ab75}', ['\u{13a5}', '\u{0}', '\u{0}']), - ('\u{ab76}', ['\u{13a6}', '\u{0}', '\u{0}']), ('\u{ab77}', ['\u{13a7}', '\u{0}', '\u{0}']), - ('\u{ab78}', ['\u{13a8}', '\u{0}', '\u{0}']), ('\u{ab79}', ['\u{13a9}', '\u{0}', '\u{0}']), - ('\u{ab7a}', ['\u{13aa}', '\u{0}', '\u{0}']), ('\u{ab7b}', ['\u{13ab}', '\u{0}', '\u{0}']), - ('\u{ab7c}', ['\u{13ac}', '\u{0}', '\u{0}']), ('\u{ab7d}', ['\u{13ad}', '\u{0}', '\u{0}']), - ('\u{ab7e}', ['\u{13ae}', '\u{0}', '\u{0}']), ('\u{ab7f}', ['\u{13af}', '\u{0}', '\u{0}']), - ('\u{ab80}', ['\u{13b0}', '\u{0}', '\u{0}']), ('\u{ab81}', ['\u{13b1}', '\u{0}', '\u{0}']), - ('\u{ab82}', ['\u{13b2}', '\u{0}', '\u{0}']), ('\u{ab83}', ['\u{13b3}', '\u{0}', '\u{0}']), - ('\u{ab84}', ['\u{13b4}', '\u{0}', '\u{0}']), ('\u{ab85}', ['\u{13b5}', '\u{0}', '\u{0}']), - ('\u{ab86}', ['\u{13b6}', '\u{0}', '\u{0}']), ('\u{ab87}', ['\u{13b7}', '\u{0}', '\u{0}']), - ('\u{ab88}', ['\u{13b8}', '\u{0}', '\u{0}']), ('\u{ab89}', ['\u{13b9}', '\u{0}', '\u{0}']), - ('\u{ab8a}', ['\u{13ba}', '\u{0}', '\u{0}']), ('\u{ab8b}', ['\u{13bb}', '\u{0}', '\u{0}']), - ('\u{ab8c}', ['\u{13bc}', '\u{0}', '\u{0}']), ('\u{ab8d}', ['\u{13bd}', '\u{0}', '\u{0}']), - ('\u{ab8e}', ['\u{13be}', '\u{0}', '\u{0}']), ('\u{ab8f}', ['\u{13bf}', '\u{0}', '\u{0}']), - ('\u{ab90}', ['\u{13c0}', '\u{0}', '\u{0}']), ('\u{ab91}', ['\u{13c1}', '\u{0}', '\u{0}']), - ('\u{ab92}', ['\u{13c2}', '\u{0}', '\u{0}']), ('\u{ab93}', ['\u{13c3}', '\u{0}', '\u{0}']), - ('\u{ab94}', ['\u{13c4}', '\u{0}', '\u{0}']), ('\u{ab95}', ['\u{13c5}', '\u{0}', '\u{0}']), - ('\u{ab96}', ['\u{13c6}', '\u{0}', '\u{0}']), ('\u{ab97}', ['\u{13c7}', '\u{0}', '\u{0}']), - ('\u{ab98}', ['\u{13c8}', '\u{0}', '\u{0}']), ('\u{ab99}', ['\u{13c9}', '\u{0}', '\u{0}']), - ('\u{ab9a}', ['\u{13ca}', '\u{0}', '\u{0}']), ('\u{ab9b}', ['\u{13cb}', '\u{0}', '\u{0}']), - ('\u{ab9c}', ['\u{13cc}', '\u{0}', '\u{0}']), ('\u{ab9d}', ['\u{13cd}', '\u{0}', '\u{0}']), - ('\u{ab9e}', ['\u{13ce}', '\u{0}', '\u{0}']), ('\u{ab9f}', ['\u{13cf}', '\u{0}', '\u{0}']), - ('\u{aba0}', ['\u{13d0}', '\u{0}', '\u{0}']), ('\u{aba1}', ['\u{13d1}', '\u{0}', '\u{0}']), - ('\u{aba2}', ['\u{13d2}', '\u{0}', '\u{0}']), ('\u{aba3}', ['\u{13d3}', '\u{0}', '\u{0}']), - ('\u{aba4}', ['\u{13d4}', '\u{0}', '\u{0}']), ('\u{aba5}', ['\u{13d5}', '\u{0}', '\u{0}']), - ('\u{aba6}', ['\u{13d6}', '\u{0}', '\u{0}']), ('\u{aba7}', ['\u{13d7}', '\u{0}', '\u{0}']), - ('\u{aba8}', ['\u{13d8}', '\u{0}', '\u{0}']), ('\u{aba9}', ['\u{13d9}', '\u{0}', '\u{0}']), - ('\u{abaa}', ['\u{13da}', '\u{0}', '\u{0}']), ('\u{abab}', ['\u{13db}', '\u{0}', '\u{0}']), - ('\u{abac}', ['\u{13dc}', '\u{0}', '\u{0}']), ('\u{abad}', ['\u{13dd}', '\u{0}', '\u{0}']), - ('\u{abae}', ['\u{13de}', '\u{0}', '\u{0}']), ('\u{abaf}', ['\u{13df}', '\u{0}', '\u{0}']), - ('\u{abb0}', ['\u{13e0}', '\u{0}', '\u{0}']), ('\u{abb1}', ['\u{13e1}', '\u{0}', '\u{0}']), - ('\u{abb2}', ['\u{13e2}', '\u{0}', '\u{0}']), ('\u{abb3}', ['\u{13e3}', '\u{0}', '\u{0}']), - ('\u{abb4}', ['\u{13e4}', '\u{0}', '\u{0}']), ('\u{abb5}', ['\u{13e5}', '\u{0}', '\u{0}']), - ('\u{abb6}', ['\u{13e6}', '\u{0}', '\u{0}']), ('\u{abb7}', ['\u{13e7}', '\u{0}', '\u{0}']), - ('\u{abb8}', ['\u{13e8}', '\u{0}', '\u{0}']), ('\u{abb9}', ['\u{13e9}', '\u{0}', '\u{0}']), - ('\u{abba}', ['\u{13ea}', '\u{0}', '\u{0}']), ('\u{abbb}', ['\u{13eb}', '\u{0}', '\u{0}']), - ('\u{abbc}', ['\u{13ec}', '\u{0}', '\u{0}']), ('\u{abbd}', ['\u{13ed}', '\u{0}', '\u{0}']), - ('\u{abbe}', ['\u{13ee}', '\u{0}', '\u{0}']), ('\u{abbf}', ['\u{13ef}', '\u{0}', '\u{0}']), - ('\u{fb00}', ['F', 'F', '\u{0}']), ('\u{fb01}', ['F', 'I', '\u{0}']), - ('\u{fb02}', ['F', 'L', '\u{0}']), ('\u{fb03}', ['F', 'F', 'I']), - ('\u{fb04}', ['F', 'F', 'L']), ('\u{fb05}', ['S', 'T', '\u{0}']), - ('\u{fb06}', ['S', 'T', '\u{0}']), ('\u{fb13}', ['\u{544}', '\u{546}', '\u{0}']), + ('\u{a7d1}', ['\u{a7d0}', '\u{0}', '\u{0}']), ('\u{a7d7}', ['\u{a7d6}', '\u{0}', '\u{0}']), + ('\u{a7d9}', ['\u{a7d8}', '\u{0}', '\u{0}']), ('\u{a7f6}', ['\u{a7f5}', '\u{0}', '\u{0}']), + ('\u{ab53}', ['\u{a7b3}', '\u{0}', '\u{0}']), ('\u{ab70}', ['\u{13a0}', '\u{0}', '\u{0}']), + ('\u{ab71}', ['\u{13a1}', '\u{0}', '\u{0}']), ('\u{ab72}', ['\u{13a2}', '\u{0}', '\u{0}']), + ('\u{ab73}', ['\u{13a3}', '\u{0}', '\u{0}']), ('\u{ab74}', ['\u{13a4}', '\u{0}', '\u{0}']), + ('\u{ab75}', ['\u{13a5}', '\u{0}', '\u{0}']), ('\u{ab76}', ['\u{13a6}', '\u{0}', '\u{0}']), + ('\u{ab77}', ['\u{13a7}', '\u{0}', '\u{0}']), ('\u{ab78}', ['\u{13a8}', '\u{0}', '\u{0}']), + ('\u{ab79}', ['\u{13a9}', '\u{0}', '\u{0}']), ('\u{ab7a}', ['\u{13aa}', '\u{0}', '\u{0}']), + ('\u{ab7b}', ['\u{13ab}', '\u{0}', '\u{0}']), ('\u{ab7c}', ['\u{13ac}', '\u{0}', '\u{0}']), + ('\u{ab7d}', ['\u{13ad}', '\u{0}', '\u{0}']), ('\u{ab7e}', ['\u{13ae}', '\u{0}', '\u{0}']), + ('\u{ab7f}', ['\u{13af}', '\u{0}', '\u{0}']), ('\u{ab80}', ['\u{13b0}', '\u{0}', '\u{0}']), + ('\u{ab81}', ['\u{13b1}', '\u{0}', '\u{0}']), ('\u{ab82}', ['\u{13b2}', '\u{0}', '\u{0}']), + ('\u{ab83}', ['\u{13b3}', '\u{0}', '\u{0}']), ('\u{ab84}', ['\u{13b4}', '\u{0}', '\u{0}']), + ('\u{ab85}', ['\u{13b5}', '\u{0}', '\u{0}']), ('\u{ab86}', ['\u{13b6}', '\u{0}', '\u{0}']), + ('\u{ab87}', ['\u{13b7}', '\u{0}', '\u{0}']), ('\u{ab88}', ['\u{13b8}', '\u{0}', '\u{0}']), + ('\u{ab89}', ['\u{13b9}', '\u{0}', '\u{0}']), ('\u{ab8a}', ['\u{13ba}', '\u{0}', '\u{0}']), + ('\u{ab8b}', ['\u{13bb}', '\u{0}', '\u{0}']), ('\u{ab8c}', ['\u{13bc}', '\u{0}', '\u{0}']), + ('\u{ab8d}', ['\u{13bd}', '\u{0}', '\u{0}']), ('\u{ab8e}', ['\u{13be}', '\u{0}', '\u{0}']), + ('\u{ab8f}', ['\u{13bf}', '\u{0}', '\u{0}']), ('\u{ab90}', ['\u{13c0}', '\u{0}', '\u{0}']), + ('\u{ab91}', ['\u{13c1}', '\u{0}', '\u{0}']), ('\u{ab92}', ['\u{13c2}', '\u{0}', '\u{0}']), + ('\u{ab93}', ['\u{13c3}', '\u{0}', '\u{0}']), ('\u{ab94}', ['\u{13c4}', '\u{0}', '\u{0}']), + ('\u{ab95}', ['\u{13c5}', '\u{0}', '\u{0}']), ('\u{ab96}', ['\u{13c6}', '\u{0}', '\u{0}']), + ('\u{ab97}', ['\u{13c7}', '\u{0}', '\u{0}']), ('\u{ab98}', ['\u{13c8}', '\u{0}', '\u{0}']), + ('\u{ab99}', ['\u{13c9}', '\u{0}', '\u{0}']), ('\u{ab9a}', ['\u{13ca}', '\u{0}', '\u{0}']), + ('\u{ab9b}', ['\u{13cb}', '\u{0}', '\u{0}']), ('\u{ab9c}', ['\u{13cc}', '\u{0}', '\u{0}']), + ('\u{ab9d}', ['\u{13cd}', '\u{0}', '\u{0}']), ('\u{ab9e}', ['\u{13ce}', '\u{0}', '\u{0}']), + ('\u{ab9f}', ['\u{13cf}', '\u{0}', '\u{0}']), ('\u{aba0}', ['\u{13d0}', '\u{0}', '\u{0}']), + ('\u{aba1}', ['\u{13d1}', '\u{0}', '\u{0}']), ('\u{aba2}', ['\u{13d2}', '\u{0}', '\u{0}']), + ('\u{aba3}', ['\u{13d3}', '\u{0}', '\u{0}']), ('\u{aba4}', ['\u{13d4}', '\u{0}', '\u{0}']), + ('\u{aba5}', ['\u{13d5}', '\u{0}', '\u{0}']), ('\u{aba6}', ['\u{13d6}', '\u{0}', '\u{0}']), + ('\u{aba7}', ['\u{13d7}', '\u{0}', '\u{0}']), ('\u{aba8}', ['\u{13d8}', '\u{0}', '\u{0}']), + ('\u{aba9}', ['\u{13d9}', '\u{0}', '\u{0}']), ('\u{abaa}', ['\u{13da}', '\u{0}', '\u{0}']), + ('\u{abab}', ['\u{13db}', '\u{0}', '\u{0}']), ('\u{abac}', ['\u{13dc}', '\u{0}', '\u{0}']), + ('\u{abad}', ['\u{13dd}', '\u{0}', '\u{0}']), ('\u{abae}', ['\u{13de}', '\u{0}', '\u{0}']), + ('\u{abaf}', ['\u{13df}', '\u{0}', '\u{0}']), ('\u{abb0}', ['\u{13e0}', '\u{0}', '\u{0}']), + ('\u{abb1}', ['\u{13e1}', '\u{0}', '\u{0}']), ('\u{abb2}', ['\u{13e2}', '\u{0}', '\u{0}']), + ('\u{abb3}', ['\u{13e3}', '\u{0}', '\u{0}']), ('\u{abb4}', ['\u{13e4}', '\u{0}', '\u{0}']), + ('\u{abb5}', ['\u{13e5}', '\u{0}', '\u{0}']), ('\u{abb6}', ['\u{13e6}', '\u{0}', '\u{0}']), + ('\u{abb7}', ['\u{13e7}', '\u{0}', '\u{0}']), ('\u{abb8}', ['\u{13e8}', '\u{0}', '\u{0}']), + ('\u{abb9}', ['\u{13e9}', '\u{0}', '\u{0}']), ('\u{abba}', ['\u{13ea}', '\u{0}', '\u{0}']), + ('\u{abbb}', ['\u{13eb}', '\u{0}', '\u{0}']), ('\u{abbc}', ['\u{13ec}', '\u{0}', '\u{0}']), + ('\u{abbd}', ['\u{13ed}', '\u{0}', '\u{0}']), ('\u{abbe}', ['\u{13ee}', '\u{0}', '\u{0}']), + ('\u{abbf}', ['\u{13ef}', '\u{0}', '\u{0}']), ('\u{fb00}', ['F', 'F', '\u{0}']), + ('\u{fb01}', ['F', 'I', '\u{0}']), ('\u{fb02}', ['F', 'L', '\u{0}']), + ('\u{fb03}', ['F', 'F', 'I']), ('\u{fb04}', ['F', 'F', 'L']), + ('\u{fb05}', ['S', 'T', '\u{0}']), ('\u{fb06}', ['S', 'T', '\u{0}']), + ('\u{fb13}', ['\u{544}', '\u{546}', '\u{0}']), ('\u{fb14}', ['\u{544}', '\u{535}', '\u{0}']), ('\u{fb15}', ['\u{544}', '\u{53b}', '\u{0}']), ('\u{fb16}', ['\u{54e}', '\u{546}', '\u{0}']), @@ -2133,6 +2187,41 @@ pub mod conversions { ('\u{104f9}', ['\u{104d1}', '\u{0}', '\u{0}']), ('\u{104fa}', ['\u{104d2}', '\u{0}', '\u{0}']), ('\u{104fb}', ['\u{104d3}', '\u{0}', '\u{0}']), + ('\u{10597}', ['\u{10570}', '\u{0}', '\u{0}']), + ('\u{10598}', ['\u{10571}', '\u{0}', '\u{0}']), + ('\u{10599}', ['\u{10572}', '\u{0}', '\u{0}']), + ('\u{1059a}', ['\u{10573}', '\u{0}', '\u{0}']), + ('\u{1059b}', ['\u{10574}', '\u{0}', '\u{0}']), + ('\u{1059c}', ['\u{10575}', '\u{0}', '\u{0}']), + ('\u{1059d}', ['\u{10576}', '\u{0}', '\u{0}']), + ('\u{1059e}', ['\u{10577}', '\u{0}', '\u{0}']), + ('\u{1059f}', ['\u{10578}', '\u{0}', '\u{0}']), + ('\u{105a0}', ['\u{10579}', '\u{0}', '\u{0}']), + ('\u{105a1}', ['\u{1057a}', '\u{0}', '\u{0}']), + ('\u{105a3}', ['\u{1057c}', '\u{0}', '\u{0}']), + ('\u{105a4}', ['\u{1057d}', '\u{0}', '\u{0}']), + ('\u{105a5}', ['\u{1057e}', '\u{0}', '\u{0}']), + ('\u{105a6}', ['\u{1057f}', '\u{0}', '\u{0}']), + ('\u{105a7}', ['\u{10580}', '\u{0}', '\u{0}']), + ('\u{105a8}', ['\u{10581}', '\u{0}', '\u{0}']), + ('\u{105a9}', ['\u{10582}', '\u{0}', '\u{0}']), + ('\u{105aa}', ['\u{10583}', '\u{0}', '\u{0}']), + ('\u{105ab}', ['\u{10584}', '\u{0}', '\u{0}']), + ('\u{105ac}', ['\u{10585}', '\u{0}', '\u{0}']), + ('\u{105ad}', ['\u{10586}', '\u{0}', '\u{0}']), + ('\u{105ae}', ['\u{10587}', '\u{0}', '\u{0}']), + ('\u{105af}', ['\u{10588}', '\u{0}', '\u{0}']), + ('\u{105b0}', ['\u{10589}', '\u{0}', '\u{0}']), + ('\u{105b1}', ['\u{1058a}', '\u{0}', '\u{0}']), + ('\u{105b3}', ['\u{1058c}', '\u{0}', '\u{0}']), + ('\u{105b4}', ['\u{1058d}', '\u{0}', '\u{0}']), + ('\u{105b5}', ['\u{1058e}', '\u{0}', '\u{0}']), + ('\u{105b6}', ['\u{1058f}', '\u{0}', '\u{0}']), + ('\u{105b7}', ['\u{10590}', '\u{0}', '\u{0}']), + ('\u{105b8}', ['\u{10591}', '\u{0}', '\u{0}']), + ('\u{105b9}', ['\u{10592}', '\u{0}', '\u{0}']), + ('\u{105bb}', ['\u{10594}', '\u{0}', '\u{0}']), + ('\u{105bc}', ['\u{10595}', '\u{0}', '\u{0}']), ('\u{10cc0}', ['\u{10c80}', '\u{0}', '\u{0}']), ('\u{10cc1}', ['\u{10c81}', '\u{0}', '\u{0}']), ('\u{10cc2}', ['\u{10c82}', '\u{0}', '\u{0}']), diff --git a/library/core/tests/array.rs b/library/core/tests/array.rs index 0ae625bdb6..b3af1328c9 100644 --- a/library/core/tests/array.rs +++ b/library/core/tests/array.rs @@ -1,5 +1,6 @@ use core::array; use core::convert::TryFrom; +use core::sync::atomic::{AtomicUsize, Ordering}; #[test] fn array_from_ref() { @@ -303,8 +304,6 @@ fn array_map() { #[test] #[should_panic(expected = "test succeeded")] fn array_map_drop_safety() { - use core::sync::atomic::AtomicUsize; - use core::sync::atomic::Ordering; static DROPPED: AtomicUsize = AtomicUsize::new(0); struct DropCounter; impl Drop for DropCounter { @@ -356,3 +355,84 @@ fn cell_allows_array_cycle() { b3.a[0].set(Some(&b1)); b3.a[1].set(Some(&b2)); } + +#[test] +fn array_from_fn() { + let array = core::array::from_fn(|idx| idx); + assert_eq!(array, [0, 1, 2, 3, 4]); +} + +#[test] +fn array_try_from_fn() { + #[derive(Debug, PartialEq)] + enum SomeError { + Foo, + } + + let array = core::array::try_from_fn(|i| Ok::<_, SomeError>(i)); + assert_eq!(array, Ok([0, 1, 2, 3, 4])); + + let another_array = core::array::try_from_fn::(|_| Err(SomeError::Foo)); + assert_eq!(another_array, Err(SomeError::Foo)); +} + +#[cfg(not(panic = "abort"))] +#[test] +fn array_try_from_fn_drops_inserted_elements_on_err() { + static DROP_COUNTER: AtomicUsize = AtomicUsize::new(0); + + struct CountDrop; + impl Drop for CountDrop { + fn drop(&mut self) { + DROP_COUNTER.fetch_add(1, Ordering::SeqCst); + } + } + + let _ = catch_unwind_silent(move || { + let _: Result<[CountDrop; 4], ()> = core::array::try_from_fn(|idx| { + if idx == 2 { + return Err(()); + } + Ok(CountDrop) + }); + }); + + assert_eq!(DROP_COUNTER.load(Ordering::SeqCst), 2); +} + +#[cfg(not(panic = "abort"))] +#[test] +fn array_try_from_fn_drops_inserted_elements_on_panic() { + static DROP_COUNTER: AtomicUsize = AtomicUsize::new(0); + + struct CountDrop; + impl Drop for CountDrop { + fn drop(&mut self) { + DROP_COUNTER.fetch_add(1, Ordering::SeqCst); + } + } + + let _ = catch_unwind_silent(move || { + let _: Result<[CountDrop; 4], ()> = core::array::try_from_fn(|idx| { + if idx == 2 { + panic!("peek a boo"); + } + Ok(CountDrop) + }); + }); + + assert_eq!(DROP_COUNTER.load(Ordering::SeqCst), 2); +} + +#[cfg(not(panic = "abort"))] +// https://stackoverflow.com/a/59211505 +fn catch_unwind_silent(f: F) -> std::thread::Result +where + F: FnOnce() -> R + core::panic::UnwindSafe, +{ + let prev_hook = std::panic::take_hook(); + std::panic::set_hook(Box::new(|_| {})); + let result = std::panic::catch_unwind(f); + std::panic::set_hook(prev_hook); + result +} diff --git a/library/core/tests/fmt/builders.rs b/library/core/tests/fmt/builders.rs index 7580010a28..9567479c81 100644 --- a/library/core/tests/fmt/builders.rs +++ b/library/core/tests/fmt/builders.rs @@ -653,6 +653,7 @@ mod debug_list { fn test_formatting_parameters_are_forwarded() { use std::collections::{BTreeMap, BTreeSet}; #[derive(Debug)] + #[allow(dead_code)] struct Foo { bar: u32, baz: u32, diff --git a/library/core/tests/fmt/num.rs b/library/core/tests/fmt/num.rs index 275a1d062c..b958422d14 100644 --- a/library/core/tests/fmt/num.rs +++ b/library/core/tests/fmt/num.rs @@ -146,6 +146,7 @@ fn test_format_int_exp_precision() { assert_eq!(format!("{:.1000e}", 1), format!("1.{}e0", "0".repeat(1000))); //test zero precision assert_eq!(format!("{:.0e}", 1), format!("1e0",)); + assert_eq!(format!("{:.0e}", 35), format!("4e1",)); //test padding with precision (and sign) assert_eq!(format!("{:+10.3e}", 1), " +1.000e0"); diff --git a/library/core/tests/iter/adapters/flatten.rs b/library/core/tests/iter/adapters/flatten.rs index aaac39c297..4ae50a2f06 100644 --- a/library/core/tests/iter/adapters/flatten.rs +++ b/library/core/tests/iter/adapters/flatten.rs @@ -58,6 +58,23 @@ fn test_flatten_try_folds() { assert_eq!(iter.next_back(), Some(35)); } +#[test] +fn test_flatten_advance_by() { + let mut it = once(0..10).chain(once(10..30)).chain(once(30..40)).flatten(); + it.advance_by(5).unwrap(); + assert_eq!(it.next(), Some(5)); + it.advance_by(9).unwrap(); + assert_eq!(it.next(), Some(15)); + it.advance_back_by(4).unwrap(); + assert_eq!(it.next_back(), Some(35)); + it.advance_back_by(9).unwrap(); + assert_eq!(it.next_back(), Some(25)); + + assert_eq!(it.advance_by(usize::MAX), Err(9)); + assert_eq!(it.advance_back_by(usize::MAX), Err(0)); + assert_eq!(it.size_hint(), (0, Some(0))); +} + #[test] fn test_flatten_non_fused_outer() { let mut iter = NonFused::new(once(0..2)).flatten(); diff --git a/library/core/tests/iter/range.rs b/library/core/tests/iter/range.rs index 44adc3c58d..6b4cf33efe 100644 --- a/library/core/tests/iter/range.rs +++ b/library/core/tests/iter/range.rs @@ -285,6 +285,29 @@ fn test_range_step() { assert_eq!((isize::MIN..isize::MAX).step_by(1).size_hint(), (usize::MAX, Some(usize::MAX))); } +#[test] +fn test_range_advance_by() { + let mut r = 0..usize::MAX; + r.advance_by(0).unwrap(); + r.advance_back_by(0).unwrap(); + + assert_eq!(r.len(), usize::MAX); + + r.advance_by(1).unwrap(); + r.advance_back_by(1).unwrap(); + + assert_eq!((r.start, r.end), (1, usize::MAX - 1)); + + assert_eq!(r.advance_by(usize::MAX), Err(usize::MAX - 2)); + + let mut r = 0u128..u128::MAX; + + r.advance_by(usize::MAX).unwrap(); + r.advance_back_by(usize::MAX).unwrap(); + + assert_eq!((r.start, r.end), (0u128 + usize::MAX as u128, u128::MAX - usize::MAX as u128)); +} + #[test] fn test_range_inclusive_step() { assert_eq!((0..=50).step_by(10).collect::>(), [0, 10, 20, 30, 40, 50]); diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index 1cf6e1d917..cf669163d3 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -10,6 +10,7 @@ #![feature(const_assume)] #![feature(const_cell_into_inner)] #![feature(const_maybe_uninit_assume_init)] +#![cfg_attr(bootstrap, feature(const_panic))] #![feature(const_ptr_read)] #![feature(const_ptr_write)] #![feature(const_ptr_offset)] @@ -26,6 +27,7 @@ #![feature(extern_types)] #![feature(flt2dec)] #![feature(fmt_internals)] +#![feature(array_from_fn)] #![feature(hashmap_internals)] #![feature(try_find)] #![feature(is_sorted)] @@ -51,7 +53,6 @@ #![feature(iter_intersperse)] #![feature(iter_is_partitioned)] #![feature(iter_order_by)] -#![feature(iter_map_while)] #![feature(const_mut_refs)] #![feature(const_pin)] #![feature(const_slice_from_raw_parts)] diff --git a/library/core/tests/num/int_log.rs b/library/core/tests/num/int_log.rs index 51122c11ce..3cd0073ddd 100644 --- a/library/core/tests/num/int_log.rs +++ b/library/core/tests/num/int_log.rs @@ -26,10 +26,10 @@ fn checked_log() { assert_eq!(i.checked_log(4), None); } for i in 1..=i16::MAX { - assert_eq!(i.checked_log(13), Some((i as f32).log(13.0) as i16)); + assert_eq!(i.checked_log(13), Some((i as f32).log(13.0) as u32)); } for i in 1..=u16::MAX { - assert_eq!(i.checked_log(13), Some((i as f32).log(13.0) as u16)); + assert_eq!(i.checked_log(13), Some((i as f32).log(13.0) as u32)); } } @@ -46,19 +46,19 @@ fn checked_log2() { assert_eq!(0i16.checked_log2(), None); for i in 1..=u8::MAX { - assert_eq!(i.checked_log2(), Some((i as f32).log2() as u8)); + assert_eq!(i.checked_log2(), Some((i as f32).log2() as u32)); } for i in 1..=u16::MAX { // Guard against Android's imprecise f32::log2 implementation. if i != 8192 && i != 32768 { - assert_eq!(i.checked_log2(), Some((i as f32).log2() as u16)); + assert_eq!(i.checked_log2(), Some((i as f32).log2() as u32)); } } for i in i8::MIN..=0 { assert_eq!(i.checked_log2(), None); } for i in 1..=i8::MAX { - assert_eq!(i.checked_log2(), Some((i as f32).log2() as i8)); + assert_eq!(i.checked_log2(), Some((i as f32).log2() as u32)); } for i in i16::MIN..=0 { assert_eq!(i.checked_log2(), None); @@ -66,7 +66,7 @@ fn checked_log2() { for i in 1..=i16::MAX { // Guard against Android's imprecise f32::log2 implementation. if i != 8192 { - assert_eq!(i.checked_log2(), Some((i as f32).log2() as i16)); + assert_eq!(i.checked_log2(), Some((i as f32).log2() as u32)); } } } @@ -75,9 +75,9 @@ fn checked_log2() { #[test] #[cfg(not(target_os = "android"))] fn checked_log2_not_android() { - assert_eq!(8192u16.checked_log2(), Some((8192f32).log2() as u16)); - assert_eq!(32768u16.checked_log2(), Some((32768f32).log2() as u16)); - assert_eq!(8192i16.checked_log2(), Some((8192f32).log2() as i16)); + assert_eq!(8192u16.checked_log2(), Some((8192f32).log2() as u32)); + assert_eq!(32768u16.checked_log2(), Some((32768f32).log2() as u32)); + assert_eq!(8192i16.checked_log2(), Some((8192f32).log2() as u32)); } #[test] @@ -91,10 +91,13 @@ fn checked_log10() { assert_eq!(i.checked_log10(), None); } for i in 1..=i16::MAX { - assert_eq!(i.checked_log10(), Some((i as f32).log10() as i16)); + assert_eq!(i.checked_log10(), Some((i as f32).log10() as u32)); } for i in 1..=u16::MAX { - assert_eq!(i.checked_log10(), Some((i as f32).log10() as u16)); + assert_eq!(i.checked_log10(), Some((i as f32).log10() as u32)); + } + for i in 1..=100_000u32 { + assert_eq!(i.checked_log10(), Some((i as f32).log10() as u32)); } } diff --git a/library/core/tests/option.rs b/library/core/tests/option.rs index cd8fdebe36..c9508c1452 100644 --- a/library/core/tests/option.rs +++ b/library/core/tests/option.rs @@ -367,6 +367,27 @@ fn option_const() { const IS_NONE: bool = OPTION.is_none(); assert!(!IS_NONE); + + const COPIED: Option = OPTION.as_ref().copied(); + assert_eq!(COPIED, OPTION); +} + +#[test] +const fn option_const_mut() { + // test that the methods of `Option` that take mutable references are usable in a const context + + let mut option: Option = Some(32); + + let _take = option.take(); + let _replace = option.replace(42); + + { + let as_mut = option.as_mut(); + match as_mut { + Some(v) => *v = 32, + None => unreachable!(), + } + } } #[test] diff --git a/library/core/tests/slice.rs b/library/core/tests/slice.rs index c591dd3e1a..b6a326f3d7 100644 --- a/library/core/tests/slice.rs +++ b/library/core/tests/slice.rs @@ -2152,3 +2152,42 @@ fn test_slice_fill_with_uninit() { let mut a = [MaybeUninit::::uninit(); 10]; a.fill(MaybeUninit::uninit()); } + +#[test] +fn test_swap() { + let mut x = ["a", "b", "c", "d"]; + x.swap(1, 3); + assert_eq!(x, ["a", "d", "c", "b"]); + x.swap(0, 3); + assert_eq!(x, ["b", "d", "c", "a"]); +} + +mod swap_panics { + #[test] + #[should_panic(expected = "index out of bounds: the len is 4 but the index is 4")] + fn index_a_equals_len() { + let mut x = ["a", "b", "c", "d"]; + x.swap(4, 2); + } + + #[test] + #[should_panic(expected = "index out of bounds: the len is 4 but the index is 4")] + fn index_b_equals_len() { + let mut x = ["a", "b", "c", "d"]; + x.swap(2, 4); + } + + #[test] + #[should_panic(expected = "index out of bounds: the len is 4 but the index is 5")] + fn index_a_greater_than_len() { + let mut x = ["a", "b", "c", "d"]; + x.swap(5, 2); + } + + #[test] + #[should_panic(expected = "index out of bounds: the len is 4 but the index is 5")] + fn index_b_greater_than_len() { + let mut x = ["a", "b", "c", "d"]; + x.swap(2, 5); + } +} diff --git a/library/core/tests/time.rs b/library/core/tests/time.rs index f14639e0d5..fe2d2f2412 100644 --- a/library/core/tests/time.rs +++ b/library/core/tests/time.rs @@ -313,6 +313,34 @@ fn debug_formatting_precision_two() { assert_eq!(format!("{:.2?}", Duration::new(8, 999_999_999)), "9.00s"); } +#[test] +fn debug_formatting_padding() { + assert_eq!("0ns ", format!("{:<9?}", Duration::new(0, 0))); + assert_eq!(" 0ns", format!("{:>9?}", Duration::new(0, 0))); + assert_eq!(" 0ns ", format!("{:^9?}", Duration::new(0, 0))); + assert_eq!("123ns ", format!("{:<9.0?}", Duration::new(0, 123))); + assert_eq!(" 123ns", format!("{:>9.0?}", Duration::new(0, 123))); + assert_eq!(" 123ns ", format!("{:^9.0?}", Duration::new(0, 123))); + assert_eq!("123.0ns ", format!("{:<9.1?}", Duration::new(0, 123))); + assert_eq!(" 123.0ns", format!("{:>9.1?}", Duration::new(0, 123))); + assert_eq!(" 123.0ns ", format!("{:^9.1?}", Duration::new(0, 123))); + assert_eq!("7.1µs ", format!("{:<9?}", Duration::new(0, 7_100))); + assert_eq!(" 7.1µs", format!("{:>9?}", Duration::new(0, 7_100))); + assert_eq!(" 7.1µs ", format!("{:^9?}", Duration::new(0, 7_100))); + assert_eq!("999.123456ms", format!("{:<9?}", Duration::new(0, 999_123_456))); + assert_eq!("999.123456ms", format!("{:>9?}", Duration::new(0, 999_123_456))); + assert_eq!("999.123456ms", format!("{:^9?}", Duration::new(0, 999_123_456))); + assert_eq!("5s ", format!("{:<9?}", Duration::new(5, 0))); + assert_eq!(" 5s", format!("{:>9?}", Duration::new(5, 0))); + assert_eq!(" 5s ", format!("{:^9?}", Duration::new(5, 0))); + assert_eq!("5.000000000000s", format!("{:<9.12?}", Duration::new(5, 0))); + assert_eq!("5.000000000000s", format!("{:>9.12?}", Duration::new(5, 0))); + assert_eq!("5.000000000000s", format!("{:^9.12?}", Duration::new(5, 0))); + + // default alignment is left: + assert_eq!("5s ", format!("{:9?}", Duration::new(5, 0))); +} + #[test] fn debug_formatting_precision_high() { assert_eq!(format!("{:.5?}", Duration::new(0, 23_678)), "23.67800µs"); diff --git a/library/panic_abort/src/lib.rs b/library/panic_abort/src/lib.rs index 4580f9a775..ac75ce7f22 100644 --- a/library/panic_abort/src/lib.rs +++ b/library/panic_abort/src/lib.rs @@ -44,6 +44,7 @@ pub unsafe extern "C-unwind" fn __rust_start_panic(_payload: *mut &mut dyn BoxMe libc::abort(); } } else if #[cfg(any(target_os = "hermit", + target_os = "solid_asp3", all(target_vendor = "fortanix", target_env = "sgx") ))] { unsafe fn abort() -> ! { diff --git a/library/panic_unwind/src/lib.rs b/library/panic_unwind/src/lib.rs index ac7d8c18e3..b5d0ca2572 100644 --- a/library/panic_unwind/src/lib.rs +++ b/library/panic_unwind/src/lib.rs @@ -45,6 +45,7 @@ cfg_if::cfg_if! { } else if #[cfg(any( all(target_family = "windows", target_env = "gnu"), target_os = "psp", + target_os = "solid_asp3", all(target_family = "unix", not(target_os = "espidf")), all(target_vendor = "fortanix", target_env = "sgx"), ))] { diff --git a/library/proc_macro/src/bridge/mod.rs b/library/proc_macro/src/bridge/mod.rs index 7001e827ad..bb05506def 100644 --- a/library/proc_macro/src/bridge/mod.rs +++ b/library/proc_macro/src/bridge/mod.rs @@ -162,6 +162,8 @@ macro_rules! with_api { fn source($self: $S::Span) -> $S::Span; fn start($self: $S::Span) -> LineColumn; fn end($self: $S::Span) -> LineColumn; + fn before($self: $S::Span) -> $S::Span; + fn after($self: $S::Span) -> $S::Span; fn join($self: $S::Span, other: $S::Span) -> Option<$S::Span>; fn resolved_at($self: $S::Span, at: $S::Span) -> $S::Span; fn source_text($self: $S::Span) -> Option; diff --git a/library/proc_macro/src/lib.rs b/library/proc_macro/src/lib.rs index 243922b18b..3a06cd04ab 100644 --- a/library/proc_macro/src/lib.rs +++ b/library/proc_macro/src/lib.rs @@ -61,7 +61,7 @@ use std::{error, fmt, iter, mem}; /// non-panicking way to detect whether the infrastructure required to use the /// API of proc_macro is presently available. Returns true if invoked from /// inside of a procedural macro, false if invoked from any other binary. -#[unstable(feature = "proc_macro_is_available", issue = "71436")] +#[stable(feature = "proc_macro_is_available", since = "1.57.0")] pub fn is_available() -> bool { bridge::Bridge::is_available() } @@ -357,6 +357,18 @@ impl Span { self.0.end().add_1_to_column() } + /// Creates an empty span pointing to directly before this span. + #[unstable(feature = "proc_macro_span_shrink", issue = "87552")] + pub fn before(&self) -> Span { + Span(self.0.before()) + } + + /// Creates an empty span pointing to directly after this span. + #[unstable(feature = "proc_macro_span_shrink", issue = "87552")] + pub fn after(&self) -> Span { + Span(self.0.after()) + } + /// Creates a new span encompassing `self` and `other`. /// /// Returns `None` if `self` and `other` are from different files. diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index 1b051b0d0f..6bc445c6f2 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -15,7 +15,7 @@ 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.99", default-features = false, features = ['rustc-dep-of-std'] } +libc = { version = "0.2.103", default-features = false, features = ['rustc-dep-of-std'] } compiler_builtins = { version = "0.1.44" } profiler_builtins = { path = "../profiler_builtins", optional = true } unwind = { path = "../unwind" } @@ -72,6 +72,7 @@ panic_immediate_abort = ["core/panic_immediate_abort"] # https://github.com/rust-lang/stdarch/blob/master/crates/std_detect/Cargo.toml std_detect_file_io = ["std_detect/std_detect_file_io"] std_detect_dlsym_getauxval = ["std_detect/std_detect_dlsym_getauxval"] +std_detect_env_override = ["std_detect/std_detect_env_override"] [package.metadata.fortanix-sgx] # Maximum possible number of threads when testing diff --git a/library/std/build.rs b/library/std/build.rs index 726157c1f1..cc7184d57f 100644 --- a/library/std/build.rs +++ b/library/std/build.rs @@ -27,6 +27,7 @@ fn main() { || target.contains("wasm32") || target.contains("asmjs") || target.contains("espidf") + || target.contains("solid") { // These platforms don't have any special requirements. } else { diff --git a/library/std/primitive_docs/box_into_raw.md b/library/std/primitive_docs/box_into_raw.md new file mode 100644 index 0000000000..307b9c85bd --- /dev/null +++ b/library/std/primitive_docs/box_into_raw.md @@ -0,0 +1 @@ +Box::into_raw diff --git a/library/std/primitive_docs/fs_file.md b/library/std/primitive_docs/fs_file.md new file mode 100644 index 0000000000..13e4540835 --- /dev/null +++ b/library/std/primitive_docs/fs_file.md @@ -0,0 +1 @@ +fs::File diff --git a/library/std/primitive_docs/io_bufread.md b/library/std/primitive_docs/io_bufread.md new file mode 100644 index 0000000000..bb688e3a5c --- /dev/null +++ b/library/std/primitive_docs/io_bufread.md @@ -0,0 +1 @@ +io::BufRead diff --git a/library/std/primitive_docs/io_read.md b/library/std/primitive_docs/io_read.md new file mode 100644 index 0000000000..5118d7c488 --- /dev/null +++ b/library/std/primitive_docs/io_read.md @@ -0,0 +1 @@ +io::Read diff --git a/library/std/primitive_docs/io_seek.md b/library/std/primitive_docs/io_seek.md new file mode 100644 index 0000000000..122e6df77b --- /dev/null +++ b/library/std/primitive_docs/io_seek.md @@ -0,0 +1 @@ +io::Seek diff --git a/library/std/primitive_docs/io_write.md b/library/std/primitive_docs/io_write.md new file mode 100644 index 0000000000..15dfc907a6 --- /dev/null +++ b/library/std/primitive_docs/io_write.md @@ -0,0 +1 @@ +io::Write diff --git a/library/std/primitive_docs/net_tosocketaddrs.md b/library/std/primitive_docs/net_tosocketaddrs.md new file mode 100644 index 0000000000..a01f318e88 --- /dev/null +++ b/library/std/primitive_docs/net_tosocketaddrs.md @@ -0,0 +1 @@ +net::ToSocketAddrs diff --git a/library/std/primitive_docs/process_exit.md b/library/std/primitive_docs/process_exit.md new file mode 100644 index 0000000000..565a71375c --- /dev/null +++ b/library/std/primitive_docs/process_exit.md @@ -0,0 +1 @@ +process::exit diff --git a/library/std/primitive_docs/string_string.md b/library/std/primitive_docs/string_string.md new file mode 100644 index 0000000000..ce7815ff91 --- /dev/null +++ b/library/std/primitive_docs/string_string.md @@ -0,0 +1 @@ +string::String diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs index 4dff4fa4a6..01019344f4 100644 --- a/library/std/src/collections/hash/map.rs +++ b/library/std/src/collections/hash/map.rs @@ -203,9 +203,9 @@ use crate::sys; /// } /// ``` -#[cfg_attr(not(test), rustc_diagnostic_item = "hashmap_type")] +#[cfg_attr(not(test), rustc_diagnostic_item = "HashMap")] #[stable(feature = "rust1", since = "1.0.0")] -#[cfg_attr(not(bootstrap), rustc_insignificant_dtor)] +#[rustc_insignificant_dtor] pub struct HashMap { base: base::HashMap, } @@ -223,6 +223,7 @@ impl HashMap { /// let mut map: HashMap<&str, i32> = HashMap::new(); /// ``` #[inline] + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] pub fn new() -> HashMap { Default::default() @@ -240,6 +241,7 @@ impl HashMap { /// let mut map: HashMap<&str, i32> = HashMap::with_capacity(10); /// ``` #[inline] + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] pub fn with_capacity(capacity: usize) -> HashMap { HashMap::with_capacity_and_hasher(capacity, Default::default()) @@ -625,14 +627,13 @@ where /// # Examples /// /// ``` - /// #![feature(try_reserve)] /// use std::collections::HashMap; /// /// let mut map: HashMap<&str, isize> = HashMap::new(); /// map.try_reserve(10).expect("why is the test harness OOMing on 10 bytes?"); /// ``` #[inline] - #[unstable(feature = "try_reserve", reason = "new API", issue = "48043")] + #[stable(feature = "try_reserve", since = "1.57.0")] pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> { self.base.try_reserve(additional).map_err(map_try_reserve_error) } @@ -1258,9 +1259,10 @@ impl<'a, K, V> IterMut<'a, K, V> { /// An owning iterator over the entries of a `HashMap`. /// /// This `struct` is created by the [`into_iter`] method on [`HashMap`] -/// (provided by the `IntoIterator` trait). See its documentation for more. +/// (provided by the [`IntoIterator`] trait). See its documentation for more. /// /// [`into_iter`]: IntoIterator::into_iter +/// [`IntoIterator`]: crate::iter::IntoIterator /// /// # Example /// @@ -1720,6 +1722,7 @@ impl<'a, K, V, S> RawOccupiedEntryMut<'a, K, V, S> { /// Converts the entry into a mutable reference to the key in the entry /// with a lifetime bound to the map itself. #[inline] + #[must_use = "`self` will be dropped if the result is not used"] #[unstable(feature = "hash_raw_entry", issue = "56167")] pub fn into_key(self) -> &'a mut K { self.base.into_key() @@ -1735,6 +1738,7 @@ impl<'a, K, V, S> RawOccupiedEntryMut<'a, K, V, S> { /// Converts the `OccupiedEntry` into a mutable reference to the value in the entry /// with a lifetime bound to the map itself. #[inline] + #[must_use = "`self` will be dropped if the result is not used"] #[unstable(feature = "hash_raw_entry", issue = "56167")] pub fn into_mut(self) -> &'a mut V { self.base.into_mut() @@ -1764,6 +1768,7 @@ impl<'a, K, V, S> RawOccupiedEntryMut<'a, K, V, S> { /// Converts the `OccupiedEntry` into a mutable reference to the key and value in the entry /// with a lifetime bound to the map itself. #[inline] + #[must_use = "`self` will be dropped if the result is not used"] #[unstable(feature = "hash_raw_entry", issue = "56167")] pub fn into_key_value(self) -> (&'a mut K, &'a mut V) { self.base.into_key_value() @@ -2891,6 +2896,7 @@ impl RandomState { #[inline] #[allow(deprecated)] // rand + #[must_use] #[stable(feature = "hashmap_build_hasher", since = "1.7.0")] pub fn new() -> RandomState { // Historically this function did not cache keys from the OS and instead @@ -2943,6 +2949,7 @@ impl DefaultHasher { /// instances created through `new` or `default`. #[stable(feature = "hashmap_default_hasher", since = "1.13.0")] #[allow(deprecated)] + #[must_use] pub fn new() -> DefaultHasher { DefaultHasher(SipHasher13::new_with_keys(0, 0)) } diff --git a/library/std/src/collections/hash/set.rs b/library/std/src/collections/hash/set.rs index 3b61acd122..5804701892 100644 --- a/library/std/src/collections/hash/set.rs +++ b/library/std/src/collections/hash/set.rs @@ -107,7 +107,7 @@ use super::map::{map_try_reserve_error, RandomState}; /// [`HashMap`]: crate::collections::HashMap /// [`RefCell`]: crate::cell::RefCell /// [`Cell`]: crate::cell::Cell -#[cfg_attr(not(test), rustc_diagnostic_item = "hashset_type")] +#[cfg_attr(not(test), rustc_diagnostic_item = "HashSet")] #[stable(feature = "rust1", since = "1.0.0")] pub struct HashSet { base: base::HashSet, @@ -126,6 +126,7 @@ impl HashSet { /// let set: HashSet = HashSet::new(); /// ``` #[inline] + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] pub fn new() -> HashSet { Default::default() @@ -144,6 +145,7 @@ impl HashSet { /// assert!(set.capacity() >= 10); /// ``` #[inline] + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] pub fn with_capacity(capacity: usize) -> HashSet { HashSet { base: base::HashSet::with_capacity_and_hasher(capacity, Default::default()) } @@ -423,13 +425,12 @@ where /// # Examples /// /// ``` - /// #![feature(try_reserve)] /// use std::collections::HashSet; /// let mut set: HashSet = HashSet::new(); /// set.try_reserve(10).expect("why is the test harness OOMing on 10 bytes?"); /// ``` #[inline] - #[unstable(feature = "try_reserve", reason = "new API", issue = "48043")] + #[stable(feature = "try_reserve", since = "1.57.0")] pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> { self.base.try_reserve(additional).map_err(map_try_reserve_error) } @@ -1237,9 +1238,10 @@ pub struct Iter<'a, K: 'a> { /// An owning iterator over the items of a `HashSet`. /// /// This `struct` is created by the [`into_iter`] method on [`HashSet`] -/// (provided by the `IntoIterator` trait). See its documentation for more. +/// (provided by the [`IntoIterator`] trait). See its documentation for more. /// /// [`into_iter`]: IntoIterator::into_iter +/// [`IntoIterator`]: crate::iter::IntoIterator /// /// # Examples /// diff --git a/library/std/src/collections/mod.rs b/library/std/src/collections/mod.rs index 130bb5cb2b..a19c343198 100644 --- a/library/std/src/collections/mod.rs +++ b/library/std/src/collections/mod.rs @@ -97,11 +97,11 @@ //! //! ## Sequences //! -//! | | get(i) | insert(i) | remove(i) | append | split_off(i) | -//! |----------------|----------------|-----------------|----------------|--------|----------------| -//! | [`Vec`] | O(1) | O(n-i)* | O(n-i) | O(m)* | O(n-i) | -//! | [`VecDeque`] | O(1) | O(min(i, n-i))* | O(min(i, n-i)) | O(m)* | O(min(i, n-i)) | -//! | [`LinkedList`] | O(min(i, n-i)) | O(min(i, n-i)) | O(min(i, n-i)) | O(1) | O(min(i, n-i)) | +//! | | get(i) | insert(i) | remove(i) | append | split_off(i) | +//! |----------------|------------------------|-------------------------|------------------------|-----------|------------------------| +//! | [`Vec`] | *O*(1) | *O*(*n*-*i*)* | *O*(*n*-*i*) | *O*(*m*)* | *O*(*n*-*i*) | +//! | [`VecDeque`] | *O*(1) | *O*(min(*i*, *n*-*i*))* | *O*(min(*i*, *n*-*i*)) | *O*(*m*)* | *O*(min(*i*, *n*-*i*)) | +//! | [`LinkedList`] | *O*(min(*i*, *n*-*i*)) | *O*(min(*i*, *n*-*i*)) | *O*(min(*i*, *n*-*i*)) | *O*(1) | *O*(min(*i*, *n*-*i*)) | //! //! Note that where ties occur, [`Vec`] is generally going to be faster than [`VecDeque`], and //! [`VecDeque`] is generally going to be faster than [`LinkedList`]. @@ -110,10 +110,10 @@ //! //! For Sets, all operations have the cost of the equivalent Map operation. //! -//! | | get | insert | remove | range | append | -//! |--------------|-----------|-----------|-----------|-----------|--------| -//! | [`HashMap`] | O(1)~ | O(1)~* | O(1)~ | N/A | N/A | -//! | [`BTreeMap`] | O(log(n)) | O(log(n)) | O(log(n)) | O(log(n)) | O(n+m) | +//! | | get | insert | remove | range | append | +//! |--------------|---------------|---------------|---------------|---------------|--------------| +//! | [`HashMap`] | *O*(1)~ | *O*(1)~* | *O*(1)~ | N/A | N/A | +//! | [`BTreeMap`] | *O*(log(*n*)) | *O*(log(*n*)) | *O*(log(*n*)) | *O*(log(*n*)) | *O*(*n*+*m*) | //! //! # Correct and Efficient Usage of Collections //! @@ -217,7 +217,7 @@ //! contents by-value. This is great when the collection itself is no longer //! needed, and the values are needed elsewhere. Using `extend` with `into_iter` //! is the main way that contents of one collection are moved into another. -//! `extend` automatically calls `into_iter`, and takes any `T: `[`IntoIterator`]. +//! `extend` automatically calls `into_iter`, and takes any T: [IntoIterator]. //! Calling `collect` on an iterator itself is also a great way to convert one //! collection into another. Both of these methods should internally use the //! capacity management tools discussed in the previous section to do this as @@ -239,7 +239,7 @@ //! Iterators also provide a series of *adapter* methods for performing common //! threads to sequences. Among the adapters are functional favorites like `map`, //! `fold`, `skip` and `take`. Of particular interest to collections is the -//! `rev` adapter, that reverses any iterator that supports this operation. Most +//! `rev` adapter, which reverses any iterator that supports this operation. Most //! collections provide reversible iterators as the way to iterate over them in //! reverse order. //! @@ -396,7 +396,7 @@ //! assert_eq!(map.keys().next().unwrap().b, "baz"); //! ``` //! -//! [`IntoIterator`]: crate::iter::IntoIterator +//! [IntoIterator]: crate::iter::IntoIterator "iter::IntoIterator" #![stable(feature = "rust1", since = "1.0.0")] @@ -420,7 +420,7 @@ pub use self::hash_map::HashMap; #[stable(feature = "rust1", since = "1.0.0")] pub use self::hash_set::HashSet; -#[unstable(feature = "try_reserve", reason = "new API", issue = "48043")] +#[stable(feature = "try_reserve", since = "1.57.0")] pub use alloc_crate::collections::TryReserveError; #[unstable( feature = "try_reserve_kind", diff --git a/library/std/src/env.rs b/library/std/src/env.rs index e343073d21..40b46878cd 100644 --- a/library/std/src/env.rs +++ b/library/std/src/env.rs @@ -879,6 +879,7 @@ pub mod consts { /// - x86_64 /// - arm /// - aarch64 + /// - m68k /// - mips /// - mips64 /// - powerpc diff --git a/library/std/src/error.rs b/library/std/src/error.rs index ec9f012295..6ae0bc47a9 100644 --- a/library/std/src/error.rs +++ b/library/std/src/error.rs @@ -31,6 +31,7 @@ use crate::num; use crate::str; use crate::string; use crate::sync::Arc; +use crate::time; /// `Error` is a trait representing the basic expectations for error values, /// i.e., values of type `E` in [`Result`]. @@ -182,7 +183,7 @@ impl<'a, E: Error + 'a> From for Box { /// /// impl fmt::Display for AnError { /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - /// write!(f , "An error") + /// write!(f, "An error") /// } /// } /// @@ -215,7 +216,7 @@ impl<'a, E: Error + Send + Sync + 'a> From for Box) -> fmt::Result { - /// write!(f , "An error") + /// write!(f, "An error") /// } /// } /// @@ -594,11 +595,11 @@ impl Error for char::ParseCharError { } } -#[unstable(feature = "try_reserve", reason = "new API", issue = "48043")] +#[stable(feature = "try_reserve", since = "1.57.0")] impl Error for alloc::collections::TryReserveError {} #[unstable(feature = "duration_checked_float", issue = "83400")] -impl Error for core::time::FromSecsError {} +impl Error for time::FromSecsError {} // Copied from `any.rs`. impl dyn Error + 'static { diff --git a/library/std/src/ffi/c_str.rs b/library/std/src/ffi/c_str.rs index de05c37785..6827d3a8d2 100644 --- a/library/std/src/ffi/c_str.rs +++ b/library/std/src/ffi/c_str.rs @@ -29,18 +29,18 @@ use crate::sys_common::memchr; /// type is a static guarantee that the underlying bytes contain no interior 0 /// bytes ("nul characters") and that the final byte is 0 ("nul terminator"). /// -/// `CString` is to [`&CStr`] as [`String`] is to [`&str`]: the former +/// `CString` is to &[CStr] as [`String`] is to &[str]: the former /// in each pair are owned strings; the latter are borrowed /// references. /// /// # Creating a `CString` /// /// A `CString` is created from either a byte slice or a byte vector, -/// or anything that implements [`Into`]`<`[`Vec`]`<`[`u8`]`>>` (for +/// or anything that implements [Into]<[Vec]<[u8]>> (for /// example, you can build a `CString` straight out of a [`String`] or -/// a [`&str`], since both implement that trait). +/// a &[str], since both implement that trait). /// -/// The [`CString::new`] method will actually check that the provided `&[u8]` +/// The [`CString::new`] method will actually check that the provided &[[u8]] /// does not have 0 bytes in the middle, and return an error if it /// finds one. /// @@ -55,7 +55,7 @@ use crate::sys_common::memchr; /// /// # Extracting a slice of the whole C string /// -/// Alternatively, you can obtain a `&[`[`u8`]`]` slice from a +/// Alternatively, you can obtain a &[[u8]] slice from a /// `CString` with the [`CString::as_bytes`] method. Slices produced in this /// way do *not* contain the trailing nul terminator. This is useful /// when you will be calling an extern function that takes a `*const @@ -64,7 +64,7 @@ use crate::sys_common::memchr; /// You can of course get the slice's length with its /// [`len`][slice::len] method. /// -/// If you need a `&[`[`u8`]`]` slice *with* the nul terminator, you +/// If you need a &[[u8]] slice *with* the nul terminator, you /// can use [`CString::as_bytes_with_nul`] instead. /// /// Once you have the kind of slice you need (with or without a nul @@ -73,9 +73,8 @@ use crate::sys_common::memchr; /// extern functions. See the documentation for that function for a /// discussion on ensuring the lifetime of the raw pointer. /// -/// [`&str`]: prim@str +/// [str]: prim@str "str" /// [`Deref`]: ops::Deref -/// [`&CStr`]: CStr /// /// # Examples /// @@ -120,12 +119,12 @@ pub struct CString { /// Representation of a borrowed C string. /// /// This type represents a borrowed reference to a nul-terminated -/// array of bytes. It can be constructed safely from a `&[`[`u8`]`]` +/// array of bytes. It can be constructed safely from a &[[u8]] /// slice, or unsafely from a raw `*const c_char`. It can then be -/// converted to a Rust [`&str`] by performing UTF-8 validation, or +/// converted to a Rust &[str] by performing UTF-8 validation, or /// into an owned [`CString`]. /// -/// `&CStr` is to [`CString`] as [`&str`] is to [`String`]: the former +/// `&CStr` is to [`CString`] as &[str] is to [`String`]: the former /// in each pair are borrowed references; the latter are owned /// strings. /// @@ -183,7 +182,7 @@ pub struct CString { /// println!("string: {}", my_string_safe()); /// ``` /// -/// [`&str`]: prim@str +/// [str]: prim@str "str" #[derive(Hash)] #[cfg_attr(not(test), rustc_diagnostic_item = "CStr")] #[stable(feature = "rust1", since = "1.0.0")] @@ -298,6 +297,7 @@ impl FromVecWithNulError { /// /// assert_eq!(&bytes[..], value.unwrap_err().as_bytes()); /// ``` + #[must_use] pub fn as_bytes(&self) -> &[u8] { &self.bytes[..] } @@ -323,6 +323,7 @@ impl FromVecWithNulError { /// /// assert_eq!(bytes, value.unwrap_err().into_bytes()); /// ``` + #[must_use = "`self` will be dropped if the result is not used"] pub fn into_bytes(self) -> Vec { self.bytes } @@ -410,6 +411,8 @@ impl CString { /// Creates a C-compatible string by consuming a byte vector, /// without checking for interior 0 bytes. /// + /// Trailing 0 byte will be appended by this function. + /// /// This method is equivalent to [`CString::new`] except that no runtime /// assertion is made that `v` contains no 0 bytes, and it requires an /// actual byte vector, not anything that can be converted to one with Into. @@ -424,6 +427,7 @@ impl CString { /// let c_string = CString::from_vec_unchecked(raw); /// } /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] pub unsafe fn from_vec_unchecked(mut v: Vec) -> CString { v.reserve_exact(1); @@ -475,6 +479,7 @@ impl CString { /// let c_string = CString::from_raw(raw); /// } /// ``` + #[must_use = "call `drop(from_raw(ptr))` if you intend to drop the `CString`"] #[stable(feature = "cstr_memory", since = "1.4.0")] pub unsafe fn from_raw(ptr: *mut c_char) -> CString { // SAFETY: This is called with a pointer that was obtained from a call @@ -523,6 +528,7 @@ impl CString { /// } /// ``` #[inline] + #[must_use = "`self` will be dropped if the result is not used"] #[stable(feature = "cstr_memory", since = "1.4.0")] pub fn into_raw(self) -> *mut c_char { Box::into_raw(self.into_inner()) as *mut c_char @@ -546,7 +552,6 @@ impl CString { /// let err = cstring.into_string().err().expect("into_string().err() failed"); /// assert_eq!(err.utf8_error().valid_up_to(), 1); /// ``` - #[stable(feature = "cstring_into", since = "1.7.0")] pub fn into_string(self) -> Result { String::from_utf8(self.into_bytes()).map_err(|e| IntoStringError { @@ -570,6 +575,7 @@ impl CString { /// let bytes = c_string.into_bytes(); /// assert_eq!(bytes, vec![b'f', b'o', b'o']); /// ``` + #[must_use = "`self` will be dropped if the result is not used"] #[stable(feature = "cstring_into", since = "1.7.0")] pub fn into_bytes(self) -> Vec { let mut vec = self.into_inner().into_vec(); @@ -590,6 +596,7 @@ impl CString { /// let bytes = c_string.into_bytes_with_nul(); /// assert_eq!(bytes, vec![b'f', b'o', b'o', b'\0']); /// ``` + #[must_use = "`self` will be dropped if the result is not used"] #[stable(feature = "cstring_into", since = "1.7.0")] pub fn into_bytes_with_nul(self) -> Vec { self.into_inner().into_vec() @@ -612,6 +619,7 @@ impl CString { /// assert_eq!(bytes, &[b'f', b'o', b'o']); /// ``` #[inline] + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] pub fn as_bytes(&self) -> &[u8] { // SAFETY: CString has a length at least 1 @@ -631,6 +639,7 @@ impl CString { /// assert_eq!(bytes, &[b'f', b'o', b'o', b'\0']); /// ``` #[inline] + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] pub fn as_bytes_with_nul(&self) -> &[u8] { &self.inner @@ -649,6 +658,7 @@ impl CString { /// CStr::from_bytes_with_nul(b"foo\0").expect("CStr::from_bytes_with_nul failed")); /// ``` #[inline] + #[must_use] #[stable(feature = "as_c_str", since = "1.20.0")] pub fn as_c_str(&self) -> &CStr { &*self @@ -666,6 +676,7 @@ impl CString { /// assert_eq!(&*boxed, /// CStr::from_bytes_with_nul(b"foo\0").expect("CStr::from_bytes_with_nul 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_boxed_c_str(self) -> Box { unsafe { Box::from_raw(Box::into_raw(self.into_inner()) as *mut CStr) } @@ -682,7 +693,7 @@ impl CString { unsafe { ptr::read(&this.inner) } } - /// Converts a [`Vec`]`` to a [`CString`] without checking the + /// Converts a [Vec]<[u8]> to a [`CString`] without checking the /// invariants on the given [`Vec`]. /// /// # Safety @@ -700,12 +711,13 @@ impl CString { /// unsafe { CString::from_vec_unchecked(b"abc".to_vec()) } /// ); /// ``` + #[must_use] #[unstable(feature = "cstring_from_vec_with_nul", issue = "73179")] pub unsafe fn from_vec_with_nul_unchecked(v: Vec) -> Self { Self { inner: v.into_boxed_slice() } } - /// Attempts to converts a [`Vec`]`` to a [`CString`]. + /// Attempts to converts a [Vec]<[u8]> to a [`CString`]. /// /// Runtime checks are present to ensure there is only one nul byte in the /// [`Vec`], its last element. @@ -793,7 +805,7 @@ impl fmt::Debug for CString { #[stable(feature = "cstring_into", since = "1.7.0")] impl From for Vec { - /// Converts a [`CString`] into a [`Vec`]``. + /// Converts a [`CString`] into a [Vec]<[u8]>. /// /// The conversion consumes the [`CString`], and removes the terminating NUL byte. #[inline] @@ -867,7 +879,7 @@ impl From> for Box { #[stable(feature = "c_string_from_box", since = "1.18.0")] impl From> for CString { - /// Converts a [`Box`]`` into a [`CString`] without copying or allocating. + /// Converts a [Box]<[CStr]> into a [`CString`] without copying or allocating. #[inline] fn from(s: Box) -> CString { s.into_c_string() @@ -876,7 +888,7 @@ impl From> for CString { #[stable(feature = "cstring_from_vec_of_nonzerou8", since = "1.43.0")] impl From> for CString { - /// Converts a [`Vec`]`<`[`NonZeroU8`]`>` into a [`CString`] without + /// Converts a [Vec]<[NonZeroU8]> into a [`CString`] without /// copying nor checking for inner null bytes. #[inline] fn from(v: Vec) -> CString { @@ -906,7 +918,7 @@ impl Clone for Box { #[stable(feature = "box_from_c_string", since = "1.20.0")] impl From for Box { - /// Converts a [`CString`] into a [`Box`]`` without copying or allocating. + /// Converts a [`CString`] into a [Box]<[CStr]> without copying or allocating. #[inline] fn from(s: CString) -> Box { s.into_boxed_c_str() @@ -915,6 +927,7 @@ impl From for Box { #[stable(feature = "cow_from_cstr", since = "1.28.0")] impl<'a> From for Cow<'a, CStr> { + /// Converts a [`CString`] into an owned [`Cow`] without copying or allocating. #[inline] fn from(s: CString) -> Cow<'a, CStr> { Cow::Owned(s) @@ -923,6 +936,7 @@ impl<'a> From for Cow<'a, CStr> { #[stable(feature = "cow_from_cstr", since = "1.28.0")] impl<'a> From<&'a CStr> for Cow<'a, CStr> { + /// Converts a [`CStr`] into a borrowed [`Cow`] without copying or allocating. #[inline] fn from(s: &'a CStr) -> Cow<'a, CStr> { Cow::Borrowed(s) @@ -931,6 +945,7 @@ impl<'a> From<&'a CStr> for Cow<'a, CStr> { #[stable(feature = "cow_from_cstr", since = "1.28.0")] impl<'a> From<&'a CString> for Cow<'a, CStr> { + /// Converts a `&`[`CString`] into a borrowed [`Cow`] without copying or allocating. #[inline] fn from(s: &'a CString) -> Cow<'a, CStr> { Cow::Borrowed(s.as_c_str()) @@ -939,7 +954,7 @@ impl<'a> From<&'a CString> for Cow<'a, CStr> { #[stable(feature = "shared_from_slice2", since = "1.24.0")] impl From for Arc { - /// Converts a [`CString`] into an [`Arc`]`` without copying or allocating. + /// Converts a [`CString`] into an [Arc]<[CStr]> without copying or allocating. #[inline] fn from(s: CString) -> Arc { let arc: Arc<[u8]> = Arc::from(s.into_inner()); @@ -958,7 +973,7 @@ impl From<&CStr> for Arc { #[stable(feature = "shared_from_slice2", since = "1.24.0")] impl From for Rc { - /// Converts a [`CString`] into an [`Rc`]`` without copying or allocating. + /// Converts a [`CString`] into an [Rc]<[CStr]> without copying or allocating. #[inline] fn from(s: CString) -> Rc { let rc: Rc<[u8]> = Rc::from(s.into_inner()); @@ -1014,6 +1029,7 @@ impl NulError { /// let nul_error = CString::new("foo\0bar").unwrap_err(); /// assert_eq!(nul_error.into_vec(), b"foo\0bar"); /// ``` + #[must_use = "`self` will be dropped if the result is not used"] #[stable(feature = "rust1", since = "1.0.0")] pub fn into_vec(self) -> Vec { self.1 @@ -1088,6 +1104,7 @@ impl fmt::Display for FromVecWithNulError { impl IntoStringError { /// Consumes this error, returning original [`CString`] which generated the /// error. + #[must_use = "`self` will be dropped if the result is not used"] #[stable(feature = "cstring_into", since = "1.7.0")] pub fn into_cstring(self) -> CString { self.inner @@ -1158,6 +1175,7 @@ impl CStr { /// } /// # } /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] pub unsafe fn from_ptr<'a>(ptr: *const c_char) -> &'a CStr { // SAFETY: The caller has provided a pointer that points to a valid C @@ -1240,6 +1258,7 @@ impl CStr { /// } /// ``` #[inline] + #[must_use] #[stable(feature = "cstr_from_bytes", since = "1.10.0")] #[rustc_const_unstable(feature = "const_cstr_unchecked", issue = "none")] pub const unsafe fn from_bytes_with_nul_unchecked(bytes: &[u8]) -> &CStr { @@ -1298,6 +1317,7 @@ impl CStr { /// This way, the lifetime of the [`CString`] in `hello` encompasses /// the lifetime of `ptr` and the `unsafe` block. #[inline] + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_str_as_ptr", since = "1.32.0")] pub const fn as_ptr(&self) -> *const c_char { @@ -1322,6 +1342,8 @@ impl CStr { /// assert_eq!(cstr.to_bytes(), b"foo"); /// ``` #[inline] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[stable(feature = "rust1", since = "1.0.0")] pub fn to_bytes(&self) -> &[u8] { let bytes = self.to_bytes_with_nul(); @@ -1347,18 +1369,20 @@ impl CStr { /// assert_eq!(cstr.to_bytes_with_nul(), b"foo\0"); /// ``` #[inline] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[stable(feature = "rust1", since = "1.0.0")] pub fn to_bytes_with_nul(&self) -> &[u8] { unsafe { &*(&self.inner as *const [c_char] as *const [u8]) } } - /// Yields a [`&str`] slice if the `CStr` contains valid UTF-8. + /// Yields a &[str] slice if the `CStr` contains valid UTF-8. /// /// If the contents of the `CStr` are valid UTF-8 data, this - /// function will return the corresponding [`&str`] slice. Otherwise, + /// function will return the corresponding &[str] slice. Otherwise, /// it will return an error with details of where UTF-8 validation failed. /// - /// [`&str`]: prim@str + /// [str]: prim@str "str" /// /// # Examples /// @@ -1377,20 +1401,19 @@ impl CStr { str::from_utf8(self.to_bytes()) } - /// Converts a `CStr` into a [`Cow`]`<`[`str`]`>`. + /// Converts a `CStr` into a [Cow]<[str]>. /// /// If the contents of the `CStr` are valid UTF-8 data, this - /// function will return a [`Cow`]`::`[`Borrowed`]`(`[`&str`]`)` - /// with the corresponding [`&str`] slice. Otherwise, it will + /// function will return a [Cow]::[Borrowed]\(&[str]) + /// with the corresponding &[str] slice. Otherwise, it will /// replace any invalid UTF-8 sequences with /// [`U+FFFD REPLACEMENT CHARACTER`][U+FFFD] and return a - /// [`Cow`]`::`[`Owned`]`(`[`String`]`)` with the result. + /// [Cow]::[Owned]\(&[str]) with the result. /// - /// [`str`]: primitive@str - /// [`&str`]: primitive@str - /// [`Borrowed`]: Cow::Borrowed - /// [`Owned`]: Cow::Owned - /// [U+FFFD]: crate::char::REPLACEMENT_CHARACTER + /// [str]: prim@str "str" + /// [Borrowed]: Cow::Borrowed + /// [Owned]: Cow::Owned + /// [U+FFFD]: crate::char::REPLACEMENT_CHARACTER "std::char::REPLACEMENT_CHARACTER" /// /// # Examples /// @@ -1418,12 +1441,14 @@ impl CStr { /// Cow::Owned(String::from("Hello �World")) as Cow<'_, str> /// ); /// ``` + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[stable(feature = "cstr_to_str", since = "1.4.0")] pub fn to_string_lossy(&self) -> Cow<'_, str> { String::from_utf8_lossy(self.to_bytes()) } - /// Converts a [`Box`]`` into a [`CString`] without copying or allocating. + /// Converts a [Box]<[CStr]> into a [`CString`] without copying or allocating. /// /// # Examples /// diff --git a/library/std/src/ffi/mod.rs b/library/std/src/ffi/mod.rs index fe4e3af91a..82a76aa73c 100644 --- a/library/std/src/ffi/mod.rs +++ b/library/std/src/ffi/mod.rs @@ -43,8 +43,8 @@ //! terminator, so the buffer length is really `len+1` characters. //! Rust strings don't have a nul terminator; their length is always //! stored and does not need to be calculated. While in Rust -//! accessing a string's length is a `O(1)` operation (because the -//! length is stored); in C it is an `O(length)` operation because the +//! accessing a string's length is an *O*(1) operation (because the +//! length is stored); in C it is an *O*(*n*) operation because the //! length needs to be computed by scanning the string for the nul //! terminator. //! @@ -64,15 +64,15 @@ //! string: it is nul-terminated, and has no internal nul characters. //! Rust code can create a [`CString`] out of a normal string (provided //! that the string doesn't have nul characters in the middle), and -//! then use a variety of methods to obtain a raw `*mut `[`u8`] that can +//! then use a variety of methods to obtain a raw \*mut [u8] that can //! then be passed as an argument to functions which use the C //! conventions for strings. //! //! * **From C to Rust:** [`CStr`] represents a borrowed C string; it -//! is what you would use to wrap a raw `*const `[`u8`] that you got from +//! is what you would use to wrap a raw \*const [u8] that you got from //! a C function. A [`CStr`] is guaranteed to be a nul-terminated array //! of bytes. Once you have a [`CStr`], you can convert it to a Rust -//! [`&str`][`str`] if it's valid UTF-8, or lossily convert it by adding +//! &[str] if it's valid UTF-8, or lossily convert it by adding //! replacement characters. //! //! [`OsString`] and [`OsStr`] are useful when you need to transfer @@ -86,9 +86,9 @@ //! library, various APIs that transfer strings to/from the operating //! system use [`OsString`] instead of plain strings. For example, //! [`env::var_os()`] is used to query environment variables; it -//! returns an [`Option`]`<`[`OsString`]`>`. If the environment variable -//! exists you will get a [`Some`]`(os_string)`, which you can *then* try to -//! convert to a Rust string. This yields a [`Result`], so that +//! returns an [Option]<[OsString]>. If the environment variable +//! exists you will get a [Some]\(os_string), which you can +//! *then* try to convert to a Rust string. This yields a [`Result`], so that //! your code can detect errors in case the environment variable did //! not in fact contain valid Unicode data. //! @@ -102,44 +102,44 @@ //! ## On Unix //! //! On Unix, [`OsStr`] implements the -//! `std::os::unix::ffi::`[`OsStrExt`][unix.OsStrExt] trait, which +//! std::os::unix::ffi::[OsStrExt][unix.OsStrExt] trait, which //! augments it with two methods, [`from_bytes`] and [`as_bytes`]. //! These do inexpensive conversions from and to UTF-8 byte slices. //! //! Additionally, on Unix [`OsString`] implements the -//! `std::os::unix::ffi::`[`OsStringExt`][unix.OsStringExt] trait, +//! std::os::unix::ffi::[OsStringExt][unix.OsStringExt] trait, //! which provides [`from_vec`] and [`into_vec`] methods that consume //! their arguments, and take or produce vectors of [`u8`]. //! //! ## On Windows //! //! On Windows, [`OsStr`] implements the -//! `std::os::windows::ffi::`[`OsStrExt`][windows.OsStrExt] trait, +//! std::os::windows::ffi::[OsStrExt][windows.OsStrExt] trait, //! which provides an [`encode_wide`] method. This provides an //! iterator that can be [`collect`]ed into a vector of [`u16`]. //! //! Additionally, on Windows [`OsString`] implements the -//! `std::os::windows:ffi::`[`OsStringExt`][windows.OsStringExt] +//! std::os::windows:ffi::[OsStringExt][windows.OsStringExt] //! trait, which provides a [`from_wide`] method. The result of this //! method is an [`OsString`] which can be round-tripped to a Windows //! string losslessly. //! //! [Unicode scalar value]: https://www.unicode.org/glossary/#unicode_scalar_value //! [Unicode code point]: https://www.unicode.org/glossary/#code_point -//! [`env::set_var()`]: crate::env::set_var -//! [`env::var_os()`]: crate::env::var_os -//! [unix.OsStringExt]: crate::os::unix::ffi::OsStringExt -//! [`from_vec`]: crate::os::unix::ffi::OsStringExt::from_vec -//! [`into_vec`]: crate::os::unix::ffi::OsStringExt::into_vec -//! [unix.OsStrExt]: crate::os::unix::ffi::OsStrExt -//! [`from_bytes`]: crate::os::unix::ffi::OsStrExt::from_bytes -//! [`as_bytes`]: crate::os::unix::ffi::OsStrExt::as_bytes -//! [`OsStrExt`]: crate::os::unix::ffi::OsStrExt -//! [windows.OsStrExt]: crate::os::windows::ffi::OsStrExt -//! [`encode_wide`]: crate::os::windows::ffi::OsStrExt::encode_wide -//! [`collect`]: crate::iter::Iterator::collect -//! [windows.OsStringExt]: crate::os::windows::ffi::OsStringExt -//! [`from_wide`]: crate::os::windows::ffi::OsStringExt::from_wide +//! [`env::set_var()`]: crate::env::set_var "env::set_var" +//! [`env::var_os()`]: crate::env::var_os "env::var_os" +//! [unix.OsStringExt]: crate::os::unix::ffi::OsStringExt "os::unix::ffi::OsStringExt" +//! [`from_vec`]: crate::os::unix::ffi::OsStringExt::from_vec "os::unix::ffi::OsStringExt::from_vec" +//! [`into_vec`]: crate::os::unix::ffi::OsStringExt::into_vec "os::unix::ffi::OsStringExt::into_vec" +//! [unix.OsStrExt]: crate::os::unix::ffi::OsStrExt "os::unix::ffi::OsStrExt" +//! [`from_bytes`]: crate::os::unix::ffi::OsStrExt::from_bytes "os::unix::ffi::OsStrExt::from_bytes" +//! [`as_bytes`]: crate::os::unix::ffi::OsStrExt::as_bytes "os::unix::ffi::OsStrExt::as_bytes" +//! [`OsStrExt`]: crate::os::unix::ffi::OsStrExt "os::unix::ffi::OsStrExt" +//! [windows.OsStrExt]: crate::os::windows::ffi::OsStrExt "os::windows::ffi::OsStrExt" +//! [`encode_wide`]: crate::os::windows::ffi::OsStrExt::encode_wide "os::windows::ffi::OsStrExt::encode_wide" +//! [`collect`]: crate::iter::Iterator::collect "iter::Iterator::collect" +//! [windows.OsStringExt]: crate::os::windows::ffi::OsStringExt "os::windows::ffi::OsStringExt" +//! [`from_wide`]: crate::os::windows::ffi::OsStringExt::from_wide "os::windows::ffi::OsStringExt::from_wide" #![stable(feature = "rust1", since = "1.0.0")] diff --git a/library/std/src/ffi/os_str.rs b/library/std/src/ffi/os_str.rs index 21f354caf6..46c9aa5e62 100644 --- a/library/std/src/ffi/os_str.rs +++ b/library/std/src/ffi/os_str.rs @@ -33,7 +33,7 @@ use crate::sys_common::{AsInner, FromInner, IntoInner}; /// of this is that `OsString` instances are *not* `NUL` terminated; in order /// to pass to e.g., Unix system call, you should create a [`CStr`]. /// -/// `OsString` is to [`&OsStr`] as [`String`] is to [`&str`]: the former +/// `OsString` is to &[OsStr] as [`String`] is to &[str]: the former /// in each pair are owned strings; the latter are borrowed /// references. /// @@ -47,18 +47,18 @@ use crate::sys_common::{AsInner, FromInner, IntoInner}; /// # Creating an `OsString` /// /// **From a Rust string**: `OsString` implements -/// [`From`]`<`[`String`]`>`, so you can use `my_string.from` to +/// [From]<[String]>, so you can use my_string.[into]\() to /// create an `OsString` from a normal Rust string. /// /// **From slices:** Just like you can start with an empty Rust -/// [`String`] and then [`String::push_str`] `&str` +/// [`String`] and then [`String::push_str`] some &[str] /// sub-string slices into it, you can create an empty `OsString` with /// the [`OsString::new`] method and then push string slices into it with the /// [`OsString::push`] method. /// /// # Extracting a borrowed reference to the whole OS string /// -/// You can use the [`OsString::as_os_str`] method to get an `&`[`OsStr`] from +/// You can use the [`OsString::as_os_str`] method to get an &[OsStr] from /// an `OsString`; this is effectively a borrowed reference to the /// whole string. /// @@ -67,10 +67,9 @@ use crate::sys_common::{AsInner, FromInner, IntoInner}; /// See the [module's toplevel documentation about conversions][conversions] for a discussion on /// the traits which `OsString` implements for [conversions] from/to native representations. /// -/// [`&OsStr`]: OsStr -/// [`&str`]: str /// [`CStr`]: crate::ffi::CStr /// [conversions]: super#conversions +/// [into]: Into::into #[cfg_attr(not(test), rustc_diagnostic_item = "OsString")] #[stable(feature = "rust1", since = "1.0.0")] pub struct OsString { @@ -86,13 +85,12 @@ impl crate::sealed::Sealed for OsString {} /// This type represents a borrowed reference to a string in the operating system's preferred /// representation. /// -/// `&OsStr` is to [`OsString`] as [`&str`] is to [`String`]: the former in each pair are borrowed -/// references; the latter are owned strings. +/// `&OsStr` is to [`OsString`] as &[str] is to [`String`]: the +/// former in each pair are borrowed references; the latter are owned strings. /// /// See the [module's toplevel documentation about conversions][conversions] for a discussion on /// the traits which `OsStr` implements for [conversions] from/to native representations. /// -/// [`&str`]: str /// [conversions]: super#conversions #[cfg_attr(not(test), rustc_diagnostic_item = "OsStr")] #[stable(feature = "rust1", since = "1.0.0")] @@ -121,6 +119,7 @@ impl OsString { /// let os_string = OsString::new(); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[must_use] #[inline] pub fn new() -> OsString { OsString { inner: Buf::from_string(String::new()) } @@ -138,6 +137,7 @@ impl OsString { /// assert_eq!(os_string.as_os_str(), os_str); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[must_use] #[inline] pub fn as_os_str(&self) -> &OsStr { self @@ -162,9 +162,7 @@ impl OsString { self.inner.into_string().map_err(|buf| OsString { inner: buf }) } - /// Extends the string with the given [`&OsStr`] slice. - /// - /// [`&OsStr`]: OsStr + /// Extends the string with the given &[OsStr] slice. /// /// # Examples /// @@ -203,6 +201,7 @@ impl OsString { /// assert_eq!(capacity, os_string.capacity()); /// ``` #[stable(feature = "osstring_simple_functions", since = "1.9.0")] + #[must_use] #[inline] pub fn with_capacity(capacity: usize) -> OsString { OsString { inner: Buf::with_capacity(capacity) } @@ -350,6 +349,7 @@ impl OsString { /// /// let b: Box = s.into_boxed_os_str(); /// ``` + #[must_use = "`self` will be dropped if the result is not used"] #[stable(feature = "into_boxed_os_str", since = "1.20.0")] pub fn into_boxed_os_str(self) -> Box { let rw = Box::into_raw(self.inner.into_box()) as *mut OsStr; @@ -563,12 +563,10 @@ impl OsStr { unsafe { &mut *(inner as *mut Slice as *mut OsStr) } } - /// Yields a [`&str`] slice if the `OsStr` is valid Unicode. + /// Yields a &[str] slice if the `OsStr` is valid Unicode. /// /// This conversion may entail doing a check for UTF-8 validity. /// - /// [`&str`]: str - /// /// # Examples /// /// ``` @@ -578,12 +576,14 @@ impl OsStr { /// assert_eq!(os_str.to_str(), Some("foo")); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[inline] pub fn to_str(&self) -> Option<&str> { self.inner.to_str() } - /// Converts an `OsStr` to a [`Cow`]`<`[`str`]`>`. + /// Converts an `OsStr` to a [Cow]<[str]>. /// /// Any non-Unicode sequences are replaced with /// [`U+FFFD REPLACEMENT CHARACTER`][U+FFFD]. @@ -629,6 +629,8 @@ impl OsStr { /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[inline] pub fn to_string_lossy(&self) -> Cow<'_, str> { self.inner.to_string_lossy() @@ -646,6 +648,8 @@ impl OsStr { /// assert_eq!(os_string, OsString::from("foo")); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[inline] pub fn to_os_string(&self) -> OsString { OsString { inner: self.inner.to_owned() } @@ -701,7 +705,7 @@ impl OsStr { self.inner.inner.len() } - /// Converts a [`Box`]`` into an [`OsString`] without copying or allocating. + /// Converts a [Box]<[OsStr]> into an [`OsString`] without copying or allocating. #[stable(feature = "into_boxed_os_str", since = "1.20.0")] pub fn into_os_string(self: Box) -> OsString { let boxed = unsafe { Box::from_raw(Box::into_raw(self) as *mut Slice) }; @@ -783,6 +787,7 @@ impl OsStr { /// /// assert_eq!("grüße, jürgen ❤", s.to_ascii_lowercase()); /// ``` + #[must_use = "to lowercase the value in-place, use `make_ascii_lowercase`"] #[stable(feature = "osstring_ascii", since = "1.53.0")] pub fn to_ascii_lowercase(&self) -> OsString { OsString::from_inner(self.inner.to_ascii_lowercase()) @@ -804,6 +809,7 @@ impl OsStr { /// /// assert_eq!("GRüßE, JüRGEN ❤", s.to_ascii_uppercase()); /// ``` + #[must_use = "to uppercase the value in-place, use `make_ascii_uppercase`"] #[stable(feature = "osstring_ascii", since = "1.53.0")] pub fn to_ascii_uppercase(&self) -> OsString { OsString::from_inner(self.inner.to_ascii_uppercase()) @@ -870,7 +876,7 @@ impl From> for Box { #[stable(feature = "os_string_from_box", since = "1.18.0")] impl From> for OsString { - /// Converts a [`Box`]`<`[`OsStr`]`>` into an [`OsString`] without copying or + /// Converts a [Box]<[OsStr]> into an [`OsString`] without copying or /// allocating. #[inline] fn from(boxed: Box) -> OsString { @@ -880,7 +886,7 @@ impl From> for OsString { #[stable(feature = "box_from_os_string", since = "1.20.0")] impl From for Box { - /// Converts an [`OsString`] into a [`Box`]`` without copying or allocating. + /// Converts an [`OsString`] into a [Box]<[OsStr]> without copying or allocating. #[inline] fn from(s: OsString) -> Box { s.into_boxed_os_str() @@ -897,7 +903,7 @@ impl Clone for Box { #[stable(feature = "shared_from_slice2", since = "1.24.0")] impl From for Arc { - /// Converts an [`OsString`] into an [`Arc`]`` without copying or allocating. + /// Converts an [`OsString`] into an [Arc]<[OsStr]> without copying or allocating. #[inline] fn from(s: OsString) -> Arc { let arc = s.inner.into_arc(); @@ -916,7 +922,7 @@ impl From<&OsStr> for Arc { #[stable(feature = "shared_from_slice2", since = "1.24.0")] impl From for Rc { - /// Converts an [`OsString`] into an [`Rc`]`` without copying or allocating. + /// Converts an [`OsString`] into an [Rc]<[OsStr]> without copying or allocating. #[inline] fn from(s: OsString) -> Rc { let rc = s.inner.into_rc(); diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index bdb172907f..9f45e89aa7 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -106,7 +106,7 @@ pub struct Metadata(fs_imp::FileAttr); /// Iterator over the entries in a directory. /// /// This iterator is returned from the [`read_dir`] function of this module and -/// will yield instances of [`io::Result`]`<`[`DirEntry`]`>`. Through a [`DirEntry`] +/// will yield instances of [io::Result]<[DirEntry]>. Through a [`DirEntry`] /// information like the entry's path and possibly other metadata can be /// learned. /// @@ -198,20 +198,10 @@ pub struct DirBuilder { recursive: bool, } -/// Indicates how large a buffer to pre-allocate before reading the entire file. -fn initial_buffer_size(file: &File) -> usize { - // Allocate one extra byte so the buffer doesn't need to grow before the - // final `read` call at the end of the file. Don't worry about `usize` - // overflow because reading will fail regardless in that case. - file.metadata().map(|m| m.len() as usize + 1).unwrap_or(0) -} - /// Read the entire contents of a file into a bytes vector. /// /// This is a convenience function for using [`File::open`] and [`read_to_end`] -/// with fewer imports and without an intermediate variable. It pre-allocates a -/// buffer based on the file size when available, so it is generally faster than -/// reading into a vector created with [`Vec::new()`]. +/// with fewer imports and without an intermediate variable. /// /// [`read_to_end`]: Read::read_to_end /// @@ -238,7 +228,7 @@ fn initial_buffer_size(file: &File) -> usize { pub fn read>(path: P) -> io::Result> { fn inner(path: &Path) -> io::Result> { let mut file = File::open(path)?; - let mut bytes = Vec::with_capacity(initial_buffer_size(&file)); + let mut bytes = Vec::new(); file.read_to_end(&mut bytes)?; Ok(bytes) } @@ -248,9 +238,7 @@ pub fn read>(path: P) -> io::Result> { /// Read the entire contents of a file into a string. /// /// This is a convenience function for using [`File::open`] and [`read_to_string`] -/// with fewer imports and without an intermediate variable. It pre-allocates a -/// buffer based on the file size when available, so it is generally faster than -/// reading into a string created with [`String::new()`]. +/// with fewer imports and without an intermediate variable. /// /// [`read_to_string`]: Read::read_to_string /// @@ -279,7 +267,7 @@ pub fn read>(path: P) -> io::Result> { pub fn read_to_string>(path: P) -> io::Result { fn inner(path: &Path) -> io::Result { let mut file = File::open(path)?; - let mut string = String::with_capacity(initial_buffer_size(&file)); + let mut string = String::new(); file.read_to_string(&mut string)?; Ok(string) } @@ -616,6 +604,15 @@ impl fmt::Debug for File { } } +/// Indicates how much extra capacity is needed to read the rest of the file. +fn buffer_capacity_required(mut file: &File) -> usize { + let size = file.metadata().map(|m| m.len()).unwrap_or(0); + let pos = file.stream_position().unwrap_or(0); + // Don't worry about `usize` overflow because reading will fail regardless + // in that case. + size.saturating_sub(pos) as usize +} + #[stable(feature = "rust1", since = "1.0.0")] impl Read for File { fn read(&mut self, buf: &mut [u8]) -> io::Result { @@ -636,6 +633,18 @@ impl Read for File { // SAFETY: Read is guaranteed to work on uninitialized memory unsafe { Initializer::nop() } } + + // Reserves space in the buffer based on the file size when available. + fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { + buf.reserve(buffer_capacity_required(self)); + io::default_read_to_end(self, buf) + } + + // Reserves space in the buffer based on the file size when available. + fn read_to_string(&mut self, buf: &mut String) -> io::Result { + buf.reserve(buffer_capacity_required(self)); + io::default_read_to_string(self, buf) + } } #[stable(feature = "rust1", since = "1.0.0")] impl Write for File { @@ -682,6 +691,18 @@ impl Read for &File { // SAFETY: Read is guaranteed to work on uninitialized memory unsafe { Initializer::nop() } } + + // Reserves space in the buffer based on the file size when available. + fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { + buf.reserve(buffer_capacity_required(self)); + io::default_read_to_end(self, buf) + } + + // Reserves space in the buffer based on the file size when available. + fn read_to_string(&mut self, buf: &mut String) -> io::Result { + buf.reserve(buffer_capacity_required(self)); + io::default_read_to_string(self, buf) + } } #[stable(feature = "rust1", since = "1.0.0")] impl Write for &File { @@ -723,6 +744,7 @@ impl OpenOptions { /// let file = options.read(true).open("foo.txt"); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[must_use] pub fn new() -> Self { OpenOptions(fs_imp::OpenOptions::new()) } @@ -786,17 +808,17 @@ impl OpenOptions { /// If a file is opened with both read and append access, beware that after /// opening, and after every write, the position for reading may be set at the /// end of the file. So, before writing, save the current position (using - /// [`seek`]`(`[`SeekFrom`]`::`[`Current`]`(0))`), and restore it before the next read. + /// [seek]\([SeekFrom]::[Current]\(0))), and restore it before the next read. /// /// ## Note /// /// This function doesn't create the file if it doesn't exist. Use the /// [`OpenOptions::create`] method to do so. /// - /// [`write()`]: Write::write - /// [`flush()`]: Write::flush - /// [`seek`]: Seek::seek - /// [`Current`]: SeekFrom::Current + /// [`write()`]: Write::write "io::Write::write" + /// [`flush()`]: Write::flush "io::Write::flush" + /// [seek]: Seek::seek "io::Seek::seek" + /// [Current]: SeekFrom::Current "io::SeekFrom::Current" /// /// # Examples /// @@ -983,6 +1005,7 @@ impl Metadata { /// Ok(()) /// } /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] pub fn is_dir(&self) -> bool { self.file_type().is_dir() @@ -1011,6 +1034,7 @@ impl Metadata { /// Ok(()) /// } /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] pub fn is_file(&self) -> bool { self.file_type().is_file() @@ -1037,6 +1061,7 @@ impl Metadata { /// Ok(()) /// } /// ``` + #[must_use] #[unstable(feature = "is_symlink", issue = "85748")] pub fn is_symlink(&self) -> bool { self.file_type().is_symlink() @@ -1284,6 +1309,7 @@ impl FileType { /// Ok(()) /// } /// ``` + #[must_use] #[stable(feature = "file_type", since = "1.1.0")] pub fn is_dir(&self) -> bool { self.0.is_dir() @@ -1316,6 +1342,7 @@ impl FileType { /// Ok(()) /// } /// ``` + #[must_use] #[stable(feature = "file_type", since = "1.1.0")] pub fn is_file(&self) -> bool { self.0.is_file() @@ -1351,6 +1378,7 @@ impl FileType { /// Ok(()) /// } /// ``` + #[must_use] #[stable(feature = "file_type", since = "1.1.0")] pub fn is_symlink(&self) -> bool { self.0.is_symlink() @@ -2043,7 +2071,7 @@ pub fn remove_dir_all>(path: P) -> io::Result<()> { /// Returns an iterator over the entries within a directory. /// -/// The iterator will yield instances of [`io::Result`]`<`[`DirEntry`]`>`. +/// The iterator will yield instances of [io::Result]<[DirEntry]>. /// New errors may be encountered after an iterator is initially constructed. /// Entries for the current and parent directories (typically `.` and `..`) are /// skipped. @@ -2163,6 +2191,7 @@ impl DirBuilder { /// let builder = DirBuilder::new(); /// ``` #[stable(feature = "dir_builder", since = "1.6.0")] + #[must_use] pub fn new() -> DirBuilder { DirBuilder { inner: fs_imp::DirBuilder::new(), recursive: false } } diff --git a/library/std/src/io/buffered/bufreader.rs b/library/std/src/io/buffered/bufreader.rs index 32d194d961..2864e94f60 100644 --- a/library/std/src/io/buffered/bufreader.rs +++ b/library/std/src/io/buffered/bufreader.rs @@ -15,7 +15,7 @@ use crate::io::{ /// *repeated* read calls to the same file or network socket. It does not /// help when reading very large amounts at once, or reading just one or a few /// times. It also provides no advantage when reading from a source that is -/// already in memory, like a [`Vec`]``. +/// already in memory, like a [Vec]\. /// /// When the `BufReader` is dropped, the contents of its buffer will be /// discarded. Creating multiple instances of a `BufReader` on the same @@ -242,14 +242,13 @@ impl BufReader { self.pos = new_pos as usize; return Ok(()); } - } else { - if let Some(new_pos) = pos.checked_add(offset as u64) { - if new_pos <= self.cap as u64 { - self.pos = new_pos as usize; - return Ok(()); - } + } else if let Some(new_pos) = pos.checked_add(offset as u64) { + if new_pos <= self.cap as u64 { + self.pos = new_pos as usize; + return Ok(()); } } + self.seek(SeekFrom::Current(offset)).map(drop) } } @@ -308,6 +307,51 @@ impl Read for BufReader { unsafe fn initializer(&self) -> Initializer { self.inner.initializer() } + + // The inner reader might have an optimized `read_to_end`. Drain our buffer and then + // delegate to the inner implementation. + fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { + let nread = self.cap - self.pos; + buf.extend_from_slice(&self.buf[self.pos..self.cap]); + self.discard_buffer(); + Ok(nread + self.inner.read_to_end(buf)?) + } + + // The inner reader might have an optimized `read_to_end`. Drain our buffer and then + // delegate to the inner implementation. + fn read_to_string(&mut self, buf: &mut String) -> io::Result { + // In the general `else` case below we must read bytes into a side buffer, check + // that they are valid UTF-8, and then append them to `buf`. This requires a + // potentially large memcpy. + // + // If `buf` is empty--the most common case--we can leverage `append_to_string` + // to read directly into `buf`'s internal byte buffer, saving an allocation and + // a memcpy. + if buf.is_empty() { + // `append_to_string`'s safety relies on the buffer only being appended to since + // it only checks the UTF-8 validity of new data. If there were existing content in + // `buf` then an untrustworthy reader (i.e. `self.inner`) could not only append + // bytes but also modify existing bytes and render them invalid. On the other hand, + // if `buf` is empty then by definition any writes must be appends and + // `append_to_string` will validate all of the new bytes. + unsafe { crate::io::append_to_string(buf, |b| self.read_to_end(b)) } + } else { + // We cannot append our byte buffer directly onto the `buf` String as there could + // be an incomplete UTF-8 sequence that has only been partially read. We must read + // everything into a side buffer first and then call `from_utf8` on the complete + // buffer. + let mut bytes = Vec::new(); + self.read_to_end(&mut bytes)?; + let string = crate::str::from_utf8(&bytes).map_err(|_| { + io::Error::new_const( + io::ErrorKind::InvalidData, + &"stream did not contain valid UTF-8", + ) + })?; + *buf += string; + Ok(string.len()) + } + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -347,7 +391,7 @@ where impl Seek for BufReader { /// Seek to an offset, in bytes, in the underlying reader. /// - /// The position used for seeking with [`SeekFrom::Current`]`(_)` is the + /// The position used for seeking with [SeekFrom::Current]\(_) is the /// position the underlying reader would be at if the `BufReader` had no /// internal buffer. /// @@ -360,11 +404,11 @@ impl Seek for BufReader { /// /// See [`std::io::Seek`] for more details. /// - /// Note: In the edge case where you're seeking with [`SeekFrom::Current`]`(n)` + /// Note: In the edge case where you're seeking with [SeekFrom::Current]\(n) /// where `n` minus the internal buffer length overflows an `i64`, two /// seeks will be performed instead of one. If the second seek returns /// [`Err`], the underlying reader will be left at the same position it would - /// have if you called `seek` with [`SeekFrom::Current`]`(0)`. + /// have if you called `seek` with [SeekFrom::Current]\(0). /// /// [`std::io::Seek`]: Seek fn seek(&mut self, pos: SeekFrom) -> io::Result { diff --git a/library/std/src/io/buffered/bufwriter.rs b/library/std/src/io/buffered/bufwriter.rs index df60af7c36..c7423e4d92 100644 --- a/library/std/src/io/buffered/bufwriter.rs +++ b/library/std/src/io/buffered/bufwriter.rs @@ -18,7 +18,7 @@ use crate::ptr; /// *repeated* write calls to the same file or network socket. It does not /// help when writing very large amounts at once, or writing just one or a few /// times. It also provides no advantage when writing to a destination that is -/// in memory, like a [`Vec`]``. +/// in memory, like a [Vec]\. /// /// It is critical to call [`flush`] before `BufWriter` is dropped. Though /// dropping will attempt to flush the contents of the buffer, any errors @@ -476,6 +476,7 @@ pub struct WriterPanicked { impl WriterPanicked { /// Returns the perhaps-unwritten data. Some of this data may have been written by the /// panicking call(s) to the underlying writer, so simply writing it again is not a good idea. + #[must_use = "`self` will be dropped if the result is not used"] #[stable(feature = "bufwriter_into_parts", since = "1.56.0")] pub fn into_inner(self) -> Vec { self.buf diff --git a/library/std/src/io/buffered/tests.rs b/library/std/src/io/buffered/tests.rs index f6c2b49956..feb149c07a 100644 --- a/library/std/src/io/buffered/tests.rs +++ b/library/std/src/io/buffered/tests.rs @@ -243,6 +243,28 @@ fn test_buffered_reader_seek_underflow_discard_buffer_between_seeks() { assert_eq!(reader.buffer().len(), 0); } +#[test] +fn test_buffered_reader_read_to_end_consumes_buffer() { + let data: &[u8] = &[0, 1, 2, 3, 4, 5, 6, 7]; + let mut reader = BufReader::with_capacity(3, data); + let mut buf = Vec::new(); + assert_eq!(reader.fill_buf().ok(), Some(&[0, 1, 2][..])); + assert_eq!(reader.read_to_end(&mut buf).ok(), Some(8)); + assert_eq!(&buf, &[0, 1, 2, 3, 4, 5, 6, 7]); + assert!(reader.buffer().is_empty()); +} + +#[test] +fn test_buffered_reader_read_to_string_consumes_buffer() { + let data: &[u8] = "deadbeef".as_bytes(); + let mut reader = BufReader::with_capacity(3, data); + let mut buf = String::new(); + assert_eq!(reader.fill_buf().ok(), Some("dea".as_bytes())); + assert_eq!(reader.read_to_string(&mut buf).ok(), Some(8)); + assert_eq!(&buf, "deadbeef"); + assert!(reader.buffer().is_empty()); +} + #[test] fn test_buffered_writer() { let inner = Vec::new(); @@ -468,9 +490,6 @@ struct ProgrammableSink { // Writes append to this slice pub buffer: Vec, - // Flush sets this flag - pub flushed: bool, - // If true, writes will always be an error pub always_write_error: bool, @@ -520,7 +539,6 @@ impl Write for ProgrammableSink { if self.always_flush_error { Err(io::Error::new(io::ErrorKind::Other, "test - always_flush_error")) } else { - self.flushed = true; Ok(()) } } diff --git a/library/std/src/io/cursor.rs b/library/std/src/io/cursor.rs index ae0cea985d..980b253119 100644 --- a/library/std/src/io/cursor.rs +++ b/library/std/src/io/cursor.rs @@ -12,13 +12,13 @@ use core::convert::TryInto; /// [`Seek`] implementation. /// /// `Cursor`s are used with in-memory buffers, anything implementing -/// [`AsRef`]`<[u8]>`, to allow them to implement [`Read`] and/or [`Write`], +/// [AsRef]<\[u8]>, to allow them to implement [`Read`] and/or [`Write`], /// allowing these buffers to be used anywhere you might use a reader or writer /// that does actual I/O. /// /// The standard library implements some I/O traits on various types which -/// are commonly used as a buffer, like `Cursor<`[`Vec`]`>` and -/// `Cursor<`[`&[u8]`][bytes]`>`. +/// are commonly used as a buffer, like Cursor<[Vec]\> and +/// Cursor<[&\[u8\]][bytes]>. /// /// # Examples /// @@ -26,7 +26,7 @@ use core::convert::TryInto; /// code, but use an in-memory buffer in our tests. We can do this with /// `Cursor`: /// -/// [bytes]: crate::slice +/// [bytes]: crate::slice "slice" /// [`File`]: crate::fs::File /// /// ```no_run @@ -292,12 +292,7 @@ where SeekFrom::End(n) => (self.inner.as_ref().len() as u64, n), SeekFrom::Current(n) => (self.pos, n), }; - let new_pos = if offset >= 0 { - base_pos.checked_add(offset as u64) - } else { - base_pos.checked_sub((offset.wrapping_neg()) as u64) - }; - match new_pos { + match base_pos.checked_add_signed(offset) { Some(n) => { self.pos = n; Ok(self.pos) diff --git a/library/std/src/io/error.rs b/library/std/src/io/error.rs index 51666c0a3c..59a9cd781c 100644 --- a/library/std/src/io/error.rs +++ b/library/std/src/io/error.rs @@ -473,6 +473,7 @@ impl Error { /// # } /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[must_use] #[inline] pub fn from_raw_os_error(code: i32) -> Error { Error { repr: Repr::Os(code) } @@ -657,6 +658,7 @@ impl Error { /// } /// ``` #[stable(feature = "io_error_inner", since = "1.3.0")] + #[must_use = "`self` will be dropped if the result is not used"] #[inline] pub fn into_inner(self) -> Option> { match self.repr { diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index e8466fa06b..abe29ba0f7 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -316,11 +316,12 @@ impl Drop for Guard<'_> { } } -// A few methods below (read_to_string, read_line) will append data into a -// `String` buffer, but we need to be pretty careful when doing this. The -// implementation will just call `.as_mut_vec()` and then delegate to a -// byte-oriented reading method, but we must ensure that when returning we never -// leave `buf` in a state such that it contains invalid UTF-8 in its bounds. +// Several `read_to_string` and `read_line` methods in the standard library will +// append data into a `String` buffer, but we need to be pretty careful when +// doing this. The implementation will just call `.as_mut_vec()` and then +// delegate to a byte-oriented reading method, but we must ensure that when +// returning we never leave `buf` in a state such that it contains invalid UTF-8 +// in its bounds. // // To this end, we use an RAII guard (to protect against panics) which updates // the length of the string when it is dropped. This guard initially truncates @@ -334,21 +335,19 @@ impl Drop for Guard<'_> { // 2. We're passing a raw buffer to the function `f`, and it is expected that // the function only *appends* bytes to the buffer. We'll get undefined // behavior if existing bytes are overwritten to have non-UTF-8 data. -fn append_to_string(buf: &mut String, f: F) -> Result +pub(crate) unsafe fn append_to_string(buf: &mut String, f: F) -> Result where F: FnOnce(&mut Vec) -> Result, { - unsafe { - let mut g = Guard { len: buf.len(), buf: buf.as_mut_vec() }; - let ret = f(g.buf); - if str::from_utf8(&g.buf[g.len..]).is_err() { - ret.and_then(|_| { - Err(Error::new_const(ErrorKind::InvalidData, &"stream did not contain valid UTF-8")) - }) - } else { - g.len = g.buf.len(); - ret - } + let mut g = Guard { len: buf.len(), buf: buf.as_mut_vec() }; + let ret = f(g.buf); + if str::from_utf8(&g.buf[g.len..]).is_err() { + ret.and_then(|_| { + Err(Error::new_const(ErrorKind::InvalidData, &"stream did not contain valid UTF-8")) + }) + } else { + g.len = g.buf.len(); + ret } } @@ -361,23 +360,19 @@ where // // Because we're extending the buffer with uninitialized data for trusted // readers, we need to make sure to truncate that if any of this panics. -fn read_to_end(r: &mut R, buf: &mut Vec) -> Result { - read_to_end_with_reservation(r, buf, |_| 32) -} - -fn read_to_end_with_reservation( - r: &mut R, - buf: &mut Vec, - mut reservation_size: F, -) -> Result -where - R: Read + ?Sized, - F: FnMut(&R) -> usize, -{ +pub(crate) fn default_read_to_end(r: &mut R, buf: &mut Vec) -> Result { let start_len = buf.len(); + let start_cap = buf.capacity(); let mut g = Guard { len: buf.len(), buf }; loop { - if g.len == g.buf.len() { + // If we've read all the way up to the capacity, reserve more space. + if g.len == g.buf.capacity() { + g.buf.reserve(32); + } + + // Initialize any excess capacity and adjust the length so we can write + // to it. + if g.buf.len() < g.buf.capacity() { unsafe { // FIXME(danielhenrymantilla): #42788 // @@ -387,7 +382,6 @@ where // - Only the standard library gets to soundly "ignore" this, // based on its privileged knowledge of unstable rustc // internals; - g.buf.reserve(reservation_size(r)); let capacity = g.buf.capacity(); g.buf.set_len(capacity); r.initializer().initialize(&mut g.buf[g.len..]); @@ -404,12 +398,49 @@ where assert!(n <= buf.len()); g.len += n; } - Err(ref e) if e.kind() == ErrorKind::Interrupted => {} + Err(ref e) if e.kind() == ErrorKind::Interrupted => continue, Err(e) => return Err(e), } + + if g.len == g.buf.capacity() && g.buf.capacity() == start_cap { + // The buffer might be an exact fit. Let's read into a probe buffer + // and see if it returns `Ok(0)`. If so, we've avoided an + // unnecessary doubling of the capacity. But if not, append the + // probe buffer to the primary buffer and let its capacity grow. + let mut probe = [0u8; 32]; + + loop { + match r.read(&mut probe) { + Ok(0) => return Ok(g.len - start_len), + Ok(n) => { + g.buf.extend_from_slice(&probe[..n]); + g.len += n; + break; + } + Err(ref e) if e.kind() == ErrorKind::Interrupted => continue, + Err(e) => return Err(e), + } + } + } } } +pub(crate) fn default_read_to_string( + r: &mut R, + buf: &mut String, +) -> Result { + // Note that we do *not* call `r.read_to_end()` here. We are passing + // `&mut Vec` (the raw contents of `buf`) into the `read_to_end` + // method to fill it up. An arbitrary implementation could overwrite the + // entire contents of the vector, not just append to it (which is what + // we are expecting). + // + // To prevent extraneously checking the UTF-8-ness of the entire buffer + // we pass it to our hardcoded `default_read_to_end` implementation which + // we know is guaranteed to only read data into the end of the buffer. + unsafe { append_to_string(buf, |b| default_read_to_end(r, b)) } +} + pub(crate) fn default_read_vectored(read: F, bufs: &mut [IoSliceMut<'_>]) -> Result where F: FnOnce(&mut [u8]) -> Result, @@ -700,7 +731,7 @@ pub trait Read { /// [`std::fs::read`]: crate::fs::read #[stable(feature = "rust1", since = "1.0.0")] fn read_to_end(&mut self, buf: &mut Vec) -> Result { - read_to_end(self, buf) + default_read_to_end(self, buf) } /// Read all bytes until EOF in this source, appending them to `buf`. @@ -743,16 +774,7 @@ pub trait Read { /// [`std::fs::read_to_string`]: crate::fs::read_to_string #[stable(feature = "rust1", since = "1.0.0")] fn read_to_string(&mut self, buf: &mut String) -> Result { - // Note that we do *not* call `.read_to_end()` here. We are passing - // `&mut Vec` (the raw contents of `buf`) into the `read_to_end` - // method to fill it up. An arbitrary implementation could overwrite the - // entire contents of the vector, not just append to it (which is what - // we are expecting). - // - // To prevent extraneously checking the UTF-8-ness of the entire buffer - // we pass it to our hardcoded `read_to_end` implementation which we - // know is guaranteed to only read data into the end of the buffer. - append_to_string(buf, |b| read_to_end(self, b)) + default_read_to_string(self, buf) } /// Read the exact number of bytes required to fill `buf`. @@ -854,8 +876,8 @@ pub trait Read { /// Transforms this `Read` instance to an [`Iterator`] over its bytes. /// - /// The returned type implements [`Iterator`] where the `Item` is - /// [`Result`]`<`[`u8`]`, `[`io::Error`]`>`. + /// The returned type implements [`Iterator`] where the [`Item`] is + /// [Result]<[u8], [io::Error]>. /// The yielded item is [`Ok`] if a byte was successfully read and [`Err`] /// otherwise. EOF is mapped to returning [`None`] from this iterator. /// @@ -863,9 +885,10 @@ pub trait Read { /// /// [`File`]s implement `Read`: /// - /// [`File`]: crate::fs::File - /// [`Result`]: crate::result::Result - /// [`io::Error`]: self::Error + /// [`Item`]: Iterator::Item + /// [`File`]: crate::fs::File "fs::File" + /// [Result]: crate::result::Result "Result" + /// [io::Error]: self::Error "io::Error" /// /// ```no_run /// use std::io; @@ -988,6 +1011,11 @@ pub trait Read { /// need more control over performance, and in those cases you should definitely use /// [`Read::read_to_string`] directly. /// +/// Note that in some special cases, such as when reading files, this function will +/// pre-allocate memory based on the size of the input it is reading. In those +/// cases, the performance should be as good as if you had used +/// [`Read::read_to_string`] with a manually pre-allocated buffer. +/// /// # Errors /// /// This function forces you to handle errors because the output (the `String`) @@ -1178,6 +1206,7 @@ impl<'a> IoSlice<'a> { /// /// Panics on Windows if the slice is larger than 4GB. #[stable(feature = "iovec", since = "1.36.0")] + #[must_use] #[inline] pub fn new(buf: &'a [u8]) -> IoSlice<'a> { IoSlice(sys::io::IoSlice::new(buf)) @@ -1611,7 +1640,7 @@ pub trait Write { /// encountered. /// /// This method is primarily used to interface with the - /// [`format_args!()`] macro, but it is rare that this should + /// [`format_args!()`] macro, and it is rare that this should /// explicitly be called. The [`write!()`] macro should be favored to /// invoke this method instead. /// @@ -2184,20 +2213,20 @@ pub trait BufRead: Read { // Note that we are not calling the `.read_until` method here, but // rather our hardcoded implementation. For more details as to why, see // the comments in `read_to_end`. - append_to_string(buf, |b| read_until(self, b'\n', b)) + unsafe { append_to_string(buf, |b| read_until(self, b'\n', b)) } } /// Returns an iterator over the contents of this reader split on the byte /// `byte`. /// /// The iterator returned from this function will return instances of - /// [`io::Result`]`<`[`Vec`]`>`. Each vector returned will *not* have + /// [io::Result]<[Vec]\>. Each vector returned will *not* have /// the delimiter byte at the end. /// /// This function will yield errors whenever [`read_until`] would have /// also yielded an error. /// - /// [`io::Result`]: self::Result + /// [io::Result]: self::Result "io::Result" /// [`read_until`]: BufRead::read_until /// /// # Examples @@ -2228,10 +2257,10 @@ pub trait BufRead: Read { /// Returns an iterator over the lines of this reader. /// /// The iterator returned from this function will yield instances of - /// [`io::Result`]`<`[`String`]`>`. Each string returned will *not* have a newline + /// [io::Result]<[String]>. Each string returned will *not* have a newline /// byte (the `0xA` byte) or `CRLF` (`0xD`, `0xA` bytes) at the end. /// - /// [`io::Result`]: self::Result + /// [io::Result]: self::Result "io::Result" /// /// # Examples /// @@ -2583,13 +2612,6 @@ impl Read for Take { unsafe fn initializer(&self) -> Initializer { self.inner.initializer() } - - fn read_to_end(&mut self, buf: &mut Vec) -> Result { - // Pass in a reservation_size closure that respects the current value - // of limit for each read. If we hit the read limit, this prevents the - // final zero-byte read from allocating again. - read_to_end_with_reservation(self, buf, |self_| cmp::min(self_.limit, 32) as usize) - } } #[stable(feature = "rust1", since = "1.0.0")] diff --git a/library/std/src/io/stdio.rs b/library/std/src/io/stdio.rs index 14a6330371..9389501e01 100644 --- a/library/std/src/io/stdio.rs +++ b/library/std/src/io/stdio.rs @@ -256,6 +256,7 @@ pub struct Stdin { /// Ok(()) /// } /// ``` +#[must_use = "if unused stdin will immediately unlock"] #[stable(feature = "rust1", since = "1.0.0")] pub struct StdinLock<'a> { inner: MutexGuard<'a, BufReader>, @@ -463,6 +464,7 @@ impl Stdin { /// println!("got a line: {}", line.unwrap()); /// } /// ``` + #[must_use = "`self` will be dropped if the result is not used"] #[unstable(feature = "stdin_forwarders", issue = "87096")] pub fn lines(self) -> Lines> { self.into_locked().lines() @@ -624,6 +626,7 @@ pub struct Stdout { /// When operating in a console, the Windows implementation of this stream does not support /// non-UTF-8 byte sequences. Attempting to write bytes that are not valid UTF-8 will return /// an error. +#[must_use = "if unused stdout will immediately unlock"] #[stable(feature = "rust1", since = "1.0.0")] pub struct StdoutLock<'a> { inner: ReentrantMutexGuard<'a, RefCell>>, @@ -907,6 +910,7 @@ pub struct Stderr { /// When operating in a console, the Windows implementation of this stream does not support /// non-UTF-8 byte sequences. Attempting to write bytes that are not valid UTF-8 will return /// an error. +#[must_use = "if unused stderr will immediately unlock"] #[stable(feature = "rust1", since = "1.0.0")] pub struct StderrLock<'a> { inner: ReentrantMutexGuard<'a, RefCell>, diff --git a/library/std/src/io/tests.rs b/library/std/src/io/tests.rs index 1beb72a9a5..0321a2b60b 100644 --- a/library/std/src/io/tests.rs +++ b/library/std/src/io/tests.rs @@ -290,7 +290,7 @@ fn bench_read_to_end(b: &mut test::Bencher) { b.iter(|| { let mut lr = repeat(1).take(10000000); let mut vec = Vec::with_capacity(1024); - super::read_to_end(&mut lr, &mut vec) + super::default_read_to_end(&mut lr, &mut vec) }); } @@ -362,24 +362,12 @@ impl<'a> Read for ExampleSliceReader<'a> { fn test_read_to_end_capacity() -> io::Result<()> { let input = &b"foo"[..]; - // read_to_end() generally needs to over-allocate, both for efficiency - // and so that it can distinguish EOF. Assert that this is the case - // with this simple ExampleSliceReader struct, which uses the default - // implementation of read_to_end. Even though vec1 is allocated with - // exactly enough capacity for the read, read_to_end will allocate more - // space here. + // read_to_end() takes care not to over-allocate when a buffer is the + // exact size needed. let mut vec1 = Vec::with_capacity(input.len()); ExampleSliceReader { slice: input }.read_to_end(&mut vec1)?; assert_eq!(vec1.len(), input.len()); - assert!(vec1.capacity() > input.len(), "allocated more"); - - // However, std::io::Take includes an implementation of read_to_end - // that will not allocate when the limit has already been reached. In - // this case, vec2 never grows. - let mut vec2 = Vec::with_capacity(input.len()); - ExampleSliceReader { slice: input }.take(input.len() as u64).read_to_end(&mut vec2)?; - assert_eq!(vec2.len(), input.len()); - assert_eq!(vec2.capacity(), input.len(), "did not allocate more"); + assert_eq!(vec1.capacity(), input.len(), "did not allocate more"); Ok(()) } diff --git a/library/std/src/io/util.rs b/library/std/src/io/util.rs index a8812f197d..2f3520ae7a 100644 --- a/library/std/src/io/util.rs +++ b/library/std/src/io/util.rs @@ -19,7 +19,7 @@ pub struct Empty; /// Constructs a new handle to an empty reader. /// -/// All reads from the returned reader will return [`Ok`]`(0)`. +/// All reads from the returned reader will return [Ok]\(0). /// /// # Examples /// diff --git a/library/std/src/keyword_docs.rs b/library/std/src/keyword_docs.rs index 749a441d18..2e93807037 100644 --- a/library/std/src/keyword_docs.rs +++ b/library/std/src/keyword_docs.rs @@ -77,7 +77,7 @@ mod as_keyword {} /// '_inner: for j in 1..=200 { /// println!(" inner iteration (j): {}", j); /// if j >= 3 { -/// // breaks from inner loop, let's outer loop continue. +/// // breaks from inner loop, lets outer loop continue. /// break; /// } /// if i >= 2 { @@ -119,7 +119,7 @@ mod break_keyword {} #[doc(keyword = "const")] // -/// Compile-time constants and compile-time evaluable functions. +/// Compile-time constants, compile-time evaluable functions, and raw pointers. /// /// ## Compile-time constants /// diff --git a/library/std/src/lazy.rs b/library/std/src/lazy.rs index 5afdb799f0..d745096235 100644 --- a/library/std/src/lazy.rs +++ b/library/std/src/lazy.rs @@ -171,6 +171,7 @@ impl Eq for SyncOnceCell {} impl SyncOnceCell { /// Creates a new empty cell. #[unstable(feature = "once_cell", issue = "74465")] + #[must_use] pub const fn new() -> SyncOnceCell { SyncOnceCell { once: Once::new(), diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 3a1eb625b5..1d2d26b8f0 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -195,6 +195,15 @@ test(no_crate_inject, attr(deny(warnings))), test(attr(allow(dead_code, deprecated, unused_variables, unused_mut))) )] +#![cfg_attr( + not(bootstrap), + doc(cfg_hide( + not(test), + not(any(test, bootstrap)), + no_global_oom_handling, + not(no_global_oom_handling) + )) +)] // Don't link to std. We are std. #![no_std] #![warn(deprecated_in_future)] @@ -234,6 +243,7 @@ #![feature(atomic_mut_ptr)] #![feature(auto_traits)] #![feature(bench_black_box)] +#![feature(bool_to_option)] #![feature(box_syntax)] #![feature(c_unwind)] #![feature(c_variadic)] @@ -247,7 +257,6 @@ #![feature(const_cstr_unchecked)] #![feature(const_fn_floating_point_arithmetic)] #![feature(const_fn_fn_ptr_basics)] -#![cfg_attr(bootstrap, feature(const_fn_transmute))] #![feature(const_format_args)] #![feature(const_io_structs)] #![feature(const_ip)] @@ -259,13 +268,15 @@ #![feature(const_trait_impl)] #![feature(container_error_extra)] #![feature(core_intrinsics)] +#![feature(core_panic)] #![feature(custom_test_frameworks)] #![feature(decl_macro)] #![feature(doc_cfg)] +#![cfg_attr(not(bootstrap), feature(doc_cfg_hide))] #![feature(doc_keyword)] #![feature(doc_masked)] #![feature(doc_notable_trait)] -#![cfg_attr(not(bootstrap), feature(doc_primitive))] +#![feature(doc_primitive)] #![feature(dropck_eyepatch)] #![feature(duration_checked_float)] #![feature(duration_constants)] @@ -296,6 +307,8 @@ #![feature(maybe_uninit_slice)] #![feature(maybe_uninit_uninit_array)] #![feature(min_specialization)] +#![feature(mixed_integer_ops)] +#![cfg_attr(not(bootstrap), feature(must_not_suspend))] #![feature(needs_panic_runtime)] #![feature(negative_impls)] #![feature(never_type)] @@ -329,7 +342,6 @@ #![feature(total_cmp)] #![feature(trace_macros)] #![feature(try_blocks)] -#![feature(try_reserve)] #![feature(try_reserve_kind)] #![feature(unboxed_closures)] #![feature(unwrap_infallible)] @@ -519,20 +531,20 @@ pub mod task { pub use alloc::task::*; } -// Platform-abstraction modules +// The runtime entry point and a few unstable public functions used by the +// compiler #[macro_use] -mod sys_common; +pub mod rt; + +// Platform-abstraction modules mod sys; +mod sys_common; pub mod alloc; // Private support modules mod panicking; -// The runtime entry point and a few unstable public functions used by the -// compiler -pub mod rt; - #[path = "../../backtrace/src/lib.rs"] #[allow(dead_code, unused_attributes)] mod backtrace_rs; diff --git a/library/std/src/net/addr.rs b/library/std/src/net/addr.rs index 43d930677f..a689d2a56b 100644 --- a/library/std/src/net/addr.rs +++ b/library/std/src/net/addr.rs @@ -131,6 +131,7 @@ impl SocketAddr { /// assert_eq!(socket.port(), 8080); /// ``` #[stable(feature = "ip_addr", since = "1.7.0")] + #[must_use] pub fn new(ip: IpAddr, port: u16) -> SocketAddr { match ip { IpAddr::V4(a) => SocketAddr::V4(SocketAddrV4::new(a, port)), @@ -231,6 +232,7 @@ impl SocketAddr { /// assert_eq!(socket.is_ipv4(), true); /// assert_eq!(socket.is_ipv6(), false); /// ``` + #[must_use] #[stable(feature = "sockaddr_checker", since = "1.16.0")] #[rustc_const_unstable(feature = "const_socketaddr", issue = "82485")] pub const fn is_ipv4(&self) -> bool { @@ -252,6 +254,7 @@ impl SocketAddr { /// assert_eq!(socket.is_ipv4(), false); /// assert_eq!(socket.is_ipv6(), true); /// ``` + #[must_use] #[stable(feature = "sockaddr_checker", since = "1.16.0")] #[rustc_const_unstable(feature = "const_socketaddr", issue = "82485")] pub const fn is_ipv6(&self) -> bool { @@ -272,6 +275,7 @@ impl SocketAddrV4 { /// let socket = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[must_use] pub fn new(ip: Ipv4Addr, port: u16) -> SocketAddrV4 { SocketAddrV4 { inner: c::sockaddr_in { @@ -368,6 +372,7 @@ impl SocketAddrV6 { /// let socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 0, 0); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[must_use] pub fn new(ip: Ipv6Addr, port: u16, flowinfo: u32, scope_id: u32) -> SocketAddrV6 { SocketAddrV6 { inner: c::sockaddr_in6 { @@ -765,15 +770,15 @@ impl hash::Hash for SocketAddrV6 { /// /// * [`SocketAddr`]: [`to_socket_addrs`] is the identity function. /// -/// * [`SocketAddrV4`], [`SocketAddrV6`], `(`[`IpAddr`]`, `[`u16`]`)`, -/// `(`[`Ipv4Addr`]`, `[`u16`]`)`, `(`[`Ipv6Addr`]`, `[`u16`]`)`: +/// * [`SocketAddrV4`], [`SocketAddrV6`], ([IpAddr], [u16]), +/// ([Ipv4Addr], [u16]), ([Ipv6Addr], [u16]): /// [`to_socket_addrs`] constructs a [`SocketAddr`] trivially. /// -/// * `(`[`&str`]`, `[`u16`]`)`: [`&str`] should be either a string representation +/// * (&[str], [u16]): &[str] should be either a string representation /// of an [`IpAddr`] address as expected by [`FromStr`] implementation or a host /// name. [`u16`] is the port number. /// -/// * [`&str`]: the string should be either a string representation of a +/// * &[str]: the string should be either a string representation of a /// [`SocketAddr`] as expected by its [`FromStr`] implementation or a string like /// `:` pair where `` is a [`u16`] value. /// @@ -789,11 +794,10 @@ impl hash::Hash for SocketAddrV6 { /// Addresses returned by the operating system that are not IP addresses are /// silently ignored. /// -/// [`FromStr`]: crate::str::FromStr -/// [`&str`]: str -/// [`TcpStream`]: crate::net::TcpStream +/// [`FromStr`]: crate::str::FromStr "std::str::FromStr" +/// [`TcpStream`]: crate::net::TcpStream "net::TcpStream" /// [`to_socket_addrs`]: ToSocketAddrs::to_socket_addrs -/// [`UdpSocket`]: crate::net::UdpSocket +/// [`UdpSocket`]: crate::net::UdpSocket "net::UdpSocket" /// /// # Examples /// @@ -872,7 +876,7 @@ pub trait ToSocketAddrs { #[stable(feature = "rust1", since = "1.0.0")] type Iter: Iterator; - /// Converts this object to an iterator of resolved `SocketAddr`s. + /// Converts this object to an iterator of resolved [`SocketAddr`]s. /// /// The returned iterator might not actually yield any values depending on the /// outcome of any resolution performed. diff --git a/library/std/src/net/ip.rs b/library/std/src/net/ip.rs index 4165a7beaa..e5e9fedb61 100644 --- a/library/std/src/net/ip.rs +++ b/library/std/src/net/ip.rs @@ -233,6 +233,7 @@ impl IpAddr { /// ``` #[rustc_const_stable(feature = "const_ip", since = "1.50.0")] #[stable(feature = "ip_shared", since = "1.12.0")] + #[must_use] #[inline] pub const fn is_unspecified(&self) -> bool { match self { @@ -256,6 +257,7 @@ impl IpAddr { /// ``` #[rustc_const_stable(feature = "const_ip", since = "1.50.0")] #[stable(feature = "ip_shared", since = "1.12.0")] + #[must_use] #[inline] pub const fn is_loopback(&self) -> bool { match self { @@ -281,6 +283,7 @@ impl IpAddr { /// ``` #[rustc_const_unstable(feature = "const_ip", issue = "76205")] #[unstable(feature = "ip", issue = "27709")] + #[must_use] #[inline] pub const fn is_global(&self) -> bool { match self { @@ -304,6 +307,7 @@ impl IpAddr { /// ``` #[rustc_const_stable(feature = "const_ip", since = "1.50.0")] #[stable(feature = "ip_shared", since = "1.12.0")] + #[must_use] #[inline] pub const fn is_multicast(&self) -> bool { match self { @@ -332,6 +336,7 @@ impl IpAddr { /// ``` #[rustc_const_unstable(feature = "const_ip", issue = "76205")] #[unstable(feature = "ip", issue = "27709")] + #[must_use] #[inline] pub const fn is_documentation(&self) -> bool { match self { @@ -340,6 +345,31 @@ impl IpAddr { } } + /// Returns [`true`] if this address is in a range designated for benchmarking. + /// + /// See the documentation for [`Ipv4Addr::is_benchmarking()`] and + /// [`Ipv6Addr::is_benchmarking()`] for more details. + /// + /// # Examples + /// + /// ``` + /// #![feature(ip)] + /// + /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; + /// + /// assert_eq!(IpAddr::V4(Ipv4Addr::new(198, 19, 255, 255)).is_benchmarking(), true); + /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0x2001, 0x2, 0, 0, 0, 0, 0, 0)).is_benchmarking(), true); + /// ``` + #[unstable(feature = "ip", issue = "27709")] + #[must_use] + #[inline] + pub const fn is_benchmarking(&self) -> bool { + match self { + IpAddr::V4(ip) => ip.is_benchmarking(), + IpAddr::V6(ip) => ip.is_benchmarking(), + } + } + /// Returns [`true`] if this address is an [`IPv4` address], and [`false`] /// otherwise. /// @@ -355,6 +385,7 @@ impl IpAddr { /// ``` #[rustc_const_stable(feature = "const_ip", since = "1.50.0")] #[stable(feature = "ipaddr_checker", since = "1.16.0")] + #[must_use] #[inline] pub const fn is_ipv4(&self) -> bool { matches!(self, IpAddr::V4(_)) @@ -375,6 +406,7 @@ impl IpAddr { /// ``` #[rustc_const_stable(feature = "const_ip", since = "1.50.0")] #[stable(feature = "ipaddr_checker", since = "1.16.0")] + #[must_use] #[inline] pub const fn is_ipv6(&self) -> bool { matches!(self, IpAddr::V6(_)) @@ -394,6 +426,8 @@ impl IpAddr { /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x7f00, 0x1)).to_canonical().is_loopback(), true); /// ``` #[inline] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[rustc_const_unstable(feature = "const_ip", issue = "76205")] #[unstable(feature = "ip", issue = "27709")] pub const fn to_canonical(&self) -> IpAddr { @@ -418,6 +452,7 @@ impl Ipv4Addr { /// ``` #[rustc_const_stable(feature = "const_ipv4", since = "1.32.0")] #[stable(feature = "rust1", since = "1.0.0")] + #[must_use] #[inline] pub const fn new(a: u8, b: u8, c: u8, d: u8) -> Ipv4Addr { // `s_addr` is stored as BE on all machine and the array is in BE order. @@ -502,6 +537,7 @@ impl Ipv4Addr { /// ``` #[rustc_const_stable(feature = "const_ipv4", since = "1.32.0")] #[stable(feature = "ip_shared", since = "1.12.0")] + #[must_use] #[inline] pub const fn is_unspecified(&self) -> bool { self.inner.s_addr == 0 @@ -523,6 +559,7 @@ impl Ipv4Addr { /// ``` #[rustc_const_stable(feature = "const_ipv4", since = "1.50.0")] #[stable(since = "1.7.0", feature = "ip_17")] + #[must_use] #[inline] pub const fn is_loopback(&self) -> bool { self.octets()[0] == 127 @@ -553,6 +590,7 @@ impl Ipv4Addr { /// ``` #[rustc_const_stable(feature = "const_ipv4", since = "1.50.0")] #[stable(since = "1.7.0", feature = "ip_17")] + #[must_use] #[inline] pub const fn is_private(&self) -> bool { match self.octets() { @@ -580,6 +618,7 @@ impl Ipv4Addr { /// ``` #[rustc_const_stable(feature = "const_ipv4", since = "1.50.0")] #[stable(since = "1.7.0", feature = "ip_17")] + #[must_use] #[inline] pub const fn is_link_local(&self) -> bool { matches!(self.octets(), [169, 254, ..]) @@ -655,6 +694,7 @@ impl Ipv4Addr { /// ``` #[rustc_const_unstable(feature = "const_ipv4", issue = "76205")] #[unstable(feature = "ip", issue = "27709")] + #[must_use] #[inline] pub const fn is_global(&self) -> bool { // check if this address is 192.0.0.9 or 192.0.0.10. These addresses are the only two @@ -695,6 +735,7 @@ impl Ipv4Addr { /// ``` #[rustc_const_unstable(feature = "const_ipv4", issue = "76205")] #[unstable(feature = "ip", issue = "27709")] + #[must_use] #[inline] pub const fn is_shared(&self) -> bool { self.octets()[0] == 100 && (self.octets()[1] & 0b1100_0000 == 0b0100_0000) @@ -720,6 +761,7 @@ impl Ipv4Addr { /// ``` #[rustc_const_unstable(feature = "const_ipv4", issue = "76205")] #[unstable(feature = "ip", issue = "27709")] + #[must_use] #[inline] pub const fn is_benchmarking(&self) -> bool { self.octets()[0] == 198 && (self.octets()[1] & 0xfe) == 18 @@ -754,6 +796,7 @@ impl Ipv4Addr { /// ``` #[rustc_const_unstable(feature = "const_ipv4", issue = "76205")] #[unstable(feature = "ip", issue = "27709")] + #[must_use] #[inline] pub const fn is_reserved(&self) -> bool { self.octets()[0] & 240 == 240 && !self.is_broadcast() @@ -777,6 +820,7 @@ impl Ipv4Addr { /// ``` #[rustc_const_stable(feature = "const_ipv4", since = "1.50.0")] #[stable(since = "1.7.0", feature = "ip_17")] + #[must_use] #[inline] pub const fn is_multicast(&self) -> bool { self.octets()[0] >= 224 && self.octets()[0] <= 239 @@ -798,6 +842,7 @@ impl Ipv4Addr { /// ``` #[rustc_const_stable(feature = "const_ipv4", since = "1.50.0")] #[stable(since = "1.7.0", feature = "ip_17")] + #[must_use] #[inline] pub const fn is_broadcast(&self) -> bool { u32::from_be_bytes(self.octets()) == u32::from_be_bytes(Self::BROADCAST.octets()) @@ -825,6 +870,7 @@ impl Ipv4Addr { /// ``` #[rustc_const_stable(feature = "const_ipv4", since = "1.50.0")] #[stable(since = "1.7.0", feature = "ip_17")] + #[must_use] #[inline] pub const fn is_documentation(&self) -> bool { match self.octets() { @@ -857,6 +903,8 @@ impl Ipv4Addr { /// ``` #[rustc_const_stable(feature = "const_ipv4", since = "1.50.0")] #[stable(feature = "rust1", since = "1.0.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[inline] pub const fn to_ipv6_compatible(&self) -> Ipv6Addr { let [a, b, c, d] = self.octets(); @@ -882,6 +930,8 @@ impl Ipv4Addr { /// ``` #[rustc_const_stable(feature = "const_ipv4", since = "1.50.0")] #[stable(feature = "rust1", since = "1.0.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[inline] pub const fn to_ipv6_mapped(&self) -> Ipv6Addr { let [a, b, c, d] = self.octets(); @@ -1166,9 +1216,9 @@ impl Ipv6Addr { /// /// let addr = Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff); /// ``` - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_fn_transmute))] #[rustc_const_stable(feature = "const_ipv6", since = "1.32.0")] #[stable(feature = "rust1", since = "1.0.0")] + #[must_use] #[inline] pub const fn new(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16, h: u16) -> Ipv6Addr { let addr16 = [ @@ -1228,7 +1278,6 @@ impl Ipv6Addr { /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).segments(), /// [0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff]); /// ``` - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_fn_transmute))] #[rustc_const_stable(feature = "const_ipv6", since = "1.50.0")] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -1267,6 +1316,7 @@ impl Ipv6Addr { /// ``` #[rustc_const_stable(feature = "const_ipv6", since = "1.50.0")] #[stable(since = "1.7.0", feature = "ip_17")] + #[must_use] #[inline] pub const fn is_unspecified(&self) -> bool { u128::from_be_bytes(self.octets()) == u128::from_be_bytes(Ipv6Addr::UNSPECIFIED.octets()) @@ -1290,6 +1340,7 @@ impl Ipv6Addr { /// ``` #[rustc_const_stable(feature = "const_ipv6", since = "1.50.0")] #[stable(since = "1.7.0", feature = "ip_17")] + #[must_use] #[inline] pub const fn is_loopback(&self) -> bool { u128::from_be_bytes(self.octets()) == u128::from_be_bytes(Ipv6Addr::LOCALHOST.octets()) @@ -1316,6 +1367,7 @@ impl Ipv6Addr { /// ``` #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")] #[unstable(feature = "ip", issue = "27709")] + #[must_use] #[inline] pub const fn is_global(&self) -> bool { match self.multicast_scope() { @@ -1343,6 +1395,7 @@ impl Ipv6Addr { /// ``` #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")] #[unstable(feature = "ip", issue = "27709")] + #[must_use] #[inline] pub const fn is_unique_local(&self) -> bool { (self.segments()[0] & 0xfe00) == 0xfc00 @@ -1371,6 +1424,7 @@ impl Ipv6Addr { /// ``` #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")] #[unstable(feature = "ip", issue = "27709")] + #[must_use] #[inline] pub const fn is_unicast(&self) -> bool { !self.is_multicast() @@ -1422,6 +1476,7 @@ impl Ipv6Addr { /// ``` #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")] #[unstable(feature = "ip", issue = "27709")] + #[must_use] #[inline] pub const fn is_unicast_link_local(&self) -> bool { (self.segments()[0] & 0xffc0) == 0xfe80 @@ -1446,11 +1501,35 @@ impl Ipv6Addr { /// ``` #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")] #[unstable(feature = "ip", issue = "27709")] + #[must_use] #[inline] pub const fn is_documentation(&self) -> bool { (self.segments()[0] == 0x2001) && (self.segments()[1] == 0xdb8) } + /// Returns [`true`] if this is an address reserved for benchmarking (`2001:2::/48`). + /// + /// This property is defined in [IETF RFC 5180], where it is mistakenly specified as covering the range `2001:0200::/48`. + /// This is corrected in [IETF RFC Errata 1752] to `2001:0002::/48`. + /// + /// [IETF RFC 5180]: https://tools.ietf.org/html/rfc5180 + /// [IETF RFC Errata 1752]: https://www.rfc-editor.org/errata_search.php?eid=1752 + /// + /// ``` + /// #![feature(ip)] + /// + /// use std::net::Ipv6Addr; + /// + /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc613, 0x0).is_benchmarking(), false); + /// assert_eq!(Ipv6Addr::new(0x2001, 0x2, 0, 0, 0, 0, 0, 0).is_benchmarking(), true); + /// ``` + #[unstable(feature = "ip", issue = "27709")] + #[must_use] + #[inline] + pub const fn is_benchmarking(&self) -> bool { + (self.segments()[0] == 0x2001) && (self.segments()[1] == 0x2) && (self.segments()[2] == 0) + } + /// Returns [`true`] if the address is a globally routable unicast address. /// /// The following return false: @@ -1483,6 +1562,7 @@ impl Ipv6Addr { /// ``` #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")] #[unstable(feature = "ip", issue = "27709")] + #[must_use] #[inline] pub const fn is_unicast_global(&self) -> bool { self.is_unicast() @@ -1544,6 +1624,7 @@ impl Ipv6Addr { /// ``` #[rustc_const_stable(feature = "const_ipv6", since = "1.50.0")] #[stable(since = "1.7.0", feature = "ip_17")] + #[must_use] #[inline] pub const fn is_multicast(&self) -> bool { (self.segments()[0] & 0xff00) == 0xff00 @@ -1573,6 +1654,8 @@ impl Ipv6Addr { /// ``` #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")] #[unstable(feature = "ip", issue = "27709")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[inline] pub const fn to_ipv4_mapped(&self) -> Option { match self.octets() { @@ -1591,7 +1674,7 @@ impl Ipv6Addr { /// `::a.b.c.d` and `::ffff:a.b.c.d` become `a.b.c.d` /// All addresses *not* starting with either all zeroes or `::ffff` will return `None`. /// - /// [IPv4 address]: Ipv4Addr + /// [`IPv4` address]: Ipv4Addr /// [IPv4-compatible]: Ipv6Addr#ipv4-compatible-ipv6-addresses /// [IPv4-mapped]: Ipv6Addr#ipv4-mapped-ipv6-addresses /// [IETF RFC 4291 section 2.5.5.1]: https://tools.ietf.org/html/rfc4291#section-2.5.5.1 @@ -1610,6 +1693,8 @@ impl Ipv6Addr { /// ``` #[rustc_const_stable(feature = "const_ipv6", since = "1.50.0")] #[stable(feature = "rust1", since = "1.0.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[inline] pub const fn to_ipv4(&self) -> Option { if let [0, 0, 0, 0, 0, 0 | 0xffff, ab, cd] = self.segments() { @@ -1633,9 +1718,11 @@ impl Ipv6Addr { /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x7f00, 0x1).is_loopback(), false); /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x7f00, 0x1).to_canonical().is_loopback(), true); /// ``` - #[inline] #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")] #[unstable(feature = "ip", issue = "27709")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] pub const fn to_canonical(&self) -> IpAddr { if let Some(mapped) = self.to_ipv4_mapped() { return IpAddr::V4(mapped); diff --git a/library/std/src/net/ip/tests.rs b/library/std/src/net/ip/tests.rs index dbfab9dde4..babc854cd1 100644 --- a/library/std/src/net/ip/tests.rs +++ b/library/std/src/net/ip/tests.rs @@ -224,6 +224,7 @@ fn ip_properties() { let global: u8 = 1 << 2; let multicast: u8 = 1 << 3; let doc: u8 = 1 << 4; + let benchmarking: u8 = 1 << 5; if ($mask & unspec) == unspec { assert!(ip!($s).is_unspecified()); @@ -254,6 +255,12 @@ fn ip_properties() { } else { assert!(!ip!($s).is_documentation()); } + + if ($mask & benchmarking) == benchmarking { + assert!(ip!($s).is_benchmarking()); + } else { + assert!(!ip!($s).is_benchmarking()); + } }}; } @@ -262,6 +269,7 @@ fn ip_properties() { let global: u8 = 1 << 2; let multicast: u8 = 1 << 3; let doc: u8 = 1 << 4; + let benchmarking: u8 = 1 << 5; check!("0.0.0.0", unspec); check!("0.0.0.1"); @@ -280,9 +288,9 @@ fn ip_properties() { check!("239.255.255.255", global | multicast); check!("255.255.255.255"); // make sure benchmarking addresses are not global - check!("198.18.0.0"); - check!("198.18.54.2"); - check!("198.19.255.255"); + check!("198.18.0.0", benchmarking); + check!("198.18.54.2", benchmarking); + check!("198.19.255.255", benchmarking); // make sure addresses reserved for protocol assignment are not global check!("192.0.0.0"); check!("192.0.0.255"); @@ -313,6 +321,7 @@ fn ip_properties() { check!("ff08::", multicast); check!("ff0e::", global | multicast); check!("2001:db8:85a3::8a2e:370:7334", doc); + check!("2001:2::ac32:23ff:21", global | benchmarking); check!("102:304:506:708:90a:b0c:d0e:f10", global); } @@ -467,21 +476,22 @@ fn ipv6_properties() { assert_eq!(&ip!($s).octets(), octets); assert_eq!(Ipv6Addr::from(*octets), ip!($s)); - let unspecified: u16 = 1 << 0; - let loopback: u16 = 1 << 1; - let unique_local: u16 = 1 << 2; - let global: u16 = 1 << 3; - let unicast_link_local: u16 = 1 << 4; - let unicast_global: u16 = 1 << 7; - let documentation: u16 = 1 << 8; - let multicast_interface_local: u16 = 1 << 9; - let multicast_link_local: u16 = 1 << 10; - let multicast_realm_local: u16 = 1 << 11; - let multicast_admin_local: u16 = 1 << 12; - let multicast_site_local: u16 = 1 << 13; - let multicast_organization_local: u16 = 1 << 14; - let multicast_global: u16 = 1 << 15; - let multicast: u16 = multicast_interface_local + let unspecified: u32 = 1 << 0; + let loopback: u32 = 1 << 1; + let unique_local: u32 = 1 << 2; + let global: u32 = 1 << 3; + let unicast_link_local: u32 = 1 << 4; + let unicast_global: u32 = 1 << 7; + let documentation: u32 = 1 << 8; + let benchmarking: u32 = 1 << 16; + let multicast_interface_local: u32 = 1 << 9; + let multicast_link_local: u32 = 1 << 10; + let multicast_realm_local: u32 = 1 << 11; + let multicast_admin_local: u32 = 1 << 12; + let multicast_site_local: u32 = 1 << 13; + let multicast_organization_local: u32 = 1 << 14; + let multicast_global: u32 = 1 << 15; + let multicast: u32 = multicast_interface_local | multicast_admin_local | multicast_global | multicast_link_local @@ -524,6 +534,11 @@ fn ipv6_properties() { } else { assert!(!ip!($s).is_documentation()); } + if ($mask & benchmarking) == benchmarking { + assert!(ip!($s).is_benchmarking()); + } else { + assert!(!ip!($s).is_benchmarking()); + } if ($mask & multicast) != 0 { assert!(ip!($s).multicast_scope().is_some()); assert!(ip!($s).is_multicast()); @@ -562,20 +577,21 @@ fn ipv6_properties() { } } - let unspecified: u16 = 1 << 0; - let loopback: u16 = 1 << 1; - let unique_local: u16 = 1 << 2; - let global: u16 = 1 << 3; - let unicast_link_local: u16 = 1 << 4; - let unicast_global: u16 = 1 << 7; - let documentation: u16 = 1 << 8; - let multicast_interface_local: u16 = 1 << 9; - let multicast_link_local: u16 = 1 << 10; - let multicast_realm_local: u16 = 1 << 11; - let multicast_admin_local: u16 = 1 << 12; - let multicast_site_local: u16 = 1 << 13; - let multicast_organization_local: u16 = 1 << 14; - let multicast_global: u16 = 1 << 15; + let unspecified: u32 = 1 << 0; + let loopback: u32 = 1 << 1; + let unique_local: u32 = 1 << 2; + let global: u32 = 1 << 3; + let unicast_link_local: u32 = 1 << 4; + let unicast_global: u32 = 1 << 7; + let documentation: u32 = 1 << 8; + let benchmarking: u32 = 1 << 16; + let multicast_interface_local: u32 = 1 << 9; + let multicast_link_local: u32 = 1 << 10; + let multicast_realm_local: u32 = 1 << 11; + let multicast_admin_local: u32 = 1 << 12; + let multicast_site_local: u32 = 1 << 13; + let multicast_organization_local: u32 = 1 << 14; + let multicast_global: u32 = 1 << 15; check!("::", &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], unspecified); @@ -671,6 +687,12 @@ fn ipv6_properties() { documentation ); + check!( + "2001:2::ac32:23ff:21", + &[0x20, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0xac, 0x32, 0x23, 0xff, 0, 0x21], + global | unicast_global | benchmarking + ); + check!( "102:304:506:708:90a:b0c:d0e:f10", &[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], @@ -874,6 +896,9 @@ fn ipv6_const() { const IS_DOCUMENTATION: bool = IP_ADDRESS.is_documentation(); assert!(!IS_DOCUMENTATION); + const IS_BENCHMARKING: bool = IP_ADDRESS.is_benchmarking(); + assert!(!IS_BENCHMARKING); + const IS_UNICAST_GLOBAL: bool = IP_ADDRESS.is_unicast_global(); assert!(!IS_UNICAST_GLOBAL); diff --git a/library/std/src/net/mod.rs b/library/std/src/net/mod.rs index d814e9b25b..a0c77b648f 100644 --- a/library/std/src/net/mod.rs +++ b/library/std/src/net/mod.rs @@ -44,16 +44,16 @@ mod udp; pub enum Shutdown { /// The reading portion of the [`TcpStream`] should be shut down. /// - /// All currently blocked and future [reads] will return [`Ok`]`(0)`. + /// All currently blocked and future [reads] will return [Ok]\(0). /// - /// [reads]: crate::io::Read + /// [reads]: crate::io::Read "io::Read" #[stable(feature = "rust1", since = "1.0.0")] Read, /// The writing portion of the [`TcpStream`] should be shut down. /// /// All currently blocked and future [writes] will return an error. /// - /// [writes]: crate::io::Write + /// [writes]: crate::io::Write "io::Write" #[stable(feature = "rust1", since = "1.0.0")] Write, /// Both the reading and the writing portions of the [`TcpStream`] should be shut down. diff --git a/library/std/src/net/tcp.rs b/library/std/src/net/tcp.rs index 5b4a9fa797..2c6e393005 100644 --- a/library/std/src/net/tcp.rs +++ b/library/std/src/net/tcp.rs @@ -96,6 +96,18 @@ pub struct Incoming<'a> { listener: &'a TcpListener, } +/// An iterator that infinitely [`accept`]s connections on a [`TcpListener`]. +/// +/// This `struct` is created by the [`TcpListener::into_incoming`] method. +/// See its documentation for more. +/// +/// [`accept`]: TcpListener::accept +#[derive(Debug)] +#[unstable(feature = "tcplistener_into_incoming", issue = "88339")] +pub struct IntoIncoming { + listener: TcpListener, +} + impl TcpStream { /// Opens a TCP connection to a remote host. /// @@ -845,6 +857,38 @@ impl TcpListener { Incoming { listener: self } } + /// Turn this into an iterator over the connections being received on this + /// listener. + /// + /// The returned iterator will never return [`None`] and will also not yield + /// the peer's [`SocketAddr`] structure. Iterating over it is equivalent to + /// calling [`TcpListener::accept`] in a loop. + /// + /// # Examples + /// + /// ```no_run + /// #![feature(tcplistener_into_incoming)] + /// use std::net::{TcpListener, TcpStream}; + /// + /// fn listen_on(port: u16) -> impl Iterator { + /// let listener = TcpListener::bind("127.0.0.1:80").unwrap(); + /// listener.into_incoming() + /// .filter_map(Result::ok) /* Ignore failed connections */ + /// } + /// + /// fn main() -> std::io::Result<()> { + /// for stream in listen_on(80) { + /// /* handle the connection here */ + /// } + /// Ok(()) + /// } + /// ``` + #[must_use = "`self` will be dropped if the result is not used"] + #[unstable(feature = "tcplistener_into_incoming", issue = "88339")] + pub fn into_incoming(self) -> IntoIncoming { + IntoIncoming { listener: self } + } + /// Sets the value for the `IP_TTL` option on this socket. /// /// This value sets the time-to-live field that is used in every packet sent @@ -982,6 +1026,14 @@ impl<'a> Iterator for Incoming<'a> { } } +#[unstable(feature = "tcplistener_into_incoming", issue = "88339")] +impl Iterator for IntoIncoming { + type Item = io::Result; + fn next(&mut self) -> Option> { + Some(self.listener.accept().map(|p| p.0)) + } +} + impl AsInner for TcpListener { fn as_inner(&self) -> &net_imp::TcpListener { &self.0 diff --git a/library/std/src/os/linux/fs.rs b/library/std/src/os/linux/fs.rs index 9b7af97616..9d18ccbeb2 100644 --- a/library/std/src/os/linux/fs.rs +++ b/library/std/src/os/linux/fs.rs @@ -1,4 +1,6 @@ -//! Linux-specific extensions to primitives in the `std::fs` module. +//! Linux-specific extensions to primitives in the [`std::fs`] module. +//! +//! [`std::fs`]: crate::fs #![stable(feature = "metadata_ext", since = "1.1.0")] diff --git a/library/std/src/os/linux/process.rs b/library/std/src/os/linux/process.rs index e3e7143c85..540363c034 100644 --- a/library/std/src/os/linux/process.rs +++ b/library/std/src/os/linux/process.rs @@ -1,4 +1,6 @@ -//! Linux-specific extensions to primitives in the `std::process` module. +//! Linux-specific extensions to primitives in the [`std::process`] module. +//! +//! [`std::process`]: crate::process #![unstable(feature = "linux_pidfd", issue = "82971")] diff --git a/library/std/src/os/linux/raw.rs b/library/std/src/os/linux/raw.rs index 5b68a7e126..cd92dcabdf 100644 --- a/library/std/src/os/linux/raw.rs +++ b/library/std/src/os/linux/raw.rs @@ -27,6 +27,7 @@ pub use self::arch::{blkcnt_t, blksize_t, ino_t, nlink_t, off_t, stat, time_t}; #[cfg(any( target_arch = "x86", target_arch = "le32", + target_arch = "m68k", target_arch = "powerpc", target_arch = "sparc", target_arch = "arm", diff --git a/library/std/src/os/mod.rs b/library/std/src/os/mod.rs index 79e6967300..90c30313db 100644 --- a/library/std/src/os/mod.rs +++ b/library/std/src/os/mod.rs @@ -10,29 +10,11 @@ pub mod raw; // of a macro that is not vendored by Rust and included in the toolchain. // See https://github.com/rust-analyzer/rust-analyzer/issues/6038. -#[cfg(all( - doc, - not(any( - all(target_arch = "wasm32", not(target_os = "wasi")), - all(target_vendor = "fortanix", target_env = "sgx") - )) -))] -#[path = "."] -mod doc { - // When documenting std we want to show the `unix`, `windows`, `linux` and `wasi` - // modules as these are the "main modules" that are used across platforms, - // so these modules are enabled when `cfg(doc)` is set. - // This should help show platform-specific functionality in a hopefully cross-platform - // way in the documentation. +// On certain platforms right now the "main modules" modules that are +// documented don't compile (missing things in `libc` which is empty), +// so just omit them with an empty module and add the "unstable" attribute. - pub mod unix; - - pub mod linux; - - pub mod wasi; - - pub mod windows; -} +// Unix, linux, wasi and windows are handled a bit differently. #[cfg(all( doc, any( @@ -40,87 +22,126 @@ mod doc { all(target_vendor = "fortanix", target_env = "sgx") ) ))] -mod doc { - // On certain platforms right now the "main modules" modules that are - // documented don't compile (missing things in `libc` which is empty), - // so just omit them with an empty module. +#[unstable(issue = "none", feature = "std_internals")] +pub mod unix {} +#[cfg(all( + doc, + any( + all(target_arch = "wasm32", not(target_os = "wasi")), + all(target_vendor = "fortanix", target_env = "sgx") + ) +))] +#[unstable(issue = "none", feature = "std_internals")] +pub mod linux {} +#[cfg(all( + doc, + any( + all(target_arch = "wasm32", not(target_os = "wasi")), + all(target_vendor = "fortanix", target_env = "sgx") + ) +))] +#[unstable(issue = "none", feature = "std_internals")] +pub mod wasi {} +#[cfg(all( + doc, + any( + all(target_arch = "wasm32", not(target_os = "wasi")), + all(target_vendor = "fortanix", target_env = "sgx") + ) +))] +#[unstable(issue = "none", feature = "std_internals")] +pub mod windows {} - #[unstable(issue = "none", feature = "std_internals")] - pub mod unix {} +// unix +#[cfg(not(all( + doc, + any( + all(target_arch = "wasm32", not(target_os = "wasi")), + all(target_vendor = "fortanix", target_env = "sgx") + ) +)))] +#[cfg(target_os = "hermit")] +#[path = "hermit/mod.rs"] +pub mod unix; +#[cfg(not(all( + doc, + any( + all(target_arch = "wasm32", not(target_os = "wasi")), + all(target_vendor = "fortanix", target_env = "sgx") + ) +)))] +#[cfg(all(not(target_os = "hermit"), any(unix, doc)))] +pub mod unix; - #[unstable(issue = "none", feature = "std_internals")] - pub mod linux {} +// linux +#[cfg(not(all( + doc, + any( + all(target_arch = "wasm32", not(target_os = "wasi")), + all(target_vendor = "fortanix", target_env = "sgx") + ) +)))] +#[cfg(any(target_os = "linux", target_os = "l4re", doc))] +pub mod linux; - #[unstable(issue = "none", feature = "std_internals")] - pub mod wasi {} +// wasi +#[cfg(not(all( + doc, + any( + all(target_arch = "wasm32", not(target_os = "wasi")), + all(target_vendor = "fortanix", target_env = "sgx") + ) +)))] +#[cfg(any(target_os = "wasi", doc))] +pub mod wasi; - #[unstable(issue = "none", feature = "std_internals")] - pub mod windows {} -} -#[cfg(doc)] -#[stable(feature = "os", since = "1.0.0")] -pub use doc::*; +// windows +#[cfg(not(all( + doc, + any( + all(target_arch = "wasm32", not(target_os = "wasi")), + all(target_vendor = "fortanix", target_env = "sgx") + ) +)))] +#[cfg(any(windows, doc))] +pub mod windows; -#[cfg(not(doc))] -#[path = "."] -mod imp { - // If we're not documenting std then we only expose modules appropriate for the - // current platform. +// Others. +#[cfg(target_os = "android")] +pub mod android; +#[cfg(target_os = "dragonfly")] +pub mod dragonfly; +#[cfg(target_os = "emscripten")] +pub mod emscripten; +#[cfg(target_os = "espidf")] +pub mod espidf; +#[cfg(all(target_vendor = "fortanix", target_env = "sgx"))] +pub mod fortanix_sgx; +#[cfg(target_os = "freebsd")] +pub mod freebsd; +#[cfg(target_os = "fuchsia")] +pub mod fuchsia; +#[cfg(target_os = "haiku")] +pub mod haiku; +#[cfg(target_os = "illumos")] +pub mod illumos; +#[cfg(target_os = "ios")] +pub mod ios; +#[cfg(target_os = "macos")] +pub mod macos; +#[cfg(target_os = "netbsd")] +pub mod netbsd; +#[cfg(target_os = "openbsd")] +pub mod openbsd; +#[cfg(target_os = "redox")] +pub mod redox; +#[cfg(target_os = "solaris")] +pub mod solaris; - #[cfg(all(target_vendor = "fortanix", target_env = "sgx"))] - pub mod fortanix_sgx; - - #[cfg(target_os = "hermit")] - #[path = "hermit/mod.rs"] - pub mod unix; - - #[cfg(target_os = "android")] - pub mod android; - #[cfg(target_os = "dragonfly")] - pub mod dragonfly; - #[cfg(target_os = "emscripten")] - pub mod emscripten; - #[cfg(target_os = "espidf")] - pub mod espidf; - #[cfg(target_os = "freebsd")] - pub mod freebsd; - #[cfg(target_os = "fuchsia")] - pub mod fuchsia; - #[cfg(target_os = "haiku")] - pub mod haiku; - #[cfg(target_os = "illumos")] - pub mod illumos; - #[cfg(target_os = "ios")] - pub mod ios; - #[cfg(target_os = "l4re")] - pub mod linux; - #[cfg(target_os = "linux")] - pub mod linux; - #[cfg(target_os = "macos")] - pub mod macos; - #[cfg(target_os = "netbsd")] - pub mod netbsd; - #[cfg(target_os = "openbsd")] - pub mod openbsd; - #[cfg(target_os = "redox")] - pub mod redox; - #[cfg(target_os = "solaris")] - pub mod solaris; - #[cfg(unix)] - pub mod unix; - - #[cfg(target_os = "vxworks")] - pub mod vxworks; - - #[cfg(target_os = "wasi")] - pub mod wasi; - - #[cfg(windows)] - pub mod windows; -} -#[cfg(not(doc))] -#[stable(feature = "os", since = "1.0.0")] -pub use imp::*; +#[cfg(target_os = "solid_asp3")] +pub mod solid; +#[cfg(target_os = "vxworks")] +pub mod vxworks; #[cfg(any(unix, target_os = "wasi", doc))] mod fd; diff --git a/library/std/src/os/raw/char.md b/library/std/src/os/raw/char.md index 8256b725ac..375d070516 100644 --- a/library/std/src/os/raw/char.md +++ b/library/std/src/os/raw/char.md @@ -1,6 +1,6 @@ Equivalent to C's `char` type. -[C's `char` type] is completely unlike [Rust's `char` type]; while Rust's type represents a unicode scalar value, C's `char` type is just an ordinary integer. This type will always be either [`i8`] or [`u8`], as the type is defined as being one byte long. +[C's `char` type] is completely unlike [Rust's `char` type]; while Rust's type represents a unicode scalar value, C's `char` type is just an ordinary integer. On modern architectures this type will always be either [`i8`] or [`u8`], as they use byte-addresses memory with 8-bit bytes. C chars are most commonly used to make C strings. Unlike Rust, where the length of a string is included alongside the string, C strings mark the end of a string with the character `'\0'`. See [`CStr`] for more information. diff --git a/library/std/src/os/raw/mod.rs b/library/std/src/os/raw/mod.rs index 1e220ea30a..30eeac14b4 100644 --- a/library/std/src/os/raw/mod.rs +++ b/library/std/src/os/raw/mod.rs @@ -46,6 +46,7 @@ macro_rules! type_alias { } type_alias! { "char.md", c_char = u8, NonZero_c_char = NonZeroU8; +#[doc(cfg(all()))] #[cfg(any( all( target_os = "linux", @@ -88,6 +89,7 @@ type_alias! { "char.md", c_char = u8, NonZero_c_char = NonZeroU8; all(target_os = "fuchsia", target_arch = "aarch64") ))]} type_alias! { "char.md", c_char = i8, NonZero_c_char = NonZeroI8; +#[doc(cfg(all()))] #[cfg(not(any( all( target_os = "linux", @@ -136,12 +138,16 @@ type_alias! { "ushort.md", c_ushort = u16, NonZero_c_ushort = NonZeroU16; } type_alias! { "int.md", c_int = i32, NonZero_c_int = NonZeroI32; } type_alias! { "uint.md", c_uint = u32, NonZero_c_uint = NonZeroU32; } type_alias! { "long.md", c_long = i32, NonZero_c_long = NonZeroI32; +#[doc(cfg(all()))] #[cfg(any(target_pointer_width = "32", windows))] } type_alias! { "ulong.md", c_ulong = u32, NonZero_c_ulong = NonZeroU32; +#[doc(cfg(all()))] #[cfg(any(target_pointer_width = "32", windows))] } type_alias! { "long.md", c_long = i64, NonZero_c_long = NonZeroI64; +#[doc(cfg(all()))] #[cfg(all(target_pointer_width = "64", not(windows)))] } type_alias! { "ulong.md", c_ulong = u64, NonZero_c_ulong = NonZeroU64; +#[doc(cfg(all()))] #[cfg(all(target_pointer_width = "64", not(windows)))] } type_alias! { "longlong.md", c_longlong = i64, NonZero_c_longlong = NonZeroI64; } type_alias! { "ulonglong.md", c_ulonglong = u64, NonZero_c_ulonglong = NonZeroU64; } diff --git a/library/std/src/os/solid/ffi.rs b/library/std/src/os/solid/ffi.rs new file mode 100644 index 0000000000..aaa2070a6a --- /dev/null +++ b/library/std/src/os/solid/ffi.rs @@ -0,0 +1,41 @@ +//! SOLID-specific extension to the primitives in the `std::ffi` module +//! +//! # Examples +//! +//! ``` +//! use std::ffi::OsString; +//! use std::os::solid::ffi::OsStringExt; +//! +//! let bytes = b"foo".to_vec(); +//! +//! // OsStringExt::from_vec +//! let os_string = OsString::from_vec(bytes); +//! assert_eq!(os_string.to_str(), Some("foo")); +//! +//! // OsStringExt::into_vec +//! let bytes = os_string.into_vec(); +//! assert_eq!(bytes, b"foo"); +//! ``` +//! +//! ``` +//! use std::ffi::OsStr; +//! use std::os::solid::ffi::OsStrExt; +//! +//! let bytes = b"foo"; +//! +//! // OsStrExt::from_bytes +//! let os_str = OsStr::from_bytes(bytes); +//! assert_eq!(os_str.to_str(), Some("foo")); +//! +//! // OsStrExt::as_bytes +//! let bytes = os_str.as_bytes(); +//! assert_eq!(bytes, b"foo"); +//! ``` + +#![stable(feature = "rust1", since = "1.0.0")] + +#[path = "../unix/ffi/os_str.rs"] +mod os_str; + +#[stable(feature = "rust1", since = "1.0.0")] +pub use self::os_str::{OsStrExt, OsStringExt}; diff --git a/library/std/src/os/solid/io.rs b/library/std/src/os/solid/io.rs new file mode 100644 index 0000000000..33cc5a015b --- /dev/null +++ b/library/std/src/os/solid/io.rs @@ -0,0 +1,113 @@ +//! SOLID-specific extensions to general I/O primitives + +#![deny(unsafe_op_in_unsafe_fn)] +#![unstable(feature = "solid_ext", issue = "none")] + +use crate::net; +use crate::sys; +use crate::sys_common::{self, AsInner, FromInner, IntoInner}; + +/// Raw file descriptors. +pub type RawFd = i32; + +/// A trait to extract the raw SOLID Sockets file descriptor from an underlying +/// object. +pub trait AsRawFd { + /// Extracts the raw file descriptor. + /// + /// This method does **not** pass ownership of the raw file descriptor + /// to the caller. The descriptor is only guaranteed to be valid while + /// the original object has not yet been destroyed. + fn as_raw_fd(&self) -> RawFd; +} + +/// A trait to express the ability to construct an object from a raw file +/// descriptor. +pub trait FromRawFd { + /// Constructs a new instance of `Self` from the given raw file + /// descriptor. + /// + /// This function **consumes ownership** of the specified file + /// descriptor. The returned object will take responsibility for closing + /// it when the object goes out of scope. + /// + /// This function is also unsafe as the primitives currently returned + /// have the contract that they are the sole owner of the file + /// descriptor they are wrapping. Usage of this function could + /// accidentally allow violating this contract which can cause memory + /// unsafety in code that relies on it being true. + unsafe fn from_raw_fd(fd: RawFd) -> Self; +} + +/// A trait to express the ability to consume an object and acquire ownership of +/// its raw file descriptor. +pub trait IntoRawFd { + /// Consumes this object, returning the raw underlying file descriptor. + /// + /// This function **transfers ownership** of the underlying file descriptor + /// to the caller. Callers are then the unique owners of the file descriptor + /// and must close the descriptor once it's no longer needed. + fn into_raw_fd(self) -> RawFd; +} + +#[stable(feature = "raw_fd_reflexive_traits", since = "1.48.0")] +impl AsRawFd for RawFd { + #[inline] + fn as_raw_fd(&self) -> RawFd { + *self + } +} +#[stable(feature = "raw_fd_reflexive_traits", since = "1.48.0")] +impl IntoRawFd for RawFd { + #[inline] + fn into_raw_fd(self) -> RawFd { + self + } +} +#[stable(feature = "raw_fd_reflexive_traits", since = "1.48.0")] +impl FromRawFd for RawFd { + #[inline] + unsafe fn from_raw_fd(fd: RawFd) -> RawFd { + fd + } +} + +macro_rules! impl_as_raw_fd { + ($($t:ident)*) => {$( + #[stable(feature = "rust1", since = "1.0.0")] + impl AsRawFd for net::$t { + #[inline] + fn as_raw_fd(&self) -> RawFd { + *self.as_inner().socket().as_inner() + } + } + )*}; +} +impl_as_raw_fd! { TcpStream TcpListener UdpSocket } + +macro_rules! impl_from_raw_fd { + ($($t:ident)*) => {$( + #[stable(feature = "from_raw_os", since = "1.1.0")] + impl FromRawFd for net::$t { + #[inline] + unsafe fn from_raw_fd(fd: RawFd) -> net::$t { + let socket = sys::net::Socket::from_inner(fd); + net::$t::from_inner(sys_common::net::$t::from_inner(socket)) + } + } + )*}; +} +impl_from_raw_fd! { TcpStream TcpListener UdpSocket } + +macro_rules! impl_into_raw_fd { + ($($t:ident)*) => {$( + #[stable(feature = "into_raw_os", since = "1.4.0")] + impl IntoRawFd for net::$t { + #[inline] + fn into_raw_fd(self) -> RawFd { + self.into_inner().into_socket().into_inner() + } + } + )*}; +} +impl_into_raw_fd! { TcpStream TcpListener UdpSocket } diff --git a/library/std/src/os/solid/mod.rs b/library/std/src/os/solid/mod.rs new file mode 100644 index 0000000000..4328ba7c34 --- /dev/null +++ b/library/std/src/os/solid/mod.rs @@ -0,0 +1,17 @@ +#![stable(feature = "rust1", since = "1.0.0")] + +pub mod ffi; +pub mod io; + +/// A prelude for conveniently writing platform-specific code. +/// +/// Includes all extension traits, and some important type definitions. +#[stable(feature = "rust1", since = "1.0.0")] +pub mod prelude { + #[doc(no_inline)] + #[stable(feature = "rust1", since = "1.0.0")] + pub use super::ffi::{OsStrExt, OsStringExt}; + #[doc(no_inline)] + #[stable(feature = "rust1", since = "1.0.0")] + pub use super::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; +} diff --git a/library/std/src/os/unix/ffi/mod.rs b/library/std/src/os/unix/ffi/mod.rs index c29df6596f..5b49f50763 100644 --- a/library/std/src/os/unix/ffi/mod.rs +++ b/library/std/src/os/unix/ffi/mod.rs @@ -1,4 +1,4 @@ -//! Unix-specific extension to the primitives in the `std::ffi` module. +//! Unix-specific extensions to primitives in the [`std::ffi`] module. //! //! # Examples //! @@ -31,6 +31,8 @@ //! let bytes = os_str.as_bytes(); //! assert_eq!(bytes, b"foo"); //! ``` +//! +//! [`std::ffi`]: crate::ffi #![stable(feature = "rust1", since = "1.0.0")] diff --git a/library/std/src/os/unix/fs.rs b/library/std/src/os/unix/fs.rs index 6cf37f23c5..0284a428b5 100644 --- a/library/std/src/os/unix/fs.rs +++ b/library/std/src/os/unix/fs.rs @@ -1,10 +1,13 @@ -//! Unix-specific extensions to primitives in the `std::fs` module. +//! Unix-specific extensions to primitives in the [`std::fs`] module. +//! +//! [`std::fs`]: crate::fs #![stable(feature = "rust1", since = "1.0.0")] use super::platform::fs::MetadataExt as _; use crate::fs::{self, OpenOptions, Permissions}; use crate::io; +use crate::os::unix::io::{AsFd, AsRawFd}; use crate::path::Path; use crate::sys; use crate::sys_common::{AsInner, AsInnerMut, FromInner}; @@ -924,6 +927,75 @@ impl DirBuilderExt for fs::DirBuilder { } } +/// Change the owner and group of the specified path. +/// +/// Specifying either the uid or gid as `None` will leave it unchanged. +/// +/// Changing the owner typically requires privileges, such as root or a specific capability. +/// Changing the group typically requires either being the owner and a member of the group, or +/// having privileges. +/// +/// If called on a symbolic link, this will change the owner and group of the link target. To +/// change the owner and group of the link itself, see [`lchown`]. +/// +/// # Examples +/// +/// ```no_run +/// #![feature(unix_chown)] +/// use std::os::unix::fs; +/// +/// fn main() -> std::io::Result<()> { +/// fs::chown("/sandbox", Some(0), Some(0))?; +/// Ok(()) +/// } +/// ``` +#[unstable(feature = "unix_chown", issue = "88989")] +pub fn chown>(dir: P, uid: Option, gid: Option) -> io::Result<()> { + sys::fs::chown(dir.as_ref(), uid.unwrap_or(u32::MAX), gid.unwrap_or(u32::MAX)) +} + +/// Change the owner and group of the file referenced by the specified open file descriptor. +/// +/// For semantics and required privileges, see [`chown`]. +/// +/// # Examples +/// +/// ```no_run +/// #![feature(unix_chown)] +/// use std::os::unix::fs; +/// +/// fn main() -> std::io::Result<()> { +/// let f = std::fs::File::open("/file")?; +/// fs::fchown(f, Some(0), Some(0))?; +/// Ok(()) +/// } +/// ``` +#[unstable(feature = "unix_chown", issue = "88989")] +pub fn fchown(fd: F, uid: Option, gid: Option) -> io::Result<()> { + sys::fs::fchown(fd.as_fd().as_raw_fd(), uid.unwrap_or(u32::MAX), gid.unwrap_or(u32::MAX)) +} + +/// Change the owner and group of the specified path, without dereferencing symbolic links. +/// +/// Identical to [`chown`], except that if called on a symbolic link, this will change the owner +/// and group of the link itself rather than the owner and group of the link target. +/// +/// # Examples +/// +/// ```no_run +/// #![feature(unix_chown)] +/// use std::os::unix::fs; +/// +/// fn main() -> std::io::Result<()> { +/// fs::lchown("/symlink", Some(0), Some(0))?; +/// Ok(()) +/// } +/// ``` +#[unstable(feature = "unix_chown", issue = "88989")] +pub fn lchown>(dir: P, uid: Option, gid: Option) -> io::Result<()> { + sys::fs::lchown(dir.as_ref(), uid.unwrap_or(u32::MAX), gid.unwrap_or(u32::MAX)) +} + /// Change the root directory of the current process to the specified path. /// /// This typically requires privileges, such as root or a specific capability. diff --git a/library/std/src/os/unix/mod.rs b/library/std/src/os/unix/mod.rs index 17a0259572..62f750fa60 100644 --- a/library/std/src/os/unix/mod.rs +++ b/library/std/src/os/unix/mod.rs @@ -4,8 +4,8 @@ //! exposes Unix-specific functions that would otherwise be inappropriate as //! part of the core `std` library. //! -//! It exposes more ways to deal with platform-specific strings (`OsStr`, -//! `OsString`), allows to set permissions more granularly, extract low-level +//! It exposes more ways to deal with platform-specific strings ([`OsStr`], +//! [`OsString`]), allows to set permissions more granularly, extract low-level //! file descriptors from files and sockets, and has platform-specific helpers //! for spawning processes. //! @@ -24,6 +24,9 @@ //! Ok(()) //! } //! ``` +//! +//! [`OsStr`]: crate::ffi::OsStr +//! [`OsString`]: crate::ffi::OsString #![stable(feature = "rust1", since = "1.0.0")] #![doc(cfg(unix))] diff --git a/library/std/src/os/unix/net/addr.rs b/library/std/src/os/unix/net/addr.rs index 62bfde8bfd..887f605993 100644 --- a/library/std/src/os/unix/net/addr.rs +++ b/library/std/src/os/unix/net/addr.rs @@ -92,8 +92,8 @@ impl<'a> fmt::Display for AsciiEscaped<'a> { #[derive(Clone)] #[stable(feature = "unix_socket", since = "1.10.0")] pub struct SocketAddr { - addr: libc::sockaddr_un, - len: libc::socklen_t, + pub(super) addr: libc::sockaddr_un, + pub(super) len: libc::socklen_t, } impl SocketAddr { @@ -156,6 +156,7 @@ impl SocketAddr { /// Ok(()) /// } /// ``` + #[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 } @@ -192,10 +193,36 @@ impl SocketAddr { /// } /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] + #[must_use] pub fn as_pathname(&self) -> Option<&Path> { if let AddressKind::Pathname(path) = self.address() { Some(path) } else { None } } + /// Returns the contents of this address if it is an abstract namespace + /// without the leading null byte. + /// + /// # Examples + /// + /// ```no_run + /// #![feature(unix_socket_abstract)] + /// use std::os::unix::net::{UnixListener, SocketAddr}; + /// + /// fn main() -> std::io::Result<()> { + /// let namespace = b"hidden"; + /// let namespace_addr = SocketAddr::from_abstract_namespace(&namespace[..])?; + /// let socket = UnixListener::bind_addr(&namespace_addr)?; + /// let local_addr = socket.local_addr().expect("Couldn't get local address"); + /// assert_eq!(local_addr.as_abstract_namespace(), Some(&namespace[..])); + /// Ok(()) + /// } + /// ``` + #[doc(cfg(any(target_os = "android", target_os = "linux")))] + #[cfg(any(doc, target_os = "android", target_os = "linux",))] + #[unstable(feature = "unix_socket_abstract", issue = "85410")] + pub fn as_abstract_namespace(&self) -> Option<&[u8]> { + if let AddressKind::Abstract(name) = self.address() { Some(name) } else { None } + } + fn address(&self) -> AddressKind<'_> { let len = self.len as usize - sun_path_offset(&self.addr); let path = unsafe { mem::transmute::<&[libc::c_char], &[u8]>(&self.addr.sun_path) }; @@ -212,6 +239,65 @@ impl SocketAddr { AddressKind::Pathname(OsStr::from_bytes(&path[..len - 1]).as_ref()) } } + + /// Creates an abstract domain socket address from a namespace + /// + /// An abstract address does not create a file unlike traditional path-based + /// Unix sockets. The advantage of this is that the address will disappear when + /// the socket bound to it is closed, so no filesystem clean up is required. + /// + /// The leading null byte for the abstract namespace is automatically added. + /// + /// This is a Linux-specific extension. See more at [`unix(7)`]. + /// + /// [`unix(7)`]: https://man7.org/linux/man-pages/man7/unix.7.html + /// + /// # Errors + /// + /// This will return an error if the given namespace is too long + /// + /// # Examples + /// + /// ```no_run + /// #![feature(unix_socket_abstract)] + /// use std::os::unix::net::{UnixListener, SocketAddr}; + /// + /// fn main() -> std::io::Result<()> { + /// let addr = SocketAddr::from_abstract_namespace(b"hidden")?; + /// let listener = match UnixListener::bind_addr(&addr) { + /// Ok(sock) => sock, + /// Err(err) => { + /// println!("Couldn't bind: {:?}", err); + /// return Err(err); + /// } + /// }; + /// Ok(()) + /// } + /// ``` + #[doc(cfg(any(target_os = "android", target_os = "linux")))] + #[cfg(any(doc, target_os = "android", target_os = "linux",))] + #[unstable(feature = "unix_socket_abstract", issue = "85410")] + pub fn from_abstract_namespace(namespace: &[u8]) -> io::Result { + unsafe { + let mut addr: libc::sockaddr_un = mem::zeroed(); + addr.sun_family = libc::AF_UNIX as libc::sa_family_t; + + if namespace.len() + 1 > addr.sun_path.len() { + return Err(io::Error::new_const( + io::ErrorKind::InvalidInput, + &"namespace must be shorter than SUN_LEN", + )); + } + + crate::ptr::copy_nonoverlapping( + namespace.as_ptr(), + addr.sun_path.as_mut_ptr().offset(1) as *mut u8, + namespace.len(), + ); + let len = (sun_path_offset(&addr) + 1 + namespace.len()) as libc::socklen_t; + SocketAddr::from_parts(addr, len) + } + } } #[stable(feature = "unix_socket", since = "1.10.0")] diff --git a/library/std/src/os/unix/net/ancillary.rs b/library/std/src/os/unix/net/ancillary.rs index 1f9d42812e..57bb61903c 100644 --- a/library/std/src/os/unix/net/ancillary.rs +++ b/library/std/src/os/unix/net/ancillary.rs @@ -189,6 +189,7 @@ impl SocketCred { /// /// PID, UID and GID is set to 0. #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] + #[must_use] pub fn new() -> SocketCred { SocketCred(libc::ucred { pid: 0, uid: 0, gid: 0 }) } diff --git a/library/std/src/os/unix/net/datagram.rs b/library/std/src/os/unix/net/datagram.rs index f11eec18cc..a2caccc784 100644 --- a/library/std/src/os/unix/net/datagram.rs +++ b/library/std/src/os/unix/net/datagram.rs @@ -112,6 +112,41 @@ impl UnixDatagram { } } + /// Creates a Unix datagram socket bound to an address. + /// + /// # Examples + /// + /// ```no_run + /// #![feature(unix_socket_abstract)] + /// use std::os::unix::net::{UnixDatagram}; + /// + /// fn main() -> std::io::Result<()> { + /// let sock1 = UnixDatagram::bind("path/to/socket")?; + /// let addr = sock1.local_addr()?; + /// + /// let sock2 = match UnixDatagram::bind_addr(&addr) { + /// Ok(sock) => sock, + /// Err(err) => { + /// println!("Couldn't bind: {:?}", err); + /// return Err(err); + /// } + /// }; + /// Ok(()) + /// } + /// ``` + #[unstable(feature = "unix_socket_abstract", issue = "85410")] + pub fn bind_addr(socket_addr: &SocketAddr) -> io::Result { + unsafe { + let socket = UnixDatagram::unbound()?; + cvt(libc::bind( + socket.as_raw_fd(), + &socket_addr.addr as *const _ as *const _, + socket_addr.len as _, + ))?; + Ok(socket) + } + } + /// Creates a Unix Datagram socket which is not bound to any address. /// /// # Examples @@ -156,7 +191,7 @@ impl UnixDatagram { Ok((UnixDatagram(i1), UnixDatagram(i2))) } - /// Connects the socket to the specified address. + /// Connects the socket to the specified path address. /// /// The [`send`] method may be used to send data to the specified address. /// [`recv`] and [`recv_from`] will only receive data from that address. @@ -192,6 +227,41 @@ impl UnixDatagram { Ok(()) } + /// Connects the socket to an address. + /// + /// # Examples + /// + /// ```no_run + /// #![feature(unix_socket_abstract)] + /// use std::os::unix::net::{UnixDatagram}; + /// + /// fn main() -> std::io::Result<()> { + /// let bound = UnixDatagram::bind("/path/to/socket")?; + /// let addr = bound.local_addr()?; + /// + /// let sock = UnixDatagram::unbound()?; + /// match sock.connect_addr(&addr) { + /// Ok(sock) => sock, + /// Err(e) => { + /// println!("Couldn't connect: {:?}", e); + /// return Err(e) + /// } + /// }; + /// Ok(()) + /// } + /// ``` + #[unstable(feature = "unix_socket_abstract", issue = "85410")] + pub fn connect_addr(&self, socket_addr: &SocketAddr) -> io::Result<()> { + unsafe { + cvt(libc::connect( + self.as_raw_fd(), + &socket_addr.addr as *const _ as *const _, + socket_addr.len, + ))?; + } + Ok(()) + } + /// Creates a new independently owned handle to the underlying socket. /// /// The returned `UnixDatagram` is a reference to the same socket that this @@ -473,6 +543,42 @@ impl UnixDatagram { } } + /// Sends data on the socket to the specified [SocketAddr]. + /// + /// On success, returns the number of bytes written. + /// + /// [SocketAddr]: crate::os::unix::net::SocketAddr + /// + /// # Examples + /// + /// ```no_run + /// #![feature(unix_socket_abstract)] + /// use std::os::unix::net::{UnixDatagram}; + /// + /// fn main() -> std::io::Result<()> { + /// let bound = UnixDatagram::bind("/path/to/socket")?; + /// let addr = bound.local_addr()?; + /// + /// let sock = UnixDatagram::unbound()?; + /// sock.send_to_addr(b"bacon egg and cheese", &addr).expect("send_to_addr function failed"); + /// Ok(()) + /// } + /// ``` + #[unstable(feature = "unix_socket_abstract", issue = "85410")] + pub fn send_to_addr(&self, buf: &[u8], socket_addr: &SocketAddr) -> io::Result { + unsafe { + let count = cvt(libc::sendto( + self.as_raw_fd(), + buf.as_ptr() as *const _, + buf.len(), + MSG_NOSIGNAL, + &socket_addr.addr as *const _ as *const _, + socket_addr.len, + ))?; + Ok(count as usize) + } + } + /// Sends data on the socket to the socket's peer. /// /// The peer address may be set by the `connect` method, and this method diff --git a/library/std/src/os/unix/net/listener.rs b/library/std/src/os/unix/net/listener.rs index f08bd252e4..97348afe7d 100644 --- a/library/std/src/os/unix/net/listener.rs +++ b/library/std/src/os/unix/net/listener.rs @@ -81,6 +81,44 @@ impl UnixListener { } } + /// Creates a new `UnixListener` bound to the specified [`socket address`]. + /// + /// [`socket address`]: crate::os::unix::net::SocketAddr + /// + /// # Examples + /// + /// ```no_run + /// #![feature(unix_socket_abstract)] + /// use std::os::unix::net::{UnixListener}; + /// + /// fn main() -> std::io::Result<()> { + /// let listener1 = UnixListener::bind("path/to/socket")?; + /// let addr = listener1.local_addr()?; + /// + /// let listener2 = match UnixListener::bind_addr(&addr) { + /// Ok(sock) => sock, + /// Err(err) => { + /// println!("Couldn't bind: {:?}", err); + /// return Err(err); + /// } + /// }; + /// Ok(()) + /// } + /// ``` + #[unstable(feature = "unix_socket_abstract", issue = "85410")] + pub fn bind_addr(socket_addr: &SocketAddr) -> io::Result { + unsafe { + let inner = Socket::new_raw(libc::AF_UNIX, libc::SOCK_STREAM)?; + cvt(libc::bind( + inner.as_raw_fd(), + &socket_addr.addr as *const _ as *const _, + socket_addr.len as _, + ))?; + cvt(libc::listen(inner.as_raw_fd(), 128))?; + Ok(UnixListener(inner)) + } + } + /// Accepts a new incoming connection to this listener. /// /// This function will block the calling thread until a new Unix connection diff --git a/library/std/src/os/unix/net/mod.rs b/library/std/src/os/unix/net/mod.rs index d462bd4b5f..8ce8220885 100644 --- a/library/std/src/os/unix/net/mod.rs +++ b/library/std/src/os/unix/net/mod.rs @@ -1,4 +1,4 @@ -//! Unix-specific networking functionality +//! Unix-specific networking functionality. #![stable(feature = "unix_socket", since = "1.10.0")] diff --git a/library/std/src/os/unix/net/stream.rs b/library/std/src/os/unix/net/stream.rs index 4119de3c03..6120d55722 100644 --- a/library/std/src/os/unix/net/stream.rs +++ b/library/std/src/os/unix/net/stream.rs @@ -106,6 +106,43 @@ impl UnixStream { } } + /// Connects to the socket specified by [`address`]. + /// + /// [`address`]: crate::os::unix::net::SocketAddr + /// + /// # Examples + /// + /// ```no_run + /// #![feature(unix_socket_abstract)] + /// use std::os::unix::net::{UnixListener, UnixStream}; + /// + /// fn main() -> std::io::Result<()> { + /// let listener = UnixListener::bind("/path/to/the/socket")?; + /// let addr = listener.local_addr()?; + /// + /// let sock = match UnixStream::connect_addr(&addr) { + /// Ok(sock) => sock, + /// Err(e) => { + /// println!("Couldn't connect: {:?}", e); + /// return Err(e) + /// } + /// }; + /// Ok(()) + /// } + /// ```` + #[unstable(feature = "unix_socket_abstract", issue = "85410")] + pub fn connect_addr(socket_addr: &SocketAddr) -> io::Result { + unsafe { + let inner = Socket::new_raw(libc::AF_UNIX, libc::SOCK_STREAM)?; + cvt(libc::connect( + inner.as_raw_fd(), + &socket_addr.addr as *const _ as *const _, + socket_addr.len, + ))?; + Ok(UnixStream(inner)) + } + } + /// Creates an unnamed pair of connected sockets. /// /// Returns two `UnixStream`s which are connected to each other. diff --git a/library/std/src/os/unix/net/tests.rs b/library/std/src/os/unix/net/tests.rs index bd9b6dd727..7ad4a02611 100644 --- a/library/std/src/os/unix/net/tests.rs +++ b/library/std/src/os/unix/net/tests.rs @@ -303,6 +303,30 @@ fn test_unnamed_unix_datagram() { assert_eq!(msg, &buf[..]); } +#[test] +fn test_unix_datagram_connect_to_recv_addr() { + let dir = tmpdir(); + let path1 = dir.path().join("sock1"); + let path2 = dir.path().join("sock2"); + + let sock1 = or_panic!(UnixDatagram::bind(&path1)); + let sock2 = or_panic!(UnixDatagram::bind(&path2)); + + let msg = b"hello world"; + let sock1_addr = or_panic!(sock1.local_addr()); + or_panic!(sock2.send_to_addr(msg, &sock1_addr)); + let mut buf = [0; 11]; + let (_, addr) = or_panic!(sock1.recv_from(&mut buf)); + + let new_msg = b"hello back"; + let mut new_buf = [0; 10]; + or_panic!(sock2.connect_addr(&addr)); + or_panic!(sock2.send(new_msg)); // set by connect_addr + let usize = or_panic!(sock2.recv(&mut new_buf)); + assert_eq!(usize, 10); + assert_eq!(new_msg, &new_buf[..]); +} + #[test] fn test_connect_unix_datagram() { let dir = tmpdir(); @@ -388,10 +412,133 @@ fn test_unix_datagram_timeout_zero_duration() { } #[test] -fn abstract_namespace_not_allowed() { +fn abstract_namespace_not_allowed_connect() { assert!(UnixStream::connect("\0asdf").is_err()); } +#[cfg(any(target_os = "android", target_os = "linux"))] +#[test] +fn test_abstract_stream_connect() { + let msg1 = b"hello"; + let msg2 = b"world"; + + let socket_addr = or_panic!(SocketAddr::from_abstract_namespace(b"namespace")); + let listener = or_panic!(UnixListener::bind_addr(&socket_addr)); + + let thread = thread::spawn(move || { + let mut stream = or_panic!(listener.accept()).0; + let mut buf = [0; 5]; + or_panic!(stream.read(&mut buf)); + assert_eq!(&msg1[..], &buf[..]); + or_panic!(stream.write_all(msg2)); + }); + + let mut stream = or_panic!(UnixStream::connect_addr(&socket_addr)); + + let peer = or_panic!(stream.peer_addr()); + assert_eq!(peer.as_abstract_namespace().unwrap(), b"namespace"); + + or_panic!(stream.write_all(msg1)); + let mut buf = vec![]; + or_panic!(stream.read_to_end(&mut buf)); + assert_eq!(&msg2[..], &buf[..]); + drop(stream); + + thread.join().unwrap(); +} + +#[cfg(any(target_os = "android", target_os = "linux"))] +#[test] +fn test_abstract_stream_iter() { + let addr = or_panic!(SocketAddr::from_abstract_namespace(b"hidden")); + let listener = or_panic!(UnixListener::bind_addr(&addr)); + + let thread = thread::spawn(move || { + for stream in listener.incoming().take(2) { + let mut stream = or_panic!(stream); + let mut buf = [0]; + or_panic!(stream.read(&mut buf)); + } + }); + + for _ in 0..2 { + let mut stream = or_panic!(UnixStream::connect_addr(&addr)); + or_panic!(stream.write_all(&[0])); + } + + thread.join().unwrap(); +} + +#[cfg(any(target_os = "android", target_os = "linux"))] +#[test] +fn test_abstract_datagram_bind_send_to_addr() { + let addr1 = or_panic!(SocketAddr::from_abstract_namespace(b"ns1")); + let sock1 = or_panic!(UnixDatagram::bind_addr(&addr1)); + + let local = or_panic!(sock1.local_addr()); + assert_eq!(local.as_abstract_namespace().unwrap(), b"ns1"); + + let addr2 = or_panic!(SocketAddr::from_abstract_namespace(b"ns2")); + let sock2 = or_panic!(UnixDatagram::bind_addr(&addr2)); + + let msg = b"hello world"; + or_panic!(sock1.send_to_addr(msg, &addr2)); + let mut buf = [0; 11]; + let (len, addr) = or_panic!(sock2.recv_from(&mut buf)); + assert_eq!(msg, &buf[..]); + assert_eq!(len, 11); + assert_eq!(addr.as_abstract_namespace().unwrap(), b"ns1"); +} + +#[cfg(any(target_os = "android", target_os = "linux"))] +#[test] +fn test_abstract_datagram_connect_addr() { + let addr1 = or_panic!(SocketAddr::from_abstract_namespace(b"ns3")); + let bsock1 = or_panic!(UnixDatagram::bind_addr(&addr1)); + + let sock = or_panic!(UnixDatagram::unbound()); + or_panic!(sock.connect_addr(&addr1)); + + let msg = b"hello world"; + or_panic!(sock.send(msg)); + let mut buf = [0; 11]; + let (len, addr) = or_panic!(bsock1.recv_from(&mut buf)); + assert_eq!(len, 11); + assert_eq!(addr.is_unnamed(), true); + assert_eq!(msg, &buf[..]); + + let addr2 = or_panic!(SocketAddr::from_abstract_namespace(b"ns4")); + let bsock2 = or_panic!(UnixDatagram::bind_addr(&addr2)); + + or_panic!(sock.connect_addr(&addr2)); + or_panic!(sock.send(msg)); + or_panic!(bsock2.recv_from(&mut buf)); +} + +#[cfg(any(target_os = "android", target_os = "linux"))] +#[test] +fn test_abstract_namespace_too_long() { + match SocketAddr::from_abstract_namespace( + b"abcdefghijklmnopqrstuvwxyzabcdefghijklmn\ + opqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghi\ + jklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz", + ) { + Err(ref e) if e.kind() == io::ErrorKind::InvalidInput => {} + Err(e) => panic!("unexpected error {}", e), + Ok(_) => panic!("unexpected success"), + } +} + +#[cfg(any(target_os = "android", target_os = "linux"))] +#[test] +fn test_abstract_namespace_no_pathname_and_not_unnamed() { + let namespace = b"local"; + let addr = or_panic!(SocketAddr::from_abstract_namespace(&namespace[..])); + assert_eq!(addr.as_pathname(), None); + assert_eq!(addr.as_abstract_namespace(), Some(&namespace[..])); + assert_eq!(addr.is_unnamed(), false); +} + #[test] fn test_unix_stream_peek() { let (txdone, rxdone) = crate::sync::mpsc::channel(); diff --git a/library/std/src/os/unix/process.rs b/library/std/src/os/unix/process.rs index 650dcbabba..4d23805e47 100644 --- a/library/std/src/os/unix/process.rs +++ b/library/std/src/os/unix/process.rs @@ -1,4 +1,6 @@ -//! Unix-specific extensions to primitives in the `std::process` module. +//! Unix-specific extensions to primitives in the [`std::process`] module. +//! +//! [`std::process`]: crate::process #![stable(feature = "rust1", since = "1.0.0")] diff --git a/library/std/src/os/unix/thread.rs b/library/std/src/os/unix/thread.rs index 7221da1a9a..03dcc3a4f9 100644 --- a/library/std/src/os/unix/thread.rs +++ b/library/std/src/os/unix/thread.rs @@ -1,4 +1,6 @@ -//! Unix-specific extensions to primitives in the `std::thread` module. +//! Unix-specific extensions to primitives in the [`std::thread`] module. +//! +//! [`std::thread`]: crate::thread #![stable(feature = "thread_extensions", since = "1.9.0")] diff --git a/library/std/src/os/wasi/ffi.rs b/library/std/src/os/wasi/ffi.rs index 17e12a395a..41dd8702e9 100644 --- a/library/std/src/os/wasi/ffi.rs +++ b/library/std/src/os/wasi/ffi.rs @@ -1,4 +1,6 @@ -//! WASI-specific extension to the primitives in the `std::ffi` module +//! WASI-specific extensions to primitives in the [`std::ffi`] module +//! +//! [`std::ffi`]: crate::ffi #![stable(feature = "rust1", since = "1.0.0")] diff --git a/library/std/src/os/wasi/fs.rs b/library/std/src/os/wasi/fs.rs index 3df27563e2..907368061d 100644 --- a/library/std/src/os/wasi/fs.rs +++ b/library/std/src/os/wasi/fs.rs @@ -1,4 +1,6 @@ -//! WASI-specific extensions to primitives in the `std::fs` module. +//! WASI-specific extensions to primitives in the [`std::fs`] module. +//! +//! [`std::fs`]: crate::fs #![deny(unsafe_op_in_unsafe_fn)] #![unstable(feature = "wasi_ext", issue = "71213")] diff --git a/library/std/src/os/wasi/mod.rs b/library/std/src/os/wasi/mod.rs index d767c149dc..bbaf328f45 100644 --- a/library/std/src/os/wasi/mod.rs +++ b/library/std/src/os/wasi/mod.rs @@ -24,6 +24,9 @@ //! Ok(()) //! } //! ``` +//! +//! [`OsStr`]: crate::ffi::OsStr +//! [`OsString`]: crate::ffi::OsString #![stable(feature = "rust1", since = "1.0.0")] #![deny(unsafe_op_in_unsafe_fn)] diff --git a/library/std/src/os/windows/ffi.rs b/library/std/src/os/windows/ffi.rs index 8d29fa7d66..a9493a94ca 100644 --- a/library/std/src/os/windows/ffi.rs +++ b/library/std/src/os/windows/ffi.rs @@ -1,4 +1,4 @@ -//! Windows-specific extensions to the primitives in the `std::ffi` module. +//! Windows-specific extensions to primitives in the [`std::ffi`] module. //! //! # Overview //! @@ -49,6 +49,7 @@ //! [ill-formed-utf-16]: https://simonsapin.github.io/wtf-8/#ill-formed-utf-16 //! [`collect`]: crate::iter::Iterator::collect //! [U+FFFD]: crate::char::REPLACEMENT_CHARACTER +//! [`std::ffi`]: crate::ffi #![stable(feature = "rust1", since = "1.0.0")] diff --git a/library/std/src/os/windows/fs.rs b/library/std/src/os/windows/fs.rs index b20eafb4d5..be35ab0ca1 100644 --- a/library/std/src/os/windows/fs.rs +++ b/library/std/src/os/windows/fs.rs @@ -1,4 +1,6 @@ -//! Windows-specific extensions for the primitives in the `std::fs` module. +//! Windows-specific extensions to primitives in the [`std::fs`] module. +//! +//! [`std::fs`]: crate::fs #![stable(feature = "rust1", since = "1.0.0")] @@ -517,11 +519,20 @@ impl FileTypeExt for fs::FileType { } } -/// Creates a new file symbolic link on the filesystem. +/// Creates a new symlink to a non-directory file on the filesystem. /// /// The `link` path will be a file symbolic link pointing to the `original` /// path. /// +/// The `original` path should not be a directory or a symlink to a directory, +/// otherwise the symlink will be broken. Use [`symlink_dir`] for directories. +/// +/// This function currently corresponds to [`CreateSymbolicLinkW`][CreateSymbolicLinkW]. +/// Note that this [may change in the future][changes]. +/// +/// [CreateSymbolicLinkW]: https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-createsymboliclinkw +/// [changes]: io#platform-specific-behavior +/// /// # Examples /// /// ```no_run @@ -537,11 +548,20 @@ pub fn symlink_file, Q: AsRef>(original: P, link: Q) -> io: sys::fs::symlink_inner(original.as_ref(), link.as_ref(), false) } -/// Creates a new directory symlink on the filesystem. +/// Creates a new symlink to a directory on the filesystem. /// /// The `link` path will be a directory symbolic link pointing to the `original` /// path. /// +/// The `original` path must be a directory or a symlink to a directory, +/// otherwise the symlink will be broken. Use [`symlink_file`] for other files. +/// +/// This function currently corresponds to [`CreateSymbolicLinkW`][CreateSymbolicLinkW]. +/// Note that this [may change in the future][changes]. +/// +/// [CreateSymbolicLinkW]: https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-createsymboliclinkw +/// [changes]: io#platform-specific-behavior +/// /// # Examples /// /// ```no_run diff --git a/library/std/src/os/windows/io/handle.rs b/library/std/src/os/windows/io/handle.rs index 72a17adb3b..1527f5b6b0 100644 --- a/library/std/src/os/windows/io/handle.rs +++ b/library/std/src/os/windows/io/handle.rs @@ -4,12 +4,10 @@ use super::raw::{AsRawHandle, FromRawHandle, IntoRawHandle, RawHandle}; use crate::convert::TryFrom; -use crate::ffi::c_void; use crate::fmt; use crate::fs; use crate::marker::PhantomData; use crate::mem::forget; -use crate::ptr::NonNull; use crate::sys::c; use crate::sys_common::{AsInner, FromInner, IntoInner}; @@ -20,17 +18,20 @@ use crate::sys_common::{AsInner, FromInner, IntoInner}; /// /// This uses `repr(transparent)` and has the representation of a host handle, /// so it can be used in FFI in places where a handle is passed as an argument, -/// it is not captured or consumed, and it is never null. +/// it is not captured or consumed. /// /// Note that it *may* have the value `INVALID_HANDLE_VALUE` (-1), which is /// sometimes a valid handle value. See [here] for the full story. /// +/// And, it *may* have the value `NULL` (0), which can occur when consoles are +/// detached from processes, or when `windows_subsystem` is used. +/// /// [here]: https://devblogs.microsoft.com/oldnewthing/20040302-00/?p=40443 #[derive(Copy, Clone)] #[repr(transparent)] #[unstable(feature = "io_safety", issue = "87074")] pub struct BorrowedHandle<'handle> { - handle: NonNull, + handle: RawHandle, _phantom: PhantomData<&'handle OwnedHandle>, } @@ -38,14 +39,11 @@ pub struct BorrowedHandle<'handle> { /// /// This closes the handle on drop. /// -/// This uses `repr(transparent)` and has the representation of a host handle, -/// so it can be used in FFI in places where a handle is passed as a consumed -/// argument or returned as an owned value, and is never null. -/// /// Note that it *may* have the value `INVALID_HANDLE_VALUE` (-1), which is -/// sometimes a valid handle value. See [here] for the full story. For APIs -/// like `CreateFileW` which report errors with `INVALID_HANDLE_VALUE` instead -/// of null, use [`HandleOrInvalid`] instead of `Option`. +/// sometimes a valid handle value. See [here] for the full story. +/// +/// And, it *may* have the value `NULL` (0), which can occur when consoles are +/// detached from processes, or when `windows_subsystem` is used. /// /// `OwnedHandle` uses [`CloseHandle`] to close its handle on drop. As such, /// it must not be used with handles to open registry keys which need to be @@ -55,12 +53,31 @@ pub struct BorrowedHandle<'handle> { /// [`RegCloseKey`]: https://docs.microsoft.com/en-us/windows/win32/api/winreg/nf-winreg-regclosekey /// /// [here]: https://devblogs.microsoft.com/oldnewthing/20040302-00/?p=40443 -#[repr(transparent)] #[unstable(feature = "io_safety", issue = "87074")] pub struct OwnedHandle { - handle: NonNull, + handle: RawHandle, } +/// FFI type for handles in return values or out parameters, where `NULL` is used +/// as a sentry value to indicate errors, such as in the return value of `CreateThread`. This uses +/// `repr(transparent)` and has the representation of a host handle, so that it can be used in such +/// FFI declarations. +/// +/// The only thing you can usefully do with a `HandleOrNull` is to convert it into an +/// `OwnedHandle` using its [`TryFrom`] implementation; this conversion takes care of the check for +/// `NULL`. This ensures that such FFI calls cannot start using the handle without +/// checking for `NULL` first. +/// +/// This type concerns any value other than `NULL` to be valid, including `INVALID_HANDLE_VALUE`. +/// This is because APIs that use `NULL` as their sentry value don't treat `INVALID_HANDLE_VALUE` +/// as special. +/// +/// If this holds a valid handle, it will close the handle on drop. +#[repr(transparent)] +#[unstable(feature = "io_safety", issue = "87074")] +#[derive(Debug)] +pub struct HandleOrNull(OwnedHandle); + /// FFI type for handles in return values or out parameters, where `INVALID_HANDLE_VALUE` is used /// as a sentry value to indicate errors, such as in the return value of `CreateFileW`. This uses /// `repr(transparent)` and has the representation of a host handle, so that it can be used in such @@ -71,11 +88,15 @@ pub struct OwnedHandle { /// `INVALID_HANDLE_VALUE`. This ensures that such FFI calls cannot start using the handle without /// checking for `INVALID_HANDLE_VALUE` first. /// +/// This type concerns any value other than `INVALID_HANDLE_VALUE` to be valid, including `NULL`. +/// This is because APIs that use `INVALID_HANDLE_VALUE` as their sentry value may return `NULL` +/// under `windows_subsystem = "windows"` or other situations where I/O devices are detached. +/// /// If this holds a valid handle, it will close the handle on drop. #[repr(transparent)] #[unstable(feature = "io_safety", issue = "87074")] #[derive(Debug)] -pub struct HandleOrInvalid(Option); +pub struct HandleOrInvalid(OwnedHandle); // The Windows [`HANDLE`] type may be transferred across and shared between // thread boundaries (despite containing a `*mut void`, which in general isn't @@ -83,9 +104,11 @@ pub struct HandleOrInvalid(Option); // // [`HANDLE`]: std::os::windows::raw::HANDLE unsafe impl Send for OwnedHandle {} +unsafe impl Send for HandleOrNull {} unsafe impl Send for HandleOrInvalid {} unsafe impl Send for BorrowedHandle<'_> {} unsafe impl Sync for OwnedHandle {} +unsafe impl Sync for HandleOrNull {} unsafe impl Sync for HandleOrInvalid {} unsafe impl Sync for BorrowedHandle<'_> {} @@ -95,18 +118,29 @@ impl BorrowedHandle<'_> { /// # Safety /// /// The resource pointed to by `handle` must be a valid open handle, it - /// must remain open for the duration of the returned `BorrowedHandle`, and - /// it must not be null. + /// must remain open for the duration of the returned `BorrowedHandle`. /// /// Note that it *may* have the value `INVALID_HANDLE_VALUE` (-1), which is /// sometimes a valid handle value. See [here] for the full story. /// + /// And, it *may* have the value `NULL` (0), which can occur when consoles are + /// detached from processes, or when `windows_subsystem` is used. + /// /// [here]: https://devblogs.microsoft.com/oldnewthing/20040302-00/?p=40443 #[inline] #[unstable(feature = "io_safety", issue = "87074")] pub unsafe fn borrow_raw_handle(handle: RawHandle) -> Self { - assert!(!handle.is_null()); - Self { handle: NonNull::new_unchecked(handle), _phantom: PhantomData } + Self { handle, _phantom: PhantomData } + } +} + +impl TryFrom for OwnedHandle { + type Error = (); + + #[inline] + fn try_from(handle_or_null: HandleOrNull) -> Result { + let owned_handle = handle_or_null.0; + if owned_handle.handle.is_null() { Err(()) } else { Ok(owned_handle) } } } @@ -115,44 +149,29 @@ impl TryFrom for OwnedHandle { #[inline] fn try_from(handle_or_invalid: HandleOrInvalid) -> Result { - // In theory, we ought to be able to assume that the pointer here is - // never null, use `OwnedHandle` rather than `Option`, and - // obviate the the panic path here. Unfortunately, Win32 documentation - // doesn't explicitly guarantee this anywhere. - // - // APIs like [`CreateFileW`] itself have `HANDLE` arguments where a - // null handle indicates an absent value, which wouldn't work if null - // were a valid handle value, so it seems very unlikely that it could - // ever return null. But who knows? - // - // [`CreateFileW`]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilew - let owned_handle = handle_or_invalid.0.expect("A `HandleOrInvalid` was null!"); - if owned_handle.handle.as_ptr() == c::INVALID_HANDLE_VALUE { - Err(()) - } else { - Ok(owned_handle) - } + let owned_handle = handle_or_invalid.0; + if owned_handle.handle == c::INVALID_HANDLE_VALUE { Err(()) } else { Ok(owned_handle) } } } impl AsRawHandle for BorrowedHandle<'_> { #[inline] fn as_raw_handle(&self) -> RawHandle { - self.handle.as_ptr() + self.handle } } impl AsRawHandle for OwnedHandle { #[inline] fn as_raw_handle(&self) -> RawHandle { - self.handle.as_ptr() + self.handle } } impl IntoRawHandle for OwnedHandle { #[inline] fn into_raw_handle(self) -> RawHandle { - let handle = self.handle.as_ptr(); + let handle = self.handle; forget(self); handle } @@ -161,9 +180,6 @@ impl IntoRawHandle for OwnedHandle { impl FromRawHandle for OwnedHandle { /// Constructs a new instance of `Self` from the given raw handle. /// - /// Use `HandleOrInvalid` instead of `Option` for APIs that - /// use `INVALID_HANDLE_VALUE` to indicate failure. - /// /// # Safety /// /// The resource pointed to by `handle` must be open and suitable for @@ -180,8 +196,28 @@ impl FromRawHandle for OwnedHandle { /// [here]: https://devblogs.microsoft.com/oldnewthing/20040302-00/?p=40443 #[inline] unsafe fn from_raw_handle(handle: RawHandle) -> Self { - assert!(!handle.is_null()); - Self { handle: NonNull::new_unchecked(handle) } + Self { handle } + } +} + +impl FromRawHandle for HandleOrNull { + /// Constructs a new instance of `Self` from the given `RawHandle` returned + /// from a Windows API that uses null to indicate failure, such as + /// `CreateThread`. + /// + /// Use `HandleOrInvalid` instead of `HandleOrNull` for APIs that + /// use `INVALID_HANDLE_VALUE` to indicate failure. + /// + /// # Safety + /// + /// The resource pointed to by `handle` must be either open and otherwise + /// unowned, or null. Note that not all Windows APIs use null for errors; + /// see [here] for the full story. + /// + /// [here]: https://devblogs.microsoft.com/oldnewthing/20040302-00/?p=40443 + #[inline] + unsafe fn from_raw_handle(handle: RawHandle) -> Self { + Self(OwnedHandle::from_raw_handle(handle)) } } @@ -190,21 +226,20 @@ impl FromRawHandle for HandleOrInvalid { /// from a Windows API that uses `INVALID_HANDLE_VALUE` to indicate /// failure, such as `CreateFileW`. /// - /// Use `Option` instead of `HandleOrInvalid` for APIs that + /// Use `HandleOrNull` instead of `HandleOrInvalid` for APIs that /// use null to indicate failure. /// /// # Safety /// /// The resource pointed to by `handle` must be either open and otherwise - /// unowned, or equal to `INVALID_HANDLE_VALUE` (-1). It must not be null. - /// Note that not all Windows APIs use `INVALID_HANDLE_VALUE` for errors; - /// see [here] for the full story. + /// unowned, null, or equal to `INVALID_HANDLE_VALUE` (-1). Note that not + /// all Windows APIs use `INVALID_HANDLE_VALUE` for errors; see [here] for + /// the full story. /// /// [here]: https://devblogs.microsoft.com/oldnewthing/20040302-00/?p=40443 #[inline] unsafe fn from_raw_handle(handle: RawHandle) -> Self { - // We require non-null here to catch errors earlier. - Self(Some(OwnedHandle::from_raw_handle(handle))) + Self(OwnedHandle::from_raw_handle(handle)) } } @@ -212,7 +247,7 @@ impl Drop for OwnedHandle { #[inline] fn drop(&mut self) { unsafe { - let _ = c::CloseHandle(self.handle.as_ptr()); + let _ = c::CloseHandle(self.handle); } } } diff --git a/library/std/src/os/windows/mod.rs b/library/std/src/os/windows/mod.rs index 969054dd3b..52eb3b7c06 100644 --- a/library/std/src/os/windows/mod.rs +++ b/library/std/src/os/windows/mod.rs @@ -5,6 +5,22 @@ //! the core `std` library. These extensions allow developers to use //! `std` types and idioms with Windows in a way that the normal //! platform-agnostic idioms would not normally support. +//! +//! # Examples +//! +//! ```no_run +//! use std::fs::File; +//! use std::os::windows::prelude::*; +//! +//! fn main() -> std::io::Result<()> { +//! let f = File::create("foo.txt")?; +//! let handle = f.as_raw_handle(); +//! +//! // use handle with native windows bindings +//! +//! Ok(()) +//! } +//! ``` #![stable(feature = "rust1", since = "1.0.0")] #![doc(cfg(windows))] diff --git a/library/std/src/os/windows/process.rs b/library/std/src/os/windows/process.rs index b246599dfc..9510d10480 100644 --- a/library/std/src/os/windows/process.rs +++ b/library/std/src/os/windows/process.rs @@ -1,4 +1,6 @@ -//! Extensions to `std::process` for Windows. +//! Windows-specific extensions to primitives in the [`std::process`] module. +//! +//! [`std::process`]: crate::process #![stable(feature = "process_extensions", since = "1.2.0")] diff --git a/library/std/src/os/windows/raw.rs b/library/std/src/os/windows/raw.rs index 5014e008eb..0ef3adade5 100644 --- a/library/std/src/os/windows/raw.rs +++ b/library/std/src/os/windows/raw.rs @@ -7,8 +7,10 @@ use crate::os::raw::c_void; #[stable(feature = "raw_ext", since = "1.1.0")] pub type HANDLE = *mut c_void; #[cfg(target_pointer_width = "32")] +#[doc(cfg(all()))] #[stable(feature = "raw_ext", since = "1.1.0")] pub type SOCKET = u32; #[cfg(target_pointer_width = "64")] +#[doc(cfg(all()))] #[stable(feature = "raw_ext", since = "1.1.0")] pub type SOCKET = u64; diff --git a/library/std/src/os/windows/thread.rs b/library/std/src/os/windows/thread.rs index fb1bf66cee..d81d6d0ac2 100644 --- a/library/std/src/os/windows/thread.rs +++ b/library/std/src/os/windows/thread.rs @@ -1,4 +1,6 @@ -//! Extensions to `std::thread` for Windows. +//! Windows-specific extensions to primitives in the [`std::thread`] module. +//! +//! [`std::thread`]: crate::thread #![stable(feature = "thread_extensions", since = "1.9.0")] diff --git a/library/std/src/panic.rs b/library/std/src/panic.rs index c1c0395849..21e9669c11 100644 --- a/library/std/src/panic.rs +++ b/library/std/src/panic.rs @@ -10,7 +10,7 @@ use crate::thread::Result; #[doc(hidden)] #[unstable(feature = "edition_panic", issue = "none", reason = "use panic!() instead")] -#[allow_internal_unstable(libstd_sys_internals, const_format_args)] +#[allow_internal_unstable(libstd_sys_internals, const_format_args, core_panic)] #[cfg_attr(not(test), rustc_diagnostic_item = "std_panic_2015_macro")] #[rustc_macro_transparency = "semitransparent"] pub macro panic_2015 { @@ -20,6 +20,10 @@ pub macro panic_2015 { ($msg:expr $(,)?) => ({ $crate::rt::begin_panic($msg) }), + // Special-case the single-argument case for const_panic. + ("{}", $arg:expr $(,)?) => ({ + $crate::rt::panic_display(&$arg) + }), ($fmt:expr, $($arg:tt)+) => ({ $crate::rt::begin_panic_fmt(&$crate::const_format_args!($fmt, $($arg)+)) }), diff --git a/library/std/src/panicking.rs b/library/std/src/panicking.rs index 7de70091be..231c9fc19c 100644 --- a/library/std/src/panicking.rs +++ b/library/std/src/panicking.rs @@ -450,7 +450,7 @@ pub fn panicking() -> bool { #[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(all(not(bootstrap), not(test)), lang = "begin_panic_fmt")] +#[cfg_attr(not(test), lang = "begin_panic_fmt")] pub fn begin_panic_fmt(msg: &fmt::Arguments<'_>) -> ! { if cfg!(feature = "panic_immediate_abort") { intrinsics::abort() diff --git a/library/std/src/path.rs b/library/std/src/path.rs index 2a9c361c18..8f00d2260e 100644 --- a/library/std/src/path.rs +++ b/library/std/src/path.rs @@ -215,6 +215,7 @@ impl<'a> Prefix<'a> { /// assert!(!Disk(b'C').is_verbatim()); /// ``` #[inline] + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] pub fn is_verbatim(&self) -> bool { use self::Prefix::*; @@ -247,6 +248,7 @@ impl<'a> Prefix<'a> { /// assert!(path::is_separator('/')); // '/' works for both Unix and Windows /// assert!(!path::is_separator('❤')); /// ``` +#[must_use] #[stable(feature = "rust1", since = "1.0.0")] pub fn is_separator(c: char) -> bool { c.is_ascii() && is_sep_byte(c as u8) @@ -427,6 +429,7 @@ impl<'a> PrefixComponent<'a> { /// Returns the raw [`OsStr`] slice for this prefix. #[stable(feature = "rust1", since = "1.0.0")] + #[must_use] #[inline] pub fn as_os_str(&self) -> &'a OsStr { self.raw @@ -532,6 +535,7 @@ impl<'a> Component<'a> { /// let components: Vec<_> = path.components().map(|comp| comp.as_os_str()).collect(); /// assert_eq!(&components, &[".", "tmp", "foo", "bar.txt"]); /// ``` + #[must_use = "`self` will be dropped if the result is not used"] #[stable(feature = "rust1", since = "1.0.0")] pub fn as_os_str(self) -> &'a OsStr { match self { @@ -675,6 +679,7 @@ impl<'a> Components<'a> { /// /// assert_eq!(Path::new("foo/bar.txt"), components.as_path()); /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] pub fn as_path(&self) -> &'a Path { let mut comps = self.clone(); @@ -820,6 +825,7 @@ impl<'a> Iter<'a> { /// assert_eq!(Path::new("foo/bar.txt"), iter.as_path()); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[must_use] #[inline] pub fn as_path(&self) -> &'a Path { self.inner.as_path() @@ -1145,6 +1151,7 @@ impl PathBuf { /// let path = PathBuf::new(); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[must_use] #[inline] pub fn new() -> PathBuf { PathBuf { inner: OsString::new() } @@ -1169,6 +1176,7 @@ impl PathBuf { /// /// [`with_capacity`]: OsString::with_capacity #[stable(feature = "path_buf_capacity", since = "1.44.0")] + #[must_use] #[inline] pub fn with_capacity(capacity: usize) -> PathBuf { PathBuf { inner: OsString::with_capacity(capacity) } @@ -1185,6 +1193,7 @@ impl PathBuf { /// assert_eq!(Path::new("/test"), p.as_path()); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[must_use] #[inline] pub fn as_path(&self) -> &Path { self @@ -1199,6 +1208,9 @@ impl PathBuf { /// * 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`. + /// * if `self` has a verbatim prefix (e.g. `\\?\C:\windows`) + /// and `path` is not empty, the new path is normalized: all references + /// to `.` and `..` are removed. /// /// # Examples /// @@ -1231,20 +1243,59 @@ impl PathBuf { let mut need_sep = self.as_mut_vec().last().map(|c| !is_sep_byte(*c)).unwrap_or(false); // in the special case of `C:` on Windows, do *not* add a separator + let comps = self.components(); + + if comps.prefix_len() > 0 + && comps.prefix_len() == comps.path.len() + && comps.prefix.unwrap().is_drive() { - let comps = self.components(); - if comps.prefix_len() > 0 - && comps.prefix_len() == comps.path.len() - && comps.prefix.unwrap().is_drive() - { - need_sep = false - } + need_sep = false } // absolute `path` replaces `self` if path.is_absolute() || path.prefix().is_some() { self.as_mut_vec().truncate(0); + // verbatim paths need . and .. removed + } else if comps.prefix_verbatim() && !path.inner.is_empty() { + let mut buf: Vec<_> = comps.collect(); + for c in path.components() { + match c { + Component::RootDir => { + buf.truncate(1); + buf.push(c); + } + Component::CurDir => (), + Component::ParentDir => { + if let Some(Component::Normal(_)) = buf.last() { + buf.pop(); + } + } + _ => buf.push(c), + } + } + + let mut res = OsString::new(); + let mut need_sep = false; + + for c in buf { + if need_sep && c != Component::RootDir { + res.push(MAIN_SEP_STR); + } + res.push(c.as_os_str()); + + need_sep = match c { + Component::RootDir => false, + Component::Prefix(prefix) => { + !prefix.parsed.is_drive() && prefix.parsed.len() > 0 + } + _ => true, + } + } + + self.inner = res; + return; + // `path` has a root but no prefix, e.g., `\windows` (Windows only) } else if path.has_root() { let prefix_len = self.components().prefix_remaining(); @@ -1389,6 +1440,7 @@ impl PathBuf { /// let os_str = p.into_os_string(); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[must_use = "`self` will be dropped if the result is not used"] #[inline] pub fn into_os_string(self) -> OsString { self.inner @@ -1396,6 +1448,7 @@ impl PathBuf { /// Converts this `PathBuf` into a [boxed](Box) [`Path`]. #[stable(feature = "into_boxed_path", since = "1.20.0")] + #[must_use = "`self` will be dropped if the result is not used"] #[inline] pub fn into_boxed_path(self) -> Box { let rw = Box::into_raw(self.inner.into_boxed_os_str()) as *mut Path; @@ -1879,6 +1932,7 @@ impl Path { /// assert_eq!(os_str, std::ffi::OsStr::new("foo.txt")); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[must_use] #[inline] pub fn as_os_str(&self) -> &OsStr { &self.inner @@ -1901,6 +1955,8 @@ impl Path { /// assert_eq!(path.to_str(), Some("foo.txt")); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[inline] pub fn to_str(&self) -> Option<&str> { self.inner.to_str() @@ -1927,6 +1983,8 @@ impl Path { /// Had `path` contained invalid unicode, the `to_string_lossy` call might /// have returned `"fo�.txt"`. #[stable(feature = "rust1", since = "1.0.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[inline] pub fn to_string_lossy(&self) -> Cow<'_, str> { self.inner.to_string_lossy() @@ -1943,6 +2001,8 @@ impl Path { /// assert_eq!(path_buf, std::path::PathBuf::from("foo.txt")); /// ``` #[rustc_conversion_suggestion] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] #[stable(feature = "rust1", since = "1.0.0")] pub fn to_path_buf(&self) -> PathBuf { PathBuf::from(self.inner.to_os_string()) @@ -1967,6 +2027,7 @@ impl Path { /// /// [`has_root`]: Path::has_root #[stable(feature = "rust1", since = "1.0.0")] + #[must_use] #[allow(deprecated)] pub fn is_absolute(&self) -> bool { if cfg!(target_os = "redox") { @@ -1991,6 +2052,7 @@ impl Path { /// /// [`is_absolute`]: Path::is_absolute #[stable(feature = "rust1", since = "1.0.0")] + #[must_use] #[inline] pub fn is_relative(&self) -> bool { !self.is_absolute() @@ -2017,6 +2079,7 @@ impl Path { /// assert!(Path::new("/etc/passwd").has_root()); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[must_use] #[inline] pub fn has_root(&self) -> bool { self.components().has_root() @@ -2467,6 +2530,8 @@ impl Path { /// println!("{}", path.display()); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[must_use = "this does not display the path, \ + it returns an object that can be displayed"] #[inline] pub fn display(&self) -> Display<'_> { Display { path: self } @@ -2552,7 +2617,7 @@ impl Path { /// Returns an iterator over the entries within a directory. /// - /// The iterator will yield instances of [`io::Result`]`<`[`fs::DirEntry`]`>`. New + /// 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`]. @@ -2654,6 +2719,7 @@ impl Path { /// a Unix-like system for example. See [`fs::File::open`] or /// [`fs::OpenOptions::open`] for more information. #[stable(feature = "path_ext", since = "1.5.0")] + #[must_use] pub fn is_file(&self) -> bool { fs::metadata(self).map(|m| m.is_file()).unwrap_or(false) } @@ -2680,6 +2746,7 @@ impl Path { /// check errors, call [`fs::metadata`] and handle its [`Result`]. Then call /// [`fs::Metadata::is_dir`] if it was [`Ok`]. #[stable(feature = "path_ext", since = "1.5.0")] + #[must_use] pub fn is_dir(&self) -> bool { fs::metadata(self).map(|m| m.is_dir()).unwrap_or(false) } @@ -2706,6 +2773,7 @@ impl Path { /// assert_eq!(link_path.exists(), false); /// ``` #[unstable(feature = "is_symlink", issue = "85748")] + #[must_use] pub fn is_symlink(&self) -> bool { fs::symlink_metadata(self).map(|m| m.is_symlink()).unwrap_or(false) } diff --git a/library/std/src/path/tests.rs b/library/std/src/path/tests.rs index ce23cf6cd2..0a16ff2a72 100644 --- a/library/std/src/path/tests.rs +++ b/library/std/src/path/tests.rs @@ -1262,6 +1262,16 @@ pub fn test_push() { tp!("\\\\.\\foo", "..\\bar", "\\\\.\\foo\\..\\bar"); tp!("\\\\?\\C:", "foo", "\\\\?\\C:\\foo"); // this is a weird one + + tp!(r"\\?\C:\bar", "../foo", r"\\?\C:\foo"); + tp!(r"\\?\C:\bar", "../../foo", r"\\?\C:\foo"); + tp!(r"\\?\C:\", "../foo", r"\\?\C:\foo"); + tp!(r"\\?\C:", r"D:\foo/./", r"D:\foo/./"); + tp!(r"\\?\C:", r"\\?\D:\foo\.\", r"\\?\D:\foo\.\"); + tp!(r"\\?\A:\x\y", "/foo", r"\\?\A:\foo"); + tp!(r"\\?\A:", r"..\foo\.", r"\\?\A:\foo"); + tp!(r"\\?\A:\x\y", r".\foo\.", r"\\?\A:\x\y\foo"); + tp!(r"\\?\A:\x\y", r"", r"\\?\A:\x\y\"); } } diff --git a/library/std/src/primitive_docs.rs b/library/std/src/primitive_docs.rs index 261d0e648e..0de9126dab 100644 --- a/library/std/src/primitive_docs.rs +++ b/library/std/src/primitive_docs.rs @@ -1,18 +1,21 @@ +// `library/{std,core}/src/primitive_docs.rs` should have the same contents. +// These are different files so that relative links work properly without +// having to have `CARGO_PKG_NAME` set, but conceptually they should always be the same. #[doc(primitive = "bool")] #[doc(alias = "true")] #[doc(alias = "false")] /// The boolean type. /// -/// The `bool` represents a value, which could only be either `true` or `false`. If you cast -/// a `bool` into an integer, `true` will be 1 and `false` will be 0. +/// The `bool` represents a value, which could only be either [`true`] or [`false`]. If you cast +/// a `bool` into an integer, [`true`] will be 1 and [`false`] will be 0. /// /// # Basic usage /// /// `bool` implements various traits, such as [`BitAnd`], [`BitOr`], [`Not`], etc., /// which allow us to perform boolean operations using `&`, `|` and `!`. /// -/// `if` requires a `bool` value as its conditional. [`assert!`], which is an -/// important macro in testing, checks whether an expression is `true` and panics +/// [`if`] requires a `bool` value as its conditional. [`assert!`], which is an +/// important macro in testing, checks whether an expression is [`true`] and panics /// if it isn't. /// /// ``` @@ -20,9 +23,12 @@ /// assert!(!bool_val); /// ``` /// +/// [`true`]: ../std/keyword.true.html +/// [`false`]: ../std/keyword.false.html /// [`BitAnd`]: ops::BitAnd /// [`BitOr`]: ops::BitOr /// [`Not`]: ops::Not +/// [`if`]: ../std/keyword.if.html /// /// # Examples /// @@ -100,7 +106,7 @@ mod prim_bool {} /// behaviour of the `!` type - expressions with type `!` will coerce into any other type. /// /// [`u32`]: prim@u32 -/// [`exit`]: process::exit +#[doc = concat!("[`exit`]: ", include_str!("../primitive_docs/process_exit.md"))] /// /// # `!` and generics /// @@ -185,7 +191,7 @@ mod prim_bool {} /// because `!` coerces to `Result` automatically. /// /// [`String::from_str`]: str::FromStr::from_str -/// [`String`]: string::String +#[doc = concat!("[`String`]: ", include_str!("../primitive_docs/string_string.md"))] /// [`FromStr`]: str::FromStr /// /// # `!` and traits @@ -261,7 +267,7 @@ mod prim_bool {} /// `impl` for this which simply panics, but the same is true for any type (we could `impl /// Default` for (eg.) [`File`] by just making [`default()`] panic.) /// -/// [`File`]: fs::File +#[doc = concat!("[`File`]: ", include_str!("../primitive_docs/fs_file.md"))] /// [`Debug`]: fmt::Debug /// [`default()`]: Default::default /// @@ -269,7 +275,6 @@ mod prim_bool {} mod prim_never {} #[doc(primitive = "char")] -// /// A character type. /// /// The `char` type represents a single character. More specifically, since @@ -301,7 +306,7 @@ mod prim_never {} /// assert_eq!(5, s.len() * std::mem::size_of::()); /// ``` /// -/// [`String`]: string/struct.String.html +#[doc = concat!("[`String`]: ", include_str!("../primitive_docs/string_string.md"))] /// /// As always, remember that a human intuition for 'character' might not map to /// Unicode's definitions. For example, despite looking similar, the 'é' @@ -385,8 +390,11 @@ mod prim_char {} #[stable(feature = "rust1", since = "1.0.0")] mod prim_unit {} -#[doc(alias = "ptr")] #[doc(primitive = "pointer")] +#[doc(alias = "ptr")] +#[doc(alias = "*")] +#[doc(alias = "*const")] +#[doc(alias = "*mut")] // /// Raw, unsafe pointers, `*const T`, and `*mut T`. /// @@ -493,16 +501,16 @@ mod prim_unit {} /// [`null_mut`]: ptr::null_mut /// [`is_null`]: pointer::is_null /// [`offset`]: pointer::offset -/// [`into_raw`]: Box::into_raw +#[doc = concat!("[`into_raw`]: ", include_str!("../primitive_docs/box_into_raw.md"))] /// [`drop`]: mem::drop /// [`write`]: ptr::write #[stable(feature = "rust1", since = "1.0.0")] mod prim_pointer {} +#[doc(primitive = "array")] #[doc(alias = "[]")] #[doc(alias = "[T;N]")] // unfortunately, rustdoc doesn't have fuzzy search for aliases #[doc(alias = "[T; N]")] -#[doc(primitive = "array")] /// A fixed-size array, denoted `[T; N]`, for the element type, `T`, and the /// non-negative compile-time constant size, `N`. /// @@ -574,10 +582,10 @@ mod prim_pointer {} /// /// # Editions /// -/// Prior to Rust 1.53, arrays did not implement `IntoIterator` by value, so the method call -/// `array.into_iter()` auto-referenced into a slice iterator. Right now, the old behavior -/// is preserved in the 2015 and 2018 editions of Rust for compatibility, ignoring -/// `IntoIterator` by value. In the future, the behavior on the 2015 and 2018 edition +/// Prior to Rust 1.53, arrays did not implement [`IntoIterator`] by value, so the method call +/// `array.into_iter()` auto-referenced into a [slice iterator](slice::iter). Right now, the old +/// behavior is preserved in the 2015 and 2018 editions of Rust for compatibility, ignoring +/// [`IntoIterator`] by value. In the future, the behavior on the 2015 and 2018 edition /// might be made consistent to the behavior of later editions. /// /// ```rust,edition2018 @@ -609,8 +617,7 @@ mod prim_pointer {} /// Starting in the 2021 edition, `array.into_iter()` uses `IntoIterator` normally to iterate /// by value, and `iter()` should be used to iterate by reference like previous editions. /// -#[cfg_attr(bootstrap, doc = "```rust,edition2021,ignore")] -#[cfg_attr(not(bootstrap), doc = "```rust,edition2021")] +/// ```rust,edition2021 /// // Rust 2021: /// /// let array: [i32; 3] = [0; 3]; @@ -833,7 +840,7 @@ mod prim_str {} /// ``` /// /// The sequential nature of the tuple applies to its implementations of various -/// traits. For example, in `PartialOrd` and `Ord`, the elements are compared +/// traits. For example, in [`PartialOrd`] and [`Ord`], the elements are compared /// sequentially until the first non-equal set is found. /// /// For more about tuples, see [the book](../book/ch03-02-data-types.html#the-tuple-type). @@ -1037,14 +1044,16 @@ mod prim_usize {} /// References, both shared and mutable. /// /// A reference represents a borrow of some owned value. You can get one by using the `&` or `&mut` -/// operators on a value, or by using a `ref` or `ref mut` pattern. +/// operators on a value, or by using a [`ref`](../std/keyword.ref.html) or +/// [ref](../std/keyword.ref.html) [mut](../std/keyword.mut.html) pattern. /// /// For those familiar with pointers, a reference is just a pointer that is assumed to be /// aligned, not null, and pointing to memory containing a valid value of `T` - for example, -/// `&bool` can only point to an allocation containing the integer values `1` (`true`) or `0` -/// (`false`), but creating a `&bool` that points to an allocation containing +/// &[bool] can only point to an allocation containing the integer values `1` +/// ([`true`](../std/keyword.true.html)) or `0` ([`false`](../std/keyword.false.html)), but +/// creating a &[bool] that points to an allocation containing /// the value `3` causes undefined behaviour. -/// In fact, `Option<&T>` has the same memory representation as a +/// In fact, [Option]\<&T> has the same memory representation as a /// nullable but aligned pointer, and can be passed across FFI boundaries as such. /// /// In most cases, references can be used much like the original value. Field access, method @@ -1110,6 +1119,7 @@ mod prim_usize {} /// /// [`DerefMut`]: ops::DerefMut /// [`BorrowMut`]: borrow::BorrowMut +/// [bool]: prim@bool /// /// The following traits are implemented on `&T` references if the underlying `T` also implements /// that trait: @@ -1127,7 +1137,7 @@ mod prim_usize {} /// [`std::fmt`]: fmt /// ['Pointer`]: fmt::Pointer /// [`Hash`]: hash::Hash -/// [`ToSocketAddrs`]: net::ToSocketAddrs +#[doc = concat!("[`ToSocketAddrs`]: ", include_str!("../primitive_docs/net_tosocketaddrs.md"))] /// /// `&mut T` references get all of the above except `ToSocketAddrs`, plus the following, if `T` /// implements that trait: @@ -1140,7 +1150,7 @@ mod prim_usize {} /// * [`ExactSizeIterator`] /// * [`FusedIterator`] /// * [`TrustedLen`] -/// * [`Send`] \(note that `&T` references only get `Send` if `T: Sync`) +/// * [`Send`] \(note that `&T` references only get `Send` if T: [Sync]) /// * [`io::Write`] /// * [`Read`] /// * [`Seek`] @@ -1148,9 +1158,10 @@ mod prim_usize {} /// /// [`FusedIterator`]: iter::FusedIterator /// [`TrustedLen`]: iter::TrustedLen -/// [`Seek`]: io::Seek -/// [`BufRead`]: io::BufRead -/// [`Read`]: io::Read +#[doc = concat!("[`Seek`]: ", include_str!("../primitive_docs/io_seek.md"))] +#[doc = concat!("[`BufRead`]: ", include_str!("../primitive_docs/io_bufread.md"))] +#[doc = concat!("[`Read`]: ", include_str!("../primitive_docs/io_read.md"))] +#[doc = concat!("[`io::Write`]: ", include_str!("../primitive_docs/io_write.md"))] /// /// Note that due to method call deref coercion, simply calling a trait method will act like they /// work on references as well as they do on owned values! The implementations described here are @@ -1172,7 +1183,8 @@ mod prim_ref {} /// Function pointers are pointers that point to *code*, not data. They can be called /// just like functions. Like references, function pointers are, among other things, assumed to /// not be null, so if you want to pass a function pointer over FFI and be able to accommodate null -/// pointers, make your type `Option` with your required signature. +/// pointers, make your type [`Option`](core::option#options-and-pointers-nullable-pointers) +/// with your required signature. /// /// ### Safety /// diff --git a/library/std/src/process.rs b/library/std/src/process.rs index c9b21fcf9c..4bd06475e2 100644 --- a/library/std/src/process.rs +++ b/library/std/src/process.rs @@ -115,7 +115,7 @@ use crate::path::Path; use crate::str; use crate::sys::pipe::{read2, AnonPipe}; use crate::sys::process as imp; -#[unstable(feature = "command_access", issue = "44434")] +#[stable(feature = "command_access", since = "1.57.0")] pub use crate::sys_common::process::CommandEnvs; use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner}; @@ -943,13 +943,12 @@ impl Command { /// # Examples /// /// ``` - /// # #![feature(command_access)] /// use std::process::Command; /// /// let cmd = Command::new("echo"); /// assert_eq!(cmd.get_program(), "echo"); /// ``` - #[unstable(feature = "command_access", issue = "44434")] + #[stable(feature = "command_access", since = "1.57.0")] pub fn get_program(&self) -> &OsStr { self.inner.get_program() } @@ -963,7 +962,6 @@ impl Command { /// # Examples /// /// ``` - /// # #![feature(command_access)] /// use std::ffi::OsStr; /// use std::process::Command; /// @@ -972,7 +970,7 @@ impl Command { /// let args: Vec<&OsStr> = cmd.get_args().collect(); /// assert_eq!(args, &["first", "second"]); /// ``` - #[unstable(feature = "command_access", issue = "44434")] + #[stable(feature = "command_access", since = "1.57.0")] pub fn get_args(&self) -> CommandArgs<'_> { CommandArgs { inner: self.inner.get_args() } } @@ -992,7 +990,6 @@ impl Command { /// # Examples /// /// ``` - /// # #![feature(command_access)] /// use std::ffi::OsStr; /// use std::process::Command; /// @@ -1004,7 +1001,7 @@ impl Command { /// (OsStr::new("TZ"), None) /// ]); /// ``` - #[unstable(feature = "command_access", issue = "44434")] + #[stable(feature = "command_access", since = "1.57.0")] pub fn get_envs(&self) -> CommandEnvs<'_> { self.inner.get_envs() } @@ -1016,7 +1013,6 @@ impl Command { /// # Examples /// /// ``` - /// # #![feature(command_access)] /// use std::path::Path; /// use std::process::Command; /// @@ -1025,7 +1021,7 @@ impl Command { /// cmd.current_dir("/bin"); /// assert_eq!(cmd.get_current_dir(), Some(Path::new("/bin"))); /// ``` - #[unstable(feature = "command_access", issue = "44434")] + #[stable(feature = "command_access", since = "1.57.0")] pub fn get_current_dir(&self) -> Option<&Path> { self.inner.get_current_dir() } @@ -1057,13 +1053,13 @@ impl AsInnerMut for Command { /// /// This struct is created by [`Command::get_args`]. See its documentation for /// more. -#[unstable(feature = "command_access", issue = "44434")] +#[stable(feature = "command_access", since = "1.57.0")] #[derive(Debug)] pub struct CommandArgs<'a> { inner: imp::CommandArgs<'a>, } -#[unstable(feature = "command_access", issue = "44434")] +#[stable(feature = "command_access", since = "1.57.0")] impl<'a> Iterator for CommandArgs<'a> { type Item = &'a OsStr; fn next(&mut self) -> Option<&'a OsStr> { @@ -1074,7 +1070,7 @@ impl<'a> Iterator for CommandArgs<'a> { } } -#[unstable(feature = "command_access", issue = "44434")] +#[stable(feature = "command_access", since = "1.57.0")] impl<'a> ExactSizeIterator for CommandArgs<'a> { fn len(&self) -> usize { self.inner.len() @@ -1907,7 +1903,7 @@ impl Child { /// [platform-specific behavior]: #platform-specific-behavior #[stable(feature = "rust1", since = "1.0.0")] pub fn exit(code: i32) -> ! { - crate::sys_common::rt::cleanup(); + crate::rt::cleanup(); crate::sys::os::exit(code) } diff --git a/library/std/src/rt.rs b/library/std/src/rt.rs index 72e6c23ee4..4d72aff011 100644 --- a/library/std/src/rt.rs +++ b/library/std/src/rt.rs @@ -13,9 +13,92 @@ issue = "none" )] #![doc(hidden)] +#![deny(unsafe_op_in_unsafe_fn)] +#![allow(unused_macros)] + +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; + +use crate::sync::Once; +use crate::sys; +use crate::sys_common::thread_info; +use crate::thread::Thread; + +// Prints to the "panic output", depending on the platform this may be: +// - the standard error output +// - some dedicated platform specific output +// - nothing (so this macro is a no-op) +macro_rules! rtprintpanic { + ($($t:tt)*) => { + if let Some(mut out) = crate::sys::stdio::panic_output() { + let _ = crate::io::Write::write_fmt(&mut out, format_args!($($t)*)); + } + } +} + +macro_rules! rtabort { + ($($t:tt)*) => { + { + rtprintpanic!("fatal runtime error: {}\n", format_args!($($t)*)); + crate::sys::abort_internal(); + } + } +} + +macro_rules! rtassert { + ($e:expr) => { + if !$e { + rtabort!(concat!("assertion failed: ", stringify!($e))); + } + }; +} + +macro_rules! rtunwrap { + ($ok:ident, $e:expr) => { + match $e { + $ok(v) => v, + ref err => { + let err = err.as_ref().map(drop); // map Ok/Some which might not be Debug + rtabort!(concat!("unwrap failed: ", stringify!($e), " = {:?}"), err) + } + } + }; +} + +// One-time runtime initialization. +// Runs before `main`. +// SAFETY: must be called only once during runtime initialization. +// NOTE: this is not guaranteed to run, for example when Rust code is called externally. +#[cfg_attr(test, allow(dead_code))] +unsafe fn init(argc: isize, argv: *const *const u8) { + unsafe { + sys::init(argc, argv); + + let main_guard = sys::thread::guard::init(); + // Next, set up the current Thread with the guard information we just + // created. Note that this isn't necessary in general for new threads, + // but we just do this to name the main thread and to give it correct + // info about the stack bounds. + let thread = Thread::new(Some(rtunwrap!(Ok, CString::new("main")))); + thread_info::set(main_guard, thread); + } +} + +// One-time runtime cleanup. +// Runs after `main` or at program exit. +// NOTE: this is not guaranteed to run, for example when the program aborts. +pub(crate) fn cleanup() { + static CLEANUP: Once = Once::new(); + CLEANUP.call_once(|| unsafe { + // Flush stdout and disable buffering. + crate::io::cleanup(); + // SAFETY: Only called once during runtime cleanup. + sys::cleanup(); + }); +} // To reduce the generated code of the new `lang_start`, this function is doing // the real work. @@ -25,7 +108,7 @@ fn lang_start_internal( argc: isize, argv: *const *const u8, ) -> Result { - use crate::{mem, panic, sys, sys_common}; + use crate::{mem, panic}; let rt_abort = move |e| { mem::forget(e); rtabort!("initialization or cleanup bug"); @@ -41,14 +124,14 @@ fn lang_start_internal( // prevent libstd from accidentally introducing a panic to these functions. Another is from // user code from `main` or, more nefariously, as described in e.g. issue #86030. // SAFETY: Only called once during runtime initialization. - panic::catch_unwind(move || unsafe { sys_common::rt::init(argc, argv) }).map_err(rt_abort)?; + panic::catch_unwind(move || unsafe { init(argc, argv) }).map_err(rt_abort)?; let ret_code = panic::catch_unwind(move || panic::catch_unwind(main).unwrap_or(101) as isize) .map_err(move |e| { mem::forget(e); rtprintpanic!("drop of the panic payload panicked"); sys::abort_internal() }); - panic::catch_unwind(sys_common::rt::cleanup).map_err(rt_abort)?; + panic::catch_unwind(cleanup).map_err(rt_abort)?; ret_code } @@ -59,10 +142,10 @@ fn lang_start( argc: isize, argv: *const *const u8, ) -> isize { - lang_start_internal( + let Ok(v) = lang_start_internal( &move || crate::sys_common::backtrace::__rust_begin_short_backtrace(main).report(), argc, argv, - ) - .into_ok() + ); + v } diff --git a/library/std/src/sync/barrier.rs b/library/std/src/sync/barrier.rs index a17b82f82e..133c3e46cd 100644 --- a/library/std/src/sync/barrier.rs +++ b/library/std/src/sync/barrier.rs @@ -80,6 +80,7 @@ impl Barrier { /// let barrier = Barrier::new(10); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[must_use] pub fn new(n: usize) -> Barrier { Barrier { lock: Mutex::new(BarrierState { count: 0, generation_id: 0 }), @@ -166,6 +167,7 @@ impl BarrierWaitResult { /// println!("{:?}", barrier_wait_result.is_leader()); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[must_use] pub fn is_leader(&self) -> bool { self.0 } diff --git a/library/std/src/sync/condvar.rs b/library/std/src/sync/condvar.rs index 00a4afc570..d8aca9651b 100644 --- a/library/std/src/sync/condvar.rs +++ b/library/std/src/sync/condvar.rs @@ -121,6 +121,7 @@ impl Condvar { /// let condvar = Condvar::new(); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[must_use] pub fn new() -> Condvar { Condvar { inner: sys::Condvar::new() } } diff --git a/library/std/src/sync/mpsc/shared.rs b/library/std/src/sync/mpsc/shared.rs index 0c32e636a5..8487a5f8b5 100644 --- a/library/std/src/sync/mpsc/shared.rs +++ b/library/std/src/sync/mpsc/shared.rs @@ -248,7 +248,11 @@ impl Packet { // Returns true if blocking should proceed. fn decrement(&self, token: SignalToken) -> StartResult { unsafe { - assert_eq!(self.to_wake.load(Ordering::SeqCst), 0); + assert_eq!( + self.to_wake.load(Ordering::SeqCst), + 0, + "This is a known bug in the Rust standard library. See https://github.com/rust-lang/rust/issues/39364" + ); let ptr = token.cast_to_usize(); self.to_wake.store(ptr, Ordering::SeqCst); diff --git a/library/std/src/sync/mutex.rs b/library/std/src/sync/mutex.rs index e1d6324c17..57f1dcca30 100644 --- a/library/std/src/sync/mutex.rs +++ b/library/std/src/sync/mutex.rs @@ -162,7 +162,7 @@ use crate::sys_common::mutex as sys; /// assert_eq!(*res_mutex.lock().unwrap(), 800); /// ``` #[stable(feature = "rust1", since = "1.0.0")] -#[cfg_attr(not(test), rustc_diagnostic_item = "mutex_type")] +#[cfg_attr(not(test), rustc_diagnostic_item = "Mutex")] pub struct Mutex { inner: sys::MovableMutex, poison: poison::Flag, @@ -188,6 +188,12 @@ unsafe impl Sync for Mutex {} /// [`lock`]: Mutex::lock /// [`try_lock`]: Mutex::try_lock #[must_use = "if unused the Mutex will immediately unlock"] +#[cfg_attr( + not(bootstrap), + must_not_suspend = "holding a MutexGuard across suspend \ + points can cause deadlocks, delays, \ + and cause Futures to not implement `Send`" +)] #[stable(feature = "rust1", since = "1.0.0")] pub struct MutexGuard<'a, T: ?Sized + 'a> { lock: &'a Mutex, diff --git a/library/std/src/sync/once.rs b/library/std/src/sync/once.rs index a2e935a0ce..1710c00539 100644 --- a/library/std/src/sync/once.rs +++ b/library/std/src/sync/once.rs @@ -186,6 +186,7 @@ impl Once { #[inline] #[stable(feature = "once_new", since = "1.2.0")] #[rustc_const_stable(feature = "const_once_new", since = "1.32.0")] + #[must_use] pub const fn new() -> Once { Once { state_and_queue: AtomicUsize::new(INCOMPLETE), _marker: marker::PhantomData } } diff --git a/library/std/src/sync/rwlock.rs b/library/std/src/sync/rwlock.rs index e50d62d817..2f4395ceef 100644 --- a/library/std/src/sync/rwlock.rs +++ b/library/std/src/sync/rwlock.rs @@ -95,6 +95,12 @@ unsafe impl Sync for RwLock {} /// [`read`]: RwLock::read /// [`try_read`]: RwLock::try_read #[must_use = "if unused the RwLock will immediately unlock"] +#[cfg_attr( + not(bootstrap), + must_not_suspend = "holding a RwLockReadGuard across suspend \ + points can cause deadlocks, delays, \ + and cause Futures to not implement `Send`" +)] #[stable(feature = "rust1", since = "1.0.0")] pub struct RwLockReadGuard<'a, T: ?Sized + 'a> { lock: &'a RwLock, @@ -115,6 +121,12 @@ unsafe impl Sync for RwLockReadGuard<'_, T> {} /// [`write`]: RwLock::write /// [`try_write`]: RwLock::try_write #[must_use = "if unused the RwLock will immediately unlock"] +#[cfg_attr( + not(bootstrap), + must_not_suspend = "holding a RwLockWriteGuard across suspend \ + points can cause deadlocks, delays, \ + and cause Future's to not implement `Send`" +)] #[stable(feature = "rust1", since = "1.0.0")] pub struct RwLockWriteGuard<'a, T: ?Sized + 'a> { lock: &'a RwLock, diff --git a/library/std/src/sys/hermit/thread.rs b/library/std/src/sys/hermit/thread.rs index 8be25f8499..81b21fbbb1 100644 --- a/library/std/src/sys/hermit/thread.rs +++ b/library/std/src/sys/hermit/thread.rs @@ -97,7 +97,7 @@ impl Thread { } } -pub fn available_concurrency() -> io::Result { +pub fn available_parallelism() -> io::Result { unsupported() } diff --git a/library/std/src/sys/itron/abi.rs b/library/std/src/sys/itron/abi.rs new file mode 100644 index 0000000000..f99ee4fa89 --- /dev/null +++ b/library/std/src/sys/itron/abi.rs @@ -0,0 +1,155 @@ +//! ABI for μITRON derivatives +pub type int_t = crate::os::raw::c_int; +pub type uint_t = crate::os::raw::c_uint; +pub type bool_t = int_t; + +/// Kernel object ID +pub type ID = int_t; + +/// The current task. +pub const TSK_SELF: ID = 0; + +/// Relative time +pub type RELTIM = u32; + +/// Timeout (a valid `RELTIM` value or `TMO_FEVR`) +pub type TMO = u32; + +/// The infinite timeout value +pub const TMO_FEVR: TMO = TMO::MAX; + +/// The maximum valid value of `RELTIM` +pub const TMAX_RELTIM: RELTIM = 4_000_000_000; + +/// System time +pub type SYSTIM = u64; + +/// Error code type +pub type ER = int_t; + +/// Error code type, `ID` on success +pub type ER_ID = int_t; + +/// Task or interrupt priority +pub type PRI = int_t; + +/// The special value of `PRI` representing the current task's priority. +pub const TPRI_SELF: PRI = 0; + +/// Object attributes +pub type ATR = uint_t; + +/// Use the priority inheritance protocol +#[cfg(target_os = "solid_asp3")] +pub const TA_INHERIT: ATR = 0x02; + +/// Activate the task on creation +pub const TA_ACT: ATR = 0x01; + +/// The maximum count of a semaphore +pub const TMAX_MAXSEM: uint_t = uint_t::MAX; + +/// Callback parameter +pub type EXINF = isize; + +/// Task entrypoint +pub type TASK = Option; + +// Error codes +pub const E_OK: ER = 0; +pub const E_SYS: ER = -5; +pub const E_NOSPT: ER = -9; +pub const E_RSFN: ER = -10; +pub const E_RSATR: ER = -11; +pub const E_PAR: ER = -17; +pub const E_ID: ER = -18; +pub const E_CTX: ER = -25; +pub const E_MACV: ER = -26; +pub const E_OACV: ER = -27; +pub const E_ILUSE: ER = -28; +pub const E_NOMEM: ER = -33; +pub const E_NOID: ER = -34; +pub const E_NORES: ER = -35; +pub const E_OBJ: ER = -41; +pub const E_NOEXS: ER = -42; +pub const E_QOVR: ER = -43; +pub const E_RLWAI: ER = -49; +pub const E_TMOUT: ER = -50; +pub const E_DLT: ER = -51; +pub const E_CLS: ER = -52; +pub const E_RASTER: ER = -53; +pub const E_WBLK: ER = -57; +pub const E_BOVR: ER = -58; +pub const E_COMM: ER = -65; + +#[derive(Clone, Copy)] +#[repr(C)] +pub struct T_CSEM { + pub sematr: ATR, + pub isemcnt: uint_t, + pub maxsem: uint_t, +} + +#[derive(Clone, Copy)] +#[repr(C)] +pub struct T_CMTX { + pub mtxatr: ATR, + pub ceilpri: PRI, +} + +#[derive(Clone, Copy)] +#[repr(C)] +pub struct T_CTSK { + pub tskatr: ATR, + pub exinf: EXINF, + pub task: TASK, + pub itskpri: PRI, + pub stksz: usize, + pub stk: *mut u8, +} + +extern "C" { + #[link_name = "__asp3_acre_tsk"] + pub fn acre_tsk(pk_ctsk: *const T_CTSK) -> ER_ID; + #[link_name = "__asp3_get_tid"] + pub fn get_tid(p_tskid: *mut ID) -> ER; + #[link_name = "__asp3_dly_tsk"] + pub fn dly_tsk(dlytim: RELTIM) -> ER; + #[link_name = "__asp3_ter_tsk"] + pub fn ter_tsk(tskid: ID) -> ER; + #[link_name = "__asp3_del_tsk"] + pub fn del_tsk(tskid: ID) -> ER; + #[link_name = "__asp3_get_pri"] + pub fn get_pri(tskid: ID, p_tskpri: *mut PRI) -> ER; + #[link_name = "__asp3_rot_rdq"] + pub fn rot_rdq(tskpri: PRI) -> ER; + #[link_name = "__asp3_slp_tsk"] + pub fn slp_tsk() -> ER; + #[link_name = "__asp3_tslp_tsk"] + pub fn tslp_tsk(tmout: TMO) -> ER; + #[link_name = "__asp3_wup_tsk"] + pub fn wup_tsk(tskid: ID) -> ER; + #[link_name = "__asp3_unl_cpu"] + pub fn unl_cpu() -> ER; + #[link_name = "__asp3_dis_dsp"] + pub fn dis_dsp() -> ER; + #[link_name = "__asp3_ena_dsp"] + pub fn ena_dsp() -> ER; + #[link_name = "__asp3_sns_dsp"] + pub fn sns_dsp() -> bool_t; + #[link_name = "__asp3_get_tim"] + pub fn get_tim(p_systim: *mut SYSTIM) -> ER; + #[link_name = "__asp3_acre_mtx"] + pub fn acre_mtx(pk_cmtx: *const T_CMTX) -> ER_ID; + #[link_name = "__asp3_del_mtx"] + pub fn del_mtx(tskid: ID) -> ER; + #[link_name = "__asp3_loc_mtx"] + pub fn loc_mtx(mtxid: ID) -> ER; + #[link_name = "__asp3_ploc_mtx"] + pub fn ploc_mtx(mtxid: ID) -> ER; + #[link_name = "__asp3_tloc_mtx"] + pub fn tloc_mtx(mtxid: ID, tmout: TMO) -> ER; + #[link_name = "__asp3_unl_mtx"] + pub fn unl_mtx(mtxid: ID) -> ER; + pub fn exd_tsk() -> ER; +} diff --git a/library/std/src/sys/itron/condvar.rs b/library/std/src/sys/itron/condvar.rs new file mode 100644 index 0000000000..dac4b8abfc --- /dev/null +++ b/library/std/src/sys/itron/condvar.rs @@ -0,0 +1,294 @@ +//! POSIX conditional variable implementation based on user-space wait queues. +use super::{abi, error::expect_success_aborting, spin::SpinMutex, task, time::with_tmos_strong}; +use crate::{mem::replace, ptr::NonNull, sys::mutex::Mutex, time::Duration}; + +// The implementation is inspired by the queue-based implementation shown in +// Andrew D. Birrell's paper "Implementing Condition Variables with Semaphores" + +pub struct Condvar { + waiters: SpinMutex, +} + +unsafe impl Send for Condvar {} +unsafe impl Sync for Condvar {} + +pub type MovableCondvar = Condvar; + +impl Condvar { + pub const fn new() -> Condvar { + Condvar { waiters: SpinMutex::new(waiter_queue::WaiterQueue::new()) } + } + + pub unsafe fn init(&mut self) {} + + pub unsafe fn notify_one(&self) { + self.waiters.with_locked(|waiters| { + if let Some(task) = waiters.pop_front() { + // Unpark the task + match unsafe { abi::wup_tsk(task) } { + // The task already has a token. + abi::E_QOVR => {} + // Can't undo the effect; abort the program on failure + er => { + expect_success_aborting(er, &"wup_tsk"); + } + } + } + }); + } + + pub unsafe fn notify_all(&self) { + self.waiters.with_locked(|waiters| { + while let Some(task) = waiters.pop_front() { + // Unpark the task + match unsafe { abi::wup_tsk(task) } { + // The task already has a token. + abi::E_QOVR => {} + // Can't undo the effect; abort the program on failure + er => { + expect_success_aborting(er, &"wup_tsk"); + } + } + } + }); + } + + pub unsafe fn wait(&self, mutex: &Mutex) { + // Construct `Waiter`. + let mut waiter = waiter_queue::Waiter::new(); + let waiter = NonNull::from(&mut waiter); + + self.waiters.with_locked(|waiters| unsafe { + waiters.insert(waiter); + }); + + unsafe { mutex.unlock() }; + + // Wait until `waiter` is removed from the queue + loop { + // Park the current task + expect_success_aborting(unsafe { abi::slp_tsk() }, &"slp_tsk"); + + if !self.waiters.with_locked(|waiters| unsafe { waiters.is_queued(waiter) }) { + break; + } + } + + unsafe { mutex.lock() }; + } + + pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool { + // Construct and pin `Waiter` + let mut waiter = waiter_queue::Waiter::new(); + let waiter = NonNull::from(&mut waiter); + + self.waiters.with_locked(|waiters| unsafe { + waiters.insert(waiter); + }); + + unsafe { mutex.unlock() }; + + // Park the current task and do not wake up until the timeout elapses + // or the task gets woken up by `notify_*` + match with_tmos_strong(dur, |tmo| { + let er = unsafe { abi::tslp_tsk(tmo) }; + if er == 0 { + // We were unparked. Are we really dequeued? + if self.waiters.with_locked(|waiters| unsafe { waiters.is_queued(waiter) }) { + // No we are not. Continue waiting. + return abi::E_TMOUT; + } + } + er + }) { + abi::E_TMOUT => {} + er => { + expect_success_aborting(er, &"tslp_tsk"); + } + } + + // Remove `waiter` from `self.waiters`. If `waiter` is still in + // `waiters`, it means we woke up because of a timeout. Otherwise, + // we woke up because of `notify_*`. + let success = self.waiters.with_locked(|waiters| unsafe { !waiters.remove(waiter) }); + + unsafe { mutex.lock() }; + success + } + + pub unsafe fn destroy(&self) {} +} + +mod waiter_queue { + use super::*; + + pub struct WaiterQueue { + head: Option, + } + + #[derive(Copy, Clone)] + struct ListHead { + first: NonNull, + last: NonNull, + } + + unsafe impl Send for ListHead {} + unsafe impl Sync for ListHead {} + + pub struct Waiter { + // These fields are only accessed through `&[mut] WaiterQueue`. + /// The waiting task's ID. Will be zeroed when the task is woken up + /// and removed from a queue. + task: abi::ID, + priority: abi::PRI, + prev: Option>, + next: Option>, + } + + unsafe impl Send for Waiter {} + unsafe impl Sync for Waiter {} + + impl Waiter { + #[inline] + pub fn new() -> Self { + let task = task::current_task_id(); + let priority = task::task_priority(abi::TSK_SELF); + + // Zeroness of `Waiter::task` indicates whether the `Waiter` is + // linked to a queue or not. This invariant is important for + // the correctness. + debug_assert_ne!(task, 0); + + Self { task, priority, prev: None, next: None } + } + } + + impl WaiterQueue { + #[inline] + pub const fn new() -> Self { + Self { head: None } + } + + /// # Safety + /// + /// - The caller must own `*waiter_ptr`. The caller will lose the + /// ownership until `*waiter_ptr` is removed from `self`. + /// + /// - `*waiter_ptr` must be valid until it's removed from the queue. + /// + /// - `*waiter_ptr` must not have been previously inserted to a `WaiterQueue`. + /// + pub unsafe fn insert(&mut self, mut waiter_ptr: NonNull) { + unsafe { + let waiter = waiter_ptr.as_mut(); + + debug_assert!(waiter.prev.is_none()); + debug_assert!(waiter.next.is_none()); + + if let Some(head) = &mut self.head { + // Find the insertion position and insert `waiter` + let insert_after = { + let mut cursor = head.last; + loop { + if waiter.priority <= cursor.as_ref().priority { + // `cursor` and all previous waiters have the same or higher + // priority than `current_task_priority`. Insert the new + // waiter right after `cursor`. + break Some(cursor); + } + cursor = if let Some(prev) = cursor.as_ref().prev { + prev + } else { + break None; + }; + } + }; + + if let Some(mut insert_after) = insert_after { + // Insert `waiter` after `insert_after` + let insert_before = insert_after.as_ref().prev; + + waiter.prev = Some(insert_after); + insert_after.as_mut().next = Some(waiter_ptr); + + waiter.next = insert_before; + if let Some(mut insert_before) = insert_before { + insert_before.as_mut().prev = Some(waiter_ptr); + } + } else { + // Insert `waiter` to the front + waiter.next = Some(head.first); + head.first.as_mut().prev = Some(waiter_ptr); + head.first = waiter_ptr; + } + } else { + // `waiter` is the only element + self.head = Some(ListHead { first: waiter_ptr, last: waiter_ptr }); + } + } + } + + /// Given a `Waiter` that was previously inserted to `self`, remove + /// it from `self` if it's still there. + #[inline] + pub unsafe fn remove(&mut self, mut waiter_ptr: NonNull) -> bool { + unsafe { + let waiter = waiter_ptr.as_mut(); + if waiter.task != 0 { + let head = self.head.as_mut().unwrap(); + + match (waiter.prev, waiter.next) { + (Some(mut prev), Some(mut next)) => { + prev.as_mut().next = Some(next); + next.as_mut().next = Some(prev); + } + (None, Some(mut next)) => { + head.first = next; + next.as_mut().next = None; + } + (Some(mut prev), None) => { + prev.as_mut().next = None; + head.last = prev; + } + (None, None) => { + self.head = None; + } + } + + waiter.task = 0; + + true + } else { + false + } + } + } + + /// Given a `Waiter` that was previously inserted to `self`, return a + /// flag indicating whether it's still in `self`. + #[inline] + pub unsafe fn is_queued(&self, waiter: NonNull) -> bool { + unsafe { waiter.as_ref().task != 0 } + } + + pub fn pop_front(&mut self) -> Option { + unsafe { + let head = self.head.as_mut()?; + let waiter = head.first.as_mut(); + + // Get the ID + let id = replace(&mut waiter.task, 0); + + // Unlink the waiter + if let Some(mut next) = waiter.next { + head.first = next; + next.as_mut().prev = None; + } else { + self.head = None; + } + + Some(id) + } + } + } +} diff --git a/library/std/src/sys/itron/error.rs b/library/std/src/sys/itron/error.rs new file mode 100644 index 0000000000..830c60d329 --- /dev/null +++ b/library/std/src/sys/itron/error.rs @@ -0,0 +1,159 @@ +use crate::{fmt, io::ErrorKind}; + +use super::abi; + +/// Wraps a μITRON error code. +#[derive(Debug, Copy, Clone)] +pub struct ItronError { + er: abi::ER, +} + +impl ItronError { + /// Construct `ItronError` from the specified error code. Returns `None` if the + /// error code does not represent a failure or warning. + #[inline] + pub fn new(er: abi::ER) -> Option { + if er < 0 { Some(Self { er }) } else { None } + } + + /// Returns `Ok(er)` if `er` represents a success or `Err(_)` otherwise. + #[inline] + pub fn err_if_negative(er: abi::ER) -> Result { + if let Some(error) = Self::new(er) { Err(error) } else { Ok(er) } + } + + /// Get the raw error code. + #[inline] + pub fn as_raw(&self) -> abi::ER { + self.er + } +} + +impl fmt::Display for ItronError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + // Allow the platforms to extend `error_name` + if let Some(name) = crate::sys::error::error_name(self.er) { + write!(f, "{} ({})", name, self.er) + } else { + write!(f, "{}", self.er) + } + } +} + +/// Describe the specified μITRON error code. Returns `None` if it's an +/// undefined error code. +pub fn error_name(er: abi::ER) -> Option<&'static str> { + match er { + // Success + er if er >= 0 => None, + + // μITRON 4.0 + abi::E_SYS => Some("system error"), + abi::E_NOSPT => Some("unsupported function"), + abi::E_RSFN => Some("reserved function code"), + abi::E_RSATR => Some("reserved attribute"), + abi::E_PAR => Some("parameter error"), + abi::E_ID => Some("invalid ID number"), + abi::E_CTX => Some("context error"), + abi::E_MACV => Some("memory access violation"), + abi::E_OACV => Some("object access violation"), + abi::E_ILUSE => Some("illegal service call use"), + abi::E_NOMEM => Some("insufficient memory"), + abi::E_NOID => Some("no ID number available"), + abi::E_OBJ => Some("object state error"), + abi::E_NOEXS => Some("non-existent object"), + abi::E_QOVR => Some("queue overflow"), + abi::E_RLWAI => Some("forced release from waiting"), + abi::E_TMOUT => Some("polling failure or timeout"), + abi::E_DLT => Some("waiting object deleted"), + abi::E_CLS => Some("waiting object state changed"), + abi::E_WBLK => Some("non-blocking code accepted"), + abi::E_BOVR => Some("buffer overflow"), + + // The TOPPERS third generation kernels + abi::E_NORES => Some("insufficient system resources"), + abi::E_RASTER => Some("termination request raised"), + abi::E_COMM => Some("communication failure"), + + _ => None, + } +} + +pub fn decode_error_kind(er: abi::ER) -> ErrorKind { + match er { + // Success + er if er >= 0 => ErrorKind::Uncategorized, + + // μITRON 4.0 + // abi::E_SYS + abi::E_NOSPT => ErrorKind::Unsupported, // Some("unsupported function"), + abi::E_RSFN => ErrorKind::InvalidInput, // Some("reserved function code"), + abi::E_RSATR => ErrorKind::InvalidInput, // Some("reserved attribute"), + abi::E_PAR => ErrorKind::InvalidInput, // Some("parameter error"), + abi::E_ID => ErrorKind::NotFound, // Some("invalid ID number"), + // abi::E_CTX + abi::E_MACV => ErrorKind::PermissionDenied, // Some("memory access violation"), + abi::E_OACV => ErrorKind::PermissionDenied, // Some("object access violation"), + // abi::E_ILUSE + abi::E_NOMEM => ErrorKind::OutOfMemory, // Some("insufficient memory"), + abi::E_NOID => ErrorKind::OutOfMemory, // Some("no ID number available"), + // abi::E_OBJ + abi::E_NOEXS => ErrorKind::NotFound, // Some("non-existent object"), + // abi::E_QOVR + abi::E_RLWAI => ErrorKind::Interrupted, // Some("forced release from waiting"), + abi::E_TMOUT => ErrorKind::TimedOut, // Some("polling failure or timeout"), + // abi::E_DLT + // abi::E_CLS + // abi::E_WBLK + // abi::E_BOVR + + // The TOPPERS third generation kernels + abi::E_NORES => ErrorKind::OutOfMemory, // Some("insufficient system resources"), + // abi::E_RASTER + // abi::E_COMM + _ => ErrorKind::Uncategorized, + } +} + +/// Similar to `ItronError::err_if_negative(er).expect()` except that, while +/// panicking, it prints the message to `panic_output` and aborts the program +/// instead. This ensures the error message is not obscured by double +/// panicking. +/// +/// This is useful for diagnosing creation failures of synchronization +/// primitives that are used by `std`'s internal mechanisms. Such failures +/// are common when the system is mis-configured to provide a too-small pool for +/// kernel objects. +#[inline] +pub fn expect_success(er: abi::ER, msg: &&str) -> abi::ER { + match ItronError::err_if_negative(er) { + Ok(x) => x, + Err(e) => fail(e, msg), + } +} + +/// Similar to `ItronError::err_if_negative(er).expect()` but aborts instead. +/// +/// Use this where panicking is not allowed or the effect of the failure +/// would be persistent. +#[inline] +pub fn expect_success_aborting(er: abi::ER, msg: &&str) -> abi::ER { + match ItronError::err_if_negative(er) { + Ok(x) => x, + Err(e) => fail_aborting(e, msg), + } +} + +#[cold] +pub fn fail(e: impl fmt::Display, msg: &&str) -> ! { + if crate::thread::panicking() { + fail_aborting(e, msg) + } else { + panic!("{} failed: {}", *msg, e) + } +} + +#[cold] +pub fn fail_aborting(e: impl fmt::Display, msg: &&str) -> ! { + rtabort!("{} failed: {}", *msg, e) +} diff --git a/library/std/src/sys/itron/mutex.rs b/library/std/src/sys/itron/mutex.rs new file mode 100644 index 0000000000..e01f595ac5 --- /dev/null +++ b/library/std/src/sys/itron/mutex.rs @@ -0,0 +1,183 @@ +//! Mutex implementation backed by μITRON mutexes. Assumes `acre_mtx` and +//! `TA_INHERIT` are available. +use super::{ + abi, + error::{expect_success, expect_success_aborting, fail, ItronError}, + spin::SpinIdOnceCell, +}; +use crate::cell::UnsafeCell; + +pub struct Mutex { + /// The ID of the underlying mutex object + mtx: SpinIdOnceCell<()>, +} + +pub type MovableMutex = Mutex; + +/// Create a mutex object. This function never panics. +fn new_mtx() -> Result { + ItronError::err_if_negative(unsafe { + abi::acre_mtx(&abi::T_CMTX { + // Priority inheritance mutex + mtxatr: abi::TA_INHERIT, + // Unused + ceilpri: 0, + }) + }) +} + +impl Mutex { + pub const fn new() -> Mutex { + Mutex { mtx: SpinIdOnceCell::new() } + } + + pub unsafe fn init(&mut self) { + // Initialize `self.mtx` eagerly + let id = new_mtx().unwrap_or_else(|e| fail(e, &"acre_mtx")); + unsafe { self.mtx.set_unchecked((id, ())) }; + } + + /// Get the inner mutex's ID, which is lazily created. + fn raw(&self) -> abi::ID { + match self.mtx.get_or_try_init(|| new_mtx().map(|id| (id, ()))) { + Ok((id, ())) => id, + Err(e) => fail(e, &"acre_mtx"), + } + } + + pub unsafe fn lock(&self) { + let mtx = self.raw(); + expect_success(unsafe { abi::loc_mtx(mtx) }, &"loc_mtx"); + } + + pub unsafe fn unlock(&self) { + let mtx = unsafe { self.mtx.get_unchecked().0 }; + expect_success_aborting(unsafe { abi::unl_mtx(mtx) }, &"unl_mtx"); + } + + pub unsafe fn try_lock(&self) -> bool { + let mtx = self.raw(); + match unsafe { abi::ploc_mtx(mtx) } { + abi::E_TMOUT => false, + er => { + expect_success(er, &"ploc_mtx"); + true + } + } + } + + pub unsafe fn destroy(&self) { + if let Some(mtx) = self.mtx.get().map(|x| x.0) { + expect_success_aborting(unsafe { abi::del_mtx(mtx) }, &"del_mtx"); + } + } +} + +pub(super) struct MutexGuard<'a>(&'a Mutex); + +impl<'a> MutexGuard<'a> { + #[inline] + pub(super) fn lock(x: &'a Mutex) -> Self { + unsafe { x.lock() }; + Self(x) + } +} + +impl Drop for MutexGuard<'_> { + #[inline] + fn drop(&mut self) { + unsafe { self.0.unlock() }; + } +} + +// All empty stubs because this platform does not yet support threads, so lock +// acquisition always succeeds. +pub struct ReentrantMutex { + /// The ID of the underlying mutex object + mtx: abi::ID, + /// The lock count. + count: UnsafeCell, +} + +unsafe impl Send for ReentrantMutex {} +unsafe impl Sync for ReentrantMutex {} + +impl ReentrantMutex { + pub const unsafe fn uninitialized() -> ReentrantMutex { + ReentrantMutex { mtx: 0, count: UnsafeCell::new(0) } + } + + pub unsafe fn init(&mut self) { + self.mtx = expect_success( + unsafe { + abi::acre_mtx(&abi::T_CMTX { + // Priority inheritance mutex + mtxatr: abi::TA_INHERIT, + // Unused + ceilpri: 0, + }) + }, + &"acre_mtx", + ); + } + + pub unsafe fn lock(&self) { + match unsafe { abi::loc_mtx(self.mtx) } { + abi::E_OBJ => { + // Recursive lock + unsafe { + let count = &mut *self.count.get(); + if let Some(new_count) = count.checked_add(1) { + *count = new_count; + } else { + // counter overflow + rtabort!("lock count overflow"); + } + } + } + er => { + expect_success(er, &"loc_mtx"); + } + } + } + + pub unsafe fn unlock(&self) { + unsafe { + let count = &mut *self.count.get(); + if *count > 0 { + *count -= 1; + return; + } + } + + expect_success_aborting(unsafe { abi::unl_mtx(self.mtx) }, &"unl_mtx"); + } + + pub unsafe fn try_lock(&self) -> bool { + let er = unsafe { abi::ploc_mtx(self.mtx) }; + if er == abi::E_OBJ { + // Recursive lock + unsafe { + let count = &mut *self.count.get(); + if let Some(new_count) = count.checked_add(1) { + *count = new_count; + } else { + // counter overflow + rtabort!("lock count overflow"); + } + } + true + } else if er == abi::E_TMOUT { + // Locked by another thread + false + } else { + expect_success(er, &"ploc_mtx"); + // Top-level lock by the current thread + true + } + } + + pub unsafe fn destroy(&self) { + expect_success_aborting(unsafe { abi::del_mtx(self.mtx) }, &"del_mtx"); + } +} diff --git a/library/std/src/sys/itron/spin.rs b/library/std/src/sys/itron/spin.rs new file mode 100644 index 0000000000..d0149d1f03 --- /dev/null +++ b/library/std/src/sys/itron/spin.rs @@ -0,0 +1,164 @@ +use super::abi; +use crate::{ + cell::UnsafeCell, + convert::TryFrom, + mem::MaybeUninit, + sync::atomic::{AtomicBool, AtomicUsize, Ordering}, +}; + +/// A mutex implemented by `dis_dsp` (for intra-core synchronization) and a +/// spinlock (for inter-core synchronization). +pub struct SpinMutex { + locked: AtomicBool, + data: UnsafeCell, +} + +impl SpinMutex { + #[inline] + pub const fn new(x: T) -> Self { + Self { locked: AtomicBool::new(false), data: UnsafeCell::new(x) } + } + + /// Acquire a lock. + #[inline] + pub fn with_locked(&self, f: impl FnOnce(&mut T) -> R) -> R { + struct SpinMutexGuard<'a>(&'a AtomicBool); + + impl Drop for SpinMutexGuard<'_> { + #[inline] + fn drop(&mut self) { + self.0.store(false, Ordering::Release); + unsafe { abi::ena_dsp() }; + } + } + + let _guard; + if unsafe { abi::sns_dsp() } == 0 { + let er = unsafe { abi::dis_dsp() }; + debug_assert!(er >= 0); + + // Wait until the current processor acquires a lock. + while self.locked.swap(true, Ordering::Acquire) {} + + _guard = SpinMutexGuard(&self.locked); + } + + f(unsafe { &mut *self.data.get() }) + } +} + +/// `OnceCell<(abi::ID, T)>` implemented by `dis_dsp` (for intra-core +/// synchronization) and a spinlock (for inter-core synchronization). +/// +/// It's assumed that `0` is not a valid ID, and all kernel +/// object IDs fall into range `1..=usize::MAX`. +pub struct SpinIdOnceCell { + id: AtomicUsize, + spin: SpinMutex<()>, + extra: UnsafeCell>, +} + +const ID_UNINIT: usize = 0; + +impl SpinIdOnceCell { + #[inline] + pub const fn new() -> Self { + Self { + id: AtomicUsize::new(ID_UNINIT), + extra: UnsafeCell::new(MaybeUninit::uninit()), + spin: SpinMutex::new(()), + } + } + + #[inline] + pub fn get(&self) -> Option<(abi::ID, &T)> { + match self.id.load(Ordering::Acquire) { + ID_UNINIT => None, + id => Some((id as abi::ID, unsafe { (&*self.extra.get()).assume_init_ref() })), + } + } + + #[inline] + pub fn get_mut(&mut self) -> Option<(abi::ID, &mut T)> { + match *self.id.get_mut() { + ID_UNINIT => None, + id => Some((id as abi::ID, unsafe { (&mut *self.extra.get()).assume_init_mut() })), + } + } + + #[inline] + pub unsafe fn get_unchecked(&self) -> (abi::ID, &T) { + (self.id.load(Ordering::Acquire) as abi::ID, unsafe { + (&*self.extra.get()).assume_init_ref() + }) + } + + /// Assign the content without checking if it's already initialized or + /// being initialized. + pub unsafe fn set_unchecked(&self, (id, extra): (abi::ID, T)) { + debug_assert!(self.get().is_none()); + + // Assumption: A positive `abi::ID` fits in `usize`. + debug_assert!(id >= 0); + debug_assert!(usize::try_from(id).is_ok()); + let id = id as usize; + + unsafe { *self.extra.get() = MaybeUninit::new(extra) }; + self.id.store(id, Ordering::Release); + } + + /// Gets the contents of the cell, initializing it with `f` if + /// the cell was empty. If the cell was empty and `f` failed, an + /// error is returned. + /// + /// Warning: `f` must not perform a blocking operation, which + /// includes panicking. + #[inline] + pub fn get_or_try_init(&self, f: F) -> Result<(abi::ID, &T), E> + where + F: FnOnce() -> Result<(abi::ID, T), E>, + { + // Fast path + if let Some(x) = self.get() { + return Ok(x); + } + + self.initialize(f)?; + + debug_assert!(self.get().is_some()); + + // Safety: The inner value has been initialized + Ok(unsafe { self.get_unchecked() }) + } + + fn initialize(&self, f: F) -> Result<(), E> + where + F: FnOnce() -> Result<(abi::ID, T), E>, + { + self.spin.with_locked(|_| { + if self.id.load(Ordering::Relaxed) == ID_UNINIT { + let (initialized_id, initialized_extra) = f()?; + + // Assumption: A positive `abi::ID` fits in `usize`. + debug_assert!(initialized_id >= 0); + debug_assert!(usize::try_from(initialized_id).is_ok()); + let initialized_id = initialized_id as usize; + + // Store the initialized contents. Use the release ordering to + // make sure the write is visible to the callers of `get`. + unsafe { *self.extra.get() = MaybeUninit::new(initialized_extra) }; + self.id.store(initialized_id, Ordering::Release); + } + Ok(()) + }) + } +} + +impl Drop for SpinIdOnceCell { + #[inline] + fn drop(&mut self) { + if self.get_mut().is_some() { + unsafe { (&mut *self.extra.get()).assume_init_drop() }; + } + } +} diff --git a/library/std/src/sys/itron/task.rs b/library/std/src/sys/itron/task.rs new file mode 100644 index 0000000000..94beb50a25 --- /dev/null +++ b/library/std/src/sys/itron/task.rs @@ -0,0 +1,44 @@ +use super::{ + abi, + error::{fail, fail_aborting, ItronError}, +}; + +use crate::mem::MaybeUninit; + +/// Get the ID of the task in Running state. Panics on failure. +#[inline] +pub fn current_task_id() -> abi::ID { + try_current_task_id().unwrap_or_else(|e| fail(e, &"get_tid")) +} + +/// Get the ID of the task in Running state. Aborts on failure. +#[inline] +pub fn current_task_id_aborting() -> abi::ID { + try_current_task_id().unwrap_or_else(|e| fail_aborting(e, &"get_tid")) +} + +/// Get the ID of the task in Running state. +#[inline] +pub fn try_current_task_id() -> Result { + unsafe { + let mut out = MaybeUninit::uninit(); + ItronError::err_if_negative(abi::get_tid(out.as_mut_ptr()))?; + Ok(out.assume_init()) + } +} + +/// Get the specified task's priority. Panics on failure. +#[inline] +pub fn task_priority(task: abi::ID) -> abi::PRI { + try_task_priority(task).unwrap_or_else(|e| fail(e, &"get_pri")) +} + +/// Get the specified task's priority. +#[inline] +pub fn try_task_priority(task: abi::ID) -> Result { + unsafe { + let mut out = MaybeUninit::uninit(); + ItronError::err_if_negative(abi::get_pri(task, out.as_mut_ptr()))?; + Ok(out.assume_init()) + } +} diff --git a/library/std/src/sys/itron/thread.rs b/library/std/src/sys/itron/thread.rs new file mode 100644 index 0000000000..4feb9c5a6d --- /dev/null +++ b/library/std/src/sys/itron/thread.rs @@ -0,0 +1,352 @@ +//! Thread implementation backed by μITRON tasks. Assumes `acre_tsk` and +//! `exd_tsk` are available. +use super::{ + abi, + error::{expect_success, expect_success_aborting, ItronError}, + task, + time::dur2reltims, +}; +use crate::{ + cell::UnsafeCell, + convert::TryFrom, + ffi::CStr, + hint, io, + mem::ManuallyDrop, + sync::atomic::{AtomicUsize, Ordering}, + sys::thread_local_dtor::run_dtors, + time::Duration, +}; + +pub struct Thread { + inner: ManuallyDrop>, + + /// The ID of the underlying task. + task: abi::ID, +} + +/// State data shared between a parent thread and child thread. It's dropped on +/// a transition to one of the final states. +struct ThreadInner { + /// This field is used on thread creation to pass a closure from + /// `Thread::new` to the created task. + start: UnsafeCell>>, + + /// A state machine. Each transition is annotated with `[...]` in the + /// source code. + /// + /// ```text + /// + ///

: parent, : child, (?): don't-care + /// + /// DETACHED (-1) --------------------> EXITED (?) + /// finish/exd_tsk + /// ^ + /// | + /// |

detach + /// | + /// + /// INIT (0) -----------------------> FINISHED (-1) + /// finish + /// | | + /// |

join/slp_tsk |

join/del_tsk + /// | |

detach/del_tsk + /// v v + /// + /// JOINING JOINED (?) + /// (parent_tid) + /// ^ + /// \ / + /// \ finish/wup_tsk /

slp_tsk-complete/ter_tsk + /// \ / & del_tsk + /// \ / + /// '--> JOIN_FINALIZE ---' + /// (-1) + /// + lifecycle: AtomicUsize, +} + +// Safety: The only `!Sync` field, `ThreadInner::start`, is only touched by +// the task represented by `ThreadInner`. +unsafe impl Sync for ThreadInner {} + +const LIFECYCLE_INIT: usize = 0; +const LIFECYCLE_FINISHED: usize = usize::MAX; +const LIFECYCLE_DETACHED: usize = usize::MAX; +const LIFECYCLE_JOIN_FINALIZE: usize = usize::MAX; +const LIFECYCLE_DETACHED_OR_JOINED: usize = usize::MAX; +const LIFECYCLE_EXITED_OR_FINISHED_OR_JOIN_FINALIZE: usize = usize::MAX; +// there's no single value for `JOINING` + +pub const DEFAULT_MIN_STACK_SIZE: usize = 1024 * crate::mem::size_of::(); + +impl Thread { + /// # Safety + /// + /// See `thread::Builder::spawn_unchecked` for safety requirements. + pub unsafe fn new(stack: usize, p: Box) -> io::Result { + // Inherit the current task's priority + let current_task = task::try_current_task_id().map_err(|e| e.as_io_error())?; + let priority = task::try_task_priority(current_task).map_err(|e| e.as_io_error())?; + + let inner = Box::new(ThreadInner { + start: UnsafeCell::new(ManuallyDrop::new(p)), + lifecycle: AtomicUsize::new(LIFECYCLE_INIT), + }); + + unsafe extern "C" fn trampoline(exinf: isize) { + // Safety: `ThreadInner` is alive at this point + let inner = unsafe { &*(exinf as *const ThreadInner) }; + + // Safety: Since `trampoline` is called only once for each + // `ThreadInner` and only `trampoline` touches `start`, + // `start` contains contents and is safe to mutably borrow. + let p = unsafe { ManuallyDrop::take(&mut *inner.start.get()) }; + p(); + + // Fix the current thread's state just in case, so that the + // destructors won't abort + // Safety: Not really unsafe + let _ = unsafe { abi::unl_cpu() }; + let _ = unsafe { abi::ena_dsp() }; + + // Run TLS destructors now because they are not + // called automatically for terminated tasks. + unsafe { run_dtors() }; + + let old_lifecycle = inner + .lifecycle + .swap(LIFECYCLE_EXITED_OR_FINISHED_OR_JOIN_FINALIZE, Ordering::Release); + + match old_lifecycle { + LIFECYCLE_DETACHED => { + // [DETACHED → EXITED] + // No one will ever join, so we'll ask the collector task to + // delete the task. + + // In this case, `inner`'s ownership has been moved to us, + // And we are responsible for dropping it. The acquire + // ordering is not necessary because the parent thread made + // no memory acccess needing synchronization since the call + // to `acre_tsk`. + // Safety: See above. + let _ = unsafe { Box::from_raw(inner as *const _ as *mut ThreadInner) }; + + // Safety: There are no pinned references to the stack + unsafe { terminate_and_delete_current_task() }; + } + LIFECYCLE_INIT => { + // [INIT → FINISHED] + // The parent hasn't decided whether to join or detach this + // thread yet. Whichever option the parent chooses, + // it'll have to delete this task. + // Since the parent might drop `*inner` as soon as it sees + // `FINISHED`, the release ordering must be used in the + // above `swap` call. + } + parent_tid => { + // Since the parent might drop `*inner` and terminate us as + // soon as it sees `JOIN_FINALIZE`, the release ordering + // must be used in the above `swap` call. + + // [JOINING → JOIN_FINALIZE] + // Wake up the parent task. + expect_success( + unsafe { + let mut er = abi::wup_tsk(parent_tid as _); + if er == abi::E_QOVR { + // `E_QOVR` indicates there's already + // a parking token + er = abi::E_OK; + } + er + }, + &"wup_tsk", + ); + } + } + } + + let inner_ptr = (&*inner) as *const ThreadInner; + + let new_task = ItronError::err_if_negative(unsafe { + abi::acre_tsk(&abi::T_CTSK { + // Activate this task immediately + tskatr: abi::TA_ACT, + exinf: inner_ptr as abi::EXINF, + // The entry point + task: Some(trampoline), + itskpri: priority, + stksz: stack, + // Let the kernel allocate the stack, + stk: crate::ptr::null_mut(), + }) + }) + .map_err(|e| e.as_io_error())?; + + Ok(Self { inner: ManuallyDrop::new(inner), task: new_task }) + } + + pub fn yield_now() { + expect_success(unsafe { abi::rot_rdq(abi::TPRI_SELF) }, &"rot_rdq"); + } + + pub fn set_name(_name: &CStr) { + // nope + } + + pub fn sleep(dur: Duration) { + for timeout in dur2reltims(dur) { + expect_success(unsafe { abi::dly_tsk(timeout) }, &"dly_tsk"); + } + } + + pub fn join(mut self) { + let inner = &*self.inner; + // Get the current task ID. Panicking here would cause a resource leak, + // so just abort on failure. + let current_task = task::current_task_id_aborting(); + debug_assert!(usize::try_from(current_task).is_ok()); + debug_assert_ne!(current_task as usize, LIFECYCLE_INIT); + debug_assert_ne!(current_task as usize, LIFECYCLE_DETACHED); + + let current_task = current_task as usize; + + match inner.lifecycle.swap(current_task, Ordering::Acquire) { + LIFECYCLE_INIT => { + // [INIT → JOINING] + // The child task will transition the state to `JOIN_FINALIZE` + // and wake us up. + loop { + expect_success_aborting(unsafe { abi::slp_tsk() }, &"slp_tsk"); + // To synchronize with the child task's memory accesses to + // `inner` up to the point of the assignment of + // `JOIN_FINALIZE`, `Ordering::Acquire` must be used for the + // `load`. + if inner.lifecycle.load(Ordering::Acquire) == LIFECYCLE_JOIN_FINALIZE { + break; + } + } + + // [JOIN_FINALIZE → JOINED] + } + LIFECYCLE_FINISHED => { + // [FINISHED → JOINED] + // To synchronize with the child task's memory accesses to + // `inner` up to the point of the assignment of `FINISHED`, + // `Ordering::Acquire` must be used for the above `swap` call`. + } + _ => unsafe { hint::unreachable_unchecked() }, + } + + // Terminate and delete the task + // Safety: `self.task` still represents a task we own (because this + // method or `detach_inner` is called only once for each + // `Thread`). The task indicated that it's safe to delete by + // entering the `FINISHED` or `JOIN_FINALIZE` state. + unsafe { terminate_and_delete_task(self.task) }; + + // In either case, we are responsible for dropping `inner`. + // Safety: The contents of `self.inner` will not be accessed hereafter + let _inner = unsafe { ManuallyDrop::take(&mut self.inner) }; + + // Skip the destructor (because it would attempt to detach the thread) + crate::mem::forget(self); + } +} + +impl Drop for Thread { + fn drop(&mut self) { + // Detach the thread. + match self.inner.lifecycle.swap(LIFECYCLE_DETACHED_OR_JOINED, Ordering::Acquire) { + LIFECYCLE_INIT => { + // [INIT → DETACHED] + // When the time comes, the child will figure out that no + // one will ever join it. + // The ownership of `self.inner` is moved to the child thread. + // However, the release ordering is not necessary because we + // made no memory acccess needing synchronization since the call + // to `acre_tsk`. + } + LIFECYCLE_FINISHED => { + // [FINISHED → JOINED] + // The task has already decided that we should delete the task. + // To synchronize with the child task's memory accesses to + // `inner` up to the point of the assignment of `FINISHED`, + // the acquire ordering is required for the above `swap` call. + + // Terminate and delete the task + // Safety: `self.task` still represents a task we own (because + // this method or `join_inner` is called only once for + // each `Thread`). The task indicated that it's safe to + // delete by entering the `FINISHED` state. + unsafe { terminate_and_delete_task(self.task) }; + + // Wwe are responsible for dropping `inner`. + // Safety: The contents of `self.inner` will not be accessed + // hereafter + unsafe { ManuallyDrop::drop(&mut self.inner) }; + } + _ => unsafe { hint::unreachable_unchecked() }, + } + } +} + +pub mod guard { + pub type Guard = !; + pub unsafe fn current() -> Option { + None + } + pub unsafe fn init() -> Option { + None + } +} + +/// Terminate and delete the specified task. +/// +/// This function will abort if `deleted_task` refers to the calling task. +/// +/// It is assumed that the specified task is solely managed by the caller - +/// i.e., other threads must not "resuscitate" the specified task or delete it +/// prematurely while this function is still in progress. It is allowed for the +/// specified task to exit by its own. +/// +/// # Safety +/// +/// The task must be safe to terminate. This is in general not true +/// because there might be pinned references to the task's stack. +unsafe fn terminate_and_delete_task(deleted_task: abi::ID) { + // Terminate the task + // Safety: Upheld by the caller + match unsafe { abi::ter_tsk(deleted_task) } { + // Indicates the task is already dormant, ignore it + abi::E_OBJ => {} + er => { + expect_success_aborting(er, &"ter_tsk"); + } + } + + // Delete the task + // Safety: Upheld by the caller + expect_success_aborting(unsafe { abi::del_tsk(deleted_task) }, &"del_tsk"); +} + +/// Terminate and delete the calling task. +/// +/// Atomicity is not required - i.e., it can be assumed that other threads won't +/// `ter_tsk` the calling task while this function is still in progress. (This +/// property makes it easy to implement this operation on μITRON-derived kernels +/// that don't support `exd_tsk`.) +/// +/// # Safety +/// +/// The task must be safe to terminate. This is in general not true +/// because there might be pinned references to the task's stack. +unsafe fn terminate_and_delete_current_task() -> ! { + expect_success_aborting(unsafe { abi::exd_tsk() }, &"exd_tsk"); + // Safety: `exd_tsk` never returns on success + unsafe { crate::hint::unreachable_unchecked() }; +} + +pub fn available_concurrency() -> io::Result { + super::unsupported() +} diff --git a/library/std/src/sys/itron/time.rs b/library/std/src/sys/itron/time.rs new file mode 100644 index 0000000000..6a992ad1d3 --- /dev/null +++ b/library/std/src/sys/itron/time.rs @@ -0,0 +1,123 @@ +use super::{abi, error::expect_success}; +use crate::{convert::TryInto, mem::MaybeUninit, time::Duration}; + +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] +pub struct Instant(abi::SYSTIM); + +impl Instant { + pub fn now() -> Instant { + // Safety: The provided pointer is valid + unsafe { + let mut out = MaybeUninit::uninit(); + expect_success(abi::get_tim(out.as_mut_ptr()), &"get_tim"); + Instant(out.assume_init()) + } + } + + pub const fn zero() -> Instant { + Instant(0) + } + + pub fn actually_monotonic() -> bool { + // There are ways to change the system time + false + } + + pub fn checked_sub_instant(&self, other: &Instant) -> Option { + self.0.checked_sub(other.0).map(|ticks| { + // `SYSTIM` is measured in microseconds + Duration::from_micros(ticks) + }) + } + + pub fn checked_add_duration(&self, other: &Duration) -> Option { + // `SYSTIM` is measured in microseconds + let ticks = other.as_micros(); + + Some(Instant(self.0.checked_add(ticks.try_into().ok()?)?)) + } + + pub fn checked_sub_duration(&self, other: &Duration) -> Option { + // `SYSTIM` is measured in microseconds + let ticks = other.as_micros(); + + Some(Instant(self.0.checked_sub(ticks.try_into().ok()?)?)) + } +} + +/// Split `Duration` into zero or more `RELTIM`s. +#[inline] +pub fn dur2reltims(dur: Duration) -> impl Iterator { + // `RELTIM` is microseconds + let mut ticks = dur.as_micros(); + + crate::iter::from_fn(move || { + if ticks == 0 { + None + } else if ticks <= abi::TMAX_RELTIM as u128 { + Some(crate::mem::replace(&mut ticks, 0) as abi::RELTIM) + } else { + ticks -= abi::TMAX_RELTIM as u128; + Some(abi::TMAX_RELTIM) + } + }) +} + +/// Split `Duration` into one or more `TMO`s. +#[inline] +fn dur2tmos(dur: Duration) -> impl Iterator { + // `TMO` is microseconds + let mut ticks = dur.as_micros(); + let mut end = false; + + crate::iter::from_fn(move || { + if end { + None + } else if ticks <= abi::TMAX_RELTIM as u128 { + end = true; + Some(crate::mem::replace(&mut ticks, 0) as abi::TMO) + } else { + ticks -= abi::TMAX_RELTIM as u128; + Some(abi::TMAX_RELTIM) + } + }) +} + +/// Split `Duration` into one or more API calls with timeout. +#[inline] +pub fn with_tmos(dur: Duration, mut f: impl FnMut(abi::TMO) -> abi::ER) -> abi::ER { + let mut er = abi::E_TMOUT; + for tmo in dur2tmos(dur) { + er = f(tmo); + if er != abi::E_TMOUT { + break; + } + } + er +} + +/// Split `Duration` into one or more API calls with timeout. This function can +/// handle spurious wakeups. +#[inline] +pub fn with_tmos_strong(dur: Duration, mut f: impl FnMut(abi::TMO) -> abi::ER) -> abi::ER { + // `TMO` and `SYSTIM` are microseconds. + // Clamp at `SYSTIM::MAX` for performance reasons. This shouldn't cause + // a problem in practice. (`u64::MAX` μs ≈ 584942 years) + let ticks = dur.as_micros().min(abi::SYSTIM::MAX as u128) as abi::SYSTIM; + + let start = Instant::now().0; + let mut elapsed = 0; + let mut er = abi::E_TMOUT; + while elapsed <= ticks { + er = f(elapsed.min(abi::TMAX_RELTIM as abi::SYSTIM) as abi::TMO); + if er != abi::E_TMOUT { + break; + } + elapsed = Instant::now().0.wrapping_sub(start); + } + + er +} + +#[cfg(test)] +mod tests; diff --git a/library/std/src/sys/itron/time/tests.rs b/library/std/src/sys/itron/time/tests.rs new file mode 100644 index 0000000000..d14035d9da --- /dev/null +++ b/library/std/src/sys/itron/time/tests.rs @@ -0,0 +1,33 @@ +use super::*; + +fn reltim2dur(t: u64) -> Duration { + Duration::from_micros(t) +} + +#[test] +fn test_dur2reltims() { + assert_eq!(dur2reltims(reltim2dur(0)).collect::>(), vec![]); + assert_eq!(dur2reltims(reltim2dur(42)).collect::>(), vec![42]); + assert_eq!( + dur2reltims(reltim2dur(abi::TMAX_RELTIM as u64)).collect::>(), + vec![abi::TMAX_RELTIM] + ); + assert_eq!( + dur2reltims(reltim2dur(abi::TMAX_RELTIM as u64 + 10000)).collect::>(), + vec![abi::TMAX_RELTIM, 10000] + ); +} + +#[test] +fn test_dur2tmos() { + assert_eq!(dur2tmos(reltim2dur(0)).collect::>(), vec![0]); + assert_eq!(dur2tmos(reltim2dur(42)).collect::>(), vec![42]); + assert_eq!( + dur2tmos(reltim2dur(abi::TMAX_RELTIM as u64)).collect::>(), + vec![abi::TMAX_RELTIM] + ); + assert_eq!( + dur2tmos(reltim2dur(abi::TMAX_RELTIM as u64 + 10000)).collect::>(), + vec![abi::TMAX_RELTIM, 10000] + ); +} diff --git a/library/std/src/sys/mod.rs b/library/std/src/sys/mod.rs index f813587b1b..8b8be6ebc2 100644 --- a/library/std/src/sys/mod.rs +++ b/library/std/src/sys/mod.rs @@ -31,6 +31,9 @@ cfg_if::cfg_if! { } else if #[cfg(windows)] { mod windows; pub use self::windows::*; + } else if #[cfg(target_os = "solid_asp3")] { + mod solid; + pub use self::solid::*; } else if #[cfg(target_os = "hermit")] { mod hermit; pub use self::hermit::*; diff --git a/library/std/src/sys/sgx/thread.rs b/library/std/src/sys/sgx/thread.rs index cbb8ba9640..d745a61961 100644 --- a/library/std/src/sys/sgx/thread.rs +++ b/library/std/src/sys/sgx/thread.rs @@ -137,7 +137,7 @@ impl Thread { } } -pub fn available_concurrency() -> io::Result { +pub fn available_parallelism() -> io::Result { unsupported() } diff --git a/library/std/src/sys/solid/abi/fs.rs b/library/std/src/sys/solid/abi/fs.rs new file mode 100644 index 0000000000..32800bd9a9 --- /dev/null +++ b/library/std/src/sys/solid/abi/fs.rs @@ -0,0 +1,53 @@ +//! `solid_fs.h` +use crate::os::raw::{c_char, c_int, c_uchar}; +pub use libc::{ + blksize_t, dev_t, ino_t, off_t, stat, time_t, O_APPEND, O_CREAT, O_EXCL, O_RDONLY, O_RDWR, + O_TRUNC, O_WRONLY, SEEK_CUR, SEEK_END, SEEK_SET, S_IEXEC, S_IFBLK, S_IFCHR, S_IFDIR, S_IFIFO, + S_IFMT, S_IFREG, S_IREAD, S_IWRITE, +}; + +pub const O_ACCMODE: c_int = 0x3; + +pub const SOLID_MAX_PATH: usize = 256; + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct dirent { + pub d_ino: ino_t, + pub d_type: c_uchar, + pub d_name: [c_char; 256usize], +} + +pub const DT_UNKNOWN: c_uchar = 0; +pub const DT_FIFO: c_uchar = 1; +pub const DT_CHR: c_uchar = 2; +pub const DT_DIR: c_uchar = 4; +pub const DT_BLK: c_uchar = 6; +pub const DT_REG: c_uchar = 8; +pub const DT_LNK: c_uchar = 10; +pub const DT_SOCK: c_uchar = 12; +pub const DT_WHT: c_uchar = 14; + +pub type S_DIR = c_int; + +extern "C" { + pub fn SOLID_FS_Open(fd: *mut c_int, path: *const c_char, mode: c_int) -> c_int; + pub fn SOLID_FS_Close(fd: c_int) -> c_int; + pub fn SOLID_FS_Read(fd: c_int, buf: *mut u8, size: usize, result: *mut usize) -> c_int; + pub fn SOLID_FS_Write(fd: c_int, buf: *const u8, size: usize, result: *mut usize) -> c_int; + pub fn SOLID_FS_Lseek(fd: c_int, offset: off_t, whence: c_int) -> c_int; + pub fn SOLID_FS_Sync(fd: c_int) -> c_int; + pub fn SOLID_FS_Ftell(fd: c_int, result: *mut off_t) -> c_int; + pub fn SOLID_FS_Feof(fd: c_int, result: *mut c_int) -> c_int; + pub fn SOLID_FS_Fsize(fd: c_int, result: *mut usize) -> c_int; + pub fn SOLID_FS_Truncate(path: *const c_char, size: off_t) -> c_int; + pub fn SOLID_FS_OpenDir(path: *const c_char, pDir: *mut S_DIR) -> c_int; + pub fn SOLID_FS_CloseDir(dir: S_DIR) -> c_int; + pub fn SOLID_FS_ReadDir(dir: S_DIR, dirp: *mut dirent) -> c_int; + pub fn SOLID_FS_Stat(path: *const c_char, buf: *mut stat) -> c_int; + pub fn SOLID_FS_Unlink(path: *const c_char) -> c_int; + pub fn SOLID_FS_Rename(oldpath: *const c_char, newpath: *const c_char) -> c_int; + pub fn SOLID_FS_Chmod(path: *const c_char, mode: c_int) -> c_int; + pub fn SOLID_FS_Utime(path: *const c_char, time: time_t) -> c_int; + pub fn SOLID_FS_Mkdir(path: *const c_char) -> c_int; +} diff --git a/library/std/src/sys/solid/abi/mod.rs b/library/std/src/sys/solid/abi/mod.rs new file mode 100644 index 0000000000..3526440fb8 --- /dev/null +++ b/library/std/src/sys/solid/abi/mod.rs @@ -0,0 +1,92 @@ +use crate::os::raw::c_int; + +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 () { + #[cfg(target_arch = "arm")] + () => asm!("bkpt #{}", const SOLID_BP_PROGRAM_EXITED, in("r0") tid), + #[cfg(target_arch = "aarch64")] + () => asm!("hlt #{}", const SOLID_BP_PROGRAM_EXITED, in("x0") tid), + } + } +} + +#[inline(always)] +pub fn breakpoint_abort() { + unsafe { + match () { + #[cfg(target_arch = "arm")] + () => asm!("bkpt #{}", const SOLID_BP_CSABORT), + #[cfg(target_arch = "aarch64")] + () => asm!("hlt #{}", const SOLID_BP_CSABORT), + } + } +} + +// `solid_types.h` +pub use super::itron::abi::{ER, ER_ID, E_TMOUT, ID}; + +pub const SOLID_ERR_NOTFOUND: ER = -1000; +pub const SOLID_ERR_NOTSUPPORTED: ER = -1001; +pub const SOLID_ERR_EBADF: ER = -1002; +pub const SOLID_ERR_INVALIDCONTENT: ER = -1003; +pub const SOLID_ERR_NOTUSED: ER = -1004; +pub const SOLID_ERR_ALREADYUSED: ER = -1005; +pub const SOLID_ERR_OUTOFBOUND: ER = -1006; +pub const SOLID_ERR_BADSEQUENCE: ER = -1007; +pub const SOLID_ERR_UNKNOWNDEVICE: ER = -1008; +pub const SOLID_ERR_BUSY: ER = -1009; +pub const SOLID_ERR_TIMEOUT: ER = -1010; +pub const SOLID_ERR_INVALIDACCESS: ER = -1011; +pub const SOLID_ERR_NOTREADY: ER = -1012; + +// `solid_rtc.h` +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct SOLID_RTC_TIME { + 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, +} + +extern "C" { + pub fn SOLID_RTC_ReadTime(time: *mut SOLID_RTC_TIME) -> c_int; +} + +// `solid_log.h` +extern "C" { + pub fn SOLID_LOG_write(s: *const u8, l: usize); +} + +// `solid_mem.h` +extern "C" { + pub fn SOLID_TLS_AddDestructor(id: i32, dtor: unsafe extern "C" fn(*mut u8)); +} + +// `solid_rng.h` +extern "C" { + pub fn SOLID_RNG_SampleRandomBytes(buffer: *mut u8, length: usize) -> c_int; +} + +// `rwlock.h` +extern "C" { + pub fn rwl_loc_rdl(id: ID) -> ER; + pub fn rwl_loc_wrl(id: ID) -> ER; + pub fn rwl_ploc_rdl(id: ID) -> ER; + pub fn rwl_ploc_wrl(id: ID) -> ER; + pub fn rwl_unl_rwl(id: ID) -> ER; + pub fn rwl_acre_rwl() -> ER_ID; + pub fn rwl_del_rwl(id: ID) -> ER; +} diff --git a/library/std/src/sys/solid/abi/sockets.rs b/library/std/src/sys/solid/abi/sockets.rs new file mode 100644 index 0000000000..7c21d0dd25 --- /dev/null +++ b/library/std/src/sys/solid/abi/sockets.rs @@ -0,0 +1,274 @@ +use crate::os::raw::{c_char, c_uint, c_void}; +pub use libc::{c_int, c_long, size_t, ssize_t, suseconds_t, time_t, timeval}; + +pub const SOLID_NET_ERR_BASE: c_int = -2000; +pub const EINPROGRESS: c_int = SOLID_NET_ERR_BASE - libc::EINPROGRESS; + +pub const AF_INET6: i32 = 10; +pub const AF_INET: i32 = 2; +pub const IPPROTO_IP: i32 = 0; +pub const IPPROTO_IPV6: i32 = 41; +pub const IPPROTO_TCP: i32 = 6; +pub const IPV6_ADD_MEMBERSHIP: i32 = 12; +pub const IPV6_DROP_MEMBERSHIP: i32 = 13; +pub const IPV6_MULTICAST_LOOP: i32 = 19; +pub const IPV6_V6ONLY: i32 = 27; +pub const IP_TTL: i32 = 2; +pub const IP_MULTICAST_TTL: i32 = 5; +pub const IP_MULTICAST_LOOP: i32 = 7; +pub const IP_ADD_MEMBERSHIP: i32 = 3; +pub const IP_DROP_MEMBERSHIP: i32 = 4; +pub const SHUT_RD: i32 = 0; +pub const SHUT_RDWR: i32 = 2; +pub const SHUT_WR: i32 = 1; +pub const SOCK_DGRAM: i32 = 2; +pub const SOCK_STREAM: i32 = 1; +pub const SOL_SOCKET: i32 = 4095; +pub const SO_BROADCAST: i32 = 32; +pub const SO_ERROR: i32 = 4103; +pub const SO_RCVTIMEO: i32 = 4102; +pub const SO_REUSEADDR: i32 = 4; +pub const SO_SNDTIMEO: i32 = 4101; +pub const SO_LINGER: i32 = 128; +pub const TCP_NODELAY: i32 = 1; +pub const MSG_PEEK: c_int = 1; +pub const FIONBIO: c_long = 0x8008667eu32 as c_long; +pub const EAI_NONAME: i32 = -2200; +pub const EAI_SERVICE: i32 = -2201; +pub const EAI_FAIL: i32 = -2202; +pub const EAI_MEMORY: i32 = -2203; +pub const EAI_FAMILY: i32 = -2204; + +pub type sa_family_t = u8; +pub type socklen_t = u32; +pub type in_addr_t = u32; +pub type in_port_t = u16; + +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct in_addr { + pub s_addr: in_addr_t, +} + +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct in6_addr { + pub s6_addr: [u8; 16], +} + +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct ip_mreq { + pub imr_multiaddr: in_addr, + pub imr_interface: in_addr, +} + +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct ipv6_mreq { + pub ipv6mr_multiaddr: in6_addr, + pub ipv6mr_interface: c_uint, +} + +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct msghdr { + pub msg_name: *mut c_void, + pub msg_namelen: socklen_t, + pub msg_iov: *mut iovec, + pub msg_iovlen: c_int, + pub msg_control: *mut c_void, + pub msg_controllen: socklen_t, + pub msg_flags: c_int, +} + +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct sockaddr { + pub sa_len: u8, + pub sa_family: sa_family_t, + pub sa_data: [c_char; 14usize], +} + +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct sockaddr_in { + pub sin_len: u8, + pub sin_family: sa_family_t, + pub sin_port: in_port_t, + pub sin_addr: in_addr, + pub sin_zero: [c_char; 8usize], +} + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct sockaddr_in6 { + pub sin6_len: u8, + pub sin6_family: sa_family_t, + pub sin6_port: in_port_t, + pub sin6_flowinfo: u32, + pub sin6_addr: in6_addr, + pub sin6_scope_id: u32, +} + +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct sockaddr_storage { + pub s2_len: u8, + pub ss_family: sa_family_t, + pub s2_data1: [c_char; 2usize], + pub s2_data2: [u32; 3usize], +} + +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct addrinfo { + pub ai_flags: c_int, + pub ai_family: c_int, + pub ai_socktype: c_int, + pub ai_protocol: c_int, + pub ai_addrlen: socklen_t, + pub ai_addr: *mut sockaddr, + pub ai_canonname: *mut c_char, + pub ai_next: *mut addrinfo, +} + +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct linger { + pub l_onoff: c_int, + pub l_linger: c_int, +} + +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct iovec { + pub iov_base: *mut c_void, + pub iov_len: usize, +} + +/// This value can be chosen by an application +pub const SOLID_NET_FD_SETSIZE: usize = 1; + +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct fd_set { + pub num_fds: usize, + pub fds: [c_int; SOLID_NET_FD_SETSIZE], +} + +extern "C" { + #[link_name = "SOLID_NET_StrError"] + pub fn strerror(errnum: c_int) -> *const c_char; + + pub fn SOLID_NET_GetLastError() -> c_int; + + #[link_name = "SOLID_NET_Accept"] + pub fn accept(s: c_int, addr: *mut sockaddr, addrlen: *mut socklen_t) -> c_int; + + #[link_name = "SOLID_NET_Bind"] + pub fn bind(s: c_int, name: *const sockaddr, namelen: socklen_t) -> c_int; + + #[link_name = "SOLID_NET_Connect"] + pub fn connect(s: c_int, name: *const sockaddr, namelen: socklen_t) -> c_int; + + #[link_name = "SOLID_NET_Close"] + pub fn close(s: c_int) -> c_int; + + #[link_name = "SOLID_NET_GetPeerName"] + pub fn getpeername(s: c_int, name: *mut sockaddr, namelen: *mut socklen_t) -> c_int; + + #[link_name = "SOLID_NET_GetSockName"] + pub fn getsockname(s: c_int, name: *mut sockaddr, namelen: *mut socklen_t) -> c_int; + + #[link_name = "SOLID_NET_GetSockOpt"] + pub fn getsockopt( + s: c_int, + level: c_int, + optname: c_int, + optval: *mut c_void, + optlen: *mut socklen_t, + ) -> c_int; + + #[link_name = "SOLID_NET_SetSockOpt"] + pub fn setsockopt( + s: c_int, + level: c_int, + optname: c_int, + optval: *const c_void, + optlen: socklen_t, + ) -> c_int; + + #[link_name = "SOLID_NET_Ioctl"] + pub fn ioctl(s: c_int, cmd: c_long, argp: *mut c_void) -> c_int; + + #[link_name = "SOLID_NET_Listen"] + pub fn listen(s: c_int, backlog: c_int) -> c_int; + + #[link_name = "SOLID_NET_Recv"] + pub fn recv(s: c_int, mem: *mut c_void, len: size_t, flags: c_int) -> ssize_t; + + #[link_name = "SOLID_NET_Read"] + pub fn read(s: c_int, mem: *mut c_void, len: size_t) -> ssize_t; + + #[link_name = "SOLID_NET_Readv"] + pub fn readv(s: c_int, bufs: *const iovec, bufcnt: c_int) -> ssize_t; + + #[link_name = "SOLID_NET_RecvFrom"] + pub fn recvfrom( + s: c_int, + mem: *mut c_void, + len: size_t, + flags: c_int, + from: *mut sockaddr, + fromlen: *mut socklen_t, + ) -> ssize_t; + + #[link_name = "SOLID_NET_Send"] + pub fn send(s: c_int, mem: *const c_void, len: size_t, flags: c_int) -> ssize_t; + + #[link_name = "SOLID_NET_SendMsg"] + pub fn sendmsg(s: c_int, message: *const msghdr, flags: c_int) -> ssize_t; + + #[link_name = "SOLID_NET_SendTo"] + pub fn sendto( + s: c_int, + mem: *const c_void, + len: size_t, + flags: c_int, + to: *const sockaddr, + tolen: socklen_t, + ) -> ssize_t; + + #[link_name = "SOLID_NET_Shutdown"] + pub fn shutdown(s: c_int, how: c_int) -> c_int; + + #[link_name = "SOLID_NET_Socket"] + pub fn socket(domain: c_int, type_: c_int, protocol: c_int) -> c_int; + + #[link_name = "SOLID_NET_Write"] + pub fn write(s: c_int, mem: *const c_void, len: size_t) -> ssize_t; + + #[link_name = "SOLID_NET_Writev"] + pub fn writev(s: c_int, bufs: *const iovec, bufcnt: c_int) -> ssize_t; + + #[link_name = "SOLID_NET_FreeAddrInfo"] + pub fn freeaddrinfo(ai: *mut addrinfo); + + #[link_name = "SOLID_NET_GetAddrInfo"] + pub fn getaddrinfo( + nodename: *const c_char, + servname: *const c_char, + hints: *const addrinfo, + res: *mut *mut addrinfo, + ) -> c_int; + + #[link_name = "SOLID_NET_Select"] + pub fn select( + maxfdp1: c_int, + readset: *mut fd_set, + writeset: *mut fd_set, + exceptset: *mut fd_set, + timeout: *mut timeval, + ) -> c_int; +} diff --git a/library/std/src/sys/solid/alloc.rs b/library/std/src/sys/solid/alloc.rs new file mode 100644 index 0000000000..d013bd8761 --- /dev/null +++ b/library/std/src/sys/solid/alloc.rs @@ -0,0 +1,32 @@ +use crate::{ + alloc::{GlobalAlloc, Layout, System}, + sys::common::alloc::{realloc_fallback, MIN_ALIGN}, +}; + +#[stable(feature = "alloc_system_type", since = "1.28.0")] +unsafe impl GlobalAlloc for System { + #[inline] + unsafe fn alloc(&self, layout: Layout) -> *mut u8 { + if layout.align() <= MIN_ALIGN && layout.align() <= layout.size() { + unsafe { libc::malloc(layout.size()) as *mut u8 } + } else { + unsafe { libc::memalign(layout.align(), layout.size()) as *mut u8 } + } + } + + #[inline] + unsafe fn dealloc(&self, ptr: *mut u8, _layout: Layout) { + unsafe { libc::free(ptr as *mut libc::c_void) } + } + + #[inline] + unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 { + unsafe { + if layout.align() <= MIN_ALIGN && layout.align() <= new_size { + libc::realloc(ptr as *mut libc::c_void, new_size) as *mut u8 + } else { + realloc_fallback(self, ptr, layout, new_size) + } + } + } +} diff --git a/library/std/src/sys/solid/env.rs b/library/std/src/sys/solid/env.rs new file mode 100644 index 0000000000..6855c113b2 --- /dev/null +++ b/library/std/src/sys/solid/env.rs @@ -0,0 +1,9 @@ +pub mod os { + pub const FAMILY: &str = "itron"; + pub const OS: &str = "solid"; + pub const DLL_PREFIX: &str = ""; + pub const DLL_SUFFIX: &str = ".so"; + pub const DLL_EXTENSION: &str = "so"; + pub const EXE_SUFFIX: &str = ""; + pub const EXE_EXTENSION: &str = ""; +} diff --git a/library/std/src/sys/solid/error.rs b/library/std/src/sys/solid/error.rs new file mode 100644 index 0000000000..547b4f3a98 --- /dev/null +++ b/library/std/src/sys/solid/error.rs @@ -0,0 +1,55 @@ +use super::{abi, itron, net}; +use crate::io::ErrorKind; + +pub use self::itron::error::{expect_success, ItronError as SolidError}; + +/// Describe the specified SOLID error code. Returns `None` if it's an +/// undefined error code. +/// +/// The SOLID error codes are a superset of μITRON error codes. +pub fn error_name(er: abi::ER) -> Option<&'static str> { + match er { + // Success + er if er >= 0 => None, + er if er < abi::sockets::SOLID_NET_ERR_BASE => net::error_name(er), + + abi::SOLID_ERR_NOTFOUND => Some("not found"), + abi::SOLID_ERR_NOTSUPPORTED => Some("not supported"), + abi::SOLID_ERR_EBADF => Some("bad flags"), + abi::SOLID_ERR_INVALIDCONTENT => Some("invalid content"), + abi::SOLID_ERR_NOTUSED => Some("not used"), + abi::SOLID_ERR_ALREADYUSED => Some("already used"), + abi::SOLID_ERR_OUTOFBOUND => Some("out of bounds"), + abi::SOLID_ERR_BADSEQUENCE => Some("bad sequence"), + abi::SOLID_ERR_UNKNOWNDEVICE => Some("unknown device"), + abi::SOLID_ERR_BUSY => Some("busy"), + abi::SOLID_ERR_TIMEOUT => Some("operation timed out"), + abi::SOLID_ERR_INVALIDACCESS => Some("invalid access"), + abi::SOLID_ERR_NOTREADY => Some("not ready"), + + _ => itron::error::error_name(er), + } +} + +pub fn decode_error_kind(er: abi::ER) -> ErrorKind { + match er { + // Success + er if er >= 0 => ErrorKind::Uncategorized, + er if er < abi::sockets::SOLID_NET_ERR_BASE => net::decode_error_kind(er), + + abi::SOLID_ERR_NOTFOUND => ErrorKind::NotFound, + abi::SOLID_ERR_NOTSUPPORTED => ErrorKind::Unsupported, + abi::SOLID_ERR_EBADF => ErrorKind::InvalidInput, + abi::SOLID_ERR_INVALIDCONTENT => ErrorKind::InvalidData, + // abi::SOLID_ERR_NOTUSED + // abi::SOLID_ERR_ALREADYUSED + abi::SOLID_ERR_OUTOFBOUND => ErrorKind::InvalidInput, + // abi::SOLID_ERR_BADSEQUENCE + abi::SOLID_ERR_UNKNOWNDEVICE => ErrorKind::NotFound, + // abi::SOLID_ERR_BUSY + abi::SOLID_ERR_TIMEOUT => ErrorKind::TimedOut, + // abi::SOLID_ERR_INVALIDACCESS + // abi::SOLID_ERR_NOTREADY + _ => itron::error::decode_error_kind(er), + } +} diff --git a/library/std/src/sys/solid/fs.rs b/library/std/src/sys/solid/fs.rs new file mode 100644 index 0000000000..abc60b56fb --- /dev/null +++ b/library/std/src/sys/solid/fs.rs @@ -0,0 +1,529 @@ +use super::{abi, error}; +use crate::{ + ffi::{CStr, CString, OsStr, OsString}, + fmt, + io::{self, IoSlice, IoSliceMut, SeekFrom}, + mem::MaybeUninit, + os::raw::{c_int, c_short}, + os::solid::ffi::OsStrExt, + path::{Path, PathBuf}, + sync::Arc, + sys::time::SystemTime, + sys::unsupported, +}; + +pub use crate::sys_common::fs::try_exists; + +/// A file descriptor. +#[derive(Clone, Copy)] +#[rustc_layout_scalar_valid_range_start(0)] +// libstd/os/raw/mod.rs assures me that every libstd-supported platform has a +// 32-bit c_int. Below is -2, in two's complement, but that only works out +// because c_int is 32 bits. +#[rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FE)] +struct FileDesc { + fd: c_int, +} + +impl FileDesc { + #[inline] + fn new(fd: c_int) -> FileDesc { + assert_ne!(fd, -1i32); + // Safety: we just asserted that the value is in the valid range and + // isn't `-1` (the only value bigger than `0xFF_FF_FF_FE` unsigned) + unsafe { FileDesc { fd } } + } + + #[inline] + fn raw(&self) -> c_int { + self.fd + } +} + +pub struct File { + fd: FileDesc, +} + +#[derive(Clone)] +pub struct FileAttr { + stat: abi::stat, +} + +// all DirEntry's will have a reference to this struct +struct InnerReadDir { + dirp: abi::S_DIR, + root: PathBuf, +} + +pub struct ReadDir { + inner: Arc, +} + +pub struct DirEntry { + entry: abi::dirent, + inner: Arc, +} + +#[derive(Clone, Debug)] +pub struct OpenOptions { + // generic + read: bool, + write: bool, + append: bool, + truncate: bool, + create: bool, + create_new: bool, + // system-specific + custom_flags: i32, +} + +#[derive(Clone, PartialEq, Eq, Debug)] +pub struct FilePermissions(c_short); + +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] +pub struct FileType(c_short); + +#[derive(Debug)] +pub struct DirBuilder {} + +impl FileAttr { + pub fn size(&self) -> u64 { + self.stat.st_size as u64 + } + + pub fn perm(&self) -> FilePermissions { + FilePermissions(self.stat.st_mode) + } + + pub fn file_type(&self) -> FileType { + FileType(self.stat.st_mode) + } + + pub fn modified(&self) -> io::Result { + Ok(SystemTime::from_time_t(self.stat.st_mtime)) + } + + pub fn accessed(&self) -> io::Result { + Ok(SystemTime::from_time_t(self.stat.st_atime)) + } + + pub fn created(&self) -> io::Result { + Ok(SystemTime::from_time_t(self.stat.st_ctime)) + } +} + +impl FilePermissions { + pub fn readonly(&self) -> bool { + (self.0 & abi::S_IWRITE) == 0 + } + + pub fn set_readonly(&mut self, readonly: bool) { + if readonly { + self.0 &= !abi::S_IWRITE; + } else { + self.0 |= abi::S_IWRITE; + } + } +} + +impl FileType { + pub fn is_dir(&self) -> bool { + self.is(abi::S_IFDIR) + } + pub fn is_file(&self) -> bool { + self.is(abi::S_IFREG) + } + pub fn is_symlink(&self) -> bool { + false + } + + pub fn is(&self, mode: c_short) -> bool { + self.0 & abi::S_IFMT == mode + } +} + +pub fn readdir(p: &Path) -> io::Result { + unsafe { + let mut dir = MaybeUninit::uninit(); + error::SolidError::err_if_negative(abi::SOLID_FS_OpenDir( + cstr(p)?.as_ptr(), + dir.as_mut_ptr(), + )) + .map_err(|e| e.as_io_error())?; + let inner = Arc::new(InnerReadDir { dirp: dir.assume_init(), root: p.to_owned() }); + Ok(ReadDir { inner }) + } +} + +impl fmt::Debug for ReadDir { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + // This will only be called from std::fs::ReadDir, which will add a "ReadDir()" frame. + // Thus the result will be e g 'ReadDir("/home")' + fmt::Debug::fmt(&*self.inner.root, f) + } +} + +impl Iterator for ReadDir { + type Item = io::Result; + + fn next(&mut self) -> Option> { + unsafe { + let mut out_dirent = MaybeUninit::uninit(); + error::SolidError::err_if_negative(abi::SOLID_FS_ReadDir( + self.inner.dirp, + out_dirent.as_mut_ptr(), + )) + .ok()?; + Some(Ok(DirEntry { entry: out_dirent.assume_init(), inner: Arc::clone(&self.inner) })) + } + } +} + +impl Drop for InnerReadDir { + fn drop(&mut self) { + unsafe { abi::SOLID_FS_CloseDir(self.dirp) }; + } +} + +impl DirEntry { + pub fn path(&self) -> PathBuf { + self.inner.root.join(OsStr::from_bytes( + unsafe { CStr::from_ptr(self.entry.d_name.as_ptr()) }.to_bytes(), + )) + } + + pub fn file_name(&self) -> OsString { + OsStr::from_bytes(unsafe { CStr::from_ptr(self.entry.d_name.as_ptr()) }.to_bytes()) + .to_os_string() + } + + pub fn metadata(&self) -> io::Result { + lstat(&self.path()) + } + + pub fn file_type(&self) -> io::Result { + match self.entry.d_type { + abi::DT_CHR => Ok(FileType(abi::S_IFCHR)), + abi::DT_FIFO => Ok(FileType(abi::S_IFIFO)), + abi::DT_REG => Ok(FileType(abi::S_IFREG)), + abi::DT_DIR => Ok(FileType(abi::S_IFDIR)), + abi::DT_BLK => Ok(FileType(abi::S_IFBLK)), + _ => lstat(&self.path()).map(|m| m.file_type()), + } + } +} + +impl OpenOptions { + pub fn new() -> OpenOptions { + OpenOptions { + // generic + read: false, + write: false, + append: false, + truncate: false, + create: false, + create_new: false, + // system-specific + custom_flags: 0, + } + } + + pub fn read(&mut self, read: bool) { + self.read = read; + } + pub fn write(&mut self, write: bool) { + self.write = write; + } + pub fn append(&mut self, append: bool) { + self.append = append; + } + pub fn truncate(&mut self, truncate: bool) { + self.truncate = truncate; + } + pub fn create(&mut self, create: bool) { + self.create = create; + } + pub fn create_new(&mut self, create_new: bool) { + self.create_new = create_new; + } + + pub fn custom_flags(&mut self, flags: i32) { + self.custom_flags = flags; + } + pub fn mode(&mut self, _mode: u32) {} + + fn get_access_mode(&self) -> io::Result { + match (self.read, self.write, self.append) { + (true, false, false) => Ok(abi::O_RDONLY), + (false, true, false) => Ok(abi::O_WRONLY), + (true, true, false) => Ok(abi::O_RDWR), + (false, _, true) => Ok(abi::O_WRONLY | abi::O_APPEND), + (true, _, true) => Ok(abi::O_RDWR | abi::O_APPEND), + (false, false, false) => Err(io::Error::from_raw_os_error(libc::EINVAL)), + } + } + + fn get_creation_mode(&self) -> io::Result { + match (self.write, self.append) { + (true, false) => {} + (false, false) => { + if self.truncate || self.create || self.create_new { + return Err(io::Error::from_raw_os_error(libc::EINVAL)); + } + } + (_, true) => { + if self.truncate && !self.create_new { + return Err(io::Error::from_raw_os_error(libc::EINVAL)); + } + } + } + + Ok(match (self.create, self.truncate, self.create_new) { + (false, false, false) => 0, + (true, false, false) => abi::O_CREAT, + (false, true, false) => abi::O_TRUNC, + (true, true, false) => abi::O_CREAT | abi::O_TRUNC, + (_, _, true) => abi::O_CREAT | abi::O_EXCL, + }) + } +} + +fn cstr(path: &Path) -> io::Result { + Ok(CString::new(path.as_os_str().as_bytes())?) +} + +impl File { + pub fn open(path: &Path, opts: &OpenOptions) -> io::Result { + let flags = opts.get_access_mode()? + | opts.get_creation_mode()? + | (opts.custom_flags as c_int & !abi::O_ACCMODE); + unsafe { + let mut fd = MaybeUninit::uninit(); + error::SolidError::err_if_negative(abi::SOLID_FS_Open( + fd.as_mut_ptr(), + cstr(path)?.as_ptr(), + flags, + )) + .map_err(|e| e.as_io_error())?; + Ok(File { fd: FileDesc::new(fd.assume_init()) }) + } + } + + pub fn file_attr(&self) -> io::Result { + unsupported() + } + + pub fn fsync(&self) -> io::Result<()> { + self.flush() + } + + pub fn datasync(&self) -> io::Result<()> { + self.flush() + } + + pub fn truncate(&self, _size: u64) -> io::Result<()> { + unsupported() + } + + pub fn read(&self, buf: &mut [u8]) -> io::Result { + unsafe { + let mut out_num_bytes = MaybeUninit::uninit(); + error::SolidError::err_if_negative(abi::SOLID_FS_Read( + self.fd.raw(), + buf.as_mut_ptr(), + buf.len(), + out_num_bytes.as_mut_ptr(), + )) + .map_err(|e| e.as_io_error())?; + Ok(out_num_bytes.assume_init()) + } + } + + pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result { + crate::io::default_read_vectored(|buf| self.read(buf), bufs) + } + + pub fn is_read_vectored(&self) -> bool { + false + } + + pub fn write(&self, buf: &[u8]) -> io::Result { + unsafe { + let mut out_num_bytes = MaybeUninit::uninit(); + error::SolidError::err_if_negative(abi::SOLID_FS_Write( + self.fd.raw(), + buf.as_ptr(), + buf.len(), + out_num_bytes.as_mut_ptr(), + )) + .map_err(|e| e.as_io_error())?; + Ok(out_num_bytes.assume_init()) + } + } + + pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result { + crate::io::default_write_vectored(|buf| self.write(buf), bufs) + } + + pub fn is_write_vectored(&self) -> bool { + false + } + + pub fn flush(&self) -> io::Result<()> { + error::SolidError::err_if_negative(unsafe { abi::SOLID_FS_Sync(self.fd.raw()) }) + .map_err(|e| e.as_io_error())?; + Ok(()) + } + + pub fn seek(&self, pos: SeekFrom) -> io::Result { + let (whence, pos) = match pos { + // Casting to `i64` is fine, too large values will end up as + // negative which will cause an error in `SOLID_FS_Lseek`. + SeekFrom::Start(off) => (abi::SEEK_SET, off as i64), + SeekFrom::End(off) => (abi::SEEK_END, off), + SeekFrom::Current(off) => (abi::SEEK_CUR, off), + }; + error::SolidError::err_if_negative(unsafe { + abi::SOLID_FS_Lseek(self.fd.raw(), pos, whence) + }) + .map_err(|e| e.as_io_error())?; + + // Get the new offset + unsafe { + let mut out_offset = MaybeUninit::uninit(); + error::SolidError::err_if_negative(abi::SOLID_FS_Ftell( + self.fd.raw(), + out_offset.as_mut_ptr(), + )) + .map_err(|e| e.as_io_error())?; + Ok(out_offset.assume_init() as u64) + } + } + + pub fn duplicate(&self) -> io::Result { + unsupported() + } + + pub fn set_permissions(&self, _perm: FilePermissions) -> io::Result<()> { + unsupported() + } +} + +impl Drop for File { + fn drop(&mut self) { + unsafe { abi::SOLID_FS_Close(self.fd.raw()) }; + } +} + +impl DirBuilder { + pub fn new() -> DirBuilder { + DirBuilder {} + } + + pub fn mkdir(&self, p: &Path) -> io::Result<()> { + error::SolidError::err_if_negative(unsafe { abi::SOLID_FS_Mkdir(cstr(p)?.as_ptr()) }) + .map_err(|e| e.as_io_error())?; + Ok(()) + } +} + +impl fmt::Debug for File { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("File").field("fd", &self.fd.raw()).finish() + } +} + +pub fn unlink(p: &Path) -> io::Result<()> { + if stat(p)?.file_type().is_dir() { + Err(io::Error::new_const(io::ErrorKind::IsADirectory, &"is a directory")) + } else { + error::SolidError::err_if_negative(unsafe { abi::SOLID_FS_Unlink(cstr(p)?.as_ptr()) }) + .map_err(|e| e.as_io_error())?; + Ok(()) + } +} + +pub fn rename(old: &Path, new: &Path) -> io::Result<()> { + error::SolidError::err_if_negative(unsafe { + abi::SOLID_FS_Rename(cstr(old)?.as_ptr(), cstr(new)?.as_ptr()) + }) + .map_err(|e| e.as_io_error())?; + Ok(()) +} + +pub fn set_perm(p: &Path, perm: FilePermissions) -> io::Result<()> { + error::SolidError::err_if_negative(unsafe { + abi::SOLID_FS_Chmod(cstr(p)?.as_ptr(), perm.0.into()) + }) + .map_err(|e| e.as_io_error())?; + Ok(()) +} + +pub fn rmdir(p: &Path) -> io::Result<()> { + if stat(p)?.file_type().is_dir() { + error::SolidError::err_if_negative(unsafe { abi::SOLID_FS_Unlink(cstr(p)?.as_ptr()) }) + .map_err(|e| e.as_io_error())?; + Ok(()) + } else { + Err(io::Error::new_const(io::ErrorKind::NotADirectory, &"not a directory")) + } +} + +pub fn remove_dir_all(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(&child.path())?; + } else { + unlink(&child.path())?; + } + } + rmdir(path) +} + +pub fn readlink(p: &Path) -> io::Result { + // This target doesn't support symlinks + stat(p)?; + Err(io::Error::new_const(io::ErrorKind::InvalidInput, &"not a symbolic link")) +} + +pub fn symlink(_original: &Path, _link: &Path) -> io::Result<()> { + // This target doesn't support symlinks + unsupported() +} + +pub fn link(_src: &Path, _dst: &Path) -> io::Result<()> { + // This target doesn't support symlinks + unsupported() +} + +pub fn stat(p: &Path) -> io::Result { + // This target doesn't support symlinks + lstat(p) +} + +pub fn lstat(p: &Path) -> io::Result { + unsafe { + let mut out_stat = MaybeUninit::uninit(); + error::SolidError::err_if_negative(abi::SOLID_FS_Stat( + cstr(p)?.as_ptr(), + out_stat.as_mut_ptr(), + )) + .map_err(|e| e.as_io_error())?; + Ok(FileAttr { stat: out_stat.assume_init() }) + } +} + +pub fn canonicalize(_p: &Path) -> io::Result { + unsupported() +} + +pub fn copy(from: &Path, to: &Path) -> io::Result { + use crate::fs::File; + + let mut reader = File::open(from)?; + let mut writer = File::create(to)?; + + io::copy(&mut reader, &mut writer) +} diff --git a/library/std/src/sys/solid/io.rs b/library/std/src/sys/solid/io.rs new file mode 100644 index 0000000000..9eb17a10da --- /dev/null +++ b/library/std/src/sys/solid/io.rs @@ -0,0 +1,77 @@ +use crate::marker::PhantomData; +use crate::slice; + +use super::abi::sockets::iovec; +use libc::c_void; + +#[derive(Copy, Clone)] +#[repr(transparent)] +pub struct IoSlice<'a> { + vec: iovec, + _p: PhantomData<&'a [u8]>, +} + +impl<'a> IoSlice<'a> { + #[inline] + pub fn new(buf: &'a [u8]) -> IoSlice<'a> { + IoSlice { + vec: iovec { iov_base: buf.as_ptr() as *mut u8 as *mut c_void, iov_len: buf.len() }, + _p: PhantomData, + } + } + + #[inline] + pub fn advance(&mut self, n: usize) { + if self.vec.iov_len < n { + panic!("advancing IoSlice beyond its length"); + } + + unsafe { + self.vec.iov_len -= n; + self.vec.iov_base = self.vec.iov_base.add(n); + } + } + + #[inline] + pub fn as_slice(&self) -> &[u8] { + unsafe { slice::from_raw_parts(self.vec.iov_base as *mut u8, self.vec.iov_len) } + } +} + +#[repr(transparent)] +pub struct IoSliceMut<'a> { + vec: iovec, + _p: PhantomData<&'a mut [u8]>, +} + +impl<'a> IoSliceMut<'a> { + #[inline] + pub fn new(buf: &'a mut [u8]) -> IoSliceMut<'a> { + IoSliceMut { + vec: iovec { iov_base: buf.as_mut_ptr() as *mut c_void, iov_len: buf.len() }, + _p: PhantomData, + } + } + + #[inline] + pub fn advance(&mut self, n: usize) { + if self.vec.iov_len < n { + panic!("advancing IoSliceMut beyond its length"); + } + + unsafe { + self.vec.iov_len -= n; + self.vec.iov_base = self.vec.iov_base.add(n); + } + } + + #[inline] + pub fn as_slice(&self) -> &[u8] { + unsafe { slice::from_raw_parts(self.vec.iov_base as *mut u8, self.vec.iov_len) } + } + + #[inline] + pub fn as_mut_slice(&mut self) -> &mut [u8] { + unsafe { slice::from_raw_parts_mut(self.vec.iov_base as *mut u8, self.vec.iov_len) } + } +} diff --git a/library/std/src/sys/solid/memchr.rs b/library/std/src/sys/solid/memchr.rs new file mode 100644 index 0000000000..452b7a3de1 --- /dev/null +++ b/library/std/src/sys/solid/memchr.rs @@ -0,0 +1,21 @@ +pub fn memchr(needle: u8, haystack: &[u8]) -> Option { + let p = unsafe { + libc::memchr( + haystack.as_ptr() as *const libc::c_void, + needle as libc::c_int, + haystack.len(), + ) + }; + if p.is_null() { None } else { Some(p as usize - (haystack.as_ptr() as usize)) } +} + +pub fn memrchr(needle: u8, haystack: &[u8]) -> Option { + let p = unsafe { + libc::memrchr( + haystack.as_ptr() as *const libc::c_void, + needle as libc::c_int, + haystack.len(), + ) + }; + if p.is_null() { None } else { Some(p as usize - (haystack.as_ptr() as usize)) } +} diff --git a/library/std/src/sys/solid/mod.rs b/library/std/src/sys/solid/mod.rs new file mode 100644 index 0000000000..211b8d7de3 --- /dev/null +++ b/library/std/src/sys/solid/mod.rs @@ -0,0 +1,96 @@ +#![allow(dead_code)] +#![allow(missing_docs, nonstandard_style)] +#![deny(unsafe_op_in_unsafe_fn)] + +mod abi; + +#[path = "../itron"] +mod itron { + pub(super) mod abi; + pub mod condvar; + pub(super) mod error; + pub mod mutex; + pub(super) mod spin; + pub(super) mod task; + pub mod thread; + pub(super) mod time; + use super::unsupported; +} + +pub mod alloc; +#[path = "../unsupported/args.rs"] +pub mod args; +#[path = "../unix/cmath.rs"] +pub mod cmath; +pub mod env; +// `error` is `pub(crate)` so that it can be accessed by `itron/error.rs` as +// `crate::sys::error` +pub(crate) mod error; +pub mod fs; +pub mod io; +pub mod net; +pub mod os; +#[path = "../unix/os_str.rs"] +pub mod os_str; +pub mod path; +#[path = "../unsupported/pipe.rs"] +pub mod pipe; +#[path = "../unsupported/process.rs"] +pub mod process; +pub mod rwlock; +pub mod stdio; +pub use self::itron::{condvar, mutex, thread}; +pub mod memchr; +pub mod thread_local_dtor; +pub mod thread_local_key; +pub mod time; + +// SAFETY: must be called only once during runtime initialization. +// NOTE: this is not guaranteed to run, for example when Rust code is called externally. +pub unsafe fn init(_argc: isize, _argv: *const *const u8) {} + +// SAFETY: must be called only once during runtime cleanup. +pub unsafe fn cleanup() {} + +pub fn unsupported() -> crate::io::Result { + Err(unsupported_err()) +} + +pub fn unsupported_err() -> crate::io::Error { + crate::io::Error::new_const( + crate::io::ErrorKind::Unsupported, + &"operation not supported on this platform", + ) +} + +pub fn decode_error_kind(code: i32) -> crate::io::ErrorKind { + error::decode_error_kind(code) +} + +#[inline(always)] +pub fn abort_internal() -> ! { + loop { + abi::breakpoint_abort(); + } +} + +// This function is needed by the panic runtime. The symbol is named in +// pre-link args for the target specification, so keep that in sync. +#[cfg(not(test))] +#[no_mangle] +// NB. used by both libunwind and libpanic_abort +pub extern "C" fn __rust_abort() { + abort_internal(); +} + +pub fn hashmap_random_keys() -> (u64, u64) { + unsafe { + let mut out = crate::mem::MaybeUninit::<[u64; 2]>::uninit(); + let result = abi::SOLID_RNG_SampleRandomBytes(out.as_mut_ptr() as *mut u8, 16); + assert_eq!(result, 0, "SOLID_RNG_SampleRandomBytes failed: {}", result); + let [x1, x2] = out.assume_init(); + (x1, x2) + } +} + +pub use libc::strlen; diff --git a/library/std/src/sys/solid/net.rs b/library/std/src/sys/solid/net.rs new file mode 100644 index 0000000000..63ba6341c7 --- /dev/null +++ b/library/std/src/sys/solid/net.rs @@ -0,0 +1,469 @@ +use super::abi; +use crate::{ + cmp, + ffi::CStr, + io::{self, ErrorKind, IoSlice, IoSliceMut}, + mem, + net::{Shutdown, SocketAddr}, + ptr, str, + sys_common::net::{getsockopt, setsockopt, sockaddr_to_addr}, + sys_common::{AsInner, FromInner, IntoInner}, + time::Duration, +}; + +use self::netc::{sockaddr, socklen_t, MSG_PEEK}; +use libc::{c_int, c_void, size_t}; + +pub mod netc { + pub use super::super::abi::sockets::*; +} + +pub type wrlen_t = size_t; + +const READ_LIMIT: usize = libc::ssize_t::MAX as usize; + +const fn max_iov() -> usize { + // Judging by the source code, it's unlimited, but specify a lower + // value just in case. + 1024 +} + +/// A file descriptor. +#[rustc_layout_scalar_valid_range_start(0)] +// libstd/os/raw/mod.rs assures me that every libstd-supported platform has a +// 32-bit c_int. Below is -2, in two's complement, but that only works out +// because c_int is 32 bits. +#[rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FE)] +struct FileDesc { + fd: c_int, +} + +impl FileDesc { + #[inline] + fn new(fd: c_int) -> FileDesc { + assert_ne!(fd, -1i32); + // Safety: we just asserted that the value is in the valid range and + // isn't `-1` (the only value bigger than `0xFF_FF_FF_FE` unsigned) + unsafe { FileDesc { fd } } + } + + #[inline] + fn raw(&self) -> c_int { + self.fd + } + + /// Extracts the actual file descriptor without closing it. + #[inline] + fn into_raw(self) -> c_int { + let fd = self.fd; + mem::forget(self); + fd + } + + fn read(&self, buf: &mut [u8]) -> io::Result { + let ret = cvt(unsafe { + netc::read(self.fd, buf.as_mut_ptr() as *mut c_void, cmp::min(buf.len(), READ_LIMIT)) + })?; + Ok(ret as usize) + } + + fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result { + let ret = cvt(unsafe { + netc::readv( + self.fd, + bufs.as_ptr() as *const netc::iovec, + cmp::min(bufs.len(), max_iov()) as c_int, + ) + })?; + Ok(ret as usize) + } + + #[inline] + fn is_read_vectored(&self) -> bool { + true + } + + fn write(&self, buf: &[u8]) -> io::Result { + let ret = cvt(unsafe { + netc::write(self.fd, buf.as_ptr() as *const c_void, cmp::min(buf.len(), READ_LIMIT)) + })?; + Ok(ret as usize) + } + + fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result { + let ret = cvt(unsafe { + netc::writev( + self.fd, + bufs.as_ptr() as *const netc::iovec, + cmp::min(bufs.len(), max_iov()) as c_int, + ) + })?; + Ok(ret as usize) + } + + #[inline] + fn is_write_vectored(&self) -> bool { + true + } + + fn duplicate(&self) -> io::Result { + super::unsupported() + } +} + +impl AsInner for FileDesc { + fn as_inner(&self) -> &c_int { + &self.fd + } +} + +impl Drop for FileDesc { + fn drop(&mut self) { + unsafe { netc::close(self.fd) }; + } +} + +#[doc(hidden)] +pub trait IsMinusOne { + fn is_minus_one(&self) -> bool; +} + +macro_rules! impl_is_minus_one { + ($($t:ident)*) => ($(impl IsMinusOne for $t { + fn is_minus_one(&self) -> bool { + *self == -1 + } + })*) +} + +impl_is_minus_one! { i8 i16 i32 i64 isize } + +pub fn cvt(t: T) -> io::Result { + if t.is_minus_one() { Err(last_error()) } else { Ok(t) } +} + +/// A variant of `cvt` for `getaddrinfo` which return 0 for a success. +pub fn cvt_gai(err: c_int) -> io::Result<()> { + if err == 0 { + Ok(()) + } else { + let msg: &dyn crate::fmt::Display = match err { + netc::EAI_NONAME => &"name or service not known", + netc::EAI_SERVICE => &"service not supported", + netc::EAI_FAIL => &"non-recoverable failure in name resolution", + netc::EAI_MEMORY => &"memory allocation failure", + netc::EAI_FAMILY => &"family not supported", + _ => &err, + }; + Err(io::Error::new( + io::ErrorKind::Uncategorized, + &format!("failed to lookup address information: {}", msg)[..], + )) + } +} + +/// Just to provide the same interface as sys/unix/net.rs +pub fn cvt_r(mut f: F) -> io::Result +where + T: IsMinusOne, + F: FnMut() -> T, +{ + cvt(f()) +} + +/// Returns the last error from the network subsystem. +fn last_error() -> io::Error { + io::Error::from_raw_os_error(unsafe { netc::SOLID_NET_GetLastError() }) +} + +pub(super) fn error_name(er: abi::ER) -> Option<&'static str> { + unsafe { CStr::from_ptr(netc::strerror(er)) }.to_str().ok() +} + +pub(super) fn decode_error_kind(er: abi::ER) -> ErrorKind { + let errno = netc::SOLID_NET_ERR_BASE - er; + match errno as libc::c_int { + libc::ECONNREFUSED => ErrorKind::ConnectionRefused, + libc::ECONNRESET => ErrorKind::ConnectionReset, + libc::EPERM | libc::EACCES => ErrorKind::PermissionDenied, + libc::EPIPE => ErrorKind::BrokenPipe, + libc::ENOTCONN => ErrorKind::NotConnected, + libc::ECONNABORTED => ErrorKind::ConnectionAborted, + libc::EADDRNOTAVAIL => ErrorKind::AddrNotAvailable, + libc::EADDRINUSE => ErrorKind::AddrInUse, + libc::ENOENT => ErrorKind::NotFound, + libc::EINTR => ErrorKind::Interrupted, + libc::EINVAL => ErrorKind::InvalidInput, + libc::ETIMEDOUT => ErrorKind::TimedOut, + libc::EEXIST => ErrorKind::AlreadyExists, + libc::ENOSYS => ErrorKind::Unsupported, + libc::ENOMEM => ErrorKind::OutOfMemory, + libc::EAGAIN => ErrorKind::WouldBlock, + + _ => ErrorKind::Uncategorized, + } +} + +pub fn init() {} + +pub struct Socket(FileDesc); + +impl Socket { + pub fn new(addr: &SocketAddr, ty: c_int) -> io::Result { + let fam = match *addr { + SocketAddr::V4(..) => netc::AF_INET, + SocketAddr::V6(..) => netc::AF_INET6, + }; + Socket::new_raw(fam, ty) + } + + pub fn new_raw(fam: c_int, ty: c_int) -> io::Result { + unsafe { + let fd = cvt(netc::socket(fam, ty, 0))?; + let fd = FileDesc::new(fd); + let socket = Socket(fd); + + Ok(socket) + } + } + + pub fn connect_timeout(&self, addr: &SocketAddr, timeout: Duration) -> io::Result<()> { + self.set_nonblocking(true)?; + let r = unsafe { + let (addrp, len) = addr.into_inner(); + cvt(netc::connect(self.0.raw(), addrp, len)) + }; + self.set_nonblocking(false)?; + + match r { + Ok(_) => return Ok(()), + // there's no ErrorKind for EINPROGRESS + Err(ref e) if e.raw_os_error() == Some(netc::EINPROGRESS) => {} + Err(e) => return Err(e), + } + + if timeout.as_secs() == 0 && timeout.subsec_nanos() == 0 { + return Err(io::Error::new_const( + io::ErrorKind::InvalidInput, + &"cannot set a 0 duration timeout", + )); + } + + let mut timeout = + netc::timeval { tv_sec: timeout.as_secs() as _, tv_usec: timeout.subsec_micros() as _ }; + if timeout.tv_sec == 0 && timeout.tv_usec == 0 { + timeout.tv_usec = 1; + } + + let fds = netc::fd_set { num_fds: 1, fds: [self.0.raw()] }; + + let mut writefds = fds; + let mut errorfds = fds; + + let n = unsafe { + cvt(netc::select( + self.0.raw() + 1, + ptr::null_mut(), + &mut writefds, + &mut errorfds, + &mut timeout, + ))? + }; + + match n { + 0 => Err(io::Error::new_const(io::ErrorKind::TimedOut, &"connection timed out")), + _ => { + let can_write = writefds.num_fds != 0; + if !can_write { + if let Some(e) = self.take_error()? { + return Err(e); + } + } + Ok(()) + } + } + } + + pub fn accept(&self, storage: *mut sockaddr, len: *mut socklen_t) -> io::Result { + let fd = cvt_r(|| unsafe { netc::accept(self.0.raw(), storage, len) })?; + let fd = FileDesc::new(fd); + Ok(Socket(fd)) + } + + pub fn duplicate(&self) -> io::Result { + self.0.duplicate().map(Socket) + } + + fn recv_with_flags(&self, buf: &mut [u8], flags: c_int) -> io::Result { + let ret = cvt(unsafe { + netc::recv(self.0.raw(), buf.as_mut_ptr() as *mut c_void, buf.len(), flags) + })?; + Ok(ret as usize) + } + + pub fn read(&self, buf: &mut [u8]) -> io::Result { + self.recv_with_flags(buf, 0) + } + + pub fn peek(&self, buf: &mut [u8]) -> io::Result { + self.recv_with_flags(buf, MSG_PEEK) + } + + pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result { + self.0.read_vectored(bufs) + } + + #[inline] + pub fn is_read_vectored(&self) -> bool { + self.0.is_read_vectored() + } + + fn recv_from_with_flags( + &self, + buf: &mut [u8], + flags: c_int, + ) -> io::Result<(usize, SocketAddr)> { + let mut storage: netc::sockaddr_storage = unsafe { mem::zeroed() }; + let mut addrlen = mem::size_of_val(&storage) as netc::socklen_t; + + let n = cvt(unsafe { + netc::recvfrom( + self.0.raw(), + buf.as_mut_ptr() as *mut c_void, + buf.len(), + flags, + &mut storage as *mut _ as *mut _, + &mut addrlen, + ) + })?; + Ok((n as usize, sockaddr_to_addr(&storage, addrlen as usize)?)) + } + + pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> { + self.recv_from_with_flags(buf, 0) + } + + pub fn peek_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> { + self.recv_from_with_flags(buf, MSG_PEEK) + } + + pub fn write(&self, buf: &[u8]) -> io::Result { + self.0.write(buf) + } + + pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result { + self.0.write_vectored(bufs) + } + + #[inline] + pub fn is_write_vectored(&self) -> bool { + self.0.is_write_vectored() + } + + pub fn set_timeout(&self, dur: Option, kind: c_int) -> io::Result<()> { + let timeout = match dur { + Some(dur) => { + if dur.as_secs() == 0 && dur.subsec_nanos() == 0 { + return Err(io::Error::new_const( + io::ErrorKind::InvalidInput, + &"cannot set a 0 duration timeout", + )); + } + + let secs = if dur.as_secs() > netc::c_long::MAX as u64 { + netc::c_long::MAX + } else { + dur.as_secs() as netc::c_long + }; + let mut timeout = netc::timeval { tv_sec: secs, tv_usec: dur.subsec_micros() as _ }; + if timeout.tv_sec == 0 && timeout.tv_usec == 0 { + timeout.tv_usec = 1; + } + timeout + } + None => netc::timeval { tv_sec: 0, tv_usec: 0 }, + }; + setsockopt(self, netc::SOL_SOCKET, kind, timeout) + } + + pub fn timeout(&self, kind: c_int) -> io::Result> { + let raw: netc::timeval = getsockopt(self, netc::SOL_SOCKET, kind)?; + if raw.tv_sec == 0 && raw.tv_usec == 0 { + Ok(None) + } else { + let sec = raw.tv_sec as u64; + let nsec = (raw.tv_usec as u32) * 1000; + Ok(Some(Duration::new(sec, nsec))) + } + } + + pub fn shutdown(&self, how: Shutdown) -> io::Result<()> { + let how = match how { + Shutdown::Write => netc::SHUT_WR, + Shutdown::Read => netc::SHUT_RD, + Shutdown::Both => netc::SHUT_RDWR, + }; + cvt(unsafe { netc::shutdown(self.0.raw(), how) })?; + Ok(()) + } + + pub fn set_linger(&self, linger: Option) -> io::Result<()> { + let linger = netc::linger { + l_onoff: linger.is_some() as netc::c_int, + l_linger: linger.unwrap_or_default().as_secs() as netc::c_int, + }; + + setsockopt(self, netc::SOL_SOCKET, netc::SO_LINGER, linger) + } + + pub fn linger(&self) -> io::Result> { + let val: netc::linger = getsockopt(self, netc::SOL_SOCKET, netc::SO_LINGER)?; + + Ok((val.l_onoff != 0).then(|| Duration::from_secs(val.l_linger as u64))) + } + + pub fn set_nodelay(&self, nodelay: bool) -> io::Result<()> { + setsockopt(self, netc::IPPROTO_TCP, netc::TCP_NODELAY, nodelay as c_int) + } + + pub fn nodelay(&self) -> io::Result { + let raw: c_int = getsockopt(self, netc::IPPROTO_TCP, netc::TCP_NODELAY)?; + Ok(raw != 0) + } + + pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { + let mut nonblocking = nonblocking as c_int; + cvt(unsafe { + netc::ioctl(*self.as_inner(), netc::FIONBIO, (&mut nonblocking) as *mut c_int as _) + }) + .map(drop) + } + + pub fn take_error(&self) -> io::Result> { + let raw: c_int = getsockopt(self, netc::SOL_SOCKET, netc::SO_ERROR)?; + if raw == 0 { Ok(None) } else { Ok(Some(io::Error::from_raw_os_error(raw as i32))) } + } + + // This method is used by sys_common code to abstract over targets. + pub fn as_raw(&self) -> c_int { + *self.as_inner() + } +} + +impl AsInner for Socket { + fn as_inner(&self) -> &c_int { + self.0.as_inner() + } +} + +impl FromInner for Socket { + fn from_inner(fd: c_int) -> Socket { + Socket(FileDesc::new(fd)) + } +} + +impl IntoInner for Socket { + fn into_inner(self) -> c_int { + self.0.into_raw() + } +} diff --git a/library/std/src/sys/solid/os.rs b/library/std/src/sys/solid/os.rs new file mode 100644 index 0000000000..82542d81e6 --- /dev/null +++ b/library/std/src/sys/solid/os.rs @@ -0,0 +1,200 @@ +use super::unsupported; +use crate::error::Error as StdError; +use crate::ffi::{CStr, CString, OsStr, OsString}; +use crate::fmt; +use crate::io; +use crate::os::{ + raw::{c_char, c_int}, + solid::ffi::{OsStrExt, OsStringExt}, +}; +use crate::path::{self, PathBuf}; +use crate::sys_common::rwlock::StaticRWLock; +use crate::vec; + +use super::{abi, error, itron, memchr}; + +// `solid` directly maps `errno`s to μITRON error codes. +impl itron::error::ItronError { + #[inline] + pub(crate) fn as_io_error(self) -> crate::io::Error { + crate::io::Error::from_raw_os_error(self.as_raw()) + } +} + +pub fn errno() -> i32 { + 0 +} + +pub fn error_string(errno: i32) -> String { + if let Some(name) = error::error_name(errno) { name.to_owned() } else { format!("{}", errno) } +} + +pub fn getcwd() -> io::Result { + unsupported() +} + +pub fn chdir(_: &path::Path) -> io::Result<()> { + unsupported() +} + +pub struct SplitPaths<'a>(&'a !); + +pub fn split_paths(_unparsed: &OsStr) -> SplitPaths<'_> { + panic!("unsupported") +} + +impl<'a> Iterator for SplitPaths<'a> { + type Item = PathBuf; + fn next(&mut self) -> Option { + *self.0 + } +} + +#[derive(Debug)] +pub struct JoinPathsError; + +pub fn join_paths(_paths: I) -> Result +where + I: Iterator, + T: AsRef, +{ + Err(JoinPathsError) +} + +impl fmt::Display for JoinPathsError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + "not supported on this platform yet".fmt(f) + } +} + +impl StdError for JoinPathsError { + #[allow(deprecated)] + fn description(&self) -> &str { + "not supported on this platform yet" + } +} + +pub fn current_exe() -> io::Result { + unsupported() +} + +static ENV_LOCK: StaticRWLock = StaticRWLock::new(); + +pub struct Env { + iter: vec::IntoIter<(OsString, OsString)>, +} + +impl !Send for Env {} +impl !Sync for Env {} + +impl Iterator for Env { + type Item = (OsString, OsString); + fn next(&mut self) -> Option<(OsString, OsString)> { + self.iter.next() + } + fn size_hint(&self) -> (usize, Option) { + self.iter.size_hint() + } +} + +/// Returns a vector of (variable, value) byte-vector pairs for all the +/// environment variables of the current process. +pub fn env() -> Env { + extern "C" { + static mut environ: *const *const c_char; + } + + unsafe { + let _guard = ENV_LOCK.read(); + let mut result = Vec::new(); + if !environ.is_null() { + while !(*environ).is_null() { + if let Some(key_value) = parse(CStr::from_ptr(*environ).to_bytes()) { + result.push(key_value); + } + environ = environ.add(1); + } + } + return Env { iter: result.into_iter() }; + } + + fn parse(input: &[u8]) -> Option<(OsString, OsString)> { + // Strategy (copied from glibc): Variable name and value are separated + // by an ASCII equals sign '='. Since a variable name must not be + // empty, allow variable names starting with an equals sign. Skip all + // malformed lines. + if input.is_empty() { + return None; + } + let pos = memchr::memchr(b'=', &input[1..]).map(|p| p + 1); + pos.map(|p| { + ( + OsStringExt::from_vec(input[..p].to_vec()), + OsStringExt::from_vec(input[p + 1..].to_vec()), + ) + }) + } +} + +pub fn getenv(k: &OsStr) -> Option { + // environment variables with a nul byte can't be set, so their value is + // always None as well + let k = CString::new(k.as_bytes()).ok()?; + unsafe { + let _guard = ENV_LOCK.read(); + let s = libc::getenv(k.as_ptr()) as *const libc::c_char; + if s.is_null() { + None + } else { + Some(OsStringExt::from_vec(CStr::from_ptr(s).to_bytes().to_vec())) + } + } +} + +pub fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> { + let k = CString::new(k.as_bytes())?; + let v = CString::new(v.as_bytes())?; + + unsafe { + let _guard = ENV_LOCK.write(); + cvt_env(libc::setenv(k.as_ptr(), v.as_ptr(), 1)).map(drop) + } +} + +pub fn unsetenv(n: &OsStr) -> io::Result<()> { + let nbuf = CString::new(n.as_bytes())?; + + unsafe { + let _guard = ENV_LOCK.write(); + cvt_env(libc::unsetenv(nbuf.as_ptr())).map(drop) + } +} + +/// In kmclib, `setenv` and `unsetenv` don't always set `errno`, so this +/// function just returns a generic error. +fn cvt_env(t: c_int) -> io::Result { + if t == -1 { + Err(io::Error::new_const(io::ErrorKind::Uncategorized, &"failure")) + } else { + Ok(t) + } +} + +pub fn temp_dir() -> PathBuf { + panic!("no standard temporary directory on this platform") +} + +pub fn home_dir() -> Option { + None +} + +pub fn exit(_code: i32) -> ! { + let tid = itron::task::try_current_task_id().unwrap_or(0); + loop { + abi::breakpoint_program_exited(tid as usize); + } +} + +pub fn getpid() -> u32 { + panic!("no pids on this platform") +} diff --git a/library/std/src/sys/solid/path.rs b/library/std/src/sys/solid/path.rs new file mode 100644 index 0000000000..4a14332d49 --- /dev/null +++ b/library/std/src/sys/solid/path.rs @@ -0,0 +1,19 @@ +use crate::ffi::OsStr; +use crate::path::Prefix; + +#[inline] +pub fn is_sep_byte(b: u8) -> bool { + b == b'\\' +} + +#[inline] +pub fn is_verbatim_sep(b: u8) -> bool { + b == b'\\' +} + +pub fn parse_prefix(_: &OsStr) -> Option> { + None +} + +pub const MAIN_SEP_STR: &str = "\\"; +pub const MAIN_SEP: char = '\\'; diff --git a/library/std/src/sys/solid/rwlock.rs b/library/std/src/sys/solid/rwlock.rs new file mode 100644 index 0000000000..4e39ac2a93 --- /dev/null +++ b/library/std/src/sys/solid/rwlock.rs @@ -0,0 +1,92 @@ +//! A readers-writer lock implementation backed by the SOLID kernel extension. +use super::{ + abi, + itron::{ + error::{expect_success, expect_success_aborting, fail, ItronError}, + spin::SpinIdOnceCell, + }, +}; + +pub struct RWLock { + /// The ID of the underlying mutex object + rwl: SpinIdOnceCell<()>, +} + +pub type MovableRWLock = RWLock; + +// Safety: `num_readers` is protected by `mtx_num_readers` +unsafe impl Send for RWLock {} +unsafe impl Sync for RWLock {} + +fn new_rwl() -> Result { + ItronError::err_if_negative(unsafe { abi::rwl_acre_rwl() }) +} + +impl RWLock { + pub const fn new() -> RWLock { + RWLock { rwl: SpinIdOnceCell::new() } + } + + /// Get the inner mutex's ID, which is lazily created. + fn raw(&self) -> abi::ID { + match self.rwl.get_or_try_init(|| new_rwl().map(|id| (id, ()))) { + Ok((id, ())) => id, + Err(e) => fail(e, &"rwl_acre_rwl"), + } + } + + #[inline] + pub unsafe fn read(&self) { + let rwl = self.raw(); + expect_success(unsafe { abi::rwl_loc_rdl(rwl) }, &"rwl_loc_rdl"); + } + + #[inline] + pub unsafe fn try_read(&self) -> bool { + let rwl = self.raw(); + match unsafe { abi::rwl_ploc_rdl(rwl) } { + abi::E_TMOUT => false, + er => { + expect_success(er, &"rwl_ploc_rdl"); + true + } + } + } + + #[inline] + pub unsafe fn write(&self) { + let rwl = self.raw(); + expect_success(unsafe { abi::rwl_loc_wrl(rwl) }, &"rwl_loc_wrl"); + } + + #[inline] + pub unsafe fn try_write(&self) -> bool { + let rwl = self.raw(); + match unsafe { abi::rwl_ploc_wrl(rwl) } { + abi::E_TMOUT => false, + er => { + expect_success(er, &"rwl_ploc_wrl"); + true + } + } + } + + #[inline] + pub unsafe fn read_unlock(&self) { + let rwl = self.raw(); + expect_success_aborting(unsafe { abi::rwl_unl_rwl(rwl) }, &"rwl_unl_rwl"); + } + + #[inline] + pub unsafe fn write_unlock(&self) { + let rwl = self.raw(); + expect_success_aborting(unsafe { abi::rwl_unl_rwl(rwl) }, &"rwl_unl_rwl"); + } + + #[inline] + pub unsafe fn destroy(&self) { + if let Some(rwl) = self.rwl.get().map(|x| x.0) { + expect_success_aborting(unsafe { abi::rwl_del_rwl(rwl) }, &"rwl_del_rwl"); + } + } +} diff --git a/library/std/src/sys/solid/stdio.rs b/library/std/src/sys/solid/stdio.rs new file mode 100644 index 0000000000..50f0176967 --- /dev/null +++ b/library/std/src/sys/solid/stdio.rs @@ -0,0 +1,80 @@ +use super::abi; +use crate::io; + +pub struct Stdin; +pub struct Stdout; +pub struct Stderr; +struct PanicOutput; + +impl Stdin { + pub const fn new() -> Stdin { + Stdin + } +} + +impl io::Read for Stdin { + fn read(&mut self, _buf: &mut [u8]) -> io::Result { + Ok(0) + } +} + +impl Stdout { + pub const fn new() -> Stdout { + Stdout + } +} + +impl io::Write for Stdout { + fn write(&mut self, buf: &[u8]) -> io::Result { + unsafe { abi::SOLID_LOG_write(buf.as_ptr(), buf.len()) }; + Ok(buf.len()) + } + + fn flush(&mut self) -> io::Result<()> { + Ok(()) + } +} + +impl Stderr { + pub const fn new() -> Stderr { + Stderr + } +} + +impl io::Write for Stderr { + fn write(&mut self, buf: &[u8]) -> io::Result { + unsafe { abi::SOLID_LOG_write(buf.as_ptr(), buf.len()) }; + Ok(buf.len()) + } + + fn flush(&mut self) -> io::Result<()> { + Ok(()) + } +} + +impl PanicOutput { + pub const fn new() -> PanicOutput { + PanicOutput + } +} + +impl io::Write for PanicOutput { + fn write(&mut self, buf: &[u8]) -> io::Result { + unsafe { abi::SOLID_LOG_write(buf.as_ptr(), buf.len()) }; + Ok(buf.len()) + } + + fn flush(&mut self) -> io::Result<()> { + Ok(()) + } +} + +pub const STDIN_BUF_SIZE: usize = 0; + +pub fn is_ebadf(_err: &io::Error) -> bool { + true +} + +pub fn panic_output() -> Option { + Some(PanicOutput::new()) +} diff --git a/library/std/src/sys/solid/thread_local_dtor.rs b/library/std/src/sys/solid/thread_local_dtor.rs new file mode 100644 index 0000000000..9735645705 --- /dev/null +++ b/library/std/src/sys/solid/thread_local_dtor.rs @@ -0,0 +1,50 @@ +#![cfg(target_thread_local)] +#![unstable(feature = "thread_local_internals", issue = "none")] + +// Simplify dtor registration by using a list of destructors. + +use super::{abi, itron::task}; +use crate::cell::Cell; +use crate::ptr; + +#[thread_local] +static DTORS: Cell<*mut List> = Cell::new(ptr::null_mut()); + +type List = Vec<(*mut u8, unsafe extern "C" fn(*mut u8))>; + +pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) { + if DTORS.get().is_null() { + let tid = task::current_task_id_aborting(); + let v: Box = box Vec::new(); + DTORS.set(Box::into_raw(v)); + + // Register `tls_dtor` to make sure the TLS destructors are called + // for tasks created by other means than `std::thread` + unsafe { abi::SOLID_TLS_AddDestructor(tid as i32, tls_dtor) }; + } + + let list: &mut List = unsafe { &mut *DTORS.get() }; + list.push((t, dtor)); +} + +pub unsafe fn run_dtors() { + let ptr = DTORS.get(); + if !ptr.is_null() { + // Swap the destructor list, call all registered destructors, + // and repeat this until the list becomes permanently empty. + while let Some(list) = Some(crate::mem::replace(unsafe { &mut *ptr }, Vec::new())) + .filter(|list| !list.is_empty()) + { + for (ptr, dtor) in list.into_iter() { + unsafe { dtor(ptr) }; + } + } + + // Drop the destructor list + unsafe { Box::from_raw(DTORS.replace(ptr::null_mut())) }; + } +} + +unsafe extern "C" fn tls_dtor(_unused: *mut u8) { + unsafe { run_dtors() }; +} diff --git a/library/std/src/sys/solid/thread_local_key.rs b/library/std/src/sys/solid/thread_local_key.rs new file mode 100644 index 0000000000..b17521f701 --- /dev/null +++ b/library/std/src/sys/solid/thread_local_key.rs @@ -0,0 +1,26 @@ +pub type Key = usize; + +#[inline] +pub unsafe fn create(_dtor: Option) -> Key { + panic!("should not be used on the solid target"); +} + +#[inline] +pub unsafe fn set(_key: Key, _value: *mut u8) { + panic!("should not be used on the solid target"); +} + +#[inline] +pub unsafe fn get(_key: Key) -> *mut u8 { + panic!("should not be used on the solid target"); +} + +#[inline] +pub unsafe fn destroy(_key: Key) { + panic!("should not be used on the solid target"); +} + +#[inline] +pub fn requires_synchronized_create() -> bool { + panic!("should not be used on the solid target"); +} diff --git a/library/std/src/sys/solid/time.rs b/library/std/src/sys/solid/time.rs new file mode 100644 index 0000000000..c67a736a90 --- /dev/null +++ b/library/std/src/sys/solid/time.rs @@ -0,0 +1,56 @@ +use super::{abi, error::expect_success}; +use crate::{convert::TryInto, mem::MaybeUninit, time::Duration}; + +pub use super::itron::time::Instant; + +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] +pub struct SystemTime(abi::time_t); + +pub const UNIX_EPOCH: SystemTime = SystemTime(0); + +impl SystemTime { + pub fn now() -> SystemTime { + let rtc = unsafe { + let mut out = MaybeUninit::zeroed(); + expect_success(abi::SOLID_RTC_ReadTime(out.as_mut_ptr()), &"SOLID_RTC_ReadTime"); + out.assume_init() + }; + let t = unsafe { + libc::mktime(&mut libc::tm { + tm_sec: rtc.tm_sec, + tm_min: rtc.tm_min, + tm_hour: rtc.tm_hour, + tm_mday: rtc.tm_mday, + tm_mon: rtc.tm_mon, + tm_year: rtc.tm_year, + tm_wday: rtc.tm_wday, + tm_yday: 0, + tm_isdst: 0, + tm_gmtoff: 0, + tm_zone: crate::ptr::null_mut(), + }) + }; + assert_ne!(t, -1, "mktime failed"); + SystemTime(t) + } + + pub(super) fn from_time_t(t: abi::time_t) -> Self { + Self(t) + } + + pub fn sub_time(&self, other: &SystemTime) -> Result { + if self.0 >= other.0 { + Ok(Duration::from_secs((self.0 as u64).wrapping_sub(other.0 as u64))) + } else { + Err(Duration::from_secs((other.0 as u64).wrapping_sub(self.0 as u64))) + } + } + + pub fn checked_add_duration(&self, other: &Duration) -> Option { + Some(SystemTime(self.0.checked_add(other.as_secs().try_into().ok()?)?)) + } + + pub fn checked_sub_duration(&self, other: &Duration) -> Option { + Some(SystemTime(self.0.checked_sub(other.as_secs().try_into().ok()?)?)) + } +} diff --git a/library/std/src/sys/unix/fs.rs b/library/std/src/sys/unix/fs.rs index 6d7524a733..a4fff9b2e6 100644 --- a/library/std/src/sys/unix/fs.rs +++ b/library/std/src/sys/unix/fs.rs @@ -1416,6 +1416,23 @@ pub fn copy(from: &Path, to: &Path) -> io::Result { Ok(bytes_copied as u64) } +pub fn chown(path: &Path, uid: u32, gid: u32) -> io::Result<()> { + let path = cstr(path)?; + cvt(unsafe { libc::chown(path.as_ptr(), uid as libc::uid_t, gid as libc::gid_t) })?; + Ok(()) +} + +pub fn fchown(fd: c_int, uid: u32, gid: u32) -> io::Result<()> { + cvt(unsafe { libc::fchown(fd, uid as libc::uid_t, gid as libc::gid_t) })?; + Ok(()) +} + +pub fn lchown(path: &Path, uid: u32, gid: u32) -> io::Result<()> { + let path = cstr(path)?; + cvt(unsafe { libc::lchown(path.as_ptr(), uid as libc::uid_t, gid as libc::gid_t) })?; + Ok(()) +} + #[cfg(not(any(target_os = "fuchsia", target_os = "vxworks")))] pub fn chroot(dir: &Path) -> io::Result<()> { let dir = cstr(dir)?; diff --git a/library/std/src/sys/unix/mod.rs b/library/std/src/sys/unix/mod.rs index f5424e3d28..2ba6c8d830 100644 --- a/library/std/src/sys/unix/mod.rs +++ b/library/std/src/sys/unix/mod.rs @@ -120,7 +120,7 @@ pub unsafe fn init(argc: isize, argv: *const *const u8) { unsafe fn reset_sigpipe() { #[cfg(not(any(target_os = "emscripten", target_os = "fuchsia")))] - assert!(signal(libc::SIGPIPE, libc::SIG_IGN) != libc::SIG_ERR); + rtassert!(signal(libc::SIGPIPE, libc::SIG_IGN) != libc::SIG_ERR); } } @@ -307,6 +307,9 @@ cfg_if::cfg_if! { #[link(name = "zircon")] #[link(name = "fdio")] extern "C" {} + } else if #[cfg(all(target_os = "linux", target_env = "uclibc"))] { + #[link(name = "dl")] + extern "C" {} } } diff --git a/library/std/src/sys/unix/os.rs b/library/std/src/sys/unix/os.rs index 1d5ffb0732..87893d2691 100644 --- a/library/std/src/sys/unix/os.rs +++ b/library/std/src/sys/unix/os.rs @@ -380,20 +380,24 @@ pub fn current_exe() -> io::Result { #[cfg(any(target_os = "solaris", target_os = "illumos"))] pub fn current_exe() -> io::Result { - extern "C" { - fn getexecname() -> *const c_char; - } - unsafe { - let path = getexecname(); - if path.is_null() { - Err(io::Error::last_os_error()) - } else { - let filename = CStr::from_ptr(path).to_bytes(); - let path = PathBuf::from(::from_bytes(filename)); + if let Ok(path) = crate::fs::read_link("/proc/self/path/a.out") { + Ok(path) + } else { + extern "C" { + fn getexecname() -> *const c_char; + } + unsafe { + let path = getexecname(); + if path.is_null() { + Err(io::Error::last_os_error()) + } else { + let filename = CStr::from_ptr(path).to_bytes(); + let path = PathBuf::from(::from_bytes(filename)); - // Prepend a current working directory to the path if - // it doesn't contain an absolute pathname. - if filename[0] == b'/' { Ok(path) } else { getcwd().map(|cwd| cwd.join(path)) } + // Prepend a current working directory to the path if + // it doesn't contain an absolute pathname. + if filename[0] == b'/' { Ok(path) } else { getcwd().map(|cwd| cwd.join(path)) } + } } } } diff --git a/library/std/src/sys/unix/process/process_common.rs b/library/std/src/sys/unix/process/process_common.rs index 7b261a302c..7ac2f9d8af 100644 --- a/library/std/src/sys/unix/process/process_common.rs +++ b/library/std/src/sys/unix/process/process_common.rs @@ -457,9 +457,15 @@ impl fmt::Debug for Command { } } -#[derive(PartialEq, Eq, Clone, Copy, Debug)] +#[derive(PartialEq, Eq, Clone, Copy)] pub struct ExitCode(u8); +impl fmt::Debug for ExitCode { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("unix_exit_status").field(&self.0).finish() + } +} + impl ExitCode { pub const SUCCESS: ExitCode = ExitCode(EXIT_SUCCESS as _); pub const FAILURE: ExitCode = ExitCode(EXIT_FAILURE as _); diff --git a/library/std/src/sys/unix/process/process_unix.rs b/library/std/src/sys/unix/process/process_unix.rs index 11d23a3289..326382d903 100644 --- a/library/std/src/sys/unix/process/process_unix.rs +++ b/library/std/src/sys/unix/process/process_unix.rs @@ -170,7 +170,7 @@ impl Command { // so we use it sparingly for now. See #89522 for details. // Some tools (e.g. sandboxing tools) may also expect `fork` // rather than `clone3`. - let want_clone3 = self.get_create_pidfd(); + let want_clone3_pidfd = self.get_create_pidfd(); // If we fail to create a pidfd for any reason, this will // stay as -1, which indicates an error. @@ -179,14 +179,9 @@ impl Command { // Attempt to use the `clone3` syscall, which supports more arguments // (in particular, the ability to create a pidfd). If this fails, // we will fall through this block to a call to `fork()` - if want_clone3 && HAS_CLONE3.load(Ordering::Relaxed) { - let mut flags = 0; - if self.get_create_pidfd() { - flags |= CLONE_PIDFD; - } - + if want_clone3_pidfd && HAS_CLONE3.load(Ordering::Relaxed) { let mut args = clone_args { - flags, + flags: CLONE_PIDFD, pidfd: &mut pidfd as *mut pid_t as u64, child_tid: 0, parent_tid: 0, @@ -339,9 +334,19 @@ impl Command { let mut set = MaybeUninit::::uninit(); cvt(sigemptyset(set.as_mut_ptr()))?; cvt(libc::pthread_sigmask(libc::SIG_SETMASK, set.as_ptr(), ptr::null_mut()))?; - let ret = sys::signal(libc::SIGPIPE, libc::SIG_DFL); - if ret == libc::SIG_ERR { - return Err(io::Error::last_os_error()); + + #[cfg(target_os = "android")] // see issue #88585 + { + let mut action: libc::sigaction = mem::zeroed(); + action.sa_sigaction = libc::SIG_DFL; + cvt(libc::sigaction(libc::SIGPIPE, &action, ptr::null_mut()))?; + } + #[cfg(not(target_os = "android"))] + { + let ret = sys::signal(libc::SIGPIPE, libc::SIG_DFL); + if ret == libc::SIG_ERR { + return Err(io::Error::last_os_error()); + } } } @@ -558,8 +563,7 @@ impl Process { use crate::os::unix::io::FromRawFd; use crate::sys_common::FromInner; // Safety: If `pidfd` is nonnegative, we assume it's valid and otherwise unowned. - let pidfd = (pidfd >= 0) - .then(|| PidFd::from_inner(unsafe { sys::fd::FileDesc::from_raw_fd(pidfd) })); + let pidfd = (pidfd >= 0).then(|| PidFd::from_inner(sys::fd::FileDesc::from_raw_fd(pidfd))); Process { pid, status: None, pidfd } } @@ -613,9 +617,15 @@ impl Process { } /// Unix exit statuses -#[derive(PartialEq, Eq, Clone, Copy, Debug)] +#[derive(PartialEq, Eq, Clone, Copy)] pub struct ExitStatus(c_int); +impl fmt::Debug for ExitStatus { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("unix_wait_status").field(&self.0).finish() + } +} + impl ExitStatus { pub fn new(status: c_int) -> ExitStatus { ExitStatus(status) @@ -689,7 +699,7 @@ impl fmt::Display for ExitStatus { } } -#[derive(PartialEq, Eq, Clone, Copy, Debug)] +#[derive(PartialEq, Eq, Clone, Copy)] pub struct ExitStatusError(NonZero_c_int); impl Into for ExitStatusError { @@ -698,6 +708,12 @@ impl Into for ExitStatusError { } } +impl fmt::Debug for ExitStatusError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("unix_wait_status").field(&self.0).finish() + } +} + impl ExitStatusError { pub fn code(self) -> Option { ExitStatus(self.0.into()).code().map(|st| st.try_into().unwrap()) diff --git a/library/std/src/sys/unix/process/zircon.rs b/library/std/src/sys/unix/process/zircon.rs index 58427bb8b6..4dfa2b4ff1 100644 --- a/library/std/src/sys/unix/process/zircon.rs +++ b/library/std/src/sys/unix/process/zircon.rs @@ -25,9 +25,12 @@ pub const ZX_TASK_TERMINATED: zx_signals_t = ZX_OBJECT_SIGNAL_3; pub const ZX_RIGHT_SAME_RIGHTS: zx_rights_t = 1 << 31; +// The upper four bits gives the minor version. pub type zx_object_info_topic_t = u32; -pub const ZX_INFO_PROCESS: zx_object_info_topic_t = 3; +pub const ZX_INFO_PROCESS: zx_object_info_topic_t = 3 | (1 << 28); + +pub type zx_info_process_flags_t = u32; pub fn zx_cvt(t: T) -> io::Result where @@ -68,9 +71,9 @@ impl Drop for Handle { #[repr(C)] pub struct zx_info_process_t { pub return_code: i64, - pub started: bool, - pub exited: bool, - pub debugger_attached: bool, + pub start_time: zx_time_t, + pub flags: zx_info_process_flags_t, + pub reserved1: u32, } extern "C" { diff --git a/library/std/src/sys/unix/stack_overflow.rs b/library/std/src/sys/unix/stack_overflow.rs index e8747e39bc..db1a2a26a8 100644 --- a/library/std/src/sys/unix/stack_overflow.rs +++ b/library/std/src/sys/unix/stack_overflow.rs @@ -143,14 +143,15 @@ mod imp { } unsafe fn get_stackp() -> *mut libc::c_void { - let stackp = mmap( - ptr::null_mut(), - SIGSTKSZ + page_size(), - PROT_READ | PROT_WRITE, - MAP_PRIVATE | MAP_ANON, - -1, - 0, - ); + // OpenBSD requires this flag for stack mapping + // otherwise the said mapping will fail as a no-op on most systems + // and has a different meaning on FreeBSD + #[cfg(any(target_os = "openbsd", target_os = "netbsd", target_os = "linux",))] + let flags = MAP_PRIVATE | MAP_ANON | libc::MAP_STACK; + #[cfg(not(any(target_os = "openbsd", target_os = "netbsd", target_os = "linux",)))] + let flags = MAP_PRIVATE | MAP_ANON; + let stackp = + mmap(ptr::null_mut(), SIGSTKSZ + page_size(), PROT_READ | PROT_WRITE, flags, -1, 0); if stackp == MAP_FAILED { panic!("failed to allocate an alternative stack: {}", io::Error::last_os_error()); } diff --git a/library/std/src/sys/unix/thread.rs b/library/std/src/sys/unix/thread.rs index 133ad3ea42..6f4863057a 100644 --- a/library/std/src/sys/unix/thread.rs +++ b/library/std/src/sys/unix/thread.rs @@ -263,7 +263,7 @@ impl Drop for Thread { } } -pub fn available_concurrency() -> io::Result { +pub fn available_parallelism() -> io::Result { cfg_if::cfg_if! { if #[cfg(any( target_os = "android", @@ -338,8 +338,21 @@ pub fn available_concurrency() -> io::Result { } Ok(unsafe { NonZeroUsize::new_unchecked(cpus as usize) }) + } else if #[cfg(target_os = "haiku")] { + // system_info cpu_count field gets the static data set at boot time with `smp_set_num_cpus` + // `get_system_info` calls then `smp_get_num_cpus` + unsafe { + let mut sinfo: libc::system_info = crate::mem::zeroed(); + let res = libc::get_system_info(&mut sinfo); + + if res != libc::B_OK { + return Err(io::Error::new_const(io::ErrorKind::NotFound, &"The number of hardware threads is not known for the target platform")); + } + + Ok(NonZeroUsize::new_unchecked(sinfo.cpu_count as usize)) + } } else { - // FIXME: implement on vxWorks, Redox, Haiku, l4re + // FIXME: implement on vxWorks, Redox, l4re Err(io::Error::new_const(io::ErrorKind::Unsupported, &"Getting the number of hardware threads is not supported on the target platform")) } } @@ -581,7 +594,8 @@ pub mod guard { Some(stackaddr - guardsize..stackaddr) } else if cfg!(all(target_os = "linux", target_env = "musl")) { Some(stackaddr - guardsize..stackaddr) - } else if cfg!(all(target_os = "linux", target_env = "gnu")) { + } else if cfg!(all(target_os = "linux", any(target_env = "gnu", target_env = "uclibc"))) + { // glibc used to include the guard area within the stack, as noted in the BUGS // section of `man pthread_attr_getguardsize`. This has been corrected starting // with glibc 2.27, and in some distro backports, so the guard is now placed at the diff --git a/library/std/src/sys/unix/time.rs b/library/std/src/sys/unix/time.rs index 7dc09add27..824283ef6c 100644 --- a/library/std/src/sys/unix/time.rs +++ b/library/std/src/sys/unix/time.rs @@ -303,6 +303,7 @@ mod inner { pub fn actually_monotonic() -> bool { (cfg!(target_os = "linux") && cfg!(target_arch = "x86_64")) || (cfg!(target_os = "linux") && cfg!(target_arch = "x86")) + || (cfg!(target_os = "linux") && cfg!(target_arch = "aarch64")) || cfg!(target_os = "fuchsia") } diff --git a/library/std/src/sys/unsupported/thread.rs b/library/std/src/sys/unsupported/thread.rs index dc75d4ee67..a8db251de2 100644 --- a/library/std/src/sys/unsupported/thread.rs +++ b/library/std/src/sys/unsupported/thread.rs @@ -31,7 +31,7 @@ impl Thread { } } -pub fn available_concurrency() -> io::Result { +pub fn available_parallelism() -> io::Result { unsupported() } diff --git a/library/std/src/sys/wasi/thread.rs b/library/std/src/sys/wasi/thread.rs index 9ec02bbec2..2e4e474c44 100644 --- a/library/std/src/sys/wasi/thread.rs +++ b/library/std/src/sys/wasi/thread.rs @@ -64,7 +64,7 @@ impl Thread { } } -pub fn available_concurrency() -> io::Result { +pub fn available_parallelism() -> io::Result { unsupported() } diff --git a/library/std/src/sys/wasm/atomics/thread.rs b/library/std/src/sys/wasm/atomics/thread.rs index a66ab08375..16418a0622 100644 --- a/library/std/src/sys/wasm/atomics/thread.rs +++ b/library/std/src/sys/wasm/atomics/thread.rs @@ -40,7 +40,7 @@ impl Thread { pub fn join(self) {} } -pub fn available_concurrency() -> io::Result { +pub fn available_parallelism() -> io::Result { unsupported() } diff --git a/library/std/src/sys/windows/c.rs b/library/std/src/sys/windows/c.rs index 6fb850d182..e5c550802a 100644 --- a/library/std/src/sys/windows/c.rs +++ b/library/std/src/sys/windows/c.rs @@ -262,6 +262,8 @@ pub const STACK_SIZE_PARAM_IS_A_RESERVATION: DWORD = 0x00010000; pub const STATUS_SUCCESS: NTSTATUS = 0x00000000; +pub const BCRYPT_USE_SYSTEM_PREFERRED_RNG: DWORD = 0x00000002; + #[repr(C)] #[cfg(not(target_pointer_width = "64"))] pub struct WSADATA { @@ -678,10 +680,6 @@ if #[cfg(not(target_vendor = "uwp"))] { #[link(name = "advapi32")] extern "system" { - // Forbidden when targeting UWP - #[link_name = "SystemFunction036"] - pub fn RtlGenRandom(RandomBuffer: *mut u8, RandomBufferLength: ULONG) -> BOOLEAN; - // Allowed but unused by UWP pub fn OpenProcessToken( ProcessHandle: HANDLE, @@ -743,8 +741,6 @@ if #[cfg(not(target_vendor = "uwp"))] { // UWP specific functions & types cfg_if::cfg_if! { if #[cfg(target_vendor = "uwp")] { - pub const BCRYPT_USE_SYSTEM_PREFERRED_RNG: DWORD = 0x00000002; - #[repr(C)] pub struct FILE_STANDARD_INFO { pub AllocationSize: LARGE_INTEGER, @@ -754,15 +750,6 @@ if #[cfg(target_vendor = "uwp")] { pub Directory: BOOLEAN, } - #[link(name = "bcrypt")] - extern "system" { - pub fn BCryptGenRandom( - hAlgorithm: LPVOID, - pBuffer: *mut u8, - cbBuffer: ULONG, - dwFlags: ULONG, - ) -> LONG; - } #[link(name = "kernel32")] extern "system" { pub fn GetFileInformationByHandleEx( @@ -1085,6 +1072,18 @@ extern "system" { ) -> c_int; } +#[link(name = "bcrypt")] +extern "system" { + // >= Vista / Server 2008 + // https://docs.microsoft.com/en-us/windows/win32/api/bcrypt/nf-bcrypt-bcryptgenrandom + pub fn BCryptGenRandom( + hAlgorithm: LPVOID, + pBuffer: *mut u8, + cbBuffer: ULONG, + dwFlags: ULONG, + ) -> NTSTATUS; +} + // Functions that aren't available on every version of Windows that we support, // but we still use them and just provide some form of a fallback implementation. compat_fn! { diff --git a/library/std/src/sys/windows/fs.rs b/library/std/src/sys/windows/fs.rs index cc137771bb..ad550a823a 100644 --- a/library/std/src/sys/windows/fs.rs +++ b/library/std/src/sys/windows/fs.rs @@ -558,7 +558,7 @@ impl IntoInner for File { impl FromInner for File { fn from_inner(handle: Handle) -> File { - File { handle: handle } + File { handle } } } @@ -672,7 +672,7 @@ impl FilePermissions { impl FileType { fn new(attrs: c::DWORD, reparse_tag: c::DWORD) -> FileType { - FileType { attributes: attrs, reparse_tag: reparse_tag } + FileType { attributes: attrs, reparse_tag } } pub fn is_dir(&self) -> bool { !self.is_symlink() && self.is_directory() diff --git a/library/std/src/sys/windows/net.rs b/library/std/src/sys/windows/net.rs index 33152cc97a..9c631e7e51 100644 --- a/library/std/src/sys/windows/net.rs +++ b/library/std/src/sys/windows/net.rs @@ -2,13 +2,13 @@ use crate::cmp; use crate::io::{self, IoSlice, IoSliceMut, Read}; +use crate::lazy::SyncOnceCell; use crate::mem; use crate::net::{Shutdown, SocketAddr}; use crate::os::windows::io::{ AsRawSocket, AsSocket, BorrowedSocket, FromRawSocket, IntoRawSocket, OwnedSocket, RawSocket, }; use crate::ptr; -use crate::sync::Once; use crate::sys; use crate::sys::c; use crate::sys_common::net; @@ -29,26 +29,31 @@ pub mod netc { pub struct Socket(OwnedSocket); -static INIT: Once = Once::new(); +static WSA_CLEANUP: SyncOnceCell i32> = SyncOnceCell::new(); /// Checks whether the Windows socket interface has been started already, and /// if not, starts it. pub fn init() { - INIT.call_once(|| unsafe { + let _ = WSA_CLEANUP.get_or_init(|| unsafe { let mut data: c::WSADATA = mem::zeroed(); let ret = c::WSAStartup( 0x202, // version 2.2 &mut data, ); assert_eq!(ret, 0); + + // Only register `WSACleanup` if `WSAStartup` is actually ever called. + // Workaround to prevent linking to `WS2_32.dll` when no network functionality is used. + // See issue #85441. + c::WSACleanup }); } pub fn cleanup() { - if INIT.is_completed() { - // only close the socket interface if it has actually been started + // only perform cleanup if network functionality was actually initialized + if let Some(cleanup) = WSA_CLEANUP.get() { unsafe { - c::WSACleanup(); + cleanup(); } } } diff --git a/library/std/src/sys/windows/rand.rs b/library/std/src/sys/windows/rand.rs index 87ea416bf6..de73e9154b 100644 --- a/library/std/src/sys/windows/rand.rs +++ b/library/std/src/sys/windows/rand.rs @@ -2,18 +2,6 @@ use crate::io; use crate::mem; use crate::sys::c; -#[cfg(not(target_vendor = "uwp"))] -pub fn hashmap_random_keys() -> (u64, u64) { - let mut v = (0, 0); - let ret = - unsafe { c::RtlGenRandom(&mut v as *mut _ as *mut u8, mem::size_of_val(&v) as c::ULONG) }; - if ret == 0 { - panic!("couldn't generate random bytes: {}", io::Error::last_os_error()); - } - v -} - -#[cfg(target_vendor = "uwp")] pub fn hashmap_random_keys() -> (u64, u64) { use crate::ptr; diff --git a/library/std/src/sys/windows/stack_overflow.rs b/library/std/src/sys/windows/stack_overflow.rs index 755dc0a6c8..18a2a36ad2 100644 --- a/library/std/src/sys/windows/stack_overflow.rs +++ b/library/std/src/sys/windows/stack_overflow.rs @@ -9,10 +9,10 @@ impl Handler { pub unsafe fn new() -> Handler { // This API isn't available on XP, so don't panic in that case and just // pray it works out ok. - if c::SetThreadStackGuarantee(&mut 0x5000) == 0 { - if c::GetLastError() as u32 != c::ERROR_CALL_NOT_IMPLEMENTED as u32 { - panic!("failed to reserve stack space for exception handling"); - } + if c::SetThreadStackGuarantee(&mut 0x5000) == 0 + && c::GetLastError() as u32 != c::ERROR_CALL_NOT_IMPLEMENTED as u32 + { + panic!("failed to reserve stack space for exception handling"); } Handler } diff --git a/library/std/src/sys/windows/stdio.rs b/library/std/src/sys/windows/stdio.rs index 2719a530df..a4fe5f67f6 100644 --- a/library/std/src/sys/windows/stdio.rs +++ b/library/std/src/sys/windows/stdio.rs @@ -291,15 +291,25 @@ fn read_u16s(handle: c::HANDLE, buf: &mut [u16]) -> io::Result { }; let mut amount = 0; - cvt(unsafe { - c::ReadConsoleW( - handle, - buf.as_mut_ptr() as c::LPVOID, - buf.len() as u32, - &mut amount, - &mut input_control as c::PCONSOLE_READCONSOLE_CONTROL, - ) - })?; + loop { + cvt(unsafe { + c::SetLastError(0); + c::ReadConsoleW( + handle, + buf.as_mut_ptr() as c::LPVOID, + buf.len() as u32, + &mut amount, + &mut input_control as c::PCONSOLE_READCONSOLE_CONTROL, + ) + })?; + + // ReadConsoleW returns success with ERROR_OPERATION_ABORTED for Ctrl-C or Ctrl-Break. + // Explicitly check for that case here and try again. + if amount == 0 && unsafe { c::GetLastError() } == c::ERROR_OPERATION_ABORTED { + continue; + } + break; + } if amount > 0 && buf[amount as usize - 1] == CTRL_Z { amount -= 1; diff --git a/library/std/src/sys/windows/thread.rs b/library/std/src/sys/windows/thread.rs index a5293133b3..75f70c2076 100644 --- a/library/std/src/sys/windows/thread.rs +++ b/library/std/src/sys/windows/thread.rs @@ -100,7 +100,7 @@ impl Thread { } } -pub fn available_concurrency() -> io::Result { +pub fn available_parallelism() -> io::Result { let res = unsafe { let mut sysinfo: c::SYSTEM_INFO = crate::mem::zeroed(); c::GetSystemInfo(&mut sysinfo); diff --git a/library/std/src/sys_common/backtrace.rs b/library/std/src/sys_common/backtrace.rs index e6a099f0e8..d5e8f12414 100644 --- a/library/std/src/sys_common/backtrace.rs +++ b/library/std/src/sys_common/backtrace.rs @@ -93,10 +93,8 @@ unsafe fn _print_fmt(fmt: &mut fmt::Formatter<'_>, print_fmt: PrintFmt) -> fmt:: if stop { return false; } - if !hit { - if start { - res = bt_fmt.frame().print_raw(frame.ip(), None, None, None); - } + if !hit && start { + res = bt_fmt.frame().print_raw(frame.ip(), None, None, None); } idx += 1; diff --git a/library/std/src/sys_common/mod.rs b/library/std/src/sys_common/mod.rs index 894440564b..5a5913ebd7 100644 --- a/library/std/src/sys_common/mod.rs +++ b/library/std/src/sys_common/mod.rs @@ -28,8 +28,6 @@ pub mod memchr; pub mod mutex; pub mod process; pub mod remutex; -#[macro_use] -pub mod rt; pub mod rwlock; pub mod thread; pub mod thread_info; diff --git a/library/std/src/sys_common/process.rs b/library/std/src/sys_common/process.rs index 38007d5c41..3d71219756 100644 --- a/library/std/src/sys_common/process.rs +++ b/library/std/src/sys_common/process.rs @@ -106,13 +106,13 @@ impl CommandEnv { /// This struct is created by /// [`Command::get_envs`][crate::process::Command::get_envs]. See its /// documentation for more. -#[unstable(feature = "command_access", issue = "44434")] +#[stable(feature = "command_access", since = "1.57.0")] #[derive(Debug)] pub struct CommandEnvs<'a> { iter: crate::collections::btree_map::Iter<'a, EnvKey, Option>, } -#[unstable(feature = "command_access", issue = "44434")] +#[stable(feature = "command_access", since = "1.57.0")] impl<'a> Iterator for CommandEnvs<'a> { type Item = (&'a OsStr, Option<&'a OsStr>); fn next(&mut self) -> Option { @@ -123,7 +123,7 @@ impl<'a> Iterator for CommandEnvs<'a> { } } -#[unstable(feature = "command_access", issue = "44434")] +#[stable(feature = "command_access", since = "1.57.0")] impl<'a> ExactSizeIterator for CommandEnvs<'a> { fn len(&self) -> usize { self.iter.len() diff --git a/library/std/src/sys_common/rt.rs b/library/std/src/sys_common/rt.rs deleted file mode 100644 index 02013ecc4c..0000000000 --- a/library/std/src/sys_common/rt.rs +++ /dev/null @@ -1,81 +0,0 @@ -#![deny(unsafe_op_in_unsafe_fn)] -#![allow(unused_macros)] - -use crate::sync::Once; -use crate::sys; -use crate::sys_common::thread_info; -use crate::thread::Thread; - -// One-time runtime initialization. -// Runs before `main`. -// SAFETY: must be called only once during runtime initialization. -// NOTE: this is not guaranteed to run, for example when Rust code is called externally. -#[cfg_attr(test, allow(dead_code))] -pub unsafe fn init(argc: isize, argv: *const *const u8) { - unsafe { - sys::init(argc, argv); - - let main_guard = sys::thread::guard::init(); - // Next, set up the current Thread with the guard information we just - // created. Note that this isn't necessary in general for new threads, - // but we just do this to name the main thread and to give it correct - // info about the stack bounds. - let thread = Thread::new(Some("main".to_owned())); - thread_info::set(main_guard, thread); - } -} - -// One-time runtime cleanup. -// Runs after `main` or at program exit. -// NOTE: this is not guaranteed to run, for example when the program aborts. -#[cfg_attr(test, allow(dead_code))] -pub fn cleanup() { - static CLEANUP: Once = Once::new(); - CLEANUP.call_once(|| unsafe { - // Flush stdout and disable buffering. - crate::io::cleanup(); - // SAFETY: Only called once during runtime cleanup. - sys::cleanup(); - }); -} - -// Prints to the "panic output", depending on the platform this may be: -// - the standard error output -// - some dedicated platform specific output -// - nothing (so this macro is a no-op) -macro_rules! rtprintpanic { - ($($t:tt)*) => { - if let Some(mut out) = crate::sys::stdio::panic_output() { - let _ = crate::io::Write::write_fmt(&mut out, format_args!($($t)*)); - } - } -} - -macro_rules! rtabort { - ($($t:tt)*) => { - { - rtprintpanic!("fatal runtime error: {}\n", format_args!($($t)*)); - crate::sys::abort_internal(); - } - } -} - -macro_rules! rtassert { - ($e:expr) => { - if !$e { - rtabort!(concat!("assertion failed: ", stringify!($e))); - } - }; -} - -macro_rules! rtunwrap { - ($ok:ident, $e:expr) => { - match $e { - $ok(v) => v, - ref err => { - let err = err.as_ref().map(drop); // map Ok/Some which might not be Debug - rtabort!(concat!("unwrap failed: ", stringify!($e), " = {:?}"), err) - } - } - }; -} diff --git a/library/std/src/sys_common/thread_info.rs b/library/std/src/sys_common/thread_info.rs index f09d16c33e..38c9e50009 100644 --- a/library/std/src/sys_common/thread_info.rs +++ b/library/std/src/sys_common/thread_info.rs @@ -1,4 +1,5 @@ #![allow(dead_code)] // stack_guard isn't used right now on all platforms +#![allow(unused_unsafe)] // thread_local with `const {}` triggers this liny use crate::cell::RefCell; use crate::sys::thread::guard::Guard; @@ -9,7 +10,7 @@ struct ThreadInfo { thread: Thread, } -thread_local! { static THREAD_INFO: RefCell> = RefCell::new(None) } +thread_local! { static THREAD_INFO: RefCell> = const { RefCell::new(None) } } impl ThreadInfo { fn with(f: F) -> Option @@ -17,12 +18,13 @@ impl ThreadInfo { F: FnOnce(&mut ThreadInfo) -> R, { THREAD_INFO - .try_with(move |c| { - if c.borrow().is_none() { - *c.borrow_mut() = - Some(ThreadInfo { stack_guard: None, thread: Thread::new(None) }) - } - f(c.borrow_mut().as_mut().unwrap()) + .try_with(move |thread_info| { + let mut thread_info = thread_info.borrow_mut(); + let thread_info = thread_info.get_or_insert_with(|| ThreadInfo { + stack_guard: None, + thread: Thread::new(None), + }); + f(thread_info) }) .ok() } @@ -37,10 +39,9 @@ pub fn stack_guard() -> Option { } pub fn set(stack_guard: Option, thread: Thread) { - THREAD_INFO.with(|c| assert!(c.borrow().is_none())); - THREAD_INFO.with(move |c| *c.borrow_mut() = Some(ThreadInfo { stack_guard, thread })); -} - -pub fn reset_guard(stack_guard: Option) { - THREAD_INFO.with(move |c| c.borrow_mut().as_mut().unwrap().stack_guard = stack_guard); + THREAD_INFO.with(move |thread_info| { + let mut thread_info = thread_info.borrow_mut(); + rtassert!(thread_info.is_none()); + *thread_info = Some(ThreadInfo { stack_guard, thread }); + }); } diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs index f44df845bf..b2aa500a0f 100644 --- a/library/std/src/thread/mod.rs +++ b/library/std/src/thread/mod.rs @@ -412,9 +412,9 @@ impl Builder { /// /// # Safety /// - /// The caller has to ensure that no references in the supplied thread closure - /// or its return type can outlive the spawned thread's lifetime. This can be - /// guaranteed in two ways: + /// The caller has to ensure that the spawned thread does not outlive any + /// references in the supplied thread closure and its return type. + /// This can be guaranteed in two ways: /// /// - ensure that [`join`][`JoinHandle::join`] is called before any referenced /// data is dropped @@ -457,7 +457,9 @@ impl Builder { let stack_size = stack_size.unwrap_or_else(thread::min_stack); - let my_thread = Thread::new(name); + let my_thread = Thread::new(name.map(|name| { + CString::new(name).expect("thread name may not contain interior null bytes") + })); let their_thread = my_thread.clone(); let my_packet: Arc>>> = Arc::new(UnsafeCell::new(None)); @@ -1029,6 +1031,7 @@ impl ThreadId { /// value is entirely opaque -- only equality testing is stable. Note that /// it is not guaranteed which values new threads will return, and this may /// change across Rust versions. + #[must_use] #[unstable(feature = "thread_id_value", issue = "67939")] pub fn as_u64(&self) -> NonZeroU64 { self.0 @@ -1073,12 +1076,8 @@ pub struct Thread { impl Thread { // Used only internally to construct a thread object without spawning // Panics if the name contains nuls. - pub(crate) fn new(name: Option) -> Thread { - let cname = - name.map(|n| CString::new(n).expect("thread name may not contain interior null bytes")); - Thread { - inner: Arc::new(Inner { name: cname, id: ThreadId::new(), parker: Parker::new() }), - } + pub(crate) fn new(name: Option) -> Thread { + Thread { inner: Arc::new(Inner { name, id: ThreadId::new(), parker: Parker::new() }) } } /// Atomically makes the handle's token available if it is not already. @@ -1429,38 +1428,77 @@ fn _assert_sync_and_send() { _assert_both::(); } -/// Returns the number of hardware threads available to the program. +/// Returns an estimate of the default amount of parallelism a program should use. /// -/// This value should be considered only a hint. +/// Parallelism is a resource. A given machine provides a certain capacity for +/// parallelism, i.e., a bound on the number of computations it can perform +/// simultaneously. This number often corresponds to the amount of CPUs or +/// computer has, but it may diverge in various cases. /// -/// # Platform-specific behavior +/// Host environments such as VMs or container orchestrators may want to +/// restrict the amount of parallelism made available to programs in them. This +/// is often done to limit the potential impact of (unintentionally) +/// resource-intensive programs on other programs running on the same machine. /// -/// If interpreted as the number of actual hardware threads, it may undercount on -/// Windows systems with more than 64 hardware threads. If interpreted as the -/// available concurrency for that process, it may overcount on Windows systems -/// when limited by a process wide affinity mask or job object limitations, and -/// it may overcount on Linux systems when limited by a process wide affinity -/// mask or affected by cgroups limits. +/// # Limitations +/// +/// The purpose of this API is to provide an easy and portable way to query +/// the default amount of parallelism the program should use. Among other things it +/// does not expose information on NUMA regions, does not account for +/// differences in (co)processor capabilities, and will not modify the program's +/// global state in order to more accurately query the amount of available +/// parallelism. +/// +/// 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 +/// parallelism available to the program, you may wish to use +/// platform-specific APIs as well. The following platform limitations currently +/// apply to `available_parallelism`: +/// +/// On Windows: +/// - It may undercount the amount of parallelism available on systems with more +/// than 64 logical CPUs. However, programs typically need specific support to +/// take advantage of more than 64 logical CPUs, and in the absence of such +/// support, the number returned by this function accurately reflects the +/// number of logical CPUs the program can use by default. +/// - It may overcount the amount of parallelism available on systems limited by +/// process-wide affinity masks, or job object limitations. +/// +/// On Linux: +/// - It may overcount the amount of parallelism available when limited by a +/// process-wide affinity mask, or when affected by cgroup limits. +/// +/// On all targets: +/// - It may overcount the amount of parallelism available when running in a VM +/// with CPU usage limits (e.g. an overcommitted host). /// /// # Errors /// -/// This function will return an error in the following situations, but is not -/// limited to just these cases: +/// This function will, but is not limited to, return errors in the following +/// cases: /// -/// - If the number of hardware threads is not known for the target platform. -/// - The process lacks permissions to view the number of hardware threads -/// available. +/// - If the amount of parallelism is not known for the target platform. +/// - If the program lacks permission to query the amount of parallelism made +/// available to it. /// /// # Examples /// /// ``` /// # #![allow(dead_code)] -/// #![feature(available_concurrency)] -/// use std::thread; +/// #![feature(available_parallelism)] +/// use std::{io, thread}; /// -/// let count = thread::available_concurrency().map(|n| n.get()).unwrap_or(1); +/// fn main() -> io::Result<()> { +/// let count = thread::available_parallelism()?.get(); +/// assert!(count >= 1_usize); +/// Ok(()) +/// } /// ``` -#[unstable(feature = "available_concurrency", issue = "74479")] -pub fn available_concurrency() -> io::Result { - imp::available_concurrency() +#[doc(alias = "available_concurrency")] // Alias for a previous name we gave this API on unstable. +#[doc(alias = "hardware_concurrency")] // Alias for C++ `std::thread::hardware_concurrency`. +#[doc(alias = "num_cpus")] // Alias for a popular ecosystem crate which provides similar functionality. +#[unstable(feature = "available_parallelism", issue = "74479")] +pub fn available_parallelism() -> io::Result { + imp::available_parallelism() } diff --git a/library/std/src/time.rs b/library/std/src/time.rs index e9207ee361..3e27e3a429 100644 --- a/library/std/src/time.rs +++ b/library/std/src/time.rs @@ -44,6 +44,9 @@ use crate::sys_common::FromInner; #[stable(feature = "time", since = "1.3.0")] pub use core::time::Duration; +#[unstable(feature = "duration_checked_float", issue = "83400")] +pub use core::time::FromSecsError; + /// A measurement of a monotonically nondecreasing clock. /// Opaque and useful only with [`Duration`]. /// @@ -105,6 +108,7 @@ pub use core::time::Duration; /// | UNIX | [clock_gettime (Monotonic Clock)] | /// | Darwin | [mach_absolute_time] | /// | VXWorks | [clock_gettime (Monotonic Clock)] | +/// | SOLID | `get_tim` | /// | WASI | [__wasi_clock_time_get (Monotonic Clock)] | /// | Windows | [QueryPerformanceCounter] | /// @@ -181,6 +185,7 @@ pub struct Instant(time::Instant); /// | UNIX | [clock_gettime (Realtime Clock)] | /// | Darwin | [gettimeofday] | /// | VXWorks | [clock_gettime (Realtime Clock)] | +/// | SOLID | `SOLID_RTC_ReadTime` | /// | WASI | [__wasi_clock_time_get (Realtime Clock)] | /// | Windows | [GetSystemTimePreciseAsFileTime] / [GetSystemTimeAsFileTime] | /// @@ -263,6 +268,20 @@ impl Instant { // // To hopefully mitigate the impact of this, a few platforms are // excluded as "these at least haven't gone backwards yet". + // + // While issues have been seen on arm64 platforms the Arm architecture + // requires that the counter monotonically increases and that it must + // provide a uniform view of system time (e.g. it must not be possible + // for a core to recieve a message from another core with a time stamp + // and observe time going backwards (ARM DDI 0487G.b D11.1.2). While + // there have been a few 64bit SoCs that have bugs which cause time to + // not monoticially increase, these have been fixed in the Linux kernel + // and we shouldn't penalize all Arm SoCs for those who refuse to + // update their kernels: + // SUN50I_ERRATUM_UNKNOWN1 - Allwinner A64 / Pine A64 - fixed in 5.1 + // FSL_ERRATUM_A008585 - Freescale LS2080A/LS1043A - fixed in 4.10 + // HISILICON_ERRATUM_161010101 - Hisilicon 1610 - fixed in 4.11 + // ARM64_ERRATUM_858921 - Cortex A73 - fixed in 4.12 if time::Instant::actually_monotonic() { return Instant(os_now); } @@ -469,7 +488,7 @@ impl SystemTime { /// as the system clock being adjusted either forwards or backwards). /// [`Instant`] can be used to measure elapsed time without this risk of failure. /// - /// If successful, [`Ok`]`(`[`Duration`]`)` is returned where the duration represents + /// If successful, [Ok]\([Duration]) is returned where the duration represents /// the amount of time elapsed from the specified measurement to this one. /// /// Returns an [`Err`] if `earlier` is later than `self`, and the error @@ -496,7 +515,7 @@ impl SystemTime { /// /// This function may fail as the underlying system clock is susceptible to /// drift and updates (e.g., the system clock could go backwards), so this - /// function might not always succeed. If successful, [`Ok`]`(`[`Duration`]`)` is + /// function might not always succeed. If successful, [Ok]\([Duration]) is /// returned where the duration represents the amount of time elapsed from /// this time measurement to the current time. /// diff --git a/library/std/src/time/monotonic.rs b/library/std/src/time/monotonic.rs index fa96b7abff..64f16245c2 100644 --- a/library/std/src/time/monotonic.rs +++ b/library/std/src/time/monotonic.rs @@ -5,7 +5,7 @@ pub(super) fn monotonize(raw: time::Instant) -> time::Instant { inner::monotonize(raw) } -#[cfg(all(target_has_atomic = "64", not(target_has_atomic = "128")))] +#[cfg(any(all(target_has_atomic = "64", not(target_has_atomic = "128")), target_arch = "aarch64"))] pub mod inner { use crate::sync::atomic::AtomicU64; use crate::sync::atomic::Ordering::*; @@ -37,40 +37,41 @@ pub mod inner { // This could be a problem for programs that call instants at intervals greater // than 68 years. Interstellar probes may want to ensure that actually_monotonic() is true. let packed = (secs << 32) | nanos; - let old = mono.load(Relaxed); - - if old == UNINITIALIZED || packed.wrapping_sub(old) < u64::MAX / 2 { - mono.store(packed, Relaxed); - raw - } else { - // Backslide occurred. We reconstruct monotonized time from the upper 32 bit of the - // passed in value and the 64bits loaded from the atomic - let seconds_lower = old >> 32; - let mut seconds_upper = secs & 0xffff_ffff_0000_0000; - if secs & 0xffff_ffff > seconds_lower { - // Backslide caused the lower 32bit of the seconds part to wrap. - // This must be the case because the seconds part is larger even though - // we are in the backslide branch, i.e. the seconds count should be smaller or equal. - // - // We assume that backslides are smaller than 2^32 seconds - // which means we need to add 1 to the upper half to restore it. - // - // Example: - // most recent observed time: 0xA1_0000_0000_0000_0000u128 - // bits stored in AtomicU64: 0x0000_0000_0000_0000u64 - // backslide by 1s - // caller time is 0xA0_ffff_ffff_0000_0000u128 - // -> we can fix up the upper half time by adding 1 << 32 - seconds_upper = seconds_upper.wrapping_add(0x1_0000_0000); + let updated = mono.fetch_update(Relaxed, Relaxed, |old| { + (old == UNINITIALIZED || packed.wrapping_sub(old) < u64::MAX / 2).then_some(packed) + }); + match updated { + Ok(_) => raw, + Err(newer) => { + // Backslide occurred. We reconstruct monotonized time from the upper 32 bit of the + // passed in value and the 64bits loaded from the atomic + let seconds_lower = newer >> 32; + let mut seconds_upper = secs & 0xffff_ffff_0000_0000; + if secs & 0xffff_ffff > seconds_lower { + // Backslide caused the lower 32bit of the seconds part to wrap. + // This must be the case because the seconds part is larger even though + // we are in the backslide branch, i.e. the seconds count should be smaller or equal. + // + // We assume that backslides are smaller than 2^32 seconds + // which means we need to add 1 to the upper half to restore it. + // + // Example: + // most recent observed time: 0xA1_0000_0000_0000_0000u128 + // bits stored in AtomicU64: 0x0000_0000_0000_0000u64 + // backslide by 1s + // caller time is 0xA0_ffff_ffff_0000_0000u128 + // -> we can fix up the upper half time by adding 1 << 32 + seconds_upper = seconds_upper.wrapping_add(0x1_0000_0000); + } + let secs = seconds_upper | seconds_lower; + let nanos = newer as u32; + ZERO.checked_add_duration(&Duration::new(secs, nanos)).unwrap() } - let secs = seconds_upper | seconds_lower; - let nanos = old as u32; - ZERO.checked_add_duration(&Duration::new(secs, nanos)).unwrap() } } } -#[cfg(target_has_atomic = "128")] +#[cfg(all(target_has_atomic = "128", not(target_arch = "aarch64")))] pub mod inner { use crate::sync::atomic::AtomicU128; use crate::sync::atomic::Ordering::*; diff --git a/library/stdarch/.github/workflows/main.yml b/library/stdarch/.github/workflows/main.yml index c7cec5a858..516ddd49f4 100644 --- a/library/stdarch/.github/workflows/main.yml +++ b/library/stdarch/.github/workflows/main.yml @@ -138,9 +138,8 @@ jobs: norun: true - target: aarch64-unknown-linux-gnu os: ubuntu-latest - # Temporarily disabled because otool crashes with "Out of memory", seems Github CI issue - #- target: x86_64-apple-darwin - # os: macos-latest + - target: x86_64-apple-darwin + os: macos-11 - target: x86_64-pc-windows-msvc os: windows-latest - target: i686-pc-windows-msvc diff --git a/library/stdarch/Cargo.toml b/library/stdarch/Cargo.toml index 73f69ca46f..6efd6b189a 100644 --- a/library/stdarch/Cargo.toml +++ b/library/stdarch/Cargo.toml @@ -4,6 +4,7 @@ members = [ "crates/core_arch", "crates/std_detect", "crates/stdarch-gen", + "crates/intrinsic-test", "examples/" ] exclude = [ diff --git a/library/stdarch/ci/docker/aarch64-unknown-linux-gnu/Dockerfile b/library/stdarch/ci/docker/aarch64-unknown-linux-gnu/Dockerfile index 09ead2c017..2b43841907 100644 --- a/library/stdarch/ci/docker/aarch64-unknown-linux-gnu/Dockerfile +++ b/library/stdarch/ci/docker/aarch64-unknown-linux-gnu/Dockerfile @@ -1,13 +1,17 @@ FROM ubuntu:20.04 RUN apt-get update && apt-get install -y --no-install-recommends \ gcc \ + g++ \ ca-certificates \ libc6-dev \ gcc-aarch64-linux-gnu \ + g++-aarch64-linux-gnu \ libc6-dev-arm64-cross \ qemu-user \ make \ - file + file \ + clang-12 \ + lld ENV CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=aarch64-linux-gnu-gcc \ CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_RUNNER="qemu-aarch64 -L /usr/aarch64-linux-gnu" \ diff --git a/library/stdarch/ci/run-docker.sh b/library/stdarch/ci/run-docker.sh index ec9393adf2..fb47b752d5 100755 --- a/library/stdarch/ci/run-docker.sh +++ b/library/stdarch/ci/run-docker.sh @@ -9,7 +9,7 @@ run() { target=$(echo "${1}" | sed 's/-emulated//') echo "Building docker container for TARGET=${1}" docker build -t stdarch -f "ci/docker/${1}/Dockerfile" ci/ - mkdir -p target + mkdir -p target c_programs rust_programs echo "Running docker" # shellcheck disable=SC2016 docker run \ @@ -29,6 +29,8 @@ run() { --volume "$(rustc --print sysroot)":/rust:ro \ --volume "$(pwd)":/checkout:ro \ --volume "$(pwd)"/target:/checkout/target \ + --volume "$(pwd)"/c_programs:/checkout/c_programs \ + --volume "$(pwd)"/rust_programs:/checkout/rust_programs \ --init \ --workdir /checkout \ --privileged \ diff --git a/library/stdarch/ci/run.sh b/library/stdarch/ci/run.sh index 1766a37ca3..1d501492b6 100755 --- a/library/stdarch/ci/run.sh +++ b/library/stdarch/ci/run.sh @@ -10,10 +10,17 @@ set -ex #export RUST_TEST_NOCAPTURE=1 #export RUST_TEST_THREADS=1 -RUSTFLAGS="$RUSTFLAGS -D warnings " +export RUSTFLAGS="${RUSTFLAGS} -D warnings -Z merge-functions=disabled " + +export STDARCH_DISABLE_DEDUP_GUARD=1 case ${TARGET} in + # On Windows the linker performs identical COMDAT folding (ICF) by default + # in release mode which removes identical COMDAT sections. This interferes + # with our instruction assertions just like LLVM's MergeFunctions pass so + # we disable it. *-pc-windows-msvc) + export RUSTFLAGS="${RUSTFLAGS} -Clink-args=/OPT:NOICF" ;; # On 32-bit use a static relocation model which avoids some extra # instructions when dealing with static data, notably allowing some @@ -65,6 +72,8 @@ cargo_test() { CORE_ARCH="--manifest-path=crates/core_arch/Cargo.toml" STD_DETECT="--manifest-path=crates/std_detect/Cargo.toml" STDARCH_EXAMPLES="--manifest-path=examples/Cargo.toml" +INTRINSIC_TEST="--manifest-path=crates/intrinsic-test/Cargo.toml" + cargo_test "${CORE_ARCH} --release" if [ "$NOSTD" != "1" ]; then @@ -111,6 +120,11 @@ case ${TARGET} in 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" +fi + if [ "$NORUN" != "1" ] && [ "$NOSTD" != 1 ]; then # Test examples ( diff --git a/library/stdarch/crates/assert-instr-macro/src/lib.rs b/library/stdarch/crates/assert-instr-macro/src/lib.rs index 5b25df7035..9fa411df3d 100644 --- a/library/stdarch/crates/assert-instr-macro/src/lib.rs +++ b/library/stdarch/crates/assert-instr-macro/src/lib.rs @@ -41,6 +41,10 @@ pub fn assert_instr( // testing for. let disable_assert_instr = std::env::var("STDARCH_DISABLE_ASSERT_INSTR").is_ok(); + // Disable dedup guard. Only works if the LLVM MergeFunctions pass is disabled, e.g. + // with `-Z merge-functions=disabled` in RUSTFLAGS. + let disable_dedup_guard = std::env::var("STDARCH_DISABLE_DEDUP_GUARD").is_ok(); + // If instruction tests are disabled avoid emitting this shim at all, just // return the original item without our attribute. if !cfg!(optimized) || disable_assert_instr { @@ -58,6 +62,10 @@ pub fn assert_instr( &format!("stdarch_test_shim_{}_{}", name, instr_str), name.span(), ); + let shim_name_ptr = syn::Ident::new( + &format!("stdarch_test_shim_{}_{}_ptr", name, instr_str).to_ascii_uppercase(), + name.span(), + ); let mut inputs = Vec::new(); let mut input_vals = Vec::new(); let mut const_vals = Vec::new(); @@ -124,34 +132,38 @@ pub fn assert_instr( syn::LitStr::new("C", proc_macro2::Span::call_site()) }; let shim_name_str = format!("{}{}", shim_name, assert_name); - let to_test = quote! { - #attrs - #[no_mangle] - #[inline(never)] - pub unsafe extern #abi fn #shim_name(#(#inputs),*) #ret { - // The compiler in optimized mode by default runs a pass called - // "mergefunc" where it'll merge functions that look identical. - // Turns out some intrinsics produce identical code and they're - // folded together, meaning that one just jumps to another. This - // messes up our inspection of the disassembly of this function and - // we're not a huge fan of that. - // - // To thwart this pass and prevent functions from being merged we - // generate some code that's hopefully very tight in terms of - // codegen but is otherwise unique to prevent code from being - // folded. - // - // This is avoided on Wasm32 right now since these functions aren't - // inlined which breaks our tests since each intrinsic looks like it - // calls functions. Turns out functions aren't similar enough to get - // merged on wasm32 anyway. This bug is tracked at - // rust-lang/rust#74320. - #[cfg(not(target_arch = "wasm32"))] - ::stdarch_test::_DONT_DEDUP.store( - std::mem::transmute(#shim_name_str.as_bytes().as_ptr()), - std::sync::atomic::Ordering::Relaxed, - ); - #name::<#(#const_vals),*>(#(#input_vals),*) + let to_test = if disable_dedup_guard { + quote! { + #attrs + #[no_mangle] + #[inline(never)] + pub unsafe extern #abi fn #shim_name(#(#inputs),*) #ret { + #name::<#(#const_vals),*>(#(#input_vals),*) + } + } + } else { + quote! { + + const #shim_name_ptr : *const u8 = #shim_name_str.as_ptr(); + + #attrs + #[no_mangle] + #[inline(never)] + pub unsafe extern #abi fn #shim_name(#(#inputs),*) #ret { + // The compiler in optimized mode by default runs a pass called + // "mergefunc" where it'll merge functions that look identical. + // Turns out some intrinsics produce identical code and they're + // folded together, meaning that one just jumps to another. This + // messes up our inspection of the disassembly of this function and + // we're not a huge fan of that. + // + // To thwart this pass and prevent functions from being merged we + // generate some code that's hopefully very tight in terms of + // codegen but is otherwise unique to prevent code from being + // folded. + ::stdarch_test::_DONT_DEDUP = #shim_name_ptr; + #name::<#(#const_vals),*>(#(#input_vals),*) + } } }; diff --git a/library/stdarch/crates/core_arch/src/aarch64/crc.rs b/library/stdarch/crates/core_arch/src/aarch64/crc.rs index c19d61ca73..6e8128534b 100644 --- a/library/stdarch/crates/core_arch/src/aarch64/crc.rs +++ b/library/stdarch/crates/core_arch/src/aarch64/crc.rs @@ -1,4 +1,4 @@ -extern "C" { +extern "unadjusted" { #[link_name = "llvm.aarch64.crc32x"] fn crc32x_(crc: u32, data: u64) -> u32; 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 28ea2592a0..d441ee562a 100644 --- a/library/stdarch/crates/core_arch/src/aarch64/neon/generated.rs +++ b/library/stdarch/crates/core_arch/src/aarch64/neon/generated.rs @@ -15,7 +15,7 @@ use stdarch_test::assert_instr; #[cfg_attr(test, assert_instr(fabd))] pub unsafe fn vabd_f64(a: float64x1_t, b: float64x1_t) -> float64x1_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fabd.v1f64")] fn vabd_f64_(a: float64x1_t, b: float64x1_t) -> float64x1_t; } @@ -28,7 +28,7 @@ pub unsafe fn vabd_f64(a: float64x1_t, b: float64x1_t) -> float64x1_t { #[cfg_attr(test, assert_instr(fabd))] pub unsafe fn vabdq_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fabd.v2f64")] fn vabdq_f64_(a: float64x2_t, b: float64x2_t) -> float64x2_t; } @@ -1084,7 +1084,7 @@ pub unsafe fn vcltzq_f64(a: float64x2_t) -> uint64x2_t { #[cfg_attr(test, assert_instr(facgt))] pub unsafe fn vcagt_f64(a: float64x1_t, b: float64x1_t) -> uint64x1_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.facgt.v1i64.v1f64")] fn vcagt_f64_(a: float64x1_t, b: float64x1_t) -> uint64x1_t; } @@ -1097,7 +1097,7 @@ pub unsafe fn vcagt_f64(a: float64x1_t, b: float64x1_t) -> uint64x1_t { #[cfg_attr(test, assert_instr(facgt))] pub unsafe fn vcagtq_f64(a: float64x2_t, b: float64x2_t) -> uint64x2_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.facgt.v2i64.v2f64")] fn vcagtq_f64_(a: float64x2_t, b: float64x2_t) -> uint64x2_t; } @@ -1110,7 +1110,7 @@ pub unsafe fn vcagtq_f64(a: float64x2_t, b: float64x2_t) -> uint64x2_t { #[cfg_attr(test, assert_instr(facge))] pub unsafe fn vcage_f64(a: float64x1_t, b: float64x1_t) -> uint64x1_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.facge.v1i64.v1f64")] fn vcage_f64_(a: float64x1_t, b: float64x1_t) -> uint64x1_t; } @@ -1123,7 +1123,7 @@ pub unsafe fn vcage_f64(a: float64x1_t, b: float64x1_t) -> uint64x1_t { #[cfg_attr(test, assert_instr(facge))] pub unsafe fn vcageq_f64(a: float64x2_t, b: float64x2_t) -> uint64x2_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.facge.v2i64.v2f64")] fn vcageq_f64_(a: float64x2_t, b: float64x2_t) -> uint64x2_t; } @@ -2103,7 +2103,7 @@ pub unsafe fn vcvt_high_f32_f64(a: float32x2_t, b: float64x2_t) -> float32x4_t { #[cfg_attr(test, assert_instr(fcvtxn))] pub unsafe fn vcvtx_f32_f64(a: float64x2_t) -> float32x2_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fcvtxn.v2f32.v2f64")] fn vcvtx_f32_f64_(a: float64x2_t) -> float32x2_t; } @@ -2126,7 +2126,7 @@ pub unsafe fn vcvtx_high_f32_f64(a: float32x2_t, b: float64x2_t) -> float32x4_t pub unsafe fn vcvt_n_f64_s64(a: int64x1_t) -> float64x1_t { static_assert!(N : i32 where N >= 1 && N <= 64); #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.vcvtfxs2fp.v1f64.v1i64")] fn vcvt_n_f64_s64_(a: int64x1_t, n: i32) -> float64x1_t; } @@ -2141,7 +2141,7 @@ pub unsafe fn vcvt_n_f64_s64(a: int64x1_t) -> float64x1_t { pub unsafe fn vcvtq_n_f64_s64(a: int64x2_t) -> float64x2_t { static_assert!(N : i32 where N >= 1 && N <= 64); #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.vcvtfxs2fp.v2f64.v2i64")] fn vcvtq_n_f64_s64_(a: int64x2_t, n: i32) -> float64x2_t; } @@ -2156,7 +2156,7 @@ pub unsafe fn vcvtq_n_f64_s64(a: int64x2_t) -> float64x2_t { pub unsafe fn vcvts_n_f32_s32(a: i32) -> f32 { static_assert!(N : i32 where N >= 1 && N <= 32); #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.vcvtfxs2fp.f32.i32")] fn vcvts_n_f32_s32_(a: i32, n: i32) -> f32; } @@ -2171,7 +2171,7 @@ pub unsafe fn vcvts_n_f32_s32(a: i32) -> f32 { pub unsafe fn vcvtd_n_f64_s64(a: i64) -> f64 { static_assert!(N : i32 where N >= 1 && N <= 64); #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.vcvtfxs2fp.f64.i64")] fn vcvtd_n_f64_s64_(a: i64, n: i32) -> f64; } @@ -2186,7 +2186,7 @@ pub unsafe fn vcvtd_n_f64_s64(a: i64) -> f64 { pub unsafe fn vcvt_n_f64_u64(a: uint64x1_t) -> float64x1_t { static_assert!(N : i32 where N >= 1 && N <= 64); #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.vcvtfxu2fp.v1f64.v1i64")] fn vcvt_n_f64_u64_(a: uint64x1_t, n: i32) -> float64x1_t; } @@ -2201,7 +2201,7 @@ pub unsafe fn vcvt_n_f64_u64(a: uint64x1_t) -> float64x1_t { pub unsafe fn vcvtq_n_f64_u64(a: uint64x2_t) -> float64x2_t { static_assert!(N : i32 where N >= 1 && N <= 64); #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.vcvtfxu2fp.v2f64.v2i64")] fn vcvtq_n_f64_u64_(a: uint64x2_t, n: i32) -> float64x2_t; } @@ -2216,7 +2216,7 @@ pub unsafe fn vcvtq_n_f64_u64(a: uint64x2_t) -> float64x2_t { pub unsafe fn vcvts_n_f32_u32(a: u32) -> f32 { static_assert!(N : i32 where N >= 1 && N <= 32); #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.vcvtfxu2fp.f32.i32")] fn vcvts_n_f32_u32_(a: u32, n: i32) -> f32; } @@ -2231,7 +2231,7 @@ pub unsafe fn vcvts_n_f32_u32(a: u32) -> f32 { pub unsafe fn vcvtd_n_f64_u64(a: u64) -> f64 { static_assert!(N : i32 where N >= 1 && N <= 64); #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.vcvtfxu2fp.f64.i64")] fn vcvtd_n_f64_u64_(a: u64, n: i32) -> f64; } @@ -2246,7 +2246,7 @@ pub unsafe fn vcvtd_n_f64_u64(a: u64) -> f64 { pub unsafe fn vcvt_n_s64_f64(a: float64x1_t) -> int64x1_t { static_assert!(N : i32 where N >= 1 && N <= 64); #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.vcvtfp2fxs.v1i64.v1f64")] fn vcvt_n_s64_f64_(a: float64x1_t, n: i32) -> int64x1_t; } @@ -2261,7 +2261,7 @@ pub unsafe fn vcvt_n_s64_f64(a: float64x1_t) -> int64x1_t { pub unsafe fn vcvtq_n_s64_f64(a: float64x2_t) -> int64x2_t { static_assert!(N : i32 where N >= 1 && N <= 64); #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.vcvtfp2fxs.v2i64.v2f64")] fn vcvtq_n_s64_f64_(a: float64x2_t, n: i32) -> int64x2_t; } @@ -2276,7 +2276,7 @@ pub unsafe fn vcvtq_n_s64_f64(a: float64x2_t) -> int64x2_t { pub unsafe fn vcvts_n_s32_f32(a: f32) -> i32 { static_assert!(N : i32 where N >= 1 && N <= 32); #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.vcvtfp2fxs.i32.f32")] fn vcvts_n_s32_f32_(a: f32, n: i32) -> i32; } @@ -2291,7 +2291,7 @@ pub unsafe fn vcvts_n_s32_f32(a: f32) -> i32 { pub unsafe fn vcvtd_n_s64_f64(a: f64) -> i64 { static_assert!(N : i32 where N >= 1 && N <= 64); #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.vcvtfp2fxs.i64.f64")] fn vcvtd_n_s64_f64_(a: f64, n: i32) -> i64; } @@ -2306,7 +2306,7 @@ pub unsafe fn vcvtd_n_s64_f64(a: f64) -> i64 { pub unsafe fn vcvt_n_u64_f64(a: float64x1_t) -> uint64x1_t { static_assert!(N : i32 where N >= 1 && N <= 64); #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.vcvtfp2fxu.v1i64.v1f64")] fn vcvt_n_u64_f64_(a: float64x1_t, n: i32) -> uint64x1_t; } @@ -2321,7 +2321,7 @@ pub unsafe fn vcvt_n_u64_f64(a: float64x1_t) -> uint64x1_t { pub unsafe fn vcvtq_n_u64_f64(a: float64x2_t) -> uint64x2_t { static_assert!(N : i32 where N >= 1 && N <= 64); #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.vcvtfp2fxu.v2i64.v2f64")] fn vcvtq_n_u64_f64_(a: float64x2_t, n: i32) -> uint64x2_t; } @@ -2336,7 +2336,7 @@ pub unsafe fn vcvtq_n_u64_f64(a: float64x2_t) -> uint64x2_t { pub unsafe fn vcvts_n_u32_f32(a: f32) -> u32 { static_assert!(N : i32 where N >= 1 && N <= 32); #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.vcvtfp2fxu.i32.f32")] fn vcvts_n_u32_f32_(a: f32, n: i32) -> u32; } @@ -2351,7 +2351,7 @@ pub unsafe fn vcvts_n_u32_f32(a: f32) -> u32 { pub unsafe fn vcvtd_n_u64_f64(a: f64) -> u64 { static_assert!(N : i32 where N >= 1 && N <= 64); #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.vcvtfp2fxu.i64.f64")] fn vcvtd_n_u64_f64_(a: f64, n: i32) -> u64; } @@ -2428,7 +2428,7 @@ pub unsafe fn vcvtd_u64_f64(a: f64) -> u64 { #[cfg_attr(test, assert_instr(fcvtzs))] pub unsafe fn vcvt_s64_f64(a: float64x1_t) -> int64x1_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.fptosi.sat.v1i64.v1f64")] fn vcvt_s64_f64_(a: float64x1_t) -> int64x1_t; } @@ -2441,7 +2441,7 @@ pub unsafe fn vcvt_s64_f64(a: float64x1_t) -> int64x1_t { #[cfg_attr(test, assert_instr(fcvtzs))] pub unsafe fn vcvtq_s64_f64(a: float64x2_t) -> int64x2_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.fptosi.sat.v2i64.v2f64")] fn vcvtq_s64_f64_(a: float64x2_t) -> int64x2_t; } @@ -2454,7 +2454,7 @@ pub unsafe fn vcvtq_s64_f64(a: float64x2_t) -> int64x2_t { #[cfg_attr(test, assert_instr(fcvtzu))] pub unsafe fn vcvt_u64_f64(a: float64x1_t) -> uint64x1_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.fptoui.sat.v1i64.v1f64")] fn vcvt_u64_f64_(a: float64x1_t) -> uint64x1_t; } @@ -2467,7 +2467,7 @@ pub unsafe fn vcvt_u64_f64(a: float64x1_t) -> uint64x1_t { #[cfg_attr(test, assert_instr(fcvtzu))] pub unsafe fn vcvtq_u64_f64(a: float64x2_t) -> uint64x2_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.fptoui.sat.v2i64.v2f64")] fn vcvtq_u64_f64_(a: float64x2_t) -> uint64x2_t; } @@ -2480,7 +2480,7 @@ pub unsafe fn vcvtq_u64_f64(a: float64x2_t) -> uint64x2_t { #[cfg_attr(test, assert_instr(fcvtas))] pub unsafe fn vcvta_s32_f32(a: float32x2_t) -> int32x2_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fcvtas.v2i32.v2f32")] fn vcvta_s32_f32_(a: float32x2_t) -> int32x2_t; } @@ -2493,7 +2493,7 @@ pub unsafe fn vcvta_s32_f32(a: float32x2_t) -> int32x2_t { #[cfg_attr(test, assert_instr(fcvtas))] pub unsafe fn vcvtaq_s32_f32(a: float32x4_t) -> int32x4_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fcvtas.v4i32.v4f32")] fn vcvtaq_s32_f32_(a: float32x4_t) -> int32x4_t; } @@ -2506,7 +2506,7 @@ pub unsafe fn vcvtaq_s32_f32(a: float32x4_t) -> int32x4_t { #[cfg_attr(test, assert_instr(fcvtas))] pub unsafe fn vcvta_s64_f64(a: float64x1_t) -> int64x1_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fcvtas.v1i64.v1f64")] fn vcvta_s64_f64_(a: float64x1_t) -> int64x1_t; } @@ -2519,7 +2519,7 @@ pub unsafe fn vcvta_s64_f64(a: float64x1_t) -> int64x1_t { #[cfg_attr(test, assert_instr(fcvtas))] pub unsafe fn vcvtaq_s64_f64(a: float64x2_t) -> int64x2_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fcvtas.v2i64.v2f64")] fn vcvtaq_s64_f64_(a: float64x2_t) -> int64x2_t; } @@ -2532,7 +2532,7 @@ pub unsafe fn vcvtaq_s64_f64(a: float64x2_t) -> int64x2_t { #[cfg_attr(test, assert_instr(fcvtas))] pub unsafe fn vcvtas_s32_f32(a: f32) -> i32 { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fcvtas.i32.f32")] fn vcvtas_s32_f32_(a: f32) -> i32; } @@ -2545,7 +2545,7 @@ pub unsafe fn vcvtas_s32_f32(a: f32) -> i32 { #[cfg_attr(test, assert_instr(fcvtas))] pub unsafe fn vcvtad_s64_f64(a: f64) -> i64 { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fcvtas.i64.f64")] fn vcvtad_s64_f64_(a: f64) -> i64; } @@ -2558,7 +2558,7 @@ pub unsafe fn vcvtad_s64_f64(a: f64) -> i64 { #[cfg_attr(test, assert_instr(fcvtau))] pub unsafe fn vcvtas_u32_f32(a: f32) -> u32 { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fcvtau.i32.f32")] fn vcvtas_u32_f32_(a: f32) -> u32; } @@ -2571,7 +2571,7 @@ pub unsafe fn vcvtas_u32_f32(a: f32) -> u32 { #[cfg_attr(test, assert_instr(fcvtau))] pub unsafe fn vcvtad_u64_f64(a: f64) -> u64 { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fcvtau.i64.f64")] fn vcvtad_u64_f64_(a: f64) -> u64; } @@ -2584,7 +2584,7 @@ pub unsafe fn vcvtad_u64_f64(a: f64) -> u64 { #[cfg_attr(test, assert_instr(fcvtns))] pub unsafe fn vcvtn_s32_f32(a: float32x2_t) -> int32x2_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fcvtns.v2i32.v2f32")] fn vcvtn_s32_f32_(a: float32x2_t) -> int32x2_t; } @@ -2597,7 +2597,7 @@ pub unsafe fn vcvtn_s32_f32(a: float32x2_t) -> int32x2_t { #[cfg_attr(test, assert_instr(fcvtns))] pub unsafe fn vcvtnq_s32_f32(a: float32x4_t) -> int32x4_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fcvtns.v4i32.v4f32")] fn vcvtnq_s32_f32_(a: float32x4_t) -> int32x4_t; } @@ -2610,7 +2610,7 @@ pub unsafe fn vcvtnq_s32_f32(a: float32x4_t) -> int32x4_t { #[cfg_attr(test, assert_instr(fcvtns))] pub unsafe fn vcvtn_s64_f64(a: float64x1_t) -> int64x1_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fcvtns.v1i64.v1f64")] fn vcvtn_s64_f64_(a: float64x1_t) -> int64x1_t; } @@ -2623,7 +2623,7 @@ pub unsafe fn vcvtn_s64_f64(a: float64x1_t) -> int64x1_t { #[cfg_attr(test, assert_instr(fcvtns))] pub unsafe fn vcvtnq_s64_f64(a: float64x2_t) -> int64x2_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fcvtns.v2i64.v2f64")] fn vcvtnq_s64_f64_(a: float64x2_t) -> int64x2_t; } @@ -2636,7 +2636,7 @@ pub unsafe fn vcvtnq_s64_f64(a: float64x2_t) -> int64x2_t { #[cfg_attr(test, assert_instr(fcvtns))] pub unsafe fn vcvtns_s32_f32(a: f32) -> i32 { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fcvtns.i32.f32")] fn vcvtns_s32_f32_(a: f32) -> i32; } @@ -2649,7 +2649,7 @@ pub unsafe fn vcvtns_s32_f32(a: f32) -> i32 { #[cfg_attr(test, assert_instr(fcvtns))] pub unsafe fn vcvtnd_s64_f64(a: f64) -> i64 { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fcvtns.i64.f64")] fn vcvtnd_s64_f64_(a: f64) -> i64; } @@ -2662,7 +2662,7 @@ pub unsafe fn vcvtnd_s64_f64(a: f64) -> i64 { #[cfg_attr(test, assert_instr(fcvtms))] pub unsafe fn vcvtm_s32_f32(a: float32x2_t) -> int32x2_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fcvtms.v2i32.v2f32")] fn vcvtm_s32_f32_(a: float32x2_t) -> int32x2_t; } @@ -2675,7 +2675,7 @@ pub unsafe fn vcvtm_s32_f32(a: float32x2_t) -> int32x2_t { #[cfg_attr(test, assert_instr(fcvtms))] pub unsafe fn vcvtmq_s32_f32(a: float32x4_t) -> int32x4_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fcvtms.v4i32.v4f32")] fn vcvtmq_s32_f32_(a: float32x4_t) -> int32x4_t; } @@ -2688,7 +2688,7 @@ pub unsafe fn vcvtmq_s32_f32(a: float32x4_t) -> int32x4_t { #[cfg_attr(test, assert_instr(fcvtms))] pub unsafe fn vcvtm_s64_f64(a: float64x1_t) -> int64x1_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fcvtms.v1i64.v1f64")] fn vcvtm_s64_f64_(a: float64x1_t) -> int64x1_t; } @@ -2701,7 +2701,7 @@ pub unsafe fn vcvtm_s64_f64(a: float64x1_t) -> int64x1_t { #[cfg_attr(test, assert_instr(fcvtms))] pub unsafe fn vcvtmq_s64_f64(a: float64x2_t) -> int64x2_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fcvtms.v2i64.v2f64")] fn vcvtmq_s64_f64_(a: float64x2_t) -> int64x2_t; } @@ -2714,7 +2714,7 @@ pub unsafe fn vcvtmq_s64_f64(a: float64x2_t) -> int64x2_t { #[cfg_attr(test, assert_instr(fcvtms))] pub unsafe fn vcvtms_s32_f32(a: f32) -> i32 { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fcvtms.i32.f32")] fn vcvtms_s32_f32_(a: f32) -> i32; } @@ -2727,7 +2727,7 @@ pub unsafe fn vcvtms_s32_f32(a: f32) -> i32 { #[cfg_attr(test, assert_instr(fcvtms))] pub unsafe fn vcvtmd_s64_f64(a: f64) -> i64 { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fcvtms.i64.f64")] fn vcvtmd_s64_f64_(a: f64) -> i64; } @@ -2740,7 +2740,7 @@ pub unsafe fn vcvtmd_s64_f64(a: f64) -> i64 { #[cfg_attr(test, assert_instr(fcvtps))] pub unsafe fn vcvtp_s32_f32(a: float32x2_t) -> int32x2_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fcvtps.v2i32.v2f32")] fn vcvtp_s32_f32_(a: float32x2_t) -> int32x2_t; } @@ -2753,7 +2753,7 @@ pub unsafe fn vcvtp_s32_f32(a: float32x2_t) -> int32x2_t { #[cfg_attr(test, assert_instr(fcvtps))] pub unsafe fn vcvtpq_s32_f32(a: float32x4_t) -> int32x4_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fcvtps.v4i32.v4f32")] fn vcvtpq_s32_f32_(a: float32x4_t) -> int32x4_t; } @@ -2766,7 +2766,7 @@ pub unsafe fn vcvtpq_s32_f32(a: float32x4_t) -> int32x4_t { #[cfg_attr(test, assert_instr(fcvtps))] pub unsafe fn vcvtp_s64_f64(a: float64x1_t) -> int64x1_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fcvtps.v1i64.v1f64")] fn vcvtp_s64_f64_(a: float64x1_t) -> int64x1_t; } @@ -2779,7 +2779,7 @@ pub unsafe fn vcvtp_s64_f64(a: float64x1_t) -> int64x1_t { #[cfg_attr(test, assert_instr(fcvtps))] pub unsafe fn vcvtpq_s64_f64(a: float64x2_t) -> int64x2_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fcvtps.v2i64.v2f64")] fn vcvtpq_s64_f64_(a: float64x2_t) -> int64x2_t; } @@ -2792,7 +2792,7 @@ pub unsafe fn vcvtpq_s64_f64(a: float64x2_t) -> int64x2_t { #[cfg_attr(test, assert_instr(fcvtps))] pub unsafe fn vcvtps_s32_f32(a: f32) -> i32 { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fcvtps.i32.f32")] fn vcvtps_s32_f32_(a: f32) -> i32; } @@ -2805,7 +2805,7 @@ pub unsafe fn vcvtps_s32_f32(a: f32) -> i32 { #[cfg_attr(test, assert_instr(fcvtps))] pub unsafe fn vcvtpd_s64_f64(a: f64) -> i64 { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fcvtps.i64.f64")] fn vcvtpd_s64_f64_(a: f64) -> i64; } @@ -2818,7 +2818,7 @@ pub unsafe fn vcvtpd_s64_f64(a: f64) -> i64 { #[cfg_attr(test, assert_instr(fcvtau))] pub unsafe fn vcvta_u32_f32(a: float32x2_t) -> uint32x2_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fcvtau.v2i32.v2f32")] fn vcvta_u32_f32_(a: float32x2_t) -> uint32x2_t; } @@ -2831,7 +2831,7 @@ pub unsafe fn vcvta_u32_f32(a: float32x2_t) -> uint32x2_t { #[cfg_attr(test, assert_instr(fcvtau))] pub unsafe fn vcvtaq_u32_f32(a: float32x4_t) -> uint32x4_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fcvtau.v4i32.v4f32")] fn vcvtaq_u32_f32_(a: float32x4_t) -> uint32x4_t; } @@ -2844,7 +2844,7 @@ pub unsafe fn vcvtaq_u32_f32(a: float32x4_t) -> uint32x4_t { #[cfg_attr(test, assert_instr(fcvtau))] pub unsafe fn vcvta_u64_f64(a: float64x1_t) -> uint64x1_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fcvtau.v1i64.v1f64")] fn vcvta_u64_f64_(a: float64x1_t) -> uint64x1_t; } @@ -2857,7 +2857,7 @@ pub unsafe fn vcvta_u64_f64(a: float64x1_t) -> uint64x1_t { #[cfg_attr(test, assert_instr(fcvtau))] pub unsafe fn vcvtaq_u64_f64(a: float64x2_t) -> uint64x2_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fcvtau.v2i64.v2f64")] fn vcvtaq_u64_f64_(a: float64x2_t) -> uint64x2_t; } @@ -2870,7 +2870,7 @@ pub unsafe fn vcvtaq_u64_f64(a: float64x2_t) -> uint64x2_t { #[cfg_attr(test, assert_instr(fcvtnu))] pub unsafe fn vcvtn_u32_f32(a: float32x2_t) -> uint32x2_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fcvtnu.v2i32.v2f32")] fn vcvtn_u32_f32_(a: float32x2_t) -> uint32x2_t; } @@ -2883,7 +2883,7 @@ pub unsafe fn vcvtn_u32_f32(a: float32x2_t) -> uint32x2_t { #[cfg_attr(test, assert_instr(fcvtnu))] pub unsafe fn vcvtnq_u32_f32(a: float32x4_t) -> uint32x4_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fcvtnu.v4i32.v4f32")] fn vcvtnq_u32_f32_(a: float32x4_t) -> uint32x4_t; } @@ -2896,7 +2896,7 @@ pub unsafe fn vcvtnq_u32_f32(a: float32x4_t) -> uint32x4_t { #[cfg_attr(test, assert_instr(fcvtnu))] pub unsafe fn vcvtn_u64_f64(a: float64x1_t) -> uint64x1_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fcvtnu.v1i64.v1f64")] fn vcvtn_u64_f64_(a: float64x1_t) -> uint64x1_t; } @@ -2909,7 +2909,7 @@ pub unsafe fn vcvtn_u64_f64(a: float64x1_t) -> uint64x1_t { #[cfg_attr(test, assert_instr(fcvtnu))] pub unsafe fn vcvtnq_u64_f64(a: float64x2_t) -> uint64x2_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fcvtnu.v2i64.v2f64")] fn vcvtnq_u64_f64_(a: float64x2_t) -> uint64x2_t; } @@ -2922,7 +2922,7 @@ pub unsafe fn vcvtnq_u64_f64(a: float64x2_t) -> uint64x2_t { #[cfg_attr(test, assert_instr(fcvtnu))] pub unsafe fn vcvtns_u32_f32(a: f32) -> u32 { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fcvtnu.i32.f32")] fn vcvtns_u32_f32_(a: f32) -> u32; } @@ -2935,7 +2935,7 @@ pub unsafe fn vcvtns_u32_f32(a: f32) -> u32 { #[cfg_attr(test, assert_instr(fcvtnu))] pub unsafe fn vcvtnd_u64_f64(a: f64) -> u64 { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fcvtnu.i64.f64")] fn vcvtnd_u64_f64_(a: f64) -> u64; } @@ -2948,7 +2948,7 @@ pub unsafe fn vcvtnd_u64_f64(a: f64) -> u64 { #[cfg_attr(test, assert_instr(fcvtmu))] pub unsafe fn vcvtm_u32_f32(a: float32x2_t) -> uint32x2_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fcvtmu.v2i32.v2f32")] fn vcvtm_u32_f32_(a: float32x2_t) -> uint32x2_t; } @@ -2961,7 +2961,7 @@ pub unsafe fn vcvtm_u32_f32(a: float32x2_t) -> uint32x2_t { #[cfg_attr(test, assert_instr(fcvtmu))] pub unsafe fn vcvtmq_u32_f32(a: float32x4_t) -> uint32x4_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fcvtmu.v4i32.v4f32")] fn vcvtmq_u32_f32_(a: float32x4_t) -> uint32x4_t; } @@ -2974,7 +2974,7 @@ pub unsafe fn vcvtmq_u32_f32(a: float32x4_t) -> uint32x4_t { #[cfg_attr(test, assert_instr(fcvtmu))] pub unsafe fn vcvtm_u64_f64(a: float64x1_t) -> uint64x1_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fcvtmu.v1i64.v1f64")] fn vcvtm_u64_f64_(a: float64x1_t) -> uint64x1_t; } @@ -2987,7 +2987,7 @@ pub unsafe fn vcvtm_u64_f64(a: float64x1_t) -> uint64x1_t { #[cfg_attr(test, assert_instr(fcvtmu))] pub unsafe fn vcvtmq_u64_f64(a: float64x2_t) -> uint64x2_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fcvtmu.v2i64.v2f64")] fn vcvtmq_u64_f64_(a: float64x2_t) -> uint64x2_t; } @@ -3000,7 +3000,7 @@ pub unsafe fn vcvtmq_u64_f64(a: float64x2_t) -> uint64x2_t { #[cfg_attr(test, assert_instr(fcvtmu))] pub unsafe fn vcvtms_u32_f32(a: f32) -> u32 { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fcvtmu.i32.f32")] fn vcvtms_u32_f32_(a: f32) -> u32; } @@ -3013,7 +3013,7 @@ pub unsafe fn vcvtms_u32_f32(a: f32) -> u32 { #[cfg_attr(test, assert_instr(fcvtmu))] pub unsafe fn vcvtmd_u64_f64(a: f64) -> u64 { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fcvtmu.i64.f64")] fn vcvtmd_u64_f64_(a: f64) -> u64; } @@ -3026,7 +3026,7 @@ pub unsafe fn vcvtmd_u64_f64(a: f64) -> u64 { #[cfg_attr(test, assert_instr(fcvtpu))] pub unsafe fn vcvtp_u32_f32(a: float32x2_t) -> uint32x2_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fcvtpu.v2i32.v2f32")] fn vcvtp_u32_f32_(a: float32x2_t) -> uint32x2_t; } @@ -3039,7 +3039,7 @@ pub unsafe fn vcvtp_u32_f32(a: float32x2_t) -> uint32x2_t { #[cfg_attr(test, assert_instr(fcvtpu))] pub unsafe fn vcvtpq_u32_f32(a: float32x4_t) -> uint32x4_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fcvtpu.v4i32.v4f32")] fn vcvtpq_u32_f32_(a: float32x4_t) -> uint32x4_t; } @@ -3052,7 +3052,7 @@ pub unsafe fn vcvtpq_u32_f32(a: float32x4_t) -> uint32x4_t { #[cfg_attr(test, assert_instr(fcvtpu))] pub unsafe fn vcvtp_u64_f64(a: float64x1_t) -> uint64x1_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fcvtpu.v1i64.v1f64")] fn vcvtp_u64_f64_(a: float64x1_t) -> uint64x1_t; } @@ -3065,7 +3065,7 @@ pub unsafe fn vcvtp_u64_f64(a: float64x1_t) -> uint64x1_t { #[cfg_attr(test, assert_instr(fcvtpu))] pub unsafe fn vcvtpq_u64_f64(a: float64x2_t) -> uint64x2_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fcvtpu.v2i64.v2f64")] fn vcvtpq_u64_f64_(a: float64x2_t) -> uint64x2_t; } @@ -3078,7 +3078,7 @@ pub unsafe fn vcvtpq_u64_f64(a: float64x2_t) -> uint64x2_t { #[cfg_attr(test, assert_instr(fcvtpu))] pub unsafe fn vcvtps_u32_f32(a: f32) -> u32 { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fcvtpu.i32.f32")] fn vcvtps_u32_f32_(a: f32) -> u32; } @@ -3091,7 +3091,7 @@ pub unsafe fn vcvtps_u32_f32(a: f32) -> u32 { #[cfg_attr(test, assert_instr(fcvtpu))] pub unsafe fn vcvtpd_u64_f64(a: f64) -> u64 { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fcvtpu.i64.f64")] fn vcvtpd_u64_f64_(a: f64) -> u64; } @@ -3914,7 +3914,7 @@ pub unsafe fn vnegq_f64(a: float64x2_t) -> float64x2_t { #[cfg_attr(test, assert_instr(sqneg))] pub unsafe fn vqneg_s64(a: int64x1_t) -> int64x1_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqneg.v1i64")] fn vqneg_s64_(a: int64x1_t) -> int64x1_t; } @@ -3927,7 +3927,7 @@ pub unsafe fn vqneg_s64(a: int64x1_t) -> int64x1_t { #[cfg_attr(test, assert_instr(sqneg))] pub unsafe fn vqnegq_s64(a: int64x2_t) -> int64x2_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqneg.v2i64")] fn vqnegq_s64_(a: int64x2_t) -> int64x2_t; } @@ -3980,7 +3980,7 @@ pub unsafe fn vqsubh_u16(a: u16, b: u16) -> u16 { #[cfg_attr(test, assert_instr(uqsub))] pub unsafe fn vqsubs_u32(a: u32, b: u32) -> u32 { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uqsub.i32")] fn vqsubs_u32_(a: u32, b: u32) -> u32; } @@ -3993,7 +3993,7 @@ pub unsafe fn vqsubs_u32(a: u32, b: u32) -> u32 { #[cfg_attr(test, assert_instr(uqsub))] pub unsafe fn vqsubd_u64(a: u64, b: u64) -> u64 { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uqsub.i64")] fn vqsubd_u64_(a: u64, b: u64) -> u64; } @@ -4006,7 +4006,7 @@ pub unsafe fn vqsubd_u64(a: u64, b: u64) -> u64 { #[cfg_attr(test, assert_instr(sqsub))] pub unsafe fn vqsubs_s32(a: i32, b: i32) -> i32 { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqsub.i32")] fn vqsubs_s32_(a: i32, b: i32) -> i32; } @@ -4019,7 +4019,7 @@ pub unsafe fn vqsubs_s32(a: i32, b: i32) -> i32 { #[cfg_attr(test, assert_instr(sqsub))] pub unsafe fn vqsubd_s64(a: i64, b: i64) -> i64 { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqsub.i64")] fn vqsubd_s64_(a: i64, b: i64) -> i64; } @@ -4032,7 +4032,7 @@ pub unsafe fn vqsubd_s64(a: i64, b: i64) -> i64 { #[cfg_attr(test, assert_instr(rbit))] pub unsafe fn vrbit_s8(a: int8x8_t) -> int8x8_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.rbit.v8i8")] fn vrbit_s8_(a: int8x8_t) -> int8x8_t; } @@ -4045,7 +4045,7 @@ pub unsafe fn vrbit_s8(a: int8x8_t) -> int8x8_t { #[cfg_attr(test, assert_instr(rbit))] pub unsafe fn vrbitq_s8(a: int8x16_t) -> int8x16_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.rbit.v16i8")] fn vrbitq_s8_(a: int8x16_t) -> int8x16_t; } @@ -4090,7 +4090,7 @@ pub unsafe fn vrbitq_p8(a: poly8x16_t) -> poly8x16_t { #[cfg_attr(test, assert_instr(frintx))] pub unsafe fn vrndx_f32(a: float32x2_t) -> float32x2_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.rint.v2f32")] fn vrndx_f32_(a: float32x2_t) -> float32x2_t; } @@ -4103,7 +4103,7 @@ pub unsafe fn vrndx_f32(a: float32x2_t) -> float32x2_t { #[cfg_attr(test, assert_instr(frintx))] pub unsafe fn vrndxq_f32(a: float32x4_t) -> float32x4_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.rint.v4f32")] fn vrndxq_f32_(a: float32x4_t) -> float32x4_t; } @@ -4116,7 +4116,7 @@ pub unsafe fn vrndxq_f32(a: float32x4_t) -> float32x4_t { #[cfg_attr(test, assert_instr(frintx))] pub unsafe fn vrndx_f64(a: float64x1_t) -> float64x1_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.rint.v1f64")] fn vrndx_f64_(a: float64x1_t) -> float64x1_t; } @@ -4129,7 +4129,7 @@ pub unsafe fn vrndx_f64(a: float64x1_t) -> float64x1_t { #[cfg_attr(test, assert_instr(frintx))] pub unsafe fn vrndxq_f64(a: float64x2_t) -> float64x2_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.rint.v2f64")] fn vrndxq_f64_(a: float64x2_t) -> float64x2_t; } @@ -4142,7 +4142,7 @@ pub unsafe fn vrndxq_f64(a: float64x2_t) -> float64x2_t { #[cfg_attr(test, assert_instr(frinta))] pub unsafe fn vrnda_f32(a: float32x2_t) -> float32x2_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.round.v2f32")] fn vrnda_f32_(a: float32x2_t) -> float32x2_t; } @@ -4155,7 +4155,7 @@ pub unsafe fn vrnda_f32(a: float32x2_t) -> float32x2_t { #[cfg_attr(test, assert_instr(frinta))] pub unsafe fn vrndaq_f32(a: float32x4_t) -> float32x4_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.round.v4f32")] fn vrndaq_f32_(a: float32x4_t) -> float32x4_t; } @@ -4168,7 +4168,7 @@ pub unsafe fn vrndaq_f32(a: float32x4_t) -> float32x4_t { #[cfg_attr(test, assert_instr(frinta))] pub unsafe fn vrnda_f64(a: float64x1_t) -> float64x1_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.round.v1f64")] fn vrnda_f64_(a: float64x1_t) -> float64x1_t; } @@ -4181,7 +4181,7 @@ pub unsafe fn vrnda_f64(a: float64x1_t) -> float64x1_t { #[cfg_attr(test, assert_instr(frinta))] pub unsafe fn vrndaq_f64(a: float64x2_t) -> float64x2_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.round.v2f64")] fn vrndaq_f64_(a: float64x2_t) -> float64x2_t; } @@ -4194,7 +4194,7 @@ pub unsafe fn vrndaq_f64(a: float64x2_t) -> float64x2_t { #[cfg_attr(test, assert_instr(frintn))] pub unsafe fn vrndn_f64(a: float64x1_t) -> float64x1_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.frintn.v1f64")] fn vrndn_f64_(a: float64x1_t) -> float64x1_t; } @@ -4207,7 +4207,7 @@ pub unsafe fn vrndn_f64(a: float64x1_t) -> float64x1_t { #[cfg_attr(test, assert_instr(frintn))] pub unsafe fn vrndnq_f64(a: float64x2_t) -> float64x2_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.frintn.v2f64")] fn vrndnq_f64_(a: float64x2_t) -> float64x2_t; } @@ -4220,7 +4220,7 @@ pub unsafe fn vrndnq_f64(a: float64x2_t) -> float64x2_t { #[cfg_attr(test, assert_instr(frintm))] pub unsafe fn vrndm_f32(a: float32x2_t) -> float32x2_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.floor.v2f32")] fn vrndm_f32_(a: float32x2_t) -> float32x2_t; } @@ -4233,7 +4233,7 @@ pub unsafe fn vrndm_f32(a: float32x2_t) -> float32x2_t { #[cfg_attr(test, assert_instr(frintm))] pub unsafe fn vrndmq_f32(a: float32x4_t) -> float32x4_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.floor.v4f32")] fn vrndmq_f32_(a: float32x4_t) -> float32x4_t; } @@ -4246,7 +4246,7 @@ pub unsafe fn vrndmq_f32(a: float32x4_t) -> float32x4_t { #[cfg_attr(test, assert_instr(frintm))] pub unsafe fn vrndm_f64(a: float64x1_t) -> float64x1_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.floor.v1f64")] fn vrndm_f64_(a: float64x1_t) -> float64x1_t; } @@ -4259,7 +4259,7 @@ pub unsafe fn vrndm_f64(a: float64x1_t) -> float64x1_t { #[cfg_attr(test, assert_instr(frintm))] pub unsafe fn vrndmq_f64(a: float64x2_t) -> float64x2_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.floor.v2f64")] fn vrndmq_f64_(a: float64x2_t) -> float64x2_t; } @@ -4272,7 +4272,7 @@ pub unsafe fn vrndmq_f64(a: float64x2_t) -> float64x2_t { #[cfg_attr(test, assert_instr(frintp))] pub unsafe fn vrndp_f32(a: float32x2_t) -> float32x2_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.ceil.v2f32")] fn vrndp_f32_(a: float32x2_t) -> float32x2_t; } @@ -4285,7 +4285,7 @@ pub unsafe fn vrndp_f32(a: float32x2_t) -> float32x2_t { #[cfg_attr(test, assert_instr(frintp))] pub unsafe fn vrndpq_f32(a: float32x4_t) -> float32x4_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.ceil.v4f32")] fn vrndpq_f32_(a: float32x4_t) -> float32x4_t; } @@ -4298,7 +4298,7 @@ pub unsafe fn vrndpq_f32(a: float32x4_t) -> float32x4_t { #[cfg_attr(test, assert_instr(frintp))] pub unsafe fn vrndp_f64(a: float64x1_t) -> float64x1_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.ceil.v1f64")] fn vrndp_f64_(a: float64x1_t) -> float64x1_t; } @@ -4311,7 +4311,7 @@ pub unsafe fn vrndp_f64(a: float64x1_t) -> float64x1_t { #[cfg_attr(test, assert_instr(frintp))] pub unsafe fn vrndpq_f64(a: float64x2_t) -> float64x2_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.ceil.v2f64")] fn vrndpq_f64_(a: float64x2_t) -> float64x2_t; } @@ -4324,7 +4324,7 @@ pub unsafe fn vrndpq_f64(a: float64x2_t) -> float64x2_t { #[cfg_attr(test, assert_instr(frintz))] pub unsafe fn vrnd_f32(a: float32x2_t) -> float32x2_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.trunc.v2f32")] fn vrnd_f32_(a: float32x2_t) -> float32x2_t; } @@ -4337,7 +4337,7 @@ pub unsafe fn vrnd_f32(a: float32x2_t) -> float32x2_t { #[cfg_attr(test, assert_instr(frintz))] pub unsafe fn vrndq_f32(a: float32x4_t) -> float32x4_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.trunc.v4f32")] fn vrndq_f32_(a: float32x4_t) -> float32x4_t; } @@ -4350,7 +4350,7 @@ pub unsafe fn vrndq_f32(a: float32x4_t) -> float32x4_t { #[cfg_attr(test, assert_instr(frintz))] pub unsafe fn vrnd_f64(a: float64x1_t) -> float64x1_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.trunc.v1f64")] fn vrnd_f64_(a: float64x1_t) -> float64x1_t; } @@ -4363,7 +4363,7 @@ pub unsafe fn vrnd_f64(a: float64x1_t) -> float64x1_t { #[cfg_attr(test, assert_instr(frintz))] pub unsafe fn vrndq_f64(a: float64x2_t) -> float64x2_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.trunc.v2f64")] fn vrndq_f64_(a: float64x2_t) -> float64x2_t; } @@ -4376,7 +4376,7 @@ pub unsafe fn vrndq_f64(a: float64x2_t) -> float64x2_t { #[cfg_attr(test, assert_instr(frinti))] pub unsafe fn vrndi_f32(a: float32x2_t) -> float32x2_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.nearbyint.v2f32")] fn vrndi_f32_(a: float32x2_t) -> float32x2_t; } @@ -4389,7 +4389,7 @@ pub unsafe fn vrndi_f32(a: float32x2_t) -> float32x2_t { #[cfg_attr(test, assert_instr(frinti))] pub unsafe fn vrndiq_f32(a: float32x4_t) -> float32x4_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.nearbyint.v4f32")] fn vrndiq_f32_(a: float32x4_t) -> float32x4_t; } @@ -4402,7 +4402,7 @@ pub unsafe fn vrndiq_f32(a: float32x4_t) -> float32x4_t { #[cfg_attr(test, assert_instr(frinti))] pub unsafe fn vrndi_f64(a: float64x1_t) -> float64x1_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.nearbyint.v1f64")] fn vrndi_f64_(a: float64x1_t) -> float64x1_t; } @@ -4415,7 +4415,7 @@ pub unsafe fn vrndi_f64(a: float64x1_t) -> float64x1_t { #[cfg_attr(test, assert_instr(frinti))] pub unsafe fn vrndiq_f64(a: float64x2_t) -> float64x2_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.nearbyint.v2f64")] fn vrndiq_f64_(a: float64x2_t) -> float64x2_t; } @@ -4468,7 +4468,7 @@ pub unsafe fn vqaddh_u16(a: u16, b: u16) -> u16 { #[cfg_attr(test, assert_instr(uqadd))] pub unsafe fn vqadds_u32(a: u32, b: u32) -> u32 { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uqadd.i32")] fn vqadds_u32_(a: u32, b: u32) -> u32; } @@ -4481,7 +4481,7 @@ pub unsafe fn vqadds_u32(a: u32, b: u32) -> u32 { #[cfg_attr(test, assert_instr(uqadd))] pub unsafe fn vqaddd_u64(a: u64, b: u64) -> u64 { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uqadd.i64")] fn vqaddd_u64_(a: u64, b: u64) -> u64; } @@ -4494,7 +4494,7 @@ pub unsafe fn vqaddd_u64(a: u64, b: u64) -> u64 { #[cfg_attr(test, assert_instr(sqadd))] pub unsafe fn vqadds_s32(a: i32, b: i32) -> i32 { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqadd.i32")] fn vqadds_s32_(a: i32, b: i32) -> i32; } @@ -4507,13 +4507,169 @@ pub unsafe fn vqadds_s32(a: i32, b: i32) -> i32 { #[cfg_attr(test, assert_instr(sqadd))] pub unsafe fn vqaddd_s64(a: i64, b: i64) -> i64 { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqadd.i64")] fn vqaddd_s64_(a: i64, b: i64) -> i64; } vqaddd_s64_(a, b) } +/// Load multiple single-element structures to one, two, three, or four registers +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(ld1))] +pub unsafe fn vld1_f64_x2(a: *const f64) -> float64x1x2_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld1x2.v1f64.p0f64")] + fn vld1_f64_x2_(a: *const f64) -> float64x1x2_t; + } + vld1_f64_x2_(a) +} + +/// Load multiple single-element structures to one, two, three, or four registers +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(ld1))] +pub unsafe fn vld1q_f64_x2(a: *const f64) -> float64x2x2_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld1x2.v2f64.p0f64")] + fn vld1q_f64_x2_(a: *const f64) -> float64x2x2_t; + } + vld1q_f64_x2_(a) +} + +/// Load multiple single-element structures to one, two, three, or four registers +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(ld1))] +pub unsafe fn vld1_f64_x3(a: *const f64) -> float64x1x3_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld1x3.v1f64.p0f64")] + fn vld1_f64_x3_(a: *const f64) -> float64x1x3_t; + } + vld1_f64_x3_(a) +} + +/// Load multiple single-element structures to one, two, three, or four registers +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(ld1))] +pub unsafe fn vld1q_f64_x3(a: *const f64) -> float64x2x3_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld1x3.v2f64.p0f64")] + fn vld1q_f64_x3_(a: *const f64) -> float64x2x3_t; + } + vld1q_f64_x3_(a) +} + +/// Load multiple single-element structures to one, two, three, or four registers +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(ld1))] +pub unsafe fn vld1_f64_x4(a: *const f64) -> float64x1x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld1x4.v1f64.p0f64")] + fn vld1_f64_x4_(a: *const f64) -> float64x1x4_t; + } + vld1_f64_x4_(a) +} + +/// Load multiple single-element structures to one, two, three, or four registers +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(ld1))] +pub unsafe fn vld1q_f64_x4(a: *const f64) -> float64x2x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld1x4.v2f64.p0f64")] + 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 +#[inline] +#[target_feature(enable = "neon")] +#[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) +} + +/// Store multiple single-element structures to one, two, three, or four 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) +} + +/// Store multiple single-element structures to one, two, three, or four registers +#[inline] +#[target_feature(enable = "neon")] +#[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.aarch64.neon.st1x3.v1f64.p0f64")] + fn vst1_f64_x3_(a: float64x1_t, b: float64x1_t, c: float64x1_t, ptr: *mut f64); + } + vst1_f64_x3_(b.0, b.1, b.2, a) +} + +/// Store multiple single-element structures to one, two, three, or four registers +#[inline] +#[target_feature(enable = "neon")] +#[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.aarch64.neon.st1x3.v2f64.p0f64")] + fn vst1q_f64_x3_(a: float64x2_t, b: float64x2_t, c: float64x2_t, ptr: *mut f64); + } + vst1q_f64_x3_(b.0, b.1, b.2, a) +} + +/// Store multiple single-element structures to one, two, three, or four registers +#[inline] +#[target_feature(enable = "neon")] +#[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) +} + +/// Store multiple single-element structures to one, two, three, or four registers +#[inline] +#[target_feature(enable = "neon")] +#[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) +} + /// Multiply #[inline] #[target_feature(enable = "neon")] @@ -4696,7 +4852,7 @@ pub unsafe fn vmull_high_u32(a: uint32x4_t, b: uint32x4_t) -> uint64x2_t { #[cfg_attr(test, assert_instr(pmull))] pub unsafe fn vmull_p64(a: p64, b: p64) -> p128 { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.pmull64")] fn vmull_p64_(a: p64, b: p64) -> int8x16_t; } @@ -4839,7 +4995,7 @@ pub unsafe fn vmull_high_laneq_u32(a: uint32x4_t, b: uint32x4_t #[cfg_attr(test, assert_instr(fmulx))] pub unsafe fn vmulx_f32(a: float32x2_t, b: float32x2_t) -> float32x2_t { #[allow(improper_ctypes)] - extern "C" { + 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; } @@ -4852,7 +5008,7 @@ pub unsafe fn vmulx_f32(a: float32x2_t, b: float32x2_t) -> float32x2_t { #[cfg_attr(test, assert_instr(fmulx))] pub unsafe fn vmulxq_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t { #[allow(improper_ctypes)] - extern "C" { + 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; } @@ -4865,7 +5021,7 @@ pub unsafe fn vmulxq_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t { #[cfg_attr(test, assert_instr(fmulx))] pub unsafe fn vmulx_f64(a: float64x1_t, b: float64x1_t) -> float64x1_t { #[allow(improper_ctypes)] - extern "C" { + 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; } @@ -4878,7 +5034,7 @@ pub unsafe fn vmulx_f64(a: float64x1_t, b: float64x1_t) -> float64x1_t { #[cfg_attr(test, assert_instr(fmulx))] pub unsafe fn vmulxq_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { #[allow(improper_ctypes)] - extern "C" { + 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; } @@ -4971,7 +5127,7 @@ pub unsafe fn vmulxq_laneq_f64(a: float64x2_t, b: float64x2_t) #[cfg_attr(test, assert_instr(fmulx))] pub unsafe fn vmulxs_f32(a: f32, b: f32) -> f32 { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fmulx.f32")] fn vmulxs_f32_(a: f32, b: f32) -> f32; } @@ -4984,7 +5140,7 @@ pub unsafe fn vmulxs_f32(a: f32, b: f32) -> f32 { #[cfg_attr(test, assert_instr(fmulx))] pub unsafe fn vmulxd_f64(a: f64, b: f64) -> f64 { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fmulx.f64")] fn vmulxd_f64_(a: f64, b: f64) -> f64; } @@ -5037,7 +5193,7 @@ pub unsafe fn vmulxd_laneq_f64(a: f64, b: float64x2_t) -> f64 { #[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 "C" { + 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; } @@ -5050,7 +5206,7 @@ pub unsafe fn vfma_f64(a: float64x1_t, b: float64x1_t, c: float64x1_t) -> float6 #[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 "C" { + 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; } @@ -5160,7 +5316,7 @@ pub unsafe fn vfmaq_laneq_f64(a: float64x2_t, b: float64x2_t, c #[rustc_legacy_const_generics(3)] pub unsafe fn vfmas_lane_f32(a: f32, b: f32, c: float32x2_t) -> f32 { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.fma.f32")] fn vfmas_lane_f32_(a: f32, b: f32, c: f32) -> f32; } @@ -5176,7 +5332,7 @@ pub unsafe fn vfmas_lane_f32(a: f32, b: f32, c: float32x2_t) -> #[rustc_legacy_const_generics(3)] pub unsafe fn vfmas_laneq_f32(a: f32, b: f32, c: float32x4_t) -> f32 { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.fma.f32")] fn vfmas_laneq_f32_(a: f32, b: f32, c: f32) -> f32; } @@ -5192,7 +5348,7 @@ pub unsafe fn vfmas_laneq_f32(a: f32, b: f32, c: float32x4_t) - #[rustc_legacy_const_generics(3)] pub unsafe fn vfmad_lane_f64(a: f64, b: f64, c: float64x1_t) -> f64 { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.fma.f64")] fn vfmad_lane_f64_(a: f64, b: f64, c: f64) -> f64; } @@ -5208,7 +5364,7 @@ pub unsafe fn vfmad_lane_f64(a: f64, b: f64, c: float64x1_t) -> #[rustc_legacy_const_generics(3)] pub unsafe fn vfmad_laneq_f64(a: f64, b: f64, c: float64x2_t) -> f64 { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.fma.f64")] fn vfmad_laneq_f64_(a: f64, b: f64, c: f64) -> f64; } @@ -5421,7 +5577,7 @@ pub unsafe fn vsubq_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { #[cfg_attr(test, assert_instr(saddlv))] pub unsafe fn vaddlv_s16(a: int16x4_t) -> i32 { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.saddlv.i32.v4i16")] fn vaddlv_s16_(a: int16x4_t) -> i32; } @@ -5434,7 +5590,7 @@ pub unsafe fn vaddlv_s16(a: int16x4_t) -> i32 { #[cfg_attr(test, assert_instr(saddlv))] pub unsafe fn vaddlvq_s16(a: int16x8_t) -> i32 { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.saddlv.i32.v8i16")] fn vaddlvq_s16_(a: int16x8_t) -> i32; } @@ -5447,7 +5603,7 @@ pub unsafe fn vaddlvq_s16(a: int16x8_t) -> i32 { #[cfg_attr(test, assert_instr(saddlp))] pub unsafe fn vaddlv_s32(a: int32x2_t) -> i64 { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.saddlv.i64.v2i32")] fn vaddlv_s32_(a: int32x2_t) -> i64; } @@ -5460,7 +5616,7 @@ pub unsafe fn vaddlv_s32(a: int32x2_t) -> i64 { #[cfg_attr(test, assert_instr(saddlv))] pub unsafe fn vaddlvq_s32(a: int32x4_t) -> i64 { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.saddlv.i64.v4i32")] fn vaddlvq_s32_(a: int32x4_t) -> i64; } @@ -5473,7 +5629,7 @@ pub unsafe fn vaddlvq_s32(a: int32x4_t) -> i64 { #[cfg_attr(test, assert_instr(uaddlv))] pub unsafe fn vaddlv_u16(a: uint16x4_t) -> u32 { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uaddlv.i32.v4i16")] fn vaddlv_u16_(a: uint16x4_t) -> u32; } @@ -5486,7 +5642,7 @@ pub unsafe fn vaddlv_u16(a: uint16x4_t) -> u32 { #[cfg_attr(test, assert_instr(uaddlv))] pub unsafe fn vaddlvq_u16(a: uint16x8_t) -> u32 { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uaddlv.i32.v8i16")] fn vaddlvq_u16_(a: uint16x8_t) -> u32; } @@ -5499,7 +5655,7 @@ pub unsafe fn vaddlvq_u16(a: uint16x8_t) -> u32 { #[cfg_attr(test, assert_instr(uaddlp))] pub unsafe fn vaddlv_u32(a: uint32x2_t) -> u64 { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uaddlv.i64.v2i32")] fn vaddlv_u32_(a: uint32x2_t) -> u64; } @@ -5512,7 +5668,7 @@ pub unsafe fn vaddlv_u32(a: uint32x2_t) -> u64 { #[cfg_attr(test, assert_instr(uaddlv))] pub unsafe fn vaddlvq_u32(a: uint32x4_t) -> u64 { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uaddlv.i64.v4i32")] fn vaddlvq_u32_(a: uint32x4_t) -> u64; } @@ -5651,7 +5807,7 @@ pub unsafe fn vsubl_high_u32(a: uint32x4_t, b: uint32x4_t) -> uint64x2_t { #[cfg_attr(test, assert_instr(fmax))] pub unsafe fn vmax_f64(a: float64x1_t, b: float64x1_t) -> float64x1_t { #[allow(improper_ctypes)] - extern "C" { + 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; } @@ -5664,7 +5820,7 @@ pub unsafe fn vmax_f64(a: float64x1_t, b: float64x1_t) -> float64x1_t { #[cfg_attr(test, assert_instr(fmax))] pub unsafe fn vmaxq_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { #[allow(improper_ctypes)] - extern "C" { + 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; } @@ -5677,7 +5833,7 @@ pub unsafe fn vmaxq_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { #[cfg_attr(test, assert_instr(fmaxnm))] pub unsafe fn vmaxnm_f64(a: float64x1_t, b: float64x1_t) -> float64x1_t { #[allow(improper_ctypes)] - extern "C" { + 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; } @@ -5690,7 +5846,7 @@ pub unsafe fn vmaxnm_f64(a: float64x1_t, b: float64x1_t) -> float64x1_t { #[cfg_attr(test, assert_instr(fmaxnm))] pub unsafe fn vmaxnmq_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { #[allow(improper_ctypes)] - extern "C" { + 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; } @@ -5703,7 +5859,7 @@ pub unsafe fn vmaxnmq_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { #[cfg_attr(test, assert_instr(fmaxnmp))] pub unsafe fn vpmaxnm_f32(a: float32x2_t, b: float32x2_t) -> float32x2_t { #[allow(improper_ctypes)] - extern "C" { + 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; } @@ -5716,7 +5872,7 @@ pub unsafe fn vpmaxnm_f32(a: float32x2_t, b: float32x2_t) -> float32x2_t { #[cfg_attr(test, assert_instr(fmaxnmp))] pub unsafe fn vpmaxnmq_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { #[allow(improper_ctypes)] - extern "C" { + 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; } @@ -5729,7 +5885,7 @@ pub unsafe fn vpmaxnmq_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { #[cfg_attr(test, assert_instr(fmaxnmp))] pub unsafe fn vpmaxnmq_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t { #[allow(improper_ctypes)] - extern "C" { + 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; } @@ -5742,7 +5898,7 @@ pub unsafe fn vpmaxnmq_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t { #[cfg_attr(test, assert_instr(fmin))] pub unsafe fn vmin_f64(a: float64x1_t, b: float64x1_t) -> float64x1_t { #[allow(improper_ctypes)] - extern "C" { + 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; } @@ -5755,7 +5911,7 @@ pub unsafe fn vmin_f64(a: float64x1_t, b: float64x1_t) -> float64x1_t { #[cfg_attr(test, assert_instr(fmin))] pub unsafe fn vminq_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { #[allow(improper_ctypes)] - extern "C" { + 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; } @@ -5768,7 +5924,7 @@ pub unsafe fn vminq_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { #[cfg_attr(test, assert_instr(fminnm))] pub unsafe fn vminnm_f64(a: float64x1_t, b: float64x1_t) -> float64x1_t { #[allow(improper_ctypes)] - extern "C" { + 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; } @@ -5781,7 +5937,7 @@ pub unsafe fn vminnm_f64(a: float64x1_t, b: float64x1_t) -> float64x1_t { #[cfg_attr(test, assert_instr(fminnm))] pub unsafe fn vminnmq_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { #[allow(improper_ctypes)] - extern "C" { + 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; } @@ -5794,7 +5950,7 @@ pub unsafe fn vminnmq_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { #[cfg_attr(test, assert_instr(fminnmp))] pub unsafe fn vpminnm_f32(a: float32x2_t, b: float32x2_t) -> float32x2_t { #[allow(improper_ctypes)] - extern "C" { + 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; } @@ -5807,7 +5963,7 @@ pub unsafe fn vpminnm_f32(a: float32x2_t, b: float32x2_t) -> float32x2_t { #[cfg_attr(test, assert_instr(fminnmp))] pub unsafe fn vpminnmq_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { #[allow(improper_ctypes)] - extern "C" { + 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; } @@ -5820,7 +5976,7 @@ pub unsafe fn vpminnmq_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { #[cfg_attr(test, assert_instr(fminnmp))] pub unsafe fn vpminnmq_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t { #[allow(improper_ctypes)] - extern "C" { + 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; } @@ -5843,7 +5999,7 @@ pub unsafe fn vqdmullh_s16(a: i16, b: i16) -> i32 { #[cfg_attr(test, assert_instr(sqdmull))] pub unsafe fn vqdmulls_s32(a: i32, b: i32) -> i64 { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqdmulls.scalar")] fn vqdmulls_s32_(a: i32, b: i32) -> i64; } @@ -6290,7 +6446,7 @@ pub unsafe fn vqmovns_u32(a: u32) -> u16 { #[cfg_attr(test, assert_instr(sqxtn))] pub unsafe fn vqmovnd_s64(a: i64) -> i32 { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.scalar.sqxtn.i32.i64")] fn vqmovnd_s64_(a: i64) -> i32; } @@ -6303,7 +6459,7 @@ pub unsafe fn vqmovnd_s64(a: i64) -> i32 { #[cfg_attr(test, assert_instr(uqxtn))] pub unsafe fn vqmovnd_u64(a: u64) -> u32 { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.scalar.uqxtn.i32.i64")] fn vqmovnd_u64_(a: u64) -> u32; } @@ -6580,7 +6736,7 @@ pub unsafe fn vqrdmlshs_laneq_s32(a: i32, b: i32, c: int32x4_t) #[cfg_attr(test, assert_instr(sqrshl))] pub unsafe fn vqrshls_s32(a: i32, b: i32) -> i32 { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqrshl.i32")] fn vqrshls_s32_(a: i32, b: i32) -> i32; } @@ -6593,7 +6749,7 @@ pub unsafe fn vqrshls_s32(a: i32, b: i32) -> i32 { #[cfg_attr(test, assert_instr(sqrshl))] pub unsafe fn vqrshld_s64(a: i64, b: i64) -> i64 { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqrshl.i64")] fn vqrshld_s64_(a: i64, b: i64) -> i64; } @@ -6626,7 +6782,7 @@ pub unsafe fn vqrshlh_s16(a: i16, b: i16) -> i16 { #[cfg_attr(test, assert_instr(uqrshl))] pub unsafe fn vqrshls_u32(a: u32, b: i32) -> u32 { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uqrshl.i32")] fn vqrshls_u32_(a: u32, b: i32) -> u32; } @@ -6639,7 +6795,7 @@ pub unsafe fn vqrshls_u32(a: u32, b: i32) -> u32 { #[cfg_attr(test, assert_instr(uqrshl))] pub unsafe fn vqrshld_u64(a: u64, b: i64) -> u64 { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uqrshl.i64")] fn vqrshld_u64_(a: u64, b: i64) -> u64; } @@ -6861,7 +7017,7 @@ pub unsafe fn vqrshrun_high_n_s64(a: uint32x2_t, b: int64x2_t) -> #[cfg_attr(test, assert_instr(sqshl))] pub unsafe fn vqshld_s64(a: i64, b: i64) -> i64 { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqshl.i64")] fn vqshld_s64_(a: i64, b: i64) -> i64; } @@ -6901,7 +7057,7 @@ pub unsafe fn vqshls_s32(a: i32, b: i32) -> i32 { #[cfg_attr(test, assert_instr(uqshl))] pub unsafe fn vqshld_u64(a: u64, b: i64) -> u64 { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uqshl.i64")] fn vqshld_u64_(a: u64, b: i64) -> u64; } @@ -7023,7 +7179,7 @@ pub unsafe fn vqshld_n_u64(a: u64) -> u64 { pub unsafe fn vqshrnd_n_s64(a: i64) -> i32 { static_assert!(N : i32 where N >= 1 && N <= 32); #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqshrn.i32")] fn vqshrnd_n_s64_(a: i64, n: i32) -> i32; } @@ -7088,7 +7244,7 @@ pub unsafe fn vqshrn_high_n_s64(a: int32x2_t, b: int64x2_t) -> int pub unsafe fn vqshrnd_n_u64(a: u64) -> u32 { static_assert!(N : i32 where N >= 1 && N <= 32); #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uqshrn.i32")] fn vqshrnd_n_u64_(a: u64, n: i32) -> u32; } @@ -7243,7 +7399,7 @@ pub unsafe fn vsqrtq_f64(a: float64x2_t) -> float64x2_t { #[cfg_attr(test, assert_instr(frsqrte))] pub unsafe fn vrsqrte_f64(a: float64x1_t) -> float64x1_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.frsqrte.v1f64")] fn vrsqrte_f64_(a: float64x1_t) -> float64x1_t; } @@ -7256,7 +7412,7 @@ pub unsafe fn vrsqrte_f64(a: float64x1_t) -> float64x1_t { #[cfg_attr(test, assert_instr(frsqrte))] pub unsafe fn vrsqrteq_f64(a: float64x2_t) -> float64x2_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.frsqrte.v2f64")] fn vrsqrteq_f64_(a: float64x2_t) -> float64x2_t; } @@ -7269,7 +7425,7 @@ pub unsafe fn vrsqrteq_f64(a: float64x2_t) -> float64x2_t { #[cfg_attr(test, assert_instr(frecpe))] pub unsafe fn vrecpe_f64(a: float64x1_t) -> float64x1_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.frecpe.v1f64")] fn vrecpe_f64_(a: float64x1_t) -> float64x1_t; } @@ -7282,7 +7438,7 @@ pub unsafe fn vrecpe_f64(a: float64x1_t) -> float64x1_t { #[cfg_attr(test, assert_instr(frecpe))] pub unsafe fn vrecpeq_f64(a: float64x2_t) -> float64x2_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.frecpe.v2f64")] fn vrecpeq_f64_(a: float64x2_t) -> float64x2_t; } @@ -7292,7 +7448,7 @@ pub unsafe fn vrecpeq_f64(a: float64x2_t) -> float64x2_t { /// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vreinterpret_s64_p64(a: poly64x1_t) -> int64x1_t { transmute(a) } @@ -7300,7 +7456,7 @@ pub unsafe fn vreinterpret_s64_p64(a: poly64x1_t) -> int64x1_t { /// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vreinterpret_u64_p64(a: poly64x1_t) -> uint64x1_t { transmute(a) } @@ -7308,7 +7464,7 @@ pub unsafe fn vreinterpret_u64_p64(a: poly64x1_t) -> uint64x1_t { /// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vreinterpret_p64_s64(a: int64x1_t) -> poly64x1_t { transmute(a) } @@ -7316,7 +7472,7 @@ pub unsafe fn vreinterpret_p64_s64(a: int64x1_t) -> poly64x1_t { /// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vreinterpret_p64_u64(a: uint64x1_t) -> poly64x1_t { transmute(a) } @@ -7324,7 +7480,7 @@ pub unsafe fn vreinterpret_p64_u64(a: uint64x1_t) -> poly64x1_t { /// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vreinterpretq_s64_p64(a: poly64x2_t) -> int64x2_t { transmute(a) } @@ -7332,7 +7488,7 @@ pub unsafe fn vreinterpretq_s64_p64(a: poly64x2_t) -> int64x2_t { /// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vreinterpretq_u64_p64(a: poly64x2_t) -> uint64x2_t { transmute(a) } @@ -7340,7 +7496,7 @@ pub unsafe fn vreinterpretq_u64_p64(a: poly64x2_t) -> uint64x2_t { /// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vreinterpretq_p64_s64(a: int64x2_t) -> poly64x2_t { transmute(a) } @@ -7348,7 +7504,7 @@ pub unsafe fn vreinterpretq_p64_s64(a: int64x2_t) -> poly64x2_t { /// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vreinterpretq_p64_u64(a: uint64x2_t) -> poly64x2_t { transmute(a) } @@ -7356,7 +7512,7 @@ pub unsafe fn vreinterpretq_p64_u64(a: uint64x2_t) -> poly64x2_t { /// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vreinterpret_s32_p64(a: poly64x1_t) -> int32x2_t { transmute(a) } @@ -7364,7 +7520,7 @@ pub unsafe fn vreinterpret_s32_p64(a: poly64x1_t) -> int32x2_t { /// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vreinterpret_u32_p64(a: poly64x1_t) -> uint32x2_t { transmute(a) } @@ -7372,7 +7528,7 @@ pub unsafe fn vreinterpret_u32_p64(a: poly64x1_t) -> uint32x2_t { /// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vreinterpretq_s32_p64(a: poly64x2_t) -> int32x4_t { transmute(a) } @@ -7380,7 +7536,7 @@ pub unsafe fn vreinterpretq_s32_p64(a: poly64x2_t) -> int32x4_t { /// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vreinterpretq_u32_p64(a: poly64x2_t) -> uint32x4_t { transmute(a) } @@ -7388,7 +7544,7 @@ pub unsafe fn vreinterpretq_u32_p64(a: poly64x2_t) -> uint32x4_t { /// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vreinterpret_p64_s32(a: int32x2_t) -> poly64x1_t { transmute(a) } @@ -7396,7 +7552,7 @@ pub unsafe fn vreinterpret_p64_s32(a: int32x2_t) -> poly64x1_t { /// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vreinterpret_p64_u32(a: uint32x2_t) -> poly64x1_t { transmute(a) } @@ -7404,7 +7560,7 @@ pub unsafe fn vreinterpret_p64_u32(a: uint32x2_t) -> poly64x1_t { /// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vreinterpretq_p64_s32(a: int32x4_t) -> poly64x2_t { transmute(a) } @@ -7412,7 +7568,7 @@ pub unsafe fn vreinterpretq_p64_s32(a: int32x4_t) -> poly64x2_t { /// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vreinterpretq_p64_u32(a: uint32x4_t) -> poly64x2_t { transmute(a) } @@ -7420,7 +7576,7 @@ pub unsafe fn vreinterpretq_p64_u32(a: uint32x4_t) -> poly64x2_t { /// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vreinterpret_s16_p64(a: poly64x1_t) -> int16x4_t { transmute(a) } @@ -7428,7 +7584,7 @@ pub unsafe fn vreinterpret_s16_p64(a: poly64x1_t) -> int16x4_t { /// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vreinterpret_u16_p64(a: poly64x1_t) -> uint16x4_t { transmute(a) } @@ -7436,7 +7592,7 @@ pub unsafe fn vreinterpret_u16_p64(a: poly64x1_t) -> uint16x4_t { /// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vreinterpret_p16_p64(a: poly64x1_t) -> poly16x4_t { transmute(a) } @@ -7444,7 +7600,7 @@ pub unsafe fn vreinterpret_p16_p64(a: poly64x1_t) -> poly16x4_t { /// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vreinterpretq_s16_p64(a: poly64x2_t) -> int16x8_t { transmute(a) } @@ -7452,7 +7608,7 @@ pub unsafe fn vreinterpretq_s16_p64(a: poly64x2_t) -> int16x8_t { /// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vreinterpretq_u16_p64(a: poly64x2_t) -> uint16x8_t { transmute(a) } @@ -7460,7 +7616,7 @@ pub unsafe fn vreinterpretq_u16_p64(a: poly64x2_t) -> uint16x8_t { /// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vreinterpretq_p16_p64(a: poly64x2_t) -> poly16x8_t { transmute(a) } @@ -7468,7 +7624,7 @@ pub unsafe fn vreinterpretq_p16_p64(a: poly64x2_t) -> poly16x8_t { /// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vreinterpret_p64_p16(a: poly16x4_t) -> poly64x1_t { transmute(a) } @@ -7476,7 +7632,7 @@ pub unsafe fn vreinterpret_p64_p16(a: poly16x4_t) -> poly64x1_t { /// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vreinterpret_p64_s16(a: int16x4_t) -> poly64x1_t { transmute(a) } @@ -7484,7 +7640,7 @@ pub unsafe fn vreinterpret_p64_s16(a: int16x4_t) -> poly64x1_t { /// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vreinterpret_p64_u16(a: uint16x4_t) -> poly64x1_t { transmute(a) } @@ -7492,7 +7648,7 @@ pub unsafe fn vreinterpret_p64_u16(a: uint16x4_t) -> poly64x1_t { /// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vreinterpretq_p64_p16(a: poly16x8_t) -> poly64x2_t { transmute(a) } @@ -7500,7 +7656,7 @@ pub unsafe fn vreinterpretq_p64_p16(a: poly16x8_t) -> poly64x2_t { /// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vreinterpretq_p64_s16(a: int16x8_t) -> poly64x2_t { transmute(a) } @@ -7508,7 +7664,7 @@ pub unsafe fn vreinterpretq_p64_s16(a: int16x8_t) -> poly64x2_t { /// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vreinterpretq_p64_u16(a: uint16x8_t) -> poly64x2_t { transmute(a) } @@ -7516,7 +7672,7 @@ pub unsafe fn vreinterpretq_p64_u16(a: uint16x8_t) -> poly64x2_t { /// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vreinterpret_s8_p64(a: poly64x1_t) -> int8x8_t { transmute(a) } @@ -7524,7 +7680,7 @@ pub unsafe fn vreinterpret_s8_p64(a: poly64x1_t) -> int8x8_t { /// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vreinterpret_u8_p64(a: poly64x1_t) -> uint8x8_t { transmute(a) } @@ -7532,7 +7688,7 @@ pub unsafe fn vreinterpret_u8_p64(a: poly64x1_t) -> uint8x8_t { /// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vreinterpret_p8_p64(a: poly64x1_t) -> poly8x8_t { transmute(a) } @@ -7540,7 +7696,7 @@ pub unsafe fn vreinterpret_p8_p64(a: poly64x1_t) -> poly8x8_t { /// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vreinterpretq_s8_p64(a: poly64x2_t) -> int8x16_t { transmute(a) } @@ -7548,7 +7704,7 @@ pub unsafe fn vreinterpretq_s8_p64(a: poly64x2_t) -> int8x16_t { /// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vreinterpretq_u8_p64(a: poly64x2_t) -> uint8x16_t { transmute(a) } @@ -7556,7 +7712,7 @@ pub unsafe fn vreinterpretq_u8_p64(a: poly64x2_t) -> uint8x16_t { /// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vreinterpretq_p8_p64(a: poly64x2_t) -> poly8x16_t { transmute(a) } @@ -7564,7 +7720,7 @@ pub unsafe fn vreinterpretq_p8_p64(a: poly64x2_t) -> poly8x16_t { /// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vreinterpret_p64_p8(a: poly8x8_t) -> poly64x1_t { transmute(a) } @@ -7572,7 +7728,7 @@ pub unsafe fn vreinterpret_p64_p8(a: poly8x8_t) -> poly64x1_t { /// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vreinterpret_p64_s8(a: int8x8_t) -> poly64x1_t { transmute(a) } @@ -7580,7 +7736,7 @@ pub unsafe fn vreinterpret_p64_s8(a: int8x8_t) -> poly64x1_t { /// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vreinterpret_p64_u8(a: uint8x8_t) -> poly64x1_t { transmute(a) } @@ -7588,7 +7744,7 @@ pub unsafe fn vreinterpret_p64_u8(a: uint8x8_t) -> poly64x1_t { /// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vreinterpretq_p64_p8(a: poly8x16_t) -> poly64x2_t { transmute(a) } @@ -7596,7 +7752,7 @@ pub unsafe fn vreinterpretq_p64_p8(a: poly8x16_t) -> poly64x2_t { /// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vreinterpretq_p64_s8(a: int8x16_t) -> poly64x2_t { transmute(a) } @@ -7604,7 +7760,7 @@ pub unsafe fn vreinterpretq_p64_s8(a: int8x16_t) -> poly64x2_t { /// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vreinterpretq_p64_u8(a: uint8x16_t) -> poly64x2_t { transmute(a) } @@ -7612,7 +7768,7 @@ pub unsafe fn vreinterpretq_p64_u8(a: uint8x16_t) -> poly64x2_t { /// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vreinterpret_s8_f64(a: float64x1_t) -> int8x8_t { transmute(a) } @@ -7620,7 +7776,7 @@ pub unsafe fn vreinterpret_s8_f64(a: float64x1_t) -> int8x8_t { /// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vreinterpret_s16_f64(a: float64x1_t) -> int16x4_t { transmute(a) } @@ -7628,7 +7784,7 @@ pub unsafe fn vreinterpret_s16_f64(a: float64x1_t) -> int16x4_t { /// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vreinterpret_s32_f64(a: float64x1_t) -> int32x2_t { transmute(a) } @@ -7636,7 +7792,7 @@ pub unsafe fn vreinterpret_s32_f64(a: float64x1_t) -> int32x2_t { /// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vreinterpret_s64_f64(a: float64x1_t) -> int64x1_t { transmute(a) } @@ -7644,7 +7800,7 @@ pub unsafe fn vreinterpret_s64_f64(a: float64x1_t) -> int64x1_t { /// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vreinterpretq_s8_f64(a: float64x2_t) -> int8x16_t { transmute(a) } @@ -7652,7 +7808,7 @@ pub unsafe fn vreinterpretq_s8_f64(a: float64x2_t) -> int8x16_t { /// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vreinterpretq_s16_f64(a: float64x2_t) -> int16x8_t { transmute(a) } @@ -7660,7 +7816,7 @@ pub unsafe fn vreinterpretq_s16_f64(a: float64x2_t) -> int16x8_t { /// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vreinterpretq_s32_f64(a: float64x2_t) -> int32x4_t { transmute(a) } @@ -7668,7 +7824,7 @@ pub unsafe fn vreinterpretq_s32_f64(a: float64x2_t) -> int32x4_t { /// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vreinterpretq_s64_f64(a: float64x2_t) -> int64x2_t { transmute(a) } @@ -7676,7 +7832,7 @@ pub unsafe fn vreinterpretq_s64_f64(a: float64x2_t) -> int64x2_t { /// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vreinterpret_u8_f64(a: float64x1_t) -> uint8x8_t { transmute(a) } @@ -7684,7 +7840,7 @@ pub unsafe fn vreinterpret_u8_f64(a: float64x1_t) -> uint8x8_t { /// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vreinterpret_u16_f64(a: float64x1_t) -> uint16x4_t { transmute(a) } @@ -7692,7 +7848,7 @@ pub unsafe fn vreinterpret_u16_f64(a: float64x1_t) -> uint16x4_t { /// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vreinterpret_u32_f64(a: float64x1_t) -> uint32x2_t { transmute(a) } @@ -7700,7 +7856,7 @@ pub unsafe fn vreinterpret_u32_f64(a: float64x1_t) -> uint32x2_t { /// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vreinterpret_u64_f64(a: float64x1_t) -> uint64x1_t { transmute(a) } @@ -7708,7 +7864,7 @@ pub unsafe fn vreinterpret_u64_f64(a: float64x1_t) -> uint64x1_t { /// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vreinterpretq_u8_f64(a: float64x2_t) -> uint8x16_t { transmute(a) } @@ -7716,7 +7872,7 @@ pub unsafe fn vreinterpretq_u8_f64(a: float64x2_t) -> uint8x16_t { /// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vreinterpretq_u16_f64(a: float64x2_t) -> uint16x8_t { transmute(a) } @@ -7724,7 +7880,7 @@ pub unsafe fn vreinterpretq_u16_f64(a: float64x2_t) -> uint16x8_t { /// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vreinterpretq_u32_f64(a: float64x2_t) -> uint32x4_t { transmute(a) } @@ -7732,7 +7888,7 @@ pub unsafe fn vreinterpretq_u32_f64(a: float64x2_t) -> uint32x4_t { /// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vreinterpretq_u64_f64(a: float64x2_t) -> uint64x2_t { transmute(a) } @@ -7740,7 +7896,7 @@ pub unsafe fn vreinterpretq_u64_f64(a: float64x2_t) -> uint64x2_t { /// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vreinterpret_p8_f64(a: float64x1_t) -> poly8x8_t { transmute(a) } @@ -7748,7 +7904,7 @@ pub unsafe fn vreinterpret_p8_f64(a: float64x1_t) -> poly8x8_t { /// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vreinterpret_p16_f64(a: float64x1_t) -> poly16x4_t { transmute(a) } @@ -7756,7 +7912,7 @@ pub unsafe fn vreinterpret_p16_f64(a: float64x1_t) -> poly16x4_t { /// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vreinterpret_p64_f32(a: float32x2_t) -> poly64x1_t { transmute(a) } @@ -7764,7 +7920,7 @@ pub unsafe fn vreinterpret_p64_f32(a: float32x2_t) -> poly64x1_t { /// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vreinterpret_p64_f64(a: float64x1_t) -> poly64x1_t { transmute(a) } @@ -7772,7 +7928,7 @@ pub unsafe fn vreinterpret_p64_f64(a: float64x1_t) -> poly64x1_t { /// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vreinterpretq_p8_f64(a: float64x2_t) -> poly8x16_t { transmute(a) } @@ -7780,7 +7936,7 @@ pub unsafe fn vreinterpretq_p8_f64(a: float64x2_t) -> poly8x16_t { /// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vreinterpretq_p16_f64(a: float64x2_t) -> poly16x8_t { transmute(a) } @@ -7788,7 +7944,7 @@ pub unsafe fn vreinterpretq_p16_f64(a: float64x2_t) -> poly16x8_t { /// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vreinterpretq_p64_f32(a: float32x4_t) -> poly64x2_t { transmute(a) } @@ -7796,7 +7952,7 @@ pub unsafe fn vreinterpretq_p64_f32(a: float32x4_t) -> poly64x2_t { /// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vreinterpretq_p64_f64(a: float64x2_t) -> poly64x2_t { transmute(a) } @@ -7804,7 +7960,7 @@ pub unsafe fn vreinterpretq_p64_f64(a: float64x2_t) -> poly64x2_t { /// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vreinterpret_f64_s8(a: int8x8_t) -> float64x1_t { transmute(a) } @@ -7812,7 +7968,7 @@ pub unsafe fn vreinterpret_f64_s8(a: int8x8_t) -> float64x1_t { /// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vreinterpret_f64_s16(a: int16x4_t) -> float64x1_t { transmute(a) } @@ -7820,7 +7976,7 @@ pub unsafe fn vreinterpret_f64_s16(a: int16x4_t) -> float64x1_t { /// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vreinterpret_f64_s32(a: int32x2_t) -> float64x1_t { transmute(a) } @@ -7828,7 +7984,7 @@ pub unsafe fn vreinterpret_f64_s32(a: int32x2_t) -> float64x1_t { /// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vreinterpret_f64_s64(a: int64x1_t) -> float64x1_t { transmute(a) } @@ -7836,7 +7992,7 @@ pub unsafe fn vreinterpret_f64_s64(a: int64x1_t) -> float64x1_t { /// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vreinterpretq_f64_s8(a: int8x16_t) -> float64x2_t { transmute(a) } @@ -7844,7 +8000,7 @@ pub unsafe fn vreinterpretq_f64_s8(a: int8x16_t) -> float64x2_t { /// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vreinterpretq_f64_s16(a: int16x8_t) -> float64x2_t { transmute(a) } @@ -7852,7 +8008,7 @@ pub unsafe fn vreinterpretq_f64_s16(a: int16x8_t) -> float64x2_t { /// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vreinterpretq_f64_s32(a: int32x4_t) -> float64x2_t { transmute(a) } @@ -7860,7 +8016,7 @@ pub unsafe fn vreinterpretq_f64_s32(a: int32x4_t) -> float64x2_t { /// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vreinterpretq_f64_s64(a: int64x2_t) -> float64x2_t { transmute(a) } @@ -7868,7 +8024,7 @@ pub unsafe fn vreinterpretq_f64_s64(a: int64x2_t) -> float64x2_t { /// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vreinterpret_f64_p8(a: poly8x8_t) -> float64x1_t { transmute(a) } @@ -7876,7 +8032,7 @@ pub unsafe fn vreinterpret_f64_p8(a: poly8x8_t) -> float64x1_t { /// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vreinterpret_f64_u16(a: uint16x4_t) -> float64x1_t { transmute(a) } @@ -7884,7 +8040,7 @@ pub unsafe fn vreinterpret_f64_u16(a: uint16x4_t) -> float64x1_t { /// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vreinterpret_f64_u32(a: uint32x2_t) -> float64x1_t { transmute(a) } @@ -7892,7 +8048,7 @@ pub unsafe fn vreinterpret_f64_u32(a: uint32x2_t) -> float64x1_t { /// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vreinterpret_f64_u64(a: uint64x1_t) -> float64x1_t { transmute(a) } @@ -7900,7 +8056,7 @@ pub unsafe fn vreinterpret_f64_u64(a: uint64x1_t) -> float64x1_t { /// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vreinterpretq_f64_p8(a: poly8x16_t) -> float64x2_t { transmute(a) } @@ -7908,7 +8064,7 @@ pub unsafe fn vreinterpretq_f64_p8(a: poly8x16_t) -> float64x2_t { /// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vreinterpretq_f64_u16(a: uint16x8_t) -> float64x2_t { transmute(a) } @@ -7916,7 +8072,7 @@ pub unsafe fn vreinterpretq_f64_u16(a: uint16x8_t) -> float64x2_t { /// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vreinterpretq_f64_u32(a: uint32x4_t) -> float64x2_t { transmute(a) } @@ -7924,7 +8080,7 @@ pub unsafe fn vreinterpretq_f64_u32(a: uint32x4_t) -> float64x2_t { /// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vreinterpretq_f64_u64(a: uint64x2_t) -> float64x2_t { transmute(a) } @@ -7932,7 +8088,7 @@ pub unsafe fn vreinterpretq_f64_u64(a: uint64x2_t) -> float64x2_t { /// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vreinterpret_f64_u8(a: uint8x8_t) -> float64x1_t { transmute(a) } @@ -7940,7 +8096,7 @@ pub unsafe fn vreinterpret_f64_u8(a: uint8x8_t) -> float64x1_t { /// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vreinterpret_f64_p16(a: poly16x4_t) -> float64x1_t { transmute(a) } @@ -7948,7 +8104,7 @@ pub unsafe fn vreinterpret_f64_p16(a: poly16x4_t) -> float64x1_t { /// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vreinterpret_f64_p64(a: poly64x1_t) -> float64x1_t { transmute(a) } @@ -7956,7 +8112,7 @@ pub unsafe fn vreinterpret_f64_p64(a: poly64x1_t) -> float64x1_t { /// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vreinterpret_f32_p64(a: poly64x1_t) -> float32x2_t { transmute(a) } @@ -7964,7 +8120,7 @@ pub unsafe fn vreinterpret_f32_p64(a: poly64x1_t) -> float32x2_t { /// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vreinterpretq_f64_u8(a: uint8x16_t) -> float64x2_t { transmute(a) } @@ -7972,7 +8128,7 @@ pub unsafe fn vreinterpretq_f64_u8(a: uint8x16_t) -> float64x2_t { /// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vreinterpretq_f64_p16(a: poly16x8_t) -> float64x2_t { transmute(a) } @@ -7980,7 +8136,7 @@ pub unsafe fn vreinterpretq_f64_p16(a: poly16x8_t) -> float64x2_t { /// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vreinterpretq_f64_p64(a: poly64x2_t) -> float64x2_t { transmute(a) } @@ -7988,7 +8144,7 @@ pub unsafe fn vreinterpretq_f64_p64(a: poly64x2_t) -> float64x2_t { /// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vreinterpretq_f32_p64(a: poly64x2_t) -> float32x4_t { transmute(a) } @@ -7996,7 +8152,7 @@ pub unsafe fn vreinterpretq_f32_p64(a: poly64x2_t) -> float32x4_t { /// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vreinterpret_f64_f32(a: float32x2_t) -> float64x1_t { transmute(a) } @@ -8004,7 +8160,7 @@ pub unsafe fn vreinterpret_f64_f32(a: float32x2_t) -> float64x1_t { /// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vreinterpret_f32_f64(a: float64x1_t) -> float32x2_t { transmute(a) } @@ -8012,7 +8168,7 @@ pub unsafe fn vreinterpret_f32_f64(a: float64x1_t) -> float32x2_t { /// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vreinterpretq_f64_f32(a: float32x4_t) -> float64x2_t { transmute(a) } @@ -8020,7 +8176,7 @@ pub unsafe fn vreinterpretq_f64_f32(a: float32x4_t) -> float64x2_t { /// Vector reinterpret cast operation #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vreinterpretq_f32_f64(a: float64x2_t) -> float32x4_t { transmute(a) } @@ -8031,7 +8187,7 @@ pub unsafe fn vreinterpretq_f32_f64(a: float64x2_t) -> float32x4_t { #[cfg_attr(test, assert_instr(srshl))] pub unsafe fn vrshld_s64(a: i64, b: i64) -> i64 { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.srshl.i64")] fn vrshld_s64_(a: i64, b: i64) -> i64; } @@ -8044,7 +8200,7 @@ pub unsafe fn vrshld_s64(a: i64, b: i64) -> i64 { #[cfg_attr(test, assert_instr(urshl))] pub unsafe fn vrshld_u64(a: u64, b: i64) -> u64 { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.urshl.i64")] fn vrshld_u64_(a: u64, b: i64) -> u64; } @@ -9446,7 +9602,7 @@ pub unsafe fn vabal_high_s32(a: int64x2_t, b: int32x4_t, c: int32x4_t) -> int64x #[cfg_attr(test, assert_instr(sqabs))] pub unsafe fn vqabs_s64(a: int64x1_t) -> int64x1_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqabs.v1i64")] fn vqabs_s64_(a: int64x1_t) -> int64x1_t; } @@ -9459,7 +9615,7 @@ pub unsafe fn vqabs_s64(a: int64x1_t) -> int64x1_t { #[cfg_attr(test, assert_instr(sqabs))] pub unsafe fn vqabsq_s64(a: int64x2_t) -> int64x2_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqabs.v2i64")] fn vqabsq_s64_(a: int64x2_t) -> int64x2_t; } @@ -12857,6 +13013,108 @@ mod test { 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + assert_eq!(r, e); + } + #[simd_test(enable = "neon")] unsafe fn test_vmul_f64() { let a: f64 = 1.0; 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 95aea69ef7..f40ed5c338 100644 --- a/library/stdarch/crates/core_arch/src/aarch64/neon/mod.rs +++ b/library/stdarch/crates/core_arch/src/aarch64/neon/mod.rs @@ -12,8 +12,8 @@ pub use self::generated::*; use crate::{ core_arch::{arm_shared::*, simd::*, simd_llvm::*}, hint::unreachable_unchecked, - mem::{size_of, transmute, zeroed}, - ptr::copy_nonoverlapping, + mem::{transmute, zeroed}, + ptr::{read_unaligned, write_unaligned}, }; #[cfg(test)] use stdarch_test::assert_instr; @@ -25,48 +25,38 @@ types! { pub struct float64x2_t(f64, f64); } -/// ARM-specific type containing two `int8x16_t` vectors. +/// ARM-specific type containing two `float64x1_t` vectors. #[derive(Copy, Clone)] -pub struct int8x16x2_t(pub int8x16_t, pub int8x16_t); -/// ARM-specific type containing three `int8x16_t` vectors. +pub struct float64x1x2_t(pub float64x1_t, pub float64x1_t); +/// ARM-specific type containing three `float64x1_t` vectors. #[derive(Copy, Clone)] -pub struct int8x16x3_t(pub int8x16_t, pub int8x16_t, pub int8x16_t); -/// ARM-specific type containing four `int8x16_t` vectors. +pub struct float64x1x3_t(pub float64x1_t, pub float64x1_t, pub float64x1_t); +/// ARM-specific type containing four `float64x1_t` vectors. #[derive(Copy, Clone)] -pub struct int8x16x4_t(pub int8x16_t, pub int8x16_t, pub int8x16_t, pub int8x16_t); - -/// ARM-specific type containing two `uint8x16_t` vectors. -#[derive(Copy, Clone)] -pub struct uint8x16x2_t(pub uint8x16_t, pub uint8x16_t); -/// ARM-specific type containing three `uint8x16_t` vectors. -#[derive(Copy, Clone)] -pub struct uint8x16x3_t(pub uint8x16_t, pub uint8x16_t, pub uint8x16_t); -/// ARM-specific type containing four `uint8x16_t` vectors. -#[derive(Copy, Clone)] -pub struct uint8x16x4_t( - pub uint8x16_t, - pub uint8x16_t, - pub uint8x16_t, - pub uint8x16_t, +pub struct float64x1x4_t( + pub float64x1_t, + pub float64x1_t, + pub float64x1_t, + pub float64x1_t, ); -/// ARM-specific type containing two `poly8x16_t` vectors. +/// ARM-specific type containing two `float64x2_t` vectors. #[derive(Copy, Clone)] -pub struct poly8x16x2_t(pub poly8x16_t, pub poly8x16_t); -/// ARM-specific type containing three `poly8x16_t` vectors. +pub struct float64x2x2_t(pub float64x2_t, pub float64x2_t); +/// ARM-specific type containing three `float64x2_t` vectors. #[derive(Copy, Clone)] -pub struct poly8x16x3_t(pub poly8x16_t, pub poly8x16_t, pub poly8x16_t); -/// ARM-specific type containing four `poly8x16_t` vectors. +pub struct float64x2x3_t(pub float64x2_t, pub float64x2_t, pub float64x2_t); +/// ARM-specific type containing four `float64x2_t` vectors. #[derive(Copy, Clone)] -pub struct poly8x16x4_t( - pub poly8x16_t, - pub poly8x16_t, - pub poly8x16_t, - pub poly8x16_t, +pub struct float64x2x4_t( + pub float64x2_t, + pub float64x2_t, + pub float64x2_t, + pub float64x2_t, ); #[allow(improper_ctypes)] -extern "C" { +extern "unadjusted" { // absolute value #[link_name = "llvm.aarch64.neon.abs.i64"] fn vabsd_s64_(a: i64) -> i64; @@ -474,16 +464,7 @@ pub unsafe fn vcopy_laneq_f64( #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ldr))] pub unsafe fn vld1_s8(ptr: *const i8) -> int8x8_t { - transmute(i8x8::new( - *ptr, - *ptr.offset(1), - *ptr.offset(2), - *ptr.offset(3), - *ptr.offset(4), - *ptr.offset(5), - *ptr.offset(6), - *ptr.offset(7), - )) + read_unaligned(ptr.cast()) } /// Load multiple single-element structures to one, two, three, or four registers. @@ -491,24 +472,7 @@ pub unsafe fn vld1_s8(ptr: *const i8) -> int8x8_t { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ldr))] pub unsafe fn vld1q_s8(ptr: *const i8) -> int8x16_t { - transmute(i8x16::new( - *ptr, - *ptr.offset(1), - *ptr.offset(2), - *ptr.offset(3), - *ptr.offset(4), - *ptr.offset(5), - *ptr.offset(6), - *ptr.offset(7), - *ptr.offset(8), - *ptr.offset(9), - *ptr.offset(10), - *ptr.offset(11), - *ptr.offset(12), - *ptr.offset(13), - *ptr.offset(14), - *ptr.offset(15), - )) + read_unaligned(ptr.cast()) } /// Load multiple single-element structures to one, two, three, or four registers. @@ -516,12 +480,7 @@ pub unsafe fn vld1q_s8(ptr: *const i8) -> int8x16_t { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ldr))] pub unsafe fn vld1_s16(ptr: *const i16) -> int16x4_t { - transmute(i16x4::new( - *ptr, - *ptr.offset(1), - *ptr.offset(2), - *ptr.offset(3), - )) + read_unaligned(ptr.cast()) } /// Load multiple single-element structures to one, two, three, or four registers. @@ -529,16 +488,7 @@ pub unsafe fn vld1_s16(ptr: *const i16) -> int16x4_t { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ldr))] pub unsafe fn vld1q_s16(ptr: *const i16) -> int16x8_t { - transmute(i16x8::new( - *ptr, - *ptr.offset(1), - *ptr.offset(2), - *ptr.offset(3), - *ptr.offset(4), - *ptr.offset(5), - *ptr.offset(6), - *ptr.offset(7), - )) + read_unaligned(ptr.cast()) } /// Load multiple single-element structures to one, two, three, or four registers. @@ -546,7 +496,7 @@ pub unsafe fn vld1q_s16(ptr: *const i16) -> int16x8_t { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ldr))] pub unsafe fn vld1_s32(ptr: *const i32) -> int32x2_t { - transmute(i32x2::new(*ptr, *ptr.offset(1))) + read_unaligned(ptr.cast()) } /// Load multiple single-element structures to one, two, three, or four registers. @@ -554,12 +504,7 @@ pub unsafe fn vld1_s32(ptr: *const i32) -> int32x2_t { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ldr))] pub unsafe fn vld1q_s32(ptr: *const i32) -> int32x4_t { - transmute(i32x4::new( - *ptr, - *ptr.offset(1), - *ptr.offset(2), - *ptr.offset(3), - )) + read_unaligned(ptr.cast()) } /// Load multiple single-element structures to one, two, three, or four registers. @@ -567,7 +512,7 @@ pub unsafe fn vld1q_s32(ptr: *const i32) -> int32x4_t { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ldr))] pub unsafe fn vld1_s64(ptr: *const i64) -> int64x1_t { - transmute(i64x1::new(*ptr)) + read_unaligned(ptr.cast()) } /// Load multiple single-element structures to one, two, three, or four registers. @@ -575,7 +520,7 @@ pub unsafe fn vld1_s64(ptr: *const i64) -> int64x1_t { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ldr))] pub unsafe fn vld1q_s64(ptr: *const i64) -> int64x2_t { - transmute(i64x2::new(*ptr, *ptr.offset(1))) + read_unaligned(ptr.cast()) } /// Load multiple single-element structures to one, two, three, or four registers. @@ -583,16 +528,7 @@ pub unsafe fn vld1q_s64(ptr: *const i64) -> int64x2_t { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ldr))] pub unsafe fn vld1_u8(ptr: *const u8) -> uint8x8_t { - transmute(u8x8::new( - *ptr, - *ptr.offset(1), - *ptr.offset(2), - *ptr.offset(3), - *ptr.offset(4), - *ptr.offset(5), - *ptr.offset(6), - *ptr.offset(7), - )) + read_unaligned(ptr.cast()) } /// Load multiple single-element structures to one, two, three, or four registers. @@ -600,24 +536,7 @@ pub unsafe fn vld1_u8(ptr: *const u8) -> uint8x8_t { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ldr))] pub unsafe fn vld1q_u8(ptr: *const u8) -> uint8x16_t { - transmute(u8x16::new( - *ptr, - *ptr.offset(1), - *ptr.offset(2), - *ptr.offset(3), - *ptr.offset(4), - *ptr.offset(5), - *ptr.offset(6), - *ptr.offset(7), - *ptr.offset(8), - *ptr.offset(9), - *ptr.offset(10), - *ptr.offset(11), - *ptr.offset(12), - *ptr.offset(13), - *ptr.offset(14), - *ptr.offset(15), - )) + read_unaligned(ptr.cast()) } /// Load multiple single-element structures to one, two, three, or four registers. @@ -625,12 +544,7 @@ pub unsafe fn vld1q_u8(ptr: *const u8) -> uint8x16_t { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ldr))] pub unsafe fn vld1_u16(ptr: *const u16) -> uint16x4_t { - transmute(u16x4::new( - *ptr, - *ptr.offset(1), - *ptr.offset(2), - *ptr.offset(3), - )) + read_unaligned(ptr.cast()) } /// Load multiple single-element structures to one, two, three, or four registers. @@ -638,16 +552,7 @@ pub unsafe fn vld1_u16(ptr: *const u16) -> uint16x4_t { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ldr))] pub unsafe fn vld1q_u16(ptr: *const u16) -> uint16x8_t { - transmute(u16x8::new( - *ptr, - *ptr.offset(1), - *ptr.offset(2), - *ptr.offset(3), - *ptr.offset(4), - *ptr.offset(5), - *ptr.offset(6), - *ptr.offset(7), - )) + read_unaligned(ptr.cast()) } /// Load multiple single-element structures to one, two, three, or four registers. @@ -655,7 +560,7 @@ pub unsafe fn vld1q_u16(ptr: *const u16) -> uint16x8_t { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ldr))] pub unsafe fn vld1_u32(ptr: *const u32) -> uint32x2_t { - transmute(u32x2::new(*ptr, *ptr.offset(1))) + read_unaligned(ptr.cast()) } /// Load multiple single-element structures to one, two, three, or four registers. @@ -663,12 +568,7 @@ pub unsafe fn vld1_u32(ptr: *const u32) -> uint32x2_t { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ldr))] pub unsafe fn vld1q_u32(ptr: *const u32) -> uint32x4_t { - transmute(u32x4::new( - *ptr, - *ptr.offset(1), - *ptr.offset(2), - *ptr.offset(3), - )) + read_unaligned(ptr.cast()) } /// Load multiple single-element structures to one, two, three, or four registers. @@ -676,7 +576,7 @@ pub unsafe fn vld1q_u32(ptr: *const u32) -> uint32x4_t { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ldr))] pub unsafe fn vld1_u64(ptr: *const u64) -> uint64x1_t { - transmute(u64x1::new(*ptr)) + read_unaligned(ptr.cast()) } /// Load multiple single-element structures to one, two, three, or four registers. @@ -684,7 +584,7 @@ pub unsafe fn vld1_u64(ptr: *const u64) -> uint64x1_t { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ldr))] pub unsafe fn vld1q_u64(ptr: *const u64) -> uint64x2_t { - transmute(u64x2::new(*ptr, *ptr.offset(1))) + read_unaligned(ptr.cast()) } /// Load multiple single-element structures to one, two, three, or four registers. @@ -692,16 +592,7 @@ pub unsafe fn vld1q_u64(ptr: *const u64) -> uint64x2_t { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ldr))] pub unsafe fn vld1_p8(ptr: *const p8) -> poly8x8_t { - transmute(u8x8::new( - *ptr, - *ptr.offset(1), - *ptr.offset(2), - *ptr.offset(3), - *ptr.offset(4), - *ptr.offset(5), - *ptr.offset(6), - *ptr.offset(7), - )) + read_unaligned(ptr.cast()) } /// Load multiple single-element structures to one, two, three, or four registers. @@ -709,24 +600,7 @@ pub unsafe fn vld1_p8(ptr: *const p8) -> poly8x8_t { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ldr))] pub unsafe fn vld1q_p8(ptr: *const p8) -> poly8x16_t { - transmute(u8x16::new( - *ptr, - *ptr.offset(1), - *ptr.offset(2), - *ptr.offset(3), - *ptr.offset(4), - *ptr.offset(5), - *ptr.offset(6), - *ptr.offset(7), - *ptr.offset(8), - *ptr.offset(9), - *ptr.offset(10), - *ptr.offset(11), - *ptr.offset(12), - *ptr.offset(13), - *ptr.offset(14), - *ptr.offset(15), - )) + read_unaligned(ptr.cast()) } /// Load multiple single-element structures to one, two, three, or four registers. @@ -734,12 +608,7 @@ pub unsafe fn vld1q_p8(ptr: *const p8) -> poly8x16_t { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ldr))] pub unsafe fn vld1_p16(ptr: *const p16) -> poly16x4_t { - transmute(u16x4::new( - *ptr, - *ptr.offset(1), - *ptr.offset(2), - *ptr.offset(3), - )) + read_unaligned(ptr.cast()) } /// Load multiple single-element structures to one, two, three, or four registers. @@ -747,16 +616,23 @@ pub unsafe fn vld1_p16(ptr: *const p16) -> poly16x4_t { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ldr))] pub unsafe fn vld1q_p16(ptr: *const p16) -> poly16x8_t { - transmute(u16x8::new( - *ptr, - *ptr.offset(1), - *ptr.offset(2), - *ptr.offset(3), - *ptr.offset(4), - *ptr.offset(5), - *ptr.offset(6), - *ptr.offset(7), - )) + read_unaligned(ptr.cast()) +} + +/// Load multiple single-element structures to one, two, three, or four registers. +#[inline] +#[target_feature(enable = "neon,aes")] +#[cfg_attr(test, assert_instr(ldr))] +pub unsafe fn vld1_p64(ptr: *const p64) -> poly64x1_t { + read_unaligned(ptr.cast()) +} + +/// Load multiple single-element structures to one, two, three, or four registers. +#[inline] +#[target_feature(enable = "neon,aes")] +#[cfg_attr(test, assert_instr(ldr))] +pub unsafe fn vld1q_p64(ptr: *const p64) -> poly64x2_t { + read_unaligned(ptr.cast()) } /// Load multiple single-element structures to one, two, three, or four registers. @@ -764,7 +640,7 @@ pub unsafe fn vld1q_p16(ptr: *const p16) -> poly16x8_t { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ldr))] pub unsafe fn vld1_f32(ptr: *const f32) -> float32x2_t { - transmute(f32x2::new(*ptr, *ptr.offset(1))) + read_unaligned(ptr.cast()) } /// Load multiple single-element structures to one, two, three, or four registers. @@ -772,12 +648,7 @@ pub unsafe fn vld1_f32(ptr: *const f32) -> float32x2_t { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ldr))] pub unsafe fn vld1q_f32(ptr: *const f32) -> float32x4_t { - transmute(f32x4::new( - *ptr, - *ptr.offset(1), - *ptr.offset(2), - *ptr.offset(3), - )) + read_unaligned(ptr.cast()) } /// Load multiple single-element structures to one, two, three, or four registers. @@ -785,7 +656,7 @@ pub unsafe fn vld1q_f32(ptr: *const f32) -> float32x4_t { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ldr))] pub unsafe fn vld1_f64(ptr: *const f64) -> float64x1_t { - transmute(f64x1::new(*ptr)) + read_unaligned(ptr.cast()) } /// Load multiple single-element structures to one, two, three, or four registers. @@ -793,7 +664,44 @@ pub unsafe fn vld1_f64(ptr: *const f64) -> float64x1_t { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ldr))] pub unsafe fn vld1q_f64(ptr: *const f64) -> float64x2_t { - transmute(f64x2::new(*ptr, *ptr.offset(1))) + read_unaligned(ptr.cast()) +} + +/// Load multiple single-element structures to one, two, three, or four registers +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(ldr))] +pub unsafe fn vld1_dup_f64(ptr: *const f64) -> float64x1_t { + vld1_f64(ptr) +} + +/// Load multiple single-element structures to one, two, three, or four registers +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(ldr))] +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]) +} + +/// Load one single-element structure to one lane of one register. +#[inline] +#[target_feature(enable = "neon")] +#[rustc_legacy_const_generics(2)] +#[cfg_attr(test, assert_instr(ldr, LANE = 0))] +pub unsafe fn vld1_lane_f64(ptr: *const f64, src: float64x1_t) -> float64x1_t { + static_assert!(LANE : i32 where LANE == 0); + simd_insert(src, LANE as u32, *ptr) +} + +/// Load one single-element structure to one lane of one register. +#[inline] +#[target_feature(enable = "neon")] +#[rustc_legacy_const_generics(2)] +#[cfg_attr(test, assert_instr(ldr, 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) } /// Store multiple single-element structures from one, two, three, or four registers. @@ -802,11 +710,7 @@ pub unsafe fn vld1q_f64(ptr: *const f64) -> float64x2_t { #[cfg_attr(test, assert_instr(str))] #[allow(clippy::cast_ptr_alignment)] pub unsafe fn vst1_s8(ptr: *mut i8, a: int8x8_t) { - copy_nonoverlapping( - &a as *const int8x8_t as *const i8, - ptr as *mut i8, - size_of::(), - ) + write_unaligned(ptr.cast(), a); } /// Store multiple single-element structures from one, two, three, or four registers. @@ -815,11 +719,7 @@ pub unsafe fn vst1_s8(ptr: *mut i8, a: int8x8_t) { #[cfg_attr(test, assert_instr(str))] #[allow(clippy::cast_ptr_alignment)] pub unsafe fn vst1q_s8(ptr: *mut i8, a: int8x16_t) { - copy_nonoverlapping( - &a as *const int8x16_t as *const i8, - ptr as *mut i8, - size_of::(), - ) + write_unaligned(ptr.cast(), a); } /// Store multiple single-element structures from one, two, three, or four registers. @@ -828,11 +728,7 @@ pub unsafe fn vst1q_s8(ptr: *mut i8, a: int8x16_t) { #[cfg_attr(test, assert_instr(str))] #[allow(clippy::cast_ptr_alignment)] pub unsafe fn vst1_s16(ptr: *mut i16, a: int16x4_t) { - copy_nonoverlapping( - &a as *const int16x4_t as *const i16, - ptr as *mut i16, - size_of::(), - ) + write_unaligned(ptr.cast(), a); } /// Store multiple single-element structures from one, two, three, or four registers. @@ -841,11 +737,7 @@ pub unsafe fn vst1_s16(ptr: *mut i16, a: int16x4_t) { #[cfg_attr(test, assert_instr(str))] #[allow(clippy::cast_ptr_alignment)] pub unsafe fn vst1q_s16(ptr: *mut i16, a: int16x8_t) { - copy_nonoverlapping( - &a as *const int16x8_t as *const i16, - ptr as *mut i16, - size_of::(), - ) + write_unaligned(ptr.cast(), a); } /// Store multiple single-element structures from one, two, three, or four registers. @@ -854,11 +746,7 @@ pub unsafe fn vst1q_s16(ptr: *mut i16, a: int16x8_t) { #[cfg_attr(test, assert_instr(str))] #[allow(clippy::cast_ptr_alignment)] pub unsafe fn vst1_s32(ptr: *mut i32, a: int32x2_t) { - copy_nonoverlapping( - &a as *const int32x2_t as *const i32, - ptr as *mut i32, - size_of::(), - ) + write_unaligned(ptr.cast(), a); } /// Store multiple single-element structures from one, two, three, or four registers. @@ -867,11 +755,7 @@ pub unsafe fn vst1_s32(ptr: *mut i32, a: int32x2_t) { #[cfg_attr(test, assert_instr(str))] #[allow(clippy::cast_ptr_alignment)] pub unsafe fn vst1q_s32(ptr: *mut i32, a: int32x4_t) { - copy_nonoverlapping( - &a as *const int32x4_t as *const i32, - ptr as *mut i32, - size_of::(), - ) + write_unaligned(ptr.cast(), a); } /// Store multiple single-element structures from one, two, three, or four registers. @@ -880,11 +764,7 @@ pub unsafe fn vst1q_s32(ptr: *mut i32, a: int32x4_t) { #[cfg_attr(test, assert_instr(str))] #[allow(clippy::cast_ptr_alignment)] pub unsafe fn vst1_s64(ptr: *mut i64, a: int64x1_t) { - copy_nonoverlapping( - &a as *const int64x1_t as *const i64, - ptr as *mut i64, - size_of::(), - ) + write_unaligned(ptr.cast(), a); } /// Store multiple single-element structures from one, two, three, or four registers. @@ -893,11 +773,7 @@ pub unsafe fn vst1_s64(ptr: *mut i64, a: int64x1_t) { #[cfg_attr(test, assert_instr(str))] #[allow(clippy::cast_ptr_alignment)] pub unsafe fn vst1q_s64(ptr: *mut i64, a: int64x2_t) { - copy_nonoverlapping( - &a as *const int64x2_t as *const i64, - ptr as *mut i64, - size_of::(), - ) + write_unaligned(ptr.cast(), a); } /// Store multiple single-element structures from one, two, three, or four registers. @@ -906,11 +782,7 @@ pub unsafe fn vst1q_s64(ptr: *mut i64, a: int64x2_t) { #[cfg_attr(test, assert_instr(str))] #[allow(clippy::cast_ptr_alignment)] pub unsafe fn vst1_u8(ptr: *mut u8, a: uint8x8_t) { - copy_nonoverlapping( - &a as *const uint8x8_t as *const u8, - ptr as *mut u8, - size_of::(), - ) + write_unaligned(ptr.cast(), a); } /// Store multiple single-element structures from one, two, three, or four registers. @@ -919,11 +791,7 @@ pub unsafe fn vst1_u8(ptr: *mut u8, a: uint8x8_t) { #[cfg_attr(test, assert_instr(str))] #[allow(clippy::cast_ptr_alignment)] pub unsafe fn vst1q_u8(ptr: *mut u8, a: uint8x16_t) { - copy_nonoverlapping( - &a as *const uint8x16_t as *const u8, - ptr as *mut u8, - size_of::(), - ) + write_unaligned(ptr.cast(), a); } /// Store multiple single-element structures from one, two, three, or four registers. @@ -932,11 +800,7 @@ pub unsafe fn vst1q_u8(ptr: *mut u8, a: uint8x16_t) { #[cfg_attr(test, assert_instr(str))] #[allow(clippy::cast_ptr_alignment)] pub unsafe fn vst1_u16(ptr: *mut u16, a: uint16x4_t) { - copy_nonoverlapping( - &a as *const uint16x4_t as *const u16, - ptr as *mut u16, - size_of::(), - ) + write_unaligned(ptr.cast(), a); } /// Store multiple single-element structures from one, two, three, or four registers. @@ -945,11 +809,7 @@ pub unsafe fn vst1_u16(ptr: *mut u16, a: uint16x4_t) { #[cfg_attr(test, assert_instr(str))] #[allow(clippy::cast_ptr_alignment)] pub unsafe fn vst1q_u16(ptr: *mut u16, a: uint16x8_t) { - copy_nonoverlapping( - &a as *const uint16x8_t as *const u16, - ptr as *mut u16, - size_of::(), - ) + write_unaligned(ptr.cast(), a); } /// Store multiple single-element structures from one, two, three, or four registers. @@ -958,11 +818,7 @@ pub unsafe fn vst1q_u16(ptr: *mut u16, a: uint16x8_t) { #[cfg_attr(test, assert_instr(str))] #[allow(clippy::cast_ptr_alignment)] pub unsafe fn vst1_u32(ptr: *mut u32, a: uint32x2_t) { - copy_nonoverlapping( - &a as *const uint32x2_t as *const u32, - ptr as *mut u32, - size_of::(), - ) + write_unaligned(ptr.cast(), a); } /// Store multiple single-element structures from one, two, three, or four registers. @@ -971,11 +827,7 @@ pub unsafe fn vst1_u32(ptr: *mut u32, a: uint32x2_t) { #[cfg_attr(test, assert_instr(str))] #[allow(clippy::cast_ptr_alignment)] pub unsafe fn vst1q_u32(ptr: *mut u32, a: uint32x4_t) { - copy_nonoverlapping( - &a as *const uint32x4_t as *const u32, - ptr as *mut u32, - size_of::(), - ) + write_unaligned(ptr.cast(), a); } /// Store multiple single-element structures from one, two, three, or four registers. @@ -984,11 +836,7 @@ pub unsafe fn vst1q_u32(ptr: *mut u32, a: uint32x4_t) { #[cfg_attr(test, assert_instr(str))] #[allow(clippy::cast_ptr_alignment)] pub unsafe fn vst1_u64(ptr: *mut u64, a: uint64x1_t) { - copy_nonoverlapping( - &a as *const uint64x1_t as *const u64, - ptr as *mut u64, - size_of::(), - ) + write_unaligned(ptr.cast(), a); } /// Store multiple single-element structures from one, two, three, or four registers. @@ -997,11 +845,7 @@ pub unsafe fn vst1_u64(ptr: *mut u64, a: uint64x1_t) { #[cfg_attr(test, assert_instr(str))] #[allow(clippy::cast_ptr_alignment)] pub unsafe fn vst1q_u64(ptr: *mut u64, a: uint64x2_t) { - copy_nonoverlapping( - &a as *const uint64x2_t as *const u64, - ptr as *mut u64, - size_of::(), - ) + write_unaligned(ptr.cast(), a); } /// Store multiple single-element structures from one, two, three, or four registers. @@ -1010,11 +854,7 @@ pub unsafe fn vst1q_u64(ptr: *mut u64, a: uint64x2_t) { #[cfg_attr(test, assert_instr(str))] #[allow(clippy::cast_ptr_alignment)] pub unsafe fn vst1_p8(ptr: *mut p8, a: poly8x8_t) { - copy_nonoverlapping( - &a as *const poly8x8_t as *const p8, - ptr as *mut p8, - size_of::(), - ) + write_unaligned(ptr.cast(), a); } /// Store multiple single-element structures from one, two, three, or four registers. @@ -1023,11 +863,7 @@ pub unsafe fn vst1_p8(ptr: *mut p8, a: poly8x8_t) { #[cfg_attr(test, assert_instr(str))] #[allow(clippy::cast_ptr_alignment)] pub unsafe fn vst1q_p8(ptr: *mut p8, a: poly8x16_t) { - copy_nonoverlapping( - &a as *const poly8x16_t as *const p8, - ptr as *mut p8, - size_of::(), - ) + write_unaligned(ptr.cast(), a); } /// Store multiple single-element structures from one, two, three, or four registers. @@ -1036,11 +872,7 @@ pub unsafe fn vst1q_p8(ptr: *mut p8, a: poly8x16_t) { #[cfg_attr(test, assert_instr(str))] #[allow(clippy::cast_ptr_alignment)] pub unsafe fn vst1_p16(ptr: *mut p16, a: poly16x4_t) { - copy_nonoverlapping( - &a as *const poly16x4_t as *const p16, - ptr as *mut p16, - size_of::(), - ) + write_unaligned(ptr.cast(), a); } /// Store multiple single-element structures from one, two, three, or four registers. @@ -1049,11 +881,7 @@ pub unsafe fn vst1_p16(ptr: *mut p16, a: poly16x4_t) { #[cfg_attr(test, assert_instr(str))] #[allow(clippy::cast_ptr_alignment)] pub unsafe fn vst1q_p16(ptr: *mut p16, a: poly16x8_t) { - copy_nonoverlapping( - &a as *const poly16x8_t as *const p16, - ptr as *mut p16, - size_of::(), - ) + write_unaligned(ptr.cast(), a); } // Store multiple single-element structures from one, two, three, or four registers. @@ -1062,11 +890,7 @@ pub unsafe fn vst1q_p16(ptr: *mut p16, a: poly16x8_t) { #[cfg_attr(test, assert_instr(str))] #[allow(clippy::cast_ptr_alignment)] pub unsafe fn vst1_p64(ptr: *mut p64, a: poly64x1_t) { - copy_nonoverlapping( - &a as *const poly64x1_t as *const p64, - ptr as *mut p64, - size_of::(), - ) + write_unaligned(ptr.cast(), a); } // Store multiple single-element structures from one, two, three, or four registers. @@ -1075,11 +899,7 @@ pub unsafe fn vst1_p64(ptr: *mut p64, a: poly64x1_t) { #[cfg_attr(test, assert_instr(str))] #[allow(clippy::cast_ptr_alignment)] pub unsafe fn vst1q_p64(ptr: *mut p64, a: poly64x2_t) { - copy_nonoverlapping( - &a as *const poly64x2_t as *const p64, - ptr as *mut p64, - size_of::(), - ) + write_unaligned(ptr.cast(), a); } // Store multiple single-element structures from one, two, three, or four registers. @@ -1088,11 +908,7 @@ pub unsafe fn vst1q_p64(ptr: *mut p64, a: poly64x2_t) { #[cfg_attr(test, assert_instr(str))] #[allow(clippy::cast_ptr_alignment)] pub unsafe fn vst1_f32(ptr: *mut f32, a: float32x2_t) { - copy_nonoverlapping( - &a as *const float32x2_t as *const f32, - ptr as *mut f32, - size_of::(), - ) + write_unaligned(ptr.cast(), a); } // Store multiple single-element structures from one, two, three, or four registers. @@ -1101,11 +917,7 @@ pub unsafe fn vst1_f32(ptr: *mut f32, a: float32x2_t) { #[cfg_attr(test, assert_instr(str))] #[allow(clippy::cast_ptr_alignment)] pub unsafe fn vst1q_f32(ptr: *mut f32, a: float32x4_t) { - copy_nonoverlapping( - &a as *const float32x4_t as *const f32, - ptr as *mut f32, - size_of::(), - ) + write_unaligned(ptr.cast(), a); } // Store multiple single-element structures from one, two, three, or four registers. @@ -1114,11 +926,7 @@ pub unsafe fn vst1q_f32(ptr: *mut f32, a: float32x4_t) { #[cfg_attr(test, assert_instr(str))] #[allow(clippy::cast_ptr_alignment)] pub unsafe fn vst1_f64(ptr: *mut f64, a: float64x1_t) { - copy_nonoverlapping( - &a as *const float64x1_t as *const f64, - ptr as *mut f64, - size_of::(), - ) + write_unaligned(ptr.cast(), a); } // Store multiple single-element structures from one, two, three, or four registers. @@ -1127,11 +935,7 @@ pub unsafe fn vst1_f64(ptr: *mut f64, a: float64x1_t) { #[cfg_attr(test, assert_instr(str))] #[allow(clippy::cast_ptr_alignment)] pub unsafe fn vst1q_f64(ptr: *mut f64, a: float64x2_t) { - copy_nonoverlapping( - &a as *const float64x2_t as *const f64, - ptr as *mut f64, - size_of::(), - ) + write_unaligned(ptr.cast(), a); } /// Absolute Value (wrapping). @@ -1905,7 +1709,7 @@ pub unsafe fn vpmaxq_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { /// Extract vector from pair of vectors #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(str, N = 0))] +#[cfg_attr(test, assert_instr(nop, N = 0))] #[rustc_legacy_const_generics(2)] pub unsafe fn vext_p64(a: poly64x1_t, _b: poly64x1_t) -> poly64x1_t { if N != 0 { @@ -1917,7 +1721,7 @@ pub unsafe fn vext_p64(a: poly64x1_t, _b: poly64x1_t) -> poly64x1_ /// Extract vector from pair of vectors #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(str, N = 0))] +#[cfg_attr(test, assert_instr(nop, N = 0))] #[rustc_legacy_const_generics(2)] pub unsafe fn vext_f64(a: float64x1_t, _b: float64x1_t) -> float64x1_t { if N != 0 { @@ -2016,7 +1820,7 @@ pub unsafe fn vdup_n_p64(value: p64) -> poly64x1_t { /// Duplicate vector element to vector or scalar #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(ldr))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vdup_n_f64(value: f64) -> float64x1_t { float64x1_t(value) } @@ -2048,7 +1852,7 @@ pub unsafe fn vmov_n_p64(value: p64) -> poly64x1_t { /// Duplicate vector element to vector or scalar #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(ldr))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vmov_n_f64(value: f64) -> float64x1_t { vdup_n_f64(value) } @@ -2080,7 +1884,7 @@ pub unsafe fn vget_high_f64(a: float64x2_t) -> float64x1_t { /// Duplicate vector element to vector or scalar #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(ldr))] +#[cfg_attr(test, assert_instr(ext))] pub unsafe fn vget_high_p64(a: poly64x2_t) -> poly64x1_t { transmute(u64x1::new(simd_extract(a, 1))) } @@ -2088,7 +1892,7 @@ pub unsafe fn vget_high_p64(a: poly64x2_t) -> poly64x1_t { /// Duplicate vector element to vector or scalar #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(ldr))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vget_low_f64(a: float64x2_t) -> float64x1_t { float64x1_t(simd_extract(a, 0)) } @@ -2096,7 +1900,7 @@ pub unsafe fn vget_low_f64(a: float64x2_t) -> float64x1_t { /// Duplicate vector element to vector or scalar #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(ldr))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vget_low_p64(a: poly64x2_t) -> poly64x1_t { transmute(u64x1::new(simd_extract(a, 0))) } @@ -4949,6 +4753,56 @@ mod tests { assert_eq!(r, e); } + #[simd_test(enable = "neon")] + unsafe fn test_vld1_f64() { + let a: [f64; 2] = [0., 1.]; + let e = f64x1::new(1.); + let r: f64x1 = transmute(vld1_f64(a[1..].as_ptr())); + assert_eq!(r, e) + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1q_f64() { + let a: [f64; 3] = [0., 1., 2.]; + let e = f64x2::new(1., 2.); + let r: f64x2 = transmute(vld1q_f64(a[1..].as_ptr())); + assert_eq!(r, e) + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1_dup_f64() { + let a: [f64; 2] = [1., 42.]; + let e = f64x1::new(42.); + let r: f64x1 = transmute(vld1_dup_f64(a[1..].as_ptr())); + assert_eq!(r, e) + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1q_dup_f64() { + let elem: f64 = 42.; + let e = f64x2::new(42., 42.); + let r: f64x2 = transmute(vld1q_dup_f64(&elem)); + assert_eq!(r, e) + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1_lane_f64() { + let a = f64x1::new(0.); + let elem: f64 = 42.; + let e = f64x1::new(42.); + let r: f64x1 = transmute(vld1_lane_f64::<0>(&elem, transmute(a))); + assert_eq!(r, e) + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1q_lane_f64() { + let a = f64x2::new(0., 1.); + let elem: f64 = 42.; + let e = f64x2::new(0., 42.); + let r: f64x2 = transmute(vld1q_lane_f64::<1>(&elem, transmute(a))); + assert_eq!(r, e) + } + #[simd_test(enable = "neon")] unsafe fn test_vst1_p64() { let mut vals = [0_u64; 2]; diff --git a/library/stdarch/crates/core_arch/src/aarch64/prefetch.rs b/library/stdarch/crates/core_arch/src/aarch64/prefetch.rs index 02b3971aa4..687c3f39a0 100644 --- a/library/stdarch/crates/core_arch/src/aarch64/prefetch.rs +++ b/library/stdarch/crates/core_arch/src/aarch64/prefetch.rs @@ -1,7 +1,7 @@ #[cfg(test)] use stdarch_test::assert_instr; -extern "C" { +extern "unadjusted" { #[link_name = "llvm.prefetch"] fn prefetch(p: *const i8, rw: i32, loc: i32, ty: i32); } diff --git a/library/stdarch/crates/core_arch/src/aarch64/tme.rs b/library/stdarch/crates/core_arch/src/aarch64/tme.rs index edf87b8034..d1b2cf334d 100644 --- a/library/stdarch/crates/core_arch/src/aarch64/tme.rs +++ b/library/stdarch/crates/core_arch/src/aarch64/tme.rs @@ -17,7 +17,7 @@ #[cfg(test)] use stdarch_test::assert_instr; -extern "C" { +extern "unadjusted" { #[link_name = "llvm.aarch64.tstart"] fn aarch64_tstart() -> u64; #[link_name = "llvm.aarch64.tcommit"] diff --git a/library/stdarch/crates/core_arch/src/arm/dsp.rs b/library/stdarch/crates/core_arch/src/arm/dsp.rs index 7039f0351d..6720f97a53 100644 --- a/library/stdarch/crates/core_arch/src/arm/dsp.rs +++ b/library/stdarch/crates/core_arch/src/arm/dsp.rs @@ -32,7 +32,7 @@ types! { pub struct uint16x2_t(u16, u16); } -extern "C" { +extern "unadjusted" { #[link_name = "llvm.arm.smulbb"] fn arm_smulbb(a: i32, b: i32) -> i32; diff --git a/library/stdarch/crates/core_arch/src/arm/ex.rs b/library/stdarch/crates/core_arch/src/arm/ex.rs index 2ad190a786..75f3786425 100644 --- a/library/stdarch/crates/core_arch/src/arm/ex.rs +++ b/library/stdarch/crates/core_arch/src/arm/ex.rs @@ -11,7 +11,7 @@ doc ))] pub unsafe fn __clrex() { - extern "C" { + extern "unadjusted" { #[link_name = "llvm.arm.clrex"] fn clrex(); } @@ -27,7 +27,7 @@ pub unsafe fn __clrex() { doc ))] pub unsafe fn __ldrexb(p: *const u8) -> u8 { - extern "C" { + extern "unadjusted" { #[link_name = "llvm.arm.ldrex.p0i8"] fn ldrex8(p: *const u8) -> u32; } @@ -43,7 +43,7 @@ pub unsafe fn __ldrexb(p: *const u8) -> u8 { doc ))] pub unsafe fn __ldrexh(p: *const u16) -> u16 { - extern "C" { + extern "unadjusted" { #[link_name = "llvm.arm.ldrex.p0i16"] fn ldrex16(p: *const u16) -> u32; } @@ -60,7 +60,7 @@ pub unsafe fn __ldrexh(p: *const u16) -> u16 { doc ))] pub unsafe fn __ldrex(p: *const u32) -> u32 { - extern "C" { + extern "unadjusted" { #[link_name = "llvm.arm.ldrex.p0i32"] fn ldrex32(p: *const u32) -> u32; } @@ -78,7 +78,7 @@ pub unsafe fn __ldrex(p: *const u32) -> u32 { doc ))] pub unsafe fn __strexb(value: u32, addr: *mut u8) -> u32 { - extern "C" { + extern "unadjusted" { #[link_name = "llvm.arm.strex.p0i8"] fn strex8(value: u32, addr: *mut u8) -> u32; } @@ -97,7 +97,7 @@ pub unsafe fn __strexb(value: u32, addr: *mut u8) -> u32 { doc ))] pub unsafe fn __strexh(value: u16, addr: *mut u16) -> u32 { - extern "C" { + extern "unadjusted" { #[link_name = "llvm.arm.strex.p0i16"] fn strex16(value: u32, addr: *mut u16) -> u32; } @@ -116,7 +116,7 @@ pub unsafe fn __strexh(value: u16, addr: *mut u16) -> u32 { doc ))] pub unsafe fn __strex(value: u32, addr: *mut u32) -> u32 { - extern "C" { + extern "unadjusted" { #[link_name = "llvm.arm.strex.p0i32"] fn strex32(value: u32, addr: *mut u32) -> u32; } diff --git a/library/stdarch/crates/core_arch/src/arm/mod.rs b/library/stdarch/crates/core_arch/src/arm/mod.rs index d6b12b8292..3c56ec7b1e 100644 --- a/library/stdarch/crates/core_arch/src/arm/mod.rs +++ b/library/stdarch/crates/core_arch/src/arm/mod.rs @@ -107,7 +107,7 @@ pub unsafe fn __dbg() { dbg(IMM4); } -extern "C" { +extern "unadjusted" { #[link_name = "llvm.arm.dbg"] fn dbg(_: i32); } diff --git a/library/stdarch/crates/core_arch/src/arm/neon.rs b/library/stdarch/crates/core_arch/src/arm/neon.rs index 473c753fd6..ebcff041a6 100644 --- a/library/stdarch/crates/core_arch/src/arm/neon.rs +++ b/library/stdarch/crates/core_arch/src/arm/neon.rs @@ -12,7 +12,7 @@ pub(crate) type p8 = u8; pub(crate) type p16 = u16; #[allow(improper_ctypes)] -extern "C" { +extern "unadjusted" { #[link_name = "llvm.arm.neon.vbsl.v8i8"] fn vbsl_s8_(a: int8x8_t, b: int8x8_t, c: int8x8_t) -> int8x8_t; #[link_name = "llvm.arm.neon.vbsl.v16i8"] @@ -288,6 +288,22 @@ pub unsafe fn vld1q_p16(ptr: *const p16) -> poly16x8_t { transmute(vld1q_v8i16(ptr as *const i8, align_of::() as i32)) } +/// Load multiple single-element structures to one, two, three, or four registers. +#[inline] +#[target_feature(enable = "neon,aes")] +#[cfg_attr(test, assert_instr(vldr))] +pub unsafe fn vld1_p64(ptr: *const p64) -> poly64x1_t { + transmute(vld1_v1i64(ptr as *const i8, align_of::() as i32)) +} + +/// Load multiple single-element structures to one, two, three, or four registers. +#[inline] +#[target_feature(enable = "neon,aes")] +#[cfg_attr(test, assert_instr("vld1.64"))] +pub unsafe fn vld1q_p64(ptr: *const p64) -> poly64x2_t { + transmute(vld1q_v2i64(ptr as *const i8, align_of::() as i32)) +} + /// Load multiple single-element structures to one, two, three, or four registers. #[inline] #[target_feature(enable = "neon,v7")] @@ -307,7 +323,7 @@ pub unsafe fn vld1q_f32(ptr: *const f32) -> float32x4_t { /// Store multiple single-element structures from one, two, three, or four registers. #[inline] #[target_feature(enable = "neon,v7")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr("vst1.8"))] pub unsafe fn vst1_s8(ptr: *mut i8, a: int8x8_t) { vst1_v8i8(ptr as *const i8, a, align_of::() as i32) } @@ -315,7 +331,7 @@ pub unsafe fn vst1_s8(ptr: *mut i8, a: int8x8_t) { /// Store multiple single-element structures from one, two, three, or four registers. #[inline] #[target_feature(enable = "neon,v7")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr("vst1.8"))] pub unsafe fn vst1q_s8(ptr: *mut i8, a: int8x16_t) { vst1q_v16i8(ptr as *const i8, a, align_of::() as i32) } @@ -323,7 +339,7 @@ pub unsafe fn vst1q_s8(ptr: *mut i8, a: int8x16_t) { /// Store multiple single-element structures from one, two, three, or four registers. #[inline] #[target_feature(enable = "neon,v7")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr("vst1.16"))] pub unsafe fn vst1_s16(ptr: *mut i16, a: int16x4_t) { vst1_v4i16(ptr as *const i8, a, align_of::() as i32) } @@ -331,7 +347,7 @@ pub unsafe fn vst1_s16(ptr: *mut i16, a: int16x4_t) { /// Store multiple single-element structures from one, two, three, or four registers. #[inline] #[target_feature(enable = "neon,v7")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr("vst1.16"))] pub unsafe fn vst1q_s16(ptr: *mut i16, a: int16x8_t) { vst1q_v8i16(ptr as *const i8, a, align_of::() as i32) } @@ -339,7 +355,7 @@ pub unsafe fn vst1q_s16(ptr: *mut i16, a: int16x8_t) { /// Store multiple single-element structures from one, two, three, or four registers. #[inline] #[target_feature(enable = "neon,v7")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr("vst1.32"))] pub unsafe fn vst1_s32(ptr: *mut i32, a: int32x2_t) { vst1_v2i32(ptr as *const i8, a, align_of::() as i32) } @@ -347,7 +363,7 @@ pub unsafe fn vst1_s32(ptr: *mut i32, a: int32x2_t) { /// Store multiple single-element structures from one, two, three, or four registers. #[inline] #[target_feature(enable = "neon,v7")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr("vst1.32"))] pub unsafe fn vst1q_s32(ptr: *mut i32, a: int32x4_t) { vst1q_v4i32(ptr as *const i8, a, align_of::() as i32) } @@ -355,7 +371,7 @@ pub unsafe fn vst1q_s32(ptr: *mut i32, a: int32x4_t) { /// Store multiple single-element structures from one, two, three, or four registers. #[inline] #[target_feature(enable = "neon,v7")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr("vst1.64"))] pub unsafe fn vst1_s64(ptr: *mut i64, a: int64x1_t) { vst1_v1i64(ptr as *const i8, a, align_of::() as i32) } @@ -363,7 +379,7 @@ pub unsafe fn vst1_s64(ptr: *mut i64, a: int64x1_t) { /// Store multiple single-element structures from one, two, three, or four registers. #[inline] #[target_feature(enable = "neon,v7")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr("vst1.64"))] pub unsafe fn vst1q_s64(ptr: *mut i64, a: int64x2_t) { vst1q_v2i64(ptr as *const i8, a, align_of::() as i32) } @@ -371,7 +387,7 @@ pub unsafe fn vst1q_s64(ptr: *mut i64, a: int64x2_t) { /// Store multiple single-element structures from one, two, three, or four registers. #[inline] #[target_feature(enable = "neon,v7")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr("vst1.8"))] pub unsafe fn vst1_u8(ptr: *mut u8, a: uint8x8_t) { vst1_v8i8(ptr as *const i8, transmute(a), align_of::() as i32) } @@ -379,7 +395,7 @@ pub unsafe fn vst1_u8(ptr: *mut u8, a: uint8x8_t) { /// Store multiple single-element structures from one, two, three, or four registers. #[inline] #[target_feature(enable = "neon,v7")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr("vst1.8"))] pub unsafe fn vst1q_u8(ptr: *mut u8, a: uint8x16_t) { vst1q_v16i8(ptr as *const i8, transmute(a), align_of::() as i32) } @@ -387,7 +403,7 @@ pub unsafe fn vst1q_u8(ptr: *mut u8, a: uint8x16_t) { /// Store multiple single-element structures from one, two, three, or four registers. #[inline] #[target_feature(enable = "neon,v7")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr("vst1.16"))] pub unsafe fn vst1_u16(ptr: *mut u16, a: uint16x4_t) { vst1_v4i16(ptr as *const i8, transmute(a), align_of::() as i32) } @@ -395,7 +411,7 @@ pub unsafe fn vst1_u16(ptr: *mut u16, a: uint16x4_t) { /// Store multiple single-element structures from one, two, three, or four registers. #[inline] #[target_feature(enable = "neon,v7")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr("vst1.16"))] pub unsafe fn vst1q_u16(ptr: *mut u16, a: uint16x8_t) { vst1q_v8i16(ptr as *const i8, transmute(a), align_of::() as i32) } @@ -403,7 +419,7 @@ pub unsafe fn vst1q_u16(ptr: *mut u16, a: uint16x8_t) { /// Store multiple single-element structures from one, two, three, or four registers. #[inline] #[target_feature(enable = "neon,v7")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr("vst1.32"))] pub unsafe fn vst1_u32(ptr: *mut u32, a: uint32x2_t) { vst1_v2i32(ptr as *const i8, transmute(a), align_of::() as i32) } @@ -411,7 +427,7 @@ pub unsafe fn vst1_u32(ptr: *mut u32, a: uint32x2_t) { /// Store multiple single-element structures from one, two, three, or four registers. #[inline] #[target_feature(enable = "neon,v7")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr("vst1.32"))] pub unsafe fn vst1q_u32(ptr: *mut u32, a: uint32x4_t) { vst1q_v4i32(ptr as *const i8, transmute(a), align_of::() as i32) } @@ -419,7 +435,7 @@ pub unsafe fn vst1q_u32(ptr: *mut u32, a: uint32x4_t) { /// Store multiple single-element structures from one, two, three, or four registers. #[inline] #[target_feature(enable = "neon,v7")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr("vst1.64"))] pub unsafe fn vst1_u64(ptr: *mut u64, a: uint64x1_t) { vst1_v1i64(ptr as *const i8, transmute(a), align_of::() as i32) } @@ -427,7 +443,7 @@ pub unsafe fn vst1_u64(ptr: *mut u64, a: uint64x1_t) { /// Store multiple single-element structures from one, two, three, or four registers. #[inline] #[target_feature(enable = "neon,v7")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr("vst1.64"))] pub unsafe fn vst1q_u64(ptr: *mut u64, a: uint64x2_t) { vst1q_v2i64(ptr as *const i8, transmute(a), align_of::() as i32) } @@ -435,7 +451,7 @@ pub unsafe fn vst1q_u64(ptr: *mut u64, a: uint64x2_t) { /// Store multiple single-element structures from one, two, three, or four registers. #[inline] #[target_feature(enable = "neon,v7")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr("vst1.8"))] pub unsafe fn vst1_p8(ptr: *mut p8, a: poly8x8_t) { vst1_v8i8(ptr as *const i8, transmute(a), align_of::() as i32) } @@ -443,7 +459,7 @@ pub unsafe fn vst1_p8(ptr: *mut p8, a: poly8x8_t) { /// Store multiple single-element structures from one, two, three, or four registers. #[inline] #[target_feature(enable = "neon,v7")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr("vst1.8"))] pub unsafe fn vst1q_p8(ptr: *mut p8, a: poly8x16_t) { vst1q_v16i8(ptr as *const i8, transmute(a), align_of::() as i32) } @@ -451,7 +467,7 @@ pub unsafe fn vst1q_p8(ptr: *mut p8, a: poly8x16_t) { /// Store multiple single-element structures from one, two, three, or four registers. #[inline] #[target_feature(enable = "neon,v7")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr("vst1.16"))] pub unsafe fn vst1_p16(ptr: *mut p16, a: poly16x4_t) { vst1_v4i16(ptr as *const i8, transmute(a), align_of::() as i32) } @@ -459,7 +475,7 @@ pub unsafe fn vst1_p16(ptr: *mut p16, a: poly16x4_t) { /// Store multiple single-element structures from one, two, three, or four registers. #[inline] #[target_feature(enable = "neon,v7")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr("vst1.16"))] pub unsafe fn vst1q_p16(ptr: *mut p16, a: poly16x8_t) { vst1q_v8i16(ptr as *const i8, transmute(a), align_of::() as i32) } @@ -467,7 +483,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,v7")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr("vst1.32"))] pub unsafe fn vst1_f32(ptr: *mut f32, a: float32x2_t) { vst1_v2f32(ptr as *const i8, a, align_of::() as i32) } @@ -475,7 +491,7 @@ pub unsafe fn vst1_f32(ptr: *mut f32, a: float32x2_t) { // Store multiple single-element structures from one, two, three, or four registers. #[inline] #[target_feature(enable = "neon,v7")] -#[cfg_attr(test, assert_instr(str))] +#[cfg_attr(test, assert_instr("vst1.32"))] pub unsafe fn vst1q_f32(ptr: *mut f32, a: float32x4_t) { vst1q_v4f32(ptr as *const i8, a, align_of::() as i32) } diff --git a/library/stdarch/crates/core_arch/src/arm/simd32.rs b/library/stdarch/crates/core_arch/src/arm/simd32.rs index 5cae2fc2aa..2d867acc83 100644 --- a/library/stdarch/crates/core_arch/src/arm/simd32.rs +++ b/library/stdarch/crates/core_arch/src/arm/simd32.rs @@ -80,7 +80,7 @@ macro_rules! dsp_call { }; } -extern "C" { +extern "unadjusted" { #[link_name = "llvm.arm.qadd8"] fn arm_qadd8(a: i32, b: i32) -> i32; diff --git a/library/stdarch/crates/core_arch/src/arm_shared/barrier/mod.rs b/library/stdarch/crates/core_arch/src/arm_shared/barrier/mod.rs index b3cbf44d27..6ccced00e3 100644 --- a/library/stdarch/crates/core_arch/src/arm_shared/barrier/mod.rs +++ b/library/stdarch/crates/core_arch/src/arm_shared/barrier/mod.rs @@ -122,7 +122,7 @@ where arg.__isb() } -extern "C" { +extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.dmb")] #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.dmb")] fn dmb(_: i32); diff --git a/library/stdarch/crates/core_arch/src/arm_shared/crc.rs b/library/stdarch/crates/core_arch/src/arm_shared/crc.rs index b1cfbb381b..e0d0fbe356 100644 --- a/library/stdarch/crates/core_arch/src/arm_shared/crc.rs +++ b/library/stdarch/crates/core_arch/src/arm_shared/crc.rs @@ -1,4 +1,4 @@ -extern "C" { +extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.crc32b")] #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.crc32b")] fn crc32b_(crc: u32, data: u32) -> u32; 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 4cdebb1da4..56b99088bf 100644 --- a/library/stdarch/crates/core_arch/src/arm_shared/crypto.rs +++ b/library/stdarch/crates/core_arch/src/arm_shared/crypto.rs @@ -1,7 +1,7 @@ use crate::core_arch::arm_shared::{uint32x4_t, uint8x16_t}; #[allow(improper_ctypes)] -extern "C" { +extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.crypto.aese")] #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.aese")] fn vaeseq_u8_(data: uint8x16_t, key: uint8x16_t) -> uint8x16_t; diff --git a/library/stdarch/crates/core_arch/src/arm_shared/hints.rs b/library/stdarch/crates/core_arch/src/arm_shared/hints.rs index 3145cde8d5..1d6551e5e7 100644 --- a/library/stdarch/crates/core_arch/src/arm_shared/hints.rs +++ b/library/stdarch/crates/core_arch/src/arm_shared/hints.rs @@ -80,7 +80,7 @@ pub unsafe fn __nop() { asm!("nop", options(nomem, nostack, preserves_flags)); } -extern "C" { +extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.hint")] #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.hint")] fn hint(_: i32); 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 7dc5b53e10..69d8da1795 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 @@ -497,7 +497,7 @@ pub unsafe fn veorq_u64(a: uint64x2_t, b: uint64x2_t) -> uint64x2_t { #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sabd))] pub unsafe fn vabd_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vabds.v8i8")] #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sabd.v8i8")] fn vabd_s8_(a: int8x8_t, b: int8x8_t) -> int8x8_t; @@ -513,7 +513,7 @@ vabd_s8_(a, b) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sabd))] pub unsafe fn vabdq_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vabds.v16i8")] #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sabd.v16i8")] fn vabdq_s8_(a: int8x16_t, b: int8x16_t) -> int8x16_t; @@ -529,7 +529,7 @@ vabdq_s8_(a, b) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sabd))] pub unsafe fn vabd_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vabds.v4i16")] #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sabd.v4i16")] fn vabd_s16_(a: int16x4_t, b: int16x4_t) -> int16x4_t; @@ -545,7 +545,7 @@ vabd_s16_(a, b) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sabd))] pub unsafe fn vabdq_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vabds.v8i16")] #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sabd.v8i16")] fn vabdq_s16_(a: int16x8_t, b: int16x8_t) -> int16x8_t; @@ -561,7 +561,7 @@ vabdq_s16_(a, b) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sabd))] pub unsafe fn vabd_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vabds.v2i32")] #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sabd.v2i32")] fn vabd_s32_(a: int32x2_t, b: int32x2_t) -> int32x2_t; @@ -577,7 +577,7 @@ vabd_s32_(a, b) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sabd))] pub unsafe fn vabdq_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vabds.v4i32")] #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sabd.v4i32")] fn vabdq_s32_(a: int32x4_t, b: int32x4_t) -> int32x4_t; @@ -593,7 +593,7 @@ vabdq_s32_(a, b) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uabd))] pub unsafe fn vabd_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vabdu.v8i8")] #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uabd.v8i8")] fn vabd_u8_(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t; @@ -609,7 +609,7 @@ vabd_u8_(a, b) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uabd))] pub unsafe fn vabdq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vabdu.v16i8")] #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uabd.v16i8")] fn vabdq_u8_(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t; @@ -625,7 +625,7 @@ vabdq_u8_(a, b) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uabd))] pub unsafe fn vabd_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vabdu.v4i16")] #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uabd.v4i16")] fn vabd_u16_(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t; @@ -641,7 +641,7 @@ vabd_u16_(a, b) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uabd))] pub unsafe fn vabdq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vabdu.v8i16")] #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uabd.v8i16")] fn vabdq_u16_(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t; @@ -657,7 +657,7 @@ vabdq_u16_(a, b) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uabd))] pub unsafe fn vabd_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vabdu.v2i32")] #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uabd.v2i32")] fn vabd_u32_(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t; @@ -673,7 +673,7 @@ vabd_u32_(a, b) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uabd))] pub unsafe fn vabdq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vabdu.v4i32")] #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uabd.v4i32")] fn vabdq_u32_(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t; @@ -689,7 +689,7 @@ vabdq_u32_(a, b) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fabd))] pub unsafe fn vabd_f32(a: float32x2_t, b: float32x2_t) -> float32x2_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vabds.v2f32")] #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fabd.v2f32")] fn vabd_f32_(a: float32x2_t, b: float32x2_t) -> float32x2_t; @@ -705,7 +705,7 @@ vabd_f32_(a, b) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fabd))] pub unsafe fn vabdq_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vabds.v4f32")] #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.fabd.v4f32")] fn vabdq_f32_(a: float32x4_t, b: float32x4_t) -> float32x4_t; @@ -1692,7 +1692,7 @@ pub unsafe fn vcgeq_f32(a: float32x4_t, b: float32x4_t) -> uint32x4_t { #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cls))] pub unsafe fn vcls_s8(a: int8x8_t) -> int8x8_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vcls.v8i8")] #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.cls.v8i8")] fn vcls_s8_(a: int8x8_t) -> int8x8_t; @@ -1708,7 +1708,7 @@ vcls_s8_(a) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cls))] pub unsafe fn vclsq_s8(a: int8x16_t) -> int8x16_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vcls.v16i8")] #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.cls.v16i8")] fn vclsq_s8_(a: int8x16_t) -> int8x16_t; @@ -1724,7 +1724,7 @@ vclsq_s8_(a) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cls))] pub unsafe fn vcls_s16(a: int16x4_t) -> int16x4_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vcls.v4i16")] #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.cls.v4i16")] fn vcls_s16_(a: int16x4_t) -> int16x4_t; @@ -1740,7 +1740,7 @@ vcls_s16_(a) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cls))] pub unsafe fn vclsq_s16(a: int16x8_t) -> int16x8_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vcls.v8i16")] #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.cls.v8i16")] fn vclsq_s16_(a: int16x8_t) -> int16x8_t; @@ -1756,7 +1756,7 @@ vclsq_s16_(a) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cls))] pub unsafe fn vcls_s32(a: int32x2_t) -> int32x2_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vcls.v2i32")] #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.cls.v2i32")] fn vcls_s32_(a: int32x2_t) -> int32x2_t; @@ -1772,7 +1772,7 @@ vcls_s32_(a) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cls))] pub unsafe fn vclsq_s32(a: int32x4_t) -> int32x4_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vcls.v4i32")] #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.cls.v4i32")] fn vclsq_s32_(a: int32x4_t) -> int32x4_t; @@ -1908,7 +1908,7 @@ pub unsafe fn vclzq_u32(a: uint32x4_t) -> uint32x4_t { #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(facgt))] pub unsafe fn vcagt_f32(a: float32x2_t, b: float32x2_t) -> uint32x2_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vacgt.v2i32.v2f32")] #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.facgt.v2i32.v2f32")] fn vcagt_f32_(a: float32x2_t, b: float32x2_t) -> uint32x2_t; @@ -1924,7 +1924,7 @@ vcagt_f32_(a, b) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(facgt))] pub unsafe fn vcagtq_f32(a: float32x4_t, b: float32x4_t) -> uint32x4_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vacgt.v4i32.v4f32")] #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.facgt.v4i32.v4f32")] fn vcagtq_f32_(a: float32x4_t, b: float32x4_t) -> uint32x4_t; @@ -1940,7 +1940,7 @@ vcagtq_f32_(a, b) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(facge))] pub unsafe fn vcage_f32(a: float32x2_t, b: float32x2_t) -> uint32x2_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vacge.v2i32.v2f32")] #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.facge.v2i32.v2f32")] fn vcage_f32_(a: float32x2_t, b: float32x2_t) -> uint32x2_t; @@ -1956,7 +1956,7 @@ vcage_f32_(a, b) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(facge))] pub unsafe fn vcageq_f32(a: float32x4_t, b: float32x4_t) -> uint32x4_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vacge.v4i32.v4f32")] #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.facge.v4i32.v4f32")] fn vcageq_f32_(a: float32x4_t, b: float32x4_t) -> uint32x4_t; @@ -2087,7 +2087,7 @@ pub unsafe fn vcreate_p16(a: u64) -> poly16x4_t { /// Insert vector element from another vector element #[inline] #[target_feature(enable = "neon,aes")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "crypto,v8"))] +#[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 vcreate_p64(a: u64) -> poly64x1_t { @@ -2153,7 +2153,7 @@ pub unsafe fn vcvtq_f32_u32(a: uint32x4_t) -> float32x4_t { pub unsafe fn vcvt_n_f32_s32(a: int32x2_t) -> float32x2_t { static_assert!(N : i32 where N >= 1 && N <= 32); #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vcvtfxs2fp.v2f32.v2i32")] fn vcvt_n_f32_s32_(a: int32x2_t, n: i32) -> float32x2_t; } @@ -2169,7 +2169,7 @@ vcvt_n_f32_s32_(a, N) pub unsafe fn vcvt_n_f32_s32(a: int32x2_t) -> float32x2_t { static_assert!(N : i32 where N >= 1 && N <= 32); #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.vcvtfxs2fp.v2f32.v2i32")] fn vcvt_n_f32_s32_(a: int32x2_t, n: i32) -> float32x2_t; } @@ -2185,7 +2185,7 @@ vcvt_n_f32_s32_(a, N) pub unsafe fn vcvtq_n_f32_s32(a: int32x4_t) -> float32x4_t { static_assert!(N : i32 where N >= 1 && N <= 32); #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vcvtfxs2fp.v4f32.v4i32")] fn vcvtq_n_f32_s32_(a: int32x4_t, n: i32) -> float32x4_t; } @@ -2201,7 +2201,7 @@ vcvtq_n_f32_s32_(a, N) pub unsafe fn vcvtq_n_f32_s32(a: int32x4_t) -> float32x4_t { static_assert!(N : i32 where N >= 1 && N <= 32); #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.vcvtfxs2fp.v4f32.v4i32")] fn vcvtq_n_f32_s32_(a: int32x4_t, n: i32) -> float32x4_t; } @@ -2217,7 +2217,7 @@ vcvtq_n_f32_s32_(a, N) pub unsafe fn vcvt_n_f32_u32(a: uint32x2_t) -> float32x2_t { static_assert!(N : i32 where N >= 1 && N <= 32); #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vcvtfxu2fp.v2f32.v2i32")] fn vcvt_n_f32_u32_(a: uint32x2_t, n: i32) -> float32x2_t; } @@ -2233,7 +2233,7 @@ vcvt_n_f32_u32_(a, N) pub unsafe fn vcvt_n_f32_u32(a: uint32x2_t) -> float32x2_t { static_assert!(N : i32 where N >= 1 && N <= 32); #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.vcvtfxu2fp.v2f32.v2i32")] fn vcvt_n_f32_u32_(a: uint32x2_t, n: i32) -> float32x2_t; } @@ -2249,7 +2249,7 @@ vcvt_n_f32_u32_(a, N) pub unsafe fn vcvtq_n_f32_u32(a: uint32x4_t) -> float32x4_t { static_assert!(N : i32 where N >= 1 && N <= 32); #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vcvtfxu2fp.v4f32.v4i32")] fn vcvtq_n_f32_u32_(a: uint32x4_t, n: i32) -> float32x4_t; } @@ -2265,7 +2265,7 @@ vcvtq_n_f32_u32_(a, N) pub unsafe fn vcvtq_n_f32_u32(a: uint32x4_t) -> float32x4_t { static_assert!(N : i32 where N >= 1 && N <= 32); #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.vcvtfxu2fp.v4f32.v4i32")] fn vcvtq_n_f32_u32_(a: uint32x4_t, n: i32) -> float32x4_t; } @@ -2281,7 +2281,7 @@ vcvtq_n_f32_u32_(a, N) pub unsafe fn vcvt_n_s32_f32(a: float32x2_t) -> int32x2_t { static_assert!(N : i32 where N >= 1 && N <= 32); #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vcvtfp2fxs.v2i32.v2f32")] fn vcvt_n_s32_f32_(a: float32x2_t, n: i32) -> int32x2_t; } @@ -2297,7 +2297,7 @@ vcvt_n_s32_f32_(a, N) pub unsafe fn vcvt_n_s32_f32(a: float32x2_t) -> int32x2_t { static_assert!(N : i32 where N >= 1 && N <= 32); #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.vcvtfp2fxs.v2i32.v2f32")] fn vcvt_n_s32_f32_(a: float32x2_t, n: i32) -> int32x2_t; } @@ -2313,7 +2313,7 @@ vcvt_n_s32_f32_(a, N) pub unsafe fn vcvtq_n_s32_f32(a: float32x4_t) -> int32x4_t { static_assert!(N : i32 where N >= 1 && N <= 32); #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vcvtfp2fxs.v4i32.v4f32")] fn vcvtq_n_s32_f32_(a: float32x4_t, n: i32) -> int32x4_t; } @@ -2329,7 +2329,7 @@ vcvtq_n_s32_f32_(a, N) pub unsafe fn vcvtq_n_s32_f32(a: float32x4_t) -> int32x4_t { static_assert!(N : i32 where N >= 1 && N <= 32); #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.vcvtfp2fxs.v4i32.v4f32")] fn vcvtq_n_s32_f32_(a: float32x4_t, n: i32) -> int32x4_t; } @@ -2345,7 +2345,7 @@ vcvtq_n_s32_f32_(a, N) pub unsafe fn vcvt_n_u32_f32(a: float32x2_t) -> uint32x2_t { static_assert!(N : i32 where N >= 1 && N <= 32); #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vcvtfp2fxu.v2i32.v2f32")] fn vcvt_n_u32_f32_(a: float32x2_t, n: i32) -> uint32x2_t; } @@ -2361,7 +2361,7 @@ vcvt_n_u32_f32_(a, N) pub unsafe fn vcvt_n_u32_f32(a: float32x2_t) -> uint32x2_t { static_assert!(N : i32 where N >= 1 && N <= 32); #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.vcvtfp2fxu.v2i32.v2f32")] fn vcvt_n_u32_f32_(a: float32x2_t, n: i32) -> uint32x2_t; } @@ -2377,7 +2377,7 @@ vcvt_n_u32_f32_(a, N) pub unsafe fn vcvtq_n_u32_f32(a: float32x4_t) -> uint32x4_t { static_assert!(N : i32 where N >= 1 && N <= 32); #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vcvtfp2fxu.v4i32.v4f32")] fn vcvtq_n_u32_f32_(a: float32x4_t, n: i32) -> uint32x4_t; } @@ -2393,7 +2393,7 @@ vcvtq_n_u32_f32_(a, N) pub unsafe fn vcvtq_n_u32_f32(a: float32x4_t) -> uint32x4_t { static_assert!(N : i32 where N >= 1 && N <= 32); #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.vcvtfp2fxu.v4i32.v4f32")] fn vcvtq_n_u32_f32_(a: float32x4_t, n: i32) -> uint32x4_t; } @@ -2408,7 +2408,7 @@ vcvtq_n_u32_f32_(a, N) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fcvtzs))] pub unsafe fn vcvt_s32_f32(a: float32x2_t) -> int32x2_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.fptosi.sat.v2i32.v2f32")] #[cfg_attr(target_arch = "aarch64", link_name = "llvm.fptosi.sat.v2i32.v2f32")] fn vcvt_s32_f32_(a: float32x2_t) -> int32x2_t; @@ -2424,7 +2424,7 @@ vcvt_s32_f32_(a) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fcvtzs))] pub unsafe fn vcvtq_s32_f32(a: float32x4_t) -> int32x4_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.fptosi.sat.v4i32.v4f32")] #[cfg_attr(target_arch = "aarch64", link_name = "llvm.fptosi.sat.v4i32.v4f32")] fn vcvtq_s32_f32_(a: float32x4_t) -> int32x4_t; @@ -2440,7 +2440,7 @@ vcvtq_s32_f32_(a) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fcvtzu))] pub unsafe fn vcvt_u32_f32(a: float32x2_t) -> uint32x2_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.fptoui.sat.v2i32.v2f32")] #[cfg_attr(target_arch = "aarch64", link_name = "llvm.fptoui.sat.v2i32.v2f32")] fn vcvt_u32_f32_(a: float32x2_t) -> uint32x2_t; @@ -2456,7 +2456,7 @@ vcvt_u32_f32_(a) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fcvtzu))] pub unsafe fn vcvtq_u32_f32(a: float32x4_t) -> uint32x4_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.fptoui.sat.v4i32.v4f32")] #[cfg_attr(target_arch = "aarch64", link_name = "llvm.fptoui.sat.v4i32.v4f32")] fn vcvtq_u32_f32_(a: float32x4_t) -> uint32x4_t; @@ -4842,7 +4842,7 @@ pub unsafe fn vnegq_f32(a: float32x4_t) -> float32x4_t { #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqneg))] pub unsafe fn vqneg_s8(a: int8x8_t) -> int8x8_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqneg.v8i8")] #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqneg.v8i8")] fn vqneg_s8_(a: int8x8_t) -> int8x8_t; @@ -4858,7 +4858,7 @@ vqneg_s8_(a) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqneg))] pub unsafe fn vqnegq_s8(a: int8x16_t) -> int8x16_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqneg.v16i8")] #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqneg.v16i8")] fn vqnegq_s8_(a: int8x16_t) -> int8x16_t; @@ -4874,7 +4874,7 @@ vqnegq_s8_(a) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqneg))] pub unsafe fn vqneg_s16(a: int16x4_t) -> int16x4_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqneg.v4i16")] #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqneg.v4i16")] fn vqneg_s16_(a: int16x4_t) -> int16x4_t; @@ -4890,7 +4890,7 @@ vqneg_s16_(a) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqneg))] pub unsafe fn vqnegq_s16(a: int16x8_t) -> int16x8_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqneg.v8i16")] #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqneg.v8i16")] fn vqnegq_s16_(a: int16x8_t) -> int16x8_t; @@ -4906,7 +4906,7 @@ vqnegq_s16_(a) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqneg))] pub unsafe fn vqneg_s32(a: int32x2_t) -> int32x2_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqneg.v2i32")] #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqneg.v2i32")] fn vqneg_s32_(a: int32x2_t) -> int32x2_t; @@ -4922,7 +4922,7 @@ vqneg_s32_(a) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqneg))] pub unsafe fn vqnegq_s32(a: int32x4_t) -> int32x4_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vqneg.v4i32")] #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqneg.v4i32")] fn vqnegq_s32_(a: int32x4_t) -> int32x4_t; @@ -4938,7 +4938,7 @@ vqnegq_s32_(a) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqsub))] pub unsafe fn vqsub_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.usub.sat.v8i8")] #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uqsub.v8i8")] fn vqsub_u8_(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t; @@ -4954,7 +4954,7 @@ vqsub_u8_(a, b) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqsub))] pub unsafe fn vqsubq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.usub.sat.v16i8")] #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uqsub.v16i8")] fn vqsubq_u8_(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t; @@ -4970,7 +4970,7 @@ vqsubq_u8_(a, b) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqsub))] pub unsafe fn vqsub_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.usub.sat.v4i16")] #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uqsub.v4i16")] fn vqsub_u16_(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t; @@ -4986,7 +4986,7 @@ vqsub_u16_(a, b) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqsub))] pub unsafe fn vqsubq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.usub.sat.v8i16")] #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uqsub.v8i16")] fn vqsubq_u16_(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t; @@ -5002,7 +5002,7 @@ vqsubq_u16_(a, b) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqsub))] pub unsafe fn vqsub_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.usub.sat.v2i32")] #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uqsub.v2i32")] fn vqsub_u32_(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t; @@ -5018,7 +5018,7 @@ vqsub_u32_(a, b) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqsub))] pub unsafe fn vqsubq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.usub.sat.v4i32")] #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uqsub.v4i32")] fn vqsubq_u32_(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t; @@ -5034,7 +5034,7 @@ vqsubq_u32_(a, b) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqsub))] pub unsafe fn vqsub_u64(a: uint64x1_t, b: uint64x1_t) -> uint64x1_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.usub.sat.v1i64")] #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uqsub.v1i64")] fn vqsub_u64_(a: uint64x1_t, b: uint64x1_t) -> uint64x1_t; @@ -5050,7 +5050,7 @@ vqsub_u64_(a, b) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqsub))] pub unsafe fn vqsubq_u64(a: uint64x2_t, b: uint64x2_t) -> uint64x2_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.usub.sat.v2i64")] #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uqsub.v2i64")] fn vqsubq_u64_(a: uint64x2_t, b: uint64x2_t) -> uint64x2_t; @@ -5066,7 +5066,7 @@ vqsubq_u64_(a, b) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqsub))] pub unsafe fn vqsub_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.ssub.sat.v8i8")] #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqsub.v8i8")] fn vqsub_s8_(a: int8x8_t, b: int8x8_t) -> int8x8_t; @@ -5082,7 +5082,7 @@ vqsub_s8_(a, b) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqsub))] pub unsafe fn vqsubq_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.ssub.sat.v16i8")] #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqsub.v16i8")] fn vqsubq_s8_(a: int8x16_t, b: int8x16_t) -> int8x16_t; @@ -5098,7 +5098,7 @@ vqsubq_s8_(a, b) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqsub))] pub unsafe fn vqsub_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.ssub.sat.v4i16")] #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqsub.v4i16")] fn vqsub_s16_(a: int16x4_t, b: int16x4_t) -> int16x4_t; @@ -5114,7 +5114,7 @@ vqsub_s16_(a, b) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqsub))] pub unsafe fn vqsubq_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.ssub.sat.v8i16")] #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqsub.v8i16")] fn vqsubq_s16_(a: int16x8_t, b: int16x8_t) -> int16x8_t; @@ -5130,7 +5130,7 @@ vqsubq_s16_(a, b) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqsub))] pub unsafe fn vqsub_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.ssub.sat.v2i32")] #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqsub.v2i32")] fn vqsub_s32_(a: int32x2_t, b: int32x2_t) -> int32x2_t; @@ -5146,7 +5146,7 @@ vqsub_s32_(a, b) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqsub))] pub unsafe fn vqsubq_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.ssub.sat.v4i32")] #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqsub.v4i32")] fn vqsubq_s32_(a: int32x4_t, b: int32x4_t) -> int32x4_t; @@ -5162,7 +5162,7 @@ vqsubq_s32_(a, b) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqsub))] pub unsafe fn vqsub_s64(a: int64x1_t, b: int64x1_t) -> int64x1_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.ssub.sat.v1i64")] #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqsub.v1i64")] fn vqsub_s64_(a: int64x1_t, b: int64x1_t) -> int64x1_t; @@ -5178,7 +5178,7 @@ vqsub_s64_(a, b) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqsub))] pub unsafe fn vqsubq_s64(a: int64x2_t, b: int64x2_t) -> int64x2_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.ssub.sat.v2i64")] #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqsub.v2i64")] fn vqsubq_s64_(a: int64x2_t, b: int64x2_t) -> int64x2_t; @@ -5194,7 +5194,7 @@ vqsubq_s64_(a, b) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uhadd))] pub unsafe fn vhadd_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vhaddu.v8i8")] #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uhadd.v8i8")] fn vhadd_u8_(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t; @@ -5210,7 +5210,7 @@ vhadd_u8_(a, b) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uhadd))] pub unsafe fn vhaddq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vhaddu.v16i8")] #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uhadd.v16i8")] fn vhaddq_u8_(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t; @@ -5226,7 +5226,7 @@ vhaddq_u8_(a, b) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uhadd))] pub unsafe fn vhadd_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vhaddu.v4i16")] #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uhadd.v4i16")] fn vhadd_u16_(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t; @@ -5242,7 +5242,7 @@ vhadd_u16_(a, b) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uhadd))] pub unsafe fn vhaddq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vhaddu.v8i16")] #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uhadd.v8i16")] fn vhaddq_u16_(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t; @@ -5258,7 +5258,7 @@ vhaddq_u16_(a, b) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uhadd))] pub unsafe fn vhadd_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vhaddu.v2i32")] #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uhadd.v2i32")] fn vhadd_u32_(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t; @@ -5274,7 +5274,7 @@ vhadd_u32_(a, b) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uhadd))] pub unsafe fn vhaddq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vhaddu.v4i32")] #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uhadd.v4i32")] fn vhaddq_u32_(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t; @@ -5290,7 +5290,7 @@ vhaddq_u32_(a, b) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shadd))] pub unsafe fn vhadd_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vhadds.v8i8")] #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.shadd.v8i8")] fn vhadd_s8_(a: int8x8_t, b: int8x8_t) -> int8x8_t; @@ -5306,7 +5306,7 @@ vhadd_s8_(a, b) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shadd))] pub unsafe fn vhaddq_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vhadds.v16i8")] #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.shadd.v16i8")] fn vhaddq_s8_(a: int8x16_t, b: int8x16_t) -> int8x16_t; @@ -5322,7 +5322,7 @@ vhaddq_s8_(a, b) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shadd))] pub unsafe fn vhadd_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vhadds.v4i16")] #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.shadd.v4i16")] fn vhadd_s16_(a: int16x4_t, b: int16x4_t) -> int16x4_t; @@ -5338,7 +5338,7 @@ vhadd_s16_(a, b) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shadd))] pub unsafe fn vhaddq_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vhadds.v8i16")] #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.shadd.v8i16")] fn vhaddq_s16_(a: int16x8_t, b: int16x8_t) -> int16x8_t; @@ -5354,7 +5354,7 @@ vhaddq_s16_(a, b) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shadd))] pub unsafe fn vhadd_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vhadds.v2i32")] #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.shadd.v2i32")] fn vhadd_s32_(a: int32x2_t, b: int32x2_t) -> int32x2_t; @@ -5370,7 +5370,7 @@ vhadd_s32_(a, b) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shadd))] pub unsafe fn vhaddq_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vhadds.v4i32")] #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.shadd.v4i32")] fn vhaddq_s32_(a: int32x4_t, b: int32x4_t) -> int32x4_t; @@ -5386,7 +5386,7 @@ vhaddq_s32_(a, b) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(urhadd))] pub unsafe fn vrhadd_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vrhaddu.v8i8")] #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.urhadd.v8i8")] fn vrhadd_u8_(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t; @@ -5402,7 +5402,7 @@ vrhadd_u8_(a, b) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(urhadd))] pub unsafe fn vrhaddq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vrhaddu.v16i8")] #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.urhadd.v16i8")] fn vrhaddq_u8_(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t; @@ -5418,7 +5418,7 @@ vrhaddq_u8_(a, b) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(urhadd))] pub unsafe fn vrhadd_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vrhaddu.v4i16")] #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.urhadd.v4i16")] fn vrhadd_u16_(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t; @@ -5434,7 +5434,7 @@ vrhadd_u16_(a, b) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(urhadd))] pub unsafe fn vrhaddq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vrhaddu.v8i16")] #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.urhadd.v8i16")] fn vrhaddq_u16_(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t; @@ -5450,7 +5450,7 @@ vrhaddq_u16_(a, b) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(urhadd))] pub unsafe fn vrhadd_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vrhaddu.v2i32")] #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.urhadd.v2i32")] fn vrhadd_u32_(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t; @@ -5466,7 +5466,7 @@ vrhadd_u32_(a, b) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(urhadd))] pub unsafe fn vrhaddq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vrhaddu.v4i32")] #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.urhadd.v4i32")] fn vrhaddq_u32_(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t; @@ -5482,7 +5482,7 @@ vrhaddq_u32_(a, b) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srhadd))] pub unsafe fn vrhadd_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vrhadds.v8i8")] #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.srhadd.v8i8")] fn vrhadd_s8_(a: int8x8_t, b: int8x8_t) -> int8x8_t; @@ -5498,7 +5498,7 @@ vrhadd_s8_(a, b) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srhadd))] pub unsafe fn vrhaddq_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vrhadds.v16i8")] #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.srhadd.v16i8")] fn vrhaddq_s8_(a: int8x16_t, b: int8x16_t) -> int8x16_t; @@ -5514,7 +5514,7 @@ vrhaddq_s8_(a, b) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srhadd))] pub unsafe fn vrhadd_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vrhadds.v4i16")] #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.srhadd.v4i16")] fn vrhadd_s16_(a: int16x4_t, b: int16x4_t) -> int16x4_t; @@ -5530,7 +5530,7 @@ vrhadd_s16_(a, b) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srhadd))] pub unsafe fn vrhaddq_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vrhadds.v8i16")] #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.srhadd.v8i16")] fn vrhaddq_s16_(a: int16x8_t, b: int16x8_t) -> int16x8_t; @@ -5546,7 +5546,7 @@ vrhaddq_s16_(a, b) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srhadd))] pub unsafe fn vrhadd_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vrhadds.v2i32")] #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.srhadd.v2i32")] fn vrhadd_s32_(a: int32x2_t, b: int32x2_t) -> int32x2_t; @@ -5562,7 +5562,7 @@ vrhadd_s32_(a, b) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srhadd))] pub unsafe fn vrhaddq_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vrhadds.v4i32")] #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.srhadd.v4i32")] fn vrhaddq_s32_(a: int32x4_t, b: int32x4_t) -> int32x4_t; @@ -5578,7 +5578,7 @@ vrhaddq_s32_(a, b) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(frintn))] pub unsafe fn vrndn_f32(a: float32x2_t) -> float32x2_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vrintn.v2f32")] #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.frintn.v2f32")] fn vrndn_f32_(a: float32x2_t) -> float32x2_t; @@ -5594,7 +5594,7 @@ vrndn_f32_(a) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(frintn))] pub unsafe fn vrndnq_f32(a: float32x4_t) -> float32x4_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vrintn.v4f32")] #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.frintn.v4f32")] fn vrndnq_f32_(a: float32x4_t) -> float32x4_t; @@ -5610,7 +5610,7 @@ vrndnq_f32_(a) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqadd))] pub unsafe fn vqadd_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.uadd.sat.v8i8")] #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uqadd.v8i8")] fn vqadd_u8_(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t; @@ -5626,7 +5626,7 @@ vqadd_u8_(a, b) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqadd))] pub unsafe fn vqaddq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.uadd.sat.v16i8")] #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uqadd.v16i8")] fn vqaddq_u8_(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t; @@ -5642,7 +5642,7 @@ vqaddq_u8_(a, b) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqadd))] pub unsafe fn vqadd_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.uadd.sat.v4i16")] #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uqadd.v4i16")] fn vqadd_u16_(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t; @@ -5658,7 +5658,7 @@ vqadd_u16_(a, b) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqadd))] pub unsafe fn vqaddq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.uadd.sat.v8i16")] #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uqadd.v8i16")] fn vqaddq_u16_(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t; @@ -5674,7 +5674,7 @@ vqaddq_u16_(a, b) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqadd))] pub unsafe fn vqadd_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.uadd.sat.v2i32")] #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uqadd.v2i32")] fn vqadd_u32_(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t; @@ -5690,7 +5690,7 @@ vqadd_u32_(a, b) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqadd))] pub unsafe fn vqaddq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.uadd.sat.v4i32")] #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uqadd.v4i32")] fn vqaddq_u32_(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t; @@ -5706,7 +5706,7 @@ vqaddq_u32_(a, b) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqadd))] pub unsafe fn vqadd_u64(a: uint64x1_t, b: uint64x1_t) -> uint64x1_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.uadd.sat.v1i64")] #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uqadd.v1i64")] fn vqadd_u64_(a: uint64x1_t, b: uint64x1_t) -> uint64x1_t; @@ -5722,7 +5722,7 @@ vqadd_u64_(a, b) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqadd))] pub unsafe fn vqaddq_u64(a: uint64x2_t, b: uint64x2_t) -> uint64x2_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.uadd.sat.v2i64")] #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.uqadd.v2i64")] fn vqaddq_u64_(a: uint64x2_t, b: uint64x2_t) -> uint64x2_t; @@ -5738,7 +5738,7 @@ vqaddq_u64_(a, b) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqadd))] pub unsafe fn vqadd_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.sadd.sat.v8i8")] #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqadd.v8i8")] fn vqadd_s8_(a: int8x8_t, b: int8x8_t) -> int8x8_t; @@ -5754,7 +5754,7 @@ vqadd_s8_(a, b) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqadd))] pub unsafe fn vqaddq_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.sadd.sat.v16i8")] #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqadd.v16i8")] fn vqaddq_s8_(a: int8x16_t, b: int8x16_t) -> int8x16_t; @@ -5770,7 +5770,7 @@ vqaddq_s8_(a, b) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqadd))] pub unsafe fn vqadd_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.sadd.sat.v4i16")] #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqadd.v4i16")] fn vqadd_s16_(a: int16x4_t, b: int16x4_t) -> int16x4_t; @@ -5786,7 +5786,7 @@ vqadd_s16_(a, b) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqadd))] pub unsafe fn vqaddq_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.sadd.sat.v8i16")] #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqadd.v8i16")] fn vqaddq_s16_(a: int16x8_t, b: int16x8_t) -> int16x8_t; @@ -5802,7 +5802,7 @@ vqaddq_s16_(a, b) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqadd))] pub unsafe fn vqadd_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.sadd.sat.v2i32")] #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqadd.v2i32")] fn vqadd_s32_(a: int32x2_t, b: int32x2_t) -> int32x2_t; @@ -5818,7 +5818,7 @@ vqadd_s32_(a, b) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqadd))] pub unsafe fn vqaddq_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.sadd.sat.v4i32")] #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqadd.v4i32")] fn vqaddq_s32_(a: int32x4_t, b: int32x4_t) -> int32x4_t; @@ -5834,7 +5834,7 @@ vqaddq_s32_(a, b) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqadd))] pub unsafe fn vqadd_s64(a: int64x1_t, b: int64x1_t) -> int64x1_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.sadd.sat.v1i64")] #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqadd.v1i64")] fn vqadd_s64_(a: int64x1_t, b: int64x1_t) -> int64x1_t; @@ -5850,7 +5850,7 @@ vqadd_s64_(a, b) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqadd))] pub unsafe fn vqaddq_s64(a: int64x2_t, b: int64x2_t) -> int64x2_t { #[allow(improper_ctypes)] - extern "C" { + extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.sadd.sat.v2i64")] #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.sqadd.v2i64")] fn vqaddq_s64_(a: int64x2_t, b: int64x2_t) -> int64x2_t; @@ -5858,6 +5858,2106 @@ pub unsafe fn vqaddq_s64(a: int64x2_t, b: int64x2_t) -> int64x2_t { vqaddq_s64_(a, b) } +/// Load 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(vld1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +pub unsafe fn vld1_s8_x2(a: *const i8) -> int8x8x2_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x2.v8i8.p0i8")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld1x2.v8i8.p0i8")] + fn vld1_s8_x2_(a: *const i8) -> int8x8x2_t; + } +vld1_s8_x2_(a) +} + +/// Load 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(vld1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +pub unsafe fn vld1_s16_x2(a: *const i16) -> int16x4x2_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x2.v4i16.p0i16")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld1x2.v4i16.p0i16")] + fn vld1_s16_x2_(a: *const i16) -> int16x4x2_t; + } +vld1_s16_x2_(a) +} + +/// Load 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(vld1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +pub unsafe fn vld1_s32_x2(a: *const i32) -> int32x2x2_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x2.v2i32.p0i32")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld1x2.v2i32.p0i32")] + fn vld1_s32_x2_(a: *const i32) -> int32x2x2_t; + } +vld1_s32_x2_(a) +} + +/// Load 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(vld1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +pub unsafe fn vld1_s64_x2(a: *const i64) -> int64x1x2_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x2.v1i64.p0i64")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld1x2.v1i64.p0i64")] + fn vld1_s64_x2_(a: *const i64) -> int64x1x2_t; + } +vld1_s64_x2_(a) +} + +/// Load 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(vld1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +pub unsafe fn vld1q_s8_x2(a: *const i8) -> int8x16x2_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x2.v16i8.p0i8")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld1x2.v16i8.p0i8")] + fn vld1q_s8_x2_(a: *const i8) -> int8x16x2_t; + } +vld1q_s8_x2_(a) +} + +/// Load 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(vld1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +pub unsafe fn vld1q_s16_x2(a: *const i16) -> int16x8x2_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x2.v8i16.p0i16")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld1x2.v8i16.p0i16")] + fn vld1q_s16_x2_(a: *const i16) -> int16x8x2_t; + } +vld1q_s16_x2_(a) +} + +/// Load 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(vld1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +pub unsafe fn vld1q_s32_x2(a: *const i32) -> int32x4x2_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x2.v4i32.p0i32")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld1x2.v4i32.p0i32")] + fn vld1q_s32_x2_(a: *const i32) -> int32x4x2_t; + } +vld1q_s32_x2_(a) +} + +/// Load 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(vld1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +pub unsafe fn vld1q_s64_x2(a: *const i64) -> int64x2x2_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x2.v2i64.p0i64")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld1x2.v2i64.p0i64")] + fn vld1q_s64_x2_(a: *const i64) -> int64x2x2_t; + } +vld1q_s64_x2_(a) +} + +/// Load 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(vld1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +pub unsafe fn vld1_s8_x3(a: *const i8) -> int8x8x3_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x3.v8i8.p0i8")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld1x3.v8i8.p0i8")] + fn vld1_s8_x3_(a: *const i8) -> int8x8x3_t; + } +vld1_s8_x3_(a) +} + +/// Load 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(vld1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +pub unsafe fn vld1_s16_x3(a: *const i16) -> int16x4x3_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x3.v4i16.p0i16")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld1x3.v4i16.p0i16")] + fn vld1_s16_x3_(a: *const i16) -> int16x4x3_t; + } +vld1_s16_x3_(a) +} + +/// Load 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(vld1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +pub unsafe fn vld1_s32_x3(a: *const i32) -> int32x2x3_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x3.v2i32.p0i32")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld1x3.v2i32.p0i32")] + fn vld1_s32_x3_(a: *const i32) -> int32x2x3_t; + } +vld1_s32_x3_(a) +} + +/// Load 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(vld1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +pub unsafe fn vld1_s64_x3(a: *const i64) -> int64x1x3_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x3.v1i64.p0i64")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld1x3.v1i64.p0i64")] + fn vld1_s64_x3_(a: *const i64) -> int64x1x3_t; + } +vld1_s64_x3_(a) +} + +/// Load 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(vld1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +pub unsafe fn vld1q_s8_x3(a: *const i8) -> int8x16x3_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x3.v16i8.p0i8")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld1x3.v16i8.p0i8")] + fn vld1q_s8_x3_(a: *const i8) -> int8x16x3_t; + } +vld1q_s8_x3_(a) +} + +/// Load 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(vld1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +pub unsafe fn vld1q_s16_x3(a: *const i16) -> int16x8x3_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x3.v8i16.p0i16")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld1x3.v8i16.p0i16")] + fn vld1q_s16_x3_(a: *const i16) -> int16x8x3_t; + } +vld1q_s16_x3_(a) +} + +/// Load 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(vld1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +pub unsafe fn vld1q_s32_x3(a: *const i32) -> int32x4x3_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x3.v4i32.p0i32")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld1x3.v4i32.p0i32")] + fn vld1q_s32_x3_(a: *const i32) -> int32x4x3_t; + } +vld1q_s32_x3_(a) +} + +/// Load 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(vld1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +pub unsafe fn vld1q_s64_x3(a: *const i64) -> int64x2x3_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x3.v2i64.p0i64")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld1x3.v2i64.p0i64")] + fn vld1q_s64_x3_(a: *const i64) -> int64x2x3_t; + } +vld1q_s64_x3_(a) +} + +/// Load 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(vld1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +pub unsafe fn vld1_s8_x4(a: *const i8) -> int8x8x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x4.v8i8.p0i8")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld1x4.v8i8.p0i8")] + fn vld1_s8_x4_(a: *const i8) -> int8x8x4_t; + } +vld1_s8_x4_(a) +} + +/// Load 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(vld1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +pub unsafe fn vld1_s16_x4(a: *const i16) -> int16x4x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x4.v4i16.p0i16")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld1x4.v4i16.p0i16")] + fn vld1_s16_x4_(a: *const i16) -> int16x4x4_t; + } +vld1_s16_x4_(a) +} + +/// Load 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(vld1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +pub unsafe fn vld1_s32_x4(a: *const i32) -> int32x2x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x4.v2i32.p0i32")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld1x4.v2i32.p0i32")] + fn vld1_s32_x4_(a: *const i32) -> int32x2x4_t; + } +vld1_s32_x4_(a) +} + +/// Load 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(vld1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +pub unsafe fn vld1_s64_x4(a: *const i64) -> int64x1x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x4.v1i64.p0i64")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld1x4.v1i64.p0i64")] + fn vld1_s64_x4_(a: *const i64) -> int64x1x4_t; + } +vld1_s64_x4_(a) +} + +/// Load 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(vld1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +pub unsafe fn vld1q_s8_x4(a: *const i8) -> int8x16x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x4.v16i8.p0i8")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld1x4.v16i8.p0i8")] + fn vld1q_s8_x4_(a: *const i8) -> int8x16x4_t; + } +vld1q_s8_x4_(a) +} + +/// Load 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(vld1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +pub unsafe fn vld1q_s16_x4(a: *const i16) -> int16x8x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x4.v8i16.p0i16")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld1x4.v8i16.p0i16")] + fn vld1q_s16_x4_(a: *const i16) -> int16x8x4_t; + } +vld1q_s16_x4_(a) +} + +/// Load 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(vld1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +pub unsafe fn vld1q_s32_x4(a: *const i32) -> int32x4x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x4.v4i32.p0i32")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld1x4.v4i32.p0i32")] + fn vld1q_s32_x4_(a: *const i32) -> int32x4x4_t; + } +vld1q_s32_x4_(a) +} + +/// Load 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(vld1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +pub unsafe fn vld1q_s64_x4(a: *const i64) -> int64x2x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x4.v2i64.p0i64")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld1x4.v2i64.p0i64")] + fn vld1q_s64_x4_(a: *const i64) -> int64x2x4_t; + } +vld1q_s64_x4_(a) +} + +/// Load 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(vld1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +pub unsafe fn vld1_u8_x2(a: *const u8) -> uint8x8x2_t { + transmute(vld1_s8_x2(transmute(a))) +} + +/// Load 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(vld1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +pub unsafe fn vld1_u16_x2(a: *const u16) -> uint16x4x2_t { + transmute(vld1_s16_x2(transmute(a))) +} + +/// Load 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(vld1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +pub unsafe fn vld1_u32_x2(a: *const u32) -> uint32x2x2_t { + transmute(vld1_s32_x2(transmute(a))) +} + +/// Load 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(vld1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +pub unsafe fn vld1_u64_x2(a: *const u64) -> uint64x1x2_t { + transmute(vld1_s64_x2(transmute(a))) +} + +/// Load 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(vld1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +pub unsafe fn vld1q_u8_x2(a: *const u8) -> uint8x16x2_t { + transmute(vld1q_s8_x2(transmute(a))) +} + +/// Load 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(vld1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +pub unsafe fn vld1q_u16_x2(a: *const u16) -> uint16x8x2_t { + transmute(vld1q_s16_x2(transmute(a))) +} + +/// Load 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(vld1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +pub unsafe fn vld1q_u32_x2(a: *const u32) -> uint32x4x2_t { + transmute(vld1q_s32_x2(transmute(a))) +} + +/// Load 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(vld1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +pub unsafe fn vld1q_u64_x2(a: *const u64) -> uint64x2x2_t { + transmute(vld1q_s64_x2(transmute(a))) +} + +/// Load 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(vld1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +pub unsafe fn vld1_u8_x3(a: *const u8) -> uint8x8x3_t { + transmute(vld1_s8_x3(transmute(a))) +} + +/// Load 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(vld1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +pub unsafe fn vld1_u16_x3(a: *const u16) -> uint16x4x3_t { + transmute(vld1_s16_x3(transmute(a))) +} + +/// Load 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(vld1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +pub unsafe fn vld1_u32_x3(a: *const u32) -> uint32x2x3_t { + transmute(vld1_s32_x3(transmute(a))) +} + +/// Load 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(vld1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +pub unsafe fn vld1_u64_x3(a: *const u64) -> uint64x1x3_t { + transmute(vld1_s64_x3(transmute(a))) +} + +/// Load 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(vld1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +pub unsafe fn vld1q_u8_x3(a: *const u8) -> uint8x16x3_t { + transmute(vld1q_s8_x3(transmute(a))) +} + +/// Load 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(vld1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +pub unsafe fn vld1q_u16_x3(a: *const u16) -> uint16x8x3_t { + transmute(vld1q_s16_x3(transmute(a))) +} + +/// Load 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(vld1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +pub unsafe fn vld1q_u32_x3(a: *const u32) -> uint32x4x3_t { + transmute(vld1q_s32_x3(transmute(a))) +} + +/// Load 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(vld1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +pub unsafe fn vld1q_u64_x3(a: *const u64) -> uint64x2x3_t { + transmute(vld1q_s64_x3(transmute(a))) +} + +/// Load 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(vld1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +pub unsafe fn vld1_u8_x4(a: *const u8) -> uint8x8x4_t { + transmute(vld1_s8_x4(transmute(a))) +} + +/// Load 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(vld1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +pub unsafe fn vld1_u16_x4(a: *const u16) -> uint16x4x4_t { + transmute(vld1_s16_x4(transmute(a))) +} + +/// Load 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(vld1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +pub unsafe fn vld1_u32_x4(a: *const u32) -> uint32x2x4_t { + transmute(vld1_s32_x4(transmute(a))) +} + +/// Load 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(vld1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +pub unsafe fn vld1_u64_x4(a: *const u64) -> uint64x1x4_t { + transmute(vld1_s64_x4(transmute(a))) +} + +/// Load 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(vld1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +pub unsafe fn vld1q_u8_x4(a: *const u8) -> uint8x16x4_t { + transmute(vld1q_s8_x4(transmute(a))) +} + +/// Load 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(vld1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +pub unsafe fn vld1q_u16_x4(a: *const u16) -> uint16x8x4_t { + transmute(vld1q_s16_x4(transmute(a))) +} + +/// Load 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(vld1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +pub unsafe fn vld1q_u32_x4(a: *const u32) -> uint32x4x4_t { + transmute(vld1q_s32_x4(transmute(a))) +} + +/// Load 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(vld1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +pub unsafe fn vld1q_u64_x4(a: *const u64) -> uint64x2x4_t { + transmute(vld1q_s64_x4(transmute(a))) +} + +/// Load 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(vld1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +pub unsafe fn vld1_p8_x2(a: *const p8) -> poly8x8x2_t { + transmute(vld1_s8_x2(transmute(a))) +} + +/// Load 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(vld1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +pub unsafe fn vld1_p8_x3(a: *const p8) -> poly8x8x3_t { + transmute(vld1_s8_x3(transmute(a))) +} + +/// Load 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(vld1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +pub unsafe fn vld1_p8_x4(a: *const p8) -> poly8x8x4_t { + transmute(vld1_s8_x4(transmute(a))) +} + +/// Load 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(vld1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +pub unsafe fn vld1q_p8_x2(a: *const p8) -> poly8x16x2_t { + transmute(vld1q_s8_x2(transmute(a))) +} + +/// Load 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(vld1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +pub unsafe fn vld1q_p8_x3(a: *const p8) -> poly8x16x3_t { + transmute(vld1q_s8_x3(transmute(a))) +} + +/// Load 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(vld1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +pub unsafe fn vld1q_p8_x4(a: *const p8) -> poly8x16x4_t { + transmute(vld1q_s8_x4(transmute(a))) +} + +/// Load 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(vld1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +pub unsafe fn vld1_p16_x2(a: *const p16) -> poly16x4x2_t { + transmute(vld1_s16_x2(transmute(a))) +} + +/// Load 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(vld1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +pub unsafe fn vld1_p16_x3(a: *const p16) -> poly16x4x3_t { + transmute(vld1_s16_x3(transmute(a))) +} + +/// Load 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(vld1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +pub unsafe fn vld1_p16_x4(a: *const p16) -> poly16x4x4_t { + transmute(vld1_s16_x4(transmute(a))) +} + +/// Load 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(vld1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +pub unsafe fn vld1q_p16_x2(a: *const p16) -> poly16x8x2_t { + transmute(vld1q_s16_x2(transmute(a))) +} + +/// Load 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(vld1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +pub unsafe fn vld1q_p16_x3(a: *const p16) -> poly16x8x3_t { + transmute(vld1q_s16_x3(transmute(a))) +} + +/// Load 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(vld1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +pub unsafe fn vld1q_p16_x4(a: *const p16) -> poly16x8x4_t { + transmute(vld1q_s16_x4(transmute(a))) +} + +/// Load multiple single-element structures to 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(vld1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +pub unsafe fn vld1_p64_x2(a: *const p64) -> poly64x1x2_t { + transmute(vld1_s64_x2(transmute(a))) +} + +/// Load multiple single-element structures to 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(ldr))] +#[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))) +} + +/// Load multiple single-element structures to 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(ldr))] +#[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))) +} + +/// Load multiple single-element structures to 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(ldr))] +#[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))) +} + +/// Load multiple single-element structures to 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(ldr))] +#[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))) +} + +/// Load multiple single-element structures to 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(ldr))] +#[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))) +} + +/// Load 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(vld1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +pub unsafe fn vld1_f32_x2(a: *const f32) -> float32x2x2_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x2.v2f32.p0f32")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld1x2.v2f32.p0f32")] + fn vld1_f32_x2_(a: *const f32) -> float32x2x2_t; + } +vld1_f32_x2_(a) +} + +/// Load 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(vld1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +pub unsafe fn vld1q_f32_x2(a: *const f32) -> float32x4x2_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x2.v4f32.p0f32")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld1x2.v4f32.p0f32")] + fn vld1q_f32_x2_(a: *const f32) -> float32x4x2_t; + } +vld1q_f32_x2_(a) +} + +/// Load 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(vld1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +pub unsafe fn vld1_f32_x3(a: *const f32) -> float32x2x3_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x3.v2f32.p0f32")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld1x3.v2f32.p0f32")] + fn vld1_f32_x3_(a: *const f32) -> float32x2x3_t; + } +vld1_f32_x3_(a) +} + +/// Load 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(vld1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +pub unsafe fn vld1q_f32_x3(a: *const f32) -> float32x4x3_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x3.v4f32.p0f32")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld1x3.v4f32.p0f32")] + fn vld1q_f32_x3_(a: *const f32) -> float32x4x3_t; + } +vld1q_f32_x3_(a) +} + +/// Load 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(vld1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +pub unsafe fn vld1_f32_x4(a: *const f32) -> float32x2x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x4.v2f32.p0f32")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld1x4.v2f32.p0f32")] + fn vld1_f32_x4_(a: *const f32) -> float32x2x4_t; + } +vld1_f32_x4_(a) +} + +/// Load 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(vld1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +pub unsafe fn vld1q_f32_x4(a: *const f32) -> float32x4x4_t { + #[allow(improper_ctypes)] + extern "unadjusted" { + #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x4.v4f32.p0f32")] + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld1x4.v4f32.p0f32")] + 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 +#[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.vst1x2.p0i8.v8i8")] + fn vst1_s8_x2_(ptr: *mut i8, a: int8x8_t, b: int8x8_t); + } +vst1_s8_x2_(a, b.0, b.1) +} + +/// Store multiple single-element structures from one, two, three, or four 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) { + #[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); + } +vst1_s8_x2_(b.0, b.1, a) +} + +/// 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_s16_x2(a: *mut i16, b: 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); + } +vst1_s16_x2_(a, b.0, b.1) +} + +/// Store multiple single-element structures from one, two, three, or four 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) { + #[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); + } +vst1_s16_x2_(b.0, b.1, a) +} + +/// 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_s32_x2(a: *mut i32, b: 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); + } +vst1_s32_x2_(a, b.0, b.1) +} + +/// Store multiple single-element structures from one, two, three, or four 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) { + #[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); + } +vst1_s32_x2_(b.0, b.1, a) +} + +/// 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_s64_x2(a: *mut i64, b: int64x1x2_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); + } +vst1_s64_x2_(a, b.0, b.1) +} + +/// Store multiple single-element structures from one, two, three, or four 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) { + #[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); + } +vst1_s64_x2_(b.0, b.1, a) +} + +/// 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 vst1q_s8_x2(a: *mut i8, b: int8x16x2_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); + } +vst1q_s8_x2_(a, b.0, b.1) +} + +/// Store multiple single-element structures from one, two, three, or four 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) { + #[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); + } +vst1q_s8_x2_(b.0, b.1, a) +} + +/// 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 vst1q_s16_x2(a: *mut i16, b: int16x8x2_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); + } +vst1q_s16_x2_(a, b.0, b.1) +} + +/// Store multiple single-element structures from one, two, three, or four 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) { + #[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); + } +vst1q_s16_x2_(b.0, b.1, a) +} + +/// 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 vst1q_s32_x2(a: *mut i32, b: int32x4x2_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); + } +vst1q_s32_x2_(a, b.0, b.1) +} + +/// Store multiple single-element structures from one, two, three, or four 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) { + #[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); + } +vst1q_s32_x2_(b.0, b.1, a) +} + +/// 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 vst1q_s64_x2(a: *mut i64, b: int64x2x2_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); + } +vst1q_s64_x2_(a, b.0, b.1) +} + +/// Store multiple single-element structures from one, two, three, or four 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) { + #[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); + } +vst1q_s64_x2_(b.0, b.1, a) +} + +/// 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_x3(a: *mut i8, b: int8x8x3_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); + } +vst1_s8_x3_(a, b.0, b.1, b.2) +} + +/// Store multiple single-element structures from one, two, three, or four 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) { + #[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); + } +vst1_s8_x3_(b.0, b.1, b.2, a) +} + +/// 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_s16_x3(a: *mut i16, b: int16x4x3_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); + } +vst1_s16_x3_(a, b.0, b.1, b.2) +} + +/// Store multiple single-element structures from one, two, three, or four 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) { + #[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); + } +vst1_s16_x3_(b.0, b.1, b.2, a) +} + +/// 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_s32_x3(a: *mut i32, b: int32x2x3_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); + } +vst1_s32_x3_(a, b.0, b.1, b.2) +} + +/// Store multiple single-element structures from one, two, three, or four 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) { + #[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); + } +vst1_s32_x3_(b.0, b.1, b.2, a) +} + +/// 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_s64_x3(a: *mut i64, b: int64x1x3_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); + } +vst1_s64_x3_(a, b.0, b.1, b.2) +} + +/// Store multiple single-element structures from one, two, three, or four 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) { + #[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); + } +vst1_s64_x3_(b.0, b.1, b.2, a) +} + +/// 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 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) +} + +/// Store multiple single-element structures from one, two, three, or four 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) { + #[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) +} + +/// 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 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) +} + +/// Store multiple single-element structures from one, two, three, or four 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) { + #[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) +} + +/// 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 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) +} + +/// Store multiple single-element structures from one, two, three, or four 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) { + #[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) +} + +/// 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 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) +} + +/// Store multiple single-element structures from one, two, three, or four 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) { + #[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) +} + +/// 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_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) +} + +/// Store multiple single-element structures from one, two, three, or four 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) +} + +/// 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_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) +} + +/// Store multiple single-element structures from one, two, three, or four 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) { + #[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) +} + +/// 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_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) +} + +/// Store multiple single-element structures from one, two, three, or four 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) { + #[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) +} + +/// 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_s64_x4(a: *mut i64, b: int64x1x4_t) { + #[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); + } +vst1_s64_x4_(a, b.0, b.1, b.2, b.3) +} + +/// Store multiple single-element structures from one, two, three, or four 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) { + #[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); + } +vst1_s64_x4_(b.0, b.1, b.2, b.3, a) +} + +/// 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 vst1q_s8_x4(a: *mut i8, b: int8x16x4_t) { + #[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); + } +vst1q_s8_x4_(a, b.0, b.1, b.2, b.3) +} + +/// Store multiple single-element structures from one, two, three, or four 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) { + #[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); + } +vst1q_s8_x4_(b.0, b.1, b.2, b.3, a) +} + +/// 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 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) +} + +/// Store multiple single-element structures from one, two, three, or four 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) { + #[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) +} + +/// 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 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) +} + +/// Store multiple single-element structures from one, two, three, or four 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) { + #[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) +} + +/// 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 vst1q_s64_x4(a: *mut i64, b: int64x2x4_t) { + #[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); + } +vst1q_s64_x4_(a, b.0, b.1, b.2, b.3) +} + +/// Store multiple single-element structures from one, two, three, or four 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) { + #[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); + } +vst1q_s64_x4_(b.0, b.1, b.2, b.3, a) +} + +/// 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_u8_x2(a: *mut u8, b: uint8x8x2_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_u16_x2(a: *mut u16, b: uint16x4x2_t) { + vst1_s16_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_u32_x2(a: *mut u32, b: uint32x2x2_t) { + vst1_s32_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_u64_x2(a: *mut u64, b: uint64x1x2_t) { + vst1_s64_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 vst1q_u8_x2(a: *mut u8, b: uint8x16x2_t) { + vst1q_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 vst1q_u16_x2(a: *mut u16, b: uint16x8x2_t) { + vst1q_s16_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 vst1q_u32_x2(a: *mut u32, b: uint32x4x2_t) { + vst1q_s32_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 vst1q_u64_x2(a: *mut u64, b: uint64x2x2_t) { + vst1q_s64_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_u8_x3(a: *mut u8, b: uint8x8x3_t) { + vst1_s8_x3(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_u16_x3(a: *mut u16, b: uint16x4x3_t) { + vst1_s16_x3(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_u32_x3(a: *mut u32, b: uint32x2x3_t) { + vst1_s32_x3(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_u64_x3(a: *mut u64, b: uint64x1x3_t) { + vst1_s64_x3(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 vst1q_u8_x3(a: *mut u8, b: uint8x16x3_t) { + vst1q_s8_x3(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 vst1q_u16_x3(a: *mut u16, b: uint16x8x3_t) { + vst1q_s16_x3(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 vst1q_u32_x3(a: *mut u32, b: uint32x4x3_t) { + vst1q_s32_x3(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 vst1q_u64_x3(a: *mut u64, b: uint64x2x3_t) { + vst1q_s64_x3(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_u8_x4(a: *mut u8, b: uint8x8x4_t) { + vst1_s8_x4(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_u16_x4(a: *mut u16, b: uint16x4x4_t) { + vst1_s16_x4(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_u32_x4(a: *mut u32, b: uint32x2x4_t) { + vst1_s32_x4(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_u64_x4(a: *mut u64, b: uint64x1x4_t) { + vst1_s64_x4(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 vst1q_u8_x4(a: *mut u8, b: uint8x16x4_t) { + vst1q_s8_x4(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 vst1q_u16_x4(a: *mut u16, b: uint16x8x4_t) { + vst1q_s16_x4(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 vst1q_u32_x4(a: *mut u32, b: uint32x4x4_t) { + vst1q_s32_x4(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 vst1q_u64_x4(a: *mut u64, b: uint64x2x4_t) { + vst1q_s64_x4(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_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)) +} + +/// 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_x4(a: *mut p8, b: poly8x8x4_t) { + vst1_s8_x4(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 vst1q_p8_x2(a: *mut p8, b: poly8x16x2_t) { + vst1q_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 vst1q_p8_x3(a: *mut p8, b: poly8x16x3_t) { + vst1q_s8_x3(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 vst1q_p8_x4(a: *mut p8, b: poly8x16x4_t) { + vst1q_s8_x4(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_p16_x2(a: *mut p16, b: poly16x4x2_t) { + vst1_s16_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_p16_x3(a: *mut p16, b: poly16x4x3_t) { + vst1_s16_x3(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_p16_x4(a: *mut p16, b: poly16x4x4_t) { + vst1_s16_x4(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 vst1q_p16_x2(a: *mut p16, b: poly16x8x2_t) { + vst1q_s16_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 vst1q_p16_x3(a: *mut p16, b: poly16x8x3_t) { + vst1q_s16_x3(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 vst1q_p16_x4(a: *mut p16, b: poly16x8x4_t) { + vst1q_s16_x4(transmute(a), transmute(b)) +} + +/// Store multiple single-element structures to 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_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) +} + +/// Store multiple single-element structures to one, two, three, or four 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) { + #[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) +} + +/// Store multiple single-element structures to 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 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) +} + +/// Store multiple single-element structures to one, two, three, or four 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) { + #[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) +} + +/// Store multiple single-element structures to 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_f32_x3(a: *mut f32, b: float32x2x3_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); + } +vst1_f32_x3_(a, b.0, b.1, b.2) +} + +/// Store multiple single-element structures to one, two, three, or four 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) { + #[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); + } +vst1_f32_x3_(b.0, b.1, b.2, a) +} + +/// Store multiple single-element structures to 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 vst1q_f32_x3(a: *mut f32, b: float32x4x3_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); + } +vst1q_f32_x3_(a, b.0, b.1, b.2) +} + +/// Store multiple single-element structures to one, two, three, or four 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) { + #[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); + } +vst1q_f32_x3_(b.0, b.1, b.2, a) +} + +/// Store multiple single-element structures to 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_f32_x4(a: *mut f32, b: float32x2x4_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); + } +vst1_f32_x4_(a, b.0, b.1, b.2, b.3) +} + +/// Store multiple single-element structures to one, two, three, or four 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) { + #[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); + } +vst1_f32_x4_(b.0, b.1, b.2, b.3, a) +} + +/// Store multiple single-element structures to 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 vst1q_f32_x4(a: *mut f32, b: float32x4x4_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); + } +vst1q_f32_x4_(a, b.0, b.1, b.2, b.3) +} + +/// Store multiple single-element structures to one, two, three, or four 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) { + #[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); + } +vst1q_f32_x4_(b.0, b.1, b.2, b.3, a) +} + /// Multiply #[inline] #[target_feature(enable = "neon")] @@ -5986,7 +8086,7 @@ pub unsafe fn vmulq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { #[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 "C" { + 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; @@ -6002,7 +8102,7 @@ vmul_p8_(a, b) #[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 "C" { + 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; @@ -6378,7 +8478,7 @@ pub unsafe fn vmulq_laneq_f32(a: float32x4_t, b: float32x4_t) - #[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 "C" { + 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; @@ -6394,7 +8494,7 @@ vmull_s8_(a, b) #[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 "C" { + 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; @@ -6410,7 +8510,7 @@ vmull_s16_(a, b) #[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 "C" { + 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; @@ -6426,7 +8526,7 @@ vmull_s32_(a, b) #[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 "C" { + 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; @@ -6442,7 +8542,7 @@ vmull_u8_(a, b) #[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 "C" { + 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; @@ -6458,7 +8558,7 @@ vmull_u16_(a, b) #[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 "C" { + 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; @@ -6474,7 +8574,7 @@ vmull_u32_(a, b) #[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 "C" { + 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; @@ -6488,7 +8588,7 @@ vmull_p8_(a, b) #[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 vmullh_n_s16(a: int16x4_t, b: i16) -> int32x4_t { +pub unsafe fn vmull_n_s16(a: int16x4_t, b: i16) -> int32x4_t { vmull_s16(a, vdup_n_s16(b)) } @@ -6498,7 +8598,7 @@ pub unsafe fn vmullh_n_s16(a: int16x4_t, b: i16) -> int32x4_t { #[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 vmulls_n_s32(a: int32x2_t, b: i32) -> int64x2_t { +pub unsafe fn vmull_n_s32(a: int32x2_t, b: i32) -> int64x2_t { vmull_s32(a, vdup_n_s32(b)) } @@ -6508,7 +8608,7 @@ pub unsafe fn vmulls_n_s32(a: int32x2_t, b: i32) -> int64x2_t { #[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 vmullh_n_u16(a: uint16x4_t, b: u16) -> uint32x4_t { +pub unsafe fn vmull_n_u16(a: uint16x4_t, b: u16) -> uint32x4_t { vmull_u16(a, vdup_n_u16(b)) } @@ -6518,7 +8618,7 @@ pub unsafe fn vmullh_n_u16(a: uint16x4_t, b: u16) -> uint32x4_t { #[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 vmulls_n_u32(a: uint32x2_t, b: u32) -> uint64x2_t { +pub unsafe fn vmull_n_u32(a: uint32x2_t, b: u32) -> uint64x2_t { vmull_u32(a, vdup_n_u32(b)) } @@ -6621,12 +8721,12 @@ pub unsafe fn vmull_laneq_u32(a: uint32x2_t, b: uint32x4_t) -> /// Floating-point fused Multiply-Add to accumulator(vector) #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "fp-armv8,v8"))] +#[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 "C" { + 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; @@ -6637,12 +8737,12 @@ vfma_f32_(b, c, a) /// Floating-point fused Multiply-Add to accumulator(vector) #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "fp-armv8,v8"))] +#[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 "C" { + 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; @@ -6653,27 +8753,27 @@ vfmaq_f32_(b, c, a) /// Floating-point fused Multiply-Add to accumulator(vector) #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "fp-armv8,v8"))] +#[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(c)) + vfma_f32(a, b, vdup_n_f32_vfp4(c)) } /// Floating-point fused Multiply-Add to accumulator(vector) #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "fp-armv8,v8"))] +#[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(c)) + vfmaq_f32(a, b, vdupq_n_f32_vfp4(c)) } /// Floating-point fused multiply-subtract from accumulator #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "fp-armv8,v8"))] +#[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 { @@ -6684,7 +8784,7 @@ pub unsafe fn vfms_f32(a: float32x2_t, b: float32x2_t, c: float32x2_t) -> float3 /// Floating-point fused multiply-subtract from accumulator #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "fp-armv8,v8"))] +#[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 { @@ -6695,21 +8795,21 @@ pub unsafe fn vfmsq_f32(a: float32x4_t, b: float32x4_t, c: float32x4_t) -> float /// Floating-point fused Multiply-subtract to accumulator(vector) #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "fp-armv8,v8"))] +#[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(c)) + vfms_f32(a, b, vdup_n_f32_vfp4(c)) } /// Floating-point fused Multiply-subtract to accumulator(vector) #[inline] #[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "fp-armv8,v8"))] +#[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(c)) + vfmsq_f32(a, b, vdupq_n_f32_vfp4(c)) } /// Subtract @@ -7032,7 +9132,7 @@ pub unsafe fn vsubhn_high_u64(a: uint32x2_t, b: uint64x2_t, c: uint64x2_t) -> ui #[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 "C" { + 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; @@ -7048,7 +9148,7 @@ vhsub_u8_(a, b) #[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 "C" { + 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; @@ -7064,7 +9164,7 @@ vhsubq_u8_(a, b) #[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 "C" { + 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; @@ -7080,7 +9180,7 @@ vhsub_u16_(a, b) #[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 "C" { + 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; @@ -7096,7 +9196,7 @@ vhsubq_u16_(a, b) #[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 "C" { + 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; @@ -7112,7 +9212,7 @@ vhsub_u32_(a, b) #[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 "C" { + 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; @@ -7128,7 +9228,7 @@ vhsubq_u32_(a, b) #[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 "C" { + 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; @@ -7144,7 +9244,7 @@ vhsub_s8_(a, b) #[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 "C" { + 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; @@ -7160,7 +9260,7 @@ vhsubq_s8_(a, b) #[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 "C" { + 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; @@ -7176,7 +9276,7 @@ vhsub_s16_(a, b) #[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 "C" { + 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; @@ -7192,7 +9292,7 @@ vhsubq_s16_(a, b) #[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 "C" { + 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; @@ -7208,7 +9308,7 @@ vhsub_s32_(a, b) #[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 "C" { + 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; @@ -7356,7 +9456,7 @@ pub unsafe fn vsubl_u32(a: uint32x2_t, b: uint32x2_t) -> uint64x2_t { #[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 "C" { + 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; @@ -7372,7 +9472,7 @@ vmax_s8_(a, b) #[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 "C" { + 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; @@ -7388,7 +9488,7 @@ vmaxq_s8_(a, b) #[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 "C" { + 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; @@ -7404,7 +9504,7 @@ vmax_s16_(a, b) #[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 "C" { + 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; @@ -7420,7 +9520,7 @@ vmaxq_s16_(a, b) #[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 "C" { + 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; @@ -7436,7 +9536,7 @@ vmax_s32_(a, b) #[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 "C" { + 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; @@ -7452,7 +9552,7 @@ vmaxq_s32_(a, b) #[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 "C" { + 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; @@ -7468,7 +9568,7 @@ vmax_u8_(a, b) #[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 "C" { + 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; @@ -7484,7 +9584,7 @@ vmaxq_u8_(a, b) #[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 "C" { + 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; @@ -7500,7 +9600,7 @@ vmax_u16_(a, b) #[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 "C" { + 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; @@ -7516,7 +9616,7 @@ vmaxq_u16_(a, b) #[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 "C" { + 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; @@ -7532,7 +9632,7 @@ vmax_u32_(a, b) #[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 "C" { + 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; @@ -7548,7 +9648,7 @@ vmaxq_u32_(a, b) #[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 "C" { + 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; @@ -7564,7 +9664,7 @@ vmax_f32_(a, b) #[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 "C" { + 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; @@ -7580,7 +9680,7 @@ vmaxq_f32_(a, b) #[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 "C" { + 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; @@ -7596,7 +9696,7 @@ vmaxnm_f32_(a, b) #[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 "C" { + 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; @@ -7612,7 +9712,7 @@ vmaxnmq_f32_(a, b) #[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 "C" { + 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; @@ -7628,7 +9728,7 @@ vmin_s8_(a, b) #[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 "C" { + 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; @@ -7644,7 +9744,7 @@ vminq_s8_(a, b) #[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 "C" { + 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; @@ -7660,7 +9760,7 @@ vmin_s16_(a, b) #[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 "C" { + 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; @@ -7676,7 +9776,7 @@ vminq_s16_(a, b) #[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 "C" { + 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; @@ -7692,7 +9792,7 @@ vmin_s32_(a, b) #[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 "C" { + 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; @@ -7708,7 +9808,7 @@ vminq_s32_(a, b) #[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 "C" { + 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; @@ -7724,7 +9824,7 @@ vmin_u8_(a, b) #[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 "C" { + 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; @@ -7740,7 +9840,7 @@ vminq_u8_(a, b) #[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 "C" { + 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; @@ -7756,7 +9856,7 @@ vmin_u16_(a, b) #[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 "C" { + 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; @@ -7772,7 +9872,7 @@ vminq_u16_(a, b) #[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 "C" { + 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; @@ -7788,7 +9888,7 @@ vmin_u32_(a, b) #[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 "C" { + 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; @@ -7804,7 +9904,7 @@ vminq_u32_(a, b) #[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 "C" { + 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; @@ -7820,7 +9920,7 @@ vmin_f32_(a, b) #[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 "C" { + 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; @@ -7836,7 +9936,7 @@ vminq_f32_(a, b) #[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 "C" { + 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; @@ -7852,7 +9952,7 @@ vminnm_f32_(a, b) #[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 "C" { + 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; @@ -7868,7 +9968,7 @@ vminnmq_f32_(a, b) #[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 "C" { + 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; @@ -7884,7 +9984,7 @@ vqdmull_s16_(a, b) #[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 "C" { + 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; @@ -8074,7 +10174,7 @@ pub unsafe fn vqdmlsl_lane_s32(a: int64x2_t, b: int32x2_t, c: int3 #[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 "C" { + 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; @@ -8090,7 +10190,7 @@ vqdmulh_s16_(a, b) #[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 "C" { + 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; @@ -8106,7 +10206,7 @@ vqdmulhq_s16_(a, b) #[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 "C" { + 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; @@ -8122,7 +10222,7 @@ vqdmulh_s32_(a, b) #[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 "C" { + 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; @@ -8158,7 +10258,7 @@ pub unsafe fn vqdmulh_n_s32(a: int32x2_t, b: i32) -> int32x2_t { #[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_nq_s16(a: int16x8_t, b: i16) -> int16x8_t { +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) } @@ -8169,7 +10269,7 @@ pub unsafe fn vqdmulhq_nq_s16(a: int16x8_t, b: i16) -> int16x8_t { #[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_nq_s32(a: int32x4_t, b: i32) -> int32x4_t { +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) } @@ -8182,7 +10282,7 @@ pub unsafe fn vqdmulhq_nq_s32(a: int32x4_t, b: i32) -> int32x4_t { #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqxtn))] pub unsafe fn vqmovn_s16(a: int16x8_t) -> int8x8_t { #[allow(improper_ctypes)] - extern "C" { + 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; @@ -8198,7 +10298,7 @@ vqmovn_s16_(a) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqxtn))] pub unsafe fn vqmovn_s32(a: int32x4_t) -> int16x4_t { #[allow(improper_ctypes)] - extern "C" { + 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; @@ -8214,7 +10314,7 @@ vqmovn_s32_(a) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqxtn))] pub unsafe fn vqmovn_s64(a: int64x2_t) -> int32x2_t { #[allow(improper_ctypes)] - extern "C" { + 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; @@ -8230,7 +10330,7 @@ vqmovn_s64_(a) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqxtn))] pub unsafe fn vqmovn_u16(a: uint16x8_t) -> uint8x8_t { #[allow(improper_ctypes)] - extern "C" { + 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; @@ -8246,7 +10346,7 @@ vqmovn_u16_(a) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqxtn))] pub unsafe fn vqmovn_u32(a: uint32x4_t) -> uint16x4_t { #[allow(improper_ctypes)] - extern "C" { + 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; @@ -8262,7 +10362,7 @@ vqmovn_u32_(a) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqxtn))] pub unsafe fn vqmovn_u64(a: uint64x2_t) -> uint32x2_t { #[allow(improper_ctypes)] - extern "C" { + 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; @@ -8278,7 +10378,7 @@ vqmovn_u64_(a) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqxtun))] pub unsafe fn vqmovun_s16(a: int16x8_t) -> uint8x8_t { #[allow(improper_ctypes)] - extern "C" { + 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; @@ -8294,7 +10394,7 @@ vqmovun_s16_(a) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqxtun))] pub unsafe fn vqmovun_s32(a: int32x4_t) -> uint16x4_t { #[allow(improper_ctypes)] - extern "C" { + 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; @@ -8310,7 +10410,7 @@ vqmovun_s32_(a) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqxtun))] pub unsafe fn vqmovun_s64(a: int64x2_t) -> uint32x2_t { #[allow(improper_ctypes)] - extern "C" { + 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; @@ -8326,7 +10426,7 @@ vqmovun_s64_(a) #[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 "C" { + 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; @@ -8342,7 +10442,7 @@ vqrdmulh_s16_(a, b) #[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 "C" { + 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; @@ -8358,7 +10458,7 @@ vqrdmulhq_s16_(a, b) #[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 "C" { + 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; @@ -8374,7 +10474,7 @@ vqrdmulh_s32_(a, b) #[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 "C" { + 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; @@ -8806,7 +10906,7 @@ pub unsafe fn vqrdmlshq_laneq_s32(a: int32x4_t, b: int32x4_t, c #[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 "C" { + 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; @@ -8822,7 +10922,7 @@ vqrshl_s8_(a, b) #[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 "C" { + 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; @@ -8838,7 +10938,7 @@ vqrshlq_s8_(a, b) #[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 "C" { + 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; @@ -8854,7 +10954,7 @@ vqrshl_s16_(a, b) #[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 "C" { + 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; @@ -8870,7 +10970,7 @@ vqrshlq_s16_(a, b) #[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 "C" { + 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; @@ -8886,7 +10986,7 @@ vqrshl_s32_(a, b) #[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 "C" { + 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; @@ -8902,7 +11002,7 @@ vqrshlq_s32_(a, b) #[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 "C" { + 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; @@ -8918,7 +11018,7 @@ vqrshl_s64_(a, b) #[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 "C" { + 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; @@ -8934,7 +11034,7 @@ vqrshlq_s64_(a, b) #[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 "C" { + 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; @@ -8950,7 +11050,7 @@ vqrshl_u8_(a, b) #[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 "C" { + 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; @@ -8966,7 +11066,7 @@ vqrshlq_u8_(a, b) #[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 "C" { + 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; @@ -8982,7 +11082,7 @@ vqrshl_u16_(a, b) #[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 "C" { + 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; @@ -8998,7 +11098,7 @@ vqrshlq_u16_(a, b) #[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 "C" { + 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; @@ -9014,7 +11114,7 @@ vqrshl_u32_(a, b) #[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 "C" { + 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; @@ -9030,7 +11130,7 @@ vqrshlq_u32_(a, b) #[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 "C" { + 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; @@ -9046,7 +11146,7 @@ vqrshl_u64_(a, b) #[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 "C" { + 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; @@ -9063,7 +11163,7 @@ vqrshlq_u64_(a, b) pub unsafe fn vqrshrn_n_s16(a: int16x8_t) -> int8x8_t { static_assert!(N : i32 where N >= 1 && N <= 8); #[allow(improper_ctypes)] - extern "C" { + 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; } @@ -9079,7 +11179,7 @@ vqrshrn_n_s16_(a, int16x8_t(-N as i16, -N as i16, -N as i16, -N as i16, -N as i1 pub unsafe fn vqrshrn_n_s16(a: int16x8_t) -> int8x8_t { static_assert!(N : i32 where N >= 1 && N <= 8); #[allow(improper_ctypes)] - extern "C" { + 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; } @@ -9095,7 +11195,7 @@ vqrshrn_n_s16_(a, N) pub unsafe fn vqrshrn_n_s32(a: int32x4_t) -> int16x4_t { static_assert!(N : i32 where N >= 1 && N <= 16); #[allow(improper_ctypes)] - extern "C" { + 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; } @@ -9111,7 +11211,7 @@ vqrshrn_n_s32_(a, int32x4_t(-N as i32, -N as i32, -N as i32, -N as i32)) pub unsafe fn vqrshrn_n_s32(a: int32x4_t) -> int16x4_t { static_assert!(N : i32 where N >= 1 && N <= 16); #[allow(improper_ctypes)] - extern "C" { + 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; } @@ -9127,7 +11227,7 @@ vqrshrn_n_s32_(a, N) pub unsafe fn vqrshrn_n_s64(a: int64x2_t) -> int32x2_t { static_assert!(N : i32 where N >= 1 && N <= 32); #[allow(improper_ctypes)] - extern "C" { + 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; } @@ -9143,7 +11243,7 @@ vqrshrn_n_s64_(a, int64x2_t(-N as i64, -N as i64)) pub unsafe fn vqrshrn_n_s64(a: int64x2_t) -> int32x2_t { static_assert!(N : i32 where N >= 1 && N <= 32); #[allow(improper_ctypes)] - extern "C" { + 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; } @@ -9159,7 +11259,7 @@ vqrshrn_n_s64_(a, N) pub unsafe fn vqrshrn_n_u16(a: uint16x8_t) -> uint8x8_t { static_assert!(N : i32 where N >= 1 && N <= 8); #[allow(improper_ctypes)] - extern "C" { + 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; } @@ -9175,7 +11275,7 @@ vqrshrn_n_u16_(a, uint16x8_t(-N as u16, -N as u16, -N as u16, -N as u16, -N as u pub unsafe fn vqrshrn_n_u16(a: uint16x8_t) -> uint8x8_t { static_assert!(N : i32 where N >= 1 && N <= 8); #[allow(improper_ctypes)] - extern "C" { + 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; } @@ -9191,7 +11291,7 @@ vqrshrn_n_u16_(a, N) pub unsafe fn vqrshrn_n_u32(a: uint32x4_t) -> uint16x4_t { static_assert!(N : i32 where N >= 1 && N <= 16); #[allow(improper_ctypes)] - extern "C" { + 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; } @@ -9207,7 +11307,7 @@ vqrshrn_n_u32_(a, uint32x4_t(-N as u32, -N as u32, -N as u32, -N as u32)) pub unsafe fn vqrshrn_n_u32(a: uint32x4_t) -> uint16x4_t { static_assert!(N : i32 where N >= 1 && N <= 16); #[allow(improper_ctypes)] - extern "C" { + 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; } @@ -9223,7 +11323,7 @@ vqrshrn_n_u32_(a, N) pub unsafe fn vqrshrn_n_u64(a: uint64x2_t) -> uint32x2_t { static_assert!(N : i32 where N >= 1 && N <= 32); #[allow(improper_ctypes)] - extern "C" { + 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; } @@ -9239,7 +11339,7 @@ vqrshrn_n_u64_(a, uint64x2_t(-N as u64, -N as u64)) pub unsafe fn vqrshrn_n_u64(a: uint64x2_t) -> uint32x2_t { static_assert!(N : i32 where N >= 1 && N <= 32); #[allow(improper_ctypes)] - extern "C" { + 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; } @@ -9255,7 +11355,7 @@ vqrshrn_n_u64_(a, N) pub unsafe fn vqrshrun_n_s16(a: int16x8_t) -> uint8x8_t { static_assert!(N : i32 where N >= 1 && N <= 8); #[allow(improper_ctypes)] - extern "C" { + 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; } @@ -9271,7 +11371,7 @@ vqrshrun_n_s16_(a, int16x8_t(-N as i16, -N as i16, -N as i16, -N as i16, -N as i pub unsafe fn vqrshrun_n_s16(a: int16x8_t) -> uint8x8_t { static_assert!(N : i32 where N >= 1 && N <= 8); #[allow(improper_ctypes)] - extern "C" { + 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; } @@ -9287,7 +11387,7 @@ vqrshrun_n_s16_(a, N) pub unsafe fn vqrshrun_n_s32(a: int32x4_t) -> uint16x4_t { static_assert!(N : i32 where N >= 1 && N <= 16); #[allow(improper_ctypes)] - extern "C" { + 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; } @@ -9303,7 +11403,7 @@ vqrshrun_n_s32_(a, int32x4_t(-N as i32, -N as i32, -N as i32, -N as i32)) pub unsafe fn vqrshrun_n_s32(a: int32x4_t) -> uint16x4_t { static_assert!(N : i32 where N >= 1 && N <= 16); #[allow(improper_ctypes)] - extern "C" { + 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; } @@ -9319,7 +11419,7 @@ vqrshrun_n_s32_(a, N) pub unsafe fn vqrshrun_n_s64(a: int64x2_t) -> uint32x2_t { static_assert!(N : i32 where N >= 1 && N <= 32); #[allow(improper_ctypes)] - extern "C" { + 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; } @@ -9335,7 +11435,7 @@ vqrshrun_n_s64_(a, int64x2_t(-N as i64, -N as i64)) pub unsafe fn vqrshrun_n_s64(a: int64x2_t) -> uint32x2_t { static_assert!(N : i32 where N >= 1 && N <= 32); #[allow(improper_ctypes)] - extern "C" { + 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; } @@ -9350,7 +11450,7 @@ vqrshrun_n_s64_(a, N) #[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 "C" { + 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; @@ -9366,7 +11466,7 @@ vqshl_s8_(a, b) #[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 "C" { + 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; @@ -9382,7 +11482,7 @@ vqshlq_s8_(a, b) #[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 "C" { + 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; @@ -9398,7 +11498,7 @@ vqshl_s16_(a, b) #[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 "C" { + 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; @@ -9414,7 +11514,7 @@ vqshlq_s16_(a, b) #[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 "C" { + 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; @@ -9430,7 +11530,7 @@ vqshl_s32_(a, b) #[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 "C" { + 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; @@ -9446,7 +11546,7 @@ vqshlq_s32_(a, b) #[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 "C" { + 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; @@ -9462,7 +11562,7 @@ vqshl_s64_(a, b) #[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 "C" { + 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; @@ -9478,7 +11578,7 @@ vqshlq_s64_(a, b) #[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 "C" { + 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; @@ -9494,7 +11594,7 @@ vqshl_u8_(a, b) #[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 "C" { + 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; @@ -9510,7 +11610,7 @@ vqshlq_u8_(a, b) #[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 "C" { + 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; @@ -9526,7 +11626,7 @@ vqshl_u16_(a, b) #[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 "C" { + 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; @@ -9542,7 +11642,7 @@ vqshlq_u16_(a, b) #[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 "C" { + 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; @@ -9558,7 +11658,7 @@ vqshl_u32_(a, b) #[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 "C" { + 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; @@ -9574,7 +11674,7 @@ vqshlq_u32_(a, b) #[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 "C" { + 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; @@ -9590,7 +11690,7 @@ vqshl_u64_(a, b) #[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 "C" { + 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; @@ -9799,7 +11899,7 @@ pub unsafe fn vqshlq_n_u64(a: uint64x2_t) -> uint64x2_t { pub unsafe fn vqshrn_n_s16(a: int16x8_t) -> int8x8_t { static_assert!(N : i32 where N >= 1 && N <= 8); #[allow(improper_ctypes)] - extern "C" { + 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; } @@ -9815,7 +11915,7 @@ vqshrn_n_s16_(a, int16x8_t(-N as i16, -N as i16, -N as i16, -N as i16, -N as i16 pub unsafe fn vqshrn_n_s16(a: int16x8_t) -> int8x8_t { static_assert!(N : i32 where N >= 1 && N <= 8); #[allow(improper_ctypes)] - extern "C" { + 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; } @@ -9831,7 +11931,7 @@ vqshrn_n_s16_(a, N) pub unsafe fn vqshrn_n_s32(a: int32x4_t) -> int16x4_t { static_assert!(N : i32 where N >= 1 && N <= 16); #[allow(improper_ctypes)] - extern "C" { + 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; } @@ -9847,7 +11947,7 @@ vqshrn_n_s32_(a, int32x4_t(-N as i32, -N as i32, -N as i32, -N as i32)) pub unsafe fn vqshrn_n_s32(a: int32x4_t) -> int16x4_t { static_assert!(N : i32 where N >= 1 && N <= 16); #[allow(improper_ctypes)] - extern "C" { + 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; } @@ -9863,7 +11963,7 @@ vqshrn_n_s32_(a, N) pub unsafe fn vqshrn_n_s64(a: int64x2_t) -> int32x2_t { static_assert!(N : i32 where N >= 1 && N <= 32); #[allow(improper_ctypes)] - extern "C" { + 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; } @@ -9879,7 +11979,7 @@ vqshrn_n_s64_(a, int64x2_t(-N as i64, -N as i64)) pub unsafe fn vqshrn_n_s64(a: int64x2_t) -> int32x2_t { static_assert!(N : i32 where N >= 1 && N <= 32); #[allow(improper_ctypes)] - extern "C" { + 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; } @@ -9895,7 +11995,7 @@ vqshrn_n_s64_(a, N) pub unsafe fn vqshrn_n_u16(a: uint16x8_t) -> uint8x8_t { static_assert!(N : i32 where N >= 1 && N <= 8); #[allow(improper_ctypes)] - extern "C" { + 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; } @@ -9911,7 +12011,7 @@ vqshrn_n_u16_(a, uint16x8_t(-N as u16, -N as u16, -N as u16, -N as u16, -N as u1 pub unsafe fn vqshrn_n_u16(a: uint16x8_t) -> uint8x8_t { static_assert!(N : i32 where N >= 1 && N <= 8); #[allow(improper_ctypes)] - extern "C" { + 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; } @@ -9927,7 +12027,7 @@ vqshrn_n_u16_(a, N) pub unsafe fn vqshrn_n_u32(a: uint32x4_t) -> uint16x4_t { static_assert!(N : i32 where N >= 1 && N <= 16); #[allow(improper_ctypes)] - extern "C" { + 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; } @@ -9943,7 +12043,7 @@ vqshrn_n_u32_(a, uint32x4_t(-N as u32, -N as u32, -N as u32, -N as u32)) pub unsafe fn vqshrn_n_u32(a: uint32x4_t) -> uint16x4_t { static_assert!(N : i32 where N >= 1 && N <= 16); #[allow(improper_ctypes)] - extern "C" { + 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; } @@ -9959,7 +12059,7 @@ vqshrn_n_u32_(a, N) pub unsafe fn vqshrn_n_u64(a: uint64x2_t) -> uint32x2_t { static_assert!(N : i32 where N >= 1 && N <= 32); #[allow(improper_ctypes)] - extern "C" { + 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; } @@ -9975,7 +12075,7 @@ vqshrn_n_u64_(a, uint64x2_t(-N as u64, -N as u64)) pub unsafe fn vqshrn_n_u64(a: uint64x2_t) -> uint32x2_t { static_assert!(N : i32 where N >= 1 && N <= 32); #[allow(improper_ctypes)] - extern "C" { + 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; } @@ -9991,7 +12091,7 @@ vqshrn_n_u64_(a, N) pub unsafe fn vqshrun_n_s16(a: int16x8_t) -> uint8x8_t { static_assert!(N : i32 where N >= 1 && N <= 8); #[allow(improper_ctypes)] - extern "C" { + 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; } @@ -10007,7 +12107,7 @@ vqshrun_n_s16_(a, int16x8_t(-N as i16, -N as i16, -N as i16, -N as i16, -N as i1 pub unsafe fn vqshrun_n_s16(a: int16x8_t) -> uint8x8_t { static_assert!(N : i32 where N >= 1 && N <= 8); #[allow(improper_ctypes)] - extern "C" { + 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; } @@ -10023,7 +12123,7 @@ vqshrun_n_s16_(a, N) pub unsafe fn vqshrun_n_s32(a: int32x4_t) -> uint16x4_t { static_assert!(N : i32 where N >= 1 && N <= 16); #[allow(improper_ctypes)] - extern "C" { + 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; } @@ -10039,7 +12139,7 @@ vqshrun_n_s32_(a, int32x4_t(-N as i32, -N as i32, -N as i32, -N as i32)) pub unsafe fn vqshrun_n_s32(a: int32x4_t) -> uint16x4_t { static_assert!(N : i32 where N >= 1 && N <= 16); #[allow(improper_ctypes)] - extern "C" { + 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; } @@ -10055,7 +12155,7 @@ vqshrun_n_s32_(a, N) pub unsafe fn vqshrun_n_s64(a: int64x2_t) -> uint32x2_t { static_assert!(N : i32 where N >= 1 && N <= 32); #[allow(improper_ctypes)] - extern "C" { + 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; } @@ -10071,7 +12171,7 @@ vqshrun_n_s64_(a, int64x2_t(-N as i64, -N as i64)) pub unsafe fn vqshrun_n_s64(a: int64x2_t) -> uint32x2_t { static_assert!(N : i32 where N >= 1 && N <= 32); #[allow(improper_ctypes)] - extern "C" { + 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; } @@ -10086,7 +12186,7 @@ vqshrun_n_s64_(a, N) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(frsqrte))] pub unsafe fn vrsqrte_f32(a: float32x2_t) -> float32x2_t { #[allow(improper_ctypes)] - extern "C" { + 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; @@ -10102,7 +12202,7 @@ vrsqrte_f32_(a) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(frsqrte))] pub unsafe fn vrsqrteq_f32(a: float32x4_t) -> float32x4_t { #[allow(improper_ctypes)] - extern "C" { + 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; @@ -10118,7 +12218,7 @@ vrsqrteq_f32_(a) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(frecpe))] pub unsafe fn vrecpe_f32(a: float32x2_t) -> float32x2_t { #[allow(improper_ctypes)] - extern "C" { + 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; @@ -10134,7 +12234,7 @@ vrecpe_f32_(a) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(frecpe))] pub unsafe fn vrecpeq_f32(a: float32x4_t) -> float32x4_t { #[allow(improper_ctypes)] - extern "C" { + 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; @@ -10146,8 +12246,8 @@ vrecpeq_f32_(a) #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -10156,8 +12256,8 @@ pub unsafe fn vreinterpret_s8_u8(a: uint8x8_t) -> int8x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -10166,8 +12266,8 @@ pub unsafe fn vreinterpret_s8_p8(a: poly8x8_t) -> int8x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -10176,8 +12276,8 @@ pub unsafe fn vreinterpret_s16_p16(a: poly16x4_t) -> int16x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -10186,8 +12286,8 @@ pub unsafe fn vreinterpret_s16_u16(a: uint16x4_t) -> int16x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -10196,8 +12296,8 @@ pub unsafe fn vreinterpret_s32_u32(a: uint32x2_t) -> int32x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -10206,8 +12306,8 @@ pub unsafe fn vreinterpret_s64_u64(a: uint64x1_t) -> int64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -10216,8 +12316,8 @@ pub unsafe fn vreinterpretq_s8_u8(a: uint8x16_t) -> int8x16_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -10226,8 +12326,8 @@ pub unsafe fn vreinterpretq_s8_p8(a: poly8x16_t) -> int8x16_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -10236,8 +12336,8 @@ pub unsafe fn vreinterpretq_s16_p16(a: poly16x8_t) -> int16x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -10246,8 +12346,8 @@ pub unsafe fn vreinterpretq_s16_u16(a: uint16x8_t) -> int16x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -10256,8 +12356,8 @@ pub unsafe fn vreinterpretq_s32_u32(a: uint32x4_t) -> int32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -10266,8 +12366,8 @@ pub unsafe fn vreinterpretq_s64_u64(a: uint64x2_t) -> int64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -10276,8 +12376,8 @@ pub unsafe fn vreinterpret_u8_p8(a: poly8x8_t) -> uint8x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -10286,8 +12386,8 @@ pub unsafe fn vreinterpret_u8_s8(a: int8x8_t) -> uint8x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -10296,8 +12396,8 @@ pub unsafe fn vreinterpret_u16_p16(a: poly16x4_t) -> uint16x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -10306,8 +12406,8 @@ pub unsafe fn vreinterpret_u16_s16(a: int16x4_t) -> uint16x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -10316,8 +12416,8 @@ pub unsafe fn vreinterpret_u32_s32(a: int32x2_t) -> uint32x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -10326,8 +12426,8 @@ pub unsafe fn vreinterpret_u64_s64(a: int64x1_t) -> uint64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -10336,8 +12436,8 @@ pub unsafe fn vreinterpretq_u8_p8(a: poly8x16_t) -> uint8x16_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -10346,8 +12446,8 @@ pub unsafe fn vreinterpretq_u8_s8(a: int8x16_t) -> uint8x16_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -10356,8 +12456,8 @@ pub unsafe fn vreinterpretq_u16_p16(a: poly16x8_t) -> uint16x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -10366,8 +12466,8 @@ pub unsafe fn vreinterpretq_u16_s16(a: int16x8_t) -> uint16x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -10376,8 +12476,8 @@ pub unsafe fn vreinterpretq_u32_s32(a: int32x4_t) -> uint32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -10386,8 +12486,8 @@ pub unsafe fn vreinterpretq_u64_s64(a: int64x2_t) -> uint64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -10396,8 +12496,8 @@ pub unsafe fn vreinterpret_p8_s8(a: int8x8_t) -> poly8x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -10406,8 +12506,8 @@ pub unsafe fn vreinterpret_p8_u8(a: uint8x8_t) -> poly8x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -10416,8 +12516,8 @@ pub unsafe fn vreinterpret_p16_s16(a: int16x4_t) -> poly16x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -10426,8 +12526,8 @@ pub unsafe fn vreinterpret_p16_u16(a: uint16x4_t) -> poly16x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -10436,8 +12536,8 @@ pub unsafe fn vreinterpretq_p8_s8(a: int8x16_t) -> poly8x16_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -10446,8 +12546,8 @@ pub unsafe fn vreinterpretq_p8_u8(a: uint8x16_t) -> poly8x16_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -10456,8 +12556,8 @@ pub unsafe fn vreinterpretq_p16_s16(a: int16x8_t) -> poly16x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -10466,8 +12566,8 @@ pub unsafe fn vreinterpretq_p16_u16(a: uint16x8_t) -> poly16x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -10476,8 +12576,8 @@ pub unsafe fn vreinterpret_s8_s16(a: int16x4_t) -> int8x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -10486,8 +12586,8 @@ pub unsafe fn vreinterpret_s8_u16(a: uint16x4_t) -> int8x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -10496,8 +12596,8 @@ pub unsafe fn vreinterpret_s8_p16(a: poly16x4_t) -> int8x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -10506,8 +12606,8 @@ pub unsafe fn vreinterpret_s16_s32(a: int32x2_t) -> int16x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -10516,8 +12616,8 @@ pub unsafe fn vreinterpret_s16_u32(a: uint32x2_t) -> int16x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -10526,8 +12626,8 @@ pub unsafe fn vreinterpret_s32_s64(a: int64x1_t) -> int32x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -10536,8 +12636,8 @@ pub unsafe fn vreinterpret_s32_u64(a: uint64x1_t) -> int32x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -10546,8 +12646,8 @@ pub unsafe fn vreinterpretq_s8_s16(a: int16x8_t) -> int8x16_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -10556,8 +12656,8 @@ pub unsafe fn vreinterpretq_s8_u16(a: uint16x8_t) -> int8x16_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -10566,8 +12666,8 @@ pub unsafe fn vreinterpretq_s8_p16(a: poly16x8_t) -> int8x16_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -10576,8 +12676,8 @@ pub unsafe fn vreinterpretq_s16_s32(a: int32x4_t) -> int16x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -10586,8 +12686,8 @@ pub unsafe fn vreinterpretq_s16_u32(a: uint32x4_t) -> int16x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -10596,8 +12696,8 @@ pub unsafe fn vreinterpretq_s32_s64(a: int64x2_t) -> int32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -10606,8 +12706,8 @@ pub unsafe fn vreinterpretq_s32_u64(a: uint64x2_t) -> int32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -10616,8 +12716,8 @@ pub unsafe fn vreinterpret_u8_p16(a: poly16x4_t) -> uint8x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -10626,8 +12726,8 @@ pub unsafe fn vreinterpret_u8_s16(a: int16x4_t) -> uint8x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -10636,8 +12736,8 @@ pub unsafe fn vreinterpret_u8_u16(a: uint16x4_t) -> uint8x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -10646,8 +12746,8 @@ pub unsafe fn vreinterpret_u16_s32(a: int32x2_t) -> uint16x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -10656,8 +12756,8 @@ pub unsafe fn vreinterpret_u16_u32(a: uint32x2_t) -> uint16x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -10666,8 +12766,8 @@ pub unsafe fn vreinterpret_u32_s64(a: int64x1_t) -> uint32x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -10676,8 +12776,8 @@ pub unsafe fn vreinterpret_u32_u64(a: uint64x1_t) -> uint32x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -10686,8 +12786,8 @@ pub unsafe fn vreinterpretq_u8_p16(a: poly16x8_t) -> uint8x16_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -10696,8 +12796,8 @@ pub unsafe fn vreinterpretq_u8_s16(a: int16x8_t) -> uint8x16_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -10706,8 +12806,8 @@ pub unsafe fn vreinterpretq_u8_u16(a: uint16x8_t) -> uint8x16_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -10716,8 +12816,8 @@ pub unsafe fn vreinterpretq_u16_s32(a: int32x4_t) -> uint16x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -10726,8 +12826,8 @@ pub unsafe fn vreinterpretq_u16_u32(a: uint32x4_t) -> uint16x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -10736,8 +12836,8 @@ pub unsafe fn vreinterpretq_u32_s64(a: int64x2_t) -> uint32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -10746,8 +12846,8 @@ pub unsafe fn vreinterpretq_u32_u64(a: uint64x2_t) -> uint32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -10756,8 +12856,8 @@ pub unsafe fn vreinterpret_p8_p16(a: poly16x4_t) -> poly8x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -10766,8 +12866,8 @@ pub unsafe fn vreinterpret_p8_s16(a: int16x4_t) -> poly8x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -10776,8 +12876,8 @@ pub unsafe fn vreinterpret_p8_u16(a: uint16x4_t) -> poly8x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -10786,8 +12886,8 @@ pub unsafe fn vreinterpret_p16_s32(a: int32x2_t) -> poly16x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -10796,8 +12896,8 @@ pub unsafe fn vreinterpret_p16_u32(a: uint32x2_t) -> poly16x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -10806,8 +12906,8 @@ pub unsafe fn vreinterpretq_p8_p16(a: poly16x8_t) -> poly8x16_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -10816,8 +12916,8 @@ pub unsafe fn vreinterpretq_p8_s16(a: int16x8_t) -> poly8x16_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -10826,8 +12926,8 @@ pub unsafe fn vreinterpretq_p8_u16(a: uint16x8_t) -> poly8x16_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -10836,8 +12936,8 @@ pub unsafe fn vreinterpretq_p16_s32(a: int32x4_t) -> poly16x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -10846,8 +12946,8 @@ pub unsafe fn vreinterpretq_p16_u32(a: uint32x4_t) -> poly16x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -10856,8 +12956,8 @@ pub unsafe fn vreinterpret_s16_p8(a: poly8x8_t) -> int16x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -10866,8 +12966,8 @@ pub unsafe fn vreinterpret_s16_s8(a: int8x8_t) -> int16x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -10876,8 +12976,8 @@ pub unsafe fn vreinterpret_s16_u8(a: uint8x8_t) -> int16x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -10886,8 +12986,8 @@ pub unsafe fn vreinterpret_s32_p16(a: poly16x4_t) -> int32x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -10896,8 +12996,8 @@ pub unsafe fn vreinterpret_s32_s16(a: int16x4_t) -> int32x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -10906,8 +13006,8 @@ pub unsafe fn vreinterpret_s32_u16(a: uint16x4_t) -> int32x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -10916,8 +13016,8 @@ pub unsafe fn vreinterpret_s64_s32(a: int32x2_t) -> int64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -10926,8 +13026,8 @@ pub unsafe fn vreinterpret_s64_u32(a: uint32x2_t) -> int64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -10936,8 +13036,8 @@ pub unsafe fn vreinterpretq_s16_p8(a: poly8x16_t) -> int16x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -10946,8 +13046,8 @@ pub unsafe fn vreinterpretq_s16_s8(a: int8x16_t) -> int16x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -10956,8 +13056,8 @@ pub unsafe fn vreinterpretq_s16_u8(a: uint8x16_t) -> int16x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -10966,8 +13066,8 @@ pub unsafe fn vreinterpretq_s32_p16(a: poly16x8_t) -> int32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -10976,8 +13076,8 @@ pub unsafe fn vreinterpretq_s32_s16(a: int16x8_t) -> int32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -10986,8 +13086,8 @@ pub unsafe fn vreinterpretq_s32_u16(a: uint16x8_t) -> int32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -10996,8 +13096,8 @@ pub unsafe fn vreinterpretq_s64_s32(a: int32x4_t) -> int64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -11006,8 +13106,8 @@ pub unsafe fn vreinterpretq_s64_u32(a: uint32x4_t) -> int64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -11016,8 +13116,8 @@ pub unsafe fn vreinterpret_u16_p8(a: poly8x8_t) -> uint16x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -11026,8 +13126,8 @@ pub unsafe fn vreinterpret_u16_s8(a: int8x8_t) -> uint16x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -11036,8 +13136,8 @@ pub unsafe fn vreinterpret_u16_u8(a: uint8x8_t) -> uint16x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -11046,8 +13146,8 @@ pub unsafe fn vreinterpret_u32_p16(a: poly16x4_t) -> uint32x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -11056,8 +13156,8 @@ pub unsafe fn vreinterpret_u32_s16(a: int16x4_t) -> uint32x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -11066,8 +13166,8 @@ pub unsafe fn vreinterpret_u32_u16(a: uint16x4_t) -> uint32x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -11076,8 +13176,8 @@ pub unsafe fn vreinterpret_u64_s32(a: int32x2_t) -> uint64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -11086,8 +13186,8 @@ pub unsafe fn vreinterpret_u64_u32(a: uint32x2_t) -> uint64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -11096,8 +13196,8 @@ pub unsafe fn vreinterpretq_u16_p8(a: poly8x16_t) -> uint16x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -11106,8 +13206,8 @@ pub unsafe fn vreinterpretq_u16_s8(a: int8x16_t) -> uint16x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -11116,8 +13216,8 @@ pub unsafe fn vreinterpretq_u16_u8(a: uint8x16_t) -> uint16x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -11126,8 +13226,8 @@ pub unsafe fn vreinterpretq_u32_p16(a: poly16x8_t) -> uint32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -11136,8 +13236,8 @@ pub unsafe fn vreinterpretq_u32_s16(a: int16x8_t) -> uint32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -11146,8 +13246,8 @@ pub unsafe fn vreinterpretq_u32_u16(a: uint16x8_t) -> uint32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -11156,8 +13256,8 @@ pub unsafe fn vreinterpretq_u64_s32(a: int32x4_t) -> uint64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -11166,8 +13266,8 @@ pub unsafe fn vreinterpretq_u64_u32(a: uint32x4_t) -> uint64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -11176,8 +13276,8 @@ pub unsafe fn vreinterpret_p16_p8(a: poly8x8_t) -> poly16x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -11186,8 +13286,8 @@ pub unsafe fn vreinterpret_p16_s8(a: int8x8_t) -> poly16x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -11196,8 +13296,8 @@ pub unsafe fn vreinterpret_p16_u8(a: uint8x8_t) -> poly16x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -11206,8 +13306,8 @@ pub unsafe fn vreinterpretq_p16_p8(a: poly8x16_t) -> poly16x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -11216,8 +13316,8 @@ pub unsafe fn vreinterpretq_p16_s8(a: int8x16_t) -> poly16x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -11226,8 +13326,8 @@ pub unsafe fn vreinterpretq_p16_u8(a: uint8x16_t) -> poly16x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -11236,8 +13336,8 @@ pub unsafe fn vreinterpret_s8_s32(a: int32x2_t) -> int8x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -11246,8 +13346,8 @@ pub unsafe fn vreinterpret_s8_u32(a: uint32x2_t) -> int8x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -11256,8 +13356,8 @@ pub unsafe fn vreinterpret_s16_s64(a: int64x1_t) -> int16x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -11266,8 +13366,8 @@ pub unsafe fn vreinterpret_s16_u64(a: uint64x1_t) -> int16x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -11276,8 +13376,8 @@ pub unsafe fn vreinterpretq_s8_s32(a: int32x4_t) -> int8x16_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -11286,8 +13386,8 @@ pub unsafe fn vreinterpretq_s8_u32(a: uint32x4_t) -> int8x16_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -11296,8 +13396,8 @@ pub unsafe fn vreinterpretq_s16_s64(a: int64x2_t) -> int16x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -11306,8 +13406,8 @@ pub unsafe fn vreinterpretq_s16_u64(a: uint64x2_t) -> int16x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -11316,8 +13416,8 @@ pub unsafe fn vreinterpret_u8_s32(a: int32x2_t) -> uint8x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -11326,8 +13426,8 @@ pub unsafe fn vreinterpret_u8_u32(a: uint32x2_t) -> uint8x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -11336,8 +13436,8 @@ pub unsafe fn vreinterpret_u16_s64(a: int64x1_t) -> uint16x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -11346,8 +13446,8 @@ pub unsafe fn vreinterpret_u16_u64(a: uint64x1_t) -> uint16x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -11356,8 +13456,8 @@ pub unsafe fn vreinterpretq_u8_s32(a: int32x4_t) -> uint8x16_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -11366,8 +13466,8 @@ pub unsafe fn vreinterpretq_u8_u32(a: uint32x4_t) -> uint8x16_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -11376,8 +13476,8 @@ pub unsafe fn vreinterpretq_u16_s64(a: int64x2_t) -> uint16x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -11386,8 +13486,8 @@ pub unsafe fn vreinterpretq_u16_u64(a: uint64x2_t) -> uint16x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -11396,8 +13496,8 @@ pub unsafe fn vreinterpret_p8_s32(a: int32x2_t) -> poly8x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -11406,8 +13506,8 @@ pub unsafe fn vreinterpret_p8_u32(a: uint32x2_t) -> poly8x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -11416,8 +13516,8 @@ pub unsafe fn vreinterpret_p16_s64(a: int64x1_t) -> poly16x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -11426,8 +13526,8 @@ pub unsafe fn vreinterpret_p16_u64(a: uint64x1_t) -> poly16x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -11436,8 +13536,8 @@ pub unsafe fn vreinterpretq_p8_s32(a: int32x4_t) -> poly8x16_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -11446,8 +13546,8 @@ pub unsafe fn vreinterpretq_p8_u32(a: uint32x4_t) -> poly8x16_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -11456,8 +13556,8 @@ pub unsafe fn vreinterpretq_p16_s64(a: int64x2_t) -> poly16x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -11466,8 +13566,8 @@ pub unsafe fn vreinterpretq_p16_u64(a: uint64x2_t) -> poly16x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -11476,8 +13576,8 @@ pub unsafe fn vreinterpret_s32_p8(a: poly8x8_t) -> int32x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -11486,8 +13586,8 @@ pub unsafe fn vreinterpret_s32_s8(a: int8x8_t) -> int32x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -11496,8 +13596,8 @@ pub unsafe fn vreinterpret_s32_u8(a: uint8x8_t) -> int32x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -11506,8 +13606,8 @@ pub unsafe fn vreinterpret_s64_p16(a: poly16x4_t) -> int64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -11516,8 +13616,8 @@ pub unsafe fn vreinterpret_s64_s16(a: int16x4_t) -> int64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -11526,8 +13626,8 @@ pub unsafe fn vreinterpret_s64_u16(a: uint16x4_t) -> int64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -11536,8 +13636,8 @@ pub unsafe fn vreinterpretq_s32_p8(a: poly8x16_t) -> int32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -11546,8 +13646,8 @@ pub unsafe fn vreinterpretq_s32_s8(a: int8x16_t) -> int32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -11556,8 +13656,8 @@ pub unsafe fn vreinterpretq_s32_u8(a: uint8x16_t) -> int32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -11566,8 +13666,8 @@ pub unsafe fn vreinterpretq_s64_p16(a: poly16x8_t) -> int64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -11576,8 +13676,8 @@ pub unsafe fn vreinterpretq_s64_s16(a: int16x8_t) -> int64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -11586,8 +13686,8 @@ pub unsafe fn vreinterpretq_s64_u16(a: uint16x8_t) -> int64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -11596,8 +13696,8 @@ pub unsafe fn vreinterpret_u32_p8(a: poly8x8_t) -> uint32x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -11606,8 +13706,8 @@ pub unsafe fn vreinterpret_u32_s8(a: int8x8_t) -> uint32x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -11616,8 +13716,8 @@ pub unsafe fn vreinterpret_u32_u8(a: uint8x8_t) -> uint32x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -11626,8 +13726,8 @@ pub unsafe fn vreinterpret_u64_p16(a: poly16x4_t) -> uint64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -11636,8 +13736,8 @@ pub unsafe fn vreinterpret_u64_s16(a: int16x4_t) -> uint64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -11646,8 +13746,8 @@ pub unsafe fn vreinterpret_u64_u16(a: uint16x4_t) -> uint64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -11656,8 +13756,8 @@ pub unsafe fn vreinterpretq_u32_p8(a: poly8x16_t) -> uint32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -11666,8 +13766,8 @@ pub unsafe fn vreinterpretq_u32_s8(a: int8x16_t) -> uint32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -11676,8 +13776,8 @@ pub unsafe fn vreinterpretq_u32_u8(a: uint8x16_t) -> uint32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -11686,8 +13786,8 @@ pub unsafe fn vreinterpretq_u64_p16(a: poly16x8_t) -> uint64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -11696,8 +13796,8 @@ pub unsafe fn vreinterpretq_u64_s16(a: int16x8_t) -> uint64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -11706,8 +13806,8 @@ pub unsafe fn vreinterpretq_u64_u16(a: uint16x8_t) -> uint64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -11716,8 +13816,8 @@ pub unsafe fn vreinterpret_s8_s64(a: int64x1_t) -> int8x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -11726,8 +13826,8 @@ pub unsafe fn vreinterpret_s8_u64(a: uint64x1_t) -> int8x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -11736,8 +13836,8 @@ pub unsafe fn vreinterpret_u8_s64(a: int64x1_t) -> uint8x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -11746,8 +13846,8 @@ pub unsafe fn vreinterpret_u8_u64(a: uint64x1_t) -> uint8x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -11756,8 +13856,8 @@ pub unsafe fn vreinterpret_p8_s64(a: int64x1_t) -> poly8x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -11766,8 +13866,8 @@ pub unsafe fn vreinterpret_p8_u64(a: uint64x1_t) -> poly8x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -11776,8 +13876,8 @@ pub unsafe fn vreinterpretq_s8_s64(a: int64x2_t) -> int8x16_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -11786,8 +13886,8 @@ pub unsafe fn vreinterpretq_s8_u64(a: uint64x2_t) -> int8x16_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -11796,8 +13896,8 @@ pub unsafe fn vreinterpretq_u8_s64(a: int64x2_t) -> uint8x16_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -11806,8 +13906,8 @@ pub unsafe fn vreinterpretq_u8_u64(a: uint64x2_t) -> uint8x16_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -11816,8 +13916,8 @@ pub unsafe fn vreinterpretq_p8_s64(a: int64x2_t) -> poly8x16_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -11826,8 +13926,8 @@ pub unsafe fn vreinterpretq_p8_u64(a: uint64x2_t) -> poly8x16_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -11836,8 +13936,8 @@ pub unsafe fn vreinterpret_s64_p8(a: poly8x8_t) -> int64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -11846,8 +13946,8 @@ pub unsafe fn vreinterpret_s64_s8(a: int8x8_t) -> int64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -11856,8 +13956,8 @@ pub unsafe fn vreinterpret_s64_u8(a: uint8x8_t) -> int64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -11866,8 +13966,8 @@ pub unsafe fn vreinterpret_u64_p8(a: poly8x8_t) -> uint64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -11876,8 +13976,8 @@ pub unsafe fn vreinterpret_u64_s8(a: int8x8_t) -> uint64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -11886,8 +13986,8 @@ pub unsafe fn vreinterpret_u64_u8(a: uint8x8_t) -> uint64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -11896,8 +13996,8 @@ pub unsafe fn vreinterpretq_s64_p8(a: poly8x16_t) -> int64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -11906,8 +14006,8 @@ pub unsafe fn vreinterpretq_s64_s8(a: int8x16_t) -> int64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -11916,8 +14016,8 @@ pub unsafe fn vreinterpretq_s64_u8(a: uint8x16_t) -> int64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -11926,8 +14026,8 @@ pub unsafe fn vreinterpretq_u64_p8(a: poly8x16_t) -> uint64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -11936,8 +14036,8 @@ pub unsafe fn vreinterpretq_u64_s8(a: int8x16_t) -> uint64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -11946,8 +14046,8 @@ pub unsafe fn vreinterpretq_u64_u8(a: uint8x16_t) -> uint64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -11956,8 +14056,8 @@ pub unsafe fn vreinterpret_s8_f32(a: float32x2_t) -> int8x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -11966,8 +14066,8 @@ pub unsafe fn vreinterpret_s16_f32(a: float32x2_t) -> int16x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -11976,8 +14076,8 @@ pub unsafe fn vreinterpret_s32_f32(a: float32x2_t) -> int32x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -11986,8 +14086,8 @@ pub unsafe fn vreinterpret_s64_f32(a: float32x2_t) -> int64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -11996,8 +14096,8 @@ pub unsafe fn vreinterpretq_s8_f32(a: float32x4_t) -> int8x16_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -12006,8 +14106,8 @@ pub unsafe fn vreinterpretq_s16_f32(a: float32x4_t) -> int16x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -12016,8 +14116,8 @@ pub unsafe fn vreinterpretq_s32_f32(a: float32x4_t) -> int32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -12026,8 +14126,8 @@ pub unsafe fn vreinterpretq_s64_f32(a: float32x4_t) -> int64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -12036,8 +14136,8 @@ pub unsafe fn vreinterpret_u8_f32(a: float32x2_t) -> uint8x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -12046,8 +14146,8 @@ pub unsafe fn vreinterpret_u16_f32(a: float32x2_t) -> uint16x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -12056,8 +14156,8 @@ pub unsafe fn vreinterpret_u32_f32(a: float32x2_t) -> uint32x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -12066,8 +14166,8 @@ pub unsafe fn vreinterpret_u64_f32(a: float32x2_t) -> uint64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -12076,8 +14176,8 @@ pub unsafe fn vreinterpretq_u8_f32(a: float32x4_t) -> uint8x16_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -12086,8 +14186,8 @@ pub unsafe fn vreinterpretq_u16_f32(a: float32x4_t) -> uint16x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -12096,8 +14196,8 @@ pub unsafe fn vreinterpretq_u32_f32(a: float32x4_t) -> uint32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -12106,8 +14206,8 @@ pub unsafe fn vreinterpretq_u64_f32(a: float32x4_t) -> uint64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -12116,8 +14216,8 @@ pub unsafe fn vreinterpret_p8_f32(a: float32x2_t) -> poly8x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -12126,8 +14226,8 @@ pub unsafe fn vreinterpret_p16_f32(a: float32x2_t) -> poly16x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -12136,8 +14236,8 @@ pub unsafe fn vreinterpretq_p8_f32(a: float32x4_t) -> poly8x16_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -12146,8 +14246,8 @@ pub unsafe fn vreinterpretq_p16_f32(a: float32x4_t) -> poly16x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -12156,8 +14256,8 @@ pub unsafe fn vreinterpret_f32_s8(a: int8x8_t) -> float32x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -12166,8 +14266,8 @@ pub unsafe fn vreinterpret_f32_s16(a: int16x4_t) -> float32x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -12176,8 +14276,8 @@ pub unsafe fn vreinterpret_f32_s32(a: int32x2_t) -> float32x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -12186,8 +14286,8 @@ pub unsafe fn vreinterpret_f32_s64(a: int64x1_t) -> float32x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -12196,8 +14296,8 @@ pub unsafe fn vreinterpretq_f32_s8(a: int8x16_t) -> float32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -12206,8 +14306,8 @@ pub unsafe fn vreinterpretq_f32_s16(a: int16x8_t) -> float32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -12216,8 +14316,8 @@ pub unsafe fn vreinterpretq_f32_s32(a: int32x4_t) -> float32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -12226,8 +14326,8 @@ pub unsafe fn vreinterpretq_f32_s64(a: int64x2_t) -> float32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -12236,8 +14336,8 @@ pub unsafe fn vreinterpret_f32_u8(a: uint8x8_t) -> float32x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -12246,8 +14346,8 @@ pub unsafe fn vreinterpret_f32_u16(a: uint16x4_t) -> float32x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -12256,8 +14356,8 @@ pub unsafe fn vreinterpret_f32_u32(a: uint32x2_t) -> float32x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -12266,8 +14366,8 @@ pub unsafe fn vreinterpret_f32_u64(a: uint64x1_t) -> float32x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -12276,8 +14376,8 @@ pub unsafe fn vreinterpretq_f32_u8(a: uint8x16_t) -> float32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -12286,8 +14386,8 @@ pub unsafe fn vreinterpretq_f32_u16(a: uint16x8_t) -> float32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -12296,8 +14396,8 @@ pub unsafe fn vreinterpretq_f32_u32(a: uint32x4_t) -> float32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -12306,8 +14406,8 @@ pub unsafe fn vreinterpretq_f32_u64(a: uint64x2_t) -> float32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -12316,8 +14416,8 @@ pub unsafe fn vreinterpret_f32_p8(a: poly8x8_t) -> float32x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -12326,8 +14426,8 @@ pub unsafe fn vreinterpret_f32_p16(a: poly16x4_t) -> float32x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -12336,8 +14436,8 @@ pub unsafe fn vreinterpretq_f32_p8(a: poly8x16_t) -> float32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(str))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(str))] +#[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) } @@ -12350,7 +14450,7 @@ pub unsafe fn vreinterpretq_f32_p16(a: poly16x8_t) -> float32x4_t { #[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 "C" { + 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; @@ -12366,7 +14466,7 @@ vrshl_s8_(a, b) #[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 "C" { + 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; @@ -12382,7 +14482,7 @@ vrshlq_s8_(a, b) #[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 "C" { + 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; @@ -12398,7 +14498,7 @@ vrshl_s16_(a, b) #[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 "C" { + 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; @@ -12414,7 +14514,7 @@ vrshlq_s16_(a, b) #[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 "C" { + 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; @@ -12430,7 +14530,7 @@ vrshl_s32_(a, b) #[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 "C" { + 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; @@ -12446,7 +14546,7 @@ vrshlq_s32_(a, b) #[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 "C" { + 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; @@ -12462,7 +14562,7 @@ vrshl_s64_(a, b) #[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 "C" { + 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; @@ -12478,7 +14578,7 @@ vrshlq_s64_(a, b) #[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 "C" { + 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; @@ -12494,7 +14594,7 @@ vrshl_u8_(a, b) #[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 "C" { + 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; @@ -12510,7 +14610,7 @@ vrshlq_u8_(a, b) #[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 "C" { + 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; @@ -12526,7 +14626,7 @@ vrshl_u16_(a, b) #[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 "C" { + 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; @@ -12542,7 +14642,7 @@ vrshlq_u16_(a, b) #[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 "C" { + 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; @@ -12558,7 +14658,7 @@ vrshl_u32_(a, b) #[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 "C" { + 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; @@ -12574,7 +14674,7 @@ vrshlq_u32_(a, b) #[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 "C" { + 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; @@ -12590,7 +14690,7 @@ vrshl_u64_(a, b) #[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 "C" { + 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; @@ -12799,7 +14899,7 @@ pub unsafe fn vrshrq_n_u64(a: uint64x2_t) -> uint64x2_t { pub unsafe fn vrshrn_n_s16(a: int16x8_t) -> int8x8_t { static_assert!(N : i32 where N >= 1 && N <= 8); #[allow(improper_ctypes)] - extern "C" { + 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; } @@ -12815,7 +14915,7 @@ vrshrn_n_s16_(a, int16x8_t(-N as i16, -N as i16, -N as i16, -N as i16, -N as i16 pub unsafe fn vrshrn_n_s16(a: int16x8_t) -> int8x8_t { static_assert!(N : i32 where N >= 1 && N <= 8); #[allow(improper_ctypes)] - extern "C" { + 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; } @@ -12831,7 +14931,7 @@ vrshrn_n_s16_(a, N) pub unsafe fn vrshrn_n_s32(a: int32x4_t) -> int16x4_t { static_assert!(N : i32 where N >= 1 && N <= 16); #[allow(improper_ctypes)] - extern "C" { + 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; } @@ -12847,7 +14947,7 @@ vrshrn_n_s32_(a, int32x4_t(-N as i32, -N as i32, -N as i32, -N as i32)) pub unsafe fn vrshrn_n_s32(a: int32x4_t) -> int16x4_t { static_assert!(N : i32 where N >= 1 && N <= 16); #[allow(improper_ctypes)] - extern "C" { + 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; } @@ -12863,7 +14963,7 @@ vrshrn_n_s32_(a, N) pub unsafe fn vrshrn_n_s64(a: int64x2_t) -> int32x2_t { static_assert!(N : i32 where N >= 1 && N <= 32); #[allow(improper_ctypes)] - extern "C" { + 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; } @@ -12879,7 +14979,7 @@ vrshrn_n_s64_(a, int64x2_t(-N as i64, -N as i64)) pub unsafe fn vrshrn_n_s64(a: int64x2_t) -> int32x2_t { static_assert!(N : i32 where N >= 1 && N <= 32); #[allow(improper_ctypes)] - extern "C" { + 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; } @@ -13237,7 +15337,7 @@ pub unsafe fn vset_lane_p16(a: p16, b: poly16x4_t) -> poly16x4_ /// Insert vector element from another vector element #[inline] #[target_feature(enable = "neon,aes")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "crypto,v8"))] +#[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)] @@ -13369,7 +15469,7 @@ pub unsafe fn vsetq_lane_p16(a: p16, b: poly16x8_t) -> poly16x8 /// Insert vector element from another vector element #[inline] #[target_feature(enable = "neon,aes")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "crypto,v8"))] +#[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)] @@ -13410,7 +15510,7 @@ pub unsafe fn vsetq_lane_f32(a: f32, b: float32x4_t) -> float32 #[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 "C" { + 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; @@ -13426,7 +15526,7 @@ vshl_s8_(a, b) #[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 "C" { + 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; @@ -13442,7 +15542,7 @@ vshlq_s8_(a, b) #[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 "C" { + 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; @@ -13458,7 +15558,7 @@ vshl_s16_(a, b) #[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 "C" { + 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; @@ -13474,7 +15574,7 @@ vshlq_s16_(a, b) #[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 "C" { + 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; @@ -13490,7 +15590,7 @@ vshl_s32_(a, b) #[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 "C" { + 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; @@ -13506,7 +15606,7 @@ vshlq_s32_(a, b) #[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 "C" { + 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; @@ -13522,7 +15622,7 @@ vshl_s64_(a, b) #[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 "C" { + 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; @@ -13538,7 +15638,7 @@ vshlq_s64_(a, b) #[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 "C" { + 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; @@ -13554,7 +15654,7 @@ vshl_u8_(a, b) #[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 "C" { + 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; @@ -13570,7 +15670,7 @@ vshlq_u8_(a, b) #[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 "C" { + 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; @@ -13586,7 +15686,7 @@ vshl_u16_(a, b) #[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 "C" { + 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; @@ -13602,7 +15702,7 @@ vshlq_u16_(a, b) #[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 "C" { + 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; @@ -13618,7 +15718,7 @@ vshl_u32_(a, b) #[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 "C" { + 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; @@ -13634,7 +15734,7 @@ vshlq_u32_(a, b) #[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 "C" { + 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; @@ -13650,7 +15750,7 @@ vshl_u64_(a, b) #[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 "C" { + 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; @@ -14455,7 +16555,7 @@ pub unsafe fn vabal_s32(a: int64x2_t, b: int32x2_t, c: int32x2_t) -> int64x2_t { #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqabs))] pub unsafe fn vqabs_s8(a: int8x8_t) -> int8x8_t { #[allow(improper_ctypes)] - extern "C" { + 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; @@ -14471,7 +16571,7 @@ vqabs_s8_(a) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqabs))] pub unsafe fn vqabsq_s8(a: int8x16_t) -> int8x16_t { #[allow(improper_ctypes)] - extern "C" { + 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; @@ -14487,7 +16587,7 @@ vqabsq_s8_(a) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqabs))] pub unsafe fn vqabs_s16(a: int16x4_t) -> int16x4_t { #[allow(improper_ctypes)] - extern "C" { + 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; @@ -14503,7 +16603,7 @@ vqabs_s16_(a) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqabs))] pub unsafe fn vqabsq_s16(a: int16x8_t) -> int16x8_t { #[allow(improper_ctypes)] - extern "C" { + 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; @@ -14519,7 +16619,7 @@ vqabsq_s16_(a) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqabs))] pub unsafe fn vqabs_s32(a: int32x2_t) -> int32x2_t { #[allow(improper_ctypes)] - extern "C" { + 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; @@ -14535,7 +16635,7 @@ vqabs_s32_(a) #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqabs))] pub unsafe fn vqabsq_s32(a: int32x4_t) -> int32x4_t { #[allow(improper_ctypes)] - extern "C" { + 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; @@ -18961,6 +21061,1176 @@ mod test { 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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())); + 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]; + let mut r: [u16; 16] = [0u16; 16]; + vst1q_p16_x2(r.as_mut_ptr(), vld1q_p16_x2(a[1..].as_ptr())); + 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())); + 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]; + let mut r: [u16; 32] = [0u16; 32]; + vst1q_p16_x4(r.as_mut_ptr(), vld1q_p16_x4(a[1..].as_ptr())); + 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())); + 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())); + 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())); + 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())); + 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.]; + let mut r: [f32; 8] = [0f32; 8]; + vst1_f32_x4(r.as_mut_ptr(), vld1_f32_x4(a[1..].as_ptr())); + 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.]; + let mut r: [f32; 16] = [0f32; 16]; + vst1q_f32_x4(r.as_mut_ptr(), vld1q_f32_x4(a[1..].as_ptr())); + assert_eq!(r, e); + } + #[simd_test(enable = "neon")] unsafe fn test_vmul_s8() { let a: i8x8 = i8x8::new(1, 2, 1, 2, 1, 2, 1, 2); @@ -19439,38 +22709,38 @@ mod test { } #[simd_test(enable = "neon")] - unsafe fn test_vmullh_n_s16() { + unsafe fn test_vmull_n_s16() { let a: i16x4 = i16x4::new(1, 2, 3, 4); let b: i16 = 2; let e: i32x4 = i32x4::new(2, 4, 6, 8); - let r: i32x4 = transmute(vmullh_n_s16(transmute(a), transmute(b))); + let r: i32x4 = transmute(vmull_n_s16(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmulls_n_s32() { + unsafe fn test_vmull_n_s32() { let a: i32x2 = i32x2::new(1, 2); let b: i32 = 2; let e: i64x2 = i64x2::new(2, 4); - let r: i64x2 = transmute(vmulls_n_s32(transmute(a), transmute(b))); + let r: i64x2 = transmute(vmull_n_s32(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmullh_n_u16() { + unsafe fn test_vmull_n_u16() { let a: u16x4 = u16x4::new(1, 2, 3, 4); let b: u16 = 2; let e: u32x4 = u32x4::new(2, 4, 6, 8); - let r: u32x4 = transmute(vmullh_n_u16(transmute(a), transmute(b))); + let r: u32x4 = transmute(vmull_n_u16(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmulls_n_u32() { + unsafe fn test_vmull_n_u32() { let a: u32x2 = u32x2::new(1, 2); let b: u32 = 2; let e: u64x2 = u64x2::new(2, 4); - let r: u64x2 = transmute(vmulls_n_u32(transmute(a), transmute(b))); + let r: u64x2 = transmute(vmull_n_u32(transmute(a), transmute(b))); assert_eq!(r, e); } @@ -20635,20 +23905,20 @@ mod test { } #[simd_test(enable = "neon")] - unsafe fn test_vqdmulhq_nq_s16() { + unsafe fn test_vqdmulhq_n_s16() { let a: i16x8 = i16x8::new(0x7F_FF, 0x7F_FF, 0x7F_FF, 0x7F_FF, 0x7F_FF, 0x7F_FF, 0x7F_FF, 0x7F_FF); let b: i16 = 2; let e: i16x8 = i16x8::new(1, 1, 1, 1, 1, 1, 1, 1); - let r: i16x8 = transmute(vqdmulhq_nq_s16(transmute(a), transmute(b))); + let r: i16x8 = transmute(vqdmulhq_n_s16(transmute(a), transmute(b))); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vqdmulhq_nq_s32() { + unsafe fn test_vqdmulhq_n_s32() { let a: i32x4 = i32x4::new(0x7F_FF_FF_FF, 0x7F_FF_FF_FF, 0x7F_FF_FF_FF, 0x7F_FF_FF_FF); let b: i32 = 2; let e: i32x4 = i32x4::new(1, 1, 1, 1); - let r: i32x4 = transmute(vqdmulhq_nq_s32(transmute(a), transmute(b))); + let r: i32x4 = transmute(vqdmulhq_n_s32(transmute(a), transmute(b))); assert_eq!(r, e); } diff --git a/library/stdarch/crates/core_arch/src/arm_shared/neon/load_tests.rs b/library/stdarch/crates/core_arch/src/arm_shared/neon/load_tests.rs index 82e2f74955..bbee29ae7a 100644 --- a/library/stdarch/crates/core_arch/src/arm_shared/neon/load_tests.rs +++ b/library/stdarch/crates/core_arch/src/arm_shared/neon/load_tests.rs @@ -173,6 +173,22 @@ unsafe fn test_vld1q_p16() { assert_eq!(r, e) } +#[simd_test(enable = "neon,aes")] +unsafe fn test_vld1_p64() { + let a: [p64; 2] = [0, 1]; + let e = u64x1::new(1); + let r: u64x1 = transmute(vld1_p64(a[1..].as_ptr())); + assert_eq!(r, e) +} + +#[simd_test(enable = "neon,aes")] +unsafe fn test_vld1q_p64() { + let a: [p64; 3] = [0, 1, 2]; + let e = u64x2::new(1, 2); + let r: u64x2 = transmute(vld1q_p64(a[1..].as_ptr())); + assert_eq!(r, e) +} + #[simd_test(enable = "neon")] unsafe fn test_vld1_f32() { let a: [f32; 3] = [0., 1., 2.]; @@ -188,21 +204,3 @@ unsafe fn test_vld1q_f32() { let r: f32x4 = transmute(vld1q_f32(a[1..].as_ptr())); assert_eq!(r, e) } - -#[cfg(target_arch = "aarch64")] -#[simd_test(enable = "neon")] -unsafe fn test_vld1_f64() { - let a: [f64; 2] = [0., 1.]; - let e = f64x1::new(1.); - let r: f64x1 = transmute(vld1_f64(a[1..].as_ptr())); - assert_eq!(r, e) -} - -#[cfg(target_arch = "aarch64")] -#[simd_test(enable = "neon")] -unsafe fn test_vld1q_f64() { - let a: [f64; 3] = [0., 1., 2.]; - let e = f64x2::new(1., 2.); - let r: f64x2 = transmute(vld1q_f64(a[1..].as_ptr())); - assert_eq!(r, e) -} 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 9ed9f77aa7..d3f88abd9b 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 @@ -92,6 +92,16 @@ pub struct int8x8x3_t(pub int8x8_t, pub int8x8_t, pub int8x8_t); #[derive(Copy, Clone)] 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)] +pub struct int8x16x2_t(pub int8x16_t, pub int8x16_t); +/// ARM-specific type containing three `int8x16_t` vectors. +#[derive(Copy, Clone)] +pub struct int8x16x3_t(pub int8x16_t, pub int8x16_t, pub int8x16_t); +/// ARM-specific type containing four `int8x16_t` vectors. +#[derive(Copy, Clone)] +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)] pub struct uint8x8x2_t(pub uint8x8_t, pub uint8x8_t); @@ -102,6 +112,21 @@ pub struct uint8x8x3_t(pub uint8x8_t, pub uint8x8_t, pub uint8x8_t); #[derive(Copy, Clone)] 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)] +pub struct uint8x16x2_t(pub uint8x16_t, pub uint8x16_t); +/// ARM-specific type containing three `uint8x16_t` vectors. +#[derive(Copy, Clone)] +pub struct uint8x16x3_t(pub uint8x16_t, pub uint8x16_t, pub uint8x16_t); +/// ARM-specific type containing four `uint8x16_t` vectors. +#[derive(Copy, Clone)] +pub struct uint8x16x4_t( + pub uint8x16_t, + pub uint8x16_t, + pub uint8x16_t, + pub uint8x16_t, +); + /// ARM-specific type containing two `poly8x8_t` vectors. #[derive(Copy, Clone)] pub struct poly8x8x2_t(pub poly8x8_t, pub poly8x8_t); @@ -112,8 +137,263 @@ pub struct poly8x8x3_t(pub poly8x8_t, pub poly8x8_t, pub poly8x8_t); #[derive(Copy, Clone)] 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)] +pub struct poly8x16x2_t(pub poly8x16_t, pub poly8x16_t); +/// ARM-specific type containing three `poly8x16_t` vectors. +#[derive(Copy, Clone)] +pub struct poly8x16x3_t(pub poly8x16_t, pub poly8x16_t, pub poly8x16_t); +/// ARM-specific type containing four `poly8x16_t` vectors. +#[derive(Copy, Clone)] +pub struct poly8x16x4_t( + pub poly8x16_t, + pub poly8x16_t, + pub poly8x16_t, + pub poly8x16_t, +); + +/// ARM-specific type containing two `int16x4_t` vectors. +#[derive(Copy, Clone)] +pub struct int16x4x2_t(pub int16x4_t, pub int16x4_t); +/// ARM-specific type containing three `int16x4_t` vectors. +#[derive(Copy, Clone)] +pub struct int16x4x3_t(pub int16x4_t, pub int16x4_t, pub int16x4_t); +/// ARM-specific type containing four `int16x4_t` vectors. +#[derive(Copy, Clone)] +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)] +pub struct int16x8x2_t(pub int16x8_t, pub int16x8_t); +/// ARM-specific type containing three `int16x8_t` vectors. +#[derive(Copy, Clone)] +pub struct int16x8x3_t(pub int16x8_t, pub int16x8_t, pub int16x8_t); +/// ARM-specific type containing four `int16x8_t` vectors. +#[derive(Copy, Clone)] +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)] +pub struct uint16x4x2_t(pub uint16x4_t, pub uint16x4_t); +/// ARM-specific type containing three `uint16x4_t` vectors. +#[derive(Copy, Clone)] +pub struct uint16x4x3_t(pub uint16x4_t, pub uint16x4_t, pub uint16x4_t); +/// ARM-specific type containing four `uint16x4_t` vectors. +#[derive(Copy, Clone)] +pub struct uint16x4x4_t( + pub uint16x4_t, + pub uint16x4_t, + pub uint16x4_t, + pub uint16x4_t, +); + +/// ARM-specific type containing two `uint16x8_t` vectors. +#[derive(Copy, Clone)] +pub struct uint16x8x2_t(pub uint16x8_t, pub uint16x8_t); +/// ARM-specific type containing three `uint16x8_t` vectors. +#[derive(Copy, Clone)] +pub struct uint16x8x3_t(pub uint16x8_t, pub uint16x8_t, pub uint16x8_t); +/// ARM-specific type containing four `uint16x8_t` vectors. +#[derive(Copy, Clone)] +pub struct uint16x8x4_t( + pub uint16x8_t, + pub uint16x8_t, + pub uint16x8_t, + pub uint16x8_t, +); + +/// ARM-specific type containing two `poly16x4_t` vectors. +#[derive(Copy, Clone)] +pub struct poly16x4x2_t(pub poly16x4_t, pub poly16x4_t); +/// ARM-specific type containing three `poly16x4_t` vectors. +#[derive(Copy, Clone)] +pub struct poly16x4x3_t(pub poly16x4_t, pub poly16x4_t, pub poly16x4_t); +/// ARM-specific type containing four `poly16x4_t` vectors. +#[derive(Copy, Clone)] +pub struct poly16x4x4_t( + pub poly16x4_t, + pub poly16x4_t, + pub poly16x4_t, + pub poly16x4_t, +); + +/// ARM-specific type containing two `poly16x8_t` vectors. +#[derive(Copy, Clone)] +pub struct poly16x8x2_t(pub poly16x8_t, pub poly16x8_t); +/// ARM-specific type containing three `poly16x8_t` vectors. +#[derive(Copy, Clone)] +pub struct poly16x8x3_t(pub poly16x8_t, pub poly16x8_t, pub poly16x8_t); +/// ARM-specific type containing four `poly16x8_t` vectors. +#[derive(Copy, Clone)] +pub struct poly16x8x4_t( + pub poly16x8_t, + pub poly16x8_t, + pub poly16x8_t, + pub poly16x8_t, +); + +/// ARM-specific type containing two `int32x2_t` vectors. +#[derive(Copy, Clone)] +pub struct int32x2x2_t(pub int32x2_t, pub int32x2_t); +/// ARM-specific type containing three `int32x2_t` vectors. +#[derive(Copy, Clone)] +pub struct int32x2x3_t(pub int32x2_t, pub int32x2_t, pub int32x2_t); +/// ARM-specific type containing four `int32x2_t` vectors. +#[derive(Copy, Clone)] +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)] +pub struct int32x4x2_t(pub int32x4_t, pub int32x4_t); +/// ARM-specific type containing three `int32x4_t` vectors. +#[derive(Copy, Clone)] +pub struct int32x4x3_t(pub int32x4_t, pub int32x4_t, pub int32x4_t); +/// ARM-specific type containing four `int32x4_t` vectors. +#[derive(Copy, Clone)] +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)] +pub struct uint32x2x2_t(pub uint32x2_t, pub uint32x2_t); +/// ARM-specific type containing three `uint32x2_t` vectors. +#[derive(Copy, Clone)] +pub struct uint32x2x3_t(pub uint32x2_t, pub uint32x2_t, pub uint32x2_t); +/// ARM-specific type containing four `uint32x2_t` vectors. +#[derive(Copy, Clone)] +pub struct uint32x2x4_t( + pub uint32x2_t, + pub uint32x2_t, + pub uint32x2_t, + pub uint32x2_t, +); + +/// ARM-specific type containing two `uint32x4_t` vectors. +#[derive(Copy, Clone)] +pub struct uint32x4x2_t(pub uint32x4_t, pub uint32x4_t); +/// ARM-specific type containing three `uint32x4_t` vectors. +#[derive(Copy, Clone)] +pub struct uint32x4x3_t(pub uint32x4_t, pub uint32x4_t, pub uint32x4_t); +/// ARM-specific type containing four `uint32x4_t` vectors. +#[derive(Copy, Clone)] +pub struct uint32x4x4_t( + pub uint32x4_t, + pub uint32x4_t, + pub uint32x4_t, + pub uint32x4_t, +); + +/// ARM-specific type containing two `float32x2_t` vectors. +#[derive(Copy, Clone)] +pub struct float32x2x2_t(pub float32x2_t, pub float32x2_t); +/// ARM-specific type containing three `float32x2_t` vectors. +#[derive(Copy, Clone)] +pub struct float32x2x3_t(pub float32x2_t, pub float32x2_t, pub float32x2_t); +/// ARM-specific type containing four `float32x2_t` vectors. +#[derive(Copy, Clone)] +pub struct float32x2x4_t( + pub float32x2_t, + pub float32x2_t, + pub float32x2_t, + pub float32x2_t, +); + +/// ARM-specific type containing two `float32x4_t` vectors. +#[derive(Copy, Clone)] +pub struct float32x4x2_t(pub float32x4_t, pub float32x4_t); +/// ARM-specific type containing three `float32x4_t` vectors. +#[derive(Copy, Clone)] +pub struct float32x4x3_t(pub float32x4_t, pub float32x4_t, pub float32x4_t); +/// ARM-specific type containing four `float32x4_t` vectors. +#[derive(Copy, Clone)] +pub struct float32x4x4_t( + pub float32x4_t, + pub float32x4_t, + pub float32x4_t, + pub float32x4_t, +); + +/// ARM-specific type containing four `int64x1_t` vectors. +#[derive(Copy, Clone)] +pub struct int64x1x2_t(pub int64x1_t, pub int64x1_t); +/// ARM-specific type containing four `int64x1_t` vectors. +#[derive(Copy, Clone)] +pub struct int64x1x3_t(pub int64x1_t, pub int64x1_t, pub int64x1_t); +/// ARM-specific type containing four `int64x1_t` vectors. +#[derive(Copy, Clone)] +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)] +pub struct int64x2x2_t(pub int64x2_t, pub int64x2_t); +/// ARM-specific type containing four `int64x2_t` vectors. +#[derive(Copy, Clone)] +pub struct int64x2x3_t(pub int64x2_t, pub int64x2_t, pub int64x2_t); +/// ARM-specific type containing four `int64x2_t` vectors. +#[derive(Copy, Clone)] +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)] +pub struct uint64x1x2_t(pub uint64x1_t, pub uint64x1_t); +/// ARM-specific type containing four `uint64x1_t` vectors. +#[derive(Copy, Clone)] +pub struct uint64x1x3_t(pub uint64x1_t, pub uint64x1_t, pub uint64x1_t); +/// ARM-specific type containing four `uint64x1_t` vectors. +#[derive(Copy, Clone)] +pub struct uint64x1x4_t( + pub uint64x1_t, + pub uint64x1_t, + pub uint64x1_t, + pub uint64x1_t, +); + +/// ARM-specific type containing four `uint64x2_t` vectors. +#[derive(Copy, Clone)] +pub struct uint64x2x2_t(pub uint64x2_t, pub uint64x2_t); +/// ARM-specific type containing four `uint64x2_t` vectors. +#[derive(Copy, Clone)] +pub struct uint64x2x3_t(pub uint64x2_t, pub uint64x2_t, pub uint64x2_t); +/// ARM-specific type containing four `uint64x2_t` vectors. +#[derive(Copy, Clone)] +pub struct uint64x2x4_t( + pub uint64x2_t, + pub uint64x2_t, + pub uint64x2_t, + pub uint64x2_t, +); + +/// ARM-specific type containing four `poly64x1_t` vectors. +#[derive(Copy, Clone)] +pub struct poly64x1x2_t(pub poly64x1_t, pub poly64x1_t); +/// ARM-specific type containing four `poly64x1_t` vectors. +#[derive(Copy, Clone)] +pub struct poly64x1x3_t(pub poly64x1_t, pub poly64x1_t, pub poly64x1_t); +/// ARM-specific type containing four `poly64x1_t` vectors. +#[derive(Copy, Clone)] +pub struct poly64x1x4_t( + pub poly64x1_t, + pub poly64x1_t, + pub poly64x1_t, + pub poly64x1_t, +); + +/// ARM-specific type containing four `poly64x2_t` vectors. +#[derive(Copy, Clone)] +pub struct poly64x2x2_t(pub poly64x2_t, pub poly64x2_t); +/// ARM-specific type containing four `poly64x2_t` vectors. +#[derive(Copy, Clone)] +pub struct poly64x2x3_t(pub poly64x2_t, pub poly64x2_t, pub poly64x2_t); +/// ARM-specific type containing four `poly64x2_t` vectors. +#[derive(Copy, Clone)] +pub struct poly64x2x4_t( + pub poly64x2_t, + pub poly64x2_t, + pub poly64x2_t, + pub poly64x2_t, +); + #[allow(improper_ctypes)] -extern "C" { +extern "unadjusted" { // absolute value (64-bit) #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vabs.v8i8")] #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.abs.v8i8")] @@ -543,6 +823,30 @@ pub unsafe fn vld1q_lane_p16(ptr: *const p16, src: poly16x8_t) simd_insert(src, LANE as u32, *ptr) } +/// Load one single-element structure to one lane of one register. +#[inline] +#[target_feature(enable = "neon,aes")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[rustc_legacy_const_generics(2)] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vldr", LANE = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ldr, LANE = 0))] +pub unsafe fn vld1_lane_p64(ptr: *const p64, src: poly64x1_t) -> poly64x1_t { + static_assert!(LANE : i32 where LANE == 0); + simd_insert(src, LANE as u32, *ptr) +} + +/// Load one single-element structure to one lane of one register. +#[inline] +#[target_feature(enable = "neon,aes")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[rustc_legacy_const_generics(2)] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vldr", LANE = 1))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1, LANE = 1))] +pub unsafe fn vld1q_lane_p64(ptr: *const p64, src: poly64x2_t) -> poly64x2_t { + static_assert_imm1!(LANE); + simd_insert(src, LANE as u32, *ptr) +} + /// Load one single-element structure to one lane of one register. #[inline] #[target_feature(enable = "neon")] @@ -810,6 +1114,34 @@ pub unsafe fn vld1_dup_f32(ptr: *const f32) -> float32x2_t { simd_shuffle2!(x, x, [0, 0]) } +/// Load one single-element structure and Replicate to all lanes (of one register). +#[inline] +#[target_feature(enable = "neon,aes")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vldr"))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ldr))] +pub unsafe fn vld1_dup_p64(ptr: *const p64) -> poly64x1_t { + #[cfg(target_arch = "aarch64")] + { + crate::core_arch::aarch64::vld1_p64(ptr) + } + #[cfg(target_arch = "arm")] + { + crate::core_arch::arm::vld1_p64(ptr) + } +} + +/// Load one single-element structure and Replicate to all lanes (of one register). +#[inline] +#[target_feature(enable = "neon,aes")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vldr"))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1r))] +pub unsafe fn vld1q_dup_p64(ptr: *const p64) -> poly64x2_t { + let x = vld1q_lane_p64::<0>(ptr, transmute(u64x2::splat(0))); + simd_shuffle2!(x, x, [0, 0]) +} + /// Load one single-element structure and Replicate to all lanes (of one register). #[inline] #[target_feature(enable = "neon")] @@ -2867,11 +3199,7 @@ pub unsafe fn vpmax_f32(a: float32x2_t, b: float32x2_t) -> float32x2_t { #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[rustc_legacy_const_generics(1)] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmov.32", IMM5 = 1))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mov, IMM5 = 1))] -// Based on the discussion in https://github.com/rust-lang/stdarch/pull/792 -// `mov` seems to be an acceptable intrinsic to compile to -// #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(vmov, IMM5 = 1))] +#[cfg_attr(test, assert_instr(nop, IMM5 = 1))] pub unsafe fn vgetq_lane_u64(v: uint64x2_t) -> u64 { static_assert_imm1!(IMM5); simd_extract(v, IMM5 as u32) @@ -2882,10 +3210,7 @@ pub unsafe fn vgetq_lane_u64(v: uint64x2_t) -> u64 { #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[rustc_legacy_const_generics(1)] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmov.32", IMM5 = 0))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmov, IMM5 = 0))] -// FIXME: no 32bit this seems to be turned into two vmov.32 instructions -// validate correctness +#[cfg_attr(test, assert_instr(nop, IMM5 = 0))] pub unsafe fn vget_lane_u64(v: uint64x1_t) -> u64 { static_assert!(IMM5 : i32 where IMM5 == 0); simd_extract(v, 0) @@ -2896,8 +3221,7 @@ pub unsafe fn vget_lane_u64(v: uint64x1_t) -> u64 { #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[rustc_legacy_const_generics(1)] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmov.u16", IMM5 = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umov, IMM5 = 2))] +#[cfg_attr(test, assert_instr(nop, IMM5 = 2))] pub unsafe fn vget_lane_u16(v: uint16x4_t) -> u16 { static_assert_imm2!(IMM5); simd_extract(v, IMM5 as u32) @@ -2908,8 +3232,7 @@ pub unsafe fn vget_lane_u16(v: uint16x4_t) -> u16 { #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[rustc_legacy_const_generics(1)] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmov.s16", IMM5 = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smov, IMM5 = 2))] +#[cfg_attr(test, assert_instr(nop, IMM5 = 2))] pub unsafe fn vget_lane_s16(v: int16x4_t) -> i16 { static_assert_imm2!(IMM5); simd_extract(v, IMM5 as u32) @@ -2920,8 +3243,7 @@ pub unsafe fn vget_lane_s16(v: int16x4_t) -> i16 { #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[rustc_legacy_const_generics(1)] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmov.u16", IMM5 = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umov, IMM5 = 2))] +#[cfg_attr(test, assert_instr(nop, IMM5 = 2))] pub unsafe fn vget_lane_p16(v: poly16x4_t) -> p16 { static_assert_imm2!(IMM5); simd_extract(v, IMM5 as u32) @@ -2932,8 +3254,7 @@ pub unsafe fn vget_lane_p16(v: poly16x4_t) -> p16 { #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[rustc_legacy_const_generics(1)] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmov.32", IMM5 = 1))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mov, IMM5 = 1))] +#[cfg_attr(test, assert_instr(nop, IMM5 = 1))] pub unsafe fn vget_lane_u32(v: uint32x2_t) -> u32 { static_assert_imm1!(IMM5); simd_extract(v, IMM5 as u32) @@ -2944,8 +3265,7 @@ pub unsafe fn vget_lane_u32(v: uint32x2_t) -> u32 { #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[rustc_legacy_const_generics(1)] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmov.32", IMM5 = 1))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mov, IMM5 = 1))] +#[cfg_attr(test, assert_instr(nop, IMM5 = 1))] pub unsafe fn vget_lane_s32(v: int32x2_t) -> i32 { static_assert_imm1!(IMM5); simd_extract(v, IMM5 as u32) @@ -2956,8 +3276,7 @@ pub unsafe fn vget_lane_s32(v: int32x2_t) -> i32 { #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[rustc_legacy_const_generics(1)] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmov.f32", IMM5 = 1))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mov, IMM5 = 1))] +#[cfg_attr(test, assert_instr(nop, IMM5 = 1))] pub unsafe fn vget_lane_f32(v: float32x2_t) -> f32 { static_assert_imm1!(IMM5); simd_extract(v, IMM5 as u32) @@ -2968,8 +3287,7 @@ pub unsafe fn vget_lane_f32(v: float32x2_t) -> f32 { #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[rustc_legacy_const_generics(1)] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmov.f32", IMM5 = 1))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mov, IMM5 = 1))] +#[cfg_attr(test, assert_instr(nop, IMM5 = 1))] pub unsafe fn vgetq_lane_f32(v: float32x4_t) -> f32 { static_assert_imm2!(IMM5); simd_extract(v, IMM5 as u32) @@ -2980,8 +3298,7 @@ pub unsafe fn vgetq_lane_f32(v: float32x4_t) -> f32 { #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[rustc_legacy_const_generics(1)] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmov.32", IMM5 = 0))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmov, IMM5 = 0))] +#[cfg_attr(test, assert_instr(nop, IMM5 = 0))] pub unsafe fn vget_lane_p64(v: poly64x1_t) -> p64 { static_assert!(IMM5 : i32 where IMM5 == 0); simd_extract(v, IMM5 as u32) @@ -2992,8 +3309,7 @@ pub unsafe fn vget_lane_p64(v: poly64x1_t) -> p64 { #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[rustc_legacy_const_generics(1)] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmov.32", IMM5 = 0))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmov, IMM5 = 0))] +#[cfg_attr(test, assert_instr(nop, IMM5 = 0))] pub unsafe fn vgetq_lane_p64(v: poly64x2_t) -> p64 { static_assert_imm1!(IMM5); simd_extract(v, IMM5 as u32) @@ -3004,8 +3320,7 @@ pub unsafe fn vgetq_lane_p64(v: poly64x2_t) -> p64 { #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[rustc_legacy_const_generics(1)] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmov.32", IMM5 = 0))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmov, IMM5 = 0))] +#[cfg_attr(test, assert_instr(nop, IMM5 = 0))] pub unsafe fn vget_lane_s64(v: int64x1_t) -> i64 { static_assert!(IMM5 : i32 where IMM5 == 0); simd_extract(v, IMM5 as u32) @@ -3016,8 +3331,7 @@ pub unsafe fn vget_lane_s64(v: int64x1_t) -> i64 { #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[rustc_legacy_const_generics(1)] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmov.32", IMM5 = 0))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmov, IMM5 = 0))] +#[cfg_attr(test, assert_instr(nop, IMM5 = 0))] pub unsafe fn vgetq_lane_s64(v: int64x2_t) -> i64 { static_assert_imm1!(IMM5); simd_extract(v, IMM5 as u32) @@ -3028,8 +3342,7 @@ pub unsafe fn vgetq_lane_s64(v: int64x2_t) -> i64 { #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[rustc_legacy_const_generics(1)] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmov.u16", IMM5 = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umov, IMM5 = 2))] +#[cfg_attr(test, assert_instr(nop, IMM5 = 2))] pub unsafe fn vgetq_lane_u16(v: uint16x8_t) -> u16 { static_assert_imm3!(IMM5); simd_extract(v, IMM5 as u32) @@ -3040,8 +3353,7 @@ pub unsafe fn vgetq_lane_u16(v: uint16x8_t) -> u16 { #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[rustc_legacy_const_generics(1)] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmov.32", IMM5 = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mov, IMM5 = 2))] +#[cfg_attr(test, assert_instr(nop, IMM5 = 2))] pub unsafe fn vgetq_lane_u32(v: uint32x4_t) -> u32 { static_assert_imm2!(IMM5); simd_extract(v, IMM5 as u32) @@ -3052,8 +3364,7 @@ pub unsafe fn vgetq_lane_u32(v: uint32x4_t) -> u32 { #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[rustc_legacy_const_generics(1)] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmov.s16", IMM5 = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smov, IMM5 = 2))] +#[cfg_attr(test, assert_instr(nop, IMM5 = 2))] pub unsafe fn vgetq_lane_s16(v: int16x8_t) -> i16 { static_assert_imm3!(IMM5); simd_extract(v, IMM5 as u32) @@ -3064,8 +3375,7 @@ pub unsafe fn vgetq_lane_s16(v: int16x8_t) -> i16 { #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[rustc_legacy_const_generics(1)] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmov.u16", IMM5 = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umov, IMM5 = 2))] +#[cfg_attr(test, assert_instr(nop, IMM5 = 2))] pub unsafe fn vgetq_lane_p16(v: poly16x8_t) -> p16 { static_assert_imm3!(IMM5); simd_extract(v, IMM5 as u32) @@ -3076,8 +3386,7 @@ pub unsafe fn vgetq_lane_p16(v: poly16x8_t) -> p16 { #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[rustc_legacy_const_generics(1)] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmov.32", IMM5 = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mov, IMM5 = 2))] +#[cfg_attr(test, assert_instr(nop, IMM5 = 2))] pub unsafe fn vgetq_lane_s32(v: int32x4_t) -> i32 { static_assert_imm2!(IMM5); simd_extract(v, IMM5 as u32) @@ -3088,8 +3397,7 @@ pub unsafe fn vgetq_lane_s32(v: int32x4_t) -> i32 { #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[rustc_legacy_const_generics(1)] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmov.u8", IMM5 = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umov, IMM5 = 2))] +#[cfg_attr(test, assert_instr(nop, IMM5 = 2))] pub unsafe fn vget_lane_u8(v: uint8x8_t) -> u8 { static_assert_imm3!(IMM5); simd_extract(v, IMM5 as u32) @@ -3100,8 +3408,7 @@ pub unsafe fn vget_lane_u8(v: uint8x8_t) -> u8 { #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[rustc_legacy_const_generics(1)] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmov.s8", IMM5 = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smov, IMM5 = 2))] +#[cfg_attr(test, assert_instr(nop, IMM5 = 2))] pub unsafe fn vget_lane_s8(v: int8x8_t) -> i8 { static_assert_imm3!(IMM5); simd_extract(v, IMM5 as u32) @@ -3112,8 +3419,7 @@ pub unsafe fn vget_lane_s8(v: int8x8_t) -> i8 { #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[rustc_legacy_const_generics(1)] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmov.u8", IMM5 = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umov, IMM5 = 2))] +#[cfg_attr(test, assert_instr(nop, IMM5 = 2))] pub unsafe fn vget_lane_p8(v: poly8x8_t) -> p8 { static_assert_imm3!(IMM5); simd_extract(v, IMM5 as u32) @@ -3124,8 +3430,7 @@ pub unsafe fn vget_lane_p8(v: poly8x8_t) -> p8 { #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[rustc_legacy_const_generics(1)] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmov.u8", IMM5 = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umov, IMM5 = 2))] +#[cfg_attr(test, assert_instr(nop, IMM5 = 2))] pub unsafe fn vgetq_lane_u8(v: uint8x16_t) -> u8 { static_assert_imm4!(IMM5); simd_extract(v, IMM5 as u32) @@ -3136,8 +3441,7 @@ pub unsafe fn vgetq_lane_u8(v: uint8x16_t) -> u8 { #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[rustc_legacy_const_generics(1)] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmov.s8", IMM5 = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smov, IMM5 = 2))] +#[cfg_attr(test, assert_instr(nop, IMM5 = 2))] pub unsafe fn vgetq_lane_s8(v: int8x16_t) -> i8 { static_assert_imm4!(IMM5); simd_extract(v, IMM5 as u32) @@ -3148,8 +3452,7 @@ pub unsafe fn vgetq_lane_s8(v: int8x16_t) -> i8 { #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[rustc_legacy_const_generics(1)] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmov.u8", IMM5 = 2))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umov, IMM5 = 2))] +#[cfg_attr(test, assert_instr(nop, IMM5 = 2))] pub unsafe fn vgetq_lane_p8(v: poly8x16_t) -> p8 { static_assert_imm4!(IMM5); simd_extract(v, IMM5 as u32) @@ -3269,8 +3572,7 @@ pub unsafe fn vget_high_f32(a: float32x4_t) -> float32x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("ldr"))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ldr))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vget_low_s8(a: int8x16_t) -> int8x8_t { simd_shuffle8!(a, a, [0, 1, 2, 3, 4, 5, 6, 7]) } @@ -3279,8 +3581,7 @@ pub unsafe fn vget_low_s8(a: int8x16_t) -> int8x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("ldr"))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ldr))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vget_low_s16(a: int16x8_t) -> int16x4_t { simd_shuffle4!(a, a, [0, 1, 2, 3]) } @@ -3289,8 +3590,7 @@ pub unsafe fn vget_low_s16(a: int16x8_t) -> int16x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("ldr"))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ldr))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vget_low_s32(a: int32x4_t) -> int32x2_t { simd_shuffle2!(a, a, [0, 1]) } @@ -3299,8 +3599,7 @@ pub unsafe fn vget_low_s32(a: int32x4_t) -> int32x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("ldr"))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ldr))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vget_low_s64(a: int64x2_t) -> int64x1_t { int64x1_t(simd_extract(a, 0)) } @@ -3309,8 +3608,7 @@ pub unsafe fn vget_low_s64(a: int64x2_t) -> int64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("ldr"))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ldr))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vget_low_u8(a: uint8x16_t) -> uint8x8_t { simd_shuffle8!(a, a, [0, 1, 2, 3, 4, 5, 6, 7]) } @@ -3319,8 +3617,7 @@ pub unsafe fn vget_low_u8(a: uint8x16_t) -> uint8x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("ldr"))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ldr))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vget_low_u16(a: uint16x8_t) -> uint16x4_t { simd_shuffle4!(a, a, [0, 1, 2, 3]) } @@ -3329,8 +3626,7 @@ pub unsafe fn vget_low_u16(a: uint16x8_t) -> uint16x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("ldr"))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ldr))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vget_low_u32(a: uint32x4_t) -> uint32x2_t { simd_shuffle2!(a, a, [0, 1]) } @@ -3339,8 +3635,7 @@ pub unsafe fn vget_low_u32(a: uint32x4_t) -> uint32x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("ldr"))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ldr))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vget_low_u64(a: uint64x2_t) -> uint64x1_t { uint64x1_t(simd_extract(a, 0)) } @@ -3349,8 +3644,7 @@ pub unsafe fn vget_low_u64(a: uint64x2_t) -> uint64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("ldr"))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ldr))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vget_low_p8(a: poly8x16_t) -> poly8x8_t { simd_shuffle8!(a, a, [0, 1, 2, 3, 4, 5, 6, 7]) } @@ -3359,8 +3653,7 @@ pub unsafe fn vget_low_p8(a: poly8x16_t) -> poly8x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("ldr"))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ldr))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vget_low_p16(a: poly16x8_t) -> poly16x4_t { simd_shuffle4!(a, a, [0, 1, 2, 3]) } @@ -3369,8 +3662,7 @@ pub unsafe fn vget_low_p16(a: poly16x8_t) -> poly16x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("ldr"))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ldr))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vget_low_f32(a: float32x4_t) -> float32x2_t { simd_shuffle2!(a, a, [0, 1]) } @@ -3494,6 +3786,19 @@ pub unsafe fn vdupq_n_f32(value: f32) -> float32x4_t { float32x4_t(value, value, value, value) } +/// Duplicate vector element to vector or scalar +/// +/// Private vfp4 version used by FMA intriniscs because LLVM does +/// not inline the non-vfp4 version in vfp4 functions. +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "vfp4"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.32"))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup))] +unsafe fn vdupq_n_f32_vfp4(value: f32) -> float32x4_t { + float32x4_t(value, value, value, value) +} + /// Duplicate vector element to vector or scalar #[inline] #[target_feature(enable = "neon")] @@ -3604,6 +3909,19 @@ pub unsafe fn vdup_n_f32(value: f32) -> float32x2_t { float32x2_t(value, value) } +/// Duplicate vector element to vector or scalar +/// +/// Private vfp4 version used by FMA intriniscs because LLVM does +/// not inline the non-vfp4 version in vfp4 functions. +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "vfp4"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.32"))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup))] +unsafe fn vdup_n_f32_vfp4(value: f32) -> float32x2_t { + float32x2_t(value, value) +} + /// Duplicate vector element to vector or scalar #[inline] #[target_feature(enable = "neon")] @@ -3828,8 +4146,8 @@ pub unsafe fn vmovq_n_f32(value: f32) -> float32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("str", N = 0))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr("str", N = 0))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("nop", N = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr("nop", N = 0))] #[rustc_legacy_const_generics(2)] pub unsafe fn vext_s64(a: int64x1_t, _b: int64x1_t) -> int64x1_t { if N != 0 { @@ -3842,8 +4160,8 @@ pub unsafe fn vext_s64(a: int64x1_t, _b: int64x1_t) -> int64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("str", N = 0))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr("str", N = 0))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("nop", N = 0))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr("nop", N = 0))] #[rustc_legacy_const_generics(2)] pub unsafe fn vext_u64(a: uint64x1_t, _b: uint64x1_t) -> uint64x1_t { if N != 0 { @@ -4663,6 +4981,24 @@ mod tests { assert_eq!(r, e) } + #[simd_test(enable = "neon,aes")] + unsafe fn test_vld1_lane_p64() { + let a = u64x1::new(0); + let elem: u64 = 42; + let e = u64x1::new(42); + let r: u64x1 = transmute(vld1_lane_p64::<0>(&elem, transmute(a))); + assert_eq!(r, e) + } + + #[simd_test(enable = "neon,aes")] + unsafe fn test_vld1q_lane_p64() { + let a = u64x2::new(0, 1); + let elem: u64 = 42; + let e = u64x2::new(0, 42); + let r: u64x2 = transmute(vld1q_lane_p64::<1>(&elem, transmute(a))); + assert_eq!(r, e) + } + #[simd_test(enable = "neon")] unsafe fn test_vld1_lane_f32() { let a = f32x2::new(0., 1.); @@ -4847,6 +5183,22 @@ mod tests { assert_eq!(r, e) } + #[simd_test(enable = "neon,aes")] + unsafe fn test_vld1_dup_p64() { + let elem: u64 = 42; + let e = u64x1::new(42); + let r: u64x1 = transmute(vld1_dup_p64(&elem)); + assert_eq!(r, e) + } + + #[simd_test(enable = "neon,aes")] + unsafe fn test_vld1q_dup_p64() { + let elem: u64 = 42; + let e = u64x2::new(42, 42); + let r: u64x2 = transmute(vld1q_dup_p64(&elem)); + assert_eq!(r, e) + } + #[simd_test(enable = "neon")] unsafe fn test_vld1_dup_f32() { let elem: f32 = 42.; diff --git a/library/stdarch/crates/core_arch/src/powerpc/vsx.rs b/library/stdarch/crates/core_arch/src/powerpc/vsx.rs index 54e067eb03..3141bc8bcd 100644 --- a/library/stdarch/crates/core_arch/src/powerpc/vsx.rs +++ b/library/stdarch/crates/core_arch/src/powerpc/vsx.rs @@ -21,7 +21,7 @@ types! { pub struct vector_signed_long(i64, i64); /// PowerPC-specific 128-bit wide vector of two packed `u64` pub struct vector_unsigned_long(u64, u64); - /// PowerPC-specific 128-bit wide vector mask of two elements + /// PowerPC-specific 128-bit wide vector mask of two `i64` pub struct vector_bool_long(i64, i64); /// PowerPC-specific 128-bit wide vector of two packed `f64` pub struct vector_double(f64, f64); diff --git a/library/stdarch/crates/core_arch/src/x86/avx512bw.rs b/library/stdarch/crates/core_arch/src/x86/avx512bw.rs index 4834f19edd..10e0096339 100644 --- a/library/stdarch/crates/core_arch/src/x86/avx512bw.rs +++ b/library/stdarch/crates/core_arch/src/x86/avx512bw.rs @@ -8013,7 +8013,7 @@ pub unsafe fn _mm_maskz_dbsad_epu8( /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_movepi16_mask&expand=3873) #[inline] #[target_feature(enable = "avx512bw")] -#[cfg_attr(test, assert_instr(mov))] // should be vpmovw2m but msvc does not generate it +#[cfg_attr(test, assert_instr(vpmovw2m))] pub unsafe fn _mm512_movepi16_mask(a: __m512i) -> __mmask32 { let filter = _mm512_set1_epi16(1 << 15); let a = _mm512_and_si512(a, filter); @@ -8025,7 +8025,7 @@ pub unsafe fn _mm512_movepi16_mask(a: __m512i) -> __mmask32 { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_movepi16_mask&expand=3872) #[inline] #[target_feature(enable = "avx512bw,avx512vl")] -#[cfg_attr(test, assert_instr(mov))] // should be vpmovw2m but msvc does not generate it +#[cfg_attr(test, assert_instr(vpmovw2m))] pub unsafe fn _mm256_movepi16_mask(a: __m256i) -> __mmask16 { let filter = _mm256_set1_epi16(1 << 15); let a = _mm256_and_si256(a, filter); @@ -8037,7 +8037,7 @@ pub unsafe fn _mm256_movepi16_mask(a: __m256i) -> __mmask16 { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_movepi16_mask&expand=3871) #[inline] #[target_feature(enable = "avx512bw,avx512vl")] -#[cfg_attr(test, assert_instr(mov))] // should be vpmovw2m but msvc does not generate it +#[cfg_attr(test, assert_instr(vpmovw2m))] pub unsafe fn _mm_movepi16_mask(a: __m128i) -> __mmask8 { let filter = _mm_set1_epi16(1 << 15); let a = _mm_and_si128(a, filter); @@ -8049,7 +8049,7 @@ pub unsafe fn _mm_movepi16_mask(a: __m128i) -> __mmask8 { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_movepi8_mask&expand=3883) #[inline] #[target_feature(enable = "avx512bw")] -#[cfg_attr(test, assert_instr(mov))] // should be vpmovb2m but msvc does not generate it +#[cfg_attr(test, assert_instr(vpmovb2m))] pub unsafe fn _mm512_movepi8_mask(a: __m512i) -> __mmask64 { let filter = _mm512_set1_epi8(1 << 7); let a = _mm512_and_si512(a, filter); @@ -8061,7 +8061,8 @@ pub unsafe fn _mm512_movepi8_mask(a: __m512i) -> __mmask64 { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_movepi8_mask&expand=3882) #[inline] #[target_feature(enable = "avx512bw,avx512vl")] -#[cfg_attr(test, assert_instr(mov))] // should be vpmovb2m but msvc does not generate it +#[cfg_attr(test, assert_instr(vpmovmskb))] // should be vpmovb2m but compiled to vpmovmskb in the test shim because that takes less cycles than + // using vpmovb2m plus converting the mask register to a standard register. pub unsafe fn _mm256_movepi8_mask(a: __m256i) -> __mmask32 { let filter = _mm256_set1_epi8(1 << 7); let a = _mm256_and_si256(a, filter); @@ -8073,7 +8074,8 @@ pub unsafe fn _mm256_movepi8_mask(a: __m256i) -> __mmask32 { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_movepi8_mask&expand=3881) #[inline] #[target_feature(enable = "avx512bw,avx512vl")] -#[cfg_attr(test, assert_instr(mov))] // should be vpmovb2m but msvc does not generate it +#[cfg_attr(test, assert_instr(vpmovmskb))] // should be vpmovb2m but compiled to vpmovmskb in the test shim because that takes less cycles than + // using vpmovb2m plus converting the mask register to a standard register. pub unsafe fn _mm_movepi8_mask(a: __m128i) -> __mmask16 { let filter = _mm_set1_epi8(1 << 7); let a = _mm_and_si128(a, filter); @@ -8216,8 +8218,9 @@ pub unsafe fn _mm_movm_epi8(k: __mmask16) -> __m128i { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_kadd_mask32&expand=3207) #[inline] #[target_feature(enable = "avx512bw")] -#[cfg_attr(test, assert_instr(mov))] // generate normal and code instead of kaddd - //llvm.x86.avx512.kadd.d +#[cfg_attr(all(test, target_arch = "x86"), assert_instr(add))] +#[cfg_attr(all(test, target_arch = "x86_64"), assert_instr(lea))] // generate normal lea/add code instead of kaddd + //llvm.x86.avx512.kadd.d pub unsafe fn _kadd_mask32(a: __mmask32, b: __mmask32) -> __mmask32 { transmute(a + b) } @@ -8227,7 +8230,9 @@ pub unsafe fn _kadd_mask32(a: __mmask32, b: __mmask32) -> __mmask32 { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_kadd_mask64&expand=3208) #[inline] #[target_feature(enable = "avx512bw")] -#[cfg_attr(test, assert_instr(mov))] // generate normal and code instead of kaddq +#[cfg_attr(all(test, target_arch = "x86"), assert_instr(add))] +#[cfg_attr(all(test, target_arch = "x86_64"), assert_instr(lea))] // generate normal lea/add code instead of kaddd + //llvm.x86.avx512.kadd.d pub unsafe fn _kadd_mask64(a: __mmask64, b: __mmask64) -> __mmask64 { transmute(a + b) } diff --git a/library/stdarch/crates/core_arch/src/x86_64/avx512f.rs b/library/stdarch/crates/core_arch/src/x86_64/avx512f.rs index 471977821c..5eed0502cb 100644 --- a/library/stdarch/crates/core_arch/src/x86_64/avx512f.rs +++ b/library/stdarch/crates/core_arch/src/x86_64/avx512f.rs @@ -75,7 +75,7 @@ pub unsafe fn _mm_cvti64_sd(a: __m128d, b: i64) -> __m128d { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtu64_ss&expand=2035) #[inline] #[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(mov))] // should be vcvtusi2ss +#[cfg_attr(test, assert_instr(vcvtusi2ss))] pub unsafe fn _mm_cvtu64_ss(a: __m128, b: u64) -> __m128 { let b = b as f32; let r = simd_insert(a, 0, b); @@ -87,7 +87,7 @@ pub unsafe fn _mm_cvtu64_ss(a: __m128, b: u64) -> __m128 { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtu64_sd&expand=2034) #[inline] #[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(mov))] // should be vcvtusi2sd +#[cfg_attr(test, assert_instr(vcvtusi2sd))] pub unsafe fn _mm_cvtu64_sd(a: __m128d, b: u64) -> __m128d { let b = b as f64; let r = simd_insert(a, 0, b); diff --git a/library/stdarch/crates/intrinsic-test/Cargo.toml b/library/stdarch/crates/intrinsic-test/Cargo.toml new file mode 100644 index 0000000000..4cdf811e5c --- /dev/null +++ b/library/stdarch/crates/intrinsic-test/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "intrinsic-test" +version = "0.1.0" +authors = ["Jamie Cunliffe "] +edition = "2018" + +[dependencies] +lazy_static = "1.4.0" +serde = { version = "1", features = ["derive"] } +csv = "1.1" +clap = "2.33.3" +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 --git a/library/stdarch/crates/intrinsic-test/README.md b/library/stdarch/crates/intrinsic-test/README.md new file mode 100644 index 0000000000..8a8ddab404 --- /dev/null +++ b/library/stdarch/crates/intrinsic-test/README.md @@ -0,0 +1,24 @@ +Generate and run programs using equivalent C and Rust intrinsics, checking that +each produces the same result from random inputs. + +# Usage +``` +USAGE: + intrinsic-test [OPTIONS] + +FLAGS: + -h, --help Prints help information + -V, --version Prints version information + +OPTIONS: + --cppcompiler The C++ compiler to use for compiling the c++ code [default: clang++] + --runner Run the C programs under emulation with this command + --toolchain The rust toolchain to use for building the rust code + +ARGS: + The input file containing the intrinsics +``` + +The intrinsic.csv is the arm neon tracking google sheet (https://docs.google.com/spreadsheets/d/1MqW1g8c7tlhdRWQixgdWvR4uJHNZzCYAf4V0oHjZkwA/edit#gid=0) +that contains the intrinsic list. The done percentage column should be renamed to "enabled". + diff --git a/library/stdarch/crates/intrinsic-test/neon-intrinsics.csv b/library/stdarch/crates/intrinsic-test/neon-intrinsics.csv new file mode 100644 index 0000000000..438c6667f5 --- /dev/null +++ b/library/stdarch/crates/intrinsic-test/neon-intrinsics.csv @@ -0,0 +1,4356 @@ +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/argument.rs b/library/stdarch/crates/intrinsic-test/src/argument.rs new file mode 100644 index 0000000000..96ed440ee7 --- /dev/null +++ b/library/stdarch/crates/intrinsic-test/src/argument.rs @@ -0,0 +1,137 @@ +use serde::{Deserialize, Deserializer}; + +use crate::types::IntrinsicType; +use crate::Language; + +/// An argument for the intrinsic. +#[derive(Debug, PartialEq, Clone)] +pub struct Argument { + /// The argument's index in the intrinsic function call. + pub pos: usize, + /// The argument name. + pub name: String, + /// The type of the argument. + pub ty: IntrinsicType, +} + +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())?; + + Ok(Self { pos, name, ty }) + } + + fn to_c_type(&self) -> String { + self.ty.c_type() + } + + fn is_simd(&self) -> bool { + self.ty.is_simd() + } + + pub fn is_ptr(&self) -> bool { + self.ty.is_ptr() + } +} + +#[derive(Debug, PartialEq, Clone)] +pub struct ArgumentList { + pub args: Vec, +} + +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 { + self.args + .iter() + .map(|arg| match arg.ty { + IntrinsicType::Ptr { .. } => { + format!("&{}", arg.name) + } + IntrinsicType::Type { .. } => arg.name.clone(), + }) + .collect::>() + .join(", ") + } + + /// Converts the argument list into the call paramters for a Rust function. + /// e.g. this would generate something like `a, b, c` + pub fn as_call_param_rust(&self) -> String { + self.args + .iter() + .map(|arg| arg.name.clone()) + .collect::>() + .join(", ") + } + + /// Creates a line that initializes this argument for C code. + /// 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) + ) + }) + .collect::>() + .join("\n ") + } + + /// Creates a line that initializes this argument for Rust code. + /// 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) + ) + } + }) + .collect::>() + .join("\n ") + } + + pub fn iter(&self) -> std::slice::Iter<'_, Argument> { + 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 new file mode 100644 index 0000000000..499cf7612c --- /dev/null +++ b/library/stdarch/crates/intrinsic-test/src/intrinsic.rs @@ -0,0 +1,112 @@ +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)] +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 { + (0..self.results.num_lanes()) + .map(|idx| -> std::string::String { + format!( + "{cast}{lane_fn}(__return_value, {lane})", + cast = self.results.c_promotion(), + lane_fn = self.results.get_lane_function(), + lane = idx + ) + }) + .collect::>() + .join(r#" << ", " << "#) + } else { + format!( + "{promote}cast<{cast}>(__return_value)", + cast = match self.results.kind() { + TypeKind::Float if self.results.inner_size() == 32 => "float".to_string(), + TypeKind::Float if self.results.inner_size() == 64 => "double".to_string(), + TypeKind::Int => format!("int{}_t", self.results.inner_size()), + TypeKind::UInt => format!("uint{}_t", self.results.inner_size()), + TypeKind::Poly => format!("poly{}_t", self.results.inner_size()), + ty => todo!("print_result_c - Unknown type: {:#?}", ty), + }, + promote = self.results.c_promotion(), + ) + }; + + format!( + r#"std::cout << "Result {idx}: {ty}" << std::fixed << std::setprecision(150) << {lanes} << "{close}" << std::endl;"#, + ty = if self.results.is_simd() { + format!("{}(", self.results.c_type()) + } else { + String::from("") + }, + close = if self.results.is_simd() { ")" } else { "" }, + lanes = lanes, + idx = index, + ) + } + + pub fn generate_pass_rust(&self, index: usize) -> String { + format!( + r#" + unsafe {{ + {initialized_args} + let res = {intrinsic_call}({args}); + println!("Result {idx}: {{:.150?}}", res); + }}"#, + initialized_args = self.arguments.init_random_values_rust(index), + intrinsic_call = self.name, + args = self.arguments.as_call_param_rust(), + idx = index, + ) + } + + pub fn generate_pass_c(&self, index: usize) -> String { + format!( + r#" {{ + {initialized_args} + auto __return_value = {intrinsic_call}({args}); + {print_result} + }}"#, + 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) + ) + } +} + +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 new file mode 100644 index 0000000000..c5ff2b5487 --- /dev/null +++ b/library/stdarch/crates/intrinsic-test/src/main.rs @@ -0,0 +1,400 @@ +#[macro_use] +extern crate lazy_static; +#[macro_use] +extern crate log; + +use std::fs::File; +use std::io::Write; +use std::process::Command; + +use clap::{App, Arg}; +use intrinsic::Intrinsic; +use rayon::prelude::*; +use types::TypeKind; + +mod argument; +mod intrinsic; +mod types; +mod values; + +#[derive(Debug, PartialEq)] +pub enum Language { + Rust, + C, +} + +fn generate_c_program(header_files: &[&str], intrinsic: &Intrinsic) -> String { + format!( + r#"{header_files} +#include +#include +#include +#include +template T1 cast(T2 x) {{ + static_assert(sizeof(T1) == sizeof(T2), "sizeof T1 and T2 must be the same"); + T1 ret = 0; + memcpy(&ret, &x, sizeof(T1)); + return ret; +}} +std::ostream& operator<<(std::ostream& os, poly128_t value) {{ + std::stringstream temp; + do {{ + int n = value % 10; + value /= 10; + temp << n; + }} while (value != 0); + std::string tempstr(temp.str()); + std::string res(tempstr.rbegin(), tempstr.rend()); + os << res; + return os; +}} +int main(int argc, char **argv) {{ +{passes} + return 0; +}}"#, + header_files = header_files + .iter() + .map(|header| format!("#include <{}>", header)) + .collect::>() + .join("\n"), + passes = (1..20) + .map(|idx| intrinsic.generate_pass_c(idx)) + .collect::>() + .join("\n"), + ) +} + +fn generate_rust_program(intrinsic: &Intrinsic) -> String { + format!( + r#"#![feature(simd_ffi)] +#![feature(link_llvm_intrinsics)] +#![feature(stdsimd)] +#![allow(overflowing_literals)] +use core_arch::arch::aarch64::*; + +fn main() {{ +{passes} +}} +"#, + passes = (1..20) + .map(|idx| intrinsic.generate_pass_rust(idx)) + .collect::>() + .join("\n"), + ) +} + +fn compile_c(c_filename: &str, intrinsic: &Intrinsic, compiler: &str) -> bool { + let flags = std::env::var("CPPFLAGS").unwrap_or("".into()); + + let output = Command::new("sh") + .arg("-c") + .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", + filename = c_filename, + intrinsic = intrinsic.name, + cpp = compiler, + cppflags = flags, + )) + .output(); + if let Ok(output) = output { + if output.status.success() { + true + } else { + let stderr = std::str::from_utf8(&output.stderr).unwrap_or(""); + if stderr.contains("error: use of undeclared identifier") { + warn!("Skipping intrinsic due to no support: {}", intrinsic.name); + true + } else { + error!( + "Failed to compile code for intrinsic: {}\n\nstdout:\n{}\n\nstderr:\n{}", + intrinsic.name, + std::str::from_utf8(&output.stdout).unwrap_or(""), + std::str::from_utf8(&output.stderr).unwrap_or("") + ); + false + } + } + } else { + error!("Command failed: {:#?}", output); + false + } +} + +fn build_c(intrinsics: &Vec, compiler: &str) -> bool { + let _ = std::fs::create_dir("c_programs"); + intrinsics + .par_iter() + .map(|i| { + let c_filename = format!(r#"c_programs/{}.cpp"#, i.name); + let mut file = File::create(&c_filename).unwrap(); + + let c_code = generate_c_program(&["arm_neon.h", "arm_acle.h"], &i); + file.write_all(c_code.into_bytes().as_slice()).unwrap(); + compile_c(&c_filename, &i, compiler) + }) + .find_any(|x| !x) + .is_none() +} + +fn build_rust(intrinsics: &Vec, toolchain: &str) -> bool { + intrinsics.iter().for_each(|i| { + let rust_dir = format!(r#"rust_programs/{}"#, i.name); + let _ = std::fs::create_dir_all(&rust_dir); + let rust_filename = format!(r#"{}/main.rs"#, rust_dir); + let mut file = File::create(&rust_filename).unwrap(); + + let c_code = generate_rust_program(&i); + file.write_all(c_code.into_bytes().as_slice()).unwrap(); + }); + + let mut cargo = File::create("rust_programs/Cargo.toml").unwrap(); + cargo + .write_all( + format!( + r#"[package] +name = "intrinsic-test" +version = "{version}" +authors = ["{authors}"] +edition = "2018" +[workspace] +[dependencies] +core_arch = {{ path = "../crates/core_arch" }} +{binaries}"#, + version = env!("CARGO_PKG_VERSION"), + authors = env!("CARGO_PKG_AUTHORS"), + binaries = intrinsics + .iter() + .map(|i| { + format!( + r#"[[bin]] +name = "{intrinsic}" +path = "{intrinsic}/main.rs""#, + intrinsic = i.name + ) + }) + .collect::>() + .join("\n") + ) + .into_bytes() + .as_slice(), + ) + .unwrap(); + + let output = Command::new("sh") + .current_dir("rust_programs") + .arg("-c") + .arg(format!( + "cargo {toolchain} build --release --target {target}", + toolchain = toolchain, + target = "aarch64-unknown-linux-gnu", + )) + .output(); + if let Ok(output) = output { + if output.status.success() { + true + } else { + error!( + "Failed to compile code for intrinsics\n\nstdout:\n{}\n\nstderr:\n{}", + std::str::from_utf8(&output.stdout).unwrap_or(""), + std::str::from_utf8(&output.stderr).unwrap_or("") + ); + false + } + } else { + error!("Command failed: {:#?}", output); + false + } +} + +fn main() { + pretty_env_logger::init(); + + let matches = App::new("Intrinsic test tool") + .about("Generates Rust and C programs for intrinsics and compares the output") + .arg( + Arg::with_name("INPUT") + .help("The input file containing the intrinsics") + .required(true) + .index(1), + ) + .arg( + Arg::with_name("TOOLCHAIN") + .takes_value(true) + .long("toolchain") + .help("The rust toolchain to use for building the rust code"), + ) + .arg( + Arg::with_name("CPPCOMPILER") + .takes_value(true) + .default_value("clang++") + .long("cppcompiler") + .help("The C++ compiler to use for compiling the c++ code"), + ) + .arg( + Arg::with_name("RUNNER") + .takes_value(true) + .long("runner") + .help("Run the C programs under emulation with this command"), + ) + .get_matches(); + + let filename = matches.value_of("INPUT").unwrap(); + let toolchain = matches + .value_of("TOOLCHAIN") + .map_or("".into(), |t| format!("+{}", t)); + + 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) + // 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() + .find(|a| a.ty.kind() == TypeKind::BFloat) + .is_none() + }) + .filter(|i| { + i.arguments + .iter() + .find(|a| a.ty.kind() == TypeKind::Float && a.ty.inner_size() == 16) + .is_none() + }) + // 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())) + .collect::>(); + intrinsics.dedup(); + + if !build_c(&intrinsics, cpp_compiler) { + std::process::exit(2); + } + + if !build_rust(&intrinsics, &toolchain) { + std::process::exit(3); + } + + if !compare_outputs(&intrinsics, &toolchain, &c_runner) { + std::process::exit(1) + } +} + +enum FailureReason { + RunC(String), + RunRust(String), + Difference(String, String, String), +} + +fn compare_outputs(intrinsics: &Vec, toolchain: &str, runner: &str) -> bool { + let intrinsics = intrinsics + .par_iter() + .filter_map(|intrinsic| { + let c = Command::new("sh") + .arg("-c") + .arg(format!( + "{runner} ./c_programs/{intrinsic}", + runner = runner, + intrinsic = intrinsic.name, + )) + .output(); + let rust = Command::new("sh") + .current_dir("rust_programs") + .arg("-c") + .arg(format!( + "cargo {toolchain} run --release --target {target} --bin {intrinsic}", + intrinsic = intrinsic.name, + toolchain = toolchain, + target = "aarch64-unknown-linux-gnu", + )) + .output(); + + let (c, rust) = match (c, rust) { + (Ok(c), Ok(rust)) => (c, rust), + a => panic!("{:#?}", a), + }; + + if !c.status.success() { + error!("Failed to run C program for intrinsic {}", intrinsic.name); + return Some(FailureReason::RunC(intrinsic.name.clone())); + } + + if !rust.status.success() { + error!( + "Failed to run rust program for intrinsic {}", + intrinsic.name + ); + return Some(FailureReason::RunRust(intrinsic.name.clone())); + } + + info!("Comparing intrinsic: {}", intrinsic.name); + + let c = std::str::from_utf8(&c.stdout) + .unwrap() + .to_lowercase() + .replace("-nan", "nan"); + let rust = std::str::from_utf8(&rust.stdout) + .unwrap() + .to_lowercase() + .replace("-nan", "nan"); + + if c == rust { + None + } else { + Some(FailureReason::Difference(intrinsic.name.clone(), c, rust)) + } + }) + .collect::>(); + + intrinsics.iter().for_each(|reason| match reason { + FailureReason::Difference(intrinsic, c, rust) => { + println!("Difference for intrinsic: {}", intrinsic); + let diff = diff::lines(c, rust); + diff.iter().for_each(|diff| match diff { + diff::Result::Left(c) => println!("C: {}", c), + diff::Result::Right(rust) => println!("Rust: {}", rust), + diff::Result::Both(_, _) => (), + }); + println!("****************************************************************"); + } + FailureReason::RunC(intrinsic) => { + println!("Failed to run C program for intrinsic {}", intrinsic) + } + FailureReason::RunRust(intrinsic) => { + println!("Failed to run rust program for intrinsic {}", intrinsic) + } + }); + println!("{} differences found", intrinsics.len()); + intrinsics.is_empty() +} diff --git a/library/stdarch/crates/intrinsic-test/src/types.rs b/library/stdarch/crates/intrinsic-test/src/types.rs new file mode 100644 index 0000000000..cc5b68973b --- /dev/null +++ b/library/stdarch/crates/intrinsic-test/src/types.rs @@ -0,0 +1,483 @@ +use regex::Regex; +use serde::{Deserialize, Deserializer}; +use std::fmt; +use std::str::FromStr; + +use crate::values::values_for_pass; +use crate::Language; + +#[derive(Debug, PartialEq, Copy, Clone)] +pub enum TypeKind { + BFloat, + Float, + Int, + UInt, + Poly, + Void, +} + +impl FromStr for TypeKind { + type Err = String; + + fn from_str(s: &str) -> Result { + match s { + "bfloat" => Ok(Self::BFloat), + "float" => Ok(Self::Float), + "int" => Ok(Self::Int), + "poly" => Ok(Self::Poly), + "uint" | "unsigned" => Ok(Self::UInt), + "void" => Ok(Self::Void), + _ => Err(format!("Impossible to parse argument kind {}", s)), + } + } +} + +impl fmt::Display for TypeKind { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!( + f, + "{}", + match self { + Self::BFloat => "bfloat", + Self::Float => "float", + Self::Int => "int", + Self::UInt => "uint", + Self::Poly => "poly", + Self::Void => "void", + } + ) + } +} + +impl TypeKind { + /// Gets the type part of a c typedef for a type that's in the form of {type}{size}_t. + pub fn c_prefix(&self) -> &str { + match self { + Self::Float => "float", + Self::Int => "int", + Self::UInt => "uint", + Self::Poly => "poly", + _ => unreachable!("Not used: {:#?}", self), + } + } + + /// Gets the rust prefix for the type kind i.e. i, u, f. + pub fn rust_prefix(&self) -> &str { + match self { + Self::Float => "f", + Self::Int => "i", + Self::UInt => "u", + Self::Poly => "u", + _ => unreachable!("Unused type kind: {:#?}", self), + } + } +} + +#[derive(Debug, PartialEq, Clone)] +pub enum IntrinsicType { + Ptr { + constant: bool, + child: Box, + }, + Type { + constant: bool, + kind: TypeKind, + /// The bit length of this type (e.g. 32 for u32). + bit_len: Option, + + /// Length of the SIMD vector (i.e. 4 for uint32x4_t), A value of `None` + /// means this is not a simd type. A `None` can be assumed to be 1, + /// although in some places a distinction is needed between `u64` and + /// `uint64x1_t` this signals that. + simd_len: Option, + + /// The number of rows for SIMD matrices (i.e. 2 for uint8x8x2_t). + /// A value of `None` represents a type that does not contain any + /// rows encoded in the type (e.g. uint8x8_t). + /// A value of `None` can be assumed to be 1 though. + vec_len: Option, + }, +} + +impl IntrinsicType { + /// Get the TypeKind for this type, recursing into pointers. + pub fn kind(&self) -> TypeKind { + match *self { + IntrinsicType::Ptr { ref child, .. } => child.kind(), + IntrinsicType::Type { kind, .. } => kind, + } + } + + /// Get the size of a single element inside this type, recursing into + /// pointers, i.e. a pointer to a u16 would be 16 rather than the size + /// of a pointer. + pub fn inner_size(&self) -> u32 { + match *self { + IntrinsicType::Ptr { ref child, .. } => child.inner_size(), + IntrinsicType::Type { + bit_len: Some(bl), .. + } => bl, + _ => unreachable!(""), + } + } + + pub fn num_lanes(&self) -> u32 { + match *self { + IntrinsicType::Ptr { ref child, .. } => child.num_lanes(), + IntrinsicType::Type { + simd_len: Some(sl), .. + } => sl, + _ => 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 { + match *self { + IntrinsicType::Ptr { ref child, .. } => child.is_simd(), + IntrinsicType::Type { + simd_len: None, + vec_len: None, + .. + } => false, + _ => true, + } + } + + pub fn is_ptr(&self) -> bool { + match *self { + IntrinsicType::Ptr { .. } => true, + IntrinsicType::Type { .. } => false, + } + } + + 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!( + "{prefix}{bits}_t", + prefix = self.kind().c_prefix(), + bits = self.inner_size() + ) + } + + fn rust_scalar_type(&self) -> String { + format!( + "{prefix}{bits}", + prefix = self.kind().rust_prefix(), + bits = self.inner_size() + ) + } + + /// Gets a string containing the typename for this type in C format. + pub fn c_type(&self) -> String { + match self { + IntrinsicType::Ptr { child, .. } => child.c_type(), + IntrinsicType::Type { + constant, + kind, + bit_len: Some(bit_len), + simd_len: None, + vec_len: None, + .. + } => format!( + "{}{}{}_t", + if *constant { "const " } else { "" }, + kind.c_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, + /// which means value of 0 will be printed as a null byte. + pub fn c_promotion(&self) -> &str { + match *self { + IntrinsicType::Type { + kind, + bit_len: Some(bit_len), + .. + } if bit_len == 8 => match kind { + TypeKind::Int => "(int)", + TypeKind::UInt => "(unsigned int)", + TypeKind::Poly => "(unsigned int)", + _ => "", + }, + _ => "", + } + } + + /// Generates a comma list of values that can be used to initialize an + /// argument for the intrinsic call. + /// This is determistic based on the pass number. + /// + /// * `pass`: The pass index, i.e. the iteration index for the call to an intrinsic + /// + /// Returns a string such as + /// * `0x1, 0x7F, 0xFF` if `language` is `Language::C` + /// * `0x1 as _, 0x7F as _, 0xFF as _` if `language` is `Language::Rust` + pub fn populate_random(&self, pass: usize, language: &Language) -> String { + match self { + IntrinsicType::Ptr { child, .. } => child.populate_random(pass, language), + IntrinsicType::Type { + bit_len: Some(bit_len), + kind, + simd_len, + vec_len, + .. + } if kind == &TypeKind::Int || kind == &TypeKind::UInt || kind == &TypeKind::Poly => (0 + ..(simd_len.unwrap_or(1) * vec_len.unwrap_or(1))) + .map(|i| { + format!( + "{}{}", + values_for_pass(*bit_len, i, pass), + match language { + &Language::Rust => format!(" as {ty} ", ty = self.rust_scalar_type()), + &Language::C => String::from(""), + } + ) + }) + .collect::>() + .join(","), + IntrinsicType::Type { + kind: TypeKind::Float, + bit_len: Some(32), + simd_len, + vec_len, + .. + } => (0..(simd_len.unwrap_or(1) * vec_len.unwrap_or(1))) + .map(|i| { + format!( + "{}({})", + match language { + &Language::Rust => "f32::from_bits", + &Language::C => "cast", + }, + values_for_pass(32, i, pass), + ) + }) + .collect::>() + .join(","), + IntrinsicType::Type { + kind: TypeKind::Float, + bit_len: Some(64), + simd_len, + vec_len, + .. + } => (0..(simd_len.unwrap_or(1) * vec_len.unwrap_or(1))) + .map(|i| { + format!( + "{}({}{})", + match language { + &Language::Rust => "f64::from_bits", + &Language::C => "cast", + }, + values_for_pass(64, i, pass), + match language { + &Language::Rust => " as u64", + &Language::C => "", + } + ) + }) + .collect::>() + .join(","), + _ => unreachable!("populate random: {:#?}", self), + } + } + + /// Determines the load function for this type. + #[allow(unused)] + pub fn get_load_function(&self) -> String { + match self { + IntrinsicType::Ptr { child, .. } => child.get_load_function(), + IntrinsicType::Type { + kind: k, + bit_len: Some(bl), + simd_len, + vec_len, + .. + } => { + let quad = if (simd_len.unwrap_or(1) * bl) > 64 { + "q" + } else { + "" + }; + format!( + "vld{len}{quad}_{type}{size}", + type = match k { + TypeKind::UInt => "u", + TypeKind::Int => "s", + TypeKind::Float => "f", + TypeKind::Poly => "p", + x => todo!("get_load_function TypeKind: {:#?}", x), + }, + size = bl, + quad = quad, + len = vec_len.unwrap_or(1), + ) + } + _ => todo!("get_load_function IntrinsicType: {:#?}", self), + } + } + + /// Determines the get lane function for this type. + pub fn get_lane_function(&self) -> String { + match self { + IntrinsicType::Ptr { child, .. } => child.get_lane_function(), + IntrinsicType::Type { + kind: k, + bit_len: Some(bl), + simd_len, + .. + } => { + let quad = if (simd_len.unwrap_or(1) * bl) > 64 { + "q" + } else { + "" + }; + format!( + "vget{quad}_lane_{type}{size}", + type = match k { + TypeKind::UInt => "u", + TypeKind::Int => "s", + TypeKind::Float => "f", + TypeKind::Poly => "p", + x => todo!("get_load_function TypeKind: {:#?}", x), + }, + size = bl, + quad = quad, + ) + } + _ => todo!("get_lane_function IntrinsicType: {:#?}", self), + } + } +} + +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/intrinsic-test/src/values.rs b/library/stdarch/crates/intrinsic-test/src/values.rs new file mode 100644 index 0000000000..4565edca09 --- /dev/null +++ b/library/stdarch/crates/intrinsic-test/src/values.rs @@ -0,0 +1,126 @@ +/// Gets a hex constant value for a single lane in in a determistic way +/// * `bits`: The number of bits for the type, only 8, 16, 32, 64 are valid values +/// * `simd`: The index of the simd lane we are generating for +/// * `pass`: The index of the pass we are generating the values for +pub fn values_for_pass(bits: u32, simd: u32, pass: usize) -> String { + let index = pass + (simd as usize); + + if bits == 8 { + format!("{:#X}", VALUES_8[index % VALUES_8.len()]) + } else if bits == 16 { + format!("{:#X}", VALUES_16[index % VALUES_16.len()]) + } else if bits == 32 { + format!("{:#X}", VALUES_32[index % VALUES_32.len()]) + } else if bits == 64 { + format!("{:#X}", VALUES_64[index % VALUES_64.len()]) + } else { + panic!("Unknown size: {}", bits); + } +} + +pub const VALUES_8: &[u8] = &[ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0xf0, 0x80, 0x3b, 0xff, +]; + +pub const VALUES_16: &[u16] = &[ + 0x0000, // 0.0 + 0x0400, // The smallest normal value. + 0x37ff, // The value just below 0.5. + 0x3800, // 0.5 + 0x3801, // The value just above 0.5. + 0x3bff, // The value just below 1.0. + 0x3c00, // 1.0 + 0x3c01, // The value just above 1.0. + 0x3e00, // 1.5 + 0x4900, // 10 + 0x7bff, // The largest finite value. + 0x7c00, // Infinity. + // NaNs. + // - Quiet NaNs + 0x7f23, 0x7e00, // - Signalling NaNs + 0x7d23, 0x7c01, // Subnormals. + // - A recognisable bit pattern. + 0x0012, // - The largest subnormal value. + 0x03ff, // - The smallest subnormal value. + 0x0001, // The same values again, but negated. + 0x8000, 0x8400, 0xb7ff, 0xb800, 0xb801, 0xbbff, 0xbc00, 0xbc01, 0xbe00, 0xc900, 0xfbff, 0xfc00, + 0xff23, 0xfe00, 0xfd23, 0xfc01, 0x8012, 0x83ff, 0x8001, +]; + +pub const VALUES_32: &[u32] = &[ + // Simple values. + 0x00000000, // 0.0 + 0x00800000, // The smallest normal value. + 0x3effffff, // The value just below 0.5. + 0x3f000000, // 0.5 + 0x3f000001, // The value just above 0.5. + 0x3f7fffff, // The value just below 1.0. + 0x3f800000, // 1.0 + 0x3f800001, // The value just above 1.0. + 0x3fc00000, // 1.5 + 0x41200000, // 10 + 0x7f8fffff, // The largest finite value. + 0x7f800000, // Infinity. + // NaNs. + // - Quiet NaNs + 0x7fd23456, 0x7fc00000, // - Signalling NaNs + 0x7f923456, 0x7f800001, // Subnormals. + // - A recognisable bit pattern. + 0x00123456, // - The largest subnormal value. + 0x007fffff, // - The smallest subnormal value. + 0x00000001, // The same values again, but negated. + 0x80000000, 0x80800000, 0xbeffffff, 0xbf000000, 0xbf000001, 0xbf7fffff, 0xbf800000, 0xbf800001, + 0xbfc00000, 0xc1200000, 0xff8fffff, 0xff800000, 0xffd23456, 0xffc00000, 0xff923456, 0xff800001, + 0x80123456, 0x807fffff, 0x80000001, +]; + +pub const VALUES_64: &[u64] = &[ + // Simple values. + 0x0000000000000000, // 0.0 + 0x0010000000000000, // The smallest normal value. + 0x3fdfffffffffffff, // The value just below 0.5. + 0x3fe0000000000000, // 0.5 + 0x3fe0000000000001, // The value just above 0.5. + 0x3fefffffffffffff, // The value just below 1.0. + 0x3ff0000000000000, // 1.0 + 0x3ff0000000000001, // The value just above 1.0. + 0x3ff8000000000000, // 1.5 + 0x4024000000000000, // 10 + 0x7fefffffffffffff, // The largest finite value. + 0x7ff0000000000000, // Infinity. + // NaNs. + // - Quiet NaNs + 0x7ff923456789abcd, + 0x7ff8000000000000, + // - Signalling NaNs + 0x7ff123456789abcd, + 0x7ff0000000000000, + // Subnormals. + // - A recognisable bit pattern. + 0x000123456789abcd, + // - The largest subnormal value. + 0x000fffffffffffff, + // - The smallest subnormal value. + 0x0000000000000001, + // The same values again, but negated. + 0x8000000000000000, + 0x8010000000000000, + 0xbfdfffffffffffff, + 0xbfe0000000000000, + 0xbfe0000000000001, + 0xbfefffffffffffff, + 0xbff0000000000000, + 0xbff0000000000001, + 0xbff8000000000000, + 0xc024000000000000, + 0xffefffffffffffff, + 0xfff0000000000000, + 0xfff923456789abcd, + 0xfff8000000000000, + 0xfff123456789abcd, + 0xfff0000000000000, + 0x800123456789abcd, + 0x800fffffffffffff, + 0x8000000000000001, +]; diff --git a/library/stdarch/crates/std_detect/src/detect/os/linux/auxvec.rs b/library/stdarch/crates/std_detect/src/detect/os/linux/auxvec.rs index 077fc9e4c8..76908db314 100644 --- a/library/stdarch/crates/std_detect/src/detect/os/linux/auxvec.rs +++ b/library/stdarch/crates/std_detect/src/detect/os/linux/auxvec.rs @@ -1,5 +1,5 @@ //! Parses ELF auxiliary vectors. -#![cfg_attr(not(target_arch = "aarch64"), allow(dead_code))] +#![allow(dead_code)] pub(crate) const AT_NULL: usize = 0; @@ -89,11 +89,10 @@ pub(crate) fn auxv() -> Result { #[cfg(not(feature = "std_detect_dlsym_getauxval"))] { - let hwcap = unsafe { libc::getauxval(AT_HWCAP as libc::c_ulong) as usize }; - // Targets with only AT_HWCAP: #[cfg(any(target_arch = "aarch64", target_arch = "mips", target_arch = "mips64"))] { + let hwcap = unsafe { libc::getauxval(AT_HWCAP as libc::c_ulong) as usize }; if hwcap != 0 { return Ok(AuxVec { hwcap }); } @@ -106,6 +105,7 @@ pub(crate) fn auxv() -> Result { target_arch = "powerpc64" ))] { + let hwcap = unsafe { libc::getauxval(AT_HWCAP as libc::c_ulong) as usize }; let hwcap2 = unsafe { libc::getauxval(AT_HWCAP2 as libc::c_ulong) as usize }; if hwcap != 0 && hwcap2 != 0 { return Ok(AuxVec { hwcap, hwcap2 }); diff --git a/library/stdarch/crates/stdarch-gen/neon.spec b/library/stdarch/crates/stdarch-gen/neon.spec index 5850be482b..a22dfe3dd4 100644 --- a/library/stdarch/crates/stdarch-gen/neon.spec +++ b/library/stdarch/crates/stdarch-gen/neon.spec @@ -955,6 +955,7 @@ multi_fn = static_assert-N-1-bits a = 1, 2, 3, 4 n = 2 validate 0.25, 0.5, 0.75, 1. +arm-aarch64-separate aarch64 = scvtf link-aarch64 = vcvtfxs2fp._EXT2_._EXT_ @@ -971,6 +972,7 @@ link-aarch64 = vcvtfxs2fp._EXT2_._EXT_ arm = vcvt link-arm = vcvtfxs2fp._EXT2_._EXT_ const-arm = N:i32 + generate int32x2_t:float32x2_t, int32x4_t:float32x4_t aarch64 = ucvtf @@ -988,6 +990,7 @@ multi_fn = static_assert-N-1-bits a = 0.25, 0.5, 0.75, 1. n = 2 validate 1, 2, 3, 4 +arm-aarch64-separate aarch64 = fcvtzs link-aarch64 = vcvtfp2fxs._EXT2_._EXT_ @@ -2033,6 +2036,320 @@ aarch64 = sqadd link-aarch64 = sqadd._EXT_ generate i32, i64 +/// Load multiple single-element structures to one, two, three, or four registers +name = vld1 +out-suffix +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 +load_fn + +aarch64 = ld1 +link-aarch64 = ld1x2._EXT2_ +arm = vld1 +link-arm = vld1x2._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 + +link-aarch64 = ld1x3._EXT2_ +link-arm = vld1x3._EXT2_ +generate *const i8:int8x8x3_t, *const i16:int16x4x3_t, *const i32:int32x2x3_t, *const i64:int64x1x3_t +generate *const i8:int8x16x3_t, *const i16:int16x8x3_t, *const i32:int32x4x3_t, *const i64:int64x2x3_t + +link-aarch64 = ld1x4._EXT2_ +link-arm = vld1x4._EXT2_ +generate *const i8:int8x8x4_t, *const i16:int16x4x4_t, *const i32:int32x2x4_t, *const i64:int64x1x4_t +generate *const i8:int8x16x4_t, *const i16:int16x8x4_t, *const i32:int32x4x4_t, *const i64:int64x2x4_t + +/// Load multiple single-element structures to one, two, three, or four registers +name = vld1 +out-suffix +multi_fn = transmute, {vld1-outsigned-noext, transmute(a)} +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 + +load_fn +aarch64 = ld1 +arm = vld1 +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 u8:uint8x8x3_t, *const u16:uint16x4x3_t, *const u32:uint32x2x3_t, *const u64:uint64x1x3_t +generate *const u8:uint8x16x3_t, *const u16:uint16x8x3_t, *const u32:uint32x4x3_t, *const u64:uint64x2x3_t +generate *const u8:uint8x8x4_t, *const u16:uint16x4x4_t, *const u32:uint32x2x4_t, *const u64:uint64x1x4_t +generate *const u8:uint8x16x4_t, *const u16:uint16x8x4_t, *const u32:uint32x4x4_t, *const u64:uint64x2x4_t +generate *const p8:poly8x8x2_t, *const p8:poly8x8x3_t, *const p8:poly8x8x4_t +generate *const p8:poly8x16x2_t, *const p8:poly8x16x3_t, *const p8:poly8x16x4_t +generate *const p16:poly16x4x2_t, *const p16:poly16x4x3_t, *const p16:poly16x4x4_t +generate *const p16:poly16x8x2_t, *const p16:poly16x8x3_t, *const p16:poly16x8x4_t +target = aes +generate *const p64:poly64x1x2_t +arm = ldr +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 +a = 0., 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14., 15., 16. +validate 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14., 15., 16. +load_fn + +aarch64 = ld1 +link-aarch64 = ld1x2._EXT2_ +generate *const f64:float64x1x2_t, *const f64:float64x2x2_t + +link-aarch64 = ld1x3._EXT2_ +generate *const f64:float64x1x3_t, *const f64:float64x2x3_t + +link-aarch64 = ld1x4._EXT2_ +generate *const f64:float64x1x4_t, *const f64:float64x2x4_t + +arm = vld1 +link-aarch64 = ld1x2._EXT2_ +link-arm = vld1x2._EXT2_ +generate *const f32:float32x2x2_t, *const f32:float32x4x2_t + +link-aarch64 = ld1x3._EXT2_ +link-arm = vld1x3._EXT2_ +generate *const f32:float32x2x3_t, *const f32:float32x4x3_t + +link-aarch64 = ld1x4._EXT2_ +link-arm = vld1x4._EXT2_ +generate *const f32:float32x2x4_t, *const f32:float32x4x4_t + +/// Load multiple 2-element structures to two registers +name = vld2 +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 + +aarch64 = ld2 +link-aarch64 = ld2._EXTv2_ +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 + +/// Load multiple 2-element structures to two registers +name = vld2 +out-nox +multi_fn = transmute, {vld2-outsignednox-noext, transmute(a)} +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 + +aarch64 = ld2 +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 + +/// Load multiple 2-element structures to two registers +name = vld2 +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 + +aarch64 = ld2 +link-aarch64 = ld2._EXTv2_ +//generate *const f64:float64x1x2_t, *const f64:float64x2x2_t + +arm = vld2 +link-arm = vld2._EXTpi82_ +//generate *const f32:float32x2x2_t, *const f32:float32x4x2_t + +/// Load single 2-element structure and replicate to all lanes of two registers +name = vld2 +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 = 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 + +/// Load single 2-element structure and replicate to all lanes of two registers +name = vld2 +out-dup-nox +multi_fn = transmute, {vld2-outsigneddupnox-noext, transmute(a)} +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 = 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 + +/// Load single 2-element structure and replicate to all lanes of two registers +name = vld2 +out-dup-nox +a = 0., 1., 1., 2., 3., 1., 4., 3., 5. +validate 1., 1., 1., 1., 1., 1., 1., 1. +load_fn + +aarch64 = ld2r +link-aarch64 = ld2r._EXT2_ +//generate *const f64:float64x1x2_t, *const f64:float64x2x2_t + +arm = vld2dup +link-arm = vld2dup._EXTpi82_ +//generate *const f32:float32x2x2_t, *const f32:float32x4x2_t + +/// Load multiple 2-element structures to two registers +name = vld2 +out-lane-nox +multi_fn = static_assert_imm-in_exp_len-LANE +constn = LANE +a = 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 +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 +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 +const-aarch64 = LANE +link-aarch64 = ld2lane._EXTpi82_ +//generate *const i64:int64x1x2_t:int64x1x2_t, *const i64:int64x2x2_t:int64x2x2_t + +arm = vld2lane +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 + +/// Load multiple 2-element structures to two registers +name = vld2 +out-lane-nox +multi_fn = static_assert_imm-in_exp_len-LANE +multi_fn = transmute, {vld2-outsignedlanenox-::, transmute(a), transmute(b)} +constn = LANE +a = 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 +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 +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 +const-aarch64 = LANE + +target = aes +//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 + +arm = vld2lane +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 + +/// Load multiple 2-element structures to two registers +name = vld2 +out-lane-nox +multi_fn = static_assert_imm-in_exp_len-LANE +constn = LANE +a = 0., 1., 2., 3., 4., 5., 6., 7., 8. +b = 0., 2., 2., 14., 2., 16., 17., 18. +n = 0 +validate 1., 2., 2., 14., 2., 16., 17., 18. +load_fn +arm-aarch64-separate + +aarch64 = ld2lane +const-aarch64 = LANE +link-aarch64 = ld2lane._EXTpi82_ +//generate *const f64:float64x1x2_t:float64x1x2_t, *const f64:float64x2x2_t:float64x2x2_t + +arm = vld2lane +const-arm = LANE +link-arm = vld2lane._EXTpi82_ +//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 +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 +multi_fn = vst1-signed-noext, transmute(a), transmute(b) +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 +aarch64 = st1 +arm = vst1 +generate *mut u8:uint8x8x2_t:void, *mut u16:uint16x4x2_t:void, *mut u32:uint32x2x2_t:void, *mut u64:uint64x1x2_t:void +generate *mut u8:uint8x16x2_t:void, *mut u16:uint16x8x2_t:void, *mut u32:uint32x4x2_t:void, *mut u64:uint64x2x2_t:void +generate *mut u8:uint8x8x3_t:void, *mut u16:uint16x4x3_t:void, *mut u32:uint32x2x3_t:void, *mut u64:uint64x1x3_t:void +generate *mut u8:uint8x16x3_t:void, *mut u16:uint16x8x3_t:void, *mut u32:uint32x4x3_t:void, *mut u64:uint64x2x3_t:void +generate *mut u8:uint8x8x4_t:void, *mut u16:uint16x4x4_t:void, *mut u32:uint32x2x4_t:void, *mut u64:uint64x1x4_t:void +generate *mut u8:uint8x16x4_t:void, *mut u16:uint16x8x4_t:void, *mut u32:uint32x4x4_t:void, *mut u64:uint64x2x4_t:void +generate *mut p8:poly8x8x2_t:void, *mut p8:poly8x8x3_t:void, *mut p8:poly8x8x4_t:void +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 + +/// Store multiple single-element structures to 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. +validate 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14., 15., 16. +store_fn +arm-aarch64-separate + +aarch64 = st1 +link-aarch64 = st1x2._EXT3_ +generate *mut f64:float64x1x2_t:void, *mut f64:float64x2x2_t:void + +link-aarch64 = st1x3._EXT3_ +generate *mut f64:float64x1x3_t:void, *mut f64:float64x2x3_t:void + +link-aarch64 = st1x4._EXT3_ +generate *mut f64:float64x1x4_t:void, *mut f64:float64x2x4_t:void + +arm = vst1 +link-aarch64 = st1x2._EXT3_ +link-arm = vst1x2._EXTr3_ +generate *mut f32:float32x2x2_t:void, *mut f32:float32x4x2_t:void + +link-aarch64 = st1x3._EXT3_ +link-arm = vst1x3._EXTr3_ +generate *mut f32:float32x2x3_t:void, *mut f32:float32x4x3_t:void + +link-aarch64 = st1x4._EXT3_ +link-arm = vst1x4._EXTr3_ +generate *mut f32:float32x2x4_t:void, *mut f32:float32x4x4_t:void + /// Multiply name = vmul a = 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2 @@ -2277,8 +2594,8 @@ aarch64 = pmull generate poly64x2_t:poly64x2_t:p128 /// Vector long multiply with scalar -name = vmull -n-suffix +name = vmull_n +no-q multi_fn = vmull-in0-noext, a, {vdup-nin0-noext, b} a = 1, 2, 3, 4, 5, 6, 7, 8 b = 2 @@ -2416,7 +2733,7 @@ generate float64x1_t aarch64 = fmla generate float64x2_t -target = fp-armv8 +target = vfp4 arm = vfma link-arm = llvm.fma._EXT_ generate float*_t @@ -2424,7 +2741,7 @@ generate float*_t /// Floating-point fused Multiply-Add to accumulator(vector) name = vfma n-suffix -multi_fn = vfma-self-noext, a, b, {vdup-nself-noext, c} +multi_fn = vfma-self-noext, a, b, {vdup-nselfvfp4-noext, c} a = 2.0, 3.0, 4.0, 5.0 b = 6.0, 4.0, 7.0, 8.0 c = 8.0 @@ -2435,7 +2752,7 @@ generate float64x1_t:float64x1_t:f64:float64x1_t aarch64 = fmla generate float64x2_t:float64x2_t:f64:float64x2_t -target = fp-armv8 +target = vfp4 arm = vfma generate float32x2_t:float32x2_t:f32:float32x2_t, float32x4_t:float32x4_t:f32:float32x4_t @@ -2494,14 +2811,14 @@ generate float64x1_t aarch64 = fmls generate float64x2_t -target = fp-armv8 +target = vfp4 arm = vfms generate float*_t /// Floating-point fused Multiply-subtract to accumulator(vector) name = vfms n-suffix -multi_fn = vfms-self-noext, a, b, {vdup-nself-noext, c} +multi_fn = vfms-self-noext, a, b, {vdup-nselfvfp4-noext, c} a = 50.0, 35.0, 60.0, 69.0 b = 6.0, 4.0, 7.0, 8.0 c = 8.0 @@ -2512,7 +2829,7 @@ generate float64x1_t:float64x1_t:f64:float64x1_t aarch64 = fmls generate float64x2_t:float64x2_t:f64:float64x2_t -target = fp-armv8 +target = vfp4 arm = vfms generate float32x2_t:float32x2_t:f32:float32x2_t, float32x4_t:float32x4_t:f32:float32x4_t @@ -3416,7 +3733,7 @@ generate int16x4_t:i16:int16x4_t, int32x2_t:i32:int32x2_t /// Vector saturating doubling multiply high with scalar name = vqdmulhq_n -out-suffix +no-q multi_fn = vdupq_n-in_ntt-noext, b:out_t, b multi_fn = vqdmulh-out-noext, a, b a = MAX, MAX, MAX, MAX, MAX, MAX, MAX, MAX @@ -3794,6 +4111,7 @@ const-aarch64 = N arm = vqrshrn link-arm = vqrshiftns._EXT2_ const-arm = -N as ttn +arm-aarch64-separate generate int16x8_t:int8x8_t, int32x4_t:int16x4_t, int64x2_t:int32x2_t /// Signed saturating rounded shift right narrow @@ -3840,6 +4158,7 @@ const-aarch64 = N arm = vqrshrn link-arm = vqrshiftnu._EXT2_ const-arm = -N as ttn +arm-aarch64-separate generate uint16x8_t:uint8x8_t, uint32x4_t:uint16x4_t, uint64x2_t:uint32x2_t /// Unsigned saturating rounded shift right narrow @@ -3886,6 +4205,7 @@ const-aarch64 = N arm = vqrshrun link-arm = vqrshiftnsu._EXT2_ const-arm = -N as ttn +arm-aarch64-separate generate int16x8_t:uint8x8_t, int32x4_t:uint16x4_t, int64x2_t:uint32x2_t /// Signed saturating rounded shift right unsigned narrow @@ -4031,6 +4351,7 @@ multi_fn = static_assert-N-1-halfbits a = 0, 4, 8, 12, 16, 20, 24, 28 n = 2 validate 0, 1, 2, 3, 4, 5, 6, 7 +arm-aarch64-separate aarch64 = sqshrn link-aarch64 = sqshrn._EXT2_ @@ -4077,6 +4398,7 @@ multi_fn = static_assert-N-1-halfbits a = 0, 4, 8, 12, 16, 20, 24, 28 n = 2 validate 0, 1, 2, 3, 4, 5, 6, 7 +arm-aarch64-separate aarch64 = uqshrn link-aarch64 = uqshrn._EXT2_ @@ -4123,6 +4445,7 @@ multi_fn = static_assert-N-1-halfbits a = 0, 4, 8, 12, 16, 20, 24, 28 n = 2 validate 0, 1, 2, 3, 4, 5, 6, 7 +arm-aarch64-separate aarch64 = sqshrun link-aarch64 = sqshrun._EXT2_ @@ -4202,11 +4525,11 @@ fn = transmute a = 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 validate 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 -aarch64 = str +aarch64 = nop generate poly64x1_t:int64x1_t, poly64x1_t:uint64x1_t, int64x1_t:poly64x1_t, uint64x1_t:poly64x1_t generate poly64x2_t:int64x2_t, poly64x2_t:uint64x2_t, int64x2_t:poly64x2_t, uint64x2_t:poly64x2_t -arm = str +arm = nop generate uint8x8_t:int8x8_t, poly8x8_t:int8x8_t, poly16x4_t:int16x4_t, uint16x4_t:int16x4_t, uint32x2_t:int32x2_t, uint64x1_t:int64x1_t generate uint8x16_t:int8x16_t, poly8x16_t:int8x16_t, poly16x8_t:int16x8_t, uint16x8_t:int16x8_t, uint32x4_t:int32x4_t, uint64x2_t:int64x2_t generate poly8x8_t:uint8x8_t, int8x8_t:uint8x8_t, poly16x4_t:uint16x4_t, int16x4_t:uint16x4_t, int32x2_t:uint32x2_t, int64x1_t:uint64x1_t @@ -4221,11 +4544,11 @@ fn = transmute 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 = str +aarch64 = nop generate poly64x1_t:int32x2_t, poly64x1_t:uint32x2_t generate poly64x2_t:int32x4_t, poly64x2_t:uint32x4_t -arm = str +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 generate poly16x4_t:uint8x8_t, int16x4_t:uint8x8_t, uint16x4_t:uint8x8_t, int32x2_t:uint16x4_t, uint32x2_t:uint16x4_t, int64x1_t:uint32x2_t, uint64x1_t:uint32x2_t @@ -4240,11 +4563,11 @@ fn = transmute 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 = str +aarch64 = nop generate int32x2_t:poly64x1_t, uint32x2_t:poly64x1_t generate int32x4_t:poly64x2_t, uint32x4_t:poly64x2_t -arm = str +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 generate poly8x8_t:uint16x4_t, int8x8_t:uint16x4_t, uint8x8_t:uint16x4_t, poly16x4_t:uint32x2_t, int16x4_t:uint32x2_t, uint16x4_t:uint32x2_t, int32x2_t:uint64x1_t, uint32x2_t:uint64x1_t @@ -4259,11 +4582,11 @@ fn = transmute a = 0, 1, 2, 3 validate 0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0 -aarch64 = str +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 = str +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 generate int32x2_t:uint8x8_t, uint32x2_t:uint8x8_t, int64x1_t:uint16x4_t, uint64x1_t:uint16x4_t @@ -4278,11 +4601,11 @@ fn = transmute a = 0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0 validate 0, 1, 2, 3 -aarch64 = str +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 = str +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 @@ -4295,11 +4618,11 @@ fn = transmute a = 0, 1 validate 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 -aarch64 = str +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 = str +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 @@ -4310,11 +4633,11 @@ fn = transmute a = 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 validate 0, 1 -aarch64 = str +aarch64 = nop 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 -arm = str +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 @@ -4325,7 +4648,7 @@ fn = transmute a = 0., 0., 0., 0., 0., 0., 0., 0. validate 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -aarch64 = str +aarch64 = nop generate float64x1_t:int8x8_t, float64x1_t:int16x4_t, float64x1_t:int32x2_t, float64x1_t:int64x1_t generate float64x2_t:int8x16_t, float64x2_t:int16x8_t, float64x2_t:int32x4_t, float64x2_t:int64x2_t generate float64x1_t:uint8x8_t, float64x1_t:uint16x4_t, float64x1_t:uint32x2_t, float64x1_t:uint64x1_t @@ -4333,7 +4656,7 @@ generate float64x2_t:uint8x16_t, float64x2_t:uint16x8_t, float64x2_t:uint32x4_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 -arm = str +arm = nop generate float32x2_t:int8x8_t, float32x2_t:int16x4_t, float32x2_t:int32x2_t, float32x2_t:int64x1_t generate float32x4_t:int8x16_t, float32x4_t:int16x8_t, float32x4_t:int32x4_t, float32x4_t:int64x2_t generate float32x2_t:uint8x8_t, float32x2_t:uint16x4_t, float32x2_t:uint32x2_t, float32x2_t:uint64x1_t @@ -4348,7 +4671,7 @@ fn = transmute a = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 validate 0., 0., 0., 0., 0., 0., 0., 0. -aarch64 = str +aarch64 = nop generate int8x8_t:float64x1_t, int16x4_t:float64x1_t, int32x2_t:float64x1_t, int64x1_t:float64x1_t generate int8x16_t:float64x2_t, int16x8_t:float64x2_t, int32x4_t:float64x2_t, int64x2_t:float64x2_t generate poly8x8_t:float64x1_t, uint16x4_t:float64x1_t, uint32x2_t:float64x1_t, uint64x1_t:float64x1_t @@ -4356,7 +4679,7 @@ generate poly8x16_t:float64x2_t, uint16x8_t:float64x2_t, uint32x4_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 -arm = str +arm = nop generate int8x8_t:float32x2_t, int16x4_t:float32x2_t, int32x2_t:float32x2_t, int64x1_t:float32x2_t generate int8x16_t:float32x4_t, int16x8_t:float32x4_t, int32x4_t:float32x4_t, int64x2_t:float32x4_t generate uint8x8_t:float32x2_t, uint16x4_t:float32x2_t, uint32x2_t:float32x2_t, uint64x1_t:float32x2_t @@ -4371,7 +4694,7 @@ fn = transmute a = 0., 0., 0., 0., 0., 0., 0., 0. validate 0., 0., 0., 0., 0., 0., 0., 0. -aarch64 = str +aarch64 = nop generate float32x2_t:float64x1_t, float64x1_t:float32x2_t generate float32x4_t:float64x2_t, float64x2_t:float32x4_t @@ -4467,6 +4790,7 @@ multi_fn = static_assert-N-1-halfbits 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 +arm-aarch64-separate aarch64 = rshrn link-aarch64 = rshrn._EXT2_ diff --git a/library/stdarch/crates/stdarch-gen/src/main.rs b/library/stdarch/crates/stdarch-gen/src/main.rs index 7f506acb77..35ed3308dc 100644 --- a/library/stdarch/crates/stdarch-gen/src/main.rs +++ b/library/stdarch/crates/stdarch-gen/src/main.rs @@ -51,38 +51,34 @@ const FLOAT_TYPES_64: [&str; 2] = [ ]; fn type_len(t: &str) -> usize { - match t { - "int8x8_t" => 8, - "int8x16_t" => 16, - "int16x4_t" => 4, - "int16x8_t" => 8, - "int32x2_t" => 2, - "int32x4_t" => 4, - "int64x1_t" => 1, - "int64x2_t" => 2, - "uint8x8_t" => 8, - "uint8x16_t" => 16, - "uint16x4_t" => 4, - "uint16x8_t" => 8, - "uint32x2_t" => 2, - "uint32x4_t" => 4, - "uint64x1_t" => 1, - "uint64x2_t" => 2, - "float16x4_t" => 4, - "float16x8_t" => 8, - "float32x2_t" => 2, - "float32x4_t" => 4, - "float64x1_t" => 1, - "float64x2_t" => 2, - "poly8x8_t" => 8, - "poly8x16_t" => 16, - "poly16x4_t" => 4, - "poly16x8_t" => 8, - "poly64x1_t" => 1, - "poly64x2_t" => 2, - "i8" | "i16" | "i32" | "i64" | "u8" | "u16" | "u32" | "u64" | "f32" | "f64" | "p8" - | "p16" | "p64" | "p128" => 1, - _ => panic!("unknown type: {}", t), + let s: Vec<_> = t.split("x").collect(); + if s.len() == 2 { + match &s[1][0..2] { + "1_" => 1, + "2_" => 2, + "4_" => 4, + "8_" => 8, + "16" => 16, + _ => panic!("unknown type: {}", t), + } + } else if s.len() == 3 { + s[1].parse::().unwrap() * type_sub_len(t) + } else { + 1 + } +} + +fn type_sub_len(t: &str) -> usize { + let s: Vec<_> = t.split('x').collect(); + if s.len() != 3 { + 1 + } else { + match s[2] { + "2_t" => 2, + "3_t" => 3, + "4_t" => 4, + _ => panic!("unknown type len: {}", t), + } } } @@ -101,35 +97,14 @@ fn type_bits(t: &str) -> usize { } fn type_exp_len(t: &str) -> usize { - match t { - "int8x8_t" => 3, - "int8x16_t" => 4, - "int16x4_t" => 2, - "int16x8_t" => 3, - "int32x2_t" => 1, - "int32x4_t" => 2, - "int64x1_t" => 0, - "int64x2_t" => 1, - "uint8x8_t" => 3, - "uint8x16_t" => 4, - "uint16x4_t" => 2, - "uint16x8_t" => 3, - "uint32x2_t" => 1, - "uint32x4_t" => 2, - "uint64x1_t" => 0, - "uint64x2_t" => 1, - "float16x4_t" => 2, - "float16x8_t" => 3, - "float32x2_t" => 1, - "float32x4_t" => 2, - "float64x1_t" => 0, - "float64x2_t" => 1, - "poly8x8_t" => 3, - "poly8x16_t" => 4, - "poly16x4_t" => 2, - "poly16x8_t" => 3, - "poly64x1_t" => 0, - "poly64x2_t" => 1, + let t = type_to_sub_type(t); + let len = type_len(&t); + match len { + 1 => 0, + 2 => 1, + 4 => 2, + 8 => 3, + 16 => 4, _ => panic!("unknown type: {}", t), } } @@ -177,6 +152,84 @@ fn type_to_suffix(t: &str) -> &str { "poly16x8_t" => "q_p16", "poly64x1_t" => "_p64", "poly64x2_t" => "q_p64", + "int8x8x2_t" => "_s8_x2", + "int8x8x3_t" => "_s8_x3", + "int8x8x4_t" => "_s8_x4", + "int16x4x2_t" => "_s16_x2", + "int16x4x3_t" => "_s16_x3", + "int16x4x4_t" => "_s16_x4", + "int32x2x2_t" => "_s32_x2", + "int32x2x3_t" => "_s32_x3", + "int32x2x4_t" => "_s32_x4", + "int64x1x2_t" => "_s64_x2", + "int64x1x3_t" => "_s64_x3", + "int64x1x4_t" => "_s64_x4", + "uint8x8x2_t" => "_u8_x2", + "uint8x8x3_t" => "_u8_x3", + "uint8x8x4_t" => "_u8_x4", + "uint16x4x2_t" => "_u16_x2", + "uint16x4x3_t" => "_u16_x3", + "uint16x4x4_t" => "_u16_x4", + "uint32x2x2_t" => "_u32_x2", + "uint32x2x3_t" => "_u32_x3", + "uint32x2x4_t" => "_u32_x4", + "uint64x1x2_t" => "_u64_x2", + "uint64x1x3_t" => "_u64_x3", + "uint64x1x4_t" => "_u64_x4", + "poly8x8x2_t" => "_p8_x2", + "poly8x8x3_t" => "_p8_x3", + "poly8x8x4_t" => "_p8_x4", + "poly16x4x2_t" => "_p16_x2", + "poly16x4x3_t" => "_p16_x3", + "poly16x4x4_t" => "_p16_x4", + "poly64x1x2_t" => "_p64_x2", + "poly64x1x3_t" => "_p64_x3", + "poly64x1x4_t" => "_p64_x4", + "float32x2x2_t" => "_f32_x2", + "float32x2x3_t" => "_f32_x3", + "float32x2x4_t" => "_f32_x4", + "float64x1x2_t" => "_f64_x2", + "float64x1x3_t" => "_f64_x3", + "float64x1x4_t" => "_f64_x4", + "int8x16x2_t" => "q_s8_x2", + "int8x16x3_t" => "q_s8_x3", + "int8x16x4_t" => "q_s8_x4", + "int16x8x2_t" => "q_s16_x2", + "int16x8x3_t" => "q_s16_x3", + "int16x8x4_t" => "q_s16_x4", + "int32x4x2_t" => "q_s32_x2", + "int32x4x3_t" => "q_s32_x3", + "int32x4x4_t" => "q_s32_x4", + "int64x2x2_t" => "q_s64_x2", + "int64x2x3_t" => "q_s64_x3", + "int64x2x4_t" => "q_s64_x4", + "uint8x16x2_t" => "q_u8_x2", + "uint8x16x3_t" => "q_u8_x3", + "uint8x16x4_t" => "q_u8_x4", + "uint16x8x2_t" => "q_u16_x2", + "uint16x8x3_t" => "q_u16_x3", + "uint16x8x4_t" => "q_u16_x4", + "uint32x4x2_t" => "q_u32_x2", + "uint32x4x3_t" => "q_u32_x3", + "uint32x4x4_t" => "q_u32_x4", + "uint64x2x2_t" => "q_u64_x2", + "uint64x2x3_t" => "q_u64_x3", + "uint64x2x4_t" => "q_u64_x4", + "poly8x16x2_t" => "q_p8_x2", + "poly8x16x3_t" => "q_p8_x3", + "poly8x16x4_t" => "q_p8_x4", + "poly16x8x2_t" => "q_p16_x2", + "poly16x8x3_t" => "q_p16_x3", + "poly16x8x4_t" => "q_p16_x4", + "poly64x2x2_t" => "q_p64_x2", + "poly64x2x3_t" => "q_p64_x3", + "poly64x2x4_t" => "q_p64_x4", + "float32x4x2_t" => "q_f32_x2", + "float32x4x3_t" => "q_f32_x3", + "float32x4x4_t" => "q_f32_x4", + "float64x2x2_t" => "q_f64_x2", + "float64x2x3_t" => "q_f64_x3", + "float64x2x4_t" => "q_f64_x4", "i8" => "b_s8", "i16" => "h_s16", "i32" => "s_s32", @@ -193,6 +246,18 @@ fn type_to_suffix(t: &str) -> &str { } } +fn type_to_dup_suffix(t: &str) -> String { + let s: Vec<_> = type_to_suffix(t).split('_').collect(); + assert_eq!(s.len(), 2); + format!("{}_dup_{}", s[0], s[1]) +} + +fn type_to_lane_suffix(t: &str) -> String { + let s: Vec<_> = type_to_suffix(t).split('_').collect(); + assert_eq!(s.len(), 2); + format!("{}_lane_{}", s[0], s[1]) +} + fn type_to_n_suffix(t: &str) -> &str { match t { "int8x8_t" => "_n_s8", @@ -274,18 +339,10 @@ fn type_to_lane_suffixes<'a>(out_t: &'a str, in_t: &'a str) -> String { str } -fn type_to_signed(t: &str) -> &str { - match t { - "int8x8_t" | "uint8x8_t" | "poly8x8_t" => "int8x8_t", - "int8x16_t" | "uint8x16_t" | "poly8x16_t" => "int8x16_t", - "int16x4_t" | "uint16x4_t" | "poly16x4_t" => "int16x4_t", - "int16x8_t" | "uint16x8_t" | "poly16x8_t" => "int16x8_t", - "int32x2_t" | "uint32x2_t" => "int32x2_t", - "int32x4_t" | "uint32x4_t" => "int32x4_t", - "int64x1_t" | "uint64x1_t" | "poly64x1_t" => "int64x1_t", - "int64x2_t" | "uint64x2_t" | "poly64x2_t" => "int64x2_t", - _ => panic!("unknown type: {}", t), - } +fn type_to_signed(t: &String) -> String { + let s = t.replace("uint", "int"); + let s = s.replace("poly", "int"); + s } fn type_to_unsigned(t: &str) -> &str { @@ -369,6 +426,9 @@ enum Suffix { NoQNSuffix, OutSuffix, OutNSuffix, + OutNox, + OutDupNox, + OutLaneNox, Lane, In2, In2Lane, @@ -378,40 +438,48 @@ enum Suffix { enum TargetFeature { Default, ArmV7, + Vfp4, FPArmV8, AES, } +#[derive(Clone, Copy)] +enum Fntype { + Normal, + Load, + Store, +} + fn type_to_global_type(t: &str) -> &str { match t { - "int8x8_t" => "i8x8", - "int8x16_t" => "i8x16", - "int16x4_t" => "i16x4", - "int16x8_t" => "i16x8", - "int32x2_t" => "i32x2", - "int32x4_t" => "i32x4", - "int64x1_t" => "i64x1", - "int64x2_t" => "i64x2", - "uint8x8_t" => "u8x8", - "uint8x16_t" => "u8x16", - "uint16x4_t" => "u16x4", - "uint16x8_t" => "u16x8", - "uint32x2_t" => "u32x2", - "uint32x4_t" => "u32x4", - "uint64x1_t" => "u64x1", - "uint64x2_t" => "u64x2", + "int8x8_t" | "int8x8x2_t" | "int8x8x3_t" | "int8x8x4_t" => "i8x8", + "int8x16_t" | "int8x16x2_t" | "int8x16x3_t" | "int8x16x4_t" => "i8x16", + "int16x4_t" | "int16x4x2_t" | "int16x4x3_t" | "int16x4x4_t" => "i16x4", + "int16x8_t" | "int16x8x2_t" | "int16x8x3_t" | "int16x8x4_t" => "i16x8", + "int32x2_t" | "int32x2x2_t" | "int32x2x3_t" | "int32x2x4_t" => "i32x2", + "int32x4_t" | "int32x4x2_t" | "int32x4x3_t" | "int32x4x4_t" => "i32x4", + "int64x1_t" | "int64x1x2_t" | "int64x1x3_t" | "int64x1x4_t" => "i64x1", + "int64x2_t" | "int64x2x2_t" | "int64x2x3_t" | "int64x2x4_t" => "i64x2", + "uint8x8_t" | "uint8x8x2_t" | "uint8x8x3_t" | "uint8x8x4_t" => "u8x8", + "uint8x16_t" | "uint8x16x2_t" | "uint8x16x3_t" | "uint8x16x4_t" => "u8x16", + "uint16x4_t" | "uint16x4x2_t" | "uint16x4x3_t" | "uint16x4x4_t" => "u16x4", + "uint16x8_t" | "uint16x8x2_t" | "uint16x8x3_t" | "uint16x8x4_t" => "u16x8", + "uint32x2_t" | "uint32x2x2_t" | "uint32x2x3_t" | "uint32x2x4_t" => "u32x2", + "uint32x4_t" | "uint32x4x2_t" | "uint32x4x3_t" | "uint32x4x4_t" => "u32x4", + "uint64x1_t" | "uint64x1x2_t" | "uint64x1x3_t" | "uint64x1x4_t" => "u64x1", + "uint64x2_t" | "uint64x2x2_t" | "uint64x2x3_t" | "uint64x2x4_t" => "u64x2", "float16x4_t" => "f16x4", "float16x8_t" => "f16x8", - "float32x2_t" => "f32x2", - "float32x4_t" => "f32x4", - "float64x1_t" => "f64", - "float64x2_t" => "f64x2", - "poly8x8_t" => "i8x8", - "poly8x16_t" => "i8x16", - "poly16x4_t" => "i16x4", - "poly16x8_t" => "i16x8", - "poly64x1_t" => "i64x1", - "poly64x2_t" => "i64x2", + "float32x2_t" | "float32x2x2_t" | "float32x2x3_t" | "float32x2x4_t" => "f32x2", + "float32x4_t" | "float32x4x2_t" | "float32x4x3_t" | "float32x4x4_t" => "f32x4", + "float64x1_t" | "float64x1x2_t" | "float64x1x3_t" | "float64x1x4_t" => "f64", + "float64x2_t" | "float64x2x2_t" | "float64x2x3_t" | "float64x2x4_t" => "f64x2", + "poly8x8_t" | "poly8x8x2_t" | "poly8x8x3_t" | "poly8x8x4_t" => "i8x8", + "poly8x16_t" | "poly8x16x2_t" | "poly8x16x3_t" | "poly8x16x4_t" => "i8x16", + "poly16x4_t" | "poly16x4x2_t" | "poly16x4x3_t" | "poly16x4x4_t" => "i16x4", + "poly16x8_t" | "poly16x8x2_t" | "poly16x8x3_t" | "poly16x8x4_t" => "i16x8", + "poly64x1_t" | "poly64x1x2_t" | "poly64x1x3_t" | "poly64x1x4_t" => "i64x1", + "poly64x2_t" | "poly64x2x2_t" | "poly64x2x3_t" | "poly64x2x4_t" => "i64x2", "i8" => "i8", "i16" => "i16", "i32" => "i32", @@ -430,20 +498,30 @@ fn type_to_global_type(t: &str) -> &str { } } -fn type_to_native_type(t: &str) -> &str { - match t { - "int8x8_t" | "int8x16_t" | "i8" => "i8", - "int16x4_t" | "int16x8_t" | "i16" => "i16", - "int32x2_t" | "int32x4_t" | "i32" => "i32", - "int64x1_t" | "int64x2_t" | "i64" => "i64", - "uint8x8_t" | "uint8x16_t" | "u8" => "u8", - "uint16x4_t" | "uint16x8_t" | "u16" => "u16", - "uint32x2_t" | "uint32x4_t" | "u32" => "u32", - "uint64x1_t" | "uint64x2_t" | "u64" => "u64", - "float16x4_t" | "float16x8_t" => "f16", - "float32x2_t" | "float32x4_t" => "f32", - "float64x1_t" | "float64x2_t" => "f64", - "poly64x1_t" | "poly64x2_t" => "u64", +fn type_to_sub_type(t: &str) -> String { + let s: Vec<_> = t.split('x').collect(); + match s.len() { + 2 => String::from(t), + 3 => format!("{}x{}_t", s[0], s[1]), + _ => panic!("unknown type: {}", t), + } +} + +fn type_to_native_type(t: &str) -> String { + let s: Vec<_> = t.split('x').collect(); + match s.len() { + 1 => { + assert!(t.contains("*const") || t.contains("*mut")); + let sub: Vec<_> = t.split(' ').collect(); + String::from(sub[1]) + } + 2 | 3 => match &s[0][0..3] { + "int" => format!("i{}", &s[0][3..]), + "uin" => format!("u{}", &s[0][4..]), + "flo" => format!("f{}", &s[0][5..]), + "pol" => format!("u{}", &s[0][4..]), + _ => panic!("unknown type: {}", t), + }, _ => panic!("unknown type: {}", t), } } @@ -482,54 +560,6 @@ fn native_type_to_long_type(t: &str) -> &str { } } -fn type_to_ext(t: &str) -> &str { - match t { - "int8x8_t" => "v8i8", - "int8x16_t" => "v16i8", - "int16x4_t" => "v4i16", - "int16x8_t" => "v8i16", - "int32x2_t" => "v2i32", - "int32x4_t" => "v4i32", - "int64x1_t" => "v1i64", - "int64x2_t" => "v2i64", - "uint8x8_t" => "v8i8", - "uint8x16_t" => "v16i8", - "uint16x4_t" => "v4i16", - "uint16x8_t" => "v8i16", - "uint32x2_t" => "v2i32", - "uint32x4_t" => "v4i32", - "uint64x1_t" => "v1i64", - "uint64x2_t" => "v2i64", - "float16x4_t" => "v4f16", - "float16x8_t" => "v8f16", - "float32x2_t" => "v2f32", - "float32x4_t" => "v4f32", - "float64x1_t" => "v1f64", - "float64x2_t" => "v2f64", - "poly8x8_t" => "v8i8", - "poly8x16_t" => "v16i8", - "poly16x4_t" => "v4i16", - "poly16x8_t" => "v8i16", - "i8" => "i8", - "i16" => "i16", - "i32" => "i32", - "i64" => "i64", - "u8" => "i8", - "u16" => "i16", - "u32" => "i32", - "u64" => "i64", - "f32" => "f32", - "f64" => "f64", - "p64" => "p64", - "p128" => "p128", - /* - "poly64x1_t" => "i64x1", - "poly64x2_t" => "i64x2", - */ - _ => panic!("unknown type for extension: {}", t), - } -} - fn type_to_half(t: &str) -> &str { match t { "int8x16_t" => "int8x8_t", @@ -835,6 +865,53 @@ fn map_val<'v>(t: &str, v: &'v str) -> &'v str { } } +fn type_to_ext(t: &str, v: bool, r: bool, pi8: bool) -> String { + if !t.contains('x') { + return t.replace("u", "i"); + } + let native = type_to_native_type(t); + let sub_ext = match type_sub_len(t) { + 1 => String::new(), + _ if v => format!( + ".p0v{}{}", + &type_len(&type_to_sub_type(t)).to_string(), + native + ), + _ if pi8 => format!(".p0i8"), + _ => format!(".p0{}", native), + }; + let sub_type = match &native[0..1] { + "i" | "f" => native, + "u" => native.replace("u", "i"), + _ => panic!("unknown type: {}", t), + }; + let ext = format!( + "v{}{}{}", + &type_len(&type_to_sub_type(t)).to_string(), + sub_type, + sub_ext + ); + if r { + let ss: Vec<_> = ext.split('.').collect(); + if ss.len() != 2 { + ext + } else { + format!("{}.{}", ss[1], ss[0]) + } + } else { + ext + } +} + +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("_EXTr3_", &type_to_ext(in_t[1], false, true, false)) + .replace("_EXTv2_", &type_to_ext(out_t, true, false, false)) + .replace("_EXTpi82_", &type_to_ext(out_t, false, false, true)) +} + #[allow(clippy::too_many_arguments)] fn gen_aarch64( current_comment: &str, @@ -858,9 +935,8 @@ fn gen_aarch64( target: TargetFeature, fixed: &Vec, multi_fn: &Vec, + fn_type: Fntype, ) -> (String, String) { - let _global_t = type_to_global_type(in_t[0]); - let _global_ret_t = type_to_global_type(out_t); let name = match suffix { Normal => format!("{}{}", current_name, type_to_suffix(in_t[1])), NoQ => format!("{}{}", current_name, type_to_noq_suffix(in_t[1])), @@ -883,6 +959,21 @@ fn gen_aarch64( NoQNSuffix => format!("{}{}", current_name, type_to_noq_n_suffix(in_t[1])), OutSuffix => format!("{}{}", current_name, type_to_suffix(out_t)), OutNSuffix => format!("{}{}", current_name, type_to_n_suffix(out_t)), + OutNox => format!( + "{}{}", + current_name, + type_to_suffix(&type_to_sub_type(out_t)) + ), + OutDupNox => format!( + "{}{}", + current_name, + type_to_dup_suffix(&type_to_sub_type(out_t)) + ), + OutLaneNox => format!( + "{}{}", + 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])), In2 => format!("{}{}", current_name, type_to_suffix(in_t[2])), In2Lane => format!("{}{}", current_name, type_to_lane_suffixes(out_t, in_t[2])), @@ -890,6 +981,7 @@ fn gen_aarch64( let current_target = match target { Default => "neon", ArmV7 => "v7", + Vfp4 => "vfp4", FPArmV8 => "fp-armv8,v8", AES => "neon,aes", }; @@ -910,14 +1002,13 @@ fn gen_aarch64( String::new() }; let current_aarch64 = current_aarch64.clone().unwrap(); - let mut ext_c = String::new(); - let mut ext_c_const = String::new(); let mut link_t: Vec = vec![ in_t[0].to_string(), in_t[1].to_string(), in_t[2].to_string(), out_t.to_string(), ]; + let mut ext_c = String::new(); if let Some(mut link_aarch64) = link_aarch64.clone() { if link_aarch64.contains(":") { let links: Vec<_> = link_aarch64.split(':').map(|v| v.to_string()).collect(); @@ -930,63 +1021,81 @@ fn gen_aarch64( links[4].clone(), ]; } - let ext = type_to_ext(in_t[0]); - let ext2 = type_to_ext(out_t); let link_aarch64 = if link_aarch64.starts_with("llvm") { - link_aarch64.replace("_EXT_", ext).replace("_EXT2_", ext2) + ext(&link_aarch64, in_t, out_t) } else { let mut link = String::from("llvm.aarch64.neon."); link.push_str(&link_aarch64); - link.replace("_EXT_", ext).replace("_EXT2_", ext2) + ext(&link, in_t, out_t) + }; + let (ext_inputs, ext_output) = { + if const_aarch64.is_some() { + if matches!(fn_type, Fntype::Load) { + 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), + 3 => format!( + "a: {}, b: {}, c: {}, n: i64, ptr: *const i8", + sub, sub, sub + ), + 4 => format!( + "a: {}, b: {}, c: {}, d: {}, n: i64, ptr: *const i8", + sub, sub, sub, sub + ), + _ => panic!("unsupported type: {}", in_t[1]), + }, + format!(" -> {}", out_t), + ) + } else { + ( + match para_num { + 1 => format!("a: {}, n: i32", in_t[0]), + 2 => format!("a: {}, b: {}, n: i32", in_t[0], in_t[1]), + 3 => format!("a: {}, b: {}, c: {}, n: i32", in_t[0], in_t[1], in_t[2]), + _ => unimplemented!("unknown para_num"), + }, + format!(" -> {}", out_t), + ) + } + } 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]); + ( + 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(), + ) + } else { + ( + match para_num { + 1 => format!("a: {}", link_t[0]), + 2 => format!("a: {}, b: {}", link_t[0], link_t[1]), + 3 => format!("a: {}, b: {}, c: {}", link_t[0], link_t[1], link_t[2]), + _ => unimplemented!("unknown para_num"), + }, + format!(" -> {}", link_t[3]), + ) + } }; ext_c = format!( r#"#[allow(improper_ctypes)] - extern "C" {{ + extern "unadjusted" {{ #[cfg_attr(target_arch = "aarch64", link_name = "{}")] - fn {}({}) -> {}; + fn {}({}){}; }} "#, - link_aarch64, - current_fn, - match para_num { - 1 => { - format!("a: {}", link_t[0]) - } - 2 => { - format!("a: {}, b: {}", link_t[0], link_t[1]) - } - 3 => { - format!("a: {}, b: {}, c: {}", link_t[0], link_t[1], link_t[2]) - } - _ => unimplemented!("unknown para_num"), - }, - link_t[3] + link_aarch64, current_fn, ext_inputs, ext_output, ); - if const_aarch64.is_some() { - ext_c_const = format!( - r#"#[allow(improper_ctypes)] - extern "C" {{ - #[cfg_attr(target_arch = "aarch64", link_name = "{}")] - fn {}({}) -> {}; - }} - "#, - link_aarch64, - current_fn, - match para_num { - 1 => { - format!("a: {}, n: i32", in_t[0]) - } - 2 => { - format!("a: {}, b: {}, n: i32", in_t[0], in_t[1]) - } - 3 => { - format!("a: {}, b: {}, c: {}, n: i32", in_t[0], in_t[1], in_t[2]) - } - _ => unimplemented!("unknown para_num"), - }, - out_t - ); - } }; let const_declare = if let Some(constn) = constn { if constn.contains(":") { @@ -1013,6 +1122,7 @@ fn gen_aarch64( out_t, fixed, None, + true, )); } calls @@ -1056,99 +1166,93 @@ fn gen_aarch64( } else { String::new() }; - let trans: [&str; 2] = if link_t[3] != out_t { - ["transmute(", ")"] - } else { - ["", ""] + let fn_decl = { + let fn_output = if out_t == "void" { + String::new() + } else { + format!("-> {} ", out_t) + }; + let fn_inputs = match para_num { + 1 => format!("(a: {})", in_t[0]), + 2 => format!("(a: {}, b: {})", in_t[0], in_t[1]), + 3 => format!("(a: {}, b: {}, c: {})", in_t[0], in_t[1], in_t[2]), + _ => panic!("unsupported parameter number"), + }; + format!( + "pub unsafe fn {}{}{} {}", + name, const_declare, fn_inputs, fn_output + ) }; - let call = if let Some(const_aarch64) = const_aarch64 { - match para_num { - 1 => format!( - r#"pub unsafe fn {}{}(a: {}) -> {} {{ - {} - {}{}(a, {}) -}}"#, - name, - const_declare, - in_t[0], - out_t, - multi_calls, - ext_c_const, - current_fn, - const_aarch64 - ), - 2 => format!( - r#"pub unsafe fn {}{}(a: {}) -> {} {{ - {}{}{}(a, b, {}) -}}"#, - name, - const_declare, - in_t[0], - out_t, - multi_calls, - ext_c_const, - current_fn, - const_aarch64 - ), - _ => String::new(), - } - } else { - match (multi_calls.len(), para_num, fixed.len()) { - (0, 1, 0) => format!( - r#"pub unsafe fn {}{}(a: {}) -> {} {{ - {}{}{}(a){} -}}"#, - name, const_declare, in_t[0], out_t, ext_c, trans[0], current_fn, trans[1] - ), - (0, 1, _) => { - let fixed: Vec = fixed.iter().take(type_len(in_t[0])).cloned().collect(); + let call_params = { + if let (Some(const_aarch64), Some(_)) = (const_aarch64, link_aarch64) { + if matches!(fn_type, Fntype::Load) { + let subs = match type_sub_len(in_t[1]) { + 1 => "b", + 2 => "b.0, b.1", + 3 => "b.0, b.1, b.2", + 4 => "b.0, b.1, b.2, b.3", + _ => panic!("unsupported type: {}", in_t[1]), + }; format!( - r#"pub unsafe fn {}{}(a: {}) -> {} {{ - let b{}; - {}{}{}(a, transmute(b)){} -}}"#, - name, - const_declare, - in_t[0], - out_t, - values(in_t[0], &fixed), + r#"{} + {}{}({}, {} as i64, a as *const i8)"#, + multi_calls, ext_c, - trans[0], current_fn, - trans[1], + subs, + constn.as_deref().unwrap() ) + } else { + match para_num { + 1 => format!( + r#"{} + {}{}(a, {})"#, + multi_calls, ext_c, current_fn, const_aarch64 + ), + 2 => format!( + r#"{} + {}{}(a, b, {})"#, + multi_calls, ext_c, current_fn, const_aarch64 + ), + _ => String::new(), + } + } + } else if matches!(fn_type, Fntype::Store) { + 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), + _ => panic!("unsupported type: {}", in_t[1]), + } + } else { + let trans: [&str; 2] = if link_t[3] != out_t { + ["transmute(", ")"] + } else { + ["", ""] + }; + match (multi_calls.len(), para_num, fixed.len()) { + (0, 1, 0) => format!(r#"{}{}{}(a){}"#, ext_c, trans[0], current_fn, trans[1]), + (0, 1, _) => { + let fixed: Vec = + fixed.iter().take(type_len(in_t[0])).cloned().collect(); + format!( + r#"let b{}; + {}{}{}(a, transmute(b)){}"#, + values(in_t[0], &fixed), + ext_c, + trans[0], + current_fn, + trans[1], + ) + } + (0, 2, _) => format!(r#"{}{}{}(a, b){}"#, ext_c, trans[0], current_fn, trans[1],), + (0, 3, _) => format!(r#"{}{}(a, b, c)"#, ext_c, current_fn,), + (_, 1, _) => format!(r#"{}{}"#, ext_c, multi_calls,), + (_, 2, _) => format!(r#"{}{}"#, ext_c, multi_calls,), + (_, 3, _) => format!(r#"{}{}"#, ext_c, multi_calls,), + (_, _, _) => String::new(), } - (0, 2, _) => format!( - r#"pub unsafe fn {}{}(a: {}, b: {}) -> {} {{ - {}{}{}(a, b){} -}}"#, - name, const_declare, in_t[0], in_t[1], out_t, ext_c, trans[0], current_fn, trans[1], - ), - (0, 3, _) => format!( - r#"pub unsafe fn {}{}(a: {}, b: {}, c: {}) -> {} {{ - {}{}(a, b, c) -}}"#, - name, const_declare, in_t[0], in_t[1], in_t[2], out_t, ext_c, current_fn, - ), - (_, 1, _) => format!( - r#"pub unsafe fn {}{}(a: {}) -> {} {{ - {}{} -}}"#, - name, const_declare, in_t[0], out_t, ext_c, multi_calls, - ), - (_, 2, _) => format!( - r#"pub unsafe fn {}{}(a: {}, b: {}) -> {} {{ - {}{} -}}"#, - name, const_declare, in_t[0], in_t[1], out_t, ext_c, multi_calls, - ), - (_, 3, _) => format!( - r#"pub unsafe fn {}{}(a: {}, b: {}, c: {}) -> {} {{ - {}{} -}}"#, - name, const_declare, in_t[0], in_t[1], in_t[2], out_t, ext_c, multi_calls, - ), - (_, _, _) => String::new(), } }; let function = format!( @@ -1157,23 +1261,197 @@ fn gen_aarch64( #[inline] #[target_feature(enable = "{}")] #[cfg_attr(test, assert_instr({}{}))]{} -{} +{}{{ + {} +}} "#, - current_comment, current_target, current_aarch64, const_assert, const_legacy, call - ); - - let test = gen_test( - &name, - in_t, - &out_t, - current_tests, - [type_len(in_t[0]), type_len(in_t[1]), type_len(in_t[2])], - type_len(out_t), - para_num, + current_comment, + current_target, + current_aarch64, + const_assert, + const_legacy, + fn_decl, + call_params ); + let test = match fn_type { + Fntype::Normal => gen_test( + &name, + in_t, + &out_t, + current_tests, + [type_len(in_t[0]), type_len(in_t[1]), type_len(in_t[2])], + type_len(out_t), + para_num, + ), + 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])), + }; (function, test) } +fn gen_load_test( + name: &str, + in_t: &[&str; 3], + out_t: &str, + current_tests: &[( + Vec, + Vec, + Vec, + Option, + Vec, + )], + type_len: usize, +) -> String { + let mut test = format!( + r#" + #[simd_test(enable = "neon")] + unsafe fn test_{}() {{"#, + name, + ); + for (a, b, _, n, 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 has_b = b.len() > 0; + let has_n = n.is_some(); + let mut input = String::from("["); + for i in 0..type_len + 1 { + if i != 0 { + input.push_str(", "); + } + input.push_str(&a[i]) + } + input.push_str("]"); + let output = |v: &Vec| { + let mut output = String::from("["); + for i in 0..type_sub_len(out_t) { + if i != 0 { + output.push_str(", "); + } + let sub_len = type_len / type_sub_len(out_t); + if type_to_global_type(out_t) != "f64" { + let mut sub_output = format!("{}::new(", type_to_global_type(out_t)); + for j in 0..sub_len { + if j != 0 { + sub_output.push_str(", "); + } + sub_output.push_str(&v[i * sub_len + j]); + } + sub_output.push_str(")"); + output.push_str(&sub_output); + } else { + output.push_str(&v[i]); + } + } + output.push_str("]"); + output + }; + let input_b = if has_b { + let b: Vec = b.iter().take(type_len).cloned().collect(); + format!( + r#" + let b: [{}; {}] = {};"#, + type_to_global_type(in_t[1]), + type_sub_len(in_t[1]), + output(&b), + ) + } else { + String::new() + }; + let t = format!( + r#" + let a: [{}; {}] = {};{} + let e: [{}; {}] = {}; + let r: [{}; {}] = transmute({}{}(a[1..].as_ptr(){})); + assert_eq!(r, e); +"#, + type_to_native_type(out_t), + type_len + 1, + input, + input_b, + type_to_global_type(out_t), + type_sub_len(out_t), + output(&e), + type_to_global_type(out_t), + type_sub_len(out_t), + name, + if has_n { + format!("::<{}>", n.as_deref().unwrap()) + } else { + String::new() + }, + if has_b { ", transmute(b)" } else { "" }, + ); + test.push_str(&t); + } + test.push_str(" }\n"); + test +} + +fn gen_store_test( + name: &str, + in_t: &[&str; 3], + _out_t: &str, + current_tests: &[( + Vec, + Vec, + Vec, + Option, + Vec, + )], + type_len: usize, +) -> String { + let mut test = format!( + r#" + #[simd_test(enable = "neon")] + unsafe fn test_{}() {{"#, + name, + ); + for (a, _, _, _, 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("["); + for i in 0..type_len + 1 { + if i != 0 { + input.push_str(", "); + } + input.push_str(&a[i]) + } + input.push_str("]"); + let mut output = String::from("["); + for i in 0..type_len { + if i != 0 { + output.push_str(", "); + } + output.push_str(&e[i]) + } + output.push_str("]"); + let t = format!( + r#" + let a: [{}; {}] = {}; + let e: [{}; {}] = {}; + let mut r: [{}; {}] = [0{}; {}]; + {}(r.as_mut_ptr(), {}(a[1..].as_ptr())); + assert_eq!(r, e); +"#, + type_to_native_type(in_t[1]), + type_len + 1, + input, + type_to_native_type(in_t[1]), + type_len, + output, + type_to_native_type(in_t[1]), + type_len, + type_to_native_type(in_t[1]), + type_len, + name, + name.replace("st", "ld"), + ); + test.push_str(&t); + } + test.push_str(" }\n"); + test +} + fn gen_test( name: &str, in_t: &[&str; 3], @@ -1305,9 +1583,9 @@ fn gen_arm( target: TargetFeature, fixed: &Vec, multi_fn: &Vec, + fn_type: Fntype, + separate: bool, ) -> (String, String) { - let _global_t = type_to_global_type(in_t[0]); - let _global_ret_t = type_to_global_type(out_t); let name = match suffix { Normal => format!("{}{}", current_name, type_to_suffix(in_t[1])), NoQ => format!("{}{}", current_name, type_to_noq_suffix(in_t[1])), @@ -1330,6 +1608,21 @@ fn gen_arm( NoQNSuffix => format!("{}{}", current_name, type_to_noq_n_suffix(in_t[1])), OutSuffix => format!("{}{}", current_name, type_to_suffix(out_t)), OutNSuffix => format!("{}{}", current_name, type_to_n_suffix(out_t)), + OutNox => format!( + "{}{}", + current_name, + type_to_suffix(&type_to_sub_type(out_t)) + ), + OutDupNox => format!( + "{}{}", + current_name, + type_to_dup_suffix(&type_to_sub_type(out_t)) + ), + OutLaneNox => format!( + "{}{}", + 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])), In2 => format!("{}{}", current_name, type_to_suffix(in_t[2])), In2Lane => format!("{}{}", current_name, type_to_lane_suffixes(out_t, in_t[2])), @@ -1340,16 +1633,17 @@ fn gen_arm( let current_target_aarch64 = match target { Default => "neon", ArmV7 => "neon", + Vfp4 => "neon", FPArmV8 => "neon", AES => "neon,aes", }; let current_target_arm = match target { Default => "v7", ArmV7 => "v7", + Vfp4 => "vfp4", FPArmV8 => "fp-armv8,v8", - AES => "crypto,v8", // TODO: Replace with AES when the minimum LLVM version has b8baa2a9132498ea286dbb0d03f005760ecc6fdb + AES => "aes,v8", }; - let current_fn = if let Some(current_fn) = current_fn.clone() { if link_aarch64.is_some() || link_arm.is_some() { panic!( @@ -1370,7 +1664,7 @@ fn gen_arm( String::new() }; let mut ext_c = String::new(); - let mut ext_c_arm = if multi_fn.is_empty() { + let mut ext_c_arm = if multi_fn.is_empty() || link_arm.is_none() { String::new() } else { String::from( @@ -1378,7 +1672,7 @@ fn gen_arm( "#, ) }; - let mut ext_c_aarch64 = if multi_fn.is_empty() { + let mut ext_c_aarch64 = if multi_fn.is_empty() || link_aarch64.is_none() { String::new() } else { String::from( @@ -1421,26 +1715,24 @@ fn gen_arm( links[4].clone(), ]; } - let ext = type_to_ext(in_t[0]); - let ext2 = type_to_ext(out_t); let link_arm = if link_arm.starts_with("llvm") { - link_arm.replace("_EXT_", ext).replace("_EXT2_", ext2) + ext(&link_arm, in_t, out_t) } else { let mut link = String::from("llvm.arm.neon."); link.push_str(&link_arm); - link.replace("_EXT_", ext).replace("_EXT2_", ext2) + ext(&link, in_t, out_t) }; let link_aarch64 = if link_aarch64.starts_with("llvm") { - link_aarch64.replace("_EXT_", ext).replace("_EXT2_", ext2) + ext(&link_aarch64, in_t, out_t) } else { let mut link = String::from("llvm.aarch64.neon."); link.push_str(&link_aarch64); - link.replace("_EXT_", ext).replace("_EXT2_", ext2) + ext(&link, in_t, out_t) }; if out_t == link_arm_t[3] && out_t == link_aarch64_t[3] { ext_c = format!( r#"#[allow(improper_ctypes)] - extern "C" {{ + extern "unadjusted" {{ #[cfg_attr(target_arch = "arm", link_name = "{}")] #[cfg_attr(target_arch = "aarch64", link_name = "{}")] fn {}({}) -> {}; @@ -1450,138 +1742,165 @@ fn gen_arm( link_aarch64, current_fn, match para_num { - 1 => { - format!("a: {}", in_t[0]) - } - 2 => { - format!("a: {}, b: {}", in_t[0], in_t[1]) - } - 3 => { - format!("a: {}, b: {}, c: {}", in_t[0], in_t[1], in_t[2]) - } + 1 => format!("a: {}", in_t[0]), + 2 => format!("a: {}, b: {}", in_t[0], in_t[1]), + 3 => format!("a: {}, b: {}, c: {}", in_t[0], in_t[1], in_t[2]), _ => unimplemented!("unknown para_num"), }, out_t ); }; - if let Some(const_arm) = const_arm { - let (_, const_type) = if const_arm.contains(":") { - let consts: Vec<_> = const_arm.split(':').map(|v| v.trim().to_string()).collect(); - (consts[0].clone(), consts[1].clone()) - } else { - ( - const_arm.to_string(), - in_t[para_num as usize - 1].to_string(), - ) - }; - ext_c_arm.push_str(&format!( - r#"#[allow(improper_ctypes)] - extern "C" {{ - #[cfg_attr(target_arch = "arm", link_name = "{}")] - fn {}({}) -> {}; - }} -"#, - link_arm, - current_fn, - match para_num { - 1 => { - format!("a: {}, n: {}", in_t[0], const_type) - } - 2 => { - format!("a: {}, b: {}, n: {}", in_t[0], in_t[1], const_type) - } - 3 => { - format!( - "a: {}, b: {}, c: {}, n: {}", - in_t[0], in_t[1], in_t[2], const_type + let (arm_ext_inputs, arm_ext_output) = { + if let Some(const_arm) = const_arm { + if matches!(fn_type, Fntype::Load) { + let sub_type = type_to_sub_type(in_t[1]); + let inputs = match type_sub_len(in_t[1]) { + 1 => format!("a: {}", sub_type), + 2 => format!("a: {}, b: {}", sub_type, sub_type,), + 3 => format!("a: {}, b: {}, c: {}", sub_type, sub_type, sub_type,), + 4 => format!( + "a: {}, b: {}, c: {}, d: {}", + sub_type, sub_type, sub_type, sub_type, + ), + _ => panic!("unknown type: {}", in_t[1]), + }; + ( + format!("ptr: *const i8, {}, n: i32, size: i32", inputs), + String::new(), + ) + } else { + let (_, const_type) = if const_arm.contains(":") { + let consts: Vec<_> = + const_arm.split(':').map(|v| v.trim().to_string()).collect(); + (consts[0].clone(), consts[1].clone()) + } else { + ( + const_arm.to_string(), + in_t[para_num as usize - 1].to_string(), ) - } - _ => unimplemented!("unknown para_num"), - }, - out_t - )); - }; - if out_t != link_arm_t[3] { - ext_c_arm.push_str(&format!( - r#"#[allow(improper_ctypes)] - extern "C" {{ - #[cfg_attr(target_arch = "arm", link_name = "{}")] - fn {}({}) -> {}; - }} -"#, - link_arm, - current_fn, - match para_num { - 1 => { - format!("a: {}", link_arm_t[0]) - } - 2 => { - format!("a: {}, b: {}", link_arm_t[0], link_arm_t[1]) - } - 3 => { - format!( + }; + ( + match para_num { + 1 => format!("a: {}, n: {}", in_t[0], const_type), + 2 => format!("a: {}, b: {}, n: {}", in_t[0], in_t[1], const_type), + 3 => format!( + "a: {}, b: {}, c: {}, n: {}", + in_t[0], in_t[1], in_t[2], const_type + ), + _ => unimplemented!("unknown para_num"), + }, + format!(" -> {}", out_t), + ) + } + } else if out_t != link_arm_t[3] { + ( + match para_num { + 1 => format!("a: {}", link_arm_t[0]), + 2 => format!("a: {}, b: {}", link_arm_t[0], link_arm_t[1]), + 3 => format!( "a: {}, b: {}, c: {}", link_arm_t[0], link_arm_t[1], link_arm_t[2] - ) - } - _ => unimplemented!("unknown para_num"), - }, - link_arm_t[3] - )); - } - if const_aarch64.is_some() { - ext_c_aarch64.push_str(&format!( - r#"#[allow(improper_ctypes)] - extern "C" {{ - #[cfg_attr(target_arch = "aarch64", link_name = "{}")] - fn {}({}) -> {}; + ), + _ => unimplemented!("unknown para_num"), + }, + format!(" -> {}", link_arm_t[3]), + ) + } else if matches!(fn_type, Fntype::Store) { + let sub_type = type_to_sub_type(in_t[1]); + let inputs = match type_sub_len(in_t[1]) { + 1 => format!("a: {}", sub_type), + 2 => format!("a: {}, b: {}", sub_type, sub_type,), + 3 => format!("a: {}, b: {}, c: {}", sub_type, sub_type, sub_type,), + 4 => format!( + "a: {}, b: {}, c: {}, d: {}", + sub_type, sub_type, sub_type, sub_type, + ), + _ => panic!("unknown type: {}", in_t[1]), + }; + ( + format!("ptr: *mut {}, {}", type_to_native_type(in_t[1]), inputs), + String::new(), + ) + } else { + (String::new(), String::new()) + } + }; + ext_c_arm.push_str(&format!( + r#"#[allow(improper_ctypes)] + extern "unadjusted" {{ + #[cfg_attr(target_arch = "arm", link_name = "{}")] + fn {}({}){}; }} "#, - link_aarch64, - current_fn, - match para_num { - 1 => { - format!("a: {}, n: i32", in_t[0]) - } - 2 => { - format!("a: {}, b: {}, n: i32", in_t[0], in_t[1]) - } - 3 => { - format!("a: {}, b: {}, c: {}, n: i32", in_t[0], in_t[1], in_t[2]) - } - _ => unimplemented!("unknown para_num"), - }, - out_t - )); - } - if out_t != link_aarch64_t[3] { - ext_c_aarch64.push_str(&format!( - r#"#[allow(improper_ctypes)] - extern "C" {{ - #[cfg_attr(target_arch = "aarch64", link_name = "{}")] - fn {}({}) -> {}; - }} -"#, - link_aarch64, - current_fn, - match para_num { - 1 => { - format!("a: {}", link_aarch64_t[0]) - } - 2 => { - format!("a: {}, b: {}", link_aarch64_t[0], link_aarch64_t[1]) - } - 3 => { - format!( + 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) { + 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,), + 2 => format!("a: {}, b: {}", sub_type, sub_type,), + 3 => format!("a: {}, b: {}, c: {}", sub_type, sub_type, sub_type,), + 4 => format!( + "a: {}, b: {}, c: {}, d: {}", + sub_type, sub_type, sub_type, sub_type, + ), + _ => panic!("unknown type: {}", in_t[1]), + }; + inputs.push_str(&format!(", n: i64, ptr: *const i8")); + (inputs, format!(" -> {}", out_t)) + } else { + ( + match para_num { + 1 => format!("a: {}, n: i32", in_t[0]), + 2 => format!("a: {}, b: {}, n: i32", in_t[0], in_t[1]), + 3 => format!("a: {}, b: {}, c: {}, n: i32", in_t[0], in_t[1], in_t[2]), + _ => unimplemented!("unknown para_num"), + }, + format!(" -> {}", out_t), + ) + } + } else if out_t != link_aarch64_t[3] { + ( + match para_num { + 1 => format!("a: {}", link_aarch64_t[0]), + 2 => format!("a: {}, b: {}", link_aarch64_t[0], link_aarch64_t[1]), + 3 => format!( "a: {}, b: {}, c: {}", link_aarch64_t[0], link_aarch64_t[1], link_aarch64_t[2] - ) - } - _ => unimplemented!("unknown para_num"), - }, - link_aarch64_t[3] - )); - } + ), + _ => unimplemented!("unknown para_num"), + }, + format!(" -> {}", link_aarch64_t[3]), + ) + } else if matches!(fn_type, Fntype::Store) { + 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,), + 2 => format!("a: {}, b: {}", sub_type, sub_type,), + 3 => format!("a: {}, b: {}, c: {}", sub_type, sub_type, sub_type,), + 4 => format!( + "a: {}, b: {}, c: {}, d: {}", + sub_type, sub_type, sub_type, sub_type, + ), + _ => panic!("unknown type: {}", in_t[1]), + }; + inputs.push_str(&format!(", ptr: *mut {}", type_to_native_type(in_t[0]))); + (inputs, String::new()) + } else { + (String::new(), String::new()) + } + }; + ext_c_aarch64.push_str(&format!( + r#"#[allow(improper_ctypes)] + extern "unadjusted" {{ + #[cfg_attr(target_arch = "aarch64", link_name = "{}")] + fn {}({}){}; + }} +"#, + link_aarch64, current_fn, aarch64_ext_inputs, aarch64_ext_output, + )); }; let const_declare = if let Some(constn) = constn { format!(r#""#, constn) @@ -1602,6 +1921,7 @@ fn gen_arm( out_t, fixed, None, + false, )); } calls @@ -1622,213 +1942,137 @@ fn gen_arm( } else { String::new() }; - let trans: [&str; 2] = if out_t == link_arm_t[3] && out_t == link_aarch64_t[3] { - ["", ""] - } else { - ["transmute(", ")"] - }; - let call = match (multi_calls.len(), para_num, fixed.len()) { - (0, 1, 0) => format!( - r#"pub unsafe fn {}{}(a: {}) -> {} {{ - {}{}(a) -}}"#, - name, const_declare, in_t[0], out_t, ext_c, current_fn, - ), - (0, 1, _) => { - let fixed: Vec = fixed.iter().take(type_len(in_t[0])).cloned().collect(); - format!( - r#"pub unsafe fn {}{}(a: {}) -> {} {{ - let b{}; - {}{}(a, transmute(b)) -}}"#, - name, - const_declare, - in_t[0], - out_t, - values(in_t[0], &fixed), - ext_c, - current_fn, - ) - } - (0, 2, _) => format!( - r#"pub unsafe fn {}{}(a: {}, b: {}) -> {} {{ - {}{}(a, b) -}}"#, - name, const_declare, in_t[0], in_t[1], out_t, ext_c, current_fn, - ), - (0, 3, _) => format!( - r#"pub unsafe fn {}{}(a: {}, b: {}, c: {}) -> {} {{ - {}{}(a, b, c) -}}"#, - name, const_declare, in_t[0], in_t[1], in_t[2], out_t, ext_c, current_fn, - ), - (_, 1, _) => format!( - r#"pub unsafe fn {}{}(a: {}) -> {} {{ - {}{} -}}"#, - name, const_declare, in_t[0], out_t, ext_c, multi_calls, - ), - (_, 2, _) => format!( - r#"pub unsafe fn {}{}(a: {}, b: {}) -> {} {{ - {}{} -}}"#, - name, const_declare, in_t[0], in_t[1], out_t, ext_c, multi_calls, - ), - (_, 3, _) => format!( - r#"pub unsafe fn {}{}(a: {}, b: {}, c: {}) -> {} {{ - {}{} -}}"#, - name, const_declare, in_t[0], in_t[1], in_t[2], out_t, ext_c, multi_calls, - ), - (_, _, _) => String::new(), - }; - let call_arm = if let Some(const_arm) = const_arm { - let cnt = if const_arm.contains(':') { - let consts: Vec<_> = const_arm.split(':').map(|v| v.trim().to_string()).collect(); - consts[0].clone() + let fn_decl = { + let fn_output = if out_t == "void" { + String::new() } else { - let const_arm = const_arm.replace("ttn", 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_arm); - } - cnt.push_str(")"); - cnt + format!("-> {} ", out_t) }; - match para_num { - 1 => format!( - r#"pub unsafe fn {}{}(a: {}) -> {} {{ - {}{}{}(a, {}) -}}"#, - name, const_declare, in_t[0], out_t, multi_calls, ext_c_arm, current_fn, cnt - ), - 2 => format!( - r#"pub unsafe fn {}{}(a: {}, b:{}) -> {} {{ - {}{}{}(a, b, {}) -}}"#, - name, - const_declare, - in_t[0], - in_t[1], - out_t, - multi_calls, - ext_c_arm, - current_fn, - cnt - ), - _ => String::new(), - } - } else if out_t != link_arm_t[3] { - match para_num { - 1 => format!( - r#"pub unsafe fn {}{}(a: {}) -> {} {{ - {}{}{}{}(a){} -}}"#, - name, - const_declare, - in_t[0], - out_t, - multi_calls, - ext_c_arm, - trans[0], - current_fn, - trans[1] - ), - 2 => format!( - r#"pub unsafe fn {}{}(a: {}, b: {}) -> {} {{ - {}{}{}{}(transmute(a), transmute(b)){} -}}"#, - name, - const_declare, - in_t[0], - in_t[1], - out_t, - multi_calls, - ext_c_arm, - trans[0], - current_fn, - trans[1], - ), - _ => String::new(), - } - } else { - String::new() + let fn_inputs = match para_num { + 1 => format!("(a: {})", in_t[0]), + 2 => format!("(a: {}, b: {})", in_t[0], in_t[1]), + 3 => format!("(a: {}, b: {}, c: {})", in_t[0], in_t[1], in_t[2]), + _ => panic!("unsupported parameter number"), + }; + format!( + "pub unsafe fn {}{}{} {}", + name, const_declare, fn_inputs, fn_output + ) }; - let call_aarch64 = if let Some(const_aarch64) = const_aarch64 { - match para_num { - 1 => format!( - r#"pub unsafe fn {}{}(a: {}) -> {} {{ - {}{}{}(a, {}) + 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) { + let subs = match type_sub_len(in_t[1]) { + 1 => "b", + 2 => "b.0, b.1", + 3 => "b.0, b.1, b.2", + 4 => "b.0, b.1, b.2, b.3", + _ => "", + }; + format!( + "{}(a as *const i8, {}, {}, {})", + current_fn, + subs, + constn.as_deref().unwrap(), + type_bits(&type_to_sub_type(in_t[1])) / 8, + ) + } else { + let cnt = if const_arm.contains(':') { + let consts: Vec<_> = + const_arm.split(':').map(|v| v.trim().to_string()).collect(); + consts[0].clone() + } else { + let const_arm = const_arm.replace("ttn", &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_arm); + } + cnt.push_str(")"); + cnt + }; + match para_num { + 1 => format!("{}(a, {})", current_fn, cnt), + 2 => format!("{}(a, b, {})", current_fn, cnt), + _ => String::new(), + } + } + } else if out_t != link_arm_t[3] { + match para_num { + 1 => format!("transmute({}(a))", current_fn,), + 2 => format!("transmute({}(transmute(a), transmute(b)))", current_fn,), + _ => String::new(), + } + } else if matches!(fn_type, Fntype::Store) { + 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), + _ => String::new(), + } + } else { + String::new() + }; + format!( + r#"{}{{ + {}{}{} }}"#, - name, - const_declare, - in_t[0], - out_t, - multi_calls, - ext_c_aarch64, - current_fn, - const_aarch64 - ), - 2 => format!( - r#"pub unsafe fn {}{}(a: {}, b: {}) -> {} {{ - {}{}{}(a, b, {}) + fn_decl, multi_calls, ext_c_arm, arm_params + ) + }; + let call_aarch64 = { + let aarch64_params = + if let (Some(const_aarch64), Some(_)) = (const_aarch64, link_aarch64) { + if matches!(fn_type, Fntype::Load) { + let subs = match type_sub_len(in_t[1]) { + 1 => "b", + 2 => "b.0, b.1", + 3 => "b.0, b.1, b.2", + 4 => "b.0, b.1, b.2, b.3", + _ => "", + }; + format!( + "{}({}, {} as i64, a as *const i8)", + current_fn, + subs, + constn.as_deref().unwrap() + ) + } else { + match para_num { + 1 => format!("{}(a, {})", current_fn, const_aarch64), + 2 => format!("{}(a, b, {})", current_fn, const_aarch64), + _ => String::new(), + } + } + } else if out_t != link_aarch64_t[3] { + match para_num { + 1 => format!("transmute({}(a))", current_fn,), + 2 => format!("transmute({}(a, b))", current_fn,), + _ => String::new(), + } + } else if matches!(fn_type, Fntype::Store) { + 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), + _ => String::new(), + } + } else { + String::new() + }; + format!( + r#"{}{{ + {}{}{} }}"#, - name, - const_declare, - in_t[0], - in_t[1], - out_t, - multi_calls, - ext_c_aarch64, - current_fn, - const_aarch64 - ), - _ => String::new(), - } - } else if out_t != link_aarch64_t[3] { - match para_num { - 1 => format!( - r#"pub unsafe fn {}{}(a: {}) -> {} {{ - {}{}{}{}(a){} -}}"#, - name, - const_declare, - in_t[0], - out_t, - multi_calls, - ext_c_aarch64, - trans[0], - current_fn, - trans[1], - ), - 2 => format!( - r#"pub unsafe fn {}{}(a: {}, b: {}) -> {} {{ - {}{}{}{}(a, b){} -}}"#, - name, - const_declare, - in_t[0], - in_t[1], - out_t, - multi_calls, - ext_c_aarch64, - trans[0], - current_fn, - trans[1], - ), - _ => String::new(), - } - } else { - String::new() - }; - let function = if (const_arm.is_some() && const_aarch64.is_some()) - || out_t != link_arm_t[3] - || out_t != link_aarch64_t[3] - { + fn_decl, multi_calls, ext_c_aarch64, aarch64_params + ) + }; format!( r#" {} @@ -1859,6 +2103,38 @@ fn gen_arm( call_aarch64, ) } else { + let call = { + let stmts = match (multi_calls.len(), para_num, fixed.len()) { + (0, 1, 0) => format!(r#"{}{}(a)"#, ext_c, current_fn,), + (0, 1, _) => { + let fixed: Vec = + fixed.iter().take(type_len(in_t[0])).cloned().collect(); + format!( + r#"let b{}; + {}{}(a, transmute(b))"#, + values(in_t[0], &fixed), + ext_c, + current_fn, + ) + } + (0, 2, _) => format!(r#"{}{}(a, b)"#, ext_c, current_fn,), + (0, 3, _) => format!(r#"{}{}(a, b, c)"#, ext_c, current_fn,), + (_, 1, _) => format!(r#"{}{}"#, ext_c, multi_calls,), + (_, 2, _) => format!(r#"{}{}"#, ext_c, multi_calls,), + (_, 3, _) => format!(r#"{}{}"#, ext_c, multi_calls,), + (_, _, _) => String::new(), + }; + if stmts != String::new() { + format!( + r#"{}{{ + {} +}}"#, + fn_decl, stmts + ) + } else { + String::new() + } + }; format!( r#" {} @@ -1880,16 +2156,19 @@ fn gen_arm( call, ) }; - let test = gen_test( - &name, - in_t, - &out_t, - current_tests, - [type_len(in_t[0]), type_len(in_t[1]), type_len(in_t[2])], - type_len(out_t), - para_num, - ); - + let test = match fn_type { + Fntype::Normal => gen_test( + &name, + in_t, + &out_t, + current_tests, + [type_len(in_t[0]), type_len(in_t[1]), type_len(in_t[2])], + type_len(out_t), + para_num, + ), + 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])), + }; (function, test) } @@ -2010,6 +2289,7 @@ fn get_call( out_t: &str, fixed: &Vec, n: Option, + aarch64: bool, ) -> String { let params: Vec<_> = in_str.split(',').map(|v| v.trim().to_string()).collect(); assert!(params.len() > 0); @@ -2177,7 +2457,8 @@ fn get_call( in_t, out_t, fixed, - Some(i as i32) + Some(i as i32), + aarch64 ) ); call.push_str(&sub_match); @@ -2226,6 +2507,7 @@ fn get_call( out_t, fixed, n.clone(), + aarch64, ); if !param_str.is_empty() { param_str.push_str(", "); @@ -2296,6 +2578,11 @@ fn get_call( fn_name.push_str(type_to_suffix(in_t[1])); } else if fn_format[1] == "nself" { fn_name.push_str(type_to_n_suffix(in_t[1])); + } else if fn_format[1] == "nselfvfp4" { + fn_name.push_str(type_to_n_suffix(in_t[1])); + if !aarch64 { + fn_name.push_str("_vfp4"); + } } else if fn_format[1] == "out" { fn_name.push_str(type_to_suffix(out_t)); } else if fn_format[1] == "in0" { @@ -2305,7 +2592,21 @@ fn get_call( } else if fn_format[1] == "in2lane" { fn_name.push_str(&type_to_lane_suffixes(out_t, in_t[2])); } else if fn_format[1] == "signed" { - fn_name.push_str(type_to_suffix(type_to_signed(in_t[1]))); + fn_name.push_str(type_to_suffix(&type_to_signed(&String::from(in_t[1])))); + } else if fn_format[1] == "outsigned" { + fn_name.push_str(type_to_suffix(&type_to_signed(&String::from(out_t)))); + } else if fn_format[1] == "outsignednox" { + fn_name.push_str(&type_to_suffix(&type_to_sub_type(&type_to_signed( + &String::from(out_t), + )))); + } 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), + )))); + } else if fn_format[1] == "outsignedlanenox" { + fn_name.push_str(&type_to_lane_suffix(&type_to_sub_type(&type_to_signed( + &String::from(out_t), + )))); } else if fn_format[1] == "unsigned" { fn_name.push_str(type_to_suffix(type_to_unsigned(in_t[1]))); } else if fn_format[1] == "doubleself" { @@ -2315,7 +2616,7 @@ fn get_call( } else if fn_format[1] == "noqself" { fn_name.push_str(type_to_noq_suffix(in_t[1])); } else if fn_format[1] == "noqsigned" { - fn_name.push_str(type_to_noq_suffix(type_to_signed(in_t[1]))); + fn_name.push_str(type_to_noq_suffix(&type_to_signed(&String::from(in_t[1])))); } else if fn_format[1] == "nosuffix" { } else if fn_format[1] == "in_len" { fn_name.push_str(&type_len(in_t[1]).to_string()); @@ -2330,7 +2631,7 @@ fn get_call( } else if fn_format[1] == "nin0" { fn_name.push_str(type_to_n_suffix(in_t[0])); } else if fn_format[1] == "nsigned" { - fn_name.push_str(type_to_n_suffix(type_to_signed(in_t[1]))); + fn_name.push_str(type_to_n_suffix(&type_to_signed(&String::from(in_t[1])))); } else if fn_format[1] == "in_ntt" { fn_name.push_str(type_to_suffix(native_type_to_type(in_t[1]))); } else if fn_format[1] == "out_ntt" { @@ -2351,14 +2652,14 @@ fn get_call( let type1 = if types[0] == "element_t" { type_to_native_type(in_t[1]) } else { - &types[0] + String::from(&types[0]) }; let type2 = if types[1] == "element_t" { type_to_native_type(in_t[1]) } else { - &types[1] + String::from(&types[1]) }; - fn_name.push_str(&format!("::<{}, {}>", type1, type2)); + fn_name.push_str(&format!("::<{}, {}>", &type1, &type2)); } else { fn_name.push_str(&fn_format[2]); } @@ -2410,6 +2711,8 @@ fn main() -> io::Result<()> { )> = Vec::new(); let mut multi_fn: Vec = Vec::new(); let mut target: TargetFeature = Default; + let mut fn_type: Fntype = Fntype::Normal; + let mut separate = false; // // THIS FILE IS GENERATED FORM neon.spec DO NOT CHANGE IT MANUALLY @@ -2491,6 +2794,8 @@ mod test { n = None; multi_fn = Vec::new(); target = Default; + fn_type = Fntype::Normal; + separate = false; } else if line.starts_with("//") { } else if line.starts_with("name = ") { current_name = Some(String::from(&line[7..])); @@ -2520,6 +2825,12 @@ mod test { suffix = NoQNSuffix; } else if line.starts_with("out-suffix") { suffix = OutSuffix; + } else if line.starts_with("out-nox") { + suffix = OutNox; + } 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("lane-suffixes") { suffix = Lane; } else if line.starts_with("in2-suffix") { @@ -2547,10 +2858,17 @@ mod test { link_arm = Some(String::from(&line[11..])); } else if line.starts_with("const-arm = ") { const_arm = Some(String::from(&line[12..])); + } else if line.starts_with("load_fn") { + fn_type = Fntype::Load; + } else if line.starts_with("store_fn") { + fn_type = Fntype::Store; + } else if line.starts_with("arm-aarch64-separate") { + separate = true; } else if line.starts_with("target = ") { target = match Some(String::from(&line[9..])) { Some(input) => match input.as_str() { "v7" => ArmV7, + "vfp4" => Vfp4, "fp-armv8" => FPArmV8, "aes" => AES, _ => Default, @@ -2593,7 +2911,11 @@ mod test { panic!("Bad spec: {}", line) } if b.len() == 0 { - para_num = 1; + if matches!(fn_type, Fntype::Store) { + para_num = 2; + } else { + para_num = 1; + } } else if c.len() != 0 { para_num = 3; } @@ -2618,6 +2940,8 @@ mod test { target, &fixed, &multi_fn, + fn_type, + separate, ); out_arm.push_str(&function); tests_arm.push_str(&test); @@ -2638,6 +2962,7 @@ mod test { target, &fixed, &multi_fn, + fn_type, ); out_aarch64.push_str(&function); tests_aarch64.push_str(&test); diff --git a/library/stdarch/crates/stdarch-test/src/disassembly.rs b/library/stdarch/crates/stdarch-test/src/disassembly.rs index 38ebce75f7..3ace6b20e1 100644 --- a/library/stdarch/crates/stdarch-test/src/disassembly.rs +++ b/library/stdarch/crates/stdarch-test/src/disassembly.rs @@ -67,25 +67,18 @@ pub(crate) fn disassemble_myself() -> HashSet { String::from_utf8_lossy(Vec::leak(output.stdout)) } else if cfg!(target_os = "windows") { panic!("disassembly unimplemented") - } else if cfg!(target_os = "macos") { - let output = Command::new("otool") - .arg("-vt") - .arg(&me) - .output() - .expect("failed to execute otool"); - println!( - "{}\n{}", - output.status, - String::from_utf8_lossy(&output.stderr) - ); - assert!(output.status.success()); - - String::from_utf8_lossy(Vec::leak(output.stdout)) } else { let objdump = env::var("OBJDUMP").unwrap_or_else(|_| "objdump".to_string()); + let add_args = if cfg!(target_os = "macos") && cfg!(target_arch = "aarch64") { + // Target features need to be enabled for LLVM objdump on Macos ARM64 + vec!["--mattr=+v8.6a,+crypto,+tme"] + } else { + vec![] + }; let output = Command::new(objdump.clone()) .arg("--disassemble") .arg("--no-show-raw-insn") + .args(add_args) .arg(&me) .output() .unwrap_or_else(|_| panic!("failed to execute objdump. OBJDUMP={}", objdump)); @@ -132,16 +125,7 @@ fn parse(output: &str) -> HashSet { cached_header = None; break; } - let parts = if cfg!(target_os = "macos") { - // Each line of instructions should look like: - // - // $addr $instruction... - instruction - .split_whitespace() - .skip(1) - .map(std::string::ToString::to_string) - .collect::>() - } else if cfg!(target_env = "msvc") { + let mut parts = if cfg!(target_env = "msvc") { // Each line looks like: // // > $addr: ab cd ef $instr.. @@ -168,6 +152,29 @@ fn parse(output: &str) -> HashSet { .map(std::string::ToString::to_string) .collect::>() }; + + if cfg!(target_arch = "aarch64") { + // Normalize [us]shll.* ..., #0 instructions to the preferred form: [us]xtl.* ... + // as LLVM objdump does not do that. + // See https://developer.arm.com/documentation/ddi0602/latest/SIMD-FP-Instructions/UXTL--UXTL2--Unsigned-extend-Long--an-alias-of-USHLL--USHLL2- + // and https://developer.arm.com/documentation/ddi0602/latest/SIMD-FP-Instructions/SXTL--SXTL2--Signed-extend-Long--an-alias-of-SSHLL--SSHLL2- + // for details. + match (parts.first(), parts.last()) { + (Some(instr), Some(last_arg)) + if (instr.starts_with("ushll.") || instr.starts_with("sshll.")) + && last_arg == "#0" => + { + assert_eq!(parts.len(), 4); + let mut new_parts = Vec::with_capacity(3); + let new_instr = format!("{}{}{}", &instr[..1], "xtl", &instr[5..]); + new_parts.push(new_instr); + new_parts.push(parts[1].clone()); + new_parts.push(parts[2][0..parts[2].len() - 1].to_owned()); // strip trailing comma + parts = new_parts; + } + _ => {} + }; + } instructions.push(parts.join(" ")); } let function = Function { diff --git a/library/stdarch/crates/stdarch-test/src/lib.rs b/library/stdarch/crates/stdarch-test/src/lib.rs index 10834c00e7..15ff9595af 100644 --- a/library/stdarch/crates/stdarch-test/src/lib.rs +++ b/library/stdarch/crates/stdarch-test/src/lib.rs @@ -14,7 +14,7 @@ extern crate cfg_if; pub use assert_instr_macro::*; pub use simd_test_macro::*; -use std::{cmp, collections::HashSet, env, hash, hint::black_box, str, sync::atomic::AtomicPtr}; +use std::{cmp, collections::HashSet, env, hash, hint::black_box, str}; cfg_if! { if #[cfg(target_arch = "wasm32")] { @@ -76,31 +76,36 @@ pub fn assert(shim_addr: usize, fnname: &str, expected: &str) { instrs = &instrs[..instrs.len() - 1]; } + // Look for `expected` as the first part of any instruction in this + // function, e.g., tzcntl in tzcntl %rax,%rax. + // // There are two cases when the expected instruction is nop: // 1. The expected intrinsic is compiled away so we can't // check for it - aka the intrinsic is not generating any code. // 2. It is a mark, indicating that the instruction will be // compiled into other instructions - mainly because of llvm // optimization. - if expected == "nop" { - return; - } + let found = expected == "nop" || instrs.iter().any(|s| s.starts_with(expected)); - // Look for `expected` as the first part of any instruction in this - // function, e.g., tzcntl in tzcntl %rax,%rax. - let found = instrs.iter().any(|s| s.starts_with(expected)); - - // Look for `call` instructions in the disassembly to detect whether - // inlining failed: all intrinsics are `#[inline(always)]`, so - // calling one intrinsic from another should not generate `call` - // instructions. - let inlining_failed = instrs.windows(2).any(|s| { - // On 32-bit x86 position independent code will call itself and be - // immediately followed by a `pop` to learn about the current address. - // Let's not take that into account when considering whether a function - // failed inlining something. - s[0].contains("call") && (!cfg!(target_arch = "x86") || s[1].contains("pop")) - }); + // Look for subroutine call instructions in the disassembly to detect whether + // inlining failed: all intrinsics are `#[inline(always)]`, so calling one + // intrinsic from another should not generate subroutine call instructions. + let inlining_failed = if cfg!(target_arch = "x86_64") || cfg!(target_arch = "wasm32") { + instrs.iter().any(|s| s.starts_with("call ")) + } else if cfg!(target_arch = "x86") { + instrs.windows(2).any(|s| { + // On 32-bit x86 position independent code will call itself and be + // immediately followed by a `pop` to learn about the current address. + // Let's not take that into account when considering whether a function + // failed inlining something. + s[0].starts_with("call ") && s[1].starts_with("pop") // FIXME: original logic but does not match comment + }) + } else if cfg!(target_arch = "aarch64") { + instrs.iter().any(|s| s.starts_with("bl ")) + } else { + // FIXME: Add detection for other archs + false + }; let instruction_limit = std::env::var("STDARCH_ASSERT_INSTR_LIMIT") .ok() @@ -124,6 +129,9 @@ pub fn assert(shim_addr: usize, fnname: &str, expected: &str) { // vfmaq_n_f32_vfma : #instructions = 26 >= 22 (limit) "usad8" | "vfma" | "vfms" => 27, "qadd8" | "qsub8" | "sadd8" | "sel" | "shadd8" | "shsub8" | "usub8" | "ssub8" => 29, + // core_arch/src/arm_shared/simd32 + // vst1q_s64_x4_vst1 : #instructions = 40 >= 22 (limit) + "vst1" => 41, // Temporary, currently the fptosi.sat and fptoui.sat LLVM // intrinsics emit unnecessary code on arm. This can be @@ -164,8 +172,8 @@ pub fn assert(shim_addr: usize, fnname: &str, expected: &str) { ); } else if inlining_failed { panic!( - "instruction found, but the disassembly contains `call` \ - instructions, which hint that inlining failed" + "instruction found, but the disassembly contains subroutine \ + call instructions, which hint that inlining failed" ); } } @@ -178,4 +186,4 @@ pub fn assert_skip_test_ok(name: &str) { } // See comment in `assert-instr-macro` crate for why this exists -pub static _DONT_DEDUP: AtomicPtr = AtomicPtr::new(b"".as_ptr() as *mut _); +pub static mut _DONT_DEDUP: *const u8 = std::ptr::null(); diff --git a/library/stdarch/crates/stdarch-verify/src/lib.rs b/library/stdarch/crates/stdarch-verify/src/lib.rs index e85f0489a8..22108d26a1 100644 --- a/library/stdarch/crates/stdarch-verify/src/lib.rs +++ b/library/stdarch/crates/stdarch-verify/src/lib.rs @@ -15,7 +15,14 @@ pub fn x86_functions(input: TokenStream) -> TokenStream { #[proc_macro] pub fn arm_functions(input: TokenStream) -> TokenStream { - functions(input, &["core_arch/src/arm", "core_arch/src/aarch64"]) + functions( + input, + &[ + "core_arch/src/arm", + "core_arch/src/aarch64", + "core_arch/src/arm_shared/neon", + ], + ) } #[proc_macro] @@ -218,11 +225,29 @@ fn to_type(t: &syn::Type) -> proc_macro2::TokenStream { "int8x16_t" => quote! { &I8X16 }, "int16x2_t" => quote! { &I16X2 }, "int16x4_t" => quote! { &I16X4 }, + "int16x4x2_t" => quote! { &I16X4X2 }, + "int16x4x3_t" => quote! { &I16X4X3 }, + "int16x4x4_t" => quote! { &I16X4X4 }, "int16x8_t" => quote! { &I16X8 }, + "int16x8x2_t" => quote! { &I16X8X2 }, + "int16x8x3_t" => quote! { &I16X8X3 }, + "int16x8x4_t" => quote! { &I16X8X4 }, "int32x2_t" => quote! { &I32X2 }, + "int32x2x2_t" => quote! { &I32X2X2 }, + "int32x2x3_t" => quote! { &I32X2X3 }, + "int32x2x4_t" => quote! { &I32X2X4 }, "int32x4_t" => quote! { &I32X4 }, + "int32x4x2_t" => quote! { &I32X4X2 }, + "int32x4x3_t" => quote! { &I32X4X3 }, + "int32x4x4_t" => quote! { &I32X4X4 }, "int64x1_t" => quote! { &I64X1 }, + "int64x1x2_t" => quote! { &I64X1X2 }, + "int64x1x3_t" => quote! { &I64X1X3 }, + "int64x1x4_t" => quote! { &I64X1X4 }, "int64x2_t" => quote! { &I64X2 }, + "int64x2x2_t" => quote! { &I64X2X2 }, + "int64x2x3_t" => quote! { &I64X2X3 }, + "int64x2x4_t" => quote! { &I64X2X4 }, "uint8x8_t" => quote! { &U8X8 }, "uint8x4_t" => quote! { &U8X4 }, "uint8x8x2_t" => quote! { &U8X8X2 }, @@ -233,15 +258,45 @@ fn to_type(t: &syn::Type) -> proc_macro2::TokenStream { "uint8x8x4_t" => quote! { &U8X8X4 }, "uint8x16_t" => quote! { &U8X16 }, "uint16x4_t" => quote! { &U16X4 }, + "uint16x4x2_t" => quote! { &U16X4X2 }, + "uint16x4x3_t" => quote! { &U16X4X3 }, + "uint16x4x4_t" => quote! { &U16X4X4 }, "uint16x8_t" => quote! { &U16X8 }, + "uint16x8x2_t" => quote! { &U16X8X2 }, + "uint16x8x3_t" => quote! { &U16X8X3 }, + "uint16x8x4_t" => quote! { &U16X8X4 }, "uint32x2_t" => quote! { &U32X2 }, + "uint32x2x2_t" => quote! { &U32X2X2 }, + "uint32x2x3_t" => quote! { &U32X2X3 }, + "uint32x2x4_t" => quote! { &U32X2X4 }, "uint32x4_t" => quote! { &U32X4 }, + "uint32x4x2_t" => quote! { &U32X4X2 }, + "uint32x4x3_t" => quote! { &U32X4X3 }, + "uint32x4x4_t" => quote! { &U32X4X4 }, "uint64x1_t" => quote! { &U64X1 }, + "uint64x1x2_t" => quote! { &U64X1X2 }, + "uint64x1x3_t" => quote! { &U64X1X3 }, + "uint64x1x4_t" => quote! { &U64X1X4 }, "uint64x2_t" => quote! { &U64X2 }, + "uint64x2x2_t" => quote! { &U64X2X2 }, + "uint64x2x3_t" => quote! { &U64X2X3 }, + "uint64x2x4_t" => quote! { &U64X2X4 }, "float32x2_t" => quote! { &F32X2 }, + "float32x2x2_t" => quote! { &F32X2X2 }, + "float32x2x3_t" => quote! { &F32X2X3 }, + "float32x2x4_t" => quote! { &F32X2X4 }, "float32x4_t" => quote! { &F32X4 }, + "float32x4x2_t" => quote! { &F32X4X2 }, + "float32x4x3_t" => quote! { &F32X4X3 }, + "float32x4x4_t" => quote! { &F32X4X4 }, "float64x1_t" => quote! { &F64X1 }, + "float64x1x2_t" => quote! { &F64X1X2 }, + "float64x1x3_t" => quote! { &F64X1X3 }, + "float64x1x4_t" => quote! { &F64X1X4 }, "float64x2_t" => quote! { &F64X2 }, + "float64x2x2_t" => quote! { &F64X2X2 }, + "float64x2x3_t" => quote! { &F64X2X3 }, + "float64x2x4_t" => quote! { &F64X2X4 }, "poly8x8_t" => quote! { &POLY8X8 }, "poly8x8x2_t" => quote! { &POLY8X8X2 }, "poly8x8x3_t" => quote! { &POLY8X8X3 }, @@ -254,7 +309,19 @@ fn to_type(t: &syn::Type) -> proc_macro2::TokenStream { "poly64x2_t" => quote! { &POLY64X2 }, "poly8x16_t" => quote! { &POLY8X16 }, "poly16x4_t" => quote! { &POLY16X4 }, + "poly16x4x2_t" => quote! { &P16X4X2 }, + "poly16x4x3_t" => quote! { &P16X4X3 }, + "poly16x4x4_t" => quote! { &P16X4X4 }, "poly16x8_t" => quote! { &POLY16X8 }, + "poly16x8x2_t" => quote! { &P16X8X2 }, + "poly16x8x3_t" => quote! { &P16X8X3 }, + "poly16x8x4_t" => quote! { &P16X8X4 }, + "poly64x1x2_t" => quote! { &P64X1X2 }, + "poly64x1x3_t" => quote! { &P64X1X3 }, + "poly64x1x4_t" => quote! { &P64X1X4 }, + "poly64x2x2_t" => quote! { &P64X2X2 }, + "poly64x2x3_t" => quote! { &P64X2X3 }, + "poly64x2x4_t" => quote! { &P64X2X4 }, "p128" => quote! { &P128 }, "v16i8" => quote! { &v16i8 }, diff --git a/library/stdarch/crates/stdarch-verify/tests/arm.rs b/library/stdarch/crates/stdarch-verify/tests/arm.rs index da17eb313c..9047a08ef7 100644 --- a/library/stdarch/crates/stdarch-verify/tests/arm.rs +++ b/library/stdarch/crates/stdarch-verify/tests/arm.rs @@ -411,65 +411,6 @@ fn verify_all_signatures() { "__smusdx", "__usad8", "__usada8", - "vld1_s8", - "vld1q_s8", - "vld1q_s8", - "vld1_s16", - "vld1q_s16", - "vld1_s32", - "vld1q_s32", - "vld1_s64", - "vld1q_s64", - "vld1_u8", - "vld1q_u8", - "vld1_u16", - "vld1q_u16", - "vld1_u32", - "vld1q_u32", - "vld1_u64", - "vld1q_u64", - "vld1_p8", - "vld1q_p8", - "vld1_p16", - "vld1q_p16", - "vld1_f32", - "vld1q_f32", - "vld1_f64", - "vld1q_f64", - "vst1_s8", - "vst1q_s8", - "vst1_s16", - "vst1q_s16", - "vst1_s32", - "vst1q_s32", - "vst1_s64", - "vst1q_s64", - "vst1_u8", - "vst1q_u8", - "vst1_u16", - "vst1q_u16", - "vst1_u32", - "vst1q_u32", - "vst1_u64", - "vst1q_u64", - "vst1_p8", - "vst1q_p8", - "vst1_p16", - "vst1q_p16", - "vst1_f32", - "vst1q_f32", - "vpadal_s8", - "vpadal_s16", - "vpadal_s32", - "vpadalq_s8", - "vpadalq_s16", - "vpadalq_s32", - "vpadal_u8", - "vpadal_u16", - "vpadal_u32", - "vpadalq_u8", - "vpadalq_u16", - "vpadalq_u32", "__ldrex", "__strex", "__ldrexb", @@ -515,12 +456,36 @@ fn verify_all_signatures() { "vqrdmlahh_laneq_s16", "vqrdmlahs_lane_s32", "vqrdmlahs_laneq_s32", + "vqrdmlah_s16", + "vqrdmlah_s32", + "vqrdmlahq_s16", + "vqrdmlahq_s32", + "vqrdmlah_lane_s16", + "vqrdmlah_laneq_s16", + "vqrdmlahq_lane_s16", + "vqrdmlahq_laneq_s16", + "vqrdmlah_lane_s32", + "vqrdmlah_laneq_s32", + "vqrdmlahq_lane_s32", + "vqrdmlahq_laneq_s32", "vqrdmlshh_s16", "vqrdmlshs_s32", "vqrdmlshh_lane_s16", "vqrdmlshh_laneq_s16", "vqrdmlshs_lane_s32", "vqrdmlshs_laneq_s32", + "vqrdmlsh_s16", + "vqrdmlshq_s16", + "vqrdmlsh_s32", + "vqrdmlshq_s32", + "vqrdmlsh_lane_s16", + "vqrdmlsh_laneq_s16", + "vqrdmlshq_lane_s16", + "vqrdmlshq_laneq_s16", + "vqrdmlsh_lane_s32", + "vqrdmlsh_laneq_s32", + "vqrdmlshq_lane_s32", + "vqrdmlshq_laneq_s32", "__dbg", ]; let arm = match map.get(rust.name) { diff --git a/library/test/Cargo.toml b/library/test/Cargo.toml index 80d6072e9b..04dab6b804 100644 --- a/library/test/Cargo.toml +++ b/library/test/Cargo.toml @@ -33,3 +33,4 @@ panic_immediate_abort = ["std/panic_immediate_abort"] profiler = ["std/profiler"] std_detect_file_io = ["std/std_detect_file_io"] std_detect_dlsym_getauxval = ["std/std_detect_dlsym_getauxval"] +std_detect_env_override = ["std/std_detect_env_override"] diff --git a/library/test/src/cli.rs b/library/test/src/cli.rs index 84874a2d22..cb40b4e965 100644 --- a/library/test/src/cli.rs +++ b/library/test/src/cli.rs @@ -21,6 +21,8 @@ pub struct TestOpts { pub nocapture: bool, pub color: ColorConfig, pub format: OutputFormat, + pub shuffle: bool, + pub shuffle_seed: Option, pub test_threads: Option, pub skip: Vec, pub time_options: Option, @@ -138,6 +140,13 @@ fn optgroups() -> getopts::Options { `CRITICAL_TIME` here means the limit that should not be exceeded by test. ", + ) + .optflag("", "shuffle", "Run tests in random order") + .optopt( + "", + "shuffle-seed", + "Run tests in random order; seed the random number generator with SEED", + "SEED", ); opts } @@ -155,6 +164,12 @@ By default, all tests are run in parallel. This can be altered with the --test-threads flag or the RUST_TEST_THREADS environment variable when running tests (set it to 1). +By default, the tests are run in alphabetical order. Use --shuffle or set +RUST_TEST_SHUFFLE to run the tests in random order. Pass the generated +"shuffle seed" to --shuffle-seed (or set RUST_TEST_SHUFFLE_SEED) to run the +tests in the same order again. Note that --shuffle and --shuffle-seed do not +affect whether the tests are run in parallel. + All tests have their standard output and standard error captured by default. This can be overridden with the --nocapture flag or setting RUST_TEST_NOCAPTURE environment variable to a value other than "0". Logging is not captured by default. @@ -218,6 +233,21 @@ macro_rules! unstable_optflag { }}; } +// Gets the option value and checks if unstable features are enabled. +macro_rules! unstable_optopt { + ($matches:ident, $allow_unstable:ident, $option_name:literal) => {{ + let opt = $matches.opt_str($option_name); + if !$allow_unstable && opt.is_some() { + return Err(format!( + "The \"{}\" option is only accepted on the nightly compiler with -Z unstable-options", + $option_name + )); + } + + opt + }}; +} + // Implementation of `parse_opts` that doesn't care about help message // and returns a `Result`. fn parse_opts_impl(matches: getopts::Matches) -> OptRes { @@ -227,6 +257,8 @@ fn parse_opts_impl(matches: getopts::Matches) -> OptRes { let force_run_in_process = unstable_optflag!(matches, allow_unstable, "force-run-in-process"); let exclude_should_panic = unstable_optflag!(matches, allow_unstable, "exclude-should-panic"); let time_options = get_time_options(&matches, allow_unstable)?; + let shuffle = get_shuffle(&matches, allow_unstable)?; + let shuffle_seed = get_shuffle_seed(&matches, allow_unstable)?; let include_ignored = matches.opt_present("include-ignored"); let quiet = matches.opt_present("quiet"); @@ -260,6 +292,8 @@ fn parse_opts_impl(matches: getopts::Matches) -> OptRes { nocapture, color, format, + shuffle, + shuffle_seed, test_threads, skip, time_options, @@ -303,6 +337,46 @@ fn get_time_options( Ok(options) } +fn get_shuffle(matches: &getopts::Matches, allow_unstable: bool) -> OptPartRes { + let mut shuffle = unstable_optflag!(matches, allow_unstable, "shuffle"); + if !shuffle && allow_unstable { + shuffle = match env::var("RUST_TEST_SHUFFLE") { + Ok(val) => &val != "0", + Err(_) => false, + }; + } + + Ok(shuffle) +} + +fn get_shuffle_seed(matches: &getopts::Matches, allow_unstable: bool) -> OptPartRes> { + let mut shuffle_seed = match unstable_optopt!(matches, allow_unstable, "shuffle-seed") { + Some(n_str) => match n_str.parse::() { + Ok(n) => Some(n), + Err(e) => { + return Err(format!( + "argument for --shuffle-seed must be a number \ + (error: {})", + e + )); + } + }, + None => None, + }; + + if shuffle_seed.is_none() && allow_unstable { + shuffle_seed = match env::var("RUST_TEST_SHUFFLE_SEED") { + Ok(val) => match val.parse::() { + Ok(n) => Some(n), + Err(_) => panic!("RUST_TEST_SHUFFLE_SEED is `{}`, should be a number.", val), + }, + Err(_) => None, + }; + } + + Ok(shuffle_seed) +} + fn get_test_threads(matches: &getopts::Matches) -> OptPartRes> { let test_threads = match matches.opt_str("test-threads") { Some(n_str) => match n_str.parse::() { diff --git a/library/test/src/console.rs b/library/test/src/console.rs index 54e30a1fcd..11c5ab48ed 100644 --- a/library/test/src/console.rs +++ b/library/test/src/console.rs @@ -225,9 +225,9 @@ fn on_test_event( out: &mut dyn OutputFormatter, ) -> io::Result<()> { match (*event).clone() { - TestEvent::TeFiltered(ref filtered_tests) => { + TestEvent::TeFiltered(ref filtered_tests, shuffle_seed) => { st.total = filtered_tests.len(); - out.write_run_start(filtered_tests.len())?; + out.write_run_start(filtered_tests.len(), shuffle_seed)?; } TestEvent::TeFilteredOut(filtered_out) => { st.filtered_out = filtered_out; diff --git a/library/test/src/event.rs b/library/test/src/event.rs index 206f3e10e8..6ff1a615eb 100644 --- a/library/test/src/event.rs +++ b/library/test/src/event.rs @@ -28,7 +28,7 @@ impl CompletedTest { #[derive(Debug, Clone)] pub enum TestEvent { - TeFiltered(Vec), + TeFiltered(Vec, Option), TeWait(TestDesc), TeResult(CompletedTest), TeTimeout(TestDesc), diff --git a/library/test/src/formatters/json.rs b/library/test/src/formatters/json.rs index 57b6d1a020..424d3ef7b4 100644 --- a/library/test/src/formatters/json.rs +++ b/library/test/src/formatters/json.rs @@ -60,10 +60,15 @@ impl JsonFormatter { } impl OutputFormatter for JsonFormatter { - fn write_run_start(&mut self, test_count: usize) -> io::Result<()> { + fn write_run_start(&mut self, test_count: usize, shuffle_seed: Option) -> io::Result<()> { + let shuffle_seed_json = if let Some(shuffle_seed) = shuffle_seed { + format!(r#", "shuffle_seed": {}"#, shuffle_seed) + } else { + String::new() + }; self.writeln_message(&*format!( - r#"{{ "type": "suite", "event": "started", "test_count": {} }}"#, - test_count + r#"{{ "type": "suite", "event": "started", "test_count": {}{} }}"#, + test_count, shuffle_seed_json )) } diff --git a/library/test/src/formatters/junit.rs b/library/test/src/formatters/junit.rs index c4b0e1e5c2..e2aebee916 100644 --- a/library/test/src/formatters/junit.rs +++ b/library/test/src/formatters/junit.rs @@ -27,9 +27,14 @@ impl JunitFormatter { } impl OutputFormatter for JunitFormatter { - fn write_run_start(&mut self, _test_count: usize) -> io::Result<()> { + fn write_run_start( + &mut self, + _test_count: usize, + _shuffle_seed: Option, + ) -> io::Result<()> { // We write xml header on run start - self.write_message(&"") + self.out.write_all(b"\n")?; + self.write_message("") } fn write_test_start(&mut self, _desc: &TestDesc) -> io::Result<()> { @@ -53,7 +58,7 @@ impl OutputFormatter for JunitFormatter { // 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 // them to a Vec and write them all at once when run is complete. - let duration = exec_time.map(|t| t.0.clone()).unwrap_or_default(); + let duration = exec_time.map(|t| t.0).unwrap_or_default(); self.results.push((desc.clone(), result.clone(), duration)); Ok(()) } @@ -133,6 +138,8 @@ impl OutputFormatter for JunitFormatter { self.write_message("")?; self.write_message("")?; + self.out.write_all(b"\n\n")?; + Ok(state.failed == 0) } } diff --git a/library/test/src/formatters/mod.rs b/library/test/src/formatters/mod.rs index 2e03581b3a..cb80859759 100644 --- a/library/test/src/formatters/mod.rs +++ b/library/test/src/formatters/mod.rs @@ -18,7 +18,7 @@ pub(crate) use self::pretty::PrettyFormatter; pub(crate) use self::terse::TerseFormatter; pub(crate) trait OutputFormatter { - fn write_run_start(&mut self, test_count: usize) -> io::Result<()>; + fn write_run_start(&mut self, test_count: usize, shuffle_seed: Option) -> io::Result<()>; fn write_test_start(&mut self, desc: &TestDesc) -> io::Result<()>; fn write_timeout(&mut self, desc: &TestDesc) -> io::Result<()>; fn write_result( diff --git a/library/test/src/formatters/pretty.rs b/library/test/src/formatters/pretty.rs index 9cad71e30b..4a03b4b914 100644 --- a/library/test/src/formatters/pretty.rs +++ b/library/test/src/formatters/pretty.rs @@ -181,9 +181,14 @@ impl PrettyFormatter { } impl OutputFormatter for PrettyFormatter { - fn write_run_start(&mut self, test_count: usize) -> io::Result<()> { + fn write_run_start(&mut self, test_count: usize, shuffle_seed: Option) -> io::Result<()> { let noun = if test_count != 1 { "tests" } else { "test" }; - self.write_plain(&format!("\nrunning {} {}\n", test_count, noun)) + let shuffle_seed_msg = if let Some(shuffle_seed) = shuffle_seed { + format!(" (shuffle seed: {})", shuffle_seed) + } else { + String::new() + }; + self.write_plain(&format!("\nrunning {} {}{}\n", test_count, noun, shuffle_seed_msg)) } fn write_test_start(&mut self, desc: &TestDesc) -> io::Result<()> { diff --git a/library/test/src/formatters/terse.rs b/library/test/src/formatters/terse.rs index 0c8215c5da..1f2c410cd9 100644 --- a/library/test/src/formatters/terse.rs +++ b/library/test/src/formatters/terse.rs @@ -170,10 +170,15 @@ impl TerseFormatter { } impl OutputFormatter for TerseFormatter { - fn write_run_start(&mut self, test_count: usize) -> io::Result<()> { + fn write_run_start(&mut self, test_count: usize, shuffle_seed: Option) -> io::Result<()> { self.total_test_count = test_count; let noun = if test_count != 1 { "tests" } else { "test" }; - self.write_plain(&format!("\nrunning {} {}\n", test_count, noun)) + let shuffle_seed_msg = if let Some(shuffle_seed) = shuffle_seed { + format!(" (shuffle seed: {})", shuffle_seed) + } else { + String::new() + }; + self.write_plain(&format!("\nrunning {} {}{}\n", test_count, noun, shuffle_seed_msg)) } fn write_test_start(&mut self, desc: &TestDesc) -> io::Result<()> { diff --git a/library/test/src/helpers/concurrency.rs b/library/test/src/helpers/concurrency.rs index c39a9b0ec0..e25f524ec0 100644 --- a/library/test/src/helpers/concurrency.rs +++ b/library/test/src/helpers/concurrency.rs @@ -9,6 +9,6 @@ pub fn get_concurrency() -> usize { _ => panic!("RUST_TEST_THREADS is `{}`, should be a positive integer.", value), } } else { - thread::available_concurrency().map(|n| n.get()).unwrap_or(1) + thread::available_parallelism().map(|n| n.get()).unwrap_or(1) } } diff --git a/library/test/src/helpers/mod.rs b/library/test/src/helpers/mod.rs index b7f00c4c86..049cadf86a 100644 --- a/library/test/src/helpers/mod.rs +++ b/library/test/src/helpers/mod.rs @@ -5,3 +5,4 @@ pub mod concurrency; pub mod exit_code; pub mod isatty; pub mod metrics; +pub mod shuffle; diff --git a/library/test/src/helpers/shuffle.rs b/library/test/src/helpers/shuffle.rs new file mode 100644 index 0000000000..ca503106c5 --- /dev/null +++ b/library/test/src/helpers/shuffle.rs @@ -0,0 +1,67 @@ +use crate::cli::TestOpts; +use crate::types::{TestDescAndFn, TestId, TestName}; +use std::collections::hash_map::DefaultHasher; +use std::hash::Hasher; +use std::time::{SystemTime, UNIX_EPOCH}; + +pub fn get_shuffle_seed(opts: &TestOpts) -> Option { + opts.shuffle_seed.or_else(|| { + if opts.shuffle { + Some( + SystemTime::now() + .duration_since(UNIX_EPOCH) + .expect("Failed to get system time") + .as_nanos() as u64, + ) + } else { + None + } + }) +} + +pub fn shuffle_tests(shuffle_seed: u64, tests: &mut [(TestId, TestDescAndFn)]) { + let test_names: Vec<&TestName> = tests.iter().map(|test| &test.1.desc.name).collect(); + let test_names_hash = calculate_hash(&test_names); + let mut rng = Rng::new(shuffle_seed, test_names_hash); + shuffle(&mut rng, tests); +} + +// `shuffle` is from `rust-analyzer/src/cli/analysis_stats.rs`. +fn shuffle(rng: &mut Rng, slice: &mut [T]) { + for i in 0..slice.len() { + randomize_first(rng, &mut slice[i..]); + } + + fn randomize_first(rng: &mut Rng, slice: &mut [T]) { + assert!(!slice.is_empty()); + let idx = rng.rand_range(0..slice.len() as u64) as usize; + slice.swap(0, idx); + } +} + +struct Rng { + state: u64, + extra: u64, +} + +impl Rng { + fn new(seed: u64, extra: u64) -> Self { + Self { state: seed, extra } + } + + fn rand_range(&mut self, range: core::ops::Range) -> u64 { + self.rand_u64() % (range.end - range.start) + range.start + } + + fn rand_u64(&mut self) -> u64 { + self.state = calculate_hash(&(self.state, self.extra)); + self.state + } +} + +// `calculate_hash` is from `core/src/hash/mod.rs`. +fn calculate_hash(t: &T) -> u64 { + let mut s = DefaultHasher::new(); + t.hash(&mut s); + s.finish() +} diff --git a/library/test/src/lib.rs b/library/test/src/lib.rs index 251f099f28..99d951d801 100644 --- a/library/test/src/lib.rs +++ b/library/test/src/lib.rs @@ -23,7 +23,7 @@ #![feature(libc)] #![feature(rustc_private)] #![feature(nll)] -#![feature(available_concurrency)] +#![feature(available_parallelism)] #![feature(bench_black_box)] #![feature(internal_output_capture)] #![feature(panic_unwind)] @@ -91,6 +91,7 @@ mod tests; use event::{CompletedTest, TestEvent}; use helpers::concurrency::get_concurrency; use helpers::exit_code::get_exit_code; +use helpers::shuffle::{get_shuffle_seed, shuffle_tests}; use options::{Concurrent, RunStrategy}; use test_result::*; use time::TestExecTime; @@ -247,7 +248,9 @@ where let filtered_descs = filtered_tests.iter().map(|t| t.desc.clone()).collect(); - let event = TestEvent::TeFiltered(filtered_descs); + let shuffle_seed = get_shuffle_seed(opts); + + let event = TestEvent::TeFiltered(filtered_descs, shuffle_seed); notify_about_test_event(event)?; let (filtered_tests, filtered_benchs): (Vec<_>, _) = filtered_tests @@ -259,7 +262,11 @@ where let concurrency = opts.test_threads.unwrap_or_else(get_concurrency); let mut remaining = filtered_tests; - remaining.reverse(); + if let Some(shuffle_seed) = shuffle_seed { + shuffle_tests(shuffle_seed, &mut remaining); + } else { + remaining.reverse(); + } let mut pending = 0; let (tx, rx) = channel::(); diff --git a/library/test/src/term/terminfo/mod.rs b/library/test/src/term/terminfo/mod.rs index f4c5a05d1e..694473f52c 100644 --- a/library/test/src/term/terminfo/mod.rs +++ b/library/test/src/term/terminfo/mod.rs @@ -16,6 +16,7 @@ use parser::compiled::{msys_terminfo, parse}; use searcher::get_dbpath_for_term; /// A parsed terminfo database entry. +#[allow(unused)] #[derive(Debug)] pub(crate) struct TermInfo { /// Names for the terminal diff --git a/library/test/src/tests.rs b/library/test/src/tests.rs index 794f727700..718613895d 100644 --- a/library/test/src/tests.rs +++ b/library/test/src/tests.rs @@ -45,6 +45,8 @@ impl TestOpts { nocapture: false, color: AutoColor, format: OutputFormat::Pretty, + shuffle: false, + shuffle_seed: None, test_threads: None, skip: vec![], time_options: None, @@ -565,11 +567,7 @@ pub fn exact_filter_match() { assert_eq!(exact.len(), 2); } -#[test] -pub fn sort_tests() { - let mut opts = TestOpts::new(); - opts.run_tests = true; - +fn sample_tests() -> Vec { let names = vec![ "sha1::test".to_string(), "isize::test_to_str".to_string(), @@ -583,26 +581,32 @@ pub fn sort_tests() { "test::run_include_ignored_option".to_string(), "test::sort_tests".to_string(), ]; - let tests = { - fn testfn() {} - let mut tests = Vec::new(); - for name in &names { - let test = TestDescAndFn { - desc: TestDesc { - name: DynTestName((*name).clone()), - ignore: false, - should_panic: ShouldPanic::No, - allow_fail: false, - compile_fail: false, - no_run: false, - test_type: TestType::Unknown, - }, - testfn: DynTestFn(Box::new(testfn)), - }; - tests.push(test); - } - tests - }; + fn testfn() {} + let mut tests = Vec::new(); + for name in &names { + let test = TestDescAndFn { + desc: TestDesc { + name: DynTestName((*name).clone()), + ignore: false, + should_panic: ShouldPanic::No, + allow_fail: false, + compile_fail: false, + no_run: false, + test_type: TestType::Unknown, + }, + testfn: DynTestFn(Box::new(testfn)), + }; + tests.push(test); + } + tests +} + +#[test] +pub fn sort_tests() { + let mut opts = TestOpts::new(); + opts.run_tests = true; + + let tests = sample_tests(); let filtered = filter_tests(&opts, tests); let expected = vec![ @@ -624,6 +628,71 @@ pub fn sort_tests() { } } +#[test] +pub fn shuffle_tests() { + let mut opts = TestOpts::new(); + opts.shuffle = true; + + let shuffle_seed = get_shuffle_seed(&opts).unwrap(); + + let left = + sample_tests().into_iter().enumerate().map(|(i, e)| (TestId(i), e)).collect::>(); + let mut right = + sample_tests().into_iter().enumerate().map(|(i, e)| (TestId(i), e)).collect::>(); + + assert!(left.iter().zip(&right).all(|(a, b)| a.1.desc.name == b.1.desc.name)); + + helpers::shuffle::shuffle_tests(shuffle_seed, right.as_mut_slice()); + + assert!(left.iter().zip(right).any(|(a, b)| a.1.desc.name != b.1.desc.name)); +} + +#[test] +pub fn shuffle_tests_with_seed() { + let mut opts = TestOpts::new(); + opts.shuffle = true; + + let shuffle_seed = get_shuffle_seed(&opts).unwrap(); + + let mut left = + sample_tests().into_iter().enumerate().map(|(i, e)| (TestId(i), e)).collect::>(); + let mut right = + sample_tests().into_iter().enumerate().map(|(i, e)| (TestId(i), e)).collect::>(); + + helpers::shuffle::shuffle_tests(shuffle_seed, left.as_mut_slice()); + helpers::shuffle::shuffle_tests(shuffle_seed, right.as_mut_slice()); + + assert!(left.iter().zip(right).all(|(a, b)| a.1.desc.name == b.1.desc.name)); +} + +#[test] +pub fn order_depends_on_more_than_seed() { + let mut opts = TestOpts::new(); + opts.shuffle = true; + + let shuffle_seed = get_shuffle_seed(&opts).unwrap(); + + let mut left_tests = sample_tests(); + let mut right_tests = sample_tests(); + + left_tests.pop(); + right_tests.remove(0); + + let mut left = + left_tests.into_iter().enumerate().map(|(i, e)| (TestId(i), e)).collect::>(); + let mut right = + right_tests.into_iter().enumerate().map(|(i, e)| (TestId(i), e)).collect::>(); + + assert_eq!(left.len(), right.len()); + + assert!(left.iter().zip(&right).all(|(a, b)| a.0 == b.0)); + + helpers::shuffle::shuffle_tests(shuffle_seed, left.as_mut_slice()); + helpers::shuffle::shuffle_tests(shuffle_seed, right.as_mut_slice()); + + assert!(left.iter().zip(right).any(|(a, b)| a.0 != b.0)); +} + #[test] pub fn test_metricmap_compare() { let mut m1 = MetricMap::new(); diff --git a/library/unwind/src/lib.rs b/library/unwind/src/lib.rs index 06384b1592..e263780bf3 100644 --- a/library/unwind/src/lib.rs +++ b/library/unwind/src/lib.rs @@ -23,6 +23,7 @@ cfg_if::cfg_if! { unix, windows, target_os = "psp", + target_os = "solid_asp3", all(target_vendor = "fortanix", target_env = "sgx"), ))] { mod libunwind; @@ -62,7 +63,7 @@ cfg_if::cfg_if! { // don't want to duplicate it here. #[cfg(all( target_os = "linux", - target_env = "gnu", + any(target_env = "gnu", target_env = "uclibc"), not(feature = "llvm-libunwind"), not(feature = "system-llvm-libunwind") ))] @@ -71,7 +72,7 @@ extern "C" {} #[cfg(all( target_os = "linux", - target_env = "gnu", + any(target_env = "gnu", target_env = "uclibc"), not(feature = "llvm-libunwind"), feature = "system-llvm-libunwind" ))] diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml index 0b76a13e02..1ce1f0b26d 100644 --- a/src/bootstrap/Cargo.toml +++ b/src/bootstrap/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "bootstrap" version = "0.0.0" -edition = "2018" +edition = "2021" build = "build.rs" [lib] diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index e34768bc2c..0170be967e 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -4,6 +4,7 @@ import contextlib import datetime import distutils.version import hashlib +import json import os import re import shutil @@ -24,19 +25,17 @@ def support_xz(): except tarfile.CompressionError: return False -def get(url, path, verbose=False, do_verify=True): - suffix = '.sha256' - sha_url = url + suffix +def get(base, url, path, checksums, verbose=False, do_verify=True): with tempfile.NamedTemporaryFile(delete=False) as temp_file: temp_path = temp_file.name - with tempfile.NamedTemporaryFile(suffix=suffix, delete=False) as sha_file: - sha_path = sha_file.name try: if do_verify: - download(sha_path, sha_url, False, verbose) + if url not in checksums: + raise RuntimeError("src/stage0.json doesn't contain a checksum for {}".format(url)) + sha256 = checksums[url] if os.path.exists(path): - if verify(path, sha_path, False): + if verify(path, sha256, False): if verbose: print("using already-download file", path) return @@ -45,23 +44,17 @@ def get(url, path, verbose=False, do_verify=True): print("ignoring already-download file", path, "due to failed verification") os.unlink(path) - download(temp_path, url, True, verbose) - if do_verify and not verify(temp_path, sha_path, verbose): + download(temp_path, "{}/{}".format(base, url), True, verbose) + if do_verify and not verify(temp_path, sha256, verbose): raise RuntimeError("failed verification") if verbose: print("moving {} to {}".format(temp_path, path)) shutil.move(temp_path, path) finally: - delete_if_present(sha_path, verbose) - delete_if_present(temp_path, verbose) - - -def delete_if_present(path, verbose): - """Remove the given file if present""" - if os.path.isfile(path): - if verbose: - print("removing", path) - os.unlink(path) + if os.path.isfile(temp_path): + if verbose: + print("removing", temp_path) + os.unlink(temp_path) def download(path, url, probably_big, verbose): @@ -98,14 +91,12 @@ def _download(path, url, probably_big, verbose, exception): exception=exception) -def verify(path, sha_path, verbose): +def verify(path, expected, verbose): """Check if the sha256 sum of the given path is valid""" if verbose: print("verifying", path) with open(path, "rb") as source: found = hashlib.sha256(source.read()).hexdigest() - with open(sha_path, "r") as sha256sum: - expected = sha256sum.readline().split()[0] verified = found == expected if not verified: print("invalid checksum:\n" @@ -176,15 +167,6 @@ def require(cmd, exit=True): sys.exit(1) -def stage0_data(rust_root): - """Build a dictionary from stage0.txt""" - nightlies = os.path.join(rust_root, "src/stage0.txt") - with open(nightlies, 'r') as nightlies: - lines = [line.rstrip() for line in nightlies - if not line.startswith("#")] - return dict([line.split(": ", 1) for line in lines if line]) - - def format_build_time(duration): """Return a nicer format for build time @@ -295,6 +277,7 @@ def default_build_triple(verbose): 'i486': 'i686', 'i686': 'i686', 'i786': 'i686', + 'm68k': 'm68k', 'powerpc': 'powerpc', 'powerpc64': 'powerpc64', 'powerpc64le': 'powerpc64le', @@ -372,13 +355,22 @@ def output(filepath): os.rename(tmp, filepath) +class Stage0Toolchain: + def __init__(self, stage0_payload): + self.date = stage0_payload["date"] + self.version = stage0_payload["version"] + + def channel(self): + return self.version + "-" + self.date + + class RustBuild(object): """Provide all the methods required to build Rust""" def __init__(self): - self.date = '' + self.checksums_sha256 = {} + self.stage0_compiler = None + self.stage0_rustfmt = None self._download_url = '' - self.rustc_channel = '' - self.rustfmt_channel = '' self.build = '' self.build_dir = '' self.clean = False @@ -402,11 +394,10 @@ class RustBuild(object): will move all the content to the right place. """ if rustc_channel is None: - rustc_channel = self.rustc_channel - rustfmt_channel = self.rustfmt_channel + rustc_channel = self.stage0_compiler.version bin_root = self.bin_root(stage0) - key = self.date + key = self.stage0_compiler.date if not stage0: key += str(self.rustc_commit) if self.rustc(stage0).startswith(bin_root) and \ @@ -445,19 +436,23 @@ class RustBuild(object): if self.rustfmt() and self.rustfmt().startswith(bin_root) and ( not os.path.exists(self.rustfmt()) - or self.program_out_of_date(self.rustfmt_stamp(), self.rustfmt_channel) + or self.program_out_of_date( + self.rustfmt_stamp(), + "" if self.stage0_rustfmt is None else self.stage0_rustfmt.channel() + ) ): - if rustfmt_channel: + if self.stage0_rustfmt is not None: tarball_suffix = '.tar.xz' if support_xz() else '.tar.gz' - [channel, date] = rustfmt_channel.split('-', 1) - filename = "rustfmt-{}-{}{}".format(channel, self.build, tarball_suffix) + filename = "rustfmt-{}-{}{}".format( + self.stage0_rustfmt.version, self.build, tarball_suffix, + ) self._download_component_helper( - filename, "rustfmt-preview", tarball_suffix, key=date + filename, "rustfmt-preview", tarball_suffix, key=self.stage0_rustfmt.date ) self.fix_bin_or_dylib("{}/bin/rustfmt".format(bin_root)) self.fix_bin_or_dylib("{}/bin/cargo-fmt".format(bin_root)) with output(self.rustfmt_stamp()) as rustfmt_stamp: - rustfmt_stamp.write(self.rustfmt_channel) + rustfmt_stamp.write(self.stage0_rustfmt.channel()) # Avoid downloading LLVM twice (once for stage0 and once for the master rustc) if self.downloading_llvm() and stage0: @@ -465,7 +460,7 @@ class RustBuild(object): # LLVM more often than necessary. # # This git command finds that commit SHA, looking for bors-authored - # merges that modified src/llvm-project or other relevant version + # commits that modified src/llvm-project or other relevant version # stamp files. # # This works even in a repository that has not yet initialized @@ -475,7 +470,7 @@ class RustBuild(object): ]).decode(sys.getdefaultencoding()).strip() llvm_sha = subprocess.check_output([ "git", "rev-list", "--author=bors@rust-lang.org", "-n1", - "--merges", "--first-parent", "HEAD", + "--first-parent", "HEAD", "--", "{}/src/llvm-project".format(top_level), "{}/src/bootstrap/download-ci-llvm-stamp".format(top_level), @@ -518,7 +513,7 @@ class RustBuild(object): ): if key is None: if stage0: - key = self.date + key = self.stage0_compiler.date else: key = self.rustc_commit cache_dst = os.path.join(self.build_dir, "cache") @@ -527,22 +522,38 @@ class RustBuild(object): os.makedirs(rustc_cache) if stage0: - url = "{}/dist/{}".format(self._download_url, key) + base = self._download_url + url = "dist/{}".format(key) else: - url = "https://ci-artifacts.rust-lang.org/rustc-builds/{}".format(self.rustc_commit) + base = "https://ci-artifacts.rust-lang.org" + url = "rustc-builds/{}".format(self.rustc_commit) tarball = os.path.join(rustc_cache, filename) if not os.path.exists(tarball): - get("{}/{}".format(url, filename), tarball, verbose=self.verbose, do_verify=stage0) + get( + base, + "{}/{}".format(url, filename), + tarball, + self.checksums_sha256, + verbose=self.verbose, + do_verify=stage0, + ) unpack(tarball, tarball_suffix, self.bin_root(stage0), match=pattern, verbose=self.verbose) def _download_ci_llvm(self, llvm_sha, llvm_assertions): + if not llvm_sha: + print("error: could not find commit hash for downloading LLVM") + print("help: maybe your repository history is too shallow?") + print("help: consider disabling `download-ci-llvm`") + print("help: or fetch enough history to include one upstream commit") + exit(1) cache_prefix = "llvm-{}-{}".format(llvm_sha, llvm_assertions) cache_dst = os.path.join(self.build_dir, "cache") rustc_cache = os.path.join(cache_dst, cache_prefix) if not os.path.exists(rustc_cache): os.makedirs(rustc_cache) - url = "https://ci-artifacts.rust-lang.org/rustc-builds/{}".format(llvm_sha) + base = "https://ci-artifacts.rust-lang.org" + url = "rustc-builds/{}".format(llvm_sha) if llvm_assertions: url = url.replace('rustc-builds', 'rustc-builds-alt') # ci-artifacts are only stored as .xz, not .gz @@ -554,7 +565,14 @@ class RustBuild(object): filename = "rust-dev-nightly-" + self.build + tarball_suffix tarball = os.path.join(rustc_cache, filename) if not os.path.exists(tarball): - get("{}/{}".format(url, filename), tarball, verbose=self.verbose, do_verify=False) + get( + base, + "{}/{}".format(url, filename), + tarball, + self.checksums_sha256, + verbose=self.verbose, + do_verify=False, + ) unpack(tarball, tarball_suffix, self.llvm_root(), match="rust-dev", verbose=self.verbose) @@ -582,19 +600,23 @@ class RustBuild(object): if ostype != "Linux": return - # Use `/etc/os-release` instead of `/etc/NIXOS`. - # The latter one does not exist on NixOS when using tmpfs as root. - try: - with open("/etc/os-release", "r") as f: - if not any(line.strip() == "ID=nixos" for line in f): - return - except FileNotFoundError: - return - if os.path.exists("/lib"): - return + # If the user has asked binaries to be patched for Nix, then + # don't check for NixOS or `/lib`, just continue to the patching. + if self.get_toml('patch-binaries-for-nix', 'build') != 'true': + # Use `/etc/os-release` instead of `/etc/NIXOS`. + # The latter one does not exist on NixOS when using tmpfs as root. + try: + with open("/etc/os-release", "r") as f: + if not any(line.strip() == "ID=nixos" for line in f): + return + except FileNotFoundError: + return + if os.path.exists("/lib"): + return - # At this point we're pretty sure the user is running NixOS - nix_os_msg = "info: you seem to be running NixOS. Attempting to patch" + # At this point we're pretty sure the user is running NixOS or + # using Nix + nix_os_msg = "info: you seem to be using Nix. Attempting to patch" print(nix_os_msg, fname) # Only build `.nix-deps` once. @@ -669,9 +691,15 @@ class RustBuild(object): # Only commits merged by bors will have CI artifacts. merge_base = [ "git", "rev-list", "--author=bors@rust-lang.org", "-n1", - "--merges", "--first-parent", "HEAD" + "--first-parent", "HEAD" ] commit = subprocess.check_output(merge_base, universal_newlines=True).strip() + if not commit: + print("error: could not find commit hash for downloading rustc") + print("help: maybe your repository history is too shallow?") + print("help: consider disabling `download-rustc`") + print("help: or fetch enough history to include one upstream commit") + exit(1) # Warn if there were changes to the compiler or standard library since the ancestor commit. status = subprocess.call(["git", "diff-index", "--quiet", commit, "--", compiler, library]) @@ -816,7 +844,7 @@ class RustBuild(object): def rustfmt(self): """Return config path for rustfmt""" - if not self.rustfmt_channel: + if self.stage0_rustfmt is None: return None return self.program_config('rustfmt') @@ -905,10 +933,9 @@ class RustBuild(object): env["LIBRARY_PATH"] = os.path.join(self.bin_root(True), "lib") + \ (os.pathsep + env["LIBRARY_PATH"]) \ if "LIBRARY_PATH" in env else "" + # preserve existing RUSTFLAGS env.setdefault("RUSTFLAGS", "") - env["RUSTFLAGS"] += " -Cdebuginfo=2" - build_section = "target.{}".format(self.build) target_features = [] if self.get_toml("crt-static", build_section) == "true": @@ -974,7 +1001,7 @@ class RustBuild(object): run(["git", "submodule", "-q", "sync", module], cwd=self.rust_root, verbose=self.verbose) - update_args = ["git", "submodule", "update", "--init", "--recursive"] + update_args = ["git", "submodule", "update", "--init", "--recursive", "--depth=1"] if self.git_version >= distutils.version.LooseVersion("2.11.0"): update_args.append("--progress") update_args.append(module) @@ -1040,19 +1067,12 @@ class RustBuild(object): self.update_submodule(module[0], module[1], recorded_submodules) print("Submodules updated in %.2f seconds" % (time() - start_time)) - def set_normal_environment(self): + def set_dist_environment(self, url): """Set download URL for normal environment""" if 'RUSTUP_DIST_SERVER' in os.environ: self._download_url = os.environ['RUSTUP_DIST_SERVER'] else: - self._download_url = 'https://static.rust-lang.org' - - def set_dev_environment(self): - """Set download URL for development environment""" - if 'RUSTUP_DEV_DIST_SERVER' in os.environ: - self._download_url = os.environ['RUSTUP_DEV_DIST_SERVER'] - else: - self._download_url = 'https://dev-static.rust-lang.org' + self._download_url = url def check_vendored_status(self): """Check that vendoring is configured properly""" @@ -1161,17 +1181,14 @@ def bootstrap(help_triggered): build_dir = build.get_toml('build-dir', 'build') or 'build' build.build_dir = os.path.abspath(build_dir.replace("$ROOT", build.rust_root)) - data = stage0_data(build.rust_root) - build.date = data['date'] - build.rustc_channel = data['rustc'] + with open(os.path.join(build.rust_root, "src", "stage0.json")) as f: + data = json.load(f) + build.checksums_sha256 = data["checksums_sha256"] + build.stage0_compiler = Stage0Toolchain(data["compiler"]) + if data.get("rustfmt") is not None: + build.stage0_rustfmt = Stage0Toolchain(data["rustfmt"]) - if "rustfmt" in data: - build.rustfmt_channel = data['rustfmt'] - - if 'dev' in data: - build.set_dev_environment() - else: - build.set_normal_environment() + build.set_dist_environment(data["dist_server"]) build.build = args.build or build.build_triple() build.update_submodules() diff --git a/src/bootstrap/bootstrap_test.py b/src/bootstrap/bootstrap_test.py index 6150711415..7bffc1c152 100644 --- a/src/bootstrap/bootstrap_test.py +++ b/src/bootstrap/bootstrap_test.py @@ -13,38 +13,18 @@ from shutil import rmtree import bootstrap -class Stage0DataTestCase(unittest.TestCase): - """Test Case for stage0_data""" - def setUp(self): - self.rust_root = tempfile.mkdtemp() - os.mkdir(os.path.join(self.rust_root, "src")) - with open(os.path.join(self.rust_root, "src", - "stage0.txt"), "w") as stage0: - stage0.write("#ignore\n\ndate: 2017-06-15\nrustc: beta\ncargo: beta\nrustfmt: beta") - - def tearDown(self): - rmtree(self.rust_root) - - def test_stage0_data(self): - """Extract data from stage0.txt""" - expected = {"date": "2017-06-15", "rustc": "beta", "cargo": "beta", "rustfmt": "beta"} - data = bootstrap.stage0_data(self.rust_root) - self.assertDictEqual(data, expected) - - class VerifyTestCase(unittest.TestCase): """Test Case for verify""" def setUp(self): self.container = tempfile.mkdtemp() self.src = os.path.join(self.container, "src.txt") - self.sums = os.path.join(self.container, "sums") self.bad_src = os.path.join(self.container, "bad.txt") content = "Hello world" + self.expected = hashlib.sha256(content.encode("utf-8")).hexdigest() + with open(self.src, "w") as src: src.write(content) - with open(self.sums, "w") as sums: - sums.write(hashlib.sha256(content.encode("utf-8")).hexdigest()) with open(self.bad_src, "w") as bad: bad.write("Hello!") @@ -53,11 +33,11 @@ class VerifyTestCase(unittest.TestCase): def test_valid_file(self): """Check if the sha256 sum of the given file is valid""" - self.assertTrue(bootstrap.verify(self.src, self.sums, False)) + self.assertTrue(bootstrap.verify(self.src, self.expected, False)) def test_invalid_file(self): """Should verify that the file is invalid""" - self.assertFalse(bootstrap.verify(self.bad_src, self.sums, False)) + self.assertFalse(bootstrap.verify(self.bad_src, self.expected, False)) class ProgramOutOfDate(unittest.TestCase): @@ -99,7 +79,6 @@ if __name__ == '__main__': TEST_LOADER = unittest.TestLoader() SUITE.addTest(doctest.DocTestSuite(bootstrap)) SUITE.addTests([ - TEST_LOADER.loadTestsFromTestCase(Stage0DataTestCase), TEST_LOADER.loadTestsFromTestCase(VerifyTestCase), TEST_LOADER.loadTestsFromTestCase(ProgramOutOfDate)]) diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 5911309a04..6750f7a549 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -370,7 +370,7 @@ impl<'a> Builder<'a> { match kind { Kind::Build => describe!( compile::Std, - compile::Rustc, + compile::Assemble, compile::CodegenBackend, compile::StartupObjects, tool::BuildManifest, @@ -523,7 +523,7 @@ impl<'a> Builder<'a> { install::Src, install::Rustc ), - Kind::Run => describe!(run::ExpandYamlAnchors, run::BuildManifest), + Kind::Run => describe!(run::ExpandYamlAnchors, run::BuildManifest, run::BumpStage0), } } @@ -1342,12 +1342,6 @@ impl<'a> Builder<'a> { rustdocflags.arg("-Dwarnings"); } - // FIXME(#58633) hide "unused attribute" errors in incremental - // builds of the standard library, as the underlying checks are - // not yet properly integrated with incremental recompilation. - if mode == Mode::Std && compiler.stage == 0 && self.config.incremental { - lint_flags.push("-Aunused-attributes"); - } // This does not use RUSTFLAGS due to caching issues with Cargo. // Clippy is treated as an "in tree" tool, but shares the same // cache as other "submodule" tools. With these options set in @@ -1617,6 +1611,22 @@ impl<'a> Builder<'a> { // Only execute if it's supposed to run as default if desc.default && should_run.is_really_default() { self.ensure(step) } else { None } } + + /// Checks if any of the "should_run" paths is in the `Builder` paths. + pub(crate) fn was_invoked_explicitly(&'a self) -> bool { + let desc = StepDescription::from::(); + let should_run = (desc.should_run)(ShouldRun::new(self)); + + for path in &self.paths { + if should_run.paths.iter().any(|s| s.has(path)) + && !desc.is_excluded(self, &PathSet::Suite(path.clone())) + { + return true; + } + } + + false + } } #[cfg(test)] diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index 4eb335979b..28e7f1fdca 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -107,6 +107,11 @@ impl Step for Std { add_to_sysroot(&builder, &libdir, &hostdir, &libstd_stamp(builder, compiler, target)); } + // don't run on std twice with x.py clippy + if builder.kind == Kind::Clippy { + return; + } + // Then run cargo again, once we've put the rmeta files for the library // crates into the sysroot. This is needed because e.g., core's tests // depend on `libtest` -- Cargo presumes it will exist, but it doesn't @@ -120,6 +125,7 @@ impl Step for Std { target, cargo_subcommand(builder.kind), ); + cargo.arg("--all-targets"); std_cargo(builder, target, compiler.stage, &mut cargo); @@ -192,7 +198,12 @@ impl Step for Rustc { cargo_subcommand(builder.kind), ); rustc_cargo(builder, &mut cargo, target); - cargo.arg("--all-targets"); + + // For ./x.py clippy, don't run with --all-targets because + // linting tests and benchmarks can produce very noisy results + if builder.kind != Kind::Clippy { + cargo.arg("--all-targets"); + } // Explicitly pass -p for all compiler krates -- this will force cargo // to also check the tests/benches/examples for these crates, rather @@ -232,11 +243,16 @@ impl Step for CodegenBackend { const DEFAULT: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - run.paths(&["compiler/rustc_codegen_cranelift", "rustc_codegen_cranelift"]) + run.paths(&[ + "compiler/rustc_codegen_cranelift", + "rustc_codegen_cranelift", + "compiler/rustc_codegen_gcc", + "rustc_codegen_gcc", + ]) } fn make_run(run: RunConfig<'_>) { - for &backend in &[INTERNER.intern_str("cranelift")] { + for &backend in &[INTERNER.intern_str("cranelift"), INTERNER.intern_str("gcc")] { run.builder.ensure(CodegenBackend { target: run.target, backend }); } } @@ -251,7 +267,7 @@ impl Step for CodegenBackend { let mut cargo = builder.cargo( compiler, Mode::Codegen, - SourceType::Submodule, + SourceType::InTree, target, cargo_subcommand(builder.kind), ); @@ -313,7 +329,12 @@ macro_rules! tool_check_step { $source_type, &[], ); - cargo.arg("--all-targets"); + + // For ./x.py clippy, don't run with --all-targets because + // linting tests and benchmarks can produce very noisy results + if builder.kind != Kind::Clippy { + cargo.arg("--all-targets"); + } // Enable internal lints for clippy and rustdoc // NOTE: this doesn't enable lints for any other tools unless they explicitly add `#![warn(rustc::internal)]` diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index d5cc81b1cd..e9cc7662e6 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -528,7 +528,7 @@ impl Step for Rustc { const DEFAULT: bool = false; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - run.path("compiler/rustc") + run.never() } fn make_run(run: RunConfig<'_>) { @@ -817,8 +817,7 @@ impl Step for CodegenBackend { let out_dir = builder.cargo_out(compiler, Mode::Codegen, target); - let mut cargo = - builder.cargo(compiler, Mode::Codegen, SourceType::Submodule, target, "build"); + let mut cargo = builder.cargo(compiler, Mode::Codegen, SourceType::InTree, target, "build"); cargo .arg("--manifest-path") .arg(builder.src.join(format!("compiler/rustc_codegen_{}/Cargo.toml", backend))); @@ -1024,9 +1023,16 @@ pub struct Assemble { impl Step for Assemble { type Output = Compiler; + const ONLY_HOSTS: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - run.never() + run.path("compiler/rustc") + } + + fn make_run(run: RunConfig<'_>) { + run.builder.ensure(Assemble { + target_compiler: run.builder.compiler(run.builder.top_stage + 1, run.target), + }); } /// Prepare a new compiler from the artifacts in `stage` diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index 5706b8f9e7..e658d958d0 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -397,6 +397,7 @@ struct Build { install_stage: Option, dist_stage: Option, bench_stage: Option, + patch_binaries_for_nix: Option, } /// TOML representation of various global install decisions. @@ -824,15 +825,10 @@ impl Config { }; } - if config.llvm_thin_lto { - // If we're building with ThinLTO on, we want to link to LLVM - // shared, to avoid re-doing ThinLTO (which happens in the link - // step) with each stage. - assert_ne!( - llvm.link_shared, - Some(false), - "setting link-shared=false is incompatible with thin-lto=true" - ); + if config.llvm_thin_lto && llvm.link_shared.is_none() { + // If we're building with ThinLTO on, by default we want to link + // to LLVM shared, to avoid re-doing ThinLTO (which happens in + // the link step) with each stage. config.llvm_link_shared = true; } } @@ -981,7 +977,8 @@ impl Config { config.rust_debug_assertions_std = debug_assertions_std.unwrap_or(config.rust_debug_assertions); config.rust_overflow_checks = overflow_checks.unwrap_or(default); - config.rust_overflow_checks_std = overflow_checks_std.unwrap_or(default); + config.rust_overflow_checks_std = + overflow_checks_std.unwrap_or(config.rust_overflow_checks); config.rust_debug_logging = debug_logging.unwrap_or(config.rust_debug_assertions); diff --git a/src/bootstrap/configure.py b/src/bootstrap/configure.py index fd148d1447..94424cb454 100755 --- a/src/bootstrap/configure.py +++ b/src/bootstrap/configure.py @@ -75,7 +75,9 @@ o("optimize-llvm", "llvm.optimize", "build optimized LLVM") o("llvm-assertions", "llvm.assertions", "build LLVM with assertions") o("llvm-plugins", "llvm.plugins", "build LLVM with plugin interface") o("debug-assertions", "rust.debug-assertions", "build with debugging assertions") +o("debug-assertions-std", "rust.debug-assertions-std", "build the standard library with debugging assertions") o("overflow-checks", "rust.overflow-checks", "build with overflow checks") +o("overflow-checks-std", "rust.overflow-checks-std", "build the standard library with overflow checks") o("llvm-release-debuginfo", "llvm.release-debuginfo", "build LLVM with debugger metadata") v("debuginfo-level", "rust.debuginfo-level", "debuginfo level for Rust code") v("debuginfo-level-rustc", "rust.debuginfo-level-rustc", "debuginfo level for the compiler") diff --git a/src/bootstrap/defaults/config.library.toml b/src/bootstrap/defaults/config.library.toml index 9874fdb767..7bc054d3a4 100644 --- a/src/bootstrap/defaults/config.library.toml +++ b/src/bootstrap/defaults/config.library.toml @@ -10,6 +10,5 @@ bench-stage = 0 incremental = true [llvm] -# Will download LLVM from CI if available on your platform (Linux only for now) -# https://github.com/rust-lang/rust/issues/77084 tracks support for more platforms +# Will download LLVM from CI if available on your platform. download-ci-llvm = "if-available" diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index c871411793..6f2470b706 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -102,18 +102,10 @@ fn open(builder: &Builder<'_>, path: impl AsRef) { // Used for deciding whether a particular step is one requested by the user on // the `x.py doc` command line, which determines whether `--open` will open that // page. -fn components_simplified(path: &PathBuf) -> Vec<&str> { +pub(crate) fn components_simplified(path: &PathBuf) -> Vec<&str> { path.iter().map(|component| component.to_str().unwrap_or("???")).collect() } -fn is_explicit_request(builder: &Builder<'_>, path: &str) -> bool { - builder - .paths - .iter() - .map(components_simplified) - .any(|requested| requested.iter().copied().eq(path.split('/'))) -} - #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] pub struct UnstableBook { target: TargetSelection, @@ -248,7 +240,7 @@ impl Step for TheBook { invoke_rustdoc(builder, compiler, target, path); } - if is_explicit_request(builder, "src/doc/book") { + if builder.was_invoked_explicitly::() { let out = builder.doc_out(target); let index = out.join("book").join("index.html"); open(builder, &index); @@ -408,7 +400,7 @@ impl Step for Standalone { // We open doc/index.html as the default if invoked as `x.py doc --open` // with no particular explicit doc requested (e.g. library/core). - if builder.paths.is_empty() || is_explicit_request(builder, "src/doc") { + if builder.paths.is_empty() || builder.was_invoked_explicitly::() { let index = out.join("index.html"); open(builder, &index); } @@ -537,7 +529,7 @@ impl Step for Rustc { fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { let builder = run.builder; - run.krate("rustc-main").default_condition(builder.config.docs) + run.krate("rustc-main").path("compiler").default_condition(builder.config.docs) } fn make_run(run: RunConfig<'_>) { @@ -555,7 +547,20 @@ impl Step for Rustc { let target = self.target; builder.info(&format!("Documenting stage{} compiler ({})", stage, target)); - if !builder.config.compiler_docs { + let paths = builder + .paths + .iter() + .map(components_simplified) + .filter_map(|path| { + if path.get(0) == Some(&"compiler") { + path.get(1).map(|p| p.to_owned()) + } else { + None + } + }) + .collect::>(); + + if !builder.config.compiler_docs && !builder.was_invoked_explicitly::() { builder.info("\tskipping - compiler/librustdoc docs disabled"); return; } @@ -589,32 +594,69 @@ impl Step for Rustc { cargo.rustdocflag("-Zunstable-options"); cargo.rustdocflag("-Znormalize-docs"); cargo.rustdocflag("--show-type-layout"); + cargo.rustdocflag("--generate-link-to-definition"); compile::rustc_cargo(builder, &mut cargo, target); + cargo.arg("-Zunstable-options"); cargo.arg("-Zskip-rustdoc-fingerprint"); // Only include compiler crates, no dependencies of those, such as `libc`. + // Do link to dependencies on `docs.rs` however using `rustdoc-map`. cargo.arg("--no-deps"); + cargo.arg("-Zrustdoc-map"); + + // FIXME: `-Zrustdoc-map` does not yet correctly work for transitive dependencies, + // once this is no longer an issue the special case for `ena` can be removed. + cargo.rustdocflag("--extern-html-root-url"); + cargo.rustdocflag("ena=https://docs.rs/ena/latest/"); - // Find dependencies for top level crates. let mut compiler_crates = HashSet::new(); - for root_crate in &["rustc_driver", "rustc_codegen_llvm", "rustc_codegen_ssa"] { - compiler_crates.extend( - builder - .in_tree_crates(root_crate, Some(target)) - .into_iter() - .map(|krate| krate.name), - ); + + if paths.is_empty() { + // Find dependencies for top level crates. + for root_crate in &["rustc_driver", "rustc_codegen_llvm", "rustc_codegen_ssa"] { + compiler_crates.extend( + builder + .in_tree_crates(root_crate, Some(target)) + .into_iter() + .map(|krate| krate.name), + ); + } + } else { + for root_crate in paths { + if !builder.src.join("compiler").join(&root_crate).exists() { + builder.info(&format!( + "\tskipping - compiler/{} (unknown compiler crate)", + root_crate + )); + } else { + compiler_crates.extend( + builder + .in_tree_crates(root_crate, Some(target)) + .into_iter() + .map(|krate| krate.name), + ); + } + } } + let mut to_open = None; for krate in &compiler_crates { // Create all crate output directories first to make sure rustdoc uses // relative links. // FIXME: Cargo should probably do this itself. t!(fs::create_dir_all(out_dir.join(krate))); cargo.arg("-p").arg(krate); + if to_open.is_none() { + to_open = Some(krate); + } } builder.run(&mut cargo.into()); + // Let's open the first crate documentation page: + if let Some(krate) = to_open { + let index = out.join(krate).join("index.html"); + open(builder, &index); + } } } @@ -648,7 +690,14 @@ macro_rules! tool_doc { fn run(self, builder: &Builder<'_>) { let stage = self.stage; let target = self.target; - builder.info(&format!("Documenting stage{} {} ({})", stage, stringify!($tool).to_lowercase(), target)); + builder.info( + &format!( + "Documenting stage{} {} ({})", + stage, + stringify!($tool).to_lowercase(), + target, + ), + ); // This is the intended out directory for compiler documentation. let out = builder.compiler_doc_out(target); @@ -656,7 +705,7 @@ macro_rules! tool_doc { let compiler = builder.compiler(stage, builder.config.build); - if !builder.config.compiler_docs { + if !builder.config.compiler_docs && !builder.was_invoked_explicitly::() { builder.info("\tskipping - compiler/tool docs disabled"); return; } @@ -691,6 +740,7 @@ macro_rules! tool_doc { cargo.rustdocflag("--document-private-items"); cargo.rustdocflag("--enable-index-page"); cargo.rustdocflag("--show-type-layout"); + cargo.rustdocflag("--generate-link-to-definition"); cargo.rustdocflag("-Zunstable-options"); builder.run(&mut cargo.into()); } @@ -860,7 +910,7 @@ impl Step for RustcBook { name: INTERNER.intern_str("rustc"), src: INTERNER.intern_path(out_base), }); - if is_explicit_request(builder, "src/doc/rustc") { + if builder.was_invoked_explicitly::() { let out = builder.doc_out(self.target); let index = out.join("rustc").join("index.html"); open(builder, &index); diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 3d56650f77..2d4e152789 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -31,7 +31,7 @@ //! When you execute `x.py build`, the steps executed are: //! //! * First, the python script is run. This will automatically download the -//! stage0 rustc and cargo according to `src/stage0.txt`, or use the cached +//! stage0 rustc and cargo according to `src/stage0.json`, or use the cached //! versions if they're available. These are then used to compile rustbuild //! itself (using Cargo). Finally, control is then transferred to rustbuild. //! @@ -1494,8 +1494,13 @@ impl Build { { eprintln!( " -Couldn't find required command: ninja -You should install ninja, or set `ninja=false` in config.toml in the `[llvm]` section. +Couldn't find required command: ninja (or ninja-build) + +You should install ninja as described at +, +or set `ninja = false` in the `[llvm]` section of `config.toml`. +Alternatively, set `download-ci-llvm = true` in that `[llvm]` section +to download LLVM rather than building it. " ); std::process::exit(1); diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index 8cf43eac40..27c9bb2504 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -165,7 +165,7 @@ impl Step for Llvm { let llvm_exp_targets = match builder.config.llvm_experimental_targets { Some(ref s) => s, - None => "AVR", + None => "AVR;M68k", }; let assertions = if builder.config.llvm_assertions { "ON" } else { "OFF" }; @@ -189,6 +189,11 @@ impl Step for Llvm { .define("LLVM_TARGET_ARCH", target_native.split('-').next().unwrap()) .define("LLVM_DEFAULT_TARGET_TRIPLE", target_native); + // Parts of our test suite rely on the `FileCheck` tool, which is built by default in + // `build/$TARGET/llvm/build/bin` is but *not* then installed to `build/$TARGET/llvm/bin`. + // This flag makes sure `FileCheck` is copied in the final binaries directory. + cfg.define("LLVM_INSTALL_UTILS", "ON"); + if builder.config.llvm_profile_generate { cfg.define("LLVM_BUILD_INSTRUMENTED", "IR"); cfg.define("LLVM_BUILD_RUNTIME", "No"); diff --git a/src/bootstrap/run.rs b/src/bootstrap/run.rs index 7c64e5a0aa..11b393857e 100644 --- a/src/bootstrap/run.rs +++ b/src/bootstrap/run.rs @@ -82,3 +82,24 @@ impl Step for BuildManifest { builder.run(&mut cmd); } } + +#[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)] +pub struct BumpStage0; + +impl Step for BumpStage0 { + type Output = (); + const ONLY_HOSTS: bool = true; + + fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { + run.path("src/tools/bump-stage0") + } + + fn make_run(run: RunConfig<'_>) { + run.builder.ensure(BumpStage0); + } + + fn run(self, builder: &Builder<'_>) -> Self::Output { + let mut cmd = builder.tool_cmd(Tool::BumpStage0); + builder.run(&mut cmd); + } +} diff --git a/src/bootstrap/sanity.rs b/src/bootstrap/sanity.rs index 74e50c6061..d7db2cef24 100644 --- a/src/bootstrap/sanity.rs +++ b/src/bootstrap/sanity.rs @@ -15,7 +15,7 @@ use std::fs; use std::path::PathBuf; use std::process::Command; -use build_helper::{output, t}; +use build_helper::output; use crate::cache::INTERNER; use crate::config::Target; @@ -227,14 +227,4 @@ $ pacman -R cmake && pacman -S mingw-w64-x86_64-cmake if let Some(ref s) = build.config.ccache { cmd_finder.must_have(s); } - - if build.config.channel == "stable" { - let stage0 = t!(fs::read_to_string(build.src.join("src/stage0.txt"))); - if stage0.contains("\ndev:") { - panic!( - "bootstrapping from a dev compiler in a stable release, but \ - should only be bootstrapping from a released compiler!" - ); - } - } } diff --git a/src/bootstrap/setup.rs b/src/bootstrap/setup.rs index a5829dfa9d..5bc0a505bf 100644 --- a/src/bootstrap/setup.rs +++ b/src/bootstrap/setup.rs @@ -1,3 +1,4 @@ +use crate::TargetSelection; use crate::{t, VERSION}; use std::fmt::Write as _; use std::path::{Path, PathBuf}; @@ -107,6 +108,17 @@ pub fn setup(src_path: &Path, profile: Profile) { let include_path = profile.include_path(src_path); println!("`x.py` will now use the configuration at {}", include_path.display()); + let build = TargetSelection::from_user(&env!("BUILD_TRIPLE")); + let stage_path = ["build", build.rustc_target_arg(), "stage1"].join("/"); + + println!(); + + if !rustup_installed() && profile != Profile::User { + println!("`rustup` is not installed; cannot link `stage1` toolchain"); + } else if stage_dir_exists(&stage_path[..]) { + attempt_toolchain_link(&stage_path[..]); + } + let suggestions = match profile { Profile::Codegen | Profile::Compiler => &["check", "build", "test"][..], Profile::Tools => &[ @@ -139,6 +151,74 @@ pub fn setup(src_path: &Path, profile: Profile) { } } +fn rustup_installed() -> bool { + Command::new("rustup") + .arg("--version") + .stdout(std::process::Stdio::null()) + .output() + .map_or(false, |output| output.status.success()) +} + +fn stage_dir_exists(stage_path: &str) -> bool { + match fs::create_dir(&stage_path[..]) { + Ok(_) => true, + Err(_) => Path::new(&stage_path[..]).exists(), + } +} + +fn attempt_toolchain_link(stage_path: &str) { + if toolchain_is_linked() { + return; + } + + if try_link_toolchain(&stage_path[..]) { + println!( + "Added `stage1` rustup toolchain; try `cargo +stage1 build` on a separate rust project to run a newly-built toolchain" + ); + } else { + println!("`rustup` failed to link stage 1 build to `stage1` toolchain"); + println!( + "To manually link stage 1 build to `stage1` toolchain, run:\n + `rustup toolchain link stage1 {}`", + &stage_path[..] + ); + } +} + +fn toolchain_is_linked() -> bool { + match Command::new("rustup") + .args(&["toolchain", "list"]) + .stdout(std::process::Stdio::piped()) + .output() + { + Ok(toolchain_list) => { + if !String::from_utf8_lossy(&toolchain_list.stdout).contains("stage1") { + return false; + } + // The toolchain has already been linked. + println!( + "`stage1` toolchain already linked; not attempting to link `stage1` toolchain" + ); + } + Err(_) => { + // In this case, we don't know if the `stage1` toolchain has been linked; + // but `rustup` failed, so let's not go any further. + println!( + "`rustup` failed to list current toolchains; not attempting to link `stage1` toolchain" + ); + } + } + true +} + +fn try_link_toolchain(stage_path: &str) -> bool { + Command::new("rustup") + .stdout(std::process::Stdio::null()) + .args(&["toolchain", "link", "stage1", &stage_path[..]]) + .output() + .map_or(false, |output| output.status.success()) +} + // Used to get the path for `Subcommand::Setup` pub fn interactive_path() -> io::Result { fn abbrev_all() -> impl Iterator { diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index d12e86b7c1..8594fa4226 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -390,7 +390,7 @@ impl Step for Rustfmt { host, "test", "src/tools/rustfmt", - SourceType::Submodule, + SourceType::InTree, &[], ); @@ -653,7 +653,7 @@ impl Step for Clippy { let host = self.host; let compiler = builder.compiler(stage, host); - let clippy = builder + builder .ensure(tool::Clippy { compiler, target: self.host, extra_features: Vec::new() }) .expect("in-tree tool"); let mut cargo = tool::prepare_tool_cargo( @@ -672,14 +672,7 @@ impl Step for Clippy { cargo.env("RUSTC_TEST_SUITE", builder.rustc(compiler)); cargo.env("RUSTC_LIB_PATH", builder.rustc_libdir(compiler)); let host_libs = builder.stage_out(compiler, Mode::ToolRustc).join(builder.cargo_dir()); - let target_libs = builder - .stage_out(compiler, Mode::ToolRustc) - .join(&self.host.triple) - .join(builder.cargo_dir()); cargo.env("HOST_LIBS", host_libs); - cargo.env("TARGET_LIBS", target_libs); - // clippy tests need to find the driver - cargo.env("CLIPPY_DRIVER_PATH", clippy); cargo.arg("--").args(builder.config.cmd.test_args()); @@ -905,7 +898,7 @@ impl Step for RustdocGUI { let out_dir = builder.test_out(self.target).join("rustdoc-gui"); // We remove existing folder to be sure there won't be artifacts remaining. - let _ = fs::remove_dir_all(&out_dir); + builder.clear_if_dirty(&out_dir, &builder.rustdoc(self.compiler)); let src_path = builder.build.src.join("src/test/rustdoc-gui/src"); // We generate docs for the libraries present in the rustdoc-gui's src folder. @@ -925,6 +918,11 @@ impl Step for RustdocGUI { .env("RUSTDOC", builder.rustdoc(self.compiler)) .env("RUSTC", builder.rustc(self.compiler)) .current_dir(path); + // FIXME: implement a `// compile-flags` command or similar + // instead of hard-coding this test + if entry.file_name() == "link_to_definition" { + cargo.env("RUSTDOCFLAGS", "-Zunstable-options --generate-link-to-definition"); + } builder.run(&mut cargo); } } diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs index 365ba9f8df..af6f4bb0e5 100644 --- a/src/bootstrap/tool.rs +++ b/src/bootstrap/tool.rs @@ -377,6 +377,7 @@ bootstrap_tool!( LintDocs, "src/tools/lint-docs", "lint-docs"; JsonDocCk, "src/tools/jsondocck", "jsondocck"; HtmlChecker, "src/tools/html-checker", "html-checker"; + BumpStage0, "src/tools/bump-stage0", "bump-stage0"; ); #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, Ord, PartialOrd)] diff --git a/src/build_helper/Cargo.toml b/src/build_helper/Cargo.toml index 17a9e55b32..d88df0e08f 100644 --- a/src/build_helper/Cargo.toml +++ b/src/build_helper/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "build_helper" version = "0.1.0" -edition = "2018" +edition = "2021" [lib] path = "lib.rs" diff --git a/src/ci/docker/host-x86_64/disabled/dist-m68k-linux/Dockerfile b/src/ci/docker/host-x86_64/disabled/dist-m68k-linux/Dockerfile new file mode 100644 index 0000000000..17203994cd --- /dev/null +++ b/src/ci/docker/host-x86_64/disabled/dist-m68k-linux/Dockerfile @@ -0,0 +1,26 @@ +FROM ubuntu:20.04 + +RUN apt-get update && apt-get install -y --no-install-recommends \ + g++ \ + make \ + file \ + curl \ + ca-certificates \ + python2.7 \ + git \ + cmake \ + sudo \ + gdb \ + xz-utils \ + g++-m68k-linux-gnu \ + libssl-dev \ + pkg-config + + +COPY scripts/sccache.sh /scripts/ +RUN sh /scripts/sccache.sh + +ENV HOSTS=m68k-unknown-linux-gnu + +ENV RUST_CONFIGURE_ARGS --host=$HOSTS --enable-extended +ENV SCRIPT python3 ../x.py dist --host $HOSTS --target $HOSTS diff --git a/src/ci/docker/host-x86_64/dist-i686-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-i686-linux/Dockerfile index 6383665429..2b4b78e813 100644 --- a/src/ci/docker/host-x86_64/dist-i686-linux/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-i686-linux/Dockerfile @@ -1,3 +1,15 @@ +# We need recent curl, OpenSSL and CA certificates, so we can download further +# dependencies in the debian:6 image. We use an ubuntu 20.04 image download +# those. +FROM ubuntu:20.04 +RUN apt-get update && \ + apt-get install -y --no-install-recommends \ + curl \ + ca-certificates +WORKDIR /tmp +COPY host-x86_64/dist-x86_64-linux/download-openssl-curl.sh /tmp/ +RUN ./download-openssl-curl.sh + # We use Debian 6 (glibc 2.11, kernel 2.6.32) as a common base for other # distros that still need Rust support: RHEL 6 (glibc 2.12, kernel 2.6.32) and # SLES 11 SP4 (glibc 2.11, kernel 3.0). @@ -14,8 +26,6 @@ RUN apt-get update && \ apt-get install --allow-unauthenticated -y --no-install-recommends \ automake \ bzip2 \ - ca-certificates \ - curl \ file \ g++ \ g++-multilib \ @@ -34,11 +44,6 @@ RUN apt-get update && \ xz-utils \ zlib1g-dev -# Install new Let's Encrypt root CA certificate and remove the expired one. -COPY host-x86_64/shared/ISRG_Root_X1.crt /usr/local/share/ca-certificates/ISRG_Root_X1.crt -RUN sed -i '/mozilla\/DST_Root_CA_X3\.crt/d' /etc/ca-certificates.conf -RUN /usr/sbin/update-ca-certificates - ENV PATH=/rustroot/bin:$PATH ENV LD_LIBRARY_PATH=/rustroot/lib64:/rustroot/lib32:/rustroot/lib ENV PKG_CONFIG_PATH=/rustroot/lib/pkgconfig @@ -50,6 +55,7 @@ COPY host-x86_64/dist-x86_64-linux/shared.sh /tmp/ # static.rust-lang.org. This'll be used to link into libcurl below (and used # later as well), so build a copy of OpenSSL with dynamic libraries into our # generic root. +COPY --from=0 /tmp/openssl.tar.gz /tmp/openssl.tar.gz COPY host-x86_64/dist-x86_64-linux/build-openssl.sh /tmp/ RUN ./build-openssl.sh @@ -59,8 +65,13 @@ RUN ./build-openssl.sh # # Note that we also disable a bunch of optional features of curl that we don't # really need. +COPY --from=0 /tmp/curl.tar.xz /tmp/curl.tar.xz COPY host-x86_64/dist-x86_64-linux/build-curl.sh /tmp/ -RUN ./build-curl.sh && apt-get remove -y curl +RUN ./build-curl.sh + +# Use up-to-date curl CA bundle +COPY --from=0 /tmp/cacert.pem /tmp/cacert.pem +ENV CURL_CA_BUNDLE /tmp/cacert.pem # binutils < 2.22 has a bug where the 32-bit executables it generates # immediately segfault in Rust, so we need to install our own binutils. diff --git a/src/ci/docker/host-x86_64/dist-various-2/build-wasi-toolchain.sh b/src/ci/docker/host-x86_64/dist-various-2/build-wasi-toolchain.sh index 82d0f7dc47..9bd56394ea 100755 --- a/src/ci/docker/host-x86_64/dist-various-2/build-wasi-toolchain.sh +++ b/src/ci/docker/host-x86_64/dist-various-2/build-wasi-toolchain.sh @@ -10,7 +10,7 @@ export PATH=`pwd`/clang+llvm-11.0.1-x86_64-linux-gnu-ubuntu-16.04/bin:$PATH git clone https://github.com/WebAssembly/wasi-libc cd wasi-libc -git reset --hard 58795582905e08fa7748846c1971b4ab911d1e16 +git reset --hard ad5133410f66b93a2381db5b542aad5e0964db96 make -j$(nproc) INSTALL_DIR=/wasm32-wasi install cd .. 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 7b560aaaaa..5045234993 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 @@ -1,3 +1,15 @@ +# We need recent curl, OpenSSL and CA certificates, so we can download further +# dependencies in the debian:6 image. We use an ubuntu 20.04 image download +# those. +FROM ubuntu:20.04 +RUN apt-get update && \ + apt-get install -y --no-install-recommends \ + curl \ + ca-certificates +WORKDIR /tmp +COPY host-x86_64/dist-x86_64-linux/download-openssl-curl.sh /tmp/ +RUN ./download-openssl-curl.sh + # We use Debian 6 (glibc 2.11, kernel 2.6.32) as a common base for other # distros that still need Rust support: RHEL 6 (glibc 2.12, kernel 2.6.32) and # SLES 11 SP4 (glibc 2.11, kernel 3.0). @@ -14,8 +26,6 @@ RUN apt-get update && \ apt-get install --allow-unauthenticated -y --no-install-recommends \ automake \ bzip2 \ - ca-certificates \ - curl \ file \ g++ \ g++-multilib \ @@ -34,11 +44,6 @@ RUN apt-get update && \ xz-utils \ zlib1g-dev -# Install new Let's Encrypt root CA certificate and remove the expired one. -COPY host-x86_64/shared/ISRG_Root_X1.crt /usr/local/share/ca-certificates/ISRG_Root_X1.crt -RUN sed -i '/mozilla\/DST_Root_CA_X3\.crt/d' /etc/ca-certificates.conf -RUN /usr/sbin/update-ca-certificates - ENV PATH=/rustroot/bin:$PATH ENV LD_LIBRARY_PATH=/rustroot/lib64:/rustroot/lib32:/rustroot/lib ENV PKG_CONFIG_PATH=/rustroot/lib/pkgconfig @@ -50,6 +55,7 @@ COPY host-x86_64/dist-x86_64-linux/shared.sh /tmp/ # static.rust-lang.org. This'll be used to link into libcurl below (and used # later as well), so build a copy of OpenSSL with dynamic libraries into our # generic root. +COPY --from=0 /tmp/openssl.tar.gz /tmp/openssl.tar.gz COPY host-x86_64/dist-x86_64-linux/build-openssl.sh /tmp/ RUN ./build-openssl.sh @@ -59,8 +65,13 @@ RUN ./build-openssl.sh # # Note that we also disable a bunch of optional features of curl that we don't # really need. +COPY --from=0 /tmp/curl.tar.xz /tmp/curl.tar.xz COPY host-x86_64/dist-x86_64-linux/build-curl.sh /tmp/ -RUN ./build-curl.sh && apt-get remove -y curl +RUN ./build-curl.sh + +# Use up-to-date curl CA bundle +COPY --from=0 /tmp/cacert.pem /tmp/cacert.pem +ENV CURL_CA_BUNDLE /tmp/cacert.pem # binutils < 2.22 has a bug where the 32-bit executables it generates # immediately segfault in Rust, so we need to install our own binutils. diff --git a/src/ci/docker/host-x86_64/dist-x86_64-linux/build-curl.sh b/src/ci/docker/host-x86_64/dist-x86_64-linux/build-curl.sh index 6efa789756..88ee96eaa8 100755 --- a/src/ci/docker/host-x86_64/dist-x86_64-linux/build-curl.sh +++ b/src/ci/docker/host-x86_64/dist-x86_64-linux/build-curl.sh @@ -3,18 +3,11 @@ set -ex source shared.sh -VERSION=7.66.0 - -# This needs to be downloaded directly from S3, it can't go through the CDN. -# That's because the CDN is backed by CloudFront, which requires SNI and TLSv1 -# (without paying an absurd amount of money). -curl https://rust-lang-ci-mirrors.s3-us-west-1.amazonaws.com/rustc/curl-$VERSION.tar.xz \ - | xz --decompress \ - | tar xf - +tar xJf curl.tar.xz mkdir curl-build cd curl-build -hide_output ../curl-$VERSION/configure \ +hide_output ../curl-*/configure \ --prefix=/rustroot \ --with-ssl=/rustroot \ --disable-sspi \ @@ -35,4 +28,4 @@ hide_output make install cd .. rm -rf curl-build -rm -rf curl-$VERSION +rm -rf curl-* diff --git a/src/ci/docker/host-x86_64/dist-x86_64-linux/build-openssl.sh b/src/ci/docker/host-x86_64/dist-x86_64-linux/build-openssl.sh index 34bbe19d2f..b48b5c4c00 100755 --- a/src/ci/docker/host-x86_64/dist-x86_64-linux/build-openssl.sh +++ b/src/ci/docker/host-x86_64/dist-x86_64-linux/build-openssl.sh @@ -3,21 +3,14 @@ set -ex source shared.sh -VERSION=1.0.2k +tar xzf openssl.tar.gz -# This needs to be downloaded directly from S3, it can't go through the CDN. -# That's because the CDN is backed by CloudFront, which requires SNI and TLSv1 -# (without paying an absurd amount of money). -URL=https://rust-lang-ci-mirrors.s3-us-west-1.amazonaws.com/rustc/openssl-$VERSION.tar.gz - -curl $URL | tar xzf - - -cd openssl-$VERSION +cd openssl-* hide_output ./config --prefix=/rustroot shared -fPIC hide_output make -j$(nproc) hide_output make install cd .. -rm -rf openssl-$VERSION +rm -rf openssl-* # Make the system cert collection available to the new install. ln -nsf /etc/pki/tls/cert.pem /rustroot/ssl/ diff --git a/src/ci/docker/host-x86_64/dist-x86_64-linux/download-openssl-curl.sh b/src/ci/docker/host-x86_64/dist-x86_64-linux/download-openssl-curl.sh new file mode 100755 index 0000000000..ca40a8cf7d --- /dev/null +++ b/src/ci/docker/host-x86_64/dist-x86_64-linux/download-openssl-curl.sh @@ -0,0 +1,10 @@ +#!/usr/bin/env bash + +set -ex + +OPENSSL_VERSION=1.0.2k +CURL_VERSION=7.66.0 + +curl -f https://ci-mirrors.rust-lang.org/rustc/openssl-$OPENSSL_VERSION.tar.gz -o openssl.tar.gz +curl -f https://ci-mirrors.rust-lang.org/rustc/curl-$CURL_VERSION.tar.xz -o curl.tar.xz +curl -f https://curl.se/ca/cacert.pem -o cacert.pem diff --git a/src/ci/docker/host-x86_64/shared/ISRG_Root_X1.crt b/src/ci/docker/host-x86_64/shared/ISRG_Root_X1.crt deleted file mode 100644 index b85c8037f6..0000000000 --- a/src/ci/docker/host-x86_64/shared/ISRG_Root_X1.crt +++ /dev/null @@ -1,31 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw -TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh -cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4 -WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJu -ZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBY -MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygc -h77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+ -0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6U -A5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sW -T8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyH -B5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UC -B5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUv -KBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWn -OlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTn -jh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbw -qHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CI -rU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV -HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkq -hkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL -ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ -3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KK -NFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5 -ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7Ur -TkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdC -jNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVc -oyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq -4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPA -mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d -emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc= ------END CERTIFICATE----- diff --git a/src/ci/docker/run.sh b/src/ci/docker/run.sh index e42b4748fd..00e8666c54 100755 --- a/src/ci/docker/run.sh +++ b/src/ci/docker/run.sh @@ -50,7 +50,8 @@ if [ -f "$docker_dir/$image/Dockerfile" ]; then # Look for all source files involves in the COPY command copied_files=/tmp/.docker-copied-files.txt rm -f "$copied_files" - for i in $(sed -n -e 's/^COPY \(.*\) .*$/\1/p' "$docker_dir/$image/Dockerfile"); do + for i in $(sed -n -e '/^COPY --from=/! s/^COPY \(.*\) .*$/\1/p' \ + "$docker_dir/$image/Dockerfile"); do # List the file names find "$script_dir/$i" -type f >> $copied_files done diff --git a/src/ci/docker/scripts/freebsd-toolchain.sh b/src/ci/docker/scripts/freebsd-toolchain.sh index c7ff78ca90..70c57e07fd 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; do +for lib in c++ c_nonshared compiler_rt execinfo gcc pthread rt ssp_nonshared procstat; do files_to_extract=("${files_to_extract[@]}" "./usr/lib/lib${lib}.*") done diff --git a/src/ci/github-actions/ci.yml b/src/ci/github-actions/ci.yml index c9f8692d41..eb16cf3c76 100644 --- a/src/ci/github-actions/ci.yml +++ b/src/ci/github-actions/ci.yml @@ -153,10 +153,6 @@ x--expand-yaml-anchors--remove: run: src/ci/scripts/install-sccache.sh <<: *step - - name: select Xcode - run: src/ci/scripts/select-xcode.sh - <<: *step - - name: install clang run: src/ci/scripts/install-clang.sh <<: *step @@ -498,7 +494,6 @@ jobs: --set rust.jemalloc --set llvm.ninja=false RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 - SELECT_XCODE: /Applications/Xcode_12.2.app USE_XCODE_CLANG: 1 MACOSX_DEPLOYMENT_TARGET: 11.0 MACOSX_STD_DEPLOYMENT_TARGET: 11.0 diff --git a/src/ci/scripts/select-xcode.sh b/src/ci/scripts/select-xcode.sh deleted file mode 100755 index 3b9c77d42b..0000000000 --- a/src/ci/scripts/select-xcode.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/bash -# This script selects the Xcode instance to use. - -set -euo pipefail -IFS=$'\n\t' - -source "$(cd "$(dirname "$0")" && pwd)/../shared.sh" - -if isMacOS; then - if [[ -s "${SELECT_XCODE-}" ]]; then - sudo xcode-select -s "${SELECT_XCODE}" - fi -fi diff --git a/src/doc/book/.github/workflows/main.yml b/src/doc/book/.github/workflows/main.yml index 4d07a3c616..53b59cf587 100644 --- a/src/doc/book/.github/workflows/main.yml +++ b/src/doc/book/.github/workflows/main.yml @@ -12,12 +12,12 @@ jobs: - name: Install Rust run: | rustup set profile minimal - rustup toolchain install 1.54 -c rust-docs - rustup default 1.54 + rustup toolchain install 1.55 -c rust-docs + rustup default 1.55 - name: Install mdbook run: | mkdir bin - curl -sSL https://github.com/rust-lang/mdBook/releases/download/v0.4.5/mdbook-v0.4.5-x86_64-unknown-linux-gnu.tar.gz | tar -xz --directory=bin + curl -sSL https://github.com/rust-lang/mdBook/releases/download/v0.4.12/mdbook-v0.4.12-x86_64-unknown-linux-gnu.tar.gz | tar -xz --directory=bin echo "$(pwd)/bin" >> ${GITHUB_PATH} - name: Report versions run: | @@ -41,7 +41,7 @@ jobs: - name: Install mdbook run: | mkdir bin - curl -sSL https://github.com/rust-lang/mdBook/releases/download/v0.4.5/mdbook-v0.4.5-x86_64-unknown-linux-gnu.tar.gz | tar -xz --directory=bin + curl -sSL https://github.com/rust-lang/mdBook/releases/download/v0.4.12/mdbook-v0.4.12-x86_64-unknown-linux-gnu.tar.gz | tar -xz --directory=bin echo "$(pwd)/bin" >> ${GITHUB_PATH} - name: Report versions run: | diff --git a/src/doc/book/listings/ch02-guessing-game-tutorial/listing-02-04/output.txt b/src/doc/book/listings/ch02-guessing-game-tutorial/listing-02-04/output.txt index 6ee46be8bc..62fe8327fc 100644 --- a/src/doc/book/listings/ch02-guessing-game-tutorial/listing-02-04/output.txt +++ b/src/doc/book/listings/ch02-guessing-game-tutorial/listing-02-04/output.txt @@ -16,9 +16,5 @@ 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. +error: could not compile `guessing_game` due to previous error diff --git a/src/doc/book/listings/ch02-guessing-game-tutorial/no-listing-02-without-expect/output.txt b/src/doc/book/listings/ch02-guessing-game-tutorial/no-listing-02-without-expect/output.txt index c56c88971d..8095bbd8db 100644 --- a/src/doc/book/listings/ch02-guessing-game-tutorial/no-listing-02-without-expect/output.txt +++ b/src/doc/book/listings/ch02-guessing-game-tutorial/no-listing-02-without-expect/output.txt @@ -9,6 +9,5 @@ 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 diff --git a/src/doc/book/listings/ch03-common-programming-concepts/no-listing-01-variables-are-immutable/output.txt b/src/doc/book/listings/ch03-common-programming-concepts/no-listing-01-variables-are-immutable/output.txt index c74ef3c44a..2b7e562d3b 100644 --- a/src/doc/book/listings/ch03-common-programming-concepts/no-listing-01-variables-are-immutable/output.txt +++ b/src/doc/book/listings/ch03-common-programming-concepts/no-listing-01-variables-are-immutable/output.txt @@ -12,9 +12,5 @@ error[E0384]: cannot assign twice to immutable variable `x` 4 | x = 6; | ^^^^^ cannot assign twice to immutable variable -error: aborting due to previous error - For more information about this error, try `rustc --explain E0384`. -error: could not compile `variables` - -To learn more, run the command again with --verbose. +error: could not compile `variables` due to previous error diff --git a/src/doc/book/listings/ch03-common-programming-concepts/no-listing-05-mut-cant-change-types/output.txt b/src/doc/book/listings/ch03-common-programming-concepts/no-listing-05-mut-cant-change-types/output.txt index 166b0798c2..8701a07d38 100644 --- a/src/doc/book/listings/ch03-common-programming-concepts/no-listing-05-mut-cant-change-types/output.txt +++ b/src/doc/book/listings/ch03-common-programming-concepts/no-listing-05-mut-cant-change-types/output.txt @@ -6,9 +6,5 @@ error[E0308]: mismatched types 3 | spaces = spaces.len(); | ^^^^^^^^^^^^ expected `&str`, found `usize` -error: aborting due to previous error - For more information about this error, try `rustc --explain E0308`. -error: could not compile `variables` - -To learn more, run the command again with --verbose. +error: could not compile `variables` due to previous error diff --git a/src/doc/book/listings/ch03-common-programming-concepts/no-listing-19-statements-vs-expressions/output.txt b/src/doc/book/listings/ch03-common-programming-concepts/no-listing-19-statements-vs-expressions/output.txt index 7409e856ed..a3a52dbedf 100644 --- a/src/doc/book/listings/ch03-common-programming-concepts/no-listing-19-statements-vs-expressions/output.txt +++ b/src/doc/book/listings/ch03-common-programming-concepts/no-listing-19-statements-vs-expressions/output.txt @@ -25,9 +25,6 @@ warning: unnecessary parentheses around assigned value | = note: `#[warn(unused_parens)]` on by default -error: aborting due to 2 previous errors; 1 warning emitted - For more information about this error, try `rustc --explain E0658`. -error: could not compile `functions` - -To learn more, run the command again with --verbose. +warning: `functions` (bin "functions") generated 1 warning +error: could not compile `functions` due to 2 previous errors; 1 warning emitted diff --git a/src/doc/book/listings/ch03-common-programming-concepts/no-listing-20-blocks-are-expressions/src/main.rs b/src/doc/book/listings/ch03-common-programming-concepts/no-listing-20-blocks-are-expressions/src/main.rs index baa853e187..0be7fcbf31 100644 --- a/src/doc/book/listings/ch03-common-programming-concepts/no-listing-20-blocks-are-expressions/src/main.rs +++ b/src/doc/book/listings/ch03-common-programming-concepts/no-listing-20-blocks-are-expressions/src/main.rs @@ -1,6 +1,4 @@ fn main() { - let x = 5; - let y = { let x = 3; x + 1 diff --git a/src/doc/book/listings/ch03-common-programming-concepts/no-listing-23-statements-dont-return-values/output.txt b/src/doc/book/listings/ch03-common-programming-concepts/no-listing-23-statements-dont-return-values/output.txt index 6657c63d46..4566ab780e 100644 --- a/src/doc/book/listings/ch03-common-programming-concepts/no-listing-23-statements-dont-return-values/output.txt +++ b/src/doc/book/listings/ch03-common-programming-concepts/no-listing-23-statements-dont-return-values/output.txt @@ -10,9 +10,5 @@ error[E0308]: mismatched types 8 | x + 1; | - help: consider removing this semicolon -error: aborting due to previous error - For more information about this error, try `rustc --explain E0308`. -error: could not compile `functions` - -To learn more, run the command again with --verbose. +error: could not compile `functions` due to previous error diff --git a/src/doc/book/listings/ch03-common-programming-concepts/no-listing-28-if-condition-must-be-bool/output.txt b/src/doc/book/listings/ch03-common-programming-concepts/no-listing-28-if-condition-must-be-bool/output.txt index 5ddb737cfb..735bfe758e 100644 --- a/src/doc/book/listings/ch03-common-programming-concepts/no-listing-28-if-condition-must-be-bool/output.txt +++ b/src/doc/book/listings/ch03-common-programming-concepts/no-listing-28-if-condition-must-be-bool/output.txt @@ -6,9 +6,5 @@ error[E0308]: mismatched types 4 | if number { | ^^^^^^ expected `bool`, found integer -error: aborting due to previous error - For more information about this error, try `rustc --explain E0308`. -error: could not compile `branches` - -To learn more, run the command again with --verbose. +error: could not compile `branches` due to previous error diff --git a/src/doc/book/listings/ch03-common-programming-concepts/no-listing-31-arms-must-return-same-type/output.txt b/src/doc/book/listings/ch03-common-programming-concepts/no-listing-31-arms-must-return-same-type/output.txt index 90934b6be4..e922acd29c 100644 --- a/src/doc/book/listings/ch03-common-programming-concepts/no-listing-31-arms-must-return-same-type/output.txt +++ b/src/doc/book/listings/ch03-common-programming-concepts/no-listing-31-arms-must-return-same-type/output.txt @@ -8,9 +8,5 @@ error[E0308]: `if` and `else` have incompatible types | | | expected because of this -error: aborting due to previous error - For more information about this error, try `rustc --explain E0308`. -error: could not compile `branches` - -To learn more, run the command again with --verbose. +error: could not compile `branches` due to previous error diff --git a/src/doc/book/listings/ch03-common-programming-concepts/output-only-01-no-type-annotations/output.txt b/src/doc/book/listings/ch03-common-programming-concepts/output-only-01-no-type-annotations/output.txt index df0ed3515e..d9807cee0a 100644 --- a/src/doc/book/listings/ch03-common-programming-concepts/output-only-01-no-type-annotations/output.txt +++ b/src/doc/book/listings/ch03-common-programming-concepts/output-only-01-no-type-annotations/output.txt @@ -6,9 +6,5 @@ error[E0282]: type annotations needed 2 | let guess = "42".parse().expect("Not a number!"); | ^^^^^ consider giving `guess` a type -error: aborting due to previous error - For more information about this error, try `rustc --explain E0282`. -error: could not compile `no_type_annotations` - -To learn more, run the command again with --verbose. +error: could not compile `no_type_annotations` due to previous error diff --git a/src/doc/book/listings/ch04-understanding-ownership/listing-04-06/output.txt b/src/doc/book/listings/ch04-understanding-ownership/listing-04-06/output.txt index b62dbd0a0d..12db871131 100644 --- a/src/doc/book/listings/ch04-understanding-ownership/listing-04-06/output.txt +++ b/src/doc/book/listings/ch04-understanding-ownership/listing-04-06/output.txt @@ -8,9 +8,5 @@ error[E0596]: cannot borrow `*some_string` as mutable, as it is behind a `&` ref 8 | some_string.push_str(", world"); | ^^^^^^^^^^^ `some_string` 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`. -error: could not compile `ownership` - -To learn more, run the command again with --verbose. +error: could not compile `ownership` due to previous error diff --git a/src/doc/book/listings/ch04-understanding-ownership/no-listing-04-cant-use-after-move/output.txt b/src/doc/book/listings/ch04-understanding-ownership/no-listing-04-cant-use-after-move/output.txt index b69c878131..210ed9ae5e 100644 --- a/src/doc/book/listings/ch04-understanding-ownership/no-listing-04-cant-use-after-move/output.txt +++ b/src/doc/book/listings/ch04-understanding-ownership/no-listing-04-cant-use-after-move/output.txt @@ -11,9 +11,5 @@ error[E0382]: borrow of moved value: `s1` 5 | println!("{}, world!", s1); | ^^ value borrowed here after move -error: aborting due to previous error - For more information about this error, try `rustc --explain E0382`. -error: could not compile `ownership` - -To learn more, run the command again with --verbose. +error: could not compile `ownership` due to previous error diff --git a/src/doc/book/listings/ch04-understanding-ownership/no-listing-10-multiple-mut-not-allowed/output.txt b/src/doc/book/listings/ch04-understanding-ownership/no-listing-10-multiple-mut-not-allowed/output.txt index 7e40a22fb2..71c29f68f1 100644 --- a/src/doc/book/listings/ch04-understanding-ownership/no-listing-10-multiple-mut-not-allowed/output.txt +++ b/src/doc/book/listings/ch04-understanding-ownership/no-listing-10-multiple-mut-not-allowed/output.txt @@ -11,9 +11,5 @@ error[E0499]: cannot borrow `s` as mutable more than once at a time 7 | println!("{}, {}", r1, r2); | -- first borrow later used here -error: aborting due to previous error - For more information about this error, try `rustc --explain E0499`. -error: could not compile `ownership` - -To learn more, run the command again with --verbose. +error: could not compile `ownership` due to previous error diff --git a/src/doc/book/listings/ch04-understanding-ownership/no-listing-12-immutable-and-mutable-not-allowed/output.txt b/src/doc/book/listings/ch04-understanding-ownership/no-listing-12-immutable-and-mutable-not-allowed/output.txt index 25ca95494c..df94c30e98 100644 --- a/src/doc/book/listings/ch04-understanding-ownership/no-listing-12-immutable-and-mutable-not-allowed/output.txt +++ b/src/doc/book/listings/ch04-understanding-ownership/no-listing-12-immutable-and-mutable-not-allowed/output.txt @@ -12,9 +12,5 @@ error[E0502]: cannot borrow `s` as mutable because it is also borrowed as immuta 8 | println!("{}, {}, and {}", r1, r2, r3); | -- immutable borrow later used here -error: aborting due to previous error - For more information about this error, try `rustc --explain E0502`. -error: could not compile `ownership` - -To learn more, run the command again with --verbose. +error: could not compile `ownership` due to previous error diff --git a/src/doc/book/listings/ch04-understanding-ownership/no-listing-14-dangling-reference/output.txt b/src/doc/book/listings/ch04-understanding-ownership/no-listing-14-dangling-reference/output.txt index dc23312387..35265dbc34 100644 --- a/src/doc/book/listings/ch04-understanding-ownership/no-listing-14-dangling-reference/output.txt +++ b/src/doc/book/listings/ch04-understanding-ownership/no-listing-14-dangling-reference/output.txt @@ -12,9 +12,5 @@ help: consider using the `'static` lifetime 5 | fn dangle() -> &'static String { | ^^^^^^^^ -error: aborting due to previous error - For more information about this error, try `rustc --explain E0106`. -error: could not compile `ownership` - -To learn more, run the command again with --verbose. +error: could not compile `ownership` due to previous error diff --git a/src/doc/book/listings/ch04-understanding-ownership/no-listing-19-slice-error/output.txt b/src/doc/book/listings/ch04-understanding-ownership/no-listing-19-slice-error/output.txt index 503a503ca3..62dc4ad526 100644 --- a/src/doc/book/listings/ch04-understanding-ownership/no-listing-19-slice-error/output.txt +++ b/src/doc/book/listings/ch04-understanding-ownership/no-listing-19-slice-error/output.txt @@ -12,9 +12,5 @@ error[E0502]: cannot borrow `s` as mutable because it is also borrowed as immuta 20 | println!("the first word is: {}", word); | ---- immutable borrow later used here -error: aborting due to previous error - For more information about this error, try `rustc --explain E0502`. -error: could not compile `ownership` - -To learn more, run the command again with --verbose. +error: could not compile `ownership` due to previous error diff --git a/src/doc/book/listings/ch05-using-structs-to-structure-related-data/listing-05-11/output.txt b/src/doc/book/listings/ch05-using-structs-to-structure-related-data/listing-05-11/output.txt index 72d73b5b31..b761fccd60 100644 --- a/src/doc/book/listings/ch05-using-structs-to-structure-related-data/listing-05-11/output.txt +++ b/src/doc/book/listings/ch05-using-structs-to-structure-related-data/listing-05-11/output.txt @@ -8,12 +8,7 @@ error[E0277]: `Rectangle` doesn't implement `std::fmt::Display` | = help: the trait `std::fmt::Display` is not implemented for `Rectangle` = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead - = note: required by `std::fmt::Display::fmt` = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error - For more information about this error, try `rustc --explain E0277`. -error: could not compile `rectangles` - -To learn more, run the command again with --verbose. +error: could not compile `rectangles` due to previous error diff --git a/src/doc/book/listings/ch05-using-structs-to-structure-related-data/no-listing-02-reference-in-struct/output.txt b/src/doc/book/listings/ch05-using-structs-to-structure-related-data/no-listing-02-reference-in-struct/output.txt index 9b54ddd8f2..304c1df607 100644 --- a/src/doc/book/listings/ch05-using-structs-to-structure-related-data/no-listing-02-reference-in-struct/output.txt +++ b/src/doc/book/listings/ch05-using-structs-to-structure-related-data/no-listing-02-reference-in-struct/output.txt @@ -1,33 +1,31 @@ $ cargo run Compiling structs v0.1.0 (file:///projects/structs) error[E0106]: missing lifetime specifier - --> src/main.rs:2:15 + --> src/main.rs:3:15 | -2 | username: &str, +3 | username: &str, | ^ expected named lifetime parameter | help: consider introducing a named lifetime parameter | 1 | struct User<'a> { -2 | username: &'a str, +2 | active: bool, +3 | username: &'a str, | error[E0106]: missing lifetime specifier - --> src/main.rs:3:12 + --> src/main.rs:4:12 | -3 | email: &str, +4 | email: &str, | ^ expected named lifetime parameter | help: consider introducing a named lifetime parameter | 1 | struct User<'a> { -2 | username: &str, -3 | email: &'a str, +2 | active: bool, +3 | username: &str, +4 | email: &'a str, | -error: aborting due to 2 previous errors - For more information about this error, try `rustc --explain E0106`. -error: could not compile `structs` - -To learn more, run the command again with --verbose. +error: could not compile `structs` due to 2 previous errors diff --git a/src/doc/book/listings/ch05-using-structs-to-structure-related-data/output-only-01-debug/output.txt b/src/doc/book/listings/ch05-using-structs-to-structure-related-data/output-only-01-debug/output.txt index 67f01e6d24..8b9c2abb33 100644 --- a/src/doc/book/listings/ch05-using-structs-to-structure-related-data/output-only-01-debug/output.txt +++ b/src/doc/book/listings/ch05-using-structs-to-structure-related-data/output-only-01-debug/output.txt @@ -7,13 +7,8 @@ error[E0277]: `Rectangle` doesn't implement `Debug` | ^^^^^ `Rectangle` cannot be formatted using `{:?}` | = help: the trait `Debug` is not implemented for `Rectangle` - = note: add `#[derive(Debug)]` or manually implement `Debug` - = note: required by `std::fmt::Debug::fmt` + = note: add `#[derive(Debug)]` to `Rectangle` or manually `impl Debug for Rectangle` = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error - For more information about this error, try `rustc --explain E0277`. -error: could not compile `rectangles` - -To learn more, run the command again with --verbose. +error: could not compile `rectangles` due to previous error diff --git a/src/doc/book/listings/ch06-enums-and-pattern-matching/no-listing-07-cant-use-option-directly/output.txt b/src/doc/book/listings/ch06-enums-and-pattern-matching/no-listing-07-cant-use-option-directly/output.txt index 856826ca06..343b9d236a 100644 --- a/src/doc/book/listings/ch06-enums-and-pattern-matching/no-listing-07-cant-use-option-directly/output.txt +++ b/src/doc/book/listings/ch06-enums-and-pattern-matching/no-listing-07-cant-use-option-directly/output.txt @@ -8,9 +8,5 @@ error[E0277]: cannot add `Option` to `i8` | = help: the trait `Add>` is not implemented for `i8` -error: aborting due to previous error - For more information about this error, try `rustc --explain E0277`. -error: could not compile `enums` - -To learn more, run the command again with --verbose. +error: could not compile `enums` due to previous error diff --git a/src/doc/book/listings/ch06-enums-and-pattern-matching/no-listing-10-non-exhaustive-match/output.txt b/src/doc/book/listings/ch06-enums-and-pattern-matching/no-listing-10-non-exhaustive-match/output.txt index 0ab76cce95..8054e7dfa5 100644 --- a/src/doc/book/listings/ch06-enums-and-pattern-matching/no-listing-10-non-exhaustive-match/output.txt +++ b/src/doc/book/listings/ch06-enums-and-pattern-matching/no-listing-10-non-exhaustive-match/output.txt @@ -9,9 +9,5 @@ error[E0004]: non-exhaustive patterns: `None` not covered = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms = note: the matched value is of type `Option` -error: aborting due to previous error - For more information about this error, try `rustc --explain E0004`. -error: could not compile `enums` - -To learn more, run the command again with --verbose. +error: could not compile `enums` due to previous error diff --git a/src/doc/book/listings/ch07-managing-growing-projects/listing-07-03/output.txt b/src/doc/book/listings/ch07-managing-growing-projects/listing-07-03/output.txt index 4979d5f642..481dcb3f74 100644 --- a/src/doc/book/listings/ch07-managing-growing-projects/listing-07-03/output.txt +++ b/src/doc/book/listings/ch07-managing-growing-projects/listing-07-03/output.txt @@ -24,9 +24,5 @@ note: the module `hosting` is defined here 2 | mod hosting { | ^^^^^^^^^^^ -error: aborting due to 2 previous errors - For more information about this error, try `rustc --explain E0603`. -error: could not compile `restaurant` - -To learn more, run the command again with --verbose. +error: could not compile `restaurant` due to 2 previous errors diff --git a/src/doc/book/listings/ch07-managing-growing-projects/listing-07-05/output.txt b/src/doc/book/listings/ch07-managing-growing-projects/listing-07-05/output.txt index 22b4601958..63eb89a146 100644 --- a/src/doc/book/listings/ch07-managing-growing-projects/listing-07-05/output.txt +++ b/src/doc/book/listings/ch07-managing-growing-projects/listing-07-05/output.txt @@ -24,9 +24,5 @@ note: the function `add_to_waitlist` is defined here 3 | fn add_to_waitlist() {} | ^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 2 previous errors - For more information about this error, try `rustc --explain E0603`. -error: could not compile `restaurant` - -To learn more, run the command again with --verbose. +error: could not compile `restaurant` due to 2 previous errors diff --git a/src/doc/book/listings/ch08-common-collections/listing-08-07/output.txt b/src/doc/book/listings/ch08-common-collections/listing-08-07/output.txt index d99310d25a..ab512a9e65 100644 --- a/src/doc/book/listings/ch08-common-collections/listing-08-07/output.txt +++ b/src/doc/book/listings/ch08-common-collections/listing-08-07/output.txt @@ -12,9 +12,5 @@ error[E0502]: cannot borrow `v` as mutable because it is also borrowed as immuta 8 | println!("The first element is: {}", first); | ----- immutable borrow later used here -error: aborting due to previous error - For more information about this error, try `rustc --explain E0502`. -error: could not compile `collections` - -To learn more, run the command again with --verbose. +error: could not compile `collections` due to previous error diff --git a/src/doc/book/listings/ch08-common-collections/listing-08-19/output.txt b/src/doc/book/listings/ch08-common-collections/listing-08-19/output.txt index d6e45b2696..2e5ad54777 100644 --- a/src/doc/book/listings/ch08-common-collections/listing-08-19/output.txt +++ b/src/doc/book/listings/ch08-common-collections/listing-08-19/output.txt @@ -8,9 +8,5 @@ error[E0277]: the type `String` cannot be indexed by `{integer}` | = help: the trait `Index<{integer}>` is not implemented for `String` -error: aborting due to previous error - For more information about this error, try `rustc --explain E0277`. -error: could not compile `collections` - -To learn more, run the command again with --verbose. +error: could not compile `collections` due to previous error diff --git a/src/doc/book/listings/ch09-error-handling/no-listing-02-ask-compiler-for-type/output.txt b/src/doc/book/listings/ch09-error-handling/no-listing-02-ask-compiler-for-type/output.txt index 6436fe6774..aa95afabe4 100644 --- a/src/doc/book/listings/ch09-error-handling/no-listing-02-ask-compiler-for-type/output.txt +++ b/src/doc/book/listings/ch09-error-handling/no-listing-02-ask-compiler-for-type/output.txt @@ -11,9 +11,5 @@ error[E0308]: mismatched types = note: expected type `u32` found enum `Result` -error: aborting due to previous error - For more information about this error, try `rustc --explain E0308`. -error: could not compile `error-handling` - -To learn more, run the command again with --verbose. +error: could not compile `error-handling` due to previous error 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/no-listing-06-question-mark-in-main/output.txt index f4bbccc9e7..4c36d20285 100644 --- 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/no-listing-06-question-mark-in-main/output.txt @@ -1,20 +1,16 @@ $ cargo run Compiling error-handling v0.1.0 (file:///projects/error-handling) 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 `?` - | - = help: the trait `FromResidual>` is not implemented for `()` - = note: required by `from_residual` - -error: aborting due to previous error + --> 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 `?` + | + = help: the trait `FromResidual>` is not implemented for `()` +note: required by `from_residual` For more information about this error, try `rustc --explain E0277`. -error: could not compile `error-handling` - -To learn more, run the command again with --verbose. +error: could not compile `error-handling` due to previous error diff --git a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-05/output.txt b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-05/output.txt index 9b6e53e47a..0738325ac3 100644 --- a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-05/output.txt +++ b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-05/output.txt @@ -13,9 +13,5 @@ help: consider restricting type parameter `T` 1 | fn largest(list: &[T]) -> T { | ^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error - For more information about this error, try `rustc --explain E0369`. -error: could not compile `chapter10` - -To learn more, run the command again with --verbose. +error: could not compile `chapter10` due to previous error diff --git a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-07/output.txt b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-07/output.txt index 5f32bdc18d..2482c38432 100644 --- a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-07/output.txt +++ b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-07/output.txt @@ -6,9 +6,5 @@ error[E0308]: mismatched types 7 | let wont_work = Point { x: 5, y: 4.0 }; | ^^^ expected integer, found floating-point number -error: aborting due to previous error - For more information about this error, try `rustc --explain E0308`. -error: could not compile `chapter10` - -To learn more, run the command again with --verbose. +error: could not compile `chapter10` due to previous error diff --git a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-17/output.txt b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-17/output.txt index c79e59c26b..8b239e422d 100644 --- a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-17/output.txt +++ b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-17/output.txt @@ -11,9 +11,5 @@ error[E0597]: `x` does not live long enough 10 | println!("r: {}", r); | - borrow later used here -error: aborting due to previous error - For more information about this error, try `rustc --explain E0597`. -error: could not compile `chapter10` - -To learn more, run the command again with --verbose. +error: could not compile `chapter10` due to previous error diff --git a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-21/output.txt b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-21/output.txt index aa38ce00bc..a39351a6e9 100644 --- a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-21/output.txt +++ b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-21/output.txt @@ -12,9 +12,5 @@ help: consider introducing a named lifetime parameter 9 | fn longest<'a>(x: &'a str, y: &'a str) -> &'a str { | ^^^^ ^^^^^^^ ^^^^^^^ ^^^ -error: aborting due to previous error - For more information about this error, try `rustc --explain E0106`. -error: could not compile `chapter10` - -To learn more, run the command again with --verbose. +error: could not compile `chapter10` due to previous error diff --git a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-24/output.txt b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-24/output.txt index 05ffdc7377..6378f5a81c 100644 --- a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-24/output.txt +++ b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-24/output.txt @@ -10,9 +10,5 @@ error[E0597]: `string2` does not live long enough 8 | println!("The longest string is {}", result); | ------ borrow later used here -error: aborting due to previous error - For more information about this error, try `rustc --explain E0597`. -error: could not compile `chapter10` - -To learn more, run the command again with --verbose. +error: could not compile `chapter10` due to previous error diff --git a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-07-fixing-listing-10-05/output.txt b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-07-fixing-listing-10-05/output.txt index 0a3e7f5277..eca02c28be 100644 --- a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-07-fixing-listing-10-05/output.txt +++ b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-07-fixing-listing-10-05/output.txt @@ -20,10 +20,6 @@ error[E0507]: cannot move out of a shared reference | |move occurs because `item` has type `T`, which does not implement the `Copy` trait | help: consider removing the `&`: `item` -error: aborting due to 2 previous errors - Some errors have detailed explanations: E0507, E0508. For more information about an error, try `rustc --explain E0507`. -error: could not compile `chapter10` - -To learn more, run the command again with --verbose. +error: could not compile `chapter10` due to 2 previous errors diff --git a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-09-unrelated-lifetime/output.txt b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-09-unrelated-lifetime/output.txt index de29d4f43c..94645b2f47 100644 --- a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-09-unrelated-lifetime/output.txt +++ b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-09-unrelated-lifetime/output.txt @@ -9,9 +9,5 @@ error[E0515]: cannot return value referencing local variable `result` | returns a value referencing data owned by the current function | `result` is borrowed here -error: aborting due to previous error - For more information about this error, try `rustc --explain E0515`. -error: could not compile `chapter10` - -To learn more, run the command again with --verbose. +error: could not compile `chapter10` due to previous error diff --git a/src/doc/book/listings/ch11-writing-automated-tests/no-listing-11-ignore-a-test/output.txt b/src/doc/book/listings/ch11-writing-automated-tests/no-listing-11-ignore-a-test/output.txt index 8931f0d8e5..fcdff2517e 100644 --- a/src/doc/book/listings/ch11-writing-automated-tests/no-listing-11-ignore-a-test/output.txt +++ b/src/doc/book/listings/ch11-writing-automated-tests/no-listing-11-ignore-a-test/output.txt @@ -7,7 +7,7 @@ running 2 tests test expensive_test ... ignored test it_works ... ok -test result: ok. 1 passed; 0 failed; 1 ignored; 0 measured; 0 filtered out; finished in 0.02s +test result: ok. 1 passed; 0 failed; 1 ignored; 0 measured; 0 filtered out; finished in 0.00s Doc-tests adder diff --git a/src/doc/book/listings/ch12-an-io-project/listing-12-12/output.txt b/src/doc/book/listings/ch12-an-io-project/listing-12-12/output.txt index 91ee1df01b..c18902518e 100644 --- a/src/doc/book/listings/ch12-an-io-project/listing-12-12/output.txt +++ b/src/doc/book/listings/ch12-an-io-project/listing-12-12/output.txt @@ -9,8 +9,7 @@ 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: `minigrep` (bin "minigrep") generated 1 warning Finished dev [unoptimized + debuginfo] target(s) in 0.71s Running `target/debug/minigrep the poem.txt` Searching for the diff --git a/src/doc/book/listings/ch12-an-io-project/output-only-02-missing-lifetimes/output.txt b/src/doc/book/listings/ch12-an-io-project/output-only-02-missing-lifetimes/output.txt index 8ba8fac52a..33036173da 100644 --- a/src/doc/book/listings/ch12-an-io-project/output-only-02-missing-lifetimes/output.txt +++ b/src/doc/book/listings/ch12-an-io-project/output-only-02-missing-lifetimes/output.txt @@ -12,9 +12,5 @@ help: consider introducing a named lifetime parameter 28 | pub fn search<'a>(query: &'a str, contents: &'a str) -> Vec<&'a str> { | ^^^^ ^^^^^^^ ^^^^^^^ ^^^ -error: aborting due to previous error - For more information about this error, try `rustc --explain E0106`. -error: could not compile `minigrep` - -To learn more, run the command again with --verbose. +error: could not compile `minigrep` due to previous error diff --git a/src/doc/book/listings/ch13-functional-features/listing-13-08/output.txt b/src/doc/book/listings/ch13-functional-features/listing-13-08/output.txt index a90814c347..30c51e12a0 100644 --- a/src/doc/book/listings/ch13-functional-features/listing-13-08/output.txt +++ b/src/doc/book/listings/ch13-functional-features/listing-13-08/output.txt @@ -9,9 +9,5 @@ error[E0308]: mismatched types | expected struct `String`, found integer | help: try using a conversion method: `5.to_string()` -error: aborting due to previous error - For more information about this error, try `rustc --explain E0308`. -error: could not compile `closure-example` - -To learn more, run the command again with --verbose. +error: could not compile `closure-example` due to previous error diff --git a/src/doc/book/listings/ch13-functional-features/listing-13-17/output.txt b/src/doc/book/listings/ch13-functional-features/listing-13-17/output.txt index 67f05573bd..228c764ed2 100644 --- a/src/doc/book/listings/ch13-functional-features/listing-13-17/output.txt +++ b/src/doc/book/listings/ch13-functional-features/listing-13-17/output.txt @@ -9,7 +9,6 @@ warning: unused `Map` that must be used = note: `#[warn(unused_must_use)]` on by default = note: iterators are lazy and do nothing unless consumed -warning: 1 warning emitted - +warning: `iterators` (bin "iterators") generated 1 warning Finished dev [unoptimized + debuginfo] target(s) in 0.47s Running `target/debug/iterators` diff --git a/src/doc/book/listings/ch13-functional-features/no-listing-02-functions-cant-capture/output.txt b/src/doc/book/listings/ch13-functional-features/no-listing-02-functions-cant-capture/output.txt index 8fa9df0f7c..3cf9915166 100644 --- a/src/doc/book/listings/ch13-functional-features/no-listing-02-functions-cant-capture/output.txt +++ b/src/doc/book/listings/ch13-functional-features/no-listing-02-functions-cant-capture/output.txt @@ -8,9 +8,5 @@ error[E0434]: can't capture dynamic environment in a fn item | = help: use the `|| { ... }` closure form instead -error: aborting due to previous error - For more information about this error, try `rustc --explain E0434`. -error: could not compile `equal-to-x` - -To learn more, run the command again with --verbose. +error: could not compile `equal-to-x` due to previous error diff --git a/src/doc/book/listings/ch13-functional-features/no-listing-03-move-closures/output.txt b/src/doc/book/listings/ch13-functional-features/no-listing-03-move-closures/output.txt index 3ca1901925..ae1aa91a7e 100644 --- a/src/doc/book/listings/ch13-functional-features/no-listing-03-move-closures/output.txt +++ b/src/doc/book/listings/ch13-functional-features/no-listing-03-move-closures/output.txt @@ -14,9 +14,5 @@ error[E0382]: borrow of moved value: `x` 6 | println!("can't use x here: {:?}", x); | ^ value borrowed here after move -error: aborting due to previous error - For more information about this error, try `rustc --explain E0382`. -error: could not compile `equal-to-x` - -To learn more, run the command again with --verbose. +error: could not compile `equal-to-x` due to previous error diff --git a/src/doc/book/listings/ch15-smart-pointers/listing-15-03/output.txt b/src/doc/book/listings/ch15-smart-pointers/listing-15-03/output.txt index 741e404963..e4180993a5 100644 --- a/src/doc/book/listings/ch15-smart-pointers/listing-15-03/output.txt +++ b/src/doc/book/listings/ch15-smart-pointers/listing-15-03/output.txt @@ -22,10 +22,6 @@ error[E0391]: cycle detected when computing drop-check constraints for `List` = note: ...which again requires computing drop-check constraints for `List`, completing the cycle = note: cycle used when computing dropck types for `Canonical { max_universe: U0, variables: [], value: ParamEnvAnd { param_env: ParamEnv { caller_bounds: [], reveal: UserFacing }, value: List } }` -error: aborting due to 2 previous errors - Some errors have detailed explanations: E0072, E0391. For more information about an error, try `rustc --explain E0072`. -error: could not compile `cons-list` - -To learn more, run the command again with --verbose. +error: could not compile `cons-list` due to 2 previous errors diff --git a/src/doc/book/listings/ch15-smart-pointers/listing-15-09/output.txt b/src/doc/book/listings/ch15-smart-pointers/listing-15-09/output.txt index a2b7995a25..75e5f1c8c4 100644 --- a/src/doc/book/listings/ch15-smart-pointers/listing-15-09/output.txt +++ b/src/doc/book/listings/ch15-smart-pointers/listing-15-09/output.txt @@ -6,9 +6,5 @@ error[E0614]: type `MyBox<{integer}>` cannot be dereferenced 14 | assert_eq!(5, *y); | ^^ -error: aborting due to previous error - For more information about this error, try `rustc --explain E0614`. -error: could not compile `deref-example` - -To learn more, run the command again with --verbose. +error: could not compile `deref-example` due to previous error diff --git a/src/doc/book/listings/ch15-smart-pointers/listing-15-15/output.txt b/src/doc/book/listings/ch15-smart-pointers/listing-15-15/output.txt index 86fe81065e..a38c9ccb76 100644 --- a/src/doc/book/listings/ch15-smart-pointers/listing-15-15/output.txt +++ b/src/doc/book/listings/ch15-smart-pointers/listing-15-15/output.txt @@ -9,9 +9,5 @@ error[E0040]: explicit use of destructor method | | explicit destructor calls not allowed | help: consider using `drop` function: `drop(c)` -error: aborting due to previous error - For more information about this error, try `rustc --explain E0040`. -error: could not compile `drop-example` - -To learn more, run the command again with --verbose. +error: could not compile `drop-example` due to previous error diff --git a/src/doc/book/listings/ch15-smart-pointers/listing-15-17/output.txt b/src/doc/book/listings/ch15-smart-pointers/listing-15-17/output.txt index a4aaeba5fb..ab314d8837 100644 --- a/src/doc/book/listings/ch15-smart-pointers/listing-15-17/output.txt +++ b/src/doc/book/listings/ch15-smart-pointers/listing-15-17/output.txt @@ -10,9 +10,5 @@ error[E0382]: use of moved value: `a` 11 | let c = Cons(4, Box::new(a)); | ^ value used here after move -error: aborting due to previous error - For more information about this error, try `rustc --explain E0382`. -error: could not compile `cons-list` - -To learn more, run the command again with --verbose. +error: could not compile `cons-list` due to previous error diff --git a/src/doc/book/listings/ch15-smart-pointers/listing-15-21/output.txt b/src/doc/book/listings/ch15-smart-pointers/listing-15-21/output.txt index 3c457938c9..9796bd7bf0 100644 --- a/src/doc/book/listings/ch15-smart-pointers/listing-15-21/output.txt +++ b/src/doc/book/listings/ch15-smart-pointers/listing-15-21/output.txt @@ -9,11 +9,7 @@ error[E0596]: cannot borrow `self.sent_messages` as mutable, as it is behind a ` 58 | self.sent_messages.push(String::from(message)); | ^^^^^^^^^^^^^^^^^^ `self` 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`. -error: could not compile `limit-tracker` - -To learn more, run the command again with --verbose. +error: could not compile `limit-tracker` due to previous error warning: build failed, waiting for other jobs to finish... error: build failed diff --git a/src/doc/book/listings/ch15-smart-pointers/no-listing-01-cant-borrow-immutable-as-mutable/output.txt b/src/doc/book/listings/ch15-smart-pointers/no-listing-01-cant-borrow-immutable-as-mutable/output.txt index 28924261c8..8e84746eec 100644 --- a/src/doc/book/listings/ch15-smart-pointers/no-listing-01-cant-borrow-immutable-as-mutable/output.txt +++ b/src/doc/book/listings/ch15-smart-pointers/no-listing-01-cant-borrow-immutable-as-mutable/output.txt @@ -8,9 +8,5 @@ error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable 3 | let y = &mut x; | ^^^^^^ cannot borrow as mutable -error: aborting due to previous error - For more information about this error, try `rustc --explain E0596`. -error: could not compile `borrowing` - -To learn more, run the command again with --verbose. +error: could not compile `borrowing` due to previous error diff --git a/src/doc/book/listings/ch15-smart-pointers/output-only-01-comparing-to-reference/output.txt b/src/doc/book/listings/ch15-smart-pointers/output-only-01-comparing-to-reference/output.txt index 11eca77c2c..e9bbab0dbc 100644 --- a/src/doc/book/listings/ch15-smart-pointers/output-only-01-comparing-to-reference/output.txt +++ b/src/doc/book/listings/ch15-smart-pointers/output-only-01-comparing-to-reference/output.txt @@ -9,9 +9,5 @@ error[E0277]: can't compare `{integer}` with `&{integer}` = help: the trait `PartialEq<&{integer}>` is not implemented for `{integer}` = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error - For more information about this error, try `rustc --explain E0277`. -error: could not compile `deref-example` - -To learn more, run the command again with --verbose. +error: could not compile `deref-example` due to previous error diff --git a/src/doc/book/listings/ch16-fearless-concurrency/listing-16-03/output.txt b/src/doc/book/listings/ch16-fearless-concurrency/listing-16-03/output.txt index 1223d38356..23d3aaf278 100644 --- a/src/doc/book/listings/ch16-fearless-concurrency/listing-16-03/output.txt +++ b/src/doc/book/listings/ch16-fearless-concurrency/listing-16-03/output.txt @@ -21,9 +21,5 @@ help: to force the closure to take ownership of `v` (and any other referenced va 6 | let handle = thread::spawn(move || { | ^^^^^^^ -error: aborting due to previous error - For more information about this error, try `rustc --explain E0373`. -error: could not compile `threads` - -To learn more, run the command again with --verbose. +error: could not compile `threads` due to previous error diff --git a/src/doc/book/listings/ch16-fearless-concurrency/listing-16-09/output.txt b/src/doc/book/listings/ch16-fearless-concurrency/listing-16-09/output.txt index deb47c97b4..bb2639d243 100644 --- a/src/doc/book/listings/ch16-fearless-concurrency/listing-16-09/output.txt +++ b/src/doc/book/listings/ch16-fearless-concurrency/listing-16-09/output.txt @@ -10,9 +10,5 @@ error[E0382]: borrow of moved value: `val` 10 | println!("val is {}", val); | ^^^ value borrowed here after move -error: aborting due to previous error - For more information about this error, try `rustc --explain E0382`. -error: could not compile `message-passing` - -To learn more, run the command again with --verbose. +error: could not compile `message-passing` due to previous error diff --git a/src/doc/book/listings/ch16-fearless-concurrency/listing-16-13/output.txt b/src/doc/book/listings/ch16-fearless-concurrency/listing-16-13/output.txt index 69e0b097d9..ea6963903d 100644 --- a/src/doc/book/listings/ch16-fearless-concurrency/listing-16-13/output.txt +++ b/src/doc/book/listings/ch16-fearless-concurrency/listing-16-13/output.txt @@ -11,9 +11,5 @@ error[E0382]: use of moved value: `counter` 10 | let mut num = counter.lock().unwrap(); | ------- use occurs due to use in closure -error: aborting due to previous error - For more information about this error, try `rustc --explain E0382`. -error: could not compile `shared-state` - -To learn more, run the command again with --verbose. +error: could not compile `shared-state` due to previous error diff --git a/src/doc/book/listings/ch16-fearless-concurrency/listing-16-14/output.txt b/src/doc/book/listings/ch16-fearless-concurrency/listing-16-14/output.txt index cd2d05b674..ffdd0674b8 100644 --- a/src/doc/book/listings/ch16-fearless-concurrency/listing-16-14/output.txt +++ b/src/doc/book/listings/ch16-fearless-concurrency/listing-16-14/output.txt @@ -16,9 +16,5 @@ error[E0277]: `Rc>` cannot be sent between threads safely = help: within `[closure@src/main.rs:11:36: 15:10]`, the trait `Send` is not implemented for `Rc>` = note: required because it appears within the type `[closure@src/main.rs:11:36: 15:10]` -error: aborting due to previous error - For more information about this error, try `rustc --explain E0277`. -error: could not compile `shared-state` - -To learn more, run the command again with --verbose. +error: could not compile `shared-state` due to previous error diff --git a/src/doc/book/listings/ch16-fearless-concurrency/output-only-01-move-drop/output.txt b/src/doc/book/listings/ch16-fearless-concurrency/output-only-01-move-drop/output.txt index 0a73128d50..f7be53b9a2 100644 --- a/src/doc/book/listings/ch16-fearless-concurrency/output-only-01-move-drop/output.txt +++ b/src/doc/book/listings/ch16-fearless-concurrency/output-only-01-move-drop/output.txt @@ -14,9 +14,5 @@ error[E0382]: use of moved value: `v` 10 | drop(v); // oh no! | ^ value used here after move -error: aborting due to previous error - For more information about this error, try `rustc --explain E0382`. -error: could not compile `threads` - -To learn more, run the command again with --verbose. +error: could not compile `threads` due to previous error diff --git a/src/doc/book/listings/ch17-oop/listing-17-10/output.txt b/src/doc/book/listings/ch17-oop/listing-17-10/output.txt index 893abd63ba..4015577105 100644 --- a/src/doc/book/listings/ch17-oop/listing-17-10/output.txt +++ b/src/doc/book/listings/ch17-oop/listing-17-10/output.txt @@ -8,9 +8,5 @@ error[E0277]: the trait bound `String: Draw` is not satisfied | = note: required for the cast to the object type `dyn Draw` -error: aborting due to previous error - For more information about this error, try `rustc --explain E0277`. -error: could not compile `gui` - -To learn more, run the command again with --verbose. +error: could not compile `gui` due to previous error diff --git a/src/doc/book/listings/ch17-oop/no-listing-01-trait-object-of-clone/output.txt b/src/doc/book/listings/ch17-oop/no-listing-01-trait-object-of-clone/output.txt index 40d6c7f9fa..fa60c4a420 100644 --- a/src/doc/book/listings/ch17-oop/no-listing-01-trait-object-of-clone/output.txt +++ b/src/doc/book/listings/ch17-oop/no-listing-01-trait-object-of-clone/output.txt @@ -1,17 +1,13 @@ $ cargo build Compiling gui v0.1.0 (file:///projects/gui) error[E0038]: the trait `Clone` cannot be made into an object - --> src/lib.rs:2:21 + --> src/lib.rs:2:29 | 2 | pub components: Vec>, - | ^^^^^^^^^^^^^^^^^^^ `Clone` cannot be made into an object + | ^^^^^^^^^ `Clone` cannot be made into an object | = note: the trait cannot be made into an object because it requires `Self: Sized` = note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit -error: aborting due to previous error - For more information about this error, try `rustc --explain E0038`. -error: could not compile `gui` - -To learn more, run the command again with --verbose. +error: could not compile `gui` due to previous error diff --git a/src/doc/book/listings/ch18-patterns-and-matching/listing-18-05/output.txt b/src/doc/book/listings/ch18-patterns-and-matching/listing-18-05/output.txt index 12eeda74e2..57916a1f15 100644 --- a/src/doc/book/listings/ch18-patterns-and-matching/listing-18-05/output.txt +++ b/src/doc/book/listings/ch18-patterns-and-matching/listing-18-05/output.txt @@ -11,9 +11,5 @@ error[E0308]: mismatched types = note: expected tuple `({integer}, {integer}, {integer})` found tuple `(_, _)` -error: aborting due to previous error - For more information about this error, try `rustc --explain E0308`. -error: could not compile `patterns` - -To learn more, run the command again with --verbose. +error: could not compile `patterns` due to previous error diff --git a/src/doc/book/listings/ch18-patterns-and-matching/listing-18-08/output.txt b/src/doc/book/listings/ch18-patterns-and-matching/listing-18-08/output.txt index 1843ece4b3..5915c39c88 100644 --- a/src/doc/book/listings/ch18-patterns-and-matching/listing-18-08/output.txt +++ b/src/doc/book/listings/ch18-patterns-and-matching/listing-18-08/output.txt @@ -14,9 +14,5 @@ help: you might want to use `if let` to ignore the variant that isn't matched 3 | if let Some(x) = some_option_value { /* */ } | -error: aborting due to previous error - For more information about this error, try `rustc --explain E0005`. -error: could not compile `patterns` - -To learn more, run the command again with --verbose. +error: could not compile `patterns` due to previous error diff --git a/src/doc/book/listings/ch18-patterns-and-matching/listing-18-10/output.txt b/src/doc/book/listings/ch18-patterns-and-matching/listing-18-10/output.txt index f30dd5fa88..b527311bb1 100644 --- a/src/doc/book/listings/ch18-patterns-and-matching/listing-18-10/output.txt +++ b/src/doc/book/listings/ch18-patterns-and-matching/listing-18-10/output.txt @@ -12,8 +12,7 @@ warning: irrefutable `if let` pattern = note: this pattern will always match, so the `if let` is useless = help: consider replacing the `if let` with a `let` -warning: 1 warning emitted - +warning: `patterns` (bin "patterns") generated 1 warning Finished dev [unoptimized + debuginfo] target(s) in 0.39s Running `target/debug/patterns` 5 diff --git a/src/doc/book/listings/ch18-patterns-and-matching/listing-18-25/output.txt b/src/doc/book/listings/ch18-patterns-and-matching/listing-18-25/output.txt index 9ba40fa1c1..7e0357eac2 100644 --- a/src/doc/book/listings/ch18-patterns-and-matching/listing-18-25/output.txt +++ b/src/doc/book/listings/ch18-patterns-and-matching/listing-18-25/output.txt @@ -8,8 +8,4 @@ error: `..` can only be used once per tuple pattern | | | previously used here -error: aborting due to previous error - -error: could not compile `patterns` - -To learn more, run the command again with --verbose. +error: could not compile `patterns` due to previous error diff --git a/src/doc/book/listings/ch19-advanced-features/listing-19-05/output.txt b/src/doc/book/listings/ch19-advanced-features/listing-19-05/output.txt index 559729f602..18191f8e33 100644 --- a/src/doc/book/listings/ch19-advanced-features/listing-19-05/output.txt +++ b/src/doc/book/listings/ch19-advanced-features/listing-19-05/output.txt @@ -13,9 +13,5 @@ error[E0499]: cannot borrow `*slice` as mutable more than once at a time | | first mutable borrow occurs here | returning this value requires that `*slice` is borrowed for `'1` -error: aborting due to previous error - For more information about this error, try `rustc --explain E0499`. -error: could not compile `unsafe-example` - -To learn more, run the command again with --verbose. +error: could not compile `unsafe-example` due to previous error diff --git a/src/doc/book/listings/ch19-advanced-features/listing-19-20/output.txt b/src/doc/book/listings/ch19-advanced-features/listing-19-20/output.txt index b95dde7627..7e3f189f35 100644 --- a/src/doc/book/listings/ch19-advanced-features/listing-19-20/output.txt +++ b/src/doc/book/listings/ch19-advanced-features/listing-19-20/output.txt @@ -3,17 +3,15 @@ $ cargo run error[E0283]: type annotations needed --> src/main.rs:20:43 | -2 | fn baby_name() -> String; - | ------------------------- required by `Animal::baby_name` -... 20 | println!("A baby dog is called a {}", Animal::baby_name()); | ^^^^^^^^^^^^^^^^^ cannot infer type | = note: cannot satisfy `_: Animal` - -error: aborting due to previous error +note: required by `Animal::baby_name` + --> src/main.rs:2:5 + | +2 | fn baby_name() -> String; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ For more information about this error, try `rustc --explain E0283`. -error: could not compile `traits-example` - -To learn more, run the command again with --verbose. +error: could not compile `traits-example` due to previous error diff --git a/src/doc/book/listings/ch19-advanced-features/no-listing-02-impl-outlineprint-for-point/output.txt b/src/doc/book/listings/ch19-advanced-features/no-listing-02-impl-outlineprint-for-point/output.txt index b9bb3f0921..1264ce7470 100644 --- a/src/doc/book/listings/ch19-advanced-features/no-listing-02-impl-outlineprint-for-point/output.txt +++ b/src/doc/book/listings/ch19-advanced-features/no-listing-02-impl-outlineprint-for-point/output.txt @@ -12,9 +12,5 @@ error[E0277]: `Point` doesn't implement `std::fmt::Display` = help: the trait `std::fmt::Display` is not implemented for `Point` = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead -error: aborting due to previous error - For more information about this error, try `rustc --explain E0277`. -error: could not compile `traits-example` - -To learn more, run the command again with --verbose. +error: could not compile `traits-example` due to previous error diff --git a/src/doc/book/listings/ch19-advanced-features/no-listing-18-returns-closure/output.txt b/src/doc/book/listings/ch19-advanced-features/no-listing-18-returns-closure/output.txt index be5584a247..9811fcde09 100644 --- a/src/doc/book/listings/ch19-advanced-features/no-listing-18-returns-closure/output.txt +++ b/src/doc/book/listings/ch19-advanced-features/no-listing-18-returns-closure/output.txt @@ -12,9 +12,5 @@ help: use `impl Fn(i32) -> i32` as the return type, as all return paths are of t 1 | fn returns_closure() -> impl Fn(i32) -> i32 { | ^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error - For more information about this error, try `rustc --explain E0746`. -error: could not compile `functions-example` - -To learn more, run the command again with --verbose. +error: could not compile `functions-example` due to previous error diff --git a/src/doc/book/listings/ch19-advanced-features/output-only-01-missing-unsafe/output.txt b/src/doc/book/listings/ch19-advanced-features/output-only-01-missing-unsafe/output.txt index 65e12009e3..5886bc6307 100644 --- a/src/doc/book/listings/ch19-advanced-features/output-only-01-missing-unsafe/output.txt +++ b/src/doc/book/listings/ch19-advanced-features/output-only-01-missing-unsafe/output.txt @@ -8,9 +8,5 @@ error[E0133]: call to unsafe function is unsafe and requires unsafe function or | = note: consult the function's documentation for information on how to avoid undefined behavior -error: aborting due to previous error - For more information about this error, try `rustc --explain E0133`. -error: could not compile `unsafe-example` - -To learn more, run the command again with --verbose. +error: could not compile `unsafe-example` due to previous error diff --git a/src/doc/book/listings/ch20-web-server/listing-20-12/output.txt b/src/doc/book/listings/ch20-web-server/listing-20-12/output.txt index 0bf6178713..d32006191b 100644 --- a/src/doc/book/listings/ch20-web-server/listing-20-12/output.txt +++ b/src/doc/book/listings/ch20-web-server/listing-20-12/output.txt @@ -6,9 +6,5 @@ error[E0433]: failed to resolve: use of undeclared type `ThreadPool` 10 | let pool = ThreadPool::new(4); | ^^^^^^^^^^ use of undeclared type `ThreadPool` -error: aborting due to previous error - For more information about this error, try `rustc --explain E0433`. -error: could not compile `hello` - -To learn more, run the command again with --verbose. +error: could not compile `hello` due to previous error diff --git a/src/doc/book/listings/ch20-web-server/listing-20-17/output.txt b/src/doc/book/listings/ch20-web-server/listing-20-17/output.txt index 4715e23b93..da2301eb04 100644 --- a/src/doc/book/listings/ch20-web-server/listing-20-17/output.txt +++ b/src/doc/book/listings/ch20-web-server/listing-20-17/output.txt @@ -9,9 +9,5 @@ error[E0382]: use of moved value: `receiver` 27 | workers.push(Worker::new(id, receiver)); | ^^^^^^^^ value moved here, in previous iteration of loop -error: aborting due to previous error - For more information about this error, try `rustc --explain E0382`. -error: could not compile `hello` - -To learn more, run the command again with --verbose. +error: could not compile `hello` due to previous error diff --git a/src/doc/book/listings/ch20-web-server/listing-20-22/output.txt b/src/doc/book/listings/ch20-web-server/listing-20-22/output.txt index e810388ae0..39801ac6a2 100644 --- a/src/doc/book/listings/ch20-web-server/listing-20-22/output.txt +++ b/src/doc/book/listings/ch20-web-server/listing-20-22/output.txt @@ -6,9 +6,5 @@ error[E0507]: cannot move out of `worker.thread` which is behind a mutable refer 52 | worker.thread.join().unwrap(); | ^^^^^^^^^^^^^ move occurs because `worker.thread` has type `JoinHandle<()>`, which does not implement the `Copy` trait -error: aborting due to previous error - For more information about this error, try `rustc --explain E0507`. -error: could not compile `hello` - -To learn more, run the command again with --verbose. +error: could not compile `hello` due to previous error diff --git a/src/doc/book/listings/ch20-web-server/no-listing-01-define-threadpool-struct/output.txt b/src/doc/book/listings/ch20-web-server/no-listing-01-define-threadpool-struct/output.txt index 187274f046..4cc1d132ce 100644 --- a/src/doc/book/listings/ch20-web-server/no-listing-01-define-threadpool-struct/output.txt +++ b/src/doc/book/listings/ch20-web-server/no-listing-01-define-threadpool-struct/output.txt @@ -6,9 +6,5 @@ error[E0599]: no function or associated item named `new` found for struct `Threa 11 | let pool = ThreadPool::new(4); | ^^^ function or associated item not found in `ThreadPool` -error: aborting due to previous error - For more information about this error, try `rustc --explain E0599`. -error: could not compile `hello` - -To learn more, run the command again with --verbose. +error: could not compile `hello` due to previous error diff --git a/src/doc/book/listings/ch20-web-server/no-listing-02-impl-threadpool-new/output.txt b/src/doc/book/listings/ch20-web-server/no-listing-02-impl-threadpool-new/output.txt index 33c8a68c00..72d4cd9dc0 100644 --- a/src/doc/book/listings/ch20-web-server/no-listing-02-impl-threadpool-new/output.txt +++ b/src/doc/book/listings/ch20-web-server/no-listing-02-impl-threadpool-new/output.txt @@ -6,9 +6,5 @@ error[E0599]: no method named `execute` found for struct `ThreadPool` in the cur 16 | pool.execute(|| { | ^^^^^^^ method not found in `ThreadPool` -error: aborting due to previous error - For more information about this error, try `rustc --explain E0599`. -error: could not compile `hello` - -To learn more, run the command again with --verbose. +error: could not compile `hello` due to previous error diff --git a/src/doc/book/listings/ch20-web-server/no-listing-04-update-worker-definition/output.txt b/src/doc/book/listings/ch20-web-server/no-listing-04-update-worker-definition/output.txt index 787d5ecdc4..5d621db834 100644 --- a/src/doc/book/listings/ch20-web-server/no-listing-04-update-worker-definition/output.txt +++ b/src/doc/book/listings/ch20-web-server/no-listing-04-update-worker-definition/output.txt @@ -18,10 +18,6 @@ error[E0308]: mismatched types = note: expected enum `Option>` found struct `JoinHandle<_>` -error: aborting due to 2 previous errors - Some errors have detailed explanations: E0308, E0599. For more information about an error, try `rustc --explain E0308`. -error: could not compile `hello` - -To learn more, run the command again with --verbose. +error: could not compile `hello` due to 2 previous errors diff --git a/src/doc/book/rust-toolchain b/src/doc/book/rust-toolchain index 108a9ade19..67fc7ad0d6 100644 --- a/src/doc/book/rust-toolchain +++ b/src/doc/book/rust-toolchain @@ -1 +1 @@ -1.54 +1.55 diff --git a/src/doc/book/src/appendix-02-operators.md b/src/doc/book/src/appendix-02-operators.md index 925862916e..68c0d0bb8b 100644 --- a/src/doc/book/src/appendix-02-operators.md +++ b/src/doc/book/src/appendix-02-operators.md @@ -136,7 +136,7 @@ parameters with trait bounds. |--------|-------------| | `T: U` | Generic parameter `T` constrained to types that implement `U` | | `T: 'a` | Generic type `T` must outlive lifetime `'a` (meaning the type cannot transitively contain any references with lifetimes shorter than `'a`) | -| `T : 'static` | Generic type `T` contains no borrowed references other than `'static` ones | +| `T: 'static` | Generic type `T` contains no borrowed references other than `'static` ones | | `'b: 'a` | Generic lifetime `'b` must outlive lifetime `'a` | | `T: ?Sized` | Allow generic type parameter to be a dynamically sized type | | `'a + trait`, `trait + trait` | Compound type constraint | diff --git a/src/doc/book/src/ch17-01-what-is-oo.md b/src/doc/book/src/ch17-01-what-is-oo.md index 86bf467a8c..fa0ec0c773 100644 --- a/src/doc/book/src/ch17-01-what-is-oo.md +++ b/src/doc/book/src/ch17-01-what-is-oo.md @@ -12,7 +12,7 @@ Rust supports it. The book *Design Patterns: Elements of Reusable Object-Oriented Software* by Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides (Addison-Wesley -Professional, 1994) colloquially referred to as *The Gang of Four* book, is a +Professional, 1994), colloquially referred to as *The Gang of Four* book, is a catalog of object-oriented design patterns. It defines OOP this way: > Object-oriented programs are made up of objects. An *object* packages both diff --git a/src/doc/book/src/title-page.md b/src/doc/book/src/title-page.md index 731da78470..29dfdc6dd6 100644 --- a/src/doc/book/src/title-page.md +++ b/src/doc/book/src/title-page.md @@ -2,7 +2,7 @@ *by Steve Klabnik and Carol Nichols, with contributions from the Rust Community* -This version of the text assumes you’re using Rust 1.54 or later with +This version of the text assumes you’re using Rust 1.55 or later with `edition="2018"` in *Cargo.toml* of all projects to use Rust 2018 Edition idioms. See the [“Installation” section of Chapter 1][install] to install or update Rust, and see the new [Appendix E][editions] ```rust,ignore -if inner.rc.fetch_sub(1, Ordering::Relaxed) != 1 { +if inner.rc.fetch_sub(1, Ordering::Release) != 1 { return; } ``` diff --git a/src/doc/nomicon/src/leaking.md b/src/doc/nomicon/src/leaking.md index e46be7dfcf..cf592efcaf 100644 --- a/src/doc/nomicon/src/leaking.md +++ b/src/doc/nomicon/src/leaking.md @@ -176,6 +176,12 @@ horribly degenerate. Also *oh my gosh* it's such a ridiculous corner case. ## thread::scoped::JoinGuard +> Note: This API has already been removed from std, for more information +> you may refer [issue #24292](https://github.com/rust-lang/rust/issues/24292). +> +> We still remain this chapter here because we think this example is still +> important, regardless of if it is still in std. + The thread::scoped API intended to allow threads to be spawned that reference data on their parent's stack without any synchronization over that data by ensuring the parent joins the thread before any of the shared data goes out diff --git a/src/doc/nomicon/src/lifetimes.md b/src/doc/nomicon/src/lifetimes.md index 0a68a28739..b35a8c65b2 100644 --- a/src/doc/nomicon/src/lifetimes.md +++ b/src/doc/nomicon/src/lifetimes.md @@ -224,8 +224,8 @@ are too dumb. ## The area covered by a lifetime A reference (sometimes called a *borrow*) is *alive* from the place it is -created to its last use. The borrowed thing needs to outlive only borrows that -are alive. This looks simple, but there are few subtleties. +created to its last use. The borrowed value needs to outlive only borrows that +are alive. This looks simple, but there are a few subtleties. The following snippet compiles, because after printing `x`, it is no longer needed, so it doesn't matter if it is dangling or aliased (even though the diff --git a/src/doc/nomicon/src/other-reprs.md b/src/doc/nomicon/src/other-reprs.md index 2b5a430405..fe06faf6c4 100644 --- a/src/doc/nomicon/src/other-reprs.md +++ b/src/doc/nomicon/src/other-reprs.md @@ -91,7 +91,7 @@ manipulate its tag and fields. See [the RFC][really-tagged] for details. These `repr`s have no effect on a struct. -Adding an explicit `repr(u*)`, `repr(i*)`, or `repr(C)` to an enum suppresses the null-pointer optimization, like: +Adding an explicit `repr(u*)`, `repr(i*)`, or `repr(C)` to an enum with fields suppresses the null-pointer optimization, like: ```rust # use std::mem::size_of; @@ -110,6 +110,8 @@ assert_eq!(8, size_of::>()); assert_eq!(16, size_of::>()); ``` +This optimization still applies to fieldless enums with an explicit `repr(u*)`, `repr(i*)`, or `repr(C)`. + ## repr(packed) `repr(packed)` forces Rust to strip any padding, and only align the type to a diff --git a/src/doc/nomicon/src/send-and-sync.md b/src/doc/nomicon/src/send-and-sync.md index 9742328274..b526ebcb35 100644 --- a/src/doc/nomicon/src/send-and-sync.md +++ b/src/doc/nomicon/src/send-and-sync.md @@ -102,7 +102,7 @@ impl Carton { pub fn new(value: T) -> Self { // Allocate enough memory on the heap to store one T. assert_ne!(size_of::(), 0, "Zero-sized types are out of the scope of this example"); - let mut memptr = ptr::null_mut() as *mut T; + let mut memptr: *mut T = ptr::null_mut(); unsafe { let ret = libc::posix_memalign( (&mut memptr).cast(), @@ -113,10 +113,10 @@ impl Carton { }; // NonNull is just a wrapper that enforces that the pointer isn't null. - let mut ptr = unsafe { + let ptr = { // Safety: memptr is dereferenceable because we created it from a // reference and have exclusive access. - ptr::NonNull::new(memptr.cast::()) + ptr::NonNull::new(memptr) .expect("Guaranteed non-null if posix_memalign returns 0") }; diff --git a/src/doc/nomicon/src/subtyping.md b/src/doc/nomicon/src/subtyping.md index 8ac7c1ab51..1d892e6cfc 100644 --- a/src/doc/nomicon/src/subtyping.md +++ b/src/doc/nomicon/src/subtyping.md @@ -418,7 +418,7 @@ And that's why function types, unlike anything else in the language, are **contra**variant over their arguments. Now, this is all well and good for the types the standard library provides, but -how is variance determined for type that *you* define? A struct, informally +how is variance determined for types that *you* define? A struct, informally speaking, inherits the variance of its fields. If a struct `MyType` has a generic argument `A` that is used in a field `a`, then MyType's variance over `A` is exactly `a`'s variance over `A`. diff --git a/src/doc/reference/src/attributes/limits.md b/src/doc/reference/src/attributes/limits.md index 517637e5dc..65cb55b43a 100644 --- a/src/doc/reference/src/attributes/limits.md +++ b/src/doc/reference/src/attributes/limits.md @@ -15,10 +15,10 @@ syntax to specify the recursion depth. #![recursion_limit = "4"] macro_rules! a { - () => { a!(1) }; - (1) => { a!(2) }; - (2) => { a!(3) }; - (3) => { a!(4) }; + () => { a!(1); }; + (1) => { a!(2); }; + (2) => { a!(3); }; + (3) => { a!(4); }; (4) => { }; } diff --git a/src/doc/reference/src/items/generics.md b/src/doc/reference/src/items/generics.md index e9c11ffcfa..0a9703335b 100644 --- a/src/doc/reference/src/items/generics.md +++ b/src/doc/reference/src/items/generics.md @@ -37,7 +37,7 @@ Generic parameters are in scope within the item definition where they are declared. They are not in scope for items declared within the body of a function as described in [item declarations]. -[References], [raw pointers], [arrays], [slices][arrays], [tuples], and +[References], [raw pointers], [arrays], [slices], [tuples], and [function pointers] have lifetime or type parameters as well, but are not referred to with path syntax. @@ -274,6 +274,7 @@ struct Foo<#[my_flexible_clone(unbounded)] H> { [array repeat expression]: ../expressions/array-expr.md [arrays]: ../types/array.md +[slices]: ../types/slice.md [associated const]: associated-items.md#associated-constants [associated type]: associated-items.md#associated-types [block]: ../expressions/block-expr.md diff --git a/src/doc/reference/src/patterns.md b/src/doc/reference/src/patterns.md index 43fde6e7a8..8cd8af042f 100644 --- a/src/doc/reference/src/patterns.md +++ b/src/doc/reference/src/patterns.md @@ -13,7 +13,6 @@ >    | [_IdentifierPattern_]\ >    | [_WildcardPattern_]\ >    | [_RestPattern_]\ ->    | [_ObsoleteRangePattern_]\ >    | [_ReferencePattern_]\ >    | [_StructPattern_]\ >    | [_TupleStructPattern_]\ @@ -407,7 +406,15 @@ match tuple { > **Syntax**\ > _RangePattern_ :\ ->    _RangePatternBound_ `..=` _RangePatternBound_ +>       _InclusiveRangePattern_\ +>    | _HalfOpenRangePattern_\ +>    | _ObsoleteRangePattern_ +> +> _InclusiveRangePattern_ :\ +>       _RangePatternBound_ `..=` _RangePatternBound_ +> +> _HalfOpenRangePattern_ :\ +>    | _RangePatternBound_ `..` > > _ObsoleteRangePattern_ :\ >    _RangePatternBound_ `...` _RangePatternBound_ @@ -420,11 +427,20 @@ match tuple { >    | [_PathInExpression_]\ >    | [_QualifiedPathInExpression_] -Range patterns match values that are within the closed range defined by its lower and -upper bounds. For example, a pattern `'m'..='p'` will match only the values `'m'`, `'n'`, -`'o'`, and `'p'`. The bounds can be literals or paths that point to constant values. +Range patterns match values within the range defined by their bounds. A range pattern may be +closed or half-open. A range pattern is closed if it has both a lower and an upper bound, and +it matches all the values between and including both of its bounds. A range pattern that is +half-open is written with a lower bound but not an upper bound, and matches any value equal to +or greater than the specified lower bound. -A pattern a `..=` b must always have a ≤ b. It is an error to have a range pattern +For example, a pattern `'m'..='p'` will match only the values `'m'`, `'n'`, `'o'`, and `'p'`. For an integer the +pattern `1..` will match 9, or 9001, or 9007199254740991 (if it is of an appropriate size), but +not 0, and not negative numbers for signed integers. The bounds can be literals or paths that point +to constant values. + +A half-open range pattern in the style `a..` cannot be used to match within the context of a slice. + +A pattern `a..=b` must always have a ≤ b. It is an error to have a range pattern `10..=0`, for example. The `...` syntax is kept for backwards compatibility. @@ -456,6 +472,12 @@ println!("{}", match ph { _ => unreachable!(), }); +# let uint: u32 = 5; +match uint { + 0 => "zero!", + 1.. => "positive number!", +}; + // using paths to constants: # const TROPOSPHERE_MIN : u8 = 6; # const TROPOSPHERE_MAX : u8 = 20; @@ -736,6 +758,10 @@ is irrefutable. When matching a slice, it is irrefutable only in the form with a single `..` [rest pattern](#rest-patterns) or [identifier pattern](#identifier-patterns) with the `..` rest pattern as a subpattern. +Within a slice, a half-open range pattern like `a..` must be enclosed in parentheses, +as in `(a..)`, to clarify it is intended to match a single value. +A future version of Rust may give the non-parenthesized version an alternate meaning. + ## Path patterns > **Syntax**\ diff --git a/src/doc/reference/src/tokens.md b/src/doc/reference/src/tokens.md index 15d8468a01..8cdf6dd577 100644 --- a/src/doc/reference/src/tokens.md +++ b/src/doc/reference/src/tokens.md @@ -585,7 +585,7 @@ usages and meanings are defined in the linked pages. | `@` | At | [Subpattern binding] | `_` | Underscore | [Wildcard patterns], [Inferred types], Unnamed items in [constants], [extern crates], and [use declarations] | `.` | Dot | [Field access][field], [Tuple index] -| `..` | DotDot | [Range][range], [Struct expressions], [Patterns] +| `..` | DotDot | [Range][range], [Struct expressions], [Patterns], [Range Patterns][rangepat] | `...` | DotDotDot | [Variadic functions][extern], [Range patterns] | `..=` | DotDotEq | [Inclusive Range][range], [Range patterns] | `,` | Comma | Various separators @@ -646,6 +646,7 @@ them are referred to as "token trees" in [macros]. The three types of brackets [patterns]: patterns.md [question]: expressions/operator-expr.md#the-question-mark-operator [range]: expressions/range-expr.md +[rangepat]: patterns.md#range-patterns [raw pointers]: types/pointer.md#raw-pointers-const-and-mut [references]: types/pointer.md [sized]: trait-bounds.md#sized diff --git a/src/doc/reference/src/type-coercions.md b/src/doc/reference/src/type-coercions.md index db143cf4cb..45d81d3860 100644 --- a/src/doc/reference/src/type-coercions.md +++ b/src/doc/reference/src/type-coercions.md @@ -147,7 +147,7 @@ Coercion is allowed between the following types: and where `U` can be obtained from `T` by [unsized coercion](#unsized-coercions). * Function item types to `fn` pointers diff --git a/src/doc/rust-by-example/src/cargo/test.md b/src/doc/rust-by-example/src/cargo/test.md index 01884a09af..f2af48db52 100644 --- a/src/doc/rust-by-example/src/cargo/test.md +++ b/src/doc/rust-by-example/src/cargo/test.md @@ -150,5 +150,5 @@ Ferris [testing]: ../testing.md [unit_testing]: ../testing/unit_testing.md -[integration_testing]: ../testing/unit_testing.md +[integration_testing]: ../testing/integration_testing.md [doc_testing]: ../testing/doc_testing.md diff --git a/src/doc/rust-by-example/src/fn.md b/src/doc/rust-by-example/src/fn.md index 3516066d54..e77552271d 100644 --- a/src/doc/rust-by-example/src/fn.md +++ b/src/doc/rust-by-example/src/fn.md @@ -44,7 +44,7 @@ fn fizzbuzz(n: u32) -> () { // When a function returns `()`, the return type can be omitted from the // signature fn fizzbuzz_to(n: u32) { - for n in 1..n + 1 { + for n in 1..=n { fizzbuzz(n); } } diff --git a/src/doc/rust-by-example/src/generics.md b/src/doc/rust-by-example/src/generics.md index 86ecc581a9..2cfd54ffb3 100644 --- a/src/doc/rust-by-example/src/generics.md +++ b/src/doc/rust-by-example/src/generics.md @@ -2,7 +2,7 @@ *Generics* is the topic of generalizing types and functionalities to broader cases. This is extremely useful for reducing code duplication in many ways, -but can call for rather involving syntax. Namely, being generic requires +but can call for rather involved syntax. Namely, being generic requires taking great care to specify over which types a generic type is actually considered valid. The simplest and most common use of generics is for type parameters. diff --git a/src/doc/rust-by-example/src/hello/print/fmt.md b/src/doc/rust-by-example/src/hello/print/fmt.md index dd698d29fc..82c3e01453 100644 --- a/src/doc/rust-by-example/src/hello/print/fmt.md +++ b/src/doc/rust-by-example/src/hello/print/fmt.md @@ -80,7 +80,7 @@ RGB (0, 0, 0) 0x000000 Two hints if you get stuck: * You [may need to list each color more than once][named_parameters], - * You can [pad with zeros to a width of 2][fmt_width] with `:02`. + * You can [pad with zeros to a width of 2][fmt_width] with `:0>2`. ### See also: diff --git a/src/doc/rust-by-example/src/std/arc.md b/src/doc/rust-by-example/src/std/arc.md index d36ca0802a..08d1ad31aa 100644 --- a/src/doc/rust-by-example/src/std/arc.md +++ b/src/doc/rust-by-example/src/std/arc.md @@ -3,25 +3,24 @@ When shared ownership between threads is needed, `Arc`(Atomic Reference Counted) can be used. This struct, via the `Clone` implementation can create a reference pointer for the location of a value in the memory heap while increasing the reference counter. As it shares ownership between threads, when the last reference pointer to a value is out of scope, the variable is dropped. ```rust,editable - -fn main() { use std::sync::Arc; use std::thread; -// This variable declaration is where its value is specified. -let apple = Arc::new("the same apple"); +fn main() { + // This variable declaration is where its value is specified. + let apple = Arc::new("the same apple"); -for _ in 0..10 { - // Here there is no value specification as it is a pointer to a reference - // in the memory heap. - let apple = Arc::clone(&apple); + for _ in 0..10 { + // Here there is no value specification as it is a pointer to a reference + // in the memory heap. + let apple = Arc::clone(&apple); - thread::spawn(move || { - // As Arc was used, threads can be spawned using the value allocated - // in the Arc variable pointer's location. - println!("{:?}", apple); - }); -} + thread::spawn(move || { + // As Arc was used, threads can be spawned using the value allocated + // in the Arc variable pointer's location. + println!("{:?}", apple); + }); + } } ``` 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 7b87bd2e9c..f429d9adf7 100644 --- a/src/doc/rust-by-example/src/trait/impl_trait.md +++ b/src/doc/rust-by-example/src/trait/impl_trait.md @@ -68,4 +68,10 @@ fn double_positives<'a>(numbers: &'a Vec) -> impl Iterator + 'a .filter(|x| x > &&0) .map(|x| x * 2) } + +fn main() { + let singles = vec![-3, -2, 2, 3]; + let doubles = double_positives(&singles); + assert_eq!(doubles.collect::>(), vec![4, 6]); +} ``` diff --git a/src/doc/rustc-dev-guide/src/SUMMARY.md b/src/doc/rustc-dev-guide/src/SUMMARY.md index cb3b4b404f..b7b6d8bd14 100644 --- a/src/doc/rustc-dev-guide/src/SUMMARY.md +++ b/src/doc/rustc-dev-guide/src/SUMMARY.md @@ -14,13 +14,13 @@ - [Distribution artifacts](./building/build-install-distribution-artifacts.md) - [Documenting Compiler](./building/compiler-documenting.md) - [Rustdoc overview](./rustdoc.md) - - [ctags](./building/ctags.md) - [Adding a new target](./building/new-target.md) - [The compiler testing framework](./tests/intro.md) - [Running tests](./tests/running.md) - [Adding new tests](./tests/adding.md) - [Using `compiletest` commands to control test execution](./compiletest.md) - [Debugging the Compiler](./compiler-debugging.md) + - [Using the tracing/logging instrumentation](./tracing.md) - [Profiling the compiler](./profiling.md) - [with the linux perf tool](./profiling/with_perf.md) - [with Windows Performance Analyzer](./profiling/wpa_profiling.md) @@ -99,6 +99,7 @@ - [Generics and substitutions](./generics.md) - [`TypeFolder` and `TypeFoldable`](./ty-fold.md) - [Generic arguments](./generic_arguments.md) + - [Constants in the type system](./constants.md) - [Type inference](./type-inference.md) - [Trait solving](./traits/resolution.md) - [Early and Late Bound Parameters](./early-late-bound.md) @@ -132,6 +133,7 @@ - [Creating Errors With SessionDiagnostic](./diagnostics/sessiondiagnostic.md) - [`LintStore`](./diagnostics/lintstore.md) - [Diagnostic Codes](./diagnostics/diagnostic-codes.md) + - [Diagnostic Items](./diagnostics/diagnostic-items.md) # MIR to Binaries diff --git a/src/doc/rustc-dev-guide/src/backend/backend-agnostic.md b/src/doc/rustc-dev-guide/src/backend/backend-agnostic.md index 3299e2cc79..271e6a16f5 100644 --- a/src/doc/rustc-dev-guide/src/backend/backend-agnostic.md +++ b/src/doc/rustc-dev-guide/src/backend/backend-agnostic.md @@ -2,7 +2,7 @@ -As of January 2021, `rustc_codegen_ssa` provides an +As of October 2021, `rustc_codegen_ssa` provides an abstract interface for all backends to implement, to allow other codegen backends (e.g. [Cranelift]). 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 9deff62dd6..1a6fa033a9 100644 --- a/src/doc/rustc-dev-guide/src/backend/updating-llvm.md +++ b/src/doc/rustc-dev-guide/src/backend/updating-llvm.md @@ -67,7 +67,7 @@ Example PRs look like: ## Feature updates > Note that this information is as of the time of this writing (April 2021). The process for updating LLVM changes with +2021-10 --> (October 2021). The process for updating LLVM changes with practically all LLVM updates, so this may be out of date! Unlike bugfixes, updating to pick up a new feature of LLVM typically requires a diff --git a/src/doc/rustc-dev-guide/src/borrow_check/region_inference/member_constraints.md b/src/doc/rustc-dev-guide/src/borrow_check/region_inference/member_constraints.md index dfc4327e50..c7c107e1ed 100644 --- a/src/doc/rustc-dev-guide/src/borrow_check/region_inference/member_constraints.md +++ b/src/doc/rustc-dev-guide/src/borrow_check/region_inference/member_constraints.md @@ -94,7 +94,7 @@ member constraints come in. ## Choices are always lifetime parameters At present, the "choice" regions from a member constraint are always lifetime -parameters from the current function. As of January 2021, +parameters from the current function. As of October 2021, this falls out from the placement of impl Trait, though in the future it may not be the case. We take some advantage of this fact, as it simplifies the current code. In particular, we don't have to consider a case like `'0 member of ['1, diff --git a/src/doc/rustc-dev-guide/src/borrow_check/two_phase_borrows.md b/src/doc/rustc-dev-guide/src/borrow_check/two_phase_borrows.md index a5e26c6a88..bcd4878211 100644 --- a/src/doc/rustc-dev-guide/src/borrow_check/two_phase_borrows.md +++ b/src/doc/rustc-dev-guide/src/borrow_check/two_phase_borrows.md @@ -77,7 +77,7 @@ borrow. [converted]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_build/thir/cx/expr/trait.ToBorrowKind.html#method.to_borrow_kind [`BorrowKind`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/enum.BorrowKind.html [`GatherBorrows`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/visit/trait.Visitor.html#method.visit_local -[`BorrowData`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/borrow_check/borrow_set/struct.BorrowData.html +[`BorrowData`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_borrowck/borrow_set/struct.BorrowData.html ## Checking two-phase borrows @@ -95,6 +95,6 @@ following exceptions: by using the [`Dominators`] for the MIR graph. 4. After the activation point, the two-phase borrow acts as a mutable borrow. -[check]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/borrow_check/struct.MirBorrowckCtxt.html#method.check_activations +[check]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_borrowck/struct.MirBorrowckCtxt.html#method.check_activations [`Dominators`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_data_structures/graph/dominators/struct.Dominators.html -[`is_active`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/borrow_check/path_utils/fn.is_active.html +[`is_active`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_borrowck/path_utils/fn.is_active.html diff --git a/src/doc/rustc-dev-guide/src/building/ctags.md b/src/doc/rustc-dev-guide/src/building/ctags.md deleted file mode 100644 index 9b63314578..0000000000 --- a/src/doc/rustc-dev-guide/src/building/ctags.md +++ /dev/null @@ -1,26 +0,0 @@ -# ctags - -One of the challenges with rustc is that the RLS can't handle it, since it's a -bootstrapping compiler. This makes code navigation difficult. One solution is to -use `ctags`. - -`ctags` has a long history and several variants. Exuberant Ctags seems to be -quite commonly distributed but it does not have out-of-box Rust support. Some -distributions seem to use [Universal Ctags][utags], which is a maintained fork -and does have built-in Rust support. - -The following script can be used to set up Exuberant Ctags: -[https://github.com/nikomatsakis/rust-etags][etags]. - -`ctags` integrates into emacs and vim quite easily. The following can then be -used to build and generate tags: - -```console -$ rust-ctags src/lib* && ./x.py build -``` - -This allows you to do "jump-to-def" with whatever functions were around when -you last built, which is ridiculously useful. - -[etags]: https://github.com/nikomatsakis/rust-etags -[utags]: https://github.com/universal-ctags/ctags diff --git a/src/doc/rustc-dev-guide/src/building/suggested.md b/src/doc/rustc-dev-guide/src/building/suggested.md index e544a68b81..24e25f5d05 100644 --- a/src/doc/rustc-dev-guide/src/building/suggested.md +++ b/src/doc/rustc-dev-guide/src/building/suggested.md @@ -22,7 +22,7 @@ You can also install the hook as a step of running `x.py setup`! a file. By default, `rust-analyzer` runs the `cargo check` and `rustfmt` commands, but you can override these commands to use more adapted versions of these tools when hacking on `rustc`. For example, for Visual Studio Code, -you can write: +you can write: ```JSON { @@ -32,7 +32,8 @@ you can write: "--json-output" ], "rust-analyzer.rustfmt.overrideCommand": [ - "./build/TARGET_TRIPLE/stage0/bin/rustfmt" + "./build/TARGET_TRIPLE/stage0/bin/rustfmt", + "--edition=2021" ], "editor.formatOnSave": true, "rust-analyzer.cargo.runBuildScripts": false, diff --git a/src/doc/rustc-dev-guide/src/closure.md b/src/doc/rustc-dev-guide/src/closure.md index 93683383ff..a38e93241a 100644 --- a/src/doc/rustc-dev-guide/src/closure.md +++ b/src/doc/rustc-dev-guide/src/closure.md @@ -162,7 +162,7 @@ The other option is to step through the code using lldb or gdb. Let's start with [`upvar.rs`][upvar]. This file has something called the [`euv::ExprUseVisitor`] which walks the source of the closure and -invokes a callbackfor each upvar that is borrowed, mutated, or moved. +invokes a callback for each upvar that is borrowed, mutated, or moved. [`euv::ExprUseVisitor`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_typeck/expr_use_visitor/struct.ExprUseVisitor.html @@ -199,7 +199,7 @@ Mutability and Type and is defined in comments, "`cmt` is a complete categorization of a value indicating where it originated and how it is located, as well as the mutability of the memory in which the value is stored". Based on the callback (consume, borrow etc.), we -will call the relevant *adjust_upvar_borrow_kind_for_* and pass the +will call the relevant `adjust_upvar_borrow_kind_for_` and pass the `cmt` along. Once the borrow type is adjusted, we store it in the table, which basically says what borrows were made for each closure. diff --git a/src/doc/rustc-dev-guide/src/compiler-debugging.md b/src/doc/rustc-dev-guide/src/compiler-debugging.md index 34f5e760f1..8f46e896eb 100644 --- a/src/doc/rustc-dev-guide/src/compiler-debugging.md +++ b/src/doc/rustc-dev-guide/src/compiler-debugging.md @@ -159,145 +159,12 @@ stack backtrace: Cool, now I have a backtrace for the error! ## Getting logging output -[getting-logging-output]: #getting-logging-output The compiler uses the [`tracing`] crate for logging. [`tracing`]: https://docs.rs/tracing -The compiler has a lot of [`debug!`] calls, which print out logging information -at many points. These are very useful to at least narrow down the location of -a bug if not to find it entirely, or just to orient yourself as to why the -compiler is doing a particular thing. - -[`debug!`]: https://docs.rs/tracing/0.1/tracing/macro.debug.html - -To see the logs, you need to set the `RUSTC_LOG` environment variable to your -log filter. Your log filter can be just `debug` to get all `debug!` output and -higher (e.g., it will also include `info!`), or `path::to::module` to get *all* -output (which will include `trace!`) from a particular module, or -`path::to::module=debug` to get `debug!` output and higher from a particular -module. - -For example, to get the `debug!` output and higher for a specific module, you -can run the compiler with `RUSTC_LOG=path::to::module=debug rustc my-file.rs`. -All `debug!` output will then appear in standard error. - -Note that you can use a partial path and the filter will still work. For -example, if you want to see `info!` output from only -`rustdoc::passes::collect_intra_doc_links`, you could use -`RUSTDOC_LOG=rustdoc::passes::collect_intra_doc_links=info` *or* you could use -`RUSTDOC_LOG=rustdoc::passes::collect_intra=info`. - -If you are developing rustdoc, use `RUSTDOC_LOG` instead. If you are developing -Miri, use `MIRI_LOG` instead. You get the idea :) - -See the [`tracing`] crate's docs, and specifically the docs for [`debug!`] to -see the full syntax you can use. (Note: unlike the compiler, the [`tracing`] -crate and its examples use the `RUST_LOG` environment variable. rustc, rustdoc, -and other tools set custom environment variables.) - -**Note that unless you use a very strict filter, the logger will emit a lot of -output, so use the most specific module(s) you can (comma-separated if -multiple)**. It's typically a good idea to pipe standard error to a file and -look at the log output with a text editor. - -So, to put it together: - -```bash -# This puts the output of all debug calls in `rustc_middle/src/traits` into -# standard error, which might fill your console backscroll. -$ RUSTC_LOG=rustc_middle::traits=debug rustc +stage1 my-file.rs - -# This puts the output of all debug calls in `rustc_middle/src/traits` in -# `traits-log`, so you can then see it with a text editor. -$ RUSTC_LOG=rustc_middle::traits=debug rustc +stage1 my-file.rs 2>traits-log - -# Not recommended! This will show the output of all `debug!` calls -# in the Rust compiler, and there are a *lot* of them, so it will be -# hard to find anything. -$ RUSTC_LOG=debug rustc +stage1 my-file.rs 2>all-log - -# This will show the output of all `info!` calls in `rustc_codegen_ssa`. -# -# There's an `info!` statement in `codegen_instance` that outputs -# every function that is codegen'd. This is useful to find out -# which function triggers an LLVM assertion, and this is an `info!` -# log rather than a `debug!` log so it will work on the official -# compilers. -$ RUSTC_LOG=rustc_codegen_ssa=info rustc +stage1 my-file.rs - -# This will show the output of all `info!` calls made by rustdoc -# or any rustc library it calls. -$ RUSTDOC_LOG=info rustdoc +stage1 my-file.rs - -# This will only show `debug!` calls made by rustdoc directly, -# not any `rustc*` crate. -$ RUSTDOC_LOG=rustdoc=debug rustdoc +stage1 my-file.rs -``` - -### Log colors - -By default, rustc (and other tools, like rustdoc and Miri) will be smart about -when to use ANSI colors in the log output. If they are outputting to a terminal, -they will use colors, and if they are outputting to a file or being piped -somewhere else, they will not. However, it's hard to read log output in your -terminal unless you have a very strict filter, so you may want to pipe the -output to a pager like `less`. But then there won't be any colors, which makes -it hard to pick out what you're looking for! - -You can override whether to have colors in log output with the `RUSTC_LOG_COLOR` -environment variable (or `RUSTDOC_LOG_COLOR` for rustdoc, or `MIRI_LOG_COLOR` -for Miri, etc.). There are three options: `auto` (the default), `always`, and -`never`. So, if you want to enable colors when piping to `less`, use something -similar to this command: - -```bash -# The `-R` switch tells less to print ANSI colors without escaping them. -$ RUSTC_LOG=debug RUSTC_LOG_COLOR=always rustc +stage1 ... | less -R -``` - -Note that `MIRI_LOG_COLOR` will only color logs that come from Miri, not logs -from rustc functions that Miri calls. Use `RUSTC_LOG_COLOR` to color logs from -rustc. - -### How to keep or remove `debug!` and `trace!` calls from the resulting binary - -While calls to `error!`, `warn!` and `info!` are included in every build of the compiler, -calls to `debug!` and `trace!` are only included in the program if -`debug-logging=true` is turned on in config.toml (it is -turned off by default), so if you don't see `DEBUG` logs, especially -if you run the compiler with `RUSTC_LOG=rustc rustc some.rs` and only see -`INFO` logs, make sure that `debug-logging=true` is turned on in your -config.toml. - -### Logging etiquette and conventions - -Because calls to `debug!` are removed by default, in most cases, don't worry -about adding "unnecessary" calls to `debug!` and leaving them in code you -commit - they won't slow down the performance of what we ship, and if they -helped you pinning down a bug, they will probably help someone else with a -different one. - -A loosely followed convention is to use `debug!("foo(...)")` at the _start_ of -a function `foo` and `debug!("foo: ...")` _within_ the function. Another -loosely followed convention is to use the `{:?}` format specifier for debug -logs. - -One thing to be **careful** of is **expensive** operations in logs. - -If in the module `rustc::foo` you have a statement - -```Rust -debug!("{:?}", random_operation(tcx)); -``` - -Then if someone runs a debug `rustc` with `RUSTC_LOG=rustc::bar`, then -`random_operation()` will run. - -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 their own module. -No-one will know it until someone tries to use logging to find *another* bug. +For details see [the guide section on tracing](./tracing.md) ## Formatting Graphviz output (.dot files) [formatting-graphviz-output]: #formatting-graphviz-output diff --git a/src/doc/rustc-dev-guide/src/constants.md b/src/doc/rustc-dev-guide/src/constants.md new file mode 100644 index 0000000000..137351c22f --- /dev/null +++ b/src/doc/rustc-dev-guide/src/constants.md @@ -0,0 +1,65 @@ +# Constants in the type system + +Constants used in the type system are represented as [`ty::Const`]. +The variants of their [`ty::ConstKind`] mostly mirror the variants of [`ty::TyKind`] +with the two *additional* variants being `ConstKind::Value` and `ConstKind::Unevaluated`. + + +## Unevaluated constants + +*This section talks about what's happening with `feature(generic_const_exprs)` enabled. +On stable we do not yet supply any generic parameters to anonymous constants, +avoiding most of the issues mentioned here.* + +Unless a constant is either a simple literal, e.g. `[u8; 3]` or `foo::<{ 'c' }>()`, +or a generic parameter, e.g. `[u8; N]`, converting a constant to its [`ty::Const`] representation +returns an unevaluated constant. Even fully concrete constants which do not depend on +generic parameters are not evaluated right away. + +We do not eagerly evaluate constant as they can be used in the `where`-clauses of their +parent item, for example: + +```rust +#[feature(generic_const_exprs)] +fn foo() +where + [u8; ::ASSOC + 1]: SomeOtherTrait, +{} +``` + +The constant `::ASSOC + 1` depends on the `T: Trait` bound of +its parents caller bounds, but is also part of another bound itself. +If we were to eagerly evaluate this constant while computing its parents bounds +this would cause a query cycle. + +### Generic arguments of anonymous constants + +Anonymous constants inherit the generic parameters of their parent, which is +why the array length in `foo() -> [u8; N + 1]` can use `N`. + +Without any manual adjustments, this causes us to include parameters even if +the constant doesn't use them in any way. This can cause +[some interesting errors](pcg-unused-substs) and breaks some already stable code. + +To deal with this, we intend to look at the generic parameters explicitly mentioned +by the constants and then search the predicates of its parents to figure out which +of the other generic parameters are reachable by our constant. + +**TODO**: Expand this section once the parameter filtering is implemented. + +As constants can be part of their parents `where`-clauses, we mention unevaluated +constants in their parents predicates. It is therefore necessary to mention unevaluated +constants before we have computed the generic parameters +available to these constants. + +To do this unevaluated constants start out with [`substs_`] being `None` while assuming +that their generic arguments could be arbitrary generic parameters. +When first accessing the generic arguments of an unevaluated constants, we then replace +`substs_` with the actual default arguments of a constants, which are the generic parameters +of their parent we assume to be used by this constant. + +[`ty::Const`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Const.html +[`ty::ConstKind`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/enum.ConstKind.html +[`ty::TyKind`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/enum.TyKind.html +[pcg-unused-substs]: https://github.com/rust-lang/project-const-generics/blob/master/design-docs/anon-const-substs.md#unused-substs +[`substs_`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/consts/kind/struct.Unevaluated.html#structfield.substs_ \ No newline at end of file diff --git a/src/doc/rustc-dev-guide/src/contributing.md b/src/doc/rustc-dev-guide/src/contributing.md index 9df9b6dfc1..aca5b142ef 100644 --- a/src/doc/rustc-dev-guide/src/contributing.md +++ b/src/doc/rustc-dev-guide/src/contributing.md @@ -424,12 +424,12 @@ Just a few things to keep in mind: Try to format the date as ` ` to ease search. - Additionally, include a machine-readable comment of the form `` (if the current month is January 2021). We have an automated + 2021-10 -->` (if the current month is October 2021). We have an automated tool that uses these (in `ci/date-check`). So, for the month of January 2021, the comment would look like: `As of January 2021`. Make sure to put the comment *between* `as of` - and `January 2021`; see [PR #1066][rdg#1066] for the rationale. + date: 2021-10 --> October 2021`. Make sure to put the comment *between* `as of` + and `October 2021`; see [PR #1066][rdg#1066] for the rationale. - A link to a relevant WG, tracking issue, `rustc` rustdoc page, or similar, that may provide further explanation for the change process or a way to verify that the information is not diff --git a/src/doc/rustc-dev-guide/src/diagnostics.md b/src/doc/rustc-dev-guide/src/diagnostics.md index ca2ba13ca9..e35bde093a 100644 --- a/src/doc/rustc-dev-guide/src/diagnostics.md +++ b/src/doc/rustc-dev-guide/src/diagnostics.md @@ -222,9 +222,13 @@ Guidelines for different diagnostic levels: The error or warning portion should *not* suggest how to fix the problem, only the "help" sub-diagnostic should. -- `note`: emitted to identify additional circumstances and parts of the code - that caused the warning or error. For example, the borrow checker will note - any previous conflicting borrows. +- `note`: emitted to given more context and identify additional circumstances + and parts of the code that caused the warning or error. For example, the + borrow checker will note any previous conflicting borrows. + + `help` vs `note`: `help` should be used to show changes the user can + possibly make to fix the problem. `note` should be used for everything else, + such as other context, information and facts, online resources to read, etc. Not to be confused with *lint levels*, whose guidelines are: diff --git a/src/doc/rustc-dev-guide/src/diagnostics/diagnostic-items.md b/src/doc/rustc-dev-guide/src/diagnostics/diagnostic-items.md new file mode 100644 index 0000000000..efaa01cf39 --- /dev/null +++ b/src/doc/rustc-dev-guide/src/diagnostics/diagnostic-items.md @@ -0,0 +1,146 @@ +# Diagnostic Items + +## Background + +While writing lints it's common to check for specific types, traits and functions. This raises +the question on how to check for these. Types can be checked by their complete type path. +However, this requires hard coding paths and can lead to misclassifications in some edge cases. +To counteract this, rustc has introduced diagnostic items that are used to identify types via +[`Symbol`]s. + +## How To Find Diagnostic Items + +Diagnostic items are added to items inside `rustc`/`std`/`core` with the `rustc_diagnostic_item` +attribute. The item for a specific type can be found by opening the source code in the +documentation and looking for this attribute. Note that it's often added with the `cfg_attr` +attribute to avoid compilation errors during tests. A definition often looks like this: + +```rs +// This is the diagnostic item for this type vvvvvvv +#[cfg_attr(not(test), rustc_diagnostic_item = "Penguin")] +struct Penguin; +``` + +Diagnostic items are usually only added to traits, types and standalone functions. If the goal +is to check for an associated type or method, please use the diagnostic item of the item and +reference [*Using Diagnostic Items*](#using-diagnostic-items). + +## How To Add Diagnostic Items + +A new diagnostic item can be added with these two steps: + +1. Find the target item inside the rust repo. Now add the diagnostic item as a string via the + `rustc_diagnostic_item` attribute. This can sometimes cause compilation errors while running + tests. These errors can be avoided by using the `cfg_attr` attribute with the `not(test)` + condition (it's fine adding then for all `rustc_diagnostic_item` attributes as a preventive + manner). At the end, it should look like this: + + ```rs + // This will be the new diagnostic item vvv + #[cfg_attr(not(test), rustc_diagnostic_item = "Cat")] + struct Cat; + ``` + + For the naming conventions of diagnostic items, please refer to + [*Naming Conventions*](#naming-conventions). + +2. As of August 2021 diagnostic items in code are accessed via symbols in + [`rustc_span::symbol::sym`]. To add your newly created diagnostic item simply open the + module file and add the name (In this case `Cat`) at the correct point in the list. + +Now you can create a pull request with your changes. :tada: (Note that when using diagnostic +items in other projects like Clippy, it might take some time until the repos get synchronized.) + +## Naming Conventions + +Diagnostic items don't have a set in stone naming convention yet. These are some guidelines that +should be used for the future, but might differ from existing names: + +* Types, traits and enums are named using UpperCamelCase (Examples: `Iterator`, `HashMap`, ...) +* For type names that are used multiple times like `Writer` it's good to choose a more precise + name, maybe by adding the module to it. (Example: `IoWriter`) +* Associated items should not get their own diagnostic items, but instead be accessed indirectly + by the diagnostic item of the type they're originating from. +* Freestanding functions like `std::mem::swap()` should be named using `snake_case` with one + important (export) module as a prefix (Example: `mem_swap`, `cmp_max`) +* Modules should usually not have a diagnostic item attached to them. Diagnostic items were + added to avoid the usage of paths, using them on modules would therefore most likely to be + counterproductive. + +## How To Use Diagnostic Items + +In rustc, diagnostic items are looked up via [`Symbol`]s from inside the +[`rustc_span::symbol::sym`] module. These can then be mapped to [`DefId`]s using +[`TyCtxt::get_diagnostic_item()`] or checked if they match a [`DefId`] using +[`TyCtxt::is_diagnostic_item()`]. When mapping from a diagnostic item to a [`DefId`] the method +will return a `Option`. This can be `None` if either the symbol isn't a diagnostic item +or the type is not registered, for instance when compiling with `#[no_std]`. All following +examples are based on [`DefId`]s and their usage. + +### Check For A Type + +```rust +use rustc_span::symbol::sym; + +/// This example checks if the given type (`ty`) has the type `HashMap` using +/// `TyCtxt::is_diagnostic_item()` +fn example_1(cx: &LateContext<'_>, ty: Ty<'_>) -> bool { + match ty.kind() { + ty::Adt(adt, _) => cx.tcx.is_diagnostic_item(sym::HashMap, adt.did), + _ => false, + } +} +``` + +### Check For A Trait Implementation + +```rust +/// This example checks if a given [`DefId`] from a method is part of a trait +/// implementation defined by a diagnostic item. +fn is_diag_trait_item( + cx: &LateContext<'_>, + def_id: DefId, + diag_item: Symbol +) -> bool { + if let Some(trait_did) = cx.tcx.trait_of_item(def_id) { + return cx.tcx.is_diagnostic_item(diag_item, trait_did); + } + false +} +``` + +### Associated Types + +Associated types of diagnostic items can be accessed indirectly by first getting the [`DefId`] +of the trait and then calling [`TyCtxt::associated_items()`]. This returns an [`AssocItems`] +object which can be used for further checks. Checkout +[`clippy_utils::ty::get_iterator_item_ty()`] for an example usage of this. + +### Usage In Clippy + +Clippy tries to use diagnostic items where possible and has developed some wrapper and utility +functions. Please also refer to its documentation when using diagnostic items in Clippy. (See +[*Common tools for writing lints*][clippy-Common-tools-for-writing-lints].) + +## Related Issues + +This lists some related issues. These are probably only interesting to people who really want to +take a deep dive into the topic :) + +* [rust#60966]: The Rust PR that introduced diagnostic items +* [rust-clippy#5393]: Clippy's tracking issue for moving away from hard coded paths to + diagnostic item + + + +[`rustc_span::symbol::sym`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_span/symbol/sym/index.html +[`Symbol`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_span/symbol/struct.Symbol.html +[`DefId`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/def_id/struct.DefId.html +[`TyCtxt::get_diagnostic_item()`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/context/struct.TyCtxt.html#method.get_diagnostic_item +[`TyCtxt::is_diagnostic_item()`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/context/struct.TyCtxt.html#method.is_diagnostic_item +[`TyCtxt::associated_items()`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/context/struct.TyCtxt.html#method.associated_items +[`AssocItems`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/assoc/struct.AssocItems.html +[`clippy_utils::ty::get_iterator_item_ty()`]: https://github.com/rust-lang/rust-clippy/blob/305177342fbc622c0b3cb148467bab4b9524c934/clippy_utils/src/ty.rs#L55-L72 +[clippy-Common-tools-for-writing-lints]: https://github.com/rust-lang/rust-clippy/blob/master/doc/common_tools_writing_lints.md +[rust#60966]: https://github.com/rust-lang/rust/pull/60966 +[rust-clippy#5393]: https://github.com/rust-lang/rust-clippy/issues/5393 diff --git a/src/doc/rustc-dev-guide/src/getting-started.md b/src/doc/rustc-dev-guide/src/getting-started.md index 18e429e5ea..abc084c2be 100644 --- a/src/doc/rustc-dev-guide/src/getting-started.md +++ b/src/doc/rustc-dev-guide/src/getting-started.md @@ -293,13 +293,15 @@ format-on-save turned on. It's a good habit to run `./x.py fmt` before every commit, as this reduces conflicts later. The pinned version is built under `build//stage0/bin/rustfmt`, so if you want, you can use it for a single file or for format-on-save in your editor, which can be faster than `./x.py fmt`. +You'll have to pass the `--edition=2021` argument +yourself when calling `rustfmt` directly. One last thing: you can use `RUSTC_LOG=XXX` to get debug logging. [Read more here][logging]. Notice the `C` in `RUSTC_LOG`. Other than that, it uses normal -[`env_logger`][envlog] syntax. +[`env_logger`][envlog] or `tracing` syntax. [envlog]: https://crates.io/crates/env_logger -[logging]: ./compiler-debugging.html#getting-logging-output +[logging]: ./tracing.md ### Building and Testing `std`/`core`/`alloc`/`test`/`proc_macro`/etc. diff --git a/src/doc/rustc-dev-guide/src/git.md b/src/doc/rustc-dev-guide/src/git.md index 72d2871518..ac03a3c0f7 100644 --- a/src/doc/rustc-dev-guide/src/git.md +++ b/src/doc/rustc-dev-guide/src/git.md @@ -269,9 +269,9 @@ git push --force-with-lease (set origin to be the same as local) ``` To avoid merges as per the [No-Merge Policy](#no-merge-policy), you may want to use -`git config pull.ff only` (this will apply the config to the local repo). -to avoid merge conflicts while pulling, without needing -`--ff-only` or `--rebase` while `git pull`ing +`git config pull.ff only` (this will apply the config only to the local repo) +to ensure that Git doesn't create merge commits when `git pull`ing, without +needing to pass `--ff-only` or `--rebase` every time. You can also `git push --force-with-lease` from master to keep your origin's master in sync with upstream. 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 728805387a..7d3c0fe360 100644 --- a/src/doc/rustc-dev-guide/src/llvm-coverage-instrumentation.md +++ b/src/doc/rustc-dev-guide/src/llvm-coverage-instrumentation.md @@ -298,8 +298,8 @@ Expected results for both the `mir-opt` tests and the `coverage*` tests under `run-make-fulldeps` can be refreshed by running: ```shell -$ ./x.py test mir-opt --blessed -$ ./x.py test src/test/run-make-fulldeps/coverage --blessed +$ ./x.py test mir-opt --bless +$ ./x.py test src/test/run-make-fulldeps/coverage --bless ``` [mir-opt-test]: https://github.com/rust-lang/rust/blob/master/src/test/mir-opt/instrument_coverage.rs diff --git a/src/doc/rustc-dev-guide/src/overview.md b/src/doc/rustc-dev-guide/src/overview.md index 6c756e18ff..26b291d35f 100644 --- a/src/doc/rustc-dev-guide/src/overview.md +++ b/src/doc/rustc-dev-guide/src/overview.md @@ -43,16 +43,17 @@ we'll talk about that later. - The lexer preserves full fidelity information for both IDEs and proc macros. - The parser [translates the token stream from the lexer into an Abstract Syntax Tree (AST)][parser]. It uses a recursive descent (top-down) approach to syntax - analysis. The crate entry points for the parser are the `Parser::parse_crate_mod()` and - `Parser::parse_mod()` methods found in `rustc_parse::parser::item`. The external - module parsing entry point is `rustc_expand::module::parse_external_mod`. And - the macro parser entry point is [`Parser::parse_nonterminal()`][parse_nonterminal]. + analysis. The crate entry points for the parser are the + [`Parser::parse_crate_mod()`][parse_crate_mod] and [`Parser::parse_mod()`][parse_mod] + methods found in [`rustc_parse::parser::Parser`]. The external module parsing + entry point is [`rustc_expand::module::parse_external_mod`][parse_external_mod]. + And the macro parser entry point is [`Parser::parse_nonterminal()`][parse_nonterminal]. - Parsing is performed with a set of `Parser` utility methods including `fn bump`, `fn check`, `fn eat`, `fn expect`, `fn look_ahead`. - Parsing is organized by the semantic construct that is being parsed. Separate - `parse_*` methods can be found in `rustc_parse` `parser` directory. The source - file name follows the construct name. For example, the following files are found - in the parser: + `parse_*` methods can be found in [`rustc_parse` `parser`][rustc_parse_parser_dir] + directory. The source file name follows the construct name. For example, the + following files are found in the parser: - `expr.rs` - `pat.rs` - `ty.rs` @@ -123,6 +124,11 @@ we'll talk about that later. [`simplify_try`]: https://github.com/rust-lang/rust/pull/66282 [codegen]: https://rustc-dev-guide.rust-lang.org/backend/codegen.html [parse_nonterminal]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_parse/parser/struct.Parser.html#method.parse_nonterminal +[parse_crate_mod]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_parse/parser/struct.Parser.html#method.parse_crate_mod +[parse_mod]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_parse/parser/struct.Parser.html#method.parse_mod +[`rustc_parse::parser::Parser`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_parse/parser/struct.Parser.html +[parse_external_mod]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_expand/module/fn.parse_external_mod.html +[rustc_parse_parser_dir]: https://github.com/rust-lang/rust/tree/master/compiler/rustc_parse/src/parser ## How it does it @@ -291,12 +297,7 @@ Compiler performance is a problem that we would like to improve on (and are always working on). One aspect of that is parallelizing `rustc` itself. -Currently, there is only one part of rustc that is already parallel: codegen. -During monomorphization, the compiler will split up all the code to be -generated into smaller chunks called _codegen units_. These are then generated -by independent instances of LLVM. Since they are independent, we can run them -in parallel. At the end, the linker is run to combine all the codegen units -together into one binary. +Currently, there is only one part of rustc that is parallel by default: codegen. However, the rest of the compiler is still not yet parallel. There have been lots of efforts spent on this, but it is generally a hard problem. The current diff --git a/src/doc/rustc-dev-guide/src/parallel-rustc.md b/src/doc/rustc-dev-guide/src/parallel-rustc.md index eec8219a5b..2ee302d244 100644 --- a/src/doc/rustc-dev-guide/src/parallel-rustc.md +++ b/src/doc/rustc-dev-guide/src/parallel-rustc.md @@ -1,16 +1,70 @@ # Parallel Compilation -Most of the compiler is not parallel. This represents an opportunity for -improving compiler performance. +As of September 2021, The only stage of the compiler +that is already parallel is codegen. The nightly compiler implements query evaluation, +but there is still a lot of work to be done. The lack of parallelism at other stages +also represents an opportunity for improving compiler performance. One can try out the current +parallel compiler work by enabling it in the `config.toml`. + +These next few sections describe where and how parallelism is currently used, +and the current status of making parallel compilation the default in `rustc`. + +The underlying thread-safe data-structures used in the parallel compiler +can be found in the `rustc_data_structures::sync` module. Some of these data structures +use the `parking_lot` crate as well. + +## Codegen + +There are two underlying thread safe data structures used in code generation: + +- `Lrc` + - Which is an [`Arc`][Arc] if `parallel_compiler` is true, and a [`Rc`][Rc] + if it is not. +- `MetadataRef` -> [`OwningRef, [u8]>`][OwningRef] + - This data structure is specific to `rustc`. + +During [monomorphization][monomorphization] the compiler splits up all the code to +be generated into smaller chunks called _codegen units_. These are then generated by +independent instances of LLVM running in parallel. At the end, the linker +is run to combine all the codegen units together into one binary. This process +occurs in the `rustc_codegen_ssa::base` module. + +## Query System + +The query model has some properties that make it actually feasible to evaluate +multiple queries in parallel without too much of an effort: + +- All data a query provider can access is accessed via the query context, so + the query context can take care of synchronizing access. +- Query results are required to be immutable so they can safely be used by + different threads concurrently. + +When a query `foo` is evaluated, the cache table for `foo` is locked. + +- If there already is a result, we can clone it, release the lock and + we are done. +- If there is no cache entry and no other active query invocation computing the + same result, we mark the key as being "in progress", release the lock and + start evaluating. +- If there *is* another query invocation for the same key in progress, we + release the lock, and just block the thread until the other invocation has + computed the result we are waiting for. This cannot deadlock because, as + mentioned before, query invocations form a DAG. Some thread will always make + progress. + +## Rustdoc + +As of September 2021, there are still a number of steps +to complete before rustdoc rendering can be made parallel. More details on +this issue can be found [here][parallel-rustdoc]. + +## Current Status As of July 2021, work on explicitly parallelizing the compiler has stalled. There is a lot of design and correctness work that needs -to be done. +to be done. -One can try out the current parallel compiler work by enabling it in the -`config.toml`. - -There are a few basic ideas in this effort: +These are the basic ideas in the effort to make `rustc` parallel: - There are a lot of loops in the compiler that just iterate over all items in a crate. These can possibly be parallelized. @@ -45,3 +99,8 @@ are a bit out of date): [imlist]: https://github.com/nikomatsakis/rustc-parallelization/blob/master/interior-mutability-list.md [irlo1]: https://internals.rust-lang.org/t/help-test-parallel-rustc/11503 [tracking]: https://github.com/rust-lang/rust/issues/48685 +[monomorphization]:https://rustc-dev-guide.rust-lang.org/backend/monomorph.html +[parallel-rustdoc]:https://github.com/rust-lang/rust/issues/82741 +[Arc]:https://doc.rust-lang.org/std/sync/struct.Arc.html +[Rc]:https://doc.rust-lang.org/std/rc/struct.Rc.html +[OwningRef]:https://doc.rust-lang.org/nightly/nightly-rustc/rustc_data_structures/owning_ref/index.html diff --git a/src/doc/rustc-dev-guide/src/queries/query-evaluation-model-in-detail.md b/src/doc/rustc-dev-guide/src/queries/query-evaluation-model-in-detail.md index 4c2427e3c4..b84a5dac42 100644 --- a/src/doc/rustc-dev-guide/src/queries/query-evaluation-model-in-detail.md +++ b/src/doc/rustc-dev-guide/src/queries/query-evaluation-model-in-detail.md @@ -211,29 +211,3 @@ much of a maintenance burden. To summarize: "Steal queries" break some of the rules in a controlled way. There are checks in place that make sure that nothing can go silently wrong. - - -## Parallel Query Execution - -The query model has some properties that make it actually feasible to evaluate -multiple queries in parallel without too much of an effort: - -- All data a query provider can access is accessed via the query context, so - the query context can take care of synchronizing access. -- Query results are required to be immutable so they can safely be used by - different threads concurrently. - -The nightly compiler already implements parallel query evaluation as follows: - -When a query `foo` is evaluated, the cache table for `foo` is locked. - -- If there already is a result, we can clone it, release the lock and - we are done. -- If there is no cache entry and no other active query invocation computing the - same result, we mark the key as being "in progress", release the lock and - start evaluating. -- If there *is* another query invocation for the same key in progress, we - release the lock, and just block the thread until the other invocation has - computed the result we are waiting for. This cannot deadlock because, as - mentioned before, query invocations form a DAG. Some thread will always make - progress. diff --git a/src/doc/rustc-dev-guide/src/rustdoc-internals.md b/src/doc/rustc-dev-guide/src/rustdoc-internals.md index a74078951e..112a5dcab7 100644 --- a/src/doc/rustc-dev-guide/src/rustdoc-internals.md +++ b/src/doc/rustc-dev-guide/src/rustdoc-internals.md @@ -71,29 +71,25 @@ Here is the list of passes as of February 2021: - `calculate-doc-coverage` calculates information used for the `--show-coverage` flag. +- `check-bare-urls` detects links that are not linkified, e.g., in Markdown such as + `Go to https://example.com/.` It suggests wrapping the link with angle brackets: + `Go to .` to linkify it. This is the code behind the + `rustdoc::bare_urls` lint. + - `check-code-block-syntax` validates syntax inside Rust code blocks (```rust) +- `check-doc-test-visibility` runs doctest visibility–related lints. + - `check-invalid-html-tags` detects invalid HTML (like an unclosed ``) in doc comments. -- `check-non-autolinks` detects links that could or should be written using - angle brackets (the code behind the nightly-only `non_autolinks` - lint). - -- `collapse-docs` concatenates all document attributes into one document - attribute. This is necessary because each line of a doc comment is given as a - separate doc attribute, and this will combine them into a single string with - line breaks between each attribute. - - `collect-intra-doc-links` resolves [intra-doc links](https://doc.rust-lang.org/rustdoc/linking-to-items-by-name.html). - `collect-trait-impls` collects trait impls for each item in the crate. For example, if we define a struct that implements a trait, this pass will note that the struct implements that trait. -- `doc-test-lints` runs various lints on the doctests. - - `propagate-doc-cfg` propagates `#[doc(cfg(...))]` to child items. - `strip-priv-imports` strips all private import statements (`use`, `extern diff --git a/src/doc/rustc-dev-guide/src/salsa.md b/src/doc/rustc-dev-guide/src/salsa.md index 9bf93727a3..a6a6b97069 100644 --- a/src/doc/rustc-dev-guide/src/salsa.md +++ b/src/doc/rustc-dev-guide/src/salsa.md @@ -44,7 +44,7 @@ something that the library produces, but, for each derived value there's a "pure" function that computes the derived value. For example, there might be a function `ast(x: Path) -> AST`. The produced -`AST` isn't a final value, it's an intermidiate value that the library would +`AST` isn't a final value, it's an intermediate value that the library would use for the computation. This means that when you try to compute with the library, Salsa is going to @@ -126,7 +126,7 @@ Example input query group: ```rust,ignore /// This attribute will process this tree, produce this tree as output, and produce -/// a bunch of intermidiate stuff that Salsa also uses. One of these things is a +/// a bunch of intermediate stuff that Salsa also uses. One of these things is a /// "StorageStruct", whose name we have specified in the attribute. /// /// This query group is a bunch of **input** queries, that do not rely on any diff --git a/src/doc/rustc-dev-guide/src/sanitizers.md b/src/doc/rustc-dev-guide/src/sanitizers.md index ce07140340..49183d6d5e 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. +* [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. * [MemorySanitizer][clang-msan] a detector of uninitialized reads. * [ThreadSanitizer][clang-tsan] a fast data race detector. @@ -12,8 +14,9 @@ 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`, `leak`, `memory` or `thread`. For more details how to use -sanitizers please refer to [the unstable book](https://doc.rust-lang.org/unstable-book/). +of `address`, `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? @@ -22,7 +25,8 @@ 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 on supported targets][sanitizer-build] when enabled in `config.toml`: + [will be built][sanitizer-build] on [supported targets][sanitizer-targets] + when enabled in `config.toml`: ```toml [build] @@ -33,9 +37,9 @@ libraries. Highlight of the most important aspects of the implementation: * During LLVM code generation, the functions intended for instrumentation are [marked][sanitizer-attribute] with appropriate LLVM attribute: - `SanitizeAddress`, `SanitizeMemory`, or `SanitizeThread`. By default all - functions are instrumented, but this behaviour can be changed with - `#[no_sanitize(...)]`. + `SanitizeAddress`, `SanitizeHWAddress`, `SanitizeMemory`, or + `SanitizeThread`. By default all functions are instrumented, but this + behaviour can be changed with `#[no_sanitize(...)]`. * The decision whether to perform instrumentation or not is possible only at a function granularity. In the cases were those decision differ between @@ -47,28 +51,66 @@ libraries. Highlight of the most important aspects of the implementation: passes are invoked after optimization passes. * When producing an executable, the sanitizer specific runtime library is - [linked in][sanitizer-link]. The libraries are searched for in target libdir - relative to default system root, so that this process is not affected - by sysroot overrides used for example by cargo `-Z build-std` functionality. + [linked in][sanitizer-link]. The libraries are searched for in the target + libdir. First relative to the overridden system root and subsequently + relative to the default system root. Fall-back to the default system root + ensures that sanitizer runtimes remain available when using sysroot overrides + constructed by cargo `-Z build-std` or xargo. [compiler-rt]: https://github.com/llvm/llvm-project/tree/main/compiler-rt -[sanitizer-build]: https://github.com/rust-lang/rust/blob/a29424a2265411dda7d7446516ac5fd7499e2b55/src/bootstrap/native.rs#L566-L624 -[sanitizer-copy]: https://github.com/rust-lang/rust/blob/a29424a2265411dda7d7446516ac5fd7499e2b55/src/bootstrap/compile.rs#L270-L304 -[sanitizer-attribute]: https://github.com/rust-lang/rust/blob/a29424a2265411dda7d7446516ac5fd7499e2b55/src/librustc_codegen_llvm/attributes.rs#L49-L72 -[inline-mir]: https://github.com/rust-lang/rust/blob/a29424a2265411dda7d7446516ac5fd7499e2b55/src/librustc_mir/transform/inline.rs#L232-L252 +[sanitizer-build]: https://github.com/rust-lang/rust/blob/1.55.0/src/bootstrap/native.rs#L700-L765 +[sanitizer-targets]: https://github.com/rust-lang/rust/blob/1.55.0/src/bootstrap/native.rs#L806-L820 +[sanitizer-copy]: https://github.com/rust-lang/rust/blob/1.55.0/src/bootstrap/compile.rs#L376-L407 +[sanitizer-attribute]: https://github.com/rust-lang/rust/blob/1.55.0/compiler/rustc_codegen_llvm/src/attributes.rs#L42-L58 +[inline-mir]: https://github.com/rust-lang/rust/blob/1.55.0/compiler/rustc_mir/src/transform/inline.rs#L314-L316 [inline-llvm]: https://github.com/rust-lang/llvm-project/blob/9330ec5a4c1df5fc1fa62f993ed6a04da68cb040/llvm/include/llvm/IR/Attributes.td#L225-L241 -[sanitizer-pass]: https://github.com/rust-lang/rust/blob/a29424a2265411dda7d7446516ac5fd7499e2b55/src/librustc_codegen_llvm/back/write.rs#L454-L475 -[sanitizer-link]: https://github.com/rust-lang/rust/blob/a29424a2265411dda7d7446516ac5fd7499e2b55/src/librustc_codegen_ssa/back/link.rs#L748-L787 +[sanitizer-pass]: https://github.com/rust-lang/rust/blob/1.55.0/compiler/rustc_codegen_llvm/src/back/write.rs#L660-L678 +[sanitizer-link]: https://github.com/rust-lang/rust/blob/1.55.0/compiler/rustc_codegen_ssa/src/back/link.rs#L1053-L1089 + +## Testing sanitizers + +Sanitizers are validated by code generation tests in +[`src/test/codegen/sanitize*.rs`][test-cg] and end-to-end functional tests in +[`src/test/ui/sanitize/`][test-ui] directory. + +Testing sanitizer functionality requires the sanitizer runtimes (built when +`sanitizer = true` in `config.toml`) and target providing support for particular +sanitizer. When sanitizer is unsupported on given target, sanitizers tests will +be ignored. This behaviour is controlled by compiletest `needs-sanitizer-*` +directives. + +[test-cg]: https://github.com/rust-lang/rust/tree/master/src/test/codegen +[test-ui]: https://github.com/rust-lang/rust/tree/master/src/test/ui/sanitize + +## Enabling sanitizer on a new target + +To enable a sanitizer on a new target which is already supported by LLVM: + +1. Include the sanitizer in the list of `supported_sanitizers` in [the target + definition][target-definition]. `rustc --target .. -Zsanitizer=..` should now + recognize sanitizer as supported. +2. [Build the runtime for the target and include it in the libdir.][sanitizer-targets] +3. [Teach compiletest that your target now supports the sanitizer.][compiletest-definition] + Tests marked with `needs-sanitizer-*` should now run on the target. +4. Run tests `./x.py test --force-rerun src/test/ui/sanitize/` to verify. +5. [--enable-sanitizers in the CI configuration][ci-configuration] to build and + distribute the sanitizer runtime as part of the release process. + +[target-definition]: https://github.com/rust-lang/rust/blob/1.55.0/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnu.rs#L10-L11 +[compiletest-definition]: https://github.com/rust-lang/rust/blob/1.55.0/src/tools/compiletest/src/util.rs#L87-L116 +[ci-configuration]: https://github.com/rust-lang/rust/blob/1.55.0/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile#L94 ## Additional Information * [Sanitizers project page](https://github.com/google/sanitizers/wiki/) * [AddressSanitizer in Clang][clang-asan] +* [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-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 [clang-tsan]: https://clang.llvm.org/docs/ThreadSanitizer.html diff --git a/src/doc/rustc-dev-guide/src/tests/adding.md b/src/doc/rustc-dev-guide/src/tests/adding.md index d9b063d5c4..d1b19516f6 100644 --- a/src/doc/rustc-dev-guide/src/tests/adding.md +++ b/src/doc/rustc-dev-guide/src/tests/adding.md @@ -208,9 +208,10 @@ source. `profiler = true` in rustc's `config.toml`. * `needs-sanitizer-support` - a sanitizer runtime is required, i.e., `sanitizers = true` in rustc's `config.toml`. -* `needs-sanitizer-{address,leak,memory,thread}` - indicates that test - requires a target with a support for AddressSanitizer, LeakSanitizer, - MemorySanitizer or ThreadSanitizer respectively. +* `needs-sanitizer-{address,hwaddress,leak,memory,thread}` - indicates that + test requires a target with a support for AddressSanitizer, hardware-assisted + AddressSanitizer, LeakSanitizer, MemorySanitizer or ThreadSanitizer + respectively. * `error-pattern` checks the diagnostics just like the `ERROR` annotation without specifying error line. This is useful when the error doesn't give any span. diff --git a/src/doc/rustc-dev-guide/src/tracing.md b/src/doc/rustc-dev-guide/src/tracing.md new file mode 100644 index 0000000000..422d94c538 --- /dev/null +++ b/src/doc/rustc-dev-guide/src/tracing.md @@ -0,0 +1,204 @@ +# Using tracing to debug the compiler + + + +The compiler has a lot of [`debug!`] (or `trace!`) calls, which print out logging information +at many points. These are very useful to at least narrow down the location of +a bug if not to find it entirely, or just to orient yourself as to why the +compiler is doing a particular thing. + +[`debug!`]: https://docs.rs/tracing/0.1/tracing/macro.debug.html + +To see the logs, you need to set the `RUSTC_LOG` environment variable to your +log filter. The full syntax of the log filters can be found in the [rustdoc +of `tracing-subscriber`](https://docs.rs/tracing-subscriber/0.2.24/tracing_subscriber/filter/struct.EnvFilter.html#directives). + +## Function level filters + +Lots of functions in rustc are annotated with + +``` +#[instrument(level = "debug", skip(self))] +fn foo(&self, bar: Type) {} +``` + +which allows you to use + +``` +RUSTC_LOG=[foo] +``` + +to do the following all at once + +* log all function calls to `foo` +* log the arguments (except for those in the `skip` list) +* log everything (from anywhere else in the compiler) until the function returns + +### I don't want everything + +Depending on the scope of the function, you may not want to log everything in its body. +As an example: the `do_mir_borrowck` function will dump hundreds of lines even for trivial +code being borrowchecked. + +Since you can combine all filters, you can add a crate/module path, e.g. + +``` +RUSTC_LOG=rustc_borrowck[do_mir_borrowck] +``` + +### I don't want all calls + +If you are compiling libcore, you likely don't want *all* borrowck dumps, but only one +for a specific function. You can filter function calls by their arguments by regexing them. + +``` +RUSTC_LOG=[do_mir_borrowck{id=\.\*from_utf8_unchecked\.\*}] +``` + +will only give you the logs of borrowchecking `from_utf8_unchecked`. Note that you will +still get a short message per ignored `do_mir_borrowck`, but none of the things inside those +calls. This helps you in looking through the calls that are happening and helps you adjust +your regex if you mistyped it. + +## Broad module level filters + +You can also use filters similar to the `log` crate's filters, which will enable +everything within a specific module. This is often too verbose and too unstructured, +so it is recommended to use function level filters. + +Your log filter can be just `debug` to get all `debug!` output and +higher (e.g., it will also include `info!`), or `path::to::module` to get *all* +output (which will include `trace!`) from a particular module, or +`path::to::module=debug` to get `debug!` output and higher from a particular +module. + +For example, to get the `debug!` output and higher for a specific module, you +can run the compiler with `RUSTC_LOG=path::to::module=debug rustc my-file.rs`. +All `debug!` output will then appear in standard error. + +Note that you can use a partial path and the filter will still work. For +example, if you want to see `info!` output from only +`rustdoc::passes::collect_intra_doc_links`, you could use +`RUSTDOC_LOG=rustdoc::passes::collect_intra_doc_links=info` *or* you could use +`RUSTDOC_LOG=rustdoc::passes::collect_intra=info`. + +If you are developing rustdoc, use `RUSTDOC_LOG` instead. If you are developing +Miri, use `MIRI_LOG` instead. You get the idea :) + +See the [`tracing`] crate's docs, and specifically the docs for [`debug!`] to +see the full syntax you can use. (Note: unlike the compiler, the [`tracing`] +crate and its examples use the `RUST_LOG` environment variable. rustc, rustdoc, +and other tools set custom environment variables.) + +**Note that unless you use a very strict filter, the logger will emit a lot of +output, so use the most specific module(s) you can (comma-separated if +multiple)**. It's typically a good idea to pipe standard error to a file and +look at the log output with a text editor. + +So, to put it together: + +```bash +# This puts the output of all debug calls in `rustc_middle/src/traits` into +# standard error, which might fill your console backscroll. +$ RUSTC_LOG=rustc_middle::traits=debug rustc +stage1 my-file.rs + +# This puts the output of all debug calls in `rustc_middle/src/traits` in +# `traits-log`, so you can then see it with a text editor. +$ RUSTC_LOG=rustc_middle::traits=debug rustc +stage1 my-file.rs 2>traits-log + +# Not recommended! This will show the output of all `debug!` calls +# in the Rust compiler, and there are a *lot* of them, so it will be +# hard to find anything. +$ RUSTC_LOG=debug rustc +stage1 my-file.rs 2>all-log + +# This will show the output of all `info!` calls in `rustc_codegen_ssa`. +# +# There's an `info!` statement in `codegen_instance` that outputs +# every function that is codegen'd. This is useful to find out +# which function triggers an LLVM assertion, and this is an `info!` +# log rather than a `debug!` log so it will work on the official +# compilers. +$ RUSTC_LOG=rustc_codegen_ssa=info rustc +stage1 my-file.rs + +# This will show the output of all `info!` calls made by rustdoc +# or any rustc library it calls. +$ RUSTDOC_LOG=info rustdoc +stage1 my-file.rs + +# This will only show `debug!` calls made by rustdoc directly, +# not any `rustc*` crate. +$ RUSTDOC_LOG=rustdoc=debug rustdoc +stage1 my-file.rs +``` + +## Log colors + +By default, rustc (and other tools, like rustdoc and Miri) will be smart about +when to use ANSI colors in the log output. If they are outputting to a terminal, +they will use colors, and if they are outputting to a file or being piped +somewhere else, they will not. However, it's hard to read log output in your +terminal unless you have a very strict filter, so you may want to pipe the +output to a pager like `less`. But then there won't be any colors, which makes +it hard to pick out what you're looking for! + +You can override whether to have colors in log output with the `RUSTC_LOG_COLOR` +environment variable (or `RUSTDOC_LOG_COLOR` for rustdoc, or `MIRI_LOG_COLOR` +for Miri, etc.). There are three options: `auto` (the default), `always`, and +`never`. So, if you want to enable colors when piping to `less`, use something +similar to this command: + +```bash +# The `-R` switch tells less to print ANSI colors without escaping them. +$ RUSTC_LOG=debug RUSTC_LOG_COLOR=always rustc +stage1 ... | less -R +``` + +Note that `MIRI_LOG_COLOR` will only color logs that come from Miri, not logs +from rustc functions that Miri calls. Use `RUSTC_LOG_COLOR` to color logs from +rustc. + +## How to keep or remove `debug!` and `trace!` calls from the resulting binary + +While calls to `error!`, `warn!` and `info!` are included in every build of the compiler, +calls to `debug!` and `trace!` are only included in the program if +`debug-logging=true` is turned on in config.toml (it is +turned off by default), so if you don't see `DEBUG` logs, especially +if you run the compiler with `RUSTC_LOG=rustc rustc some.rs` and only see +`INFO` logs, make sure that `debug-logging=true` is turned on in your +config.toml. + +## Logging etiquette and conventions + +Because calls to `debug!` are removed by default, in most cases, don't worry +about the performance of adding "unnecessary" calls to `debug!` and leaving them in code you +commit - they won't slow down the performance of what we ship. + +That said, there can also be excessive tracing calls, especially +when they are redundant with other calls nearby or in functions called from +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. + +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)) +in favour of `debug!("foo(...)")` at the start of a function `foo`. +Within functions, prefer `debug!(?variable.field)` over `debug!("xyz = {:?}", variable.field)` +and `debug!(bar = ?var.method(arg))` over `debug!("bar = {:?}", var.method(arg))`. +The documentation for this syntax can be found [here](https://docs.rs/tracing/0.1.28/tracing/#recording-fields). + +One thing to be **careful** of is **expensive** operations in logs. + +If in the module `rustc::foo` you have a statement + +```Rust +debug!(x = ?random_operation(tcx)); +``` + +Then if someone runs a debug `rustc` with `RUSTC_LOG=rustc::foo`, then +`random_operation()` will run. `RUSTC_LOG` filters that do not enable this +debug statement will not execute `random_operation`. + +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 diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md index bc1873b683..8c41835183 100644 --- a/src/doc/rustc/src/SUMMARY.md +++ b/src/doc/rustc/src/SUMMARY.md @@ -14,6 +14,7 @@ - [Tests](tests/index.md) - [Platform Support](platform-support.md) - [aarch64-apple-ios-sim](platform-support/aarch64-apple-ios-sim.md) + - [\*-kmc-solid_\*](platform-support/kmc-solid.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 05384117ac..4f8c4c66f8 100644 --- a/src/doc/rustc/src/codegen-options/index.md +++ b/src/doc/rustc/src/codegen-options/index.md @@ -435,6 +435,10 @@ Equivalent to the "uppercase" `-fPIC` or `-fPIE` options in other compilers, depending on the produced crate types. \ This is the default model for majority of supported targets. +- `pie` - position independent executable, relocatable code but without support for symbol +interpositioning (replacing symbols by name using `LD_PRELOAD` and similar). Equivalent to the "uppercase" `-fPIE` option in other compilers. `pie` +code cannot be linked into shared libraries (you'll get a linking error on attempt to do this). + #### Special relocation models - `dynamic-no-pic` - relocatable external references, non-relocatable code. \ diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index 6da0703bea..bbeab598f2 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -133,8 +133,8 @@ target | std | notes `armv5te-unknown-linux-musleabi` | ✓ | ARMv5TE Linux with MUSL `armv7-linux-androideabi` | ✓ | ARMv7a Android `armv7-unknown-linux-gnueabi` | ✓ |ARMv7 Linux (kernel 4.15, glibc 2.27) -`armv7-unknown-linux-musleabi` | ✓ |ARMv7 Linux, MUSL -`armv7-unknown-linux-musleabihf` | ✓ | ARMv7 Linux with MUSL +`armv7-unknown-linux-musleabi` | ✓ |ARMv7 Linux with MUSL +`armv7-unknown-linux-musleabihf` | ✓ | ARMv7 Linux with MUSL, hardfloat `armv7a-none-eabi` | * | Bare ARMv7-A `armv7r-none-eabi` | * | Bare ARMv7-R `armv7r-none-eabihf` | * | Bare ARMv7-R, hardfloat @@ -202,6 +202,7 @@ target | std | host | notes -------|:---:|:----:|------- `aarch64-apple-ios-macabi` | ? | | Apple Catalyst on ARM64 `aarch64-apple-tvos` | * | | ARM64 tvOS +[`aarch64-kmc-solid_asp3`](platform-support/kmc-solid.md) | ✓ | | ARM64 SOLID with TOPPERS/ASP3 `aarch64-unknown-freebsd` | ✓ | ✓ | ARM64 FreeBSD `aarch64-unknown-hermit` | ? | | `aarch64-unknown-uefi` | * | | ARM64 UEFI @@ -217,10 +218,14 @@ target | std | host | notes `armv5te-unknown-linux-uclibceabi` | ? | | ARMv5TE Linux with uClibc `armv6-unknown-freebsd` | ✓ | ✓ | ARMv6 FreeBSD `armv6-unknown-netbsd-eabihf` | ? | | +`armv6k-nintendo-3ds` | * | | ARMv6K Nintendo 3DS, Horizon (Requires devkitARM toolchain) `armv7-apple-ios` | ✓ | | ARMv7 iOS, Cortex-a8 +`armv7-unknown-linux-uclibceabihf` | ✓ | ? | ARMv7 Linux uClibc `armv7-unknown-freebsd` | ✓ | ✓ | ARMv7 FreeBSD `armv7-unknown-netbsd-eabihf` | ✓ | ✓ | `armv7-wrs-vxworks-eabihf` | ? | | +[`armv7a-kmc-solid_asp3-eabi`](platform-support/kmc-solid.md) | ✓ | | ARM SOLID with TOPPERS/ASP3 +[`armv7a-kmc-solid_asp3-eabihf`](platform-support/kmc-solid.md) | ✓ | | ARM SOLID with TOPPERS/ASP3, hardfloat `armv7a-none-eabihf` | * | | ARM Cortex-A, hardfloat `armv7s-apple-ios` | ✓ | | `avr-unknown-gnu-atmega328` | * | | AVR. Requires `-Z build-std=core` @@ -237,6 +242,7 @@ target | std | host | notes `i686-uwp-windows-gnu` | ? | | `i686-uwp-windows-msvc` | ? | | `i686-wrs-vxworks` | ? | | +`m68k-unknown-linux-gnu` | ? | | Motorola 680x0 Linux `mips-unknown-linux-uclibc` | ✓ | | MIPS Linux with uClibc `mipsel-sony-psp` | * | | MIPS (LE) Sony PlayStation Portable (PSP) `mipsel-unknown-linux-uclibc` | ✓ | | MIPS (LE) Linux with uClibc diff --git a/src/doc/rustc/src/platform-support/armv7-unknown-linux-uclibceabihf.md b/src/doc/rustc/src/platform-support/armv7-unknown-linux-uclibceabihf.md new file mode 100644 index 0000000000..b3a4275c6e --- /dev/null +++ b/src/doc/rustc/src/platform-support/armv7-unknown-linux-uclibceabihf.md @@ -0,0 +1,66 @@ +# armv7-unknown-linux-uclibceabihf + +**Tier: 3** + +This tier supports the ARMv7 processor running a Linux kernel and uClibc-ng standard library. It provides full support for rust and the rust standard library. + +## Designated Developers + +* [@skrap](https://github.com/skrap) + +## Requirements + +This target is cross compiled, and requires a cross toolchain. You can find suitable pre-built toolchains at [bootlin](https://toolchains.bootlin.com/) or build one yourself via [buildroot](https://buildroot.org). + +## Building + +### Get a C toolchain + +Compiling rust for this target has been tested on `x86_64` linux hosts. Other host types have not been tested, but may work, if you can find a suitable cross compilation toolchain for them. + +If you don't already have a suitable toolchain, download one [here](https://toolchains.bootlin.com/downloads/releases/toolchains/armv7-eabihf/tarballs/armv7-eabihf--uclibc--bleeding-edge-2020.08-1.tar.bz2), and unpack it into a directory. + +### Configure rust + +The target can be built by enabling it for a `rustc` build, by placing the following in `config.toml`: + +```toml +[build] +target = ["armv7-unknown-linux-uclibceabihf"] +stage = 2 + +[target.armv7-unknown-linux-uclibceabihf] +# ADJUST THIS PATH TO POINT AT YOUR TOOLCHAIN +cc = "/TOOLCHAIN_PATH/bin/arm-buildroot-linux-uclibcgnueabihf-gcc" +``` + +### Build + +```sh +# in rust dir +./x.py build --stage 2 +``` + +## Building and Running Rust Programs + +To test cross-compiled binaries on a `x86_64` system, you can use the `qemu-arm` [userspace emulation](https://qemu-project.gitlab.io/qemu/user/main.html) program. This avoids having a full emulated ARM system by doing dynamic binary translation and dynamic system call translation. It lets you run ARM programs directly on your `x86_64` kernel. It's very convenient! + +To use: + +* Install `qemu-arm` according to your distro. +* Link your built toolchain via: + * `rustup toolchain link stage2 ${RUST}/build/x86_64-unknown-linux-gnu/stage2` +* Create a test program + +```sh +cargo new hello_world +cd hello_world +``` + +* Build and run + +```sh +CARGO_TARGET_ARMV7_UNKNOWN_LINUX_UCLIBCEABIHF_RUNNER="qemu-arm -L ${TOOLCHAIN}/arm-buildroot-linux-uclibcgnueabihf/sysroot/" \ +CARGO_TARGET_ARMV7_UNKNOWN_LINUX_UCLIBCEABIHF_LINKER=${TOOLCHAIN}/bin/arm-buildroot-linux-uclibcgnueabihf-gcc \ +cargo +stage2 run --target armv7-unknown-linux-uclibceabihf +``` diff --git a/src/doc/rustc/src/platform-support/kmc-solid.md b/src/doc/rustc/src/platform-support/kmc-solid.md new file mode 100644 index 0000000000..bbcd0f711c --- /dev/null +++ b/src/doc/rustc/src/platform-support/kmc-solid.md @@ -0,0 +1,65 @@ +# \*-kmc-solid_\* + +**Tier: 3** + +[SOLID] embedded development platform by Kyoto Microcomputer Co., Ltd. + +[SOLID]: https://www.kmckk.co.jp/eng/SOLID/ + +The target names follow this format: `$ARCH-kmc-solid_$KERNEL-$ABI`, where `$ARCH` specifies the target processor architecture, `$KERNEL` the base kernel, and `$ABI` the target ABI (optional). The following targets are currently defined: + +| Target name | `target_arch` | `target_vendor` | `target_os` | +|--------------------------------|---------------|-----------------|--------------| +| `aarch64-kmc-solid_asp3` | `aarch64` | `kmc` | `solid_asp3` | +| `armv7a-kmc-solid_asp3-eabi` | `arm` | `kmc` | `solid_asp3` | +| `armv7a-kmc-solid_asp3-eabihf` | `arm` | `kmc` | `solid_asp3` | + +## Designated Developers + +- [@kawadakk](https://github.com/kawadakk) + +## Requirements + +This target is cross-compiled. +A platform-provided C compiler toolchain is required, though it can be substituted by [GNU Arm Embedded Toolchain](https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-rm) for the purpose of building Rust and functional binaries. + +## Building + +The target can be built by enabling it for a `rustc` build. + +```toml +[build] +target = ["aarch64-kmc-solid_asp3"] +``` + +Make sure `aarch64-kmc-elf-gcc` is included in `$PATH`. Alternatively, you can use GNU Arm Embedded Toolchain by adding the following to `config.toml`: + +```toml +[target.aarch64-kmc-solid_asp3] +cc = "arm-none-eabi-gcc" +``` + +## Cross-compilation + +This target can be cross-compiled from any hosts. + +## Testing + +Currently there is no support to run the rustc test suite for this target. + +## Building Rust programs + +Building executables is not supported yet. + +If `rustc` has support for that target and the library artifacts are available, then Rust static libraries can be built for that target: + +```shell +$ rustc --target aarch64-kmc-solid_asp3 your-code.rs --crate-type staticlib +$ ls libyour_code.a +``` + +On Rust Nightly it's possible to build without the target artifacts available: + +```text +cargo build -Z build-std --target aarch64-kmc-solid_asp3 +``` diff --git a/src/doc/rustc/src/platform-support/m68k-unknown-linux-gnu.md b/src/doc/rustc/src/platform-support/m68k-unknown-linux-gnu.md new file mode 100644 index 0000000000..d325ba3346 --- /dev/null +++ b/src/doc/rustc/src/platform-support/m68k-unknown-linux-gnu.md @@ -0,0 +1,97 @@ +# m68k-unknown-linux-gnu + +**Tier: 3** + +Motorola 680x0 Linux + +## Designated Developers + +* [@glaubitz](https://github.com/glaubitz) +* [@ricky26](https://github.com/ricky26) + +## Requirements + +This target requires a Linux/m68k build environment for cross-compilation which +is available on Debian and Debian-based systems, openSUSE and other distributions. + +On Debian, it should be sufficient to install a g++ cross-compiler for the m68k +architecture which will automatically pull in additional dependencies such as +the glibc cross development package: + +```text +# apt install g++-m68k-linux-gnu +``` + +Binaries can be run using QEMU user emulation. On Debian-based systems, it should be +sufficient to install the package `qemu-user-static` to be able to run simple static +binaries: + +```text +# apt install qemu-user-static +``` + +To run more complex programs, it will be necessary to set up a Debian/m68k chroot with +the help of the command `debootstrap`: + +```text +# apt install debootstrap debian-ports-archive-keyring +# debootstrap --keyring=/usr/share/keyrings/debian-ports-archive-keyring.gpg --arch=m68k unstable debian-68k http://ftp.ports.debian.org/debian-ports +``` + +This chroot can then seamlessly entered using the normal `chroot` command thanks to +QEMU user emulation: + +```text +# chroot /path/to/debian-68k +``` + +To get started with native builds, which are currently untested, a native Debian/m68k +system can be installed either on real hardware such as 68k-based Commodore Amiga or +Atari systems or emulated environments such as QEMU version 4.2 or newer or ARAnyM. + +ISO images for installation are provided by the Debian Ports team and can be obtained +from the Debian CD image server available at: + +[https://cdimage.debian.org/cdimage/ports/current](https://cdimage.debian.org/cdimage/ports/current/) + +Documentation for Debian/m68k is available on the Debian Wiki at: + +[https://wiki.debian.org/M68k](https://wiki.debian.org/M68k) + +Support is available either through the `debian-68k` mailing list: + +[https://lists.debian.org/debian-68k/](https://lists.debian.org/debian-68k/) + +or the `#debian-68k` IRC channel on OFTC network. + +## Building + +The codegen for this target should be built by default. However, core and std +are currently missing but are being worked on and should become available in +the near future. + +## Cross-compilation + +This target can be cross-compiled from a standard Debian or Debian-based, openSUSE or any +other distribution which has a basic m68k cross-toolchain available. + +## Testing + +Currently there is no support to run the rustc test suite for this target. + +## Building Rust programs + +Rust programs can be built for that target: + +```text +rustc --target m68k-unknown-linux-gnu your-code.rs +``` + +Very simple progams can be run using the `qemu-m68k-static` program: + +```text +$ qemu-m68k-static your-code +``` + +For more complex applications, a chroot or native (emulated) Debian/m68k system are required +for testing. diff --git a/src/doc/rustc/src/tests/index.md b/src/doc/rustc/src/tests/index.md index ec23d4fe0d..23a9f31e8e 100644 --- a/src/doc/rustc/src/tests/index.md +++ b/src/doc/rustc/src/tests/index.md @@ -161,7 +161,7 @@ The following options affect how tests are executed. Sets the number of threads to use for running tests in parallel. By default, uses the amount of concurrency available on the hardware as indicated by -[`available_concurrency`]. +[`available_parallelism`]. This can also be specified with the `RUST_TEST_THREADS` environment variable. @@ -181,6 +181,40 @@ unstable-options` flag. See [tracking issue #64888](https://github.com/rust-lang/rust/issues/64888) and the [unstable docs](../../unstable-book/compiler-flags/report-time.html) for more information. +#### `--shuffle` + +Runs the tests in random order, as opposed to the default alphabetical order. + +This may also be specified by setting the `RUST_TEST_SHUFFLE` environment +variable to anything but `0`. + +The random number generator seed that is output can be passed to +[`--shuffle-seed`](#--shuffle-seed-seed) to run the tests in the same order +again. + +Note that `--shuffle` does not affect whether the tests are run in parallel. To +run the tests in random order sequentially, use `--shuffle --test-threads 1`. + +⚠️ 🚧 This option is [unstable](#unstable-options), and requires the `-Z +unstable-options` flag. See [tracking issue +#89583](https://github.com/rust-lang/rust/issues/89583) for more information. + +#### `--shuffle-seed` _SEED_ + +Like [`--shuffle`](#--shuffle), but seeds the random number generator with +_SEED_. Thus, calling the test harness with `--shuffle-seed` _SEED_ twice runs +the tests in the same order both times. + +_SEED_ is any 64-bit unsigned integer, for example, one produced by +[`--shuffle`](#--shuffle). + +This can also be specified with the `RUST_TEST_SHUFFLE_SEED` environment +variable. + +⚠️ 🚧 This option is [unstable](#unstable-options), and requires the `-Z +unstable-options` flag. See [tracking issue +#89583](https://github.com/rust-lang/rust/issues/89583) for more information. + ### Output options The following options affect the output behavior. @@ -197,7 +231,7 @@ to the console. Usually the output is captured, and only displayed if the test fails. This may also be specified by setting the `RUST_TEST_NOCAPTURE` environment -variable set to anything but `0`. +variable to anything but `0`. #### `--show-output` @@ -265,7 +299,7 @@ Experimental support for using custom test harnesses is available on the [`--test` option]: ../command-line-arguments.md#option-test [`-Z panic-abort-tests`]: https://github.com/rust-lang/rust/issues/67650 -[`available_concurrency`]: ../../std/thread/fn.available_concurrency.html +[`available_parallelism`]: ../../std/thread/fn.available_parallelism.html [`cargo test`]: ../../cargo/commands/cargo-test.html [`libtest`]: ../../test/index.html [`main` function]: ../../reference/crates-and-source-files.html#main-functions diff --git a/src/doc/rustdoc/src/lints.md b/src/doc/rustdoc/src/lints.md index 16b091eb25..1773c15464 100644 --- a/src/doc/rustdoc/src/lints.md +++ b/src/doc/rustdoc/src/lints.md @@ -70,6 +70,8 @@ This lint **warns by default**. This lint detects when [intra-doc links] from pu For example: ```rust +#![warn(rustdoc::private_intra_doc_links)] // note: unnecessary - warns by default. + /// [private] pub fn public() {} fn private() {} @@ -227,6 +229,8 @@ This lint **warns by default**. It detects code block attributes in documentation examples that have potentially mis-typed values. For example: ```rust +#![warn(rustdoc::invalid_codeblock_attributes)] // note: unnecessary - warns by default. + /// Example. /// /// ```should-panic @@ -344,6 +348,8 @@ This lint is **warn-by-default**. It detects URLs which are not links. For example: ```rust +#![warn(rustdoc::bare_urls)] // note: unnecessary - warns by default. + /// http://example.org /// [http://example.net] pub fn foo() {} diff --git a/src/doc/rustdoc/src/unstable-features.md b/src/doc/rustdoc/src/unstable-features.md index dce98abcf5..9179599764 100644 --- a/src/doc/rustdoc/src/unstable-features.md +++ b/src/doc/rustdoc/src/unstable-features.md @@ -209,6 +209,22 @@ some consideration for their stability, and names that end in a number). Giving `rustdoc` will disable this sorting and instead make it print the items in the order they appear in the source. +### `--show-type-layout`: add a section to each type's docs describing its memory layout + +Using this flag looks like this: + +```bash +$ rustdoc src/lib.rs -Z unstable-options --show-type-layout +``` + +When this flag is passed, rustdoc will add a "Layout" section at the bottom of +each type's docs page that includes a summary of the type's memory layout as +computed by rustc. For example, rustdoc will show the size in bytes that a value +of that type will take in memory. + +Note that most layout information is **completely unstable** and may even differ +between compilations. + ### `--resource-suffix`: modifying the name of CSS/JavaScript in crate docs Using this flag looks like this: @@ -222,13 +238,13 @@ 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-warnings`: display warnings when documenting or running documentation tests +### `--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-warnings -$ rustdoc --test src/lib.rs -Z unstable-options --display-warnings +$ 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 @@ -333,7 +349,7 @@ 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 +### `-w`/`--output-format`: output format When using [`--show-coverage`](https://doc.rust-lang.org/nightly/rustdoc/unstable-features.html#--show-coverage-get-statistics-about-code-documentation-coverage), diff --git a/src/doc/unstable-book/src/compiler-flags/debug_info_for_profiling.md b/src/doc/unstable-book/src/compiler-flags/debug_info_for_profiling.md new file mode 100644 index 0000000000..44bd3baeee --- /dev/null +++ b/src/doc/unstable-book/src/compiler-flags/debug_info_for_profiling.md @@ -0,0 +1,35 @@ +# `debug-info-for-profiling + +--- + +## Introduction + +Automatic Feedback Directed Optimization (AFDO) is a method for using sampling +based profiles to guide optimizations. This is contrasted with other methods of +FDO or profile-guided optimization (PGO) which use instrumented profiling. + +Unlike PGO (controlled by the `rustc` flags `-Cprofile-generate` and +`-Cprofile-use`), a binary being profiled does not perform significantly worse, +and thus it's possible to profile binaries used in real workflows and not +necessary to construct artificial workflows. + +## Use + +In order to use AFDO, the target platform must be Linux running on an `x86_64` +architecture with the performance profiler `perf` available. In addition, the +external tool `create_llvm_prof` from [this repository] must be used. + +Given a Rust file `main.rs`, we can produce an optimized binary as follows: + +```shell +rustc -O -Zdebug-info-for-profiling main.rs -o main +perf record -b ./main +create_llvm_prof --binary=main --out=code.prof +rustc -O -Zprofile-sample-use=code.prof main.rs -o main2 +``` + +The `perf` command produces a profile `perf.data`, which is then used by the +`create_llvm_prof` command to create `code.prof`. This final profile is then +used by `rustc` to guide optimizations in producing the binary `main2`. + +[this repository]: https://github.com/google/autofdo diff --git a/src/doc/unstable-book/src/compiler-flags/profile_sample_use.md b/src/doc/unstable-book/src/compiler-flags/profile_sample_use.md new file mode 100644 index 0000000000..ce894ce6ac --- /dev/null +++ b/src/doc/unstable-book/src/compiler-flags/profile_sample_use.md @@ -0,0 +1,10 @@ +# `profile-sample-use + +--- + +`-Zprofile-sample-use=code.prof` directs `rustc` to use the profile +`code.prof` as a source for Automatic Feedback Directed Optimization (AFDO). +See the documentation of [`-Zdebug-info-for-profiling`] for more information +on using AFDO. + +[`-Zdebug-info-for-profiling`]: debug_info_for_profiling.html diff --git a/src/doc/unstable-book/src/compiler-flags/remap-cwd-prefix.md b/src/doc/unstable-book/src/compiler-flags/remap-cwd-prefix.md new file mode 100644 index 0000000000..977d258529 --- /dev/null +++ b/src/doc/unstable-book/src/compiler-flags/remap-cwd-prefix.md @@ -0,0 +1,24 @@ +# `remap-cwd-prefix` + +The tracking issue for this feature is: [#87325](https://github.com/rust-lang/rust/issues/87325). + +------------------------ + +This flag will rewrite absolute paths under the current working directory, +replacing the current working directory prefix with a specified value. + +The given value may be absolute or relative, or empty. This switch takes +precidence over `--remap-path-prefix` in case they would both match a given +path. + +This flag helps to produce deterministic output, by removing the current working +directory from build output, while allowing the command line to be universally +reproducible, such that the same execution will work on all machines, regardless +of build environment. + +## Example +```sh +# This would produce an absolute path to main.rs in build outputs of +# "./main.rs". +rustc -Z remap-cwd-prefix=. main.rs +``` diff --git a/src/doc/unstable-book/src/language-features/closure-track-caller.md b/src/doc/unstable-book/src/language-features/closure-track-caller.md new file mode 100644 index 0000000000..c948810d3e --- /dev/null +++ b/src/doc/unstable-book/src/language-features/closure-track-caller.md @@ -0,0 +1,12 @@ +# `closure_track_caller` + +The tracking issue for this feature is: [#87417] + +[#87417]: https://github.com/rust-lang/rust/issues/87417 + +------------------------ + +Allows using the `#[track_caller]` attribute on closures and generators. +Calls made to the closure or generator will have caller information +available through `std::panic::Location::caller()`, just like using +`#[track_caller]` on a function. diff --git a/src/doc/unstable-book/src/library-features/asm.md b/src/doc/unstable-book/src/library-features/asm.md index a10928a747..5a2cef2487 100644 --- a/src/doc/unstable-book/src/library-features/asm.md +++ b/src/doc/unstable-book/src/library-features/asm.md @@ -375,7 +375,7 @@ Any reuse of a named label, local or otherwise, can result in a assembler or lin As a consequence, you should only use GNU assembler **numeric** [local labels] inside inline assembly code. Defining symbols in assembly code may lead to assembler and/or linker errors due to duplicate symbol definitions. -Moreover, on x86 when using the default intel syntax, due to [an llvm bug], you shouldn't use labels exclusively made of `0` and `1` digits, e.g. `0`, `11` or `101010`, as they may end up being interpreted as binary values. Using `option(att_syntax)` will avoid any ambiguity, but that affects the syntax of the _entire_ `asm!` block. +Moreover, on x86 when using the default intel syntax, due to [an llvm bug], you shouldn't use labels exclusively made of `0` and `1` digits, e.g. `0`, `11` or `101010`, as they may end up being interpreted as binary values. Using `options(att_syntax)` will avoid any ambiguity, but that affects the syntax of the _entire_ `asm!` block. ```rust,allow_fail #![feature(asm)] @@ -456,7 +456,7 @@ operand := reg_operand / "const" const_expr / "sym" path 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: @@ -613,8 +613,8 @@ Each register class has constraints on which value types they can be used with. | x86 | `xmm_reg` | `sse` | `i32`, `f32`, `i64`, `f64`,
`i8x16`, `i16x8`, `i32x4`, `i64x2`, `f32x4`, `f64x2` | | x86 | `ymm_reg` | `avx` | `i32`, `f32`, `i64`, `f64`,
`i8x16`, `i16x8`, `i32x4`, `i64x2`, `f32x4`, `f64x2`
`i8x32`, `i16x16`, `i32x8`, `i64x4`, `f32x8`, `f64x4` | | x86 | `zmm_reg` | `avx512f` | `i32`, `f32`, `i64`, `f64`,
`i8x16`, `i16x8`, `i32x4`, `i64x2`, `f32x4`, `f64x2`
`i8x32`, `i16x16`, `i32x8`, `i64x4`, `f32x8`, `f64x4`
`i8x64`, `i16x32`, `i32x16`, `i64x8`, `f32x16`, `f64x8` | -| x86 | `kreg` | `axv512f` | `i8`, `i16` | -| x86 | `kreg` | `axv512bw` | `i32`, `i64` | +| x86 | `kreg` | `avx512f` | `i8`, `i16` | +| x86 | `kreg` | `avx512bw` | `i32`, `i64` | | x86 | `mmx_reg` | N/A | Only clobbers | | x86 | `x87_reg` | N/A | Only clobbers | | AArch64 | `reg` | None | `i8`, `i16`, `i32`, `f32`, `i64`, `f64` | @@ -804,9 +804,9 @@ The following ABIs can be used with `clobber_abi`: | Architecture | ABI name | Clobbered registers | | ------------ | -------- | ------------------- | -| x86-32 | `"C"`, `"system"`, `"efiapi"`, `"cdecl"`, `"stdcall"`, `"fastcall"` | `ax`, `cx`, `dx`, `xmm[0-7]`, `mm[0-7]`, `st([0-7])` | -| x86-64 | `"C"`, `"system"` (on Windows), `"efiapi"`, `"win64"` | `ax`, `cx`, `dx`, `r[8-11]`, `xmm[0-31]`, `mm[0-7]`, `st([0-7])` | -| x86-64 | `"C"`, `"system"` (on non-Windows), `"sysv64"` | `ax`, `cx`, `dx`, `si`, `di`, `r[8-11]`, `xmm[0-31]`, `mm[0-7]`, `st([0-7])` | +| x86-32 | `"C"`, `"system"`, `"efiapi"`, `"cdecl"`, `"stdcall"`, `"fastcall"` | `ax`, `cx`, `dx`, `xmm[0-7]`, `mm[0-7]`, `k[1-7]`, `st([0-7])` | +| x86-64 | `"C"`, `"system"` (on Windows), `"efiapi"`, `"win64"` | `ax`, `cx`, `dx`, `r[8-11]`, `xmm[0-31]`, `mm[0-7]`, `k[1-7]`, `st([0-7])` | +| x86-64 | `"C"`, `"system"` (on non-Windows), `"sysv64"` | `ax`, `cx`, `dx`, `si`, `di`, `r[8-11]`, `xmm[0-31]`, `mm[0-7]`, `k[1-7]`, `st([0-7])` | | AArch64 | `"C"`, `"system"`, `"efiapi"` | `x[0-17]`, `x30`, `v[0-31]`, `p[0-15]`, `ffr` | | ARM | `"C"`, `"system"`, `"efiapi"`, `"aapcs"` | `r[0-3]`, `r12`, `r14`, `s[0-15]`, `d[0-7]`, `d[16-31]` | | RISC-V | `"C"`, `"system"`, `"efiapi"` | `x1`, `x[5-7]`, `x[10-17]`, `x[28-31]`, `f[0-7]`, `f[10-17]`, `f[28-31]`, `v[0-31]` | diff --git a/src/etc/check_missing_items.py b/src/etc/check_missing_items.py index 7572b8c6f4..7ed317c778 100644 --- a/src/etc/check_missing_items.py +++ b/src/etc/check_missing_items.py @@ -9,7 +9,7 @@ import sys import json -crate = json.load(open(sys.argv[1])) +crate = json.load(open(sys.argv[1], encoding="utf-8")) def get_local_item(item_id): diff --git a/src/etc/test-float-parse/Cargo.toml b/src/etc/test-float-parse/Cargo.toml index 8226e815c2..7ee19a0b6d 100644 --- a/src/etc/test-float-parse/Cargo.toml +++ b/src/etc/test-float-parse/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "test-float-parse" version = "0.1.0" -edition = "2018" +edition = "2021" publish = false [workspace] diff --git a/src/librustdoc/Cargo.toml b/src/librustdoc/Cargo.toml index e02cef235a..945b2a8e9a 100644 --- a/src/librustdoc/Cargo.toml +++ b/src/librustdoc/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustdoc" version = "0.0.0" -edition = "2018" +edition = "2021" [lib] path = "lib.rs" diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs index 9217209fcf..f9d1666977 100644 --- a/src/librustdoc/clean/auto_trait.rs +++ b/src/librustdoc/clean/auto_trait.rs @@ -114,17 +114,17 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { attrs: Default::default(), visibility: Inherited, def_id: ItemId::Auto { trait_: trait_def_id, for_: item_def_id }, - kind: Box::new(ImplItem(Impl { + kind: box ImplItem(Impl { span: Span::dummy(), unsafety: hir::Unsafety::Normal, generics: new_generics, - trait_: Some(trait_ref.clean(self.cx).get_trait_type().unwrap()), + trait_: Some(trait_ref.clean(self.cx)), for_: ty.clean(self.cx), items: Vec::new(), negative_polarity, synthetic: true, blanket_impl: None, - })), + }), cfg: None, }) } @@ -166,16 +166,16 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { .clone() } - // This method calculates two things: Lifetime constraints of the form 'a: 'b, - // and region constraints of the form ReVar: 'a - // - // This is essentially a simplified version of lexical_region_resolve. However, - // handle_lifetimes determines what *needs be* true in order for an impl to hold. - // lexical_region_resolve, along with much of the rest of the compiler, is concerned - // with determining if a given set up constraints/predicates *are* met, given some - // starting conditions (e.g., user-provided code). For this reason, it's easier - // to perform the calculations we need on our own, rather than trying to make - // existing inference/solver code do what we want. + /// This method calculates two things: Lifetime constraints of the form `'a: 'b`, + /// and region constraints of the form `RegionVid: 'a` + /// + /// This is essentially a simplified version of lexical_region_resolve. However, + /// handle_lifetimes determines what *needs be* true in order for an impl to hold. + /// lexical_region_resolve, along with much of the rest of the compiler, is concerned + /// with determining if a given set up constraints/predicates *are* met, given some + /// starting conditions (e.g., user-provided code). For this reason, it's easier + /// to perform the calculations we need on our own, rather than trying to make + /// existing inference/solver code do what we want. fn handle_lifetimes<'cx>( regions: &RegionConstraintData<'cx>, names_map: &FxHashMap, @@ -331,9 +331,10 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { match br { // We only care about named late bound regions, as we need to add them // to the 'for<>' section - ty::BrNamed(_, name) => { - Some(GenericParamDef { name, kind: GenericParamDefKind::Lifetime }) - } + ty::BrNamed(_, name) => Some(GenericParamDef { + name, + kind: GenericParamDefKind::Lifetime { outlives: vec![] }, + }), _ => None, } }) @@ -352,52 +353,35 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { if let Some(data) = ty_to_fn.get(&ty) { let (poly_trait, output) = (data.0.as_ref().unwrap().clone(), data.1.as_ref().cloned().map(Box::new)); - let new_ty = match poly_trait.trait_ { - Type::ResolvedPath { ref path, ref did, ref is_generic } => { - let mut new_path = path.clone(); - let last_segment = - new_path.segments.pop().expect("segments were empty"); + let mut new_path = poly_trait.trait_.clone(); + let last_segment = new_path.segments.pop().expect("segments were empty"); - let (old_input, old_output) = match last_segment.args { - GenericArgs::AngleBracketed { args, .. } => { - let types = args - .iter() - .filter_map(|arg| match arg { - GenericArg::Type(ty) => Some(ty.clone()), - _ => None, - }) - .collect(); - (types, None) - } - GenericArgs::Parenthesized { inputs, output, .. } => { - (inputs, output) - } - }; - - if old_output.is_some() && old_output != output { - panic!( - "Output mismatch for {:?} {:?} {:?}", - ty, old_output, data.1 - ); - } - - let new_params = - GenericArgs::Parenthesized { inputs: old_input, output }; - - new_path - .segments - .push(PathSegment { name: last_segment.name, args: new_params }); - - Type::ResolvedPath { - path: new_path, - did: *did, - is_generic: *is_generic, - } + let (old_input, old_output) = match last_segment.args { + GenericArgs::AngleBracketed { args, .. } => { + let types = args + .iter() + .filter_map(|arg| match arg { + GenericArg::Type(ty) => Some(ty.clone()), + _ => None, + }) + .collect(); + (types, None) } - _ => panic!("Unexpected data: {:?}, {:?}", ty, data), + GenericArgs::Parenthesized { inputs, output } => (inputs, output), }; + + if old_output.is_some() && old_output != output { + panic!("Output mismatch for {:?} {:?} {:?}", ty, old_output, data.1); + } + + let new_params = GenericArgs::Parenthesized { inputs: old_input, output }; + + new_path + .segments + .push(PathSegment { name: last_segment.name, args: new_params }); + bounds.insert(GenericBound::TraitBound( - PolyTrait { trait_: new_ty, generic_params: poly_trait.generic_params }, + PolyTrait { trait_: new_path, generic_params: poly_trait.generic_params }, hir::TraitBoundModifier::None, )); } @@ -426,15 +410,15 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { .collect() } - // Converts the calculated ParamEnv and lifetime information to a clean::Generics, suitable for - // display on the docs page. Cleaning the Predicates produces sub-optimal `WherePredicate`s, - // so we fix them up: - // - // * Multiple bounds for the same type are coalesced into one: e.g., 'T: Copy', 'T: Debug' - // becomes 'T: Copy + Debug' - // * Fn bounds are handled specially - instead of leaving it as 'T: Fn(), = - // K', we use the dedicated syntax 'T: Fn() -> K' - // * We explicitly add a '?Sized' bound if we didn't find any 'Sized' predicates for a type + /// Converts the calculated `ParamEnv` and lifetime information to a [`clean::Generics`](Generics), suitable for + /// display on the docs page. Cleaning the `Predicates` produces sub-optimal [`WherePredicate`]s, + /// so we fix them up: + /// + /// * Multiple bounds for the same type are coalesced into one: e.g., `T: Copy`, `T: Debug` + /// becomes `T: Copy + Debug` + /// * `Fn` bounds are handled specially - instead of leaving it as `T: Fn(), = + /// K`, we use the dedicated syntax `T: Fn() -> K` + /// * We explicitly add a `?Sized` bound if we didn't find any `Sized` predicates for a type fn param_env_to_generics( &mut self, item_def_id: DefId, @@ -479,7 +463,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { let mut has_sized = FxHashSet::default(); let mut ty_to_bounds: FxHashMap<_, FxHashSet<_>> = Default::default(); let mut lifetime_to_bounds: FxHashMap<_, FxHashSet<_>> = Default::default(); - let mut ty_to_traits: FxHashMap> = Default::default(); + let mut ty_to_traits: FxHashMap> = Default::default(); let mut ty_to_fn: FxHashMap, Option)> = Default::default(); @@ -514,11 +498,11 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { if b.is_sized_bound(self.cx) { has_sized.insert(ty.clone()); } else if !b - .get_trait_type() - .and_then(|t| { + .get_trait_path() + .and_then(|trait_| { ty_to_traits .get(&ty) - .map(|bounds| bounds.contains(&strip_type(t.clone()))) + .map(|bounds| bounds.contains(&strip_path_generics(trait_.clone()))) }) .unwrap_or(false) { @@ -535,7 +519,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { // that we don't end up with duplicate bounds (e.g., for<'b, 'b>) for_generics.extend(p.generic_params.clone()); p.generic_params = for_generics.into_iter().collect(); - self.is_fn_ty(&p.trait_) + self.is_fn_trait(&p.trait_) } _ => false, }; @@ -561,83 +545,59 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { match lhs { Type::QPath { name: left_name, ref self_type, ref trait_, .. } => { let ty = &*self_type; - match **trait_ { - Type::ResolvedPath { - path: ref trait_path, - ref did, - ref is_generic, - } => { - let mut new_trait_path = trait_path.clone(); + let mut new_trait = trait_.clone(); - if self.is_fn_ty(trait_) && left_name == sym::Output { - ty_to_fn - .entry(*ty.clone()) - .and_modify(|e| *e = (e.0.clone(), Some(rhs.clone()))) - .or_insert((None, Some(rhs))); - continue; - } - - let args = &mut new_trait_path - .segments - .last_mut() - .expect("segments were empty") - .args; - - match args { - // Convert something like ' = u8' - // to 'T: Iterator' - GenericArgs::AngleBracketed { - ref mut bindings, .. - } => { - bindings.push(TypeBinding { - name: left_name, - kind: TypeBindingKind::Equality { ty: rhs }, - }); - } - GenericArgs::Parenthesized { .. } => { - existing_predicates.push(WherePredicate::EqPredicate { - lhs: lhs.clone(), - rhs, - }); - continue; // If something other than a Fn ends up - // with parenthesis, leave it alone - } - } - - let bounds = ty_to_bounds.entry(*ty.clone()).or_default(); - - bounds.insert(GenericBound::TraitBound( - PolyTrait { - trait_: Type::ResolvedPath { - path: new_trait_path, - did: *did, - is_generic: *is_generic, - }, - generic_params: Vec::new(), - }, - hir::TraitBoundModifier::None, - )); - - // Remove any existing 'plain' bound (e.g., 'T: Iterator`) so - // that we don't see a - // duplicate bound like `T: Iterator + Iterator` - // on the docs page. - bounds.remove(&GenericBound::TraitBound( - PolyTrait { - trait_: *trait_.clone(), - generic_params: Vec::new(), - }, - hir::TraitBoundModifier::None, - )); - // Avoid creating any new duplicate bounds later in the outer - // loop - ty_to_traits - .entry(*ty.clone()) - .or_default() - .insert(*trait_.clone()); - } - _ => panic!("Unexpected trait {:?} for {:?}", trait_, item_def_id), + if self.is_fn_trait(trait_) && left_name == sym::Output { + ty_to_fn + .entry(*ty.clone()) + .and_modify(|e| *e = (e.0.clone(), Some(rhs.clone()))) + .or_insert((None, Some(rhs))); + continue; } + + let args = &mut new_trait + .segments + .last_mut() + .expect("segments were empty") + .args; + + match args { + // Convert something like ' = u8' + // to 'T: Iterator' + GenericArgs::AngleBracketed { ref mut bindings, .. } => { + bindings.push(TypeBinding { + name: left_name, + kind: TypeBindingKind::Equality { ty: rhs }, + }); + } + GenericArgs::Parenthesized { .. } => { + existing_predicates.push(WherePredicate::EqPredicate { + lhs: lhs.clone(), + rhs, + }); + continue; // If something other than a Fn ends up + // with parenthesis, leave it alone + } + } + + let bounds = ty_to_bounds.entry(*ty.clone()).or_default(); + + bounds.insert(GenericBound::TraitBound( + PolyTrait { trait_: new_trait, generic_params: Vec::new() }, + hir::TraitBoundModifier::None, + )); + + // Remove any existing 'plain' bound (e.g., 'T: Iterator`) so + // that we don't see a + // duplicate bound like `T: Iterator + Iterator` + // on the docs page. + bounds.remove(&GenericBound::TraitBound( + PolyTrait { trait_: trait_.clone(), generic_params: Vec::new() }, + hir::TraitBoundModifier::None, + )); + // Avoid creating any new duplicate bounds later in the outer + // loop + ty_to_traits.entry(*ty.clone()).or_default().insert(trait_.clone()); } _ => panic!("Unexpected LHS {:?} for {:?}", lhs, item_def_id), } @@ -659,7 +619,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { bounds.insert(0, GenericBound::maybe_sized(self.cx)); } } - GenericParamDefKind::Lifetime => {} + GenericParamDefKind::Lifetime { .. } => {} GenericParamDefKind::Const { ref mut default, .. } => { // We never want something like `impl` default.take(); @@ -672,11 +632,11 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { Generics { params: generic_params, where_predicates: existing_predicates } } - // Ensure that the predicates are in a consistent order. The precise - // ordering doesn't actually matter, but it's important that - // a given set of predicates always appears in the same order - - // both for visual consistency between 'rustdoc' runs, and to - // make writing tests much easier + /// Ensure that the predicates are in a consistent order. The precise + /// ordering doesn't actually matter, but it's important that + /// a given set of predicates always appears in the same order - + /// both for visual consistency between 'rustdoc' runs, and to + /// make writing tests much easier #[inline] fn sort_where_predicates(&self, mut predicates: &mut Vec) { // We should never have identical bounds - and if we do, @@ -685,11 +645,11 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { self.unstable_debug_sort(&mut predicates); } - // Ensure that the bounds are in a consistent order. The precise - // ordering doesn't actually matter, but it's important that - // a given set of bounds always appears in the same order - - // both for visual consistency between 'rustdoc' runs, and to - // make writing tests much easier + /// Ensure that the bounds are in a consistent order. The precise + /// ordering doesn't actually matter, but it's important that + /// a given set of bounds always appears in the same order - + /// both for visual consistency between 'rustdoc' runs, and to + /// make writing tests much easier #[inline] fn sort_where_bounds(&self, mut bounds: &mut Vec) { // We should never have identical bounds - and if we do, @@ -698,47 +658,43 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { self.unstable_debug_sort(&mut bounds); } - // This might look horrendously hacky, but it's actually not that bad. - // - // For performance reasons, we use several different FxHashMaps - // in the process of computing the final set of where predicates. - // However, the iteration order of a HashMap is completely unspecified. - // In fact, the iteration of an FxHashMap can even vary between platforms, - // since FxHasher has different behavior for 32-bit and 64-bit platforms. - // - // Obviously, it's extremely undesirable for documentation rendering - // to be dependent on the platform it's run on. Apart from being confusing - // to end users, it makes writing tests much more difficult, as predicates - // can appear in any order in the final result. - // - // To solve this problem, we sort WherePredicates and GenericBounds - // by their Debug string. The thing to keep in mind is that we don't really - // care what the final order is - we're synthesizing an impl or bound - // ourselves, so any order can be considered equally valid. By sorting the - // predicates and bounds, however, we ensure that for a given codebase, all - // auto-trait impls always render in exactly the same way. - // - // Using the Debug implementation for sorting prevents us from needing to - // write quite a bit of almost entirely useless code (e.g., how should two - // Types be sorted relative to each other). It also allows us to solve the - // problem for both WherePredicates and GenericBounds at the same time. This - // approach is probably somewhat slower, but the small number of items - // involved (impls rarely have more than a few bounds) means that it - // shouldn't matter in practice. + /// This might look horrendously hacky, but it's actually not that bad. + /// + /// For performance reasons, we use several different FxHashMaps + /// in the process of computing the final set of where predicates. + /// However, the iteration order of a HashMap is completely unspecified. + /// In fact, the iteration of an FxHashMap can even vary between platforms, + /// since FxHasher has different behavior for 32-bit and 64-bit platforms. + /// + /// Obviously, it's extremely undesirable for documentation rendering + /// to be dependent on the platform it's run on. Apart from being confusing + /// to end users, it makes writing tests much more difficult, as predicates + /// can appear in any order in the final result. + /// + /// To solve this problem, we sort WherePredicates and GenericBounds + /// by their Debug string. The thing to keep in mind is that we don't really + /// care what the final order is - we're synthesizing an impl or bound + /// ourselves, so any order can be considered equally valid. By sorting the + /// predicates and bounds, however, we ensure that for a given codebase, all + /// auto-trait impls always render in exactly the same way. + /// + /// Using the Debug implementation for sorting prevents us from needing to + /// write quite a bit of almost entirely useless code (e.g., how should two + /// Types be sorted relative to each other). It also allows us to solve the + /// problem for both WherePredicates and GenericBounds at the same time. This + /// approach is probably somewhat slower, but the small number of items + /// involved (impls rarely have more than a few bounds) means that it + /// shouldn't matter in practice. fn unstable_debug_sort(&self, vec: &mut Vec) { vec.sort_by_cached_key(|x| format!("{:?}", x)) } - fn is_fn_ty(&self, ty: &Type) -> bool { + fn is_fn_trait(&self, path: &Path) -> bool { let tcx = self.cx.tcx; - match ty { - &Type::ResolvedPath { did, .. } => { - did == tcx.require_lang_item(LangItem::Fn, None) - || did == tcx.require_lang_item(LangItem::FnMut, None) - || did == tcx.require_lang_item(LangItem::FnOnce, None) - } - _ => false, - } + let did = path.def_id(); + did == tcx.require_lang_item(LangItem::Fn, None) + || did == tcx.require_lang_item(LangItem::FnMut, None) + || did == tcx.require_lang_item(LangItem::FnOnce, None) } } @@ -749,7 +705,7 @@ fn region_name(region: Region<'_>) -> Option { } } -// Replaces all ReVars in a type with ty::Region's, using the provided map +/// Replaces all [`ty::RegionVid`]s in a type with [`ty::Region`]s, using the provided map. struct RegionReplacer<'a, 'tcx> { vid_to_region: &'a FxHashMap>, tcx: TyCtxt<'tcx>, diff --git a/src/librustdoc/clean/blanket_impl.rs b/src/librustdoc/clean/blanket_impl.rs index ff3641d6c9..843dda324d 100644 --- a/src/librustdoc/clean/blanket_impl.rs +++ b/src/librustdoc/clean/blanket_impl.rs @@ -17,7 +17,7 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> { let param_env = self.cx.tcx.param_env(item_def_id); let ty = self.cx.tcx.type_of(item_def_id); - debug!("get_blanket_impls({:?})", ty); + trace!("get_blanket_impls({:?})", ty); let mut impls = Vec::new(); for &trait_def_id in self.cx.tcx.all_traits(()).iter() { if !self.cx.cache.access_levels.is_public(trait_def_id) @@ -28,9 +28,10 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> { // NOTE: doesn't use `for_each_relevant_impl` to avoid looking at anything besides blanket impls let trait_impls = self.cx.tcx.trait_impls_of(trait_def_id); for &impl_def_id in trait_impls.blanket_impls() { - debug!( + trace!( "get_blanket_impls: Considering impl for trait '{:?}' {:?}", - trait_def_id, impl_def_id + trait_def_id, + impl_def_id ); let trait_ref = self.cx.tcx.impl_trait_ref(impl_def_id).unwrap(); let is_param = matches!(trait_ref.self_ty().kind(), ty::Param(_)); @@ -50,9 +51,11 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> { // FIXME(eddyb) ignoring `obligations` might cause false positives. drop(obligations); - debug!( + trace!( "invoking predicate_may_hold: param_env={:?}, trait_ref={:?}, ty={:?}", - param_env, trait_ref, ty + param_env, + trait_ref, + ty ); let predicates = self .cx @@ -61,7 +64,11 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> { .instantiate(self.cx.tcx, impl_substs) .predicates .into_iter() - .chain(Some(trait_ref.without_const().to_predicate(infcx.tcx))); + .chain(Some( + ty::Binder::dummy(trait_ref) + .without_const() + .to_predicate(infcx.tcx), + )); for predicate in predicates { debug!("testing predicate {:?}", predicate); let obligation = traits::Obligation::new( @@ -71,7 +78,8 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> { ); match infcx.evaluate_obligation(&obligation) { Ok(eval_result) if eval_result.may_apply() => {} - Err(traits::OverflowError) => {} + Err(traits::OverflowError::Canonical) => {} + Err(traits::OverflowError::ErrorReporting) => {} _ => { return false; } @@ -97,7 +105,7 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> { attrs: Default::default(), visibility: Inherited, def_id: ItemId::Blanket { impl_id: impl_def_id, for_: item_def_id }, - kind: Box::new(ImplItem(Impl { + kind: box ImplItem(Impl { span: Span::new(self.cx.tcx.def_span(impl_def_id)), unsafety: hir::Unsafety::Normal, generics: ( @@ -107,7 +115,7 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> { .clean(self.cx), // FIXME(eddyb) compute both `trait_` and `for_` from // the post-inference `trait_ref`, as it's more accurate. - trait_: Some(trait_ref.clean(self.cx).get_trait_type().unwrap()), + trait_: Some(trait_ref.clean(self.cx)), for_: ty.clean(self.cx), items: self .cx @@ -118,8 +126,8 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> { .clean(self.cx), negative_polarity: false, synthetic: false, - blanket_impl: Some(Box::new(trait_ref.self_ty().clean(self.cx))), - })), + blanket_impl: Some(box trait_ref.self_ty().clean(self.cx)), + }), cfg: None, }); } diff --git a/src/librustdoc/clean/cfg.rs b/src/librustdoc/clean/cfg.rs index 592aefb6a4..9b5ca06848 100644 --- a/src/librustdoc/clean/cfg.rs +++ b/src/librustdoc/clean/cfg.rs @@ -491,6 +491,7 @@ impl<'a> fmt::Display for Display<'a> { "aarch64" => "AArch64", "arm" => "ARM", "asmjs" => "JavaScript", + "m68k" => "M68k", "mips" => "MIPS", "mips64" => "MIPS-64", "msp430" => "MSP430", diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 0c81a55843..e11b802a09 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -124,14 +124,8 @@ crate fn try_inline( let (attrs, cfg) = merge_attrs(cx, Some(parent_module), load_attrs(cx, did), attrs_clone); cx.inlined.insert(did.into()); - let mut item = clean::Item::from_def_id_and_attrs_and_parts( - did, - Some(name), - kind, - Box::new(attrs), - cx, - cfg, - ); + let mut item = + clean::Item::from_def_id_and_attrs_and_parts(did, Some(name), kind, box attrs, cx, cfg); if let Some(import_def_id) = import_def_id { // The visibility needs to reflect the one from the reexport and not from the "source" DefId. item.visibility = cx.tcx.visibility(import_def_id).clean(cx); @@ -324,10 +318,10 @@ fn merge_attrs( } else { Attributes::from_ast(&both, None) }, - both.cfg(cx.sess()), + both.cfg(cx.tcx, &cx.cache.hidden_cfg), ) } else { - (old_attrs.clean(cx), old_attrs.cfg(cx.sess())) + (old_attrs.clean(cx), old_attrs.cfg(cx.tcx, &cx.cache.hidden_cfg)) } } @@ -395,13 +389,45 @@ crate fn build_impl( } } + let document_hidden = cx.render_options.document_hidden; let predicates = tcx.explicit_predicates_of(did); let (trait_items, generics) = match impl_item { Some(impl_) => ( impl_ .items .iter() - .map(|item| tcx.hir().impl_item(item.id).clean(cx)) + .map(|item| tcx.hir().impl_item(item.id)) + .filter(|item| { + // Filter out impl items whose corresponding trait item has `doc(hidden)` + // not to document such impl items. + // For inherent impls, we don't do any filtering, because that's already done in strip_hidden.rs. + + // When `--document-hidden-items` is passed, we don't + // do any filtering, too. + if document_hidden { + return true; + } + if let Some(associated_trait) = associated_trait { + let assoc_kind = match item.kind { + hir::ImplItemKind::Const(..) => ty::AssocKind::Const, + hir::ImplItemKind::Fn(..) => ty::AssocKind::Fn, + hir::ImplItemKind::TyAlias(..) => ty::AssocKind::Type, + }; + let trait_item = tcx + .associated_items(associated_trait.def_id) + .find_by_name_and_kind( + tcx, + item.ident, + assoc_kind, + associated_trait.def_id, + ) + .unwrap(); // SAFETY: For all impl items there exists trait item that has the same name. + !tcx.get_attrs(trait_item.def_id).lists(sym::doc).has_word(sym::hidden) + } else { + true + } + }) + .map(|item| item.clean(cx)) .collect::>(), impl_.generics.clean(cx), ), @@ -420,20 +446,26 @@ crate fn build_impl( ), }; let polarity = tcx.impl_polarity(did); - let trait_ = associated_trait.clean(cx).map(|bound| match bound { - clean::GenericBound::TraitBound(polyt, _) => polyt.trait_, - clean::GenericBound::Outlives(..) => unreachable!(), - }); - if trait_.def_id() == tcx.lang_items().deref_trait() { + let trait_ = associated_trait.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); } // Return if the trait itself or any types of the generic parameters are doc(hidden). - let mut stack: Vec<&Type> = trait_.iter().collect(); - stack.push(&for_); + let mut stack: Vec<&Type> = vec![&for_]; + + if let Some(did) = trait_.as_ref().map(|t| t.def_id()) { + if tcx.get_attrs(did).lists(sym::doc).has_word(sym::hidden) { + return; + } + } + if let Some(generics) = trait_.as_ref().and_then(|t| t.generics()) { + stack.extend(generics); + } + while let Some(ty) = stack.pop() { if let Some(did) = ty.def_id() { - if cx.tcx.get_attrs(did).lists(sym::doc).has_word(sym::hidden) { + if tcx.get_attrs(did).lists(sym::doc).has_word(sym::hidden) { return; } } @@ -442,14 +474,14 @@ crate fn build_impl( } } - if let Some(trait_did) = trait_.def_id() { - record_extern_trait(cx, trait_did); + if let Some(did) = trait_.as_ref().map(|t| t.def_id()) { + record_extern_trait(cx, did); } let (merged_attrs, cfg) = merge_attrs(cx, parent_module.into(), load_attrs(cx, did), attrs); - debug!("merged_attrs={:?}", merged_attrs); + trace!("merged_attrs={:?}", merged_attrs); - debug!("build_impl: impl {:?} for {:?}", trait_.def_id(), for_.def_id()); + trace!("build_impl: impl {:?} for {:?}", trait_.as_ref().map(|t| t.def_id()), for_.def_id()); ret.push(clean::Item::from_def_id_and_attrs_and_parts( did, None, @@ -464,7 +496,7 @@ crate fn build_impl( synthetic: false, blanket_impl: None, }), - Box::new(merged_attrs), + box merged_attrs, cx, cfg, )); @@ -482,25 +514,25 @@ fn build_module( // visit each node at most once. for &item in cx.tcx.item_children(did).iter() { if item.vis == ty::Visibility::Public { - if let Some(def_id) = item.res.mod_def_id() { + let res = item.res.expect_non_local(); + if let Some(def_id) = res.mod_def_id() { if did == def_id || !visited.insert(def_id) { continue; } } - if let Res::PrimTy(p) = item.res { + if let Res::PrimTy(p) = res { // Primitive types can't be inlined so generate an import instead. let prim_ty = clean::PrimitiveType::from(p); items.push(clean::Item { name: None, - attrs: Box::new(clean::Attributes::default()), + attrs: box clean::Attributes::default(), def_id: ItemId::Primitive(prim_ty, did.krate), visibility: clean::Public, - kind: Box::new(clean::ImportItem(clean::Import::new_simple( + kind: box clean::ImportItem(clean::Import::new_simple( item.ident.name, clean::ImportSource { path: clean::Path { - global: false, - res: item.res, + res, segments: vec![clean::PathSegment { name: prim_ty.as_sym(), args: clean::GenericArgs::AngleBracketed { @@ -512,12 +544,10 @@ fn build_module( did: None, }, true, - ))), + )), cfg: None, }); - } else if let Some(i) = - try_inline(cx, did, None, item.res, item.ident.name, None, visited) - { + } else if let Some(i) = try_inline(cx, did, None, res, item.ident.name, None, visited) { items.extend(i) } } @@ -557,7 +587,6 @@ fn build_macro( name: Symbol, import_def_id: Option, ) -> clean::ItemKind { - let imported_from = cx.tcx.crate_name(def_id.krate); 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 { @@ -569,7 +598,6 @@ fn build_macro( def_id, cx.tcx.visibility(import_def_id.unwrap_or(def_id)), ), - imported_from: Some(imported_from), }) } else { unreachable!() @@ -598,11 +626,10 @@ fn filter_non_trait_generics(trait_did: DefId, mut g: clean::Generics) -> clean: ref mut bounds, .. } if *s == kw::SelfUpper => { - bounds.retain(|bound| match *bound { - clean::GenericBound::TraitBound( - clean::PolyTrait { trait_: clean::ResolvedPath { did, .. }, .. }, - _, - ) => did != trait_did, + bounds.retain(|bound| match bound { + clean::GenericBound::TraitBound(clean::PolyTrait { trait_, .. }, _) => { + trait_.def_id() != trait_did + } _ => true, }); } @@ -610,18 +637,12 @@ fn filter_non_trait_generics(trait_did: DefId, mut g: clean::Generics) -> clean: } } - g.where_predicates.retain(|pred| match *pred { + g.where_predicates.retain(|pred| match pred { clean::WherePredicate::BoundPredicate { - ty: - clean::QPath { - self_type: box clean::Generic(ref s), - trait_: box clean::ResolvedPath { did, .. }, - name: ref _name, - .. - }, - ref bounds, + ty: clean::QPath { self_type: box clean::Generic(ref s), trait_, name: _, .. }, + bounds, .. - } => !(bounds.is_empty() || *s == kw::SelfUpper && did == trait_did), + } => !(bounds.is_empty() || *s == kw::SelfUpper && trait_.def_id() == trait_did), _ => true, }); g diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index a9baa1c31a..9d102d6878 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -11,6 +11,7 @@ crate mod utils; use rustc_ast as ast; use rustc_attr as attr; +use rustc_const_eval::const_eval::is_unstable_const_fn; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_hir as hir; use rustc_hir::def::{CtorKind, DefKind, Res}; @@ -22,7 +23,6 @@ use rustc_middle::ty::fold::TypeFolder; use rustc_middle::ty::subst::{InternalSubsts, Subst}; use rustc_middle::ty::{self, AdtKind, DefIdTree, Lift, Ty, TyCtxt}; use rustc_middle::{bug, span_bug}; -use rustc_mir::const_eval::{is_const_fn, is_unstable_const_fn}; use rustc_span::hygiene::{AstPass, MacroKind}; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{self, ExpnKind}; @@ -30,6 +30,7 @@ use rustc_target::spec::abi::Abi; use rustc_typeck::check::intrinsic::intrinsic_operation_unsafety; use rustc_typeck::hir_ty_to_ty; +use std::assert_matches::assert_matches; use std::collections::hash_map::Entry; use std::default::Default; use std::hash::Hash; @@ -128,11 +129,10 @@ impl Clean for hir::GenericBound<'_> { fn clean(&self, cx: &mut DocContext<'_>) -> GenericBound { match *self { hir::GenericBound::Outlives(lt) => GenericBound::Outlives(lt.clean(cx)), - hir::GenericBound::Unsized(_) => GenericBound::maybe_sized(cx), hir::GenericBound::LangItemTrait(lang_item, span, _, generic_args) => { let def_id = cx.tcx.require_lang_item(lang_item, Some(span)); - let trait_ref = ty::TraitRef::identity(cx.tcx, def_id); + let trait_ref = ty::TraitRef::identity(cx.tcx, def_id).skip_binder(); let generic_args = generic_args.clean(cx); let bindings = match generic_args { @@ -152,8 +152,8 @@ impl Clean for hir::GenericBound<'_> { } } -impl Clean for (ty::TraitRef<'_>, &[TypeBinding]) { - fn clean(&self, cx: &mut DocContext<'_>) -> Type { +impl Clean for (ty::TraitRef<'_>, &[TypeBinding]) { + fn clean(&self, cx: &mut DocContext<'_>) -> Path { let (trait_ref, bounds) = *self; let kind = cx.tcx.def_kind(trait_ref.def_id).into(); if !matches!(kind, ItemType::Trait | ItemType::TraitAlias) { @@ -164,27 +164,17 @@ impl Clean for (ty::TraitRef<'_>, &[TypeBinding]) { ); } inline::record_extern_fqn(cx, trait_ref.def_id, kind); - let path = external_path( - cx, - cx.tcx.item_name(trait_ref.def_id), - Some(trait_ref.def_id), - true, - bounds.to_vec(), - trait_ref.substs, - ); + let path = external_path(cx, trait_ref.def_id, true, bounds.to_vec(), trait_ref.substs); debug!("ty::TraitRef\n subst: {:?}\n", trait_ref.substs); - ResolvedPath { path, did: trait_ref.def_id, is_generic: false } + path } } -impl<'tcx> Clean for ty::TraitRef<'tcx> { - fn clean(&self, cx: &mut DocContext<'_>) -> GenericBound { - GenericBound::TraitBound( - PolyTrait { trait_: (*self, &[][..]).clean(cx), generic_params: vec![] }, - hir::TraitBoundModifier::None, - ) +impl Clean for ty::TraitRef<'tcx> { + fn clean(&self, cx: &mut DocContext<'_>) -> Path { + (*self, &[][..]).clean(cx) } } @@ -199,9 +189,10 @@ impl Clean for (ty::PolyTraitRef<'_>, &[TypeBinding]) { .collect_referenced_late_bound_regions(&poly_trait_ref) .into_iter() .filter_map(|br| match br { - ty::BrNamed(_, name) => { - Some(GenericParamDef { name, kind: GenericParamDefKind::Lifetime }) - } + ty::BrNamed(_, name) => Some(GenericParamDef { + name, + kind: GenericParamDefKind::Lifetime { outlives: vec![] }, + }), _ => None, }) .collect(); @@ -241,30 +232,6 @@ impl Clean for hir::Lifetime { } } -impl Clean for hir::GenericParam<'_> { - fn clean(&self, _: &mut DocContext<'_>) -> Lifetime { - match self.kind { - hir::GenericParamKind::Lifetime { .. } => { - if !self.bounds.is_empty() { - let mut bounds = self.bounds.iter().map(|bound| match bound { - hir::GenericBound::Outlives(lt) => lt, - _ => panic!(), - }); - let name = bounds.next().expect("no more bounds").name.ident(); - let mut s = format!("{}: {}", self.name.ident(), name); - for bound in bounds { - s.push_str(&format!(" + {}", bound.name.ident())); - } - Lifetime(Symbol::intern(&s)) - } else { - Lifetime(self.name.ident().name) - } - } - _ => panic!(), - } - } -} - impl Clean for hir::ConstArg { fn clean(&self, cx: &mut DocContext<'_>) -> Constant { Constant { @@ -302,11 +269,30 @@ impl Clean> for ty::RegionKind { impl Clean for hir::WherePredicate<'_> { fn clean(&self, cx: &mut DocContext<'_>) -> WherePredicate { match *self { - hir::WherePredicate::BoundPredicate(ref wbp) => WherePredicate::BoundPredicate { - ty: wbp.bounded_ty.clean(cx), - bounds: wbp.bounds.clean(cx), - bound_params: wbp.bound_generic_params.into_iter().map(|x| x.clean(cx)).collect(), - }, + hir::WherePredicate::BoundPredicate(ref wbp) => { + let bound_params = wbp + .bound_generic_params + .into_iter() + .map(|param| { + // Higher-ranked params must be lifetimes. + // Higher-ranked lifetimes can't have bounds. + assert_matches!( + param, + hir::GenericParam { + kind: hir::GenericParamKind::Lifetime { .. }, + bounds: [], + .. + } + ); + Lifetime(param.name.ident().name) + }) + .collect(); + WherePredicate::BoundPredicate { + ty: wbp.bounded_ty.clean(cx), + bounds: wbp.bounds.clean(cx), + bound_params, + } + } hir::WherePredicate::RegionPredicate(ref wrp) => WherePredicate::RegionPredicate { lifetime: wrp.lifetime.clean(cx), @@ -395,16 +381,13 @@ impl<'tcx> Clean for ty::ProjectionPredicate<'tcx> { impl<'tcx> Clean for ty::ProjectionTy<'tcx> { fn clean(&self, cx: &mut DocContext<'_>) -> Type { let lifted = self.lift_to_tcx(cx.tcx).unwrap(); - let trait_ = match lifted.trait_ref(cx.tcx).clean(cx) { - GenericBound::TraitBound(t, _) => t.trait_, - GenericBound::Outlives(_) => panic!("cleaning a trait got a lifetime"), - }; + let trait_ = lifted.trait_ref(cx.tcx).clean(cx); 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_type: Box::new(self_type), - trait_: Box::new(trait_), + self_type: box self_type, + trait_, } } } @@ -412,7 +395,9 @@ impl<'tcx> Clean for ty::ProjectionTy<'tcx> { impl Clean for ty::GenericParamDef { fn clean(&self, cx: &mut DocContext<'_>) -> GenericParamDef { let (name, kind) = match self.kind { - ty::GenericParamDefKind::Lifetime => (self.name, GenericParamDefKind::Lifetime), + ty::GenericParamDefKind::Lifetime => { + (self.name, GenericParamDefKind::Lifetime { outlives: vec![] }) + } ty::GenericParamDefKind::Type { has_default, synthetic, .. } => { let default = if has_default { let mut default = cx.tcx.type_of(self.def_id).clean(cx); @@ -462,21 +447,15 @@ impl Clean for hir::GenericParam<'_> { fn clean(&self, cx: &mut DocContext<'_>) -> GenericParamDef { let (name, kind) = match self.kind { hir::GenericParamKind::Lifetime { .. } => { - let name = if !self.bounds.is_empty() { - let mut bounds = self.bounds.iter().map(|bound| match bound { - hir::GenericBound::Outlives(lt) => lt, + let outlives = self + .bounds + .iter() + .map(|bound| match bound { + hir::GenericBound::Outlives(lt) => lt.clean(cx), _ => panic!(), - }); - let name = bounds.next().expect("no more bounds").name.ident(); - let mut s = format!("{}: {}", self.name.ident(), name); - for bound in bounds { - s.push_str(&format!(" + {}", bound.name.ident())); - } - Symbol::intern(&s) - } else { - self.name.ident().name - }; - (name, GenericParamDefKind::Lifetime) + }) + .collect(); + (self.name.ident().name, GenericParamDefKind::Lifetime { outlives }) } hir::GenericParamKind::Type { ref default, synthetic } => ( self.name.ident().name, @@ -536,7 +515,7 @@ impl Clean for hir::Generics<'_> { .map(|param| { let param: GenericParamDef = param.clean(cx); match param.kind { - GenericParamDefKind::Lifetime => unreachable!(), + GenericParamDefKind::Lifetime { .. } => unreachable!(), GenericParamDefKind::Type { did, ref bounds, .. } => { cx.impl_trait_bounds.insert(did.into(), bounds.clone()); } @@ -564,19 +543,13 @@ impl Clean for hir::Generics<'_> { WherePredicate::BoundPredicate { ty: Generic(ref name), ref mut bounds, .. } => { - if let [] | [GenericBound::TraitBound(_, hir::TraitBoundModifier::Maybe)] = - &bounds[..] - { + if bounds.is_empty() { for param in &mut generics.params { match param.kind { - GenericParamDefKind::Lifetime => {} + GenericParamDefKind::Lifetime { .. } => {} GenericParamDefKind::Type { bounds: ref mut ty_bounds, .. } => { if ¶m.name == name { mem::swap(bounds, ty_bounds); - // We now keep track of `?Sized` obligations in the HIR. - // If we don't clear `ty_bounds` we end up with - // `fn foo(_: X) where X: ?Sized`. - ty_bounds.clear(); break; } } @@ -808,7 +781,7 @@ fn clean_fn_or_proc_macro( let mut func = (sig, generics, body_id).clean(cx); let def_id = item.def_id.to_def_id(); func.header.constness = - if is_const_fn(cx.tcx, def_id) && is_unstable_const_fn(cx.tcx, def_id).is_none() { + if cx.tcx.is_const_fn(def_id) && is_unstable_const_fn(cx.tcx, def_id).is_none() { hir::Constness::Const } else { hir::Constness::NotConst @@ -917,10 +890,11 @@ impl Clean for hir::IsAuto { } } -impl Clean for hir::TraitRef<'_> { - fn clean(&self, cx: &mut DocContext<'_>) -> Type { +impl Clean for hir::TraitRef<'_> { + fn clean(&self, cx: &mut DocContext<'_>) -> Path { let path = self.path.clean(cx); - resolve_type(cx, path, self.hir_ref_id) + register_res(cx, path.res); + path } } @@ -1126,9 +1100,8 @@ impl Clean for ty::AssocItem { if *name != my_name { return None; } - match **trait_ { - ResolvedPath { did, .. } if did == self.container.id() => {} - _ => return None, + if trait_.def_id() != self.container.id() { + return None; } match **self_type { Generic(ref s) if *s == kw::SelfUpper => {} @@ -1178,7 +1151,7 @@ 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 hir::Ty { hir_id: _, span, ref kind } = *hir_ty; let qpath = match kind { hir::TyKind::Path(qpath) => qpath, _ => unreachable!(), @@ -1285,7 +1258,7 @@ fn clean_qpath(hir_ty: &hir::Ty<'_>, cx: &mut DocContext<'_>) -> Type { return cx.enter_alias(ty_substs, lt_substs, ct_substs, |cx| ty.clean(cx)); } let path = path.clean(cx); - resolve_type(cx, path, hir_id) + resolve_type(cx, path) } hir::QPath::Resolved(Some(ref qself), ref p) => { // Try to normalize `::T` to a type @@ -1294,19 +1267,18 @@ fn clean_qpath(hir_ty: &hir::Ty<'_>, cx: &mut DocContext<'_>) -> Type { return normalized_value.clean(cx); } - let segments = if p.is_global() { &p.segments[1..] } else { &p.segments }; - let trait_segments = &segments[..segments.len() - 1]; + let trait_segments = &p.segments[..p.segments.len() - 1]; let trait_def = cx.tcx.associated_item(p.res.def_id()).container.id(); - let trait_path = self::Path { - global: p.is_global(), + let trait_ = self::Path { res: Res::Def(DefKind::Trait, trait_def), segments: trait_segments.clean(cx), }; + register_res(cx, trait_.res); Type::QPath { name: p.segments.last().expect("segments were empty").ident.name, self_def_id: Some(DefId::local(qself.hir_id.owner.local_def_index)), - self_type: Box::new(qself.clean(cx)), - trait_: Box::new(resolve_type(cx, trait_path, hir_id)), + self_type: box qself.clean(cx), + trait_, } } hir::QPath::TypeRelative(ref qself, ref segment) => { @@ -1317,12 +1289,13 @@ fn clean_qpath(hir_ty: &hir::Ty<'_>, cx: &mut DocContext<'_>) -> Type { ty::Error(_) => return Type::Infer, _ => bug!("clean: expected associated type, found `{:?}`", ty), }; - let trait_path = hir::Path { span, res, segments: &[] }.clean(cx); + let trait_ = hir::Path { span, res, segments: &[] }.clean(cx); + register_res(cx, trait_.res); Type::QPath { name: segment.ident.name, self_def_id: res.opt_def_id(), - self_type: Box::new(qself.clean(cx)), - trait_: Box::new(resolve_type(cx, trait_path, hir_id)), + self_type: box qself.clean(cx), + trait_, } } hir::QPath::LangItem(..) => bug!("clean: requiring documentation of lang item"), @@ -1334,8 +1307,8 @@ impl Clean for hir::Ty<'_> { use rustc_hir::*; match self.kind { - TyKind::Never => Never, - TyKind::Ptr(ref m) => RawPointer(m.mutbl, Box::new(m.ty.clean(cx))), + TyKind::Never => Primitive(PrimitiveType::Never), + TyKind::Ptr(ref m) => RawPointer(m.mutbl, box m.ty.clean(cx)), TyKind::Rptr(ref l, ref m) => { // There are two times a `Fresh` lifetime can be created: // 1. For `&'_ x`, written by the user. This corresponds to `lower_lifetime` in `rustc_ast_lowering`. @@ -1347,9 +1320,9 @@ impl Clean for hir::Ty<'_> { let elided = l.is_elided() || matches!(l.name, LifetimeName::Param(ParamName::Fresh(_))); let lifetime = if elided { None } else { Some(l.clean(cx)) }; - BorrowedRef { lifetime, mutability: m.mutbl, type_: Box::new(m.ty.clean(cx)) } + BorrowedRef { lifetime, mutability: m.mutbl, type_: box m.ty.clean(cx) } } - TyKind::Slice(ref ty) => Slice(Box::new(ty.clean(cx))), + TyKind::Slice(ref ty) => Slice(box ty.clean(cx)), TyKind::Array(ref ty, ref length) => { let def_id = cx.tcx.hir().local_def_id(length.hir_id); // NOTE(min_const_generics): We can't use `const_eval_poly` for constants @@ -1362,7 +1335,7 @@ impl Clean for hir::Ty<'_> { let ct = ty::Const::from_anon_const(cx.tcx, def_id); let param_env = cx.tcx.param_env(def_id); let length = print_const(cx, ct.eval(cx.tcx, param_env)); - Array(Box::new(ty.clean(cx)), length) + Array(box ty.clean(cx), length) } TyKind::Tup(ref tys) => Tuple(tys.clean(cx)), TyKind::OpaqueDef(item_id, _) => { @@ -1379,7 +1352,7 @@ impl Clean for hir::Ty<'_> { let lifetime = if !lifetime.is_elided() { Some(lifetime.clean(cx)) } else { None }; DynTrait(bounds, lifetime) } - TyKind::BareFn(ref barefn) => BareFunction(Box::new(barefn.clean(cx))), + TyKind::BareFn(ref barefn) => BareFunction(box barefn.clean(cx)), // Rustdoc handles `TyKind::Err`s by turning them into `Type::Infer`s. TyKind::Infer | TyKind::Err => Infer, TyKind::Typeof(..) => panic!("unimplemented type {:?}", self.kind), @@ -1420,39 +1393,37 @@ fn normalize(cx: &mut DocContext<'tcx>, ty: Ty<'_>) -> Option> { impl<'tcx> Clean for Ty<'tcx> { fn clean(&self, cx: &mut DocContext<'_>) -> Type { - debug!("cleaning type: {:?}", self); + trace!("cleaning type: {:?}", self); let ty = normalize(cx, self).unwrap_or(self); match *ty.kind() { - ty::Never => Never, + ty::Never => Primitive(PrimitiveType::Never), ty::Bool => Primitive(PrimitiveType::Bool), ty::Char => Primitive(PrimitiveType::Char), ty::Int(int_ty) => Primitive(int_ty.into()), ty::Uint(uint_ty) => Primitive(uint_ty.into()), ty::Float(float_ty) => Primitive(float_ty.into()), ty::Str => Primitive(PrimitiveType::Str), - ty::Slice(ty) => Slice(Box::new(ty.clean(cx))), + ty::Slice(ty) => Slice(box ty.clean(cx)), ty::Array(ty, n) => { let mut n = cx.tcx.lift(n).expect("array lift failed"); n = n.eval(cx.tcx, ty::ParamEnv::reveal_all()); let n = print_const(cx, n); - Array(Box::new(ty.clean(cx)), n) + Array(box ty.clean(cx), n) + } + ty::RawPtr(mt) => RawPointer(mt.mutbl, box mt.ty.clean(cx)), + ty::Ref(r, ty, mutbl) => { + BorrowedRef { lifetime: r.clean(cx), mutability: mutbl, type_: box ty.clean(cx) } } - ty::RawPtr(mt) => RawPointer(mt.mutbl, Box::new(mt.ty.clean(cx))), - ty::Ref(r, ty, mutbl) => BorrowedRef { - lifetime: r.clean(cx), - mutability: mutbl, - type_: Box::new(ty.clean(cx)), - }, ty::FnDef(..) | ty::FnPtr(_) => { let ty = cx.tcx.lift(*self).expect("FnPtr lift failed"); let sig = ty.fn_sig(cx.tcx); let def_id = DefId::local(CRATE_DEF_INDEX); - BareFunction(Box::new(BareFunctionDecl { + BareFunction(box BareFunctionDecl { unsafety: sig.unsafety(), generic_params: Vec::new(), decl: (def_id, sig).clean(cx), abi: sig.abi(), - })) + }) } ty::Adt(def, substs) => { let did = def.did; @@ -1462,20 +1433,13 @@ impl<'tcx> Clean for Ty<'tcx> { AdtKind::Enum => ItemType::Enum, }; inline::record_extern_fqn(cx, did, kind); - let path = external_path(cx, cx.tcx.item_name(did), None, false, vec![], substs); - ResolvedPath { path, did, is_generic: false } + let path = external_path(cx, did, false, vec![], substs); + ResolvedPath { path, did } } ty::Foreign(did) => { inline::record_extern_fqn(cx, did, ItemType::ForeignType); - let path = external_path( - cx, - cx.tcx.item_name(did), - None, - false, - vec![], - InternalSubsts::empty(), - ); - ResolvedPath { path, did, is_generic: false } + let path = external_path(cx, did, false, vec![], InternalSubsts::empty()); + ResolvedPath { path, did } } ty::Dynamic(ref obj, ref reg) => { // HACK: pick the first `did` as the `did` of the trait object. Someone @@ -1498,13 +1462,9 @@ impl<'tcx> Clean for Ty<'tcx> { for did in dids { let empty = cx.tcx.intern_substs(&[]); - let path = - external_path(cx, cx.tcx.item_name(did), Some(did), false, vec![], empty); + let path = external_path(cx, did, false, vec![], empty); inline::record_extern_fqn(cx, did, ItemType::Trait); - let bound = PolyTrait { - trait_: ResolvedPath { path, did, is_generic: false }, - generic_params: Vec::new(), - }; + let bound = PolyTrait { trait_: path, generic_params: Vec::new() }; bounds.push(bound); } @@ -1516,15 +1476,8 @@ impl<'tcx> Clean for Ty<'tcx> { }); } - let path = - external_path(cx, cx.tcx.item_name(did), Some(did), false, bindings, substs); - bounds.insert( - 0, - PolyTrait { - trait_: ResolvedPath { path, did, is_generic: false }, - generic_params: Vec::new(), - }, - ); + let path = external_path(cx, did, false, bindings, substs); + bounds.insert(0, PolyTrait { trait_: path, generic_params: Vec::new() }); DynTrait(bounds, lifetime) } @@ -1763,11 +1716,7 @@ impl Clean for hir::VariantData<'_> { impl Clean for hir::Path<'_> { fn clean(&self, cx: &mut DocContext<'_>) -> Path { - Path { - global: self.is_global(), - res: self.res, - segments: if self.is_global() { &self.segments[1..] } else { &self.segments }.clean(cx), - } + Path { res: self.res, segments: self.segments.clean(cx) } } } @@ -1789,7 +1738,7 @@ impl Clean for hir::GenericArgs<'_> { } hir::GenericArg::Lifetime(_) => GenericArg::Lifetime(Lifetime::elided()), hir::GenericArg::Type(ty) => GenericArg::Type(ty.clean(cx)), - hir::GenericArg::Const(ct) => GenericArg::Const(ct.clean(cx)), + hir::GenericArg::Const(ct) => GenericArg::Const(Box::new(ct.clean(cx))), hir::GenericArg::Infer(_inf) => GenericArg::Infer, }) .collect(), @@ -1873,7 +1822,6 @@ impl Clean> for (&hir::Item<'_>, Option) { } ItemKind::Macro(ref macro_def) => MacroItem(Macro { source: display_macro_source(cx, name, ¯o_def, def_id, &item.vis), - imported_from: None, }), ItemKind::Trait(is_auto, unsafety, ref generics, ref bounds, ref item_ids) => { let items = item_ids @@ -1934,7 +1882,7 @@ fn clean_impl(impl_: &hir::Impl<'_>, hir_id: hir::HirId, cx: &mut DocContext<'_> // If this impl block is an implementation of the Deref trait, then we // need to try inlining the target's inherent impl blocks as well. - if trait_.def_id() == tcx.lang_items().deref_trait() { + if trait_.as_ref().map(|t| t.def_id()) == tcx.lang_items().deref_trait() { build_deref_target_impls(cx, &items, &mut ret); } @@ -1943,7 +1891,7 @@ fn clean_impl(impl_: &hir::Impl<'_>, hir_id: hir::HirId, cx: &mut DocContext<'_> DefKind::TyAlias => Some(tcx.type_of(did).clean(cx)), _ => None, }); - let mut make_item = |trait_: Option, for_: Type, items: Vec| { + 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, @@ -2005,11 +1953,11 @@ fn clean_extern_crate( // FIXME: using `from_def_id_and_kind` breaks `rustdoc/masked` for some reason vec![Item { name: Some(name), - attrs: Box::new(attrs.clean(cx)), + attrs: box attrs.clean(cx), def_id: crate_def_id.into(), visibility: krate.vis.clean(cx), - kind: Box::new(ExternCrateItem { src: orig_name }), - cfg: attrs.cfg(cx.sess()), + kind: box ExternCrateItem { src: orig_name }, + cfg: attrs.cfg(cx.tcx, &cx.cache.hidden_cfg), }] } diff --git a/src/librustdoc/clean/simplify.rs b/src/librustdoc/clean/simplify.rs index d139b19f5d..4c81e75e8d 100644 --- a/src/librustdoc/clean/simplify.rs +++ b/src/librustdoc/clean/simplify.rs @@ -11,8 +11,7 @@ //! This module attempts to reconstruct the original where and/or parameter //! bounds by special casing scenarios such as these. Fun! -use std::collections::BTreeMap; - +use rustc_data_structures::fx::FxIndexMap; use rustc_hir::def_id::DefId; use rustc_middle::ty; use rustc_span::Symbol; @@ -23,8 +22,11 @@ use crate::clean::WherePredicate as WP; use crate::core::DocContext; crate fn where_clauses(cx: &DocContext<'_>, clauses: Vec) -> Vec { - // First, partition the where clause into its separate components - let mut params: BTreeMap<_, (Vec<_>, Vec<_>)> = BTreeMap::new(); + // First, partition the where clause into its separate components. + // + // We use `FxIndexMap` so that the insertion order is preserved to prevent messing up to + // the order of the generated bounds. + let mut params: FxIndexMap, Vec<_>)> = FxIndexMap::default(); let mut lifetimes = Vec::new(); let mut equalities = Vec::new(); let mut tybounds = Vec::new(); @@ -97,17 +99,13 @@ crate fn merge_bounds( clean::GenericBound::TraitBound(ref mut tr, _) => tr, clean::GenericBound::Outlives(..) => return false, }; - let (did, path) = match trait_ref.trait_ { - clean::ResolvedPath { did, ref mut path, .. } => (did, path), - _ => return false, - }; // If this QPath's trait `trait_did` is the same as, or a supertrait // of, the bound's trait `did` then we can keep going, otherwise // this is just a plain old equality bound. - if !trait_is_same_or_supertrait(cx, did, trait_did) { + if !trait_is_same_or_supertrait(cx, trait_ref.trait_.def_id(), trait_did) { return false; } - let last = path.segments.last_mut().expect("segments were empty"); + let last = trait_ref.trait_.segments.last_mut().expect("segments were empty"); match last.args { PP::AngleBracketed { ref mut bindings, .. } => { bindings.push(clean::TypeBinding { diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 36b862120a..153435367a 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -120,8 +120,7 @@ crate struct Crate { crate module: Item, crate externs: Vec, crate primitives: ThinVec<(DefId, PrimitiveType)>, - // These are later on moved into `CACHEKEY`, leaving the map empty. - // Only here so that they can be filtered through the rustdoc passes. + /// Only here so that they can be filtered through the rustdoc passes. crate external_traits: Rc>>, crate collapsed: bool, } @@ -212,7 +211,7 @@ impl ExternalCrate { crate fn keywords(&self, tcx: TyCtxt<'_>) -> ThinVec<(DefId, Symbol)> { let root = self.def_id(); - let as_keyword = |res: Res| { + let as_keyword = |res: Res| { if let Res::Def(DefKind::Mod, def_id) = res { let attrs = tcx.get_attrs(def_id); let mut keyword = None; @@ -230,8 +229,7 @@ impl ExternalCrate { }; if root.is_local() { tcx.hir() - .krate() - .module() + .root_module() .item_ids .iter() .filter_map(|&id| { @@ -243,7 +241,8 @@ impl ExternalCrate { hir::ItemKind::Use(ref path, hir::UseKind::Single) if item.vis.node.is_pub() => { - as_keyword(path.res).map(|(_, prim)| (id.def_id.to_def_id(), prim)) + as_keyword(path.res.expect_non_local()) + .map(|(_, prim)| (id.def_id.to_def_id(), prim)) } _ => None, } @@ -274,7 +273,7 @@ impl ExternalCrate { // Also note that this does not attempt to deal with modules tagged // duplicately for the same primitive. This is handled later on when // rendering by delegating everything to a hash map. - let as_primitive = |res: Res| { + let as_primitive = |res: Res| { if let Res::Def(DefKind::Mod, def_id) = res { let attrs = tcx.get_attrs(def_id); let mut prim = None; @@ -296,8 +295,7 @@ impl ExternalCrate { if root.is_local() { tcx.hir() - .krate() - .module() + .root_module() .item_ids .iter() .filter_map(|&id| { @@ -309,7 +307,7 @@ impl ExternalCrate { hir::ItemKind::Use(ref path, hir::UseKind::Single) if item.vis.node.is_pub() => { - as_primitive(path.res).map(|(_, prim)| { + as_primitive(path.res.expect_non_local()).map(|(_, prim)| { // Pretend the primitive is local. (id.def_id.to_def_id(), prim) }) @@ -420,9 +418,9 @@ impl Item { def_id, name, kind, - Box::new(ast_attrs.clean(cx)), + box ast_attrs.clean(cx), cx, - ast_attrs.cfg(cx.sess()), + ast_attrs.cfg(cx.tcx, &cx.cache.hidden_cfg), ) } @@ -438,7 +436,7 @@ impl Item { Item { def_id: def_id.into(), - kind: Box::new(kind), + kind: box kind, name, attrs, visibility: cx.tcx.visibility(def_id).clean(cx), @@ -461,60 +459,20 @@ impl Item { .map_or(&[][..], |v| v.as_slice()) .iter() .filter_map(|ItemLink { link: s, link_text, did, ref fragment }| { - match did { - Some(did) => { - if let Ok((mut href, ..)) = href(did.clone(), cx) { - if let Some(ref fragment) = *fragment { - href.push('#'); - href.push_str(fragment); - } - Some(RenderedLink { - original_text: s.clone(), - new_text: link_text.clone(), - href, - }) - } else { - None - } - } - // FIXME(83083): using fragments as a side-channel for - // primitive names is very unfortunate - None => { - let relative_to = &cx.current; - if let Some(ref fragment) = *fragment { - let url = match cx.cache().extern_locations.get(&self.def_id.krate()) { - Some(&ExternalLocation::Local) => { - if relative_to[0] == "std" { - let depth = relative_to.len() - 1; - "../".repeat(depth) - } else { - let depth = relative_to.len(); - format!("{}std/", "../".repeat(depth)) - } - } - Some(ExternalLocation::Remote(ref s)) => { - format!("{}/std/", s.trim_end_matches('/')) - } - Some(ExternalLocation::Unknown) | None => { - format!("{}/std/", crate::DOC_RUST_LANG_ORG_CHANNEL) - } - }; - // This is a primitive so the url is done "by hand". - let tail = fragment.find('#').unwrap_or_else(|| fragment.len()); - Some(RenderedLink { - original_text: s.clone(), - new_text: link_text.clone(), - href: format!( - "{}primitive.{}.html{}", - url, - &fragment[..tail], - &fragment[tail..] - ), - }) - } else { - panic!("This isn't a primitive?!"); - } + debug!(?did); + if let Ok((mut href, ..)) = href(*did, cx) { + debug!(?href); + if let Some(ref fragment) = *fragment { + href.push('#'); + href.push_str(fragment); } + Some(RenderedLink { + original_text: s.clone(), + new_text: link_text.clone(), + href, + }) + } else { + None } }) .collect() @@ -531,18 +489,10 @@ impl Item { .get(&self.def_id) .map_or(&[][..], |v| v.as_slice()) .iter() - .filter_map(|ItemLink { link: s, link_text, did, fragment }| { - // FIXME(83083): using fragments as a side-channel for - // primitive names is very unfortunate - if did.is_some() || fragment.is_some() { - Some(RenderedLink { - original_text: s.clone(), - new_text: link_text.clone(), - href: String::new(), - }) - } else { - None - } + .map(|ItemLink { link: s, link_text, .. }| RenderedLink { + original_text: s.clone(), + new_text: link_text.clone(), + href: String::new(), }) .collect() } @@ -796,7 +746,7 @@ crate trait AttributesExt { fn other_attrs(&self) -> Vec; - fn cfg(&self, sess: &Session) -> Option>; + fn cfg(&self, tcx: TyCtxt<'_>, hidden_cfg: &FxHashSet) -> Option>; } impl AttributesExt for [ast::Attribute] { @@ -821,8 +771,44 @@ impl AttributesExt for [ast::Attribute] { self.iter().filter(|attr| attr.doc_str().is_none()).cloned().collect() } - fn cfg(&self, sess: &Session) -> Option> { - let mut cfg = Cfg::True; + fn cfg(&self, tcx: TyCtxt<'_>, hidden_cfg: &FxHashSet) -> Option> { + let sess = tcx.sess; + let doc_cfg_active = tcx.features().doc_cfg; + let doc_auto_cfg_active = tcx.features().doc_auto_cfg; + + fn single(it: T) -> Option { + let mut iter = it.into_iter(); + let item = iter.next()?; + if iter.next().is_some() { + return None; + } + Some(item) + } + + let mut cfg = if doc_cfg_active || doc_auto_cfg_active { + let mut doc_cfg = self + .iter() + .filter(|attr| attr.has_name(sym::doc)) + .flat_map(|attr| attr.meta_item_list().unwrap_or_else(Vec::new)) + .filter(|attr| attr.has_name(sym::cfg)) + .peekable(); + if doc_cfg.peek().is_some() && doc_cfg_active { + doc_cfg + .filter_map(|attr| Cfg::parse(attr.meta_item()?).ok()) + .fold(Cfg::True, |cfg, new_cfg| cfg & new_cfg) + } else if doc_auto_cfg_active { + self.iter() + .filter(|attr| attr.has_name(sym::cfg)) + .filter_map(|attr| single(attr.meta_item_list()?)) + .filter_map(|attr| Cfg::parse(attr.meta_item()?).ok()) + .filter(|cfg| !hidden_cfg.contains(cfg)) + .fold(Cfg::True, |cfg, new_cfg| cfg & new_cfg) + } else { + Cfg::True + } + } else { + Cfg::True + }; for attr in self.iter() { // #[doc] @@ -849,6 +835,8 @@ impl AttributesExt for [ast::Attribute] { } } + // treat #[target_feature(enable = "feat")] attributes as if they were + // #[doc(cfg(target_feature = "feat"))] attributes as well for attr in self.lists(sym::target_feature) { if attr.has_name(sym::enable) { if let Some(feat) = attr.value_str() { @@ -955,18 +943,10 @@ impl<'a> FromIterator<&'a DocFragment> for String { } } -/// The attributes on an [`Item`], including attributes like `#[derive(...)]` and `#[inline]`, -/// as well as doc comments. -#[derive(Clone, Debug, Default)] -crate struct Attributes { - crate doc_strings: Vec, - crate other_attrs: Vec, -} - -#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)] /// A link that has not yet been rendered. /// /// This link will be turned into a rendered link by [`Item::links`]. +#[derive(Clone, Debug, PartialEq, Eq, Hash)] crate struct ItemLink { /// The original link written in the markdown pub(crate) link: String, @@ -975,7 +955,7 @@ crate struct ItemLink { /// This may not be the same as `link` if there was a disambiguator /// in an intra-doc link (e.g. \[`fn@f`\]) pub(crate) link_text: String, - pub(crate) did: Option, + pub(crate) did: DefId, /// The url fragment to append to the link pub(crate) fragment: Option, } @@ -991,6 +971,14 @@ pub struct RenderedLink { pub(crate) href: String, } +/// The attributes on an [`Item`], including attributes like `#[derive(...)]` and `#[inline]`, +/// as well as doc comments. +#[derive(Clone, Debug, Default)] +crate struct Attributes { + crate doc_strings: Vec, + crate other_attrs: Vec, +} + impl Attributes { crate fn lists(&self, name: Symbol) -> ListAttributesIter<'_> { self.other_attrs.lists(name) @@ -1158,13 +1146,10 @@ impl GenericBound { crate fn maybe_sized(cx: &mut DocContext<'_>) -> GenericBound { let did = cx.tcx.require_lang_item(LangItem::Sized, None); let empty = cx.tcx.intern_substs(&[]); - let path = external_path(cx, cx.tcx.item_name(did), Some(did), false, vec![], empty); + let path = external_path(cx, did, false, vec![], empty); inline::record_extern_fqn(cx, did, ItemType::Trait); GenericBound::TraitBound( - PolyTrait { - trait_: ResolvedPath { path, did, is_generic: false }, - generic_params: Vec::new(), - }, + PolyTrait { trait_: path, generic_params: Vec::new() }, hir::TraitBoundModifier::Maybe, ) } @@ -1172,7 +1157,7 @@ impl GenericBound { crate fn is_sized_bound(&self, cx: &DocContext<'_>) -> bool { use rustc_hir::TraitBoundModifier as TBM; if let GenericBound::TraitBound(PolyTrait { ref trait_, .. }, TBM::None) = *self { - if trait_.def_id() == cx.tcx.lang_items().sized_trait() { + if Some(trait_.def_id()) == cx.tcx.lang_items().sized_trait() { return true; } } @@ -1186,7 +1171,7 @@ impl GenericBound { None } - crate fn get_trait_type(&self) -> Option { + crate fn get_trait_path(&self) -> Option { if let GenericBound::TraitBound(PolyTrait { ref trait_, .. }, _) = *self { Some(trait_.clone()) } else { @@ -1231,7 +1216,9 @@ impl WherePredicate { #[derive(Clone, PartialEq, Eq, Debug, Hash)] crate enum GenericParamDefKind { - Lifetime, + Lifetime { + outlives: Vec, + }, Type { did: DefId, bounds: Vec, @@ -1257,7 +1244,7 @@ impl GenericParamDefKind { match self { GenericParamDefKind::Type { default, .. } => default.clone(), GenericParamDefKind::Const { ty, .. } => Some(ty.clone()), - GenericParamDefKind::Lifetime => None, + GenericParamDefKind::Lifetime { .. } => None, } } } @@ -1271,7 +1258,7 @@ crate struct GenericParamDef { impl GenericParamDef { crate fn is_synthetic_type_param(&self) -> bool { match self.kind { - GenericParamDefKind::Lifetime | GenericParamDefKind::Const { .. } => false, + GenericParamDefKind::Lifetime { .. } | GenericParamDefKind::Const { .. } => false, GenericParamDefKind::Type { ref synthetic, .. } => synthetic.is_some(), } } @@ -1416,90 +1403,56 @@ crate struct TraitAlias { /// A trait reference, which may have higher ranked lifetimes. #[derive(Clone, PartialEq, Eq, Debug, Hash)] crate struct PolyTrait { - crate trait_: Type, + crate trait_: Path, crate generic_params: Vec, } -/// A representation of a type suitable for hyperlinking purposes. Ideally, one can get the original -/// type out of the AST/`TyCtxt` given one of these, if more information is needed. Most -/// importantly, it does not preserve mutability or boxes. +/// Rustdoc's representation of types, mostly based on the [`hir::Ty`]. #[derive(Clone, PartialEq, Eq, Debug, Hash)] crate enum Type { - /// Structs/enums/traits (most that would be an `hir::TyKind::Path`). - ResolvedPath { - path: Path, - did: DefId, - /// `true` if is a `T::Name` path for associated types. - is_generic: bool, - }, - /// `dyn for<'a> Trait<'a> + Send + 'static` + /// 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 }, + /// A `dyn Trait` object: `dyn for<'a> Trait<'a> + Send + 'static` DynTrait(Vec, Option), - /// For parameterized types, so the consumer of the JSON don't go - /// looking for types which don't exist anywhere. + /// A type parameter. Generic(Symbol), - /// Primitives are the fixed-size numeric types (plus int/usize/float), char, - /// arrays, slices, and tuples. + /// A primitive (aka, builtin) type. Primitive(PrimitiveType), - /// `extern "ABI" fn` + /// A function pointer: `extern "ABI" fn(...) -> ...` BareFunction(Box), + /// A tuple type: `(i32, &str)`. Tuple(Vec), + /// A slice type (does *not* include the `&`): `[i32]` Slice(Box), - /// The `String` field is about the size or the constant representing the array's length. + /// An array type. + /// + /// The `String` field is a stringified version of the array's length parameter. Array(Box, String), - Never, + /// A raw pointer type: `*const i32`, `*mut i32` RawPointer(Mutability, Box), - BorrowedRef { - lifetime: Option, - mutability: Mutability, - type_: Box, - }, + /// A reference type: `&i32`, `&'a mut Foo` + BorrowedRef { lifetime: Option, mutability: Mutability, type_: Box }, - // `::Name` + /// A qualified path to an associated item: `::Name` QPath { name: Symbol, self_type: Box, + /// FIXME: This is a hack that should be removed; see [this discussion][1]. + /// + /// [1]: https://github.com/rust-lang/rust/pull/85479#discussion_r635729093 self_def_id: Option, - trait_: Box, + trait_: Path, }, - // `_` + /// A type that is inferred: `_` Infer, - // `impl TraitA + TraitB + ...` + /// An `impl Trait`: `impl TraitA + TraitB + ...` ImplTrait(Vec), } -#[derive(Clone, PartialEq, Eq, Hash, Copy, Debug)] -/// N.B. this has to be different from `hir::PrimTy` because it also includes types that aren't -/// paths, like `Unit`. -crate enum PrimitiveType { - Isize, - I8, - I16, - I32, - I64, - I128, - Usize, - U8, - U16, - U32, - U64, - U128, - F32, - F64, - Char, - Bool, - Str, - Slice, - Array, - Tuple, - Unit, - RawPointer, - Reference, - Fn, - Never, -} - 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`]. @@ -1543,14 +1496,14 @@ impl Type { } RawPointer(..) => Some(PrimitiveType::RawPointer), BareFunction(..) => Some(PrimitiveType::Fn), - Never => Some(PrimitiveType::Never), _ => None, } } - crate fn is_generic(&self) -> bool { - match *self { - ResolvedPath { is_generic, .. } => is_generic, + /// 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(), _ => false, } } @@ -1563,34 +1516,8 @@ impl Type { } crate fn generics(&self) -> Option> { - match *self { - ResolvedPath { ref path, .. } => path.segments.last().and_then(|seg| { - if let GenericArgs::AngleBracketed { ref args, .. } = seg.args { - Some( - args.iter() - .filter_map(|arg| match arg { - GenericArg::Type(ty) => Some(ty), - _ => None, - }) - .collect(), - ) - } else { - None - } - }), - _ => None, - } - } - - crate fn bindings(&self) -> Option<&[TypeBinding]> { - match *self { - ResolvedPath { ref path, .. } => path.segments.last().and_then(|seg| { - if let GenericArgs::AngleBracketed { ref bindings, .. } = seg.args { - Some(&**bindings) - } else { - None - } - }), + match self { + ResolvedPath { path, .. } => path.generics(), _ => None, } } @@ -1608,19 +1535,13 @@ impl Type { QPath { self_type, trait_, name, .. } => (self_type, trait_, name), _ => return None, }; - let trait_did = match **trait_ { - ResolvedPath { did, .. } => did, - _ => return None, - }; - Some((&self_, trait_did, *name)) + Some((&self_, trait_.def_id(), *name)) } -} -impl Type { fn inner_def_id(&self, cache: Option<&Cache>) -> Option { let t: PrimitiveType = match *self { ResolvedPath { did, .. } => return Some(did), - DynTrait(ref bounds, _) => return bounds[0].trait_.inner_def_id(cache), + 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, BorrowedRef { ref type_, .. } => return type_.inner_def_id(cache), @@ -1632,7 +1553,6 @@ impl Type { } } BareFunction(..) => PrimitiveType::Fn, - Never => PrimitiveType::Never, Slice(..) => PrimitiveType::Slice, Array(..) => PrimitiveType::Array, RawPointer(..) => PrimitiveType::RawPointer, @@ -1653,6 +1573,41 @@ impl GetDefId for Type { } } +/// A primitive (aka, builtin) type. +/// +/// This represents things like `i32`, `str`, etc. +/// +/// N.B. This has to be different from [`hir::PrimTy`] because it also includes types that aren't +/// paths, like [`Self::Unit`]. +#[derive(Clone, PartialEq, Eq, Hash, Copy, Debug)] +crate enum PrimitiveType { + Isize, + I8, + I16, + I32, + I64, + I128, + Usize, + U8, + U16, + U32, + U64, + U128, + F32, + F64, + Char, + Bool, + Str, + Slice, + Array, + Tuple, + Unit, + RawPointer, + Reference, + Fn, + Never, +} + impl PrimitiveType { crate fn from_hir(prim: hir::PrimTy) -> PrimitiveType { use ast::{FloatTy, IntTy, UintTy}; @@ -1800,6 +1755,39 @@ impl PrimitiveType { Never => sym::never, } } + + /// Returns the DefId of the module with `doc(primitive)` for this primitive type. + /// Panics if there is no such module. + /// + /// This gives precedence to primitives defined in the current crate, and deprioritizes primitives defined in `core`, + /// but otherwise, if multiple crates define the same primitive, there is no guarantee of which will be picked. + /// In particular, if a crate depends on both `std` and another crate that also defines `doc(primitive)`, then + /// it's entirely random whether `std` or the other crate is picked. (no_std crates are usually fine unless multiple dependencies define a primitive.) + crate fn primitive_locations(tcx: TyCtxt<'_>) -> &FxHashMap { + static PRIMITIVE_LOCATIONS: OnceCell> = OnceCell::new(); + PRIMITIVE_LOCATIONS.get_or_init(|| { + let mut primitive_locations = FxHashMap::default(); + // NOTE: technically this misses crates that are only passed with `--extern` and not loaded when checking the crate. + // This is a degenerate case that I don't plan to support. + for &crate_num in tcx.crates(()) { + let e = ExternalCrate { crate_num }; + let crate_name = e.name(tcx); + debug!(?crate_num, ?crate_name); + for &(def_id, prim) in &e.primitives(tcx) { + // HACK: try to link to std instead where possible + if crate_name == sym::core && primitive_locations.contains_key(&prim) { + continue; + } + primitive_locations.insert(prim, def_id); + } + } + let local_primitives = ExternalCrate { crate_num: LOCAL_CRATE }.primitives(tcx); + for (def_id, prim) in local_primitives { + primitive_locations.insert(prim, def_id); + } + primitive_locations + }) + } } impl From for PrimitiveType { @@ -1988,12 +1976,15 @@ impl Span { #[derive(Clone, PartialEq, Eq, Debug, Hash)] crate struct Path { - crate global: bool, crate res: Res, crate segments: Vec, } impl Path { + crate fn def_id(&self) -> DefId { + self.res.def_id() + } + crate fn last(&self) -> Symbol { self.segments.last().expect("segments were empty").name } @@ -2003,8 +1994,48 @@ impl Path { } crate fn whole_name(&self) -> String { - String::from(if self.global { "::" } else { "" }) - + &self.segments.iter().map(|s| s.name.to_string()).collect::>().join("::") + self.segments + .iter() + .map(|s| if s.name == kw::PathRoot { String::new() } else { s.name.to_string() }) + .intersperse("::".into()) + .collect() + } + + /// Checks if this is a `T::Name` path for an associated type. + crate fn is_assoc_ty(&self) -> bool { + match self.res { + Res::SelfTy(..) if self.segments.len() != 1 => true, + Res::Def(DefKind::TyParam, _) if self.segments.len() != 1 => true, + Res::Def(DefKind::AssocTy, _) => true, + _ => false, + } + } + + crate fn generics(&self) -> Option> { + self.segments.last().and_then(|seg| { + if let GenericArgs::AngleBracketed { ref args, .. } = seg.args { + Some( + args.iter() + .filter_map(|arg| match arg { + GenericArg::Type(ty) => Some(ty), + _ => None, + }) + .collect(), + ) + } else { + None + } + }) + } + + crate fn bindings(&self) -> Option<&[TypeBinding]> { + self.segments.last().and_then(|seg| { + if let GenericArgs::AngleBracketed { ref bindings, .. } = seg.args { + Some(&**bindings) + } else { + None + } + }) } } @@ -2012,10 +2043,15 @@ impl Path { crate enum GenericArg { Lifetime(Lifetime), Type(Type), - Const(Constant), + Const(Box), Infer, } +// `GenericArg` can occur many times in a single `Path`, so make sure it +// doesn't increase in size unexpectedly. +#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] +rustc_data_structures::static_assert_size!(GenericArg, 80); + #[derive(Clone, PartialEq, Eq, Debug, Hash)] crate enum GenericArgs { AngleBracketed { args: Vec, bindings: Vec }, @@ -2144,7 +2180,7 @@ crate struct Impl { crate span: Span, crate unsafety: hir::Unsafety, crate generics: Generics, - crate trait_: Option, + crate trait_: Option, crate for_: Type, crate items: Vec, crate negative_polarity: bool, @@ -2155,7 +2191,8 @@ crate struct Impl { impl Impl { crate fn provided_trait_methods(&self, tcx: TyCtxt<'_>) -> FxHashSet { self.trait_ - .def_id() + .as_ref() + .map(|t| t.def_id()) .map(|did| tcx.provided_trait_methods(did).map(|meth| meth.ident.name).collect()) .unwrap_or_default() } @@ -2195,7 +2232,6 @@ crate struct ImportSource { #[derive(Clone, Debug)] crate struct Macro { crate source: String, - crate imported_from: Option, } #[derive(Clone, Debug)] diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index bdfe3ffc13..de43daff6f 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -2,7 +2,7 @@ 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, PolyTrait, Primitive, PrimitiveType, ResolvedPath, Type, + ItemKind, Lifetime, Path, PathSegment, Primitive, PrimitiveType, ResolvedPath, Type, TypeBinding, Visibility, }; use crate::core::DocContext; @@ -26,12 +26,7 @@ mod tests; crate fn krate(cx: &mut DocContext<'_>) -> Crate { use crate::visit_lib::LibEmbargoVisitor; - let krate = cx.tcx.hir().krate(); - let module = crate::visit_ast::RustdocVisitor::new(cx).visit(krate); - - cx.cache.deref_trait_did = cx.tcx.lang_items().deref_trait(); - cx.cache.deref_mut_trait_did = cx.tcx.lang_items().deref_mut_trait(); - cx.cache.owned_box_did = cx.tcx.lang_items().owned_box(); + let module = crate::visit_ast::RustdocVisitor::new(cx).visit(); let mut externs = Vec::new(); for &cnum in cx.tcx.crates(()).iter() { @@ -97,7 +92,7 @@ crate fn krate(cx: &mut DocContext<'_>) -> Crate { fn external_generic_args( cx: &mut DocContext<'_>, - trait_did: Option, + did: DefId, has_self: bool, bindings: Vec, substs: SubstsRef<'_>, @@ -121,85 +116,47 @@ fn external_generic_args( ty_kind = Some(ty.kind()); Some(GenericArg::Type(ty.clean(cx))) } - GenericArgKind::Const(ct) => Some(GenericArg::Const(ct.clean(cx))), + GenericArgKind::Const(ct) => Some(GenericArg::Const(Box::new(ct.clean(cx)))), }) .collect(); - match trait_did { - // Attempt to sugar an external path like Fn<(A, B,), C> to Fn(A, B) -> C - Some(did) if cx.tcx.fn_trait_kind_from_lang_item(did).is_some() => { - assert!(ty_kind.is_some()); - let inputs = match ty_kind { - Some(ty::Tuple(ref tys)) => tys.iter().map(|t| t.expect_ty().clean(cx)).collect(), - _ => return GenericArgs::AngleBracketed { args, bindings }, - }; - let output = None; - // FIXME(#20299) return type comes from a projection now - // match types[1].kind { - // ty::Tuple(ref v) if v.is_empty() => None, // -> () - // _ => Some(types[1].clean(cx)) - // }; - GenericArgs::Parenthesized { inputs, output } - } - _ => GenericArgs::AngleBracketed { args, bindings }, + if cx.tcx.fn_trait_kind_from_lang_item(did).is_some() { + let inputs = match ty_kind.unwrap() { + ty::Tuple(tys) => tys.iter().map(|t| t.expect_ty().clean(cx)).collect(), + _ => return GenericArgs::AngleBracketed { args, bindings }, + }; + let output = None; + // FIXME(#20299) return type comes from a projection now + // match types[1].kind { + // ty::Tuple(ref v) if v.is_empty() => None, // -> () + // _ => Some(types[1].clean(cx)) + // }; + GenericArgs::Parenthesized { inputs, output } + } else { + GenericArgs::AngleBracketed { args, bindings } } } -// trait_did should be set to a trait's DefId if called on a TraitRef, in order to sugar -// from Fn<(A, B,), C> to Fn(A, B) -> C pub(super) fn external_path( cx: &mut DocContext<'_>, - name: Symbol, - trait_did: Option, + did: DefId, has_self: bool, bindings: Vec, substs: SubstsRef<'_>, ) -> Path { + let def_kind = cx.tcx.def_kind(did); + let name = cx.tcx.item_name(did); Path { - global: false, - res: Res::Err, + res: Res::Def(def_kind, did), segments: vec![PathSegment { name, - args: external_generic_args(cx, trait_did, has_self, bindings, substs), + args: external_generic_args(cx, did, has_self, bindings, substs), }], } } -crate fn strip_type(ty: Type) -> Type { - match ty { - Type::ResolvedPath { path, did, is_generic } => { - Type::ResolvedPath { path: strip_path(&path), did, is_generic } - } - Type::DynTrait(mut bounds, lt) => { - let first = bounds.remove(0); - let stripped_trait = strip_type(first.trait_); - - bounds.insert( - 0, - PolyTrait { trait_: stripped_trait, generic_params: first.generic_params }, - ); - Type::DynTrait(bounds, lt) - } - Type::Tuple(inner_tys) => { - Type::Tuple(inner_tys.iter().map(|t| strip_type(t.clone())).collect()) - } - Type::Slice(inner_ty) => Type::Slice(Box::new(strip_type(*inner_ty))), - Type::Array(inner_ty, s) => Type::Array(Box::new(strip_type(*inner_ty)), s), - Type::RawPointer(m, inner_ty) => Type::RawPointer(m, Box::new(strip_type(*inner_ty))), - Type::BorrowedRef { lifetime, mutability, type_ } => { - Type::BorrowedRef { lifetime, mutability, type_: Box::new(strip_type(*type_)) } - } - Type::QPath { name, self_type, trait_, self_def_id } => Type::QPath { - name, - self_def_id, - self_type: Box::new(strip_type(*self_type)), - trait_: Box::new(strip_type(*trait_)), - }, - _ => ty, - } -} - -crate fn strip_path(path: &Path) -> Path { +/// Remove the generic arguments from a path. +crate fn strip_path_generics(path: Path) -> Path { let segments = path .segments .iter() @@ -209,7 +166,7 @@ crate fn strip_path(path: &Path) -> Path { }) .collect(); - Path { global: path.global, res: path.res, segments } + Path { res: path.res, segments } } crate fn qpath_to_string(p: &hir::QPath<'_>) -> String { @@ -409,22 +366,18 @@ crate fn print_const_expr(tcx: TyCtxt<'_>, body: hir::BodyId) -> String { } /// Given a type Path, resolve it to a Type using the TyCtxt -crate fn resolve_type(cx: &mut DocContext<'_>, path: Path, id: hir::HirId) -> Type { - debug!("resolve_type({:?},{:?})", path, id); +crate fn resolve_type(cx: &mut DocContext<'_>, path: Path) -> Type { + debug!("resolve_type({:?})", path); - let is_generic = match path.res { - Res::PrimTy(p) => return Primitive(PrimitiveType::from(p)), - Res::SelfTy(..) if path.segments.len() == 1 => { - return Generic(kw::SelfUpper); + match path.res { + Res::PrimTy(p) => Primitive(PrimitiveType::from(p)), + 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 } } - Res::Def(DefKind::TyParam, _) if path.segments.len() == 1 => { - return Generic(Symbol::intern(&path.whole_name())); - } - Res::SelfTy(..) | Res::Def(DefKind::TyParam | DefKind::AssocTy, _) => true, - _ => false, - }; - let did = register_res(cx, path.res); - ResolvedPath { path, did, is_generic } + } } crate fn get_auto_trait_and_blanket_impls( diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index 97930f1069..ac440a3951 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -137,7 +137,7 @@ crate struct Options { 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_warnings: bool, + 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, @@ -192,7 +192,7 @@ 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_warnings", &self.display_warnings) + .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) @@ -632,7 +632,7 @@ 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_warnings = matches.opt_present("display-warnings"); + 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"); @@ -696,7 +696,7 @@ impl Options { test_args, default_passes, manual_passes, - display_warnings, + display_doctest_warnings, show_coverage, crate_version, test_run_directory, diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index bd1d970fc1..0c79d37a6d 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -16,15 +16,18 @@ use rustc_middle::hir::map::Map; use rustc_middle::middle::privacy::AccessLevels; use rustc_middle::ty::{ParamEnv, Ty, TyCtxt}; use rustc_resolve as resolve; +use rustc_resolve::Namespace::TypeNS; use rustc_session::config::{self, CrateType, ErrorOutputType}; use rustc_session::lint; use rustc_session::DiagnosticOutput; use rustc_session::Session; +use rustc_span::def_id::CRATE_DEF_INDEX; use rustc_span::source_map; use rustc_span::symbol::sym; -use rustc_span::Span; +use rustc_span::{Span, DUMMY_SP}; use std::cell::RefCell; +use std::lazy::SyncLazy; use std::mem; use std::rc::Rc; @@ -204,7 +207,6 @@ crate fn create_config( lint_opts, describe_lints, lint_cap, - display_warnings, .. }: RustdocOptions, ) -> rustc_interface::Config { @@ -237,7 +239,7 @@ crate fn create_config( maybe_sysroot, search_paths: libs, crate_types, - lint_opts: if !display_warnings { lint_opts } else { vec![] }, + lint_opts, lint_cap, cg: codegen_options, externs, @@ -264,7 +266,7 @@ crate fn create_config( stderr: None, lint_caps, parse_sess_created: None, - register_lints: Some(Box::new(crate::lint::register_lints)), + register_lints: Some(box crate::lint::register_lints), override_queries: Some(|_sess, providers, _external_providers| { // Most lints will require typechecking, so just don't run them. providers.lint_mod = |_, _| {}; @@ -272,9 +274,8 @@ crate fn create_config( providers.typeck_item_bodies = |_, _| {}; // hack so that `used_trait_imports` won't try to call typeck providers.used_trait_imports = |_, _| { - lazy_static! { - static ref EMPTY_SET: FxHashSet = FxHashSet::default(); - } + static EMPTY_SET: SyncLazy> = + SyncLazy::new(FxHashSet::default); &EMPTY_SET }; // In case typeck does end up being called, don't ICE in case there were name resolution errors @@ -300,13 +301,43 @@ crate fn create_config( } crate fn create_resolver<'a>( + externs: config::Externs, queries: &Queries<'a>, sess: &Session, ) -> Rc> { let (krate, resolver, _) = &*abort_on_err(queries.expansion(), sess).peek(); let resolver = resolver.clone(); - crate::passes::collect_intra_doc_links::load_intra_link_crates(resolver, krate) + let resolver = crate::passes::collect_intra_doc_links::load_intra_link_crates(resolver, krate); + + // FIXME: somehow rustdoc is still missing crates even though we loaded all + // the known necessary crates. Load them all unconditionally until we find a way to fix this. + // DO NOT REMOVE THIS without first testing on the reproducer in + // https://github.com/jyn514/objr/commit/edcee7b8124abf0e4c63873e8422ff81beb11ebb + let extern_names: Vec = externs + .iter() + .filter(|(_, entry)| entry.add_prelude) + .map(|(name, _)| name) + .cloned() + .collect(); + resolver.borrow_mut().access(|resolver| { + sess.time("load_extern_crates", || { + for extern_name in &extern_names { + debug!("loading extern crate {}", extern_name); + if let Err(()) = resolver + .resolve_str_path_error( + DUMMY_SP, + extern_name, + TypeNS, + LocalDefId { local_def_index: CRATE_DEF_INDEX }.to_def_id(), + ) { + warn!("unable to resolve external crate {} (do you have an unused `--extern` crate?)", extern_name) + } + } + }); + }); + + resolver } crate fn run_global_ctxt( @@ -330,18 +361,14 @@ crate fn run_global_ctxt( // NOTE: This is copy/pasted from typeck/lib.rs and should be kept in sync with those changes. tcx.sess.time("item_types_checking", || { - for &module in tcx.hir().krate().modules.keys() { - tcx.ensure().check_mod_item_types(module); - } + tcx.hir().for_each_module(|module| tcx.ensure().check_mod_item_types(module)) }); tcx.sess.abort_if_errors(); tcx.sess.time("missing_docs", || { rustc_lint::check_crate(tcx, rustc_lint::builtin::MissingDoc::new); }); tcx.sess.time("check_mod_attrs", || { - for &module in tcx.hir().krate().modules.keys() { - tcx.ensure().check_mod_attrs(module); - } + tcx.hir().for_each_module(|module| tcx.ensure().check_mod_attrs(module)) }); rustc_passes::stability::check_unused_or_stable_features(tcx); diff --git a/src/librustdoc/docfs.rs b/src/librustdoc/docfs.rs index 9b740acfcd..a5fab1b3d4 100644 --- a/src/librustdoc/docfs.rs +++ b/src/librustdoc/docfs.rs @@ -11,7 +11,7 @@ use std::fs; use std::io; -use std::path::Path; +use std::path::{Path, PathBuf}; use std::string::ToString; use std::sync::mpsc::Sender; @@ -55,17 +55,17 @@ impl DocFS { fs::create_dir_all(path) } - crate fn write(&self, path: P, contents: C) -> Result<(), E> + crate fn write( + &self, + path: PathBuf, + contents: impl 'static + Send + AsRef<[u8]>, + ) -> Result<(), E> where - P: AsRef, - C: AsRef<[u8]>, E: PathError, { if !self.sync_only && cfg!(windows) { // A possible future enhancement after more detailed profiling would // be to create the file sync so errors are reported eagerly. - let path = path.as_ref().to_path_buf(); - let contents = contents.as_ref().to_vec(); let sender = self.errors.clone().expect("can't write after closing"); rayon::spawn(move || { fs::write(&path, contents).unwrap_or_else(|e| { diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index e61b7a0903..9e64d200b4 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -40,7 +40,7 @@ crate struct TestOptions { crate no_crate_inject: bool, /// Whether to emit compilation warnings when compiling doctests. Setting this will suppress /// the default `#![allow(unused)]`. - crate display_warnings: bool, + crate display_doctest_warnings: bool, /// Additional crate-level attributes to add to doctests. crate attrs: Vec, } @@ -72,8 +72,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_warnings { lint_opts } else { vec![] }, - lint_cap: Some(options.lint_cap.clone().unwrap_or_else(|| lint::Forbid)), + lint_opts: if !options.display_doctest_warnings { lint_opts } else { vec![] }, + lint_cap: Some(options.lint_cap.unwrap_or_else(|| lint::Forbid)), cg: options.codegen_options.clone(), externs: options.externs.clone(), unstable_features: options.render_options.unstable_features, @@ -99,14 +99,14 @@ crate fn run(options: Options) -> Result<(), ErrorReported> { stderr: None, lint_caps, parse_sess_created: None, - register_lints: Some(Box::new(crate::lint::register_lints)), + register_lints: Some(box crate::lint::register_lints), override_queries: None, make_codegen_backend: None, registry: rustc_driver::diagnostics_registry(), }; let test_args = options.test_args.clone(); - let display_warnings = options.display_warnings; + 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; @@ -116,11 +116,10 @@ crate fn run(options: Options) -> Result<(), ErrorReported> { let mut global_ctxt = queries.global_ctxt()?.take(); let collector = global_ctxt.enter(|tcx| { - let krate = tcx.hir().krate(); let crate_attrs = tcx.hir().attrs(CRATE_HIR_ID); let mut opts = scrape_test_config(crate_attrs); - opts.display_warnings |= options.display_warnings; + opts.display_doctest_warnings |= options.display_doctest_warnings; let enable_per_target_ignores = options.enable_per_target_ignores; let mut collector = Collector::new( tcx.crate_name(LOCAL_CRATE), @@ -144,10 +143,8 @@ crate fn run(options: Options) -> Result<(), ErrorReported> { hir_collector.visit_testable( "".to_string(), CRATE_HIR_ID, - krate.module().inner, - |this| { - intravisit::walk_crate(this, krate); - }, + tcx.hir().span(CRATE_HIR_ID), + |this| tcx.hir().walk_toplevel_module(this), ); collector @@ -166,7 +163,7 @@ crate fn run(options: Options) -> Result<(), ErrorReported> { Err(ErrorReported) => return Err(ErrorReported), }; - run_tests(test_args, nocapture, display_warnings, tests); + run_tests(test_args, nocapture, display_doctest_warnings, tests); // Collect and warn about unused externs, but only if we've gotten // reports for each doctest @@ -212,14 +209,18 @@ crate fn run(options: Options) -> Result<(), ErrorReported> { crate fn run_tests( mut test_args: Vec, nocapture: bool, - display_warnings: bool, + display_doctest_warnings: 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_warnings))); + test::test_main( + &test_args, + tests, + Some(test::Options::new().display_output(display_doctest_warnings)), + ); } // Look for `#![doc(test(no_crate_inject))]`, used by crates in the std facade. @@ -227,7 +228,7 @@ fn scrape_test_config(attrs: &[ast::Attribute]) -> TestOptions { use rustc_ast_pretty::pprust; let mut opts = - TestOptions { no_crate_inject: false, display_warnings: false, attrs: Vec::new() }; + TestOptions { no_crate_inject: false, display_doctest_warnings: false, attrs: Vec::new() }; let test_attrs: Vec<_> = attrs .iter() @@ -507,7 +508,7 @@ crate fn make_test( let mut prog = String::new(); let mut supports_color = false; - if opts.attrs.is_empty() && !opts.display_warnings { + if opts.attrs.is_empty() && !opts.display_doctest_warnings { // 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 @@ -549,10 +550,10 @@ crate fn make_test( .supports_color(); let emitter = - EmitterWriter::new(Box::new(io::sink()), None, false, false, false, None, false); + EmitterWriter::new(box io::sink(), None, false, false, false, None, false); // FIXME(misdreavus): pass `-Z treat-err-as-bug` to the doctest parser - let handler = Handler::with_emitter(false, None, Box::new(emitter)); + let handler = Handler::with_emitter(false, None, box emitter); let sess = ParseSess::with_span_handler(handler, sm); let mut found_main = false; @@ -852,6 +853,7 @@ impl Collector { fn generate_name(&self, line: usize, filename: &FileName) -> String { let mut item_path = self.names.join("::"); + item_path.retain(|c| c != ' '); if !item_path.is_empty() { item_path.push(' '); } @@ -962,7 +964,7 @@ impl Tester for Collector { no_run, test_type: test::TestType::DocTest, }, - testfn: test::DynTestFn(Box::new(move || { + testfn: test::DynTestFn(box move || { let report_unused_externs = |uext| { unused_externs.lock().unwrap().push(uext); }; @@ -1042,9 +1044,9 @@ impl Tester for Collector { } } - panic::resume_unwind(Box::new(())); + panic::resume_unwind(box ()); } - })), + }), }); } @@ -1121,7 +1123,7 @@ impl<'a, 'hir, 'tcx> HirCollector<'a, 'hir, 'tcx> { let ast_attrs = self.tcx.hir().attrs(hir_id); let mut attrs = Attributes::from_ast(ast_attrs, None); - if let Some(ref cfg) = ast_attrs.cfg(self.sess) { + if let Some(ref cfg) = ast_attrs.cfg(self.tcx, &FxHashSet::default()) { 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 c49e45c0e2..1851708096 100644 --- a/src/librustdoc/doctest/tests.rs +++ b/src/librustdoc/doctest/tests.rs @@ -52,7 +52,8 @@ 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_warnings: false, attrs: vec![] }; + let opts = + TestOptions { no_crate_inject: true, display_doctest_warnings: false, attrs: vec![] }; let input = "use asdf::qwop; assert_eq!(2+2, 4);"; let expected = "#![allow(unused)] @@ -215,10 +216,10 @@ assert_eq!(2+2, 4);" } #[test] -fn make_test_display_warnings() { +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_warnings = true; + opts.display_doctest_warnings = true; let input = "assert_eq!(2+2, 4);"; let expected = "fn main() { assert_eq!(2+2, 4); diff --git a/src/librustdoc/externalfiles.rs b/src/librustdoc/externalfiles.rs index 56d2ca5721..302fc5a677 100644 --- a/src/librustdoc/externalfiles.rs +++ b/src/librustdoc/externalfiles.rs @@ -1,4 +1,4 @@ -use crate::html::markdown::{ErrorCodes, IdMap, Markdown, Playground}; +use crate::html::markdown::{ErrorCodes, HeadingOffset, IdMap, Markdown, Playground}; use crate::rustc_span::edition::Edition; use std::fs; use std::path::Path; @@ -39,14 +39,32 @@ impl ExternalHtml { let bc = format!( "{}{}", bc, - Markdown(&m_bc, &[], id_map, codes, edition, playground).into_string() + Markdown { + content: &m_bc, + links: &[], + ids: id_map, + error_codes: codes, + edition, + playground, + heading_offset: HeadingOffset::H2, + } + .into_string() ); let ac = load_external_files(after_content, diag)?; let m_ac = load_external_files(md_after_content, diag)?; let ac = format!( "{}{}", ac, - Markdown(&m_ac, &[], id_map, codes, edition, playground).into_string() + Markdown { + content: &m_ac, + links: &[], + ids: id_map, + error_codes: codes, + edition, + playground, + heading_offset: HeadingOffset::H2, + } + .into_string() ); Some(ExternalHtml { in_header: ih, before_content: bc, after_content: ac }) } diff --git a/src/librustdoc/fold.rs b/src/librustdoc/fold.rs index b4859e4c9c..f84850c0fe 100644 --- a/src/librustdoc/fold.rs +++ b/src/librustdoc/fold.rs @@ -2,7 +2,7 @@ use crate::clean::*; crate fn strip_item(mut item: Item) -> Item { if !matches!(*item.kind, StrippedItem(..)) { - item.kind = Box::new(StrippedItem(item.kind)); + item.kind = box StrippedItem(item.kind); } item } @@ -69,10 +69,10 @@ crate trait DocFolder: Sized { /// don't override! fn fold_item_recur(&mut self, mut item: Item) -> Item { - item.kind = Box::new(match *item.kind { - StrippedItem(box i) => StrippedItem(Box::new(self.fold_inner_recur(i))), + item.kind = box match *item.kind { + StrippedItem(box i) => StrippedItem(box self.fold_inner_recur(i)), _ => self.fold_inner_recur(*item.kind), - }); + }; item } diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs index 1830909d94..8b883ffaaf 100644 --- a/src/librustdoc/formats/cache.rs +++ b/src/librustdoc/formats/cache.rs @@ -6,7 +6,7 @@ use rustc_middle::middle::privacy::AccessLevels; use rustc_middle::ty::TyCtxt; use rustc_span::symbol::sym; -use crate::clean::{self, GetDefId, ItemId}; +use crate::clean::{self, GetDefId, ItemId, PrimitiveType}; use crate::config::RenderOptions; use crate::fold::DocFolder; use crate::formats::item_type::ItemType; @@ -98,9 +98,6 @@ crate struct Cache { stripped_mod: bool, crate search_index: Vec, - crate deref_trait_did: Option, - crate deref_mut_trait_did: Option, - crate owned_box_did: Option, // In rare case where a structure is defined in one module but implemented // in another, if the implementing module is parsed before defining module, @@ -122,6 +119,8 @@ crate struct Cache { /// /// Links are indexed by the DefId of the item they document. crate intra_doc_links: FxHashMap>, + /// Cfg that have been hidden via #![doc(cfg_hide(...))] + crate hidden_cfg: FxHashSet, } /// This struct is used to wrap the `cache` and `tcx` in order to run `DocFolder`. @@ -159,17 +158,16 @@ impl Cache { self.external_paths.insert(e.def_id(), (vec![name.to_string()], ItemType::Module)); } - // Cache where all known primitives have their documentation located. - // - // Favor linking to as local extern as possible, so iterate all crates in - // reverse topological order. - for &e in krate.externs.iter().rev() { - for &(def_id, prim) in &e.primitives(tcx) { - self.primitive_locations.insert(prim, def_id); - } - } - for &(def_id, prim) in &krate.primitives { - self.primitive_locations.insert(prim, def_id); + // FIXME: avoid this clone (requires implementing Default manually) + self.primitive_locations = PrimitiveType::primitive_locations(tcx).clone(); + for (prim, &def_id) in &self.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( + def_id, + (vec![crate_name.to_string(), prim.as_sym().to_string()], ItemType::Primitive), + ); } krate = CacheBuilder { tcx, cache: self }.fold_crate(krate); @@ -205,7 +203,9 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> { // masked crate then remove it completely. if let clean::ImplItem(ref i) = *item.kind { if self.cache.masked_crates.contains(&item.def_id.krate()) - || i.trait_.def_id().map_or(false, |d| self.cache.masked_crates.contains(&d.krate)) + || 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)) { return None; @@ -225,11 +225,11 @@ 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(did) = i.trait_.def_id() { + if let Some(trait_) = &i.trait_ { if i.blanket_impl.is_none() { self.cache .implementors - .entry(did) + .entry(trait_.def_id()) .or_default() .push(Impl { impl_item: item.clone() }); } @@ -404,12 +404,8 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> { } clean::DynTrait(ref bounds, _) | clean::BorrowedRef { type_: box clean::DynTrait(ref bounds, _), .. } => { - if let Some(did) = bounds[0].trait_.def_id() { - self.cache.parent_stack.push(did); - true - } else { - false - } + self.cache.parent_stack.push(bounds[0].trait_.def_id()); + true } ref t => { let prim_did = t @@ -443,9 +439,7 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> { } clean::DynTrait(ref bounds, _) | clean::BorrowedRef { type_: box clean::DynTrait(ref bounds, _), .. } => { - if let Some(did) = bounds[0].trait_.def_id() { - dids.insert(did); - } + dids.insert(bounds[0].trait_.def_id()); } ref t => { let did = t diff --git a/src/librustdoc/formats/mod.rs b/src/librustdoc/formats/mod.rs index 6060b0560c..4f0c5a9ede 100644 --- a/src/librustdoc/formats/mod.rs +++ b/src/librustdoc/formats/mod.rs @@ -7,14 +7,12 @@ use rustc_hir::def_id::DefId; crate use renderer::{run_format, FormatRenderer}; use crate::clean; -use crate::clean::types::GetDefId; -use crate::formats::cache::Cache; /// Specifies whether rendering directly implemented trait items or ones from a certain Deref /// impl. crate enum AssocItemRender<'a> { All, - DerefFor { trait_: &'a clean::Type, type_: &'a clean::Type, deref_mut_: bool }, + DerefFor { trait_: &'a clean::Path, type_: &'a clean::Type, deref_mut_: bool }, } /// For different handling of associated items from the Deref target of a type rather than the type @@ -40,10 +38,6 @@ impl Impl { } crate fn trait_did(&self) -> Option { - self.inner_impl().trait_.def_id() - } - - crate fn trait_did_full(&self, cache: &Cache) -> Option { - self.inner_impl().trait_.def_id_full(cache) + self.inner_impl().trait_.as_ref().map(|t| t.def_id()) } } diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 54be830bf4..f2751947c7 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -18,9 +18,7 @@ use rustc_middle::ty::TyCtxt; use rustc_span::def_id::CRATE_DEF_INDEX; use rustc_target::spec::abi::Abi; -use crate::clean::{ - self, utils::find_nearest_parent_module, ExternalCrate, GetDefId, ItemId, PrimitiveType, -}; +use crate::clean::{self, utils::find_nearest_parent_module, ExternalCrate, ItemId, PrimitiveType}; use crate::formats::item_type::ItemType; use crate::html::escape::Escape; use crate::html::render::cache::ExternalLocation; @@ -155,9 +153,23 @@ impl clean::GenericParamDef { &'a self, cx: &'a Context<'tcx>, ) -> impl fmt::Display + 'a + Captures<'tcx> { - display_fn(move |f| match self.kind { - clean::GenericParamDefKind::Lifetime => write!(f, "{}", self.name), - clean::GenericParamDefKind::Type { ref bounds, ref default, .. } => { + display_fn(move |f| match &self.kind { + clean::GenericParamDefKind::Lifetime { outlives } => { + write!(f, "{}", self.name)?; + + if !outlives.is_empty() { + f.write_str(": ")?; + for (i, lt) in outlives.iter().enumerate() { + if i != 0 { + f.write_str(" + ")?; + } + write!(f, "{}", lt.print())?; + } + } + + Ok(()) + } + clean::GenericParamDefKind::Type { bounds, default, .. } => { f.write_str(&*self.name.as_str())?; if !bounds.is_empty() { @@ -178,7 +190,7 @@ impl clean::GenericParamDef { Ok(()) } - clean::GenericParamDefKind::Const { ref ty, ref default, .. } => { + clean::GenericParamDefKind::Const { ty, default, .. } => { if f.alternate() { write!(f, "const {}: {:#}", self.name, ty.print(cx))?; } else { @@ -256,7 +268,7 @@ crate fn print_where_clause<'a, 'tcx: 'a>( 0 => String::new(), _ if f.alternate() => { format!( - "for<{:#}> ", + "for<{:#}> ", comma_sep(bound_params.iter().map(|lt| lt.print())) ) } @@ -495,7 +507,11 @@ crate fn href_with_root_path( if shortty == ItemType::Module { fqp } else { &fqp[..fqp.len() - 1] } } - if !did.is_local() && !cache.access_levels.is_public(did) && !cache.document_private { + if !did.is_local() + && !cache.access_levels.is_public(did) + && !cache.document_private + && !cache.primitive_locations.values().any(|&id| id == did) + { return Err(HrefError::Private); } @@ -503,6 +519,7 @@ crate fn href_with_root_path( let (fqp, shortty, mut url_parts) = match cache.paths.get(&did) { Some(&(ref fqp, shortty)) => (fqp, shortty, { let module_fqp = to_module_fqp(shortty, fqp); + debug!(?fqp, ?shortty, ?module_fqp); href_relative_parts(module_fqp, relative_to) }), None => { @@ -534,6 +551,7 @@ crate fn href_with_root_path( url_parts.insert(0, root); } } + debug!(?url_parts); let last = &fqp.last().unwrap()[..]; let filename; match shortty { @@ -728,19 +746,22 @@ fn fmt_type<'cx>( use_absolute: bool, cx: &'cx Context<'_>, ) -> fmt::Result { - debug!("fmt_type(t = {:?})", t); + trace!("fmt_type(t = {:?})", t); match *t { clean::Generic(name) => write!(f, "{}", name), - clean::ResolvedPath { did, ref path, is_generic } => { + clean::ResolvedPath { did, ref path } => { // Paths like `T::Output` and `Self::Output` should be rendered with all segments. - resolved_path(f, did, path, is_generic, use_absolute, cx) + resolved_path(f, did, path, path.is_assoc_ty(), use_absolute, cx) } clean::DynTrait(ref bounds, ref lt) => { f.write_str("dyn ")?; fmt::Display::fmt(&tybounds(bounds, lt, cx), f) } clean::Infer => write!(f, "_"), + clean::Primitive(clean::PrimitiveType::Never) => { + primitive_link(f, PrimitiveType::Never, "!", cx) + } clean::Primitive(prim) => primitive_link(f, prim, &*prim.as_sym().as_str(), cx), clean::BareFunction(ref decl) => { if f.alternate() { @@ -799,34 +820,22 @@ fn fmt_type<'cx>( primitive_link(f, PrimitiveType::Array, &format!("; {}]", Escape(n)), cx) } } - clean::Never => primitive_link(f, PrimitiveType::Never, "!", cx), clean::RawPointer(m, ref t) => { let m = match m { hir::Mutability::Mut => "mut", hir::Mutability::Not => "const", }; - match **t { - clean::Generic(_) | clean::ResolvedPath { is_generic: true, .. } => { - if f.alternate() { - primitive_link( - f, - clean::PrimitiveType::RawPointer, - &format!("*{} {:#}", m, t.print(cx)), - cx, - ) - } else { - primitive_link( - f, - clean::PrimitiveType::RawPointer, - &format!("*{} {}", m, t.print(cx)), - cx, - ) - } - } - _ => { - primitive_link(f, clean::PrimitiveType::RawPointer, &format!("*{} ", m), cx)?; - fmt::Display::fmt(&t.print(cx), f) - } + + if matches!(**t, clean::Generic(_)) || t.is_assoc_ty() { + let text = if f.alternate() { + format!("*{} {:#}", m, t.print(cx)) + } else { + format!("*{} {}", m, t.print(cx)) + }; + primitive_link(f, clean::PrimitiveType::RawPointer, &text, cx) + } else { + primitive_link(f, clean::PrimitiveType::RawPointer, &format!("*{} ", m), cx)?; + fmt::Display::fmt(&t.print(cx), f) } } clean::BorrowedRef { lifetime: ref l, mutability, type_: ref ty } => { @@ -903,15 +912,10 @@ fn fmt_type<'cx>( } } clean::QPath { ref name, ref self_type, ref trait_, ref self_def_id } => { - let should_show_cast = match *trait_ { - box clean::ResolvedPath { ref path, .. } => { - !path.segments.is_empty() - && self_def_id - .zip(trait_.def_id()) - .map_or(!self_type.is_self_type(), |(id, trait_)| id != trait_) - } - _ => true, - }; + let should_show_cast = !trait_.segments.is_empty() + && self_def_id + .zip(Some(trait_.def_id())) + .map_or(!self_type.is_self_type(), |(id, trait_)| id != trait_); if f.alternate() { if should_show_cast { write!(f, "<{:#} as {:#}>::", self_type.print(cx), trait_.print(cx))? @@ -925,36 +929,31 @@ fn fmt_type<'cx>( write!(f, "{}::", self_type.print(cx))? } }; - match *trait_ { - // It's pretty unsightly to look at `
::C` in output, and - // we've got hyperlinking on our side, so try to avoid longer - // notation as much as possible by making `C` a hyperlink to trait - // `B` to disambiguate. - // - // FIXME: this is still a lossy conversion and there should probably - // be a better way of representing this in general? Most of - // the ugliness comes from inlining across crates where - // everything comes in as a fully resolved QPath (hard to - // look at). - box clean::ResolvedPath { did, .. } => { - match href(did, cx) { - Ok((ref url, _, ref path)) if !f.alternate() => { - write!( - f, - "::C` in output, and + // we've got hyperlinking on our side, so try to avoid longer + // notation as much as possible by making `C` a hyperlink to trait + // `B` to disambiguate. + // + // FIXME: this is still a lossy conversion and there should probably + // be a better way of representing this in general? Most of + // the ugliness comes from inlining across crates where + // everything comes in as a fully resolved QPath (hard to + // look at). + match href(trait_.def_id(), cx) { + Ok((ref url, _, ref path)) if !f.alternate() => { + write!( + f, + "{name}", - url = url, - shortty = ItemType::AssocType, - name = name, - path = path.join("::") - )?; - } - _ => write!(f, "{}", name)?, - } - Ok(()) + url = url, + shortty = ItemType::AssocType, + name = name, + path = path.join("::") + )?; } - _ => write!(f, "{}", name), + _ => write!(f, "{}", name)?, } + Ok(()) } } } @@ -968,6 +967,15 @@ impl clean::Type { } } +impl clean::Path { + crate fn print<'b, 'a: 'b, 'tcx: 'a>( + &'a self, + cx: &'a Context<'tcx>, + ) -> impl fmt::Display + 'b + Captures<'tcx> { + display_fn(move |f| resolved_path(f, self.def_id(), self, false, false, cx)) + } +} + impl clean::Impl { crate fn print<'a, 'tcx: 'a>( &'a self, @@ -1048,7 +1056,11 @@ impl clean::BareFunctionDecl { ) -> impl fmt::Display + 'a + Captures<'tcx> { display_fn(move |f| { if !self.generic_params.is_empty() { - write!(f, "for<{}> ", comma_sep(self.generic_params.iter().map(|g| g.print(cx)))) + write!( + f, + "for<{}> ", + comma_sep(self.generic_params.iter().map(|g| g.print(cx))) + ) } else { Ok(()) } diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs index f8fc9243e1..8ed6996287 100644 --- a/src/librustdoc/html/highlight.rs +++ b/src/librustdoc/html/highlight.rs @@ -5,11 +5,12 @@ //! //! Use the `render_with_highlighting` to highlight some rust code. +use crate::clean::PrimitiveType; use crate::html::escape::Escape; use crate::html::render::Context; +use std::collections::VecDeque; use std::fmt::{Display, Write}; -use std::iter::Peekable; use rustc_lexer::{LiteralKind, TokenKind}; use rustc_span::edition::Edition; @@ -200,10 +201,57 @@ fn get_real_ident_class(text: &str, edition: Edition, allow_path_keywords: bool) }) } +/// This iterator comes from the same idea than "Peekable" except that it allows to "peek" more than +/// just the next item by using `peek_next`. The `peek` method always returns the next item after +/// the current one whereas `peek_next` will return the next item after the last one peeked. +/// +/// You can use both `peek` and `peek_next` at the same time without problem. +struct PeekIter<'a> { + stored: VecDeque<(TokenKind, &'a str)>, + /// This position is reinitialized when using `next`. It is used in `peek_next`. + peek_pos: usize, + iter: TokenIter<'a>, +} + +impl PeekIter<'a> { + fn new(iter: TokenIter<'a>) -> Self { + Self { stored: VecDeque::new(), peek_pos: 0, iter } + } + /// Returns the next item after the current one. It doesn't interfer with `peek_next` output. + fn peek(&mut self) -> Option<&(TokenKind, &'a str)> { + if self.stored.is_empty() { + if let Some(next) = self.iter.next() { + self.stored.push_back(next); + } + } + self.stored.front() + } + /// Returns the next item after the last one peeked. It doesn't interfer with `peek` output. + fn peek_next(&mut self) -> Option<&(TokenKind, &'a str)> { + self.peek_pos += 1; + if self.peek_pos - 1 < self.stored.len() { + self.stored.get(self.peek_pos - 1) + } else if let Some(next) = self.iter.next() { + self.stored.push_back(next); + self.stored.back() + } else { + None + } + } +} + +impl Iterator for PeekIter<'a> { + type Item = (TokenKind, &'a str); + fn next(&mut self) -> Option { + self.peek_pos = 0; + if let Some(first) = self.stored.pop_front() { Some(first) } else { self.iter.next() } + } +} + /// Processes program tokens, classifying strings of text by highlighting /// category (`Class`). struct Classifier<'a> { - tokens: Peekable>, + tokens: PeekIter<'a>, in_attribute: bool, in_macro: bool, in_macro_nonterminal: bool, @@ -217,7 +265,7 @@ 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<'_> { - let tokens = TokenIter { src }.peekable(); + let tokens = PeekIter::new(TokenIter { src }); Classifier { tokens, in_attribute: false, @@ -368,7 +416,7 @@ 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 lookahead { + TokenKind::Star => match self.peek() { Some(TokenKind::Whitespace) => Class::Op, _ => Class::RefKeyWord, }, @@ -387,7 +435,27 @@ impl<'a> Classifier<'a> { _ => Class::RefKeyWord, }, - // Operators. + // These can either be operators, or arrows. + TokenKind::Eq => match lookahead { + Some(TokenKind::Eq) => { + self.next(); + sink(Highlight::Token { text: "==", class: Some(Class::Op) }); + return; + } + Some(TokenKind::Gt) => { + self.next(); + sink(Highlight::Token { text: "=>", class: None }); + return; + } + _ => Class::Op, + }, + TokenKind::Minus if lookahead == Some(TokenKind::Gt) => { + self.next(); + sink(Highlight::Token { text: "->", class: None }); + return; + } + + // Other operators. TokenKind::Minus | TokenKind::Plus | TokenKind::Or @@ -395,7 +463,6 @@ impl<'a> Classifier<'a> { | TokenKind::Caret | TokenKind::Percent | TokenKind::Bang - | TokenKind::Eq | TokenKind::Lt | TokenKind::Gt => Class::Op, @@ -479,6 +546,9 @@ impl<'a> Classifier<'a> { None => match text { "Option" | "Result" => Class::PreludeTy, "Some" | "None" | "Ok" | "Err" => Class::PreludeVal, + // "union" is a weak keyword and is only considered as a keyword when declaring + // a union type. + "union" if self.check_if_is_union_keyword() => Class::KeyWord, _ if self.in_macro_nonterminal => { self.in_macro_nonterminal = false; Class::MacroNonTerminal @@ -499,7 +569,17 @@ impl<'a> Classifier<'a> { } fn peek(&mut self) -> Option { - self.tokens.peek().map(|(toke_kind, _text)| *toke_kind) + self.tokens.peek().map(|(token_kind, _text)| *token_kind) + } + + fn check_if_is_union_keyword(&mut self) -> bool { + while let Some(kind) = self.tokens.peek_next().map(|(token_kind, _text)| token_kind) { + if *kind == TokenKind::Whitespace { + continue; + } + return *kind == TokenKind::Ident; + } + false } } @@ -584,6 +664,13 @@ fn string( .ok() .map(|(url, _, _)| url) } + LinkFromSrc::Primitive(prim) => format::href_with_root_path( + PrimitiveType::primitive_locations(context.tcx())[&prim], + context, + Some(context_info.root_path), + ) + .ok() + .map(|(url, _, _)| url), } }) { diff --git a/src/librustdoc/html/highlight/fixtures/sample.html b/src/librustdoc/html/highlight/fixtures/sample.html index 866caea925..22e650af7e 100644 --- a/src/librustdoc/html/highlight/fixtures/sample.html +++ b/src/librustdoc/html/highlight/fixtures/sample.html @@ -13,7 +13,7 @@ use std::path::{Path, PathBuf}; #[cfg(target_os = "linux")] -fn main() { +fn main() -> () { let foo = true && false || true; let _: *const () = 0; let _ = &foo; @@ -27,11 +27,11 @@ let mut s = String::new(); match &s { - ref mut x => {} + ref mut x => {} } } macro_rules! bar { - ($foo:tt) => {}; + ($foo:tt) => {}; } diff --git a/src/librustdoc/html/highlight/fixtures/sample.rs b/src/librustdoc/html/highlight/fixtures/sample.rs index b027203655..fbfdc67673 100644 --- a/src/librustdoc/html/highlight/fixtures/sample.rs +++ b/src/librustdoc/html/highlight/fixtures/sample.rs @@ -3,7 +3,7 @@ use std::path::{Path, PathBuf}; #[cfg(target_os = "linux")] -fn main() { +fn main() -> () { let foo = true && false || true; let _: *const () = 0; let _ = &foo; diff --git a/src/librustdoc/html/highlight/fixtures/union.html b/src/librustdoc/html/highlight/fixtures/union.html new file mode 100644 index 0000000000..c0acf31a05 --- /dev/null +++ b/src/librustdoc/html/highlight/fixtures/union.html @@ -0,0 +1,8 @@ +union Foo { + i: i8, + u: i8, +} + +fn main() { + let union = 0; +} diff --git a/src/librustdoc/html/highlight/fixtures/union.rs b/src/librustdoc/html/highlight/fixtures/union.rs new file mode 100644 index 0000000000..269ee115d3 --- /dev/null +++ b/src/librustdoc/html/highlight/fixtures/union.rs @@ -0,0 +1,8 @@ +union Foo { + i: i8, + u: i8, +} + +fn main() { + let union = 0; +} diff --git a/src/librustdoc/html/highlight/tests.rs b/src/librustdoc/html/highlight/tests.rs index 68592ae96c..450bbfea1e 100644 --- a/src/librustdoc/html/highlight/tests.rs +++ b/src/librustdoc/html/highlight/tests.rs @@ -54,3 +54,13 @@ let y = Self::whatever;"; expect_file!["fixtures/highlight.html"].assert_eq(&html.into_inner()); }); } + +#[test] +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); + expect_file!["fixtures/union.html"].assert_eq(&html.into_inner()); + }); +} diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index 5c0525506d..c46439b851 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -8,11 +8,19 @@ //! extern crate rustc_span; //! //! use rustc_span::edition::Edition; -//! use rustdoc::html::markdown::{IdMap, Markdown, ErrorCodes}; +//! use rustdoc::html::markdown::{HeadingOffset, IdMap, Markdown, ErrorCodes}; //! //! let s = "My *markdown* _text_"; //! let mut id_map = IdMap::new(); -//! let md = Markdown(s, &[], &mut id_map, ErrorCodes::Yes, Edition::Edition2015, &None); +//! let md = Markdown { +//! content: s, +//! links: &[], +//! ids: &mut id_map, +//! error_codes: ErrorCodes::Yes, +//! edition: Edition::Edition2015, +//! playground: &None, +//! heading_offset: HeadingOffset::H2, +//! }; //! let html = md.into_string(); //! // ... something using html //! ``` @@ -47,8 +55,10 @@ use pulldown_cmark::{ #[cfg(test)] mod tests; +const MAX_HEADER_LEVEL: u32 = 6; + /// Options for rendering Markdown in the main body of documentation. -pub(crate) fn opts() -> Options { +pub(crate) fn main_body_opts() -> Options { Options::ENABLE_TABLES | Options::ENABLE_FOOTNOTES | Options::ENABLE_STRIKETHROUGH @@ -56,25 +66,42 @@ pub(crate) fn opts() -> Options { | Options::ENABLE_SMART_PUNCTUATION } -/// A subset of [`opts()`] used for rendering summaries. +/// Options for rendering Markdown in summaries (e.g., in search results). pub(crate) fn summary_opts() -> Options { - Options::ENABLE_STRIKETHROUGH | Options::ENABLE_SMART_PUNCTUATION | Options::ENABLE_TABLES + Options::ENABLE_TABLES + | Options::ENABLE_FOOTNOTES + | Options::ENABLE_STRIKETHROUGH + | Options::ENABLE_TASKLISTS + | Options::ENABLE_SMART_PUNCTUATION +} + +#[derive(Debug, Clone, Copy)] +pub enum HeadingOffset { + H1 = 0, + H2, + H3, + H4, + H5, + H6, } /// When `to_string` is called, this struct will emit the HTML corresponding to /// the rendered version of the contained markdown string. -pub struct Markdown<'a>( - pub &'a str, +pub struct Markdown<'a> { + pub content: &'a str, /// A list of link replacements. - pub &'a [RenderedLink], + pub links: &'a [RenderedLink], /// The current list of used header IDs. - pub &'a mut IdMap, + pub ids: &'a mut IdMap, /// Whether to allow the use of explicit error codes in doctest lang strings. - pub ErrorCodes, + pub error_codes: ErrorCodes, /// Default edition to use when parsing doctests (to add a `fn main`). - pub Edition, - pub &'a Option, -); + pub edition: Edition, + pub playground: &'a Option, + /// Offset at which we render headings. + /// E.g. if `heading_offset: HeadingOffset::H2`, then `# something` renders an `

`. + pub heading_offset: HeadingOffset, +} /// A tuple struct like `Markdown` that renders the markdown with a table of contents. crate struct MarkdownWithToc<'a>( crate &'a str, @@ -441,6 +468,42 @@ impl<'a, I: Iterator>> Iterator for LinkReplacer<'a, I> { } } +/// Wrap HTML tables into `
` to prevent having the doc blocks width being too big. +struct TableWrapper<'a, I: Iterator>> { + inner: I, + stored_events: VecDeque>, +} + +impl<'a, I: Iterator>> TableWrapper<'a, I> { + fn new(iter: I) -> Self { + Self { inner: iter, stored_events: VecDeque::new() } + } +} + +impl<'a, I: Iterator>> Iterator for TableWrapper<'a, I> { + type Item = Event<'a>; + + fn next(&mut self) -> Option { + if let Some(first) = self.stored_events.pop_front() { + return Some(first); + } + + let event = self.inner.next()?; + + Some(match event { + Event::Start(Tag::Table(t)) => { + self.stored_events.push_back(Event::Start(Tag::Table(t))); + Event::Html(CowStr::Borrowed("
")) + } + Event::End(Tag::Table(t)) => { + self.stored_events.push_back(Event::Html(CowStr::Borrowed("
"))); + Event::End(Tag::Table(t)) + } + e => e, + }) + } +} + type SpannedEvent<'a> = (Event<'a>, Range); /// Make headings links with anchor IDs and build up TOC. @@ -449,11 +512,17 @@ struct HeadingLinks<'a, 'b, 'ids, I> { toc: Option<&'b mut TocBuilder>, buf: VecDeque>, id_map: &'ids mut IdMap, + heading_offset: HeadingOffset, } impl<'a, 'b, 'ids, I> HeadingLinks<'a, 'b, 'ids, I> { - fn new(iter: I, toc: Option<&'b mut TocBuilder>, ids: &'ids mut IdMap) -> Self { - HeadingLinks { inner: iter, toc, buf: VecDeque::new(), id_map: ids } + fn new( + iter: I, + toc: Option<&'b mut TocBuilder>, + ids: &'ids mut IdMap, + heading_offset: HeadingOffset, + ) -> Self { + HeadingLinks { inner: iter, toc, buf: VecDeque::new(), id_map: ids, heading_offset } } } @@ -490,6 +559,7 @@ impl<'a, 'b, 'ids, I: Iterator>> Iterator self.buf.push_front((Event::Html(format!("{} ", sec).into()), 0..0)); } + let level = std::cmp::min(level + (self.heading_offset as u32), MAX_HEADER_LEVEL); self.buf.push_back((Event::Html(format!("", level).into()), 0..0)); let start_tags = format!( @@ -692,6 +762,12 @@ crate fn find_testable_code( .join("\n"); nb_lines += doc[prev_offset..offset.start].lines().count(); + // If there are characters between the preceding line ending and + // this code block, `str::lines` will return an additional line, + // which we subtract here. + if nb_lines != 0 && !&doc[prev_offset..offset.start].ends_with('\n') { + nb_lines -= 1; + } let line = tests.get_line() + nb_lines + 1; tests.add_test(text, block_info, line); prev_offset = offset.start; @@ -959,7 +1035,15 @@ impl LangString { impl Markdown<'_> { pub fn into_string(self) -> String { - let Markdown(md, links, mut ids, codes, edition, playground) = self; + let Markdown { + content: md, + links, + mut ids, + error_codes: codes, + edition, + playground, + heading_offset, + } = self; // This is actually common enough to special-case if md.is_empty() { @@ -975,14 +1059,15 @@ impl Markdown<'_> { } }; - let p = Parser::new_with_broken_link_callback(md, opts(), Some(&mut replacer)); + let p = Parser::new_with_broken_link_callback(md, main_body_opts(), Some(&mut replacer)); let p = p.into_offset_iter(); let mut s = String::with_capacity(md.len() * 3 / 2); - let p = HeadingLinks::new(p, None, &mut ids); + let p = HeadingLinks::new(p, None, &mut ids, heading_offset); let p = Footnotes::new(p); let p = LinkReplacer::new(p.map(|(ev, _)| ev), links); + let p = TableWrapper::new(p); let p = CodeBlocks::new(p, codes, edition, playground); html::push_html(&mut s, p); @@ -994,16 +1079,17 @@ impl MarkdownWithToc<'_> { crate fn into_string(self) -> String { let MarkdownWithToc(md, mut ids, codes, edition, playground) = self; - let p = Parser::new_ext(md, opts()).into_offset_iter(); + let p = Parser::new_ext(md, main_body_opts()).into_offset_iter(); let mut s = String::with_capacity(md.len() * 3 / 2); let mut toc = TocBuilder::new(); { - let p = HeadingLinks::new(p, Some(&mut toc), &mut ids); + let p = HeadingLinks::new(p, Some(&mut toc), &mut ids, HeadingOffset::H1); let p = Footnotes::new(p); - let p = CodeBlocks::new(p.map(|(ev, _)| ev), codes, edition, playground); + let p = TableWrapper::new(p.map(|(ev, _)| ev)); + let p = CodeBlocks::new(p, codes, edition, playground); html::push_html(&mut s, p); } @@ -1019,7 +1105,7 @@ impl MarkdownHtml<'_> { if md.is_empty() { return String::new(); } - let p = Parser::new_ext(md, opts()).into_offset_iter(); + let p = Parser::new_ext(md, main_body_opts()).into_offset_iter(); // Treat inline HTML as plain text. let p = p.map(|event| match event.0 { @@ -1029,9 +1115,10 @@ impl MarkdownHtml<'_> { let mut s = String::with_capacity(md.len() * 3 / 2); - let p = HeadingLinks::new(p, None, &mut ids); + let p = HeadingLinks::new(p, None, &mut ids, HeadingOffset::H1); let p = Footnotes::new(p); - let p = CodeBlocks::new(p.map(|(ev, _)| ev), codes, edition, playground); + let p = TableWrapper::new(p.map(|(ev, _)| ev)); + let p = CodeBlocks::new(p, codes, edition, playground); html::push_html(&mut s, p); s @@ -1093,7 +1180,7 @@ fn markdown_summary_with_limit( } }; - let p = Parser::new_with_broken_link_callback(md, opts(), Some(&mut replacer)); + let p = Parser::new_with_broken_link_callback(md, summary_opts(), Some(&mut replacer)); let mut p = LinkReplacer::new(p, link_names); let mut buf = HtmlWithLimit::new(length_limit); @@ -1240,12 +1327,13 @@ crate fn markdown_links(md: &str) -> Vec { }); None }; - let p = Parser::new_with_broken_link_callback(md, opts(), Some(&mut push)).into_offset_iter(); + let p = Parser::new_with_broken_link_callback(md, main_body_opts(), Some(&mut push)) + .into_offset_iter(); // There's no need to thread an IdMap through to here because // the IDs generated aren't going to be emitted anywhere. let mut ids = IdMap::new(); - let iter = Footnotes::new(HeadingLinks::new(p, None, &mut ids)); + let iter = Footnotes::new(HeadingLinks::new(p, None, &mut ids, HeadingOffset::H1)); for ev in iter { if let Event::Start(Tag::Link(kind, dest, _)) = ev.0 { @@ -1278,7 +1366,7 @@ crate fn rust_code_blocks(md: &str, extra_info: &ExtraInfo<'_>) -> VecFoo bar

", + "

Foo bar

", ); t( "## Foo-bar_baz qux", - "

\ - Foo-bar_baz qux

", + "

\ + Foo-bar_baz qux

", ); t( "### **Foo** *bar* baz!?!& -_qux_-%", - "

\ + "

\ Foo \ bar baz!?!& -qux-%\ -

", + ", ); t( "#### **Foo?** & \\*bar?!* _`baz`_ ❤ #qux", - "

\ + "

\ Foo? & *bar?!* \ baz ❤ #qux\ -
", + ", ); } @@ -181,40 +189,48 @@ fn test_header() { fn test_header_ids_multiple_blocks() { let mut map = IdMap::new(); fn t(map: &mut IdMap, input: &str, expect: &str) { - let output = - Markdown(input, &[], map, ErrorCodes::Yes, DEFAULT_EDITION, &None).into_string(); + let output = Markdown { + content: input, + links: &[], + ids: map, + error_codes: ErrorCodes::Yes, + edition: DEFAULT_EDITION, + playground: &None, + heading_offset: HeadingOffset::H2, + } + .into_string(); assert_eq!(output, expect, "original: {}", input); } t( &mut map, "# Example", - "

Example

", + "

Example

", ); t( &mut map, "# Panics", - "

Panics

", + "

Panics

", ); t( &mut map, "# Example", - "

Example

", + "

Example

", ); t( &mut map, "# Main", - "

Main

", + "

Main

", ); t( &mut map, "# Example", - "

Example

", + "

Example

", ); t( &mut map, "# Panics", - "

Panics

", + "

Panics

", ); } @@ -300,3 +316,25 @@ fn test_markdown_html_escape() { t("Struct<'a, T>", "

Struct<’a, T>

\n"); t("Struct
", "

Struct<br>

\n"); } + +#[test] +fn test_find_testable_code_line() { + fn t(input: &str, expect: &[usize]) { + impl crate::doctest::Tester for Vec { + fn add_test(&mut self, _test: String, _config: LangString, line: usize) { + self.push(line); + } + } + let mut lines = Vec::::new(); + find_testable_code(input, &mut lines, ErrorCodes::No, false, None); + assert_eq!(lines, expect); + } + + t("", &[]); + t("```rust\n```", &[1]); + t(" ```rust\n```", &[1]); + t("\n```rust\n```", &[2]); + t("\n ```rust\n```", &[2]); + t("```rust\n```\n```rust\n```", &[1, 3]); + t("```rust\n```\n ```rust\n```", &[1, 3]); +} diff --git a/src/librustdoc/html/render/cache.rs b/src/librustdoc/html/render/cache.rs index 1c083522be..9c05c80d55 100644 --- a/src/librustdoc/html/render/cache.rs +++ b/src/librustdoc/html/render/cache.rs @@ -226,16 +226,13 @@ fn get_index_type(clean_type: &clean::Type) -> RenderType { fn get_index_type_name(clean_type: &clean::Type, accept_generic: bool) -> Option { match *clean_type { clean::ResolvedPath { ref path, .. } => { - let segments = &path.segments; - let path_segment = segments.iter().last().unwrap_or_else(|| { - panic!( - "get_index_type_name(clean_type: {:?}, accept_generic: {:?}) had length zero path", - clean_type, accept_generic - ) - }); + let path_segment = path.segments.last().unwrap(); Some(path_segment.name) } - clean::DynTrait(ref bounds, _) => get_index_type_name(&bounds[0].trait_, accept_generic), + clean::DynTrait(ref bounds, _) => { + let path = &bounds[0].trait_; + Some(path.segments.last().unwrap().name) + } clean::Generic(s) if accept_generic => Some(s), clean::Primitive(ref p) => Some(p.as_sym()), clean::BorrowedRef { ref type_, .. } => get_index_type_name(type_, accept_generic), @@ -244,7 +241,6 @@ fn get_index_type_name(clean_type: &clean::Type, accept_generic: bool) -> Option | clean::Tuple(_) | clean::Slice(_) | clean::Array(_, _) - | clean::Never | clean::RawPointer(_, _) | clean::QPath { .. } | clean::Infer @@ -325,7 +321,8 @@ crate fn get_real_types<'tcx>( } if let Some(bound) = generics.params.iter().find(|g| g.is_type() && g.name == arg_s) { for bound in bound.get_bounds().unwrap_or(&[]) { - if let Some(ty) = bound.get_trait_type() { + 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() { diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs index 733bedfdde..011d3cfcf7 100644 --- a/src/librustdoc/html/render/context.rs +++ b/src/librustdoc/html/render/context.rs @@ -1,6 +1,5 @@ use std::cell::RefCell; use std::collections::BTreeMap; -use std::error::Error as StdError; use std::io; use std::path::{Path, PathBuf}; use std::rc::Rc; @@ -16,6 +15,7 @@ use rustc_span::symbol::sym; use super::cache::{build_index, ExternalLocation}; use super::print_item::{full_path, item_path, print_item}; +use super::templates; use super::write_shared::write_shared; use super::{ collect_spans_and_sources, print_sidebar, settings, AllTypes, LinkFromSrc, NameDoc, StylePath, @@ -33,7 +33,6 @@ use crate::formats::FormatRenderer; use crate::html::escape::Escape; use crate::html::format::Buffer; use crate::html::markdown::{self, plain_text_summary, ErrorCodes, IdMap}; -use crate::html::static_files::PAGE; use crate::html::{layout, sources}; /// Major driving force in all rustdoc rendering. This contains information @@ -69,7 +68,7 @@ crate struct Context<'tcx> { } // `Context` is cloned a lot, so we don't want the size to grow unexpectedly. -#[cfg(target_arch = "x86_64")] +#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] rustc_data_structures::static_assert_size!(Context<'_>, 104); /// Shared mutable state used in [`Context`] and elsewhere. @@ -225,7 +224,7 @@ impl<'tcx> Context<'tcx> { &self.shared.layout, &page, |buf: &mut _| print_sidebar(self, it, buf), - |buf: &mut _| print_item(self, it, buf, &page), + |buf: &mut _| print_item(self, &self.shared.templates, it, buf, &page), &self.shared.style_files, ) } else { @@ -416,12 +415,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { }; let mut issue_tracker_base_url = None; let mut include_sources = true; - - let mut templates = tera::Tera::default(); - templates.add_raw_template("page.html", PAGE).map_err(|e| Error { - file: "page.html".into(), - error: format!("{}: {}", e, e.source().map(|e| e.to_string()).unwrap_or_default()), - })?; + let templates = templates::load()?; // Crawl the crate attributes looking for attributes which control how we're // going to emit HTML @@ -574,7 +568,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { |buf: &mut Buffer| all.print(buf), &self.shared.style_files, ); - self.shared.fs.write(final_file, v.as_bytes())?; + self.shared.fs.write(final_file, v)?; // Generating settings page. page.title = "Rustdoc settings"; @@ -596,14 +590,14 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { )?, &style_files, ); - self.shared.fs.write(&settings_file, v.as_bytes())?; + self.shared.fs.write(settings_file, v)?; if let Some(ref redirections) = self.shared.redirections { if !redirections.borrow().is_empty() { let redirect_map_path = self.dst.join(&*crate_name.as_str()).join("redirect-map.json"); let paths = serde_json::to_string(&*redirections.borrow()).unwrap(); self.shared.ensure_dir(&self.dst.join(&*crate_name.as_str()))?; - self.shared.fs.write(&redirect_map_path, paths.as_bytes())?; + self.shared.fs.write(redirect_map_path, paths)?; } } @@ -641,7 +635,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { if !buf.is_empty() { self.shared.ensure_dir(&self.dst)?; let joint_dst = self.dst.join("index.html"); - scx.fs.write(&joint_dst, buf.as_bytes())?; + scx.fs.write(joint_dst, buf)?; } // Render sidebar-items.js used throughout this module. @@ -653,7 +647,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { let items = self.build_sidebar_items(module); let js_dst = self.dst.join("sidebar-items.js"); let v = format!("initSidebarItems({});", serde_json::to_string(&items).unwrap()); - scx.fs.write(&js_dst, &v)?; + scx.fs.write(js_dst, v)?; } Ok(()) } @@ -687,7 +681,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { let file_name = &item_path(item_type, &name.as_str()); self.shared.ensure_dir(&self.dst)?; let joint_dst = self.dst.join(file_name); - self.shared.fs.write(&joint_dst, buf.as_bytes())?; + self.shared.fs.write(joint_dst, buf)?; if !self.render_redirect_pages { self.shared.all.borrow_mut().append(full_path(self, &item), &item_type); @@ -705,7 +699,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { } else { let v = layout::redirect(file_name); let redir_dst = self.dst.join(redir_name); - self.shared.fs.write(&redir_dst, v.as_bytes())?; + self.shared.fs.write(redir_dst, v)?; } } } diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 172fe5d164..2898da1cbf 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -31,6 +31,7 @@ mod tests; mod context; mod print_item; mod span_map; +mod templates; mod write_shared; crate use context::*; @@ -51,6 +52,7 @@ use rustc_hir::def::CtorKind; use rustc_hir::def_id::DefId; use rustc_hir::Mutability; use rustc_middle::middle::stability; +use rustc_middle::ty::TyCtxt; use rustc_span::symbol::{kw, sym, Symbol}; use serde::ser::SerializeSeq; use serde::{Serialize, Serializer}; @@ -66,7 +68,7 @@ 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::markdown::{Markdown, MarkdownHtml, MarkdownSummaryLine}; +use crate::html::markdown::{HeadingOffset, Markdown, MarkdownHtml, MarkdownSummaryLine}; /// A pair of name and its optional document. crate type NameDoc = (String, Option); @@ -224,7 +226,6 @@ struct AllTypes { opaque_tys: FxHashSet, statics: FxHashSet, constants: FxHashSet, - keywords: FxHashSet, attributes: FxHashSet, derives: FxHashSet, trait_aliases: FxHashSet, @@ -245,7 +246,6 @@ impl AllTypes { opaque_tys: new_set(100), statics: new_set(100), constants: new_set(100), - keywords: new_set(100), attributes: new_set(100), derives: new_set(100), trait_aliases: new_set(100), @@ -471,32 +471,45 @@ fn settings(root_path: &str, suffix: &str, themes: &[StylePath]) -> Result, item: &clean::Item, parent: Option<&clean::Item>) { +fn document( + w: &mut Buffer, + cx: &Context<'_>, + item: &clean::Item, + parent: Option<&clean::Item>, + heading_offset: HeadingOffset, +) { if let Some(ref name) = item.name { info!("Documenting {}", name); } document_item_info(w, cx, item, parent); if parent.is_none() { - document_full_collapsible(w, item, cx); + document_full_collapsible(w, item, cx, heading_offset); } else { - document_full(w, item, cx); + document_full(w, item, cx, heading_offset); } } /// Render md_text as markdown. -fn render_markdown(w: &mut Buffer, cx: &Context<'_>, md_text: &str, links: Vec) { +fn render_markdown( + w: &mut Buffer, + cx: &Context<'_>, + md_text: &str, + links: Vec, + heading_offset: HeadingOffset, +) { let mut ids = cx.id_map.borrow_mut(); write!( w, "
{}
", - Markdown( - md_text, - &links, - &mut ids, - cx.shared.codes, - cx.shared.edition(), - &cx.shared.playground - ) + Markdown { + content: md_text, + links: &links, + ids: &mut ids, + error_codes: cx.shared.codes, + edition: cx.shared.edition(), + playground: &cx.shared.playground, + heading_offset, + } .into_string() ) } @@ -532,15 +545,31 @@ fn document_short( } } -fn document_full_collapsible(w: &mut Buffer, item: &clean::Item, cx: &Context<'_>) { - document_full_inner(w, item, cx, true); +fn document_full_collapsible( + w: &mut Buffer, + item: &clean::Item, + cx: &Context<'_>, + heading_offset: HeadingOffset, +) { + document_full_inner(w, item, cx, true, heading_offset); } -fn document_full(w: &mut Buffer, item: &clean::Item, cx: &Context<'_>) { - document_full_inner(w, item, cx, false); +fn document_full( + w: &mut Buffer, + item: &clean::Item, + cx: &Context<'_>, + heading_offset: HeadingOffset, +) { + document_full_inner(w, item, cx, false, heading_offset); } -fn document_full_inner(w: &mut Buffer, item: &clean::Item, cx: &Context<'_>, is_collapsible: bool) { +fn document_full_inner( + w: &mut Buffer, + item: &clean::Item, + cx: &Context<'_>, + is_collapsible: bool, + heading_offset: HeadingOffset, +) { if let Some(s) = cx.shared.maybe_collapsed_doc_value(item) { debug!("Doc block: =====\n{}\n=====", s); if is_collapsible { @@ -550,10 +579,10 @@ fn document_full_inner(w: &mut Buffer, item: &clean::Item, cx: &Context<'_>, is_ Expand description\ ", ); - render_markdown(w, cx, &s, item.links(cx)); + render_markdown(w, cx, &s, item.links(cx), heading_offset); w.write_str(""); } else { - render_markdown(w, cx, &s, item.links(cx)); + render_markdown(w, cx, &s, item.links(cx), heading_offset); } } } @@ -600,14 +629,14 @@ fn short_item_info( let mut extra_info = vec![]; let error_codes = cx.shared.codes; - if let Some(Deprecation { note, since, is_since_rustc_version, suggestion: _ }) = + if let Some(depr @ Deprecation { note, since, is_since_rustc_version: _, suggestion: _ }) = item.deprecation(cx.tcx()) { // We display deprecation messages for #[deprecated] and #[rustc_deprecated] // but only display the future-deprecation messages for #[rustc_deprecated]. let mut message = if let Some(since) = since { let since = &since.as_str(); - if !stability::deprecation_in_effect(is_since_rustc_version, Some(since)) { + if !stability::deprecation_in_effect(&depr) { if *since == "TBD" { String::from("Deprecating in a future Rust version") } else { @@ -688,18 +717,12 @@ fn short_item_info( // Render the list of items inside one of the sections "Trait Implementations", // "Auto Trait Implementations," "Blanket Trait Implementations" (on struct/enum pages). -fn render_impls( - cx: &Context<'_>, - w: &mut Buffer, - traits: &[&&Impl], - containing_item: &clean::Item, -) { - let cache = cx.cache(); +fn render_impls(cx: &Context<'_>, w: &mut Buffer, impls: &[&&Impl], containing_item: &clean::Item) { let tcx = cx.tcx(); - let mut impls = traits + let mut rendered_impls = impls .iter() .map(|i| { - let did = i.trait_did_full(cache).unwrap(); + let did = i.trait_did().unwrap(); let provided_trait_methods = i.inner_impl().provided_trait_methods(tcx); let assoc_link = AssocItemLink::GotoSource(did.into(), &provided_trait_methods); let mut buffer = if w.is_for_html() { Buffer::html() } else { Buffer::new() }; @@ -723,8 +746,8 @@ fn render_impls( buffer.into_inner() }) .collect::>(); - impls.sort(); - w.write_str(&impls.join("")); + rendered_impls.sort(); + w.write_str(&rendered_impls.join("")); } fn naive_assoc_href(it: &clean::Item, link: AssocItemLink<'_>, cx: &Context<'_>) -> String { @@ -1069,13 +1092,11 @@ fn render_assoc_items( return; } if !traits.is_empty() { - let deref_impl = traits - .iter() - .find(|t| t.inner_impl().trait_.def_id_full(cache) == cache.deref_trait_did); + 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.inner_impl().trait_.def_id_full(cache) == cache.deref_mut_trait_did); + 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); } let (synthetic, concrete): (Vec<&&Impl>, Vec<&&Impl>) = @@ -1165,7 +1186,7 @@ fn render_deref_methods( } } -fn should_render_item(item: &clean::Item, deref_mut_: bool, cache: &Cache) -> bool { +fn should_render_item(item: &clean::Item, deref_mut_: bool, tcx: TyCtxt<'_>) -> bool { let self_type_opt = match *item.kind { clean::MethodItem(ref method, _) => method.decl.self_type(), clean::TyMethodItem(ref method) => method.decl.self_type(), @@ -1179,7 +1200,7 @@ fn should_render_item(item: &clean::Item, deref_mut_: bool, cache: &Cache) -> bo (mutability == Mutability::Mut, false, false) } SelfTy::SelfExplicit(clean::ResolvedPath { did, .. }) => { - (false, Some(did) == cache.owned_box_did, false) + (false, Some(did) == tcx.lang_items().owned_box(), false) } SelfTy::SelfValue => (false, false, true), _ => (false, false, false), @@ -1193,45 +1214,39 @@ fn should_render_item(item: &clean::Item, deref_mut_: bool, cache: &Cache) -> bo fn notable_traits_decl(decl: &clean::FnDecl, cx: &Context<'_>) -> String { let mut out = Buffer::html(); - let mut trait_ = String::new(); if let Some(did) = decl.output.def_id_full(cx.cache()) { if let Some(impls) = cx.cache().impls.get(&did) { for i in impls { let impl_ = i.inner_impl(); - if impl_.trait_.def_id().map_or(false, |d| { - cx.cache().traits.get(&d).map(|t| t.is_notable).unwrap_or(false) - }) { - if out.is_empty() { + if let Some(trait_) = &impl_.trait_ { + let trait_did = trait_.def_id(); + + if cx.cache().traits.get(&trait_did).map_or(false, |t| t.is_notable) { + if out.is_empty() { + write!( + &mut out, + "
Notable traits for {}
\ + ", + impl_.for_.print(cx) + ); + } + + //use the "where" class here to make it small write!( &mut out, - "
Notable traits for {}
\ - ", - impl_.for_.print(cx) + "{}", + impl_.print(false, cx) ); - trait_.push_str(&impl_.for_.print(cx).to_string()); - } - - //use the "where" class here to make it small - write!( - &mut out, - "{}", - impl_.print(false, cx) - ); - let t_did = impl_.trait_.def_id_full(cx.cache()).unwrap(); - for it in &impl_.items { - if let clean::TypedefItem(ref tydef, _) = *it.kind { - out.push_str(" "); - assoc_type( - &mut out, - it, - &[], - Some(&tydef.type_), - AssocItemLink::GotoSource(t_did.into(), &FxHashSet::default()), - "", - cx, - ); - out.push_str(";"); + for it in &impl_.items { + if let clean::TypedefItem(ref tydef, _) = *it.kind { + out.push_str(" "); + let empty_set = FxHashSet::default(); + let src_link = + AssocItemLink::GotoSource(trait_did.into(), &empty_set); + assoc_type(&mut out, it, &[], Some(&tydef.type_), src_link, "", cx); + out.push_str(";"); + } } } } @@ -1274,7 +1289,7 @@ fn render_impl( ) { let cache = cx.cache(); let traits = &cache.traits; - let trait_ = i.trait_did_full(cache).map(|did| &traits[&did]); + let trait_ = i.trait_did().map(|did| &traits[&did]); let mut close_tags = String::new(); // For trait implementations, the `interesting` output contains all methods that have doc @@ -1302,7 +1317,7 @@ fn render_impl( && match render_mode { RenderMode::Normal => true, RenderMode::ForDeref { mut_: deref_mut_ } => { - should_render_item(&item, deref_mut_, cx.cache()) + should_render_item(&item, deref_mut_, cx.tcx()) } }; @@ -1322,7 +1337,7 @@ fn render_impl( // because impls can't have a stability. if item.doc_value().is_some() { document_item_info(&mut info_buffer, cx, it, Some(parent)); - document_full(&mut doc_buffer, item, cx); + document_full(&mut doc_buffer, item, cx, HeadingOffset::H5); short_documented = false; } else { // In case the item isn't documented, @@ -1340,7 +1355,7 @@ fn render_impl( } else { document_item_info(&mut info_buffer, cx, item, Some(parent)); if rendering_params.show_def_docs { - document_full(&mut doc_buffer, item, cx); + document_full(&mut doc_buffer, item, cx, HeadingOffset::H5); short_documented = false; } } @@ -1504,7 +1519,7 @@ fn render_impl( if i.items.iter().any(|m| m.name == n) { continue; } - let did = i.trait_.as_ref().unwrap().def_id_full(cx.cache()).unwrap(); + let did = i.trait_.as_ref().unwrap().def_id(); let provided_methods = i.provided_trait_methods(cx.tcx()); let assoc_link = AssocItemLink::GotoSource(did.into(), &provided_methods); @@ -1574,14 +1589,15 @@ fn render_impl( write!( w, "
{}
", - Markdown( - &*dox, - &i.impl_item.links(cx), - &mut ids, - cx.shared.codes, - cx.shared.edition(), - &cx.shared.playground - ) + Markdown { + content: &*dox, + links: &i.impl_item.links(cx), + ids: &mut ids, + error_codes: cx.shared.codes, + edition: cx.shared.edition(), + playground: &cx.shared.playground, + heading_offset: HeadingOffset::H4 + } .into_string() ); } @@ -1795,23 +1811,53 @@ fn get_next_url(used_links: &mut FxHashSet, url: String) -> String { format!("{}-{}", url, add) } +struct SidebarLink { + name: Symbol, + url: String, +} + +impl fmt::Display for SidebarLink { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", self.url, self.name) + } +} + +impl PartialEq for SidebarLink { + fn eq(&self, other: &Self) -> bool { + self.url == other.url + } +} + +impl Eq for SidebarLink {} + +impl PartialOrd for SidebarLink { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl Ord for SidebarLink { + fn cmp(&self, other: &Self) -> std::cmp::Ordering { + self.url.cmp(&other.url) + } +} + fn get_methods( i: &clean::Impl, for_deref: bool, used_links: &mut FxHashSet, deref_mut: bool, - cache: &Cache, -) -> Vec { + tcx: TyCtxt<'_>, +) -> Vec { i.items .iter() .filter_map(|item| match item.name { - Some(ref name) if !name.is_empty() && item.is_method() => { - if !for_deref || should_render_item(item, deref_mut, cache) { - Some(format!( - "{}", - get_next_url(used_links, format!("method.{}", name)), - name - )) + Some(name) if !name.is_empty() && item.is_method() => { + if !for_deref || should_render_item(item, deref_mut, tcx) { + Some(SidebarLink { + name, + url: get_next_url(used_links, format!("method.{}", name)), + }) } else { None } @@ -1821,6 +1867,22 @@ fn get_methods( .collect::>() } +fn get_associated_constants( + i: &clean::Impl, + used_links: &mut FxHashSet, +) -> Vec { + i.items + .iter() + .filter_map(|item| match item.name { + Some(name) if !name.is_empty() && item.is_associated_const() => Some(SidebarLink { + name, + url: get_next_url(used_links, format!("associatedconstant.{}", name)), + }), + _ => None, + }) + .collect::>() +} + // The point is to url encode any potential character from a type with genericity. fn small_url_encode(s: String) -> String { let mut st = String::new(); @@ -1865,31 +1927,48 @@ fn sidebar_assoc_items(cx: &Context<'_>, out: &mut Buffer, it: &clean::Item) { { let used_links_bor = &mut used_links; - let mut ret = v + let mut assoc_consts = v + .iter() + .flat_map(|i| get_associated_constants(i.inner_impl(), used_links_bor)) + .collect::>(); + if !assoc_consts.is_empty() { + // We want links' order to be reproducible so we don't use unstable sort. + assoc_consts.sort(); + + out.push_str( + "

\ + Associated Constants\ +

\ +
", + ); + for line in assoc_consts { + write!(out, "{}", line); + } + out.push_str("
"); + } + let mut methods = v .iter() .filter(|i| i.inner_impl().trait_.is_none()) - .flat_map(move |i| get_methods(i.inner_impl(), false, used_links_bor, false, cache)) + .flat_map(|i| get_methods(i.inner_impl(), false, used_links_bor, false, cx.tcx())) .collect::>(); - if !ret.is_empty() { + if !methods.is_empty() { // We want links' order to be reproducible so we don't use unstable sort. - ret.sort(); + methods.sort(); out.push_str( "

Methods

\
", ); - for line in ret { - out.push_str(&line); + for line in methods { + write!(out, "{}", line); } out.push_str("
"); } } if v.iter().any(|i| i.inner_impl().trait_.is_some()) { - if let Some(impl_) = v - .iter() - .filter(|i| i.inner_impl().trait_.is_some()) - .find(|i| i.inner_impl().trait_.def_id_full(cache) == cache.deref_trait_did) + if let Some(impl_) = + v.iter().find(|i| i.trait_did() == cx.tcx().lang_items().deref_trait()) { sidebar_deref_methods(cx, out, impl_, v); } @@ -1988,10 +2067,7 @@ fn sidebar_deref_methods(cx: &Context<'_>, out: &mut Buffer, impl_: &Impl, v: &V } } } - let deref_mut = v - .iter() - .filter(|i| i.inner_impl().trait_.is_some()) - .any(|i| i.inner_impl().trait_.def_id_full(c) == c.deref_mut_trait_did); + 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) .or_else(|| { @@ -2004,7 +2080,9 @@ fn sidebar_deref_methods(cx: &Context<'_>, out: &mut Buffer, impl_: &Impl, v: &V let mut ret = impls .iter() .filter(|i| i.inner_impl().trait_.is_none()) - .flat_map(|i| get_methods(i.inner_impl(), true, &mut used_links, deref_mut, c)) + .flat_map(|i| { + get_methods(i.inner_impl(), true, &mut used_links, deref_mut, cx.tcx()) + }) .collect::>(); if !ret.is_empty() { write!( @@ -2017,7 +2095,7 @@ fn sidebar_deref_methods(cx: &Context<'_>, out: &mut Buffer, impl_: &Impl, v: &V ret.sort(); out.push_str("
"); for link in ret { - out.push_str(&link); + write!(out, "{}", link); } out.push_str("
"); } @@ -2056,10 +2134,10 @@ fn sidebar_struct(cx: &Context<'_>, buf: &mut Buffer, it: &clean::Item, s: &clea fn get_id_for_impl_on_foreign_type( for_: &clean::Type, - trait_: &clean::Type, + trait_: &clean::Path, cx: &Context<'_>, ) -> String { - small_url_encode(format!("impl-{:#}-for-{:#}", trait_.print(cx), for_.print(cx),)) + small_url_encode(format!("impl-{:#}-for-{:#}", trait_.print(cx), for_.print(cx))) } fn extract_for_impl_name(item: &clean::Item, cx: &Context<'_>) -> Option<(String, String)> { @@ -2370,6 +2448,15 @@ fn collect_paths_for_type(first_ty: clean::Type, cache: &Cache) -> Vec { let mut visited = FxHashSet::default(); let mut work = VecDeque::new(); + let mut process_path = |did: DefId| { + let get_extern = || cache.external_paths.get(&did).map(|s| s.0.clone()); + let fqp = cache.exact_paths.get(&did).cloned().or_else(get_extern); + + if let Some(path) = fqp { + out.push(path.join("::")); + } + }; + work.push_back(first_ty); while let Some(ty) = work.pop_front() { @@ -2378,14 +2465,7 @@ fn collect_paths_for_type(first_ty: clean::Type, cache: &Cache) -> Vec { } match ty { - clean::Type::ResolvedPath { did, .. } => { - let get_extern = || cache.external_paths.get(&did).map(|s| s.0.clone()); - let fqp = cache.exact_paths.get(&did).cloned().or_else(get_extern); - - if let Some(path) = fqp { - out.push(path.join("::")); - } - } + clean::Type::ResolvedPath { did, .. } => process_path(did), clean::Type::Tuple(tys) => { work.extend(tys.into_iter()); } @@ -2403,7 +2483,7 @@ fn collect_paths_for_type(first_ty: clean::Type, cache: &Cache) -> Vec { } clean::Type::QPath { self_type, trait_, .. } => { work.push_back(*self_type); - work.push_back(*trait_); + process_path(trait_.def_id()); } _ => {} } diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index 0001b73ef7..739ea35dc3 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -8,10 +8,12 @@ use rustc_hir as hir; use rustc_hir::def::CtorKind; use rustc_hir::def_id::DefId; use rustc_middle::middle::stability; +use rustc_middle::span_bug; use rustc_middle::ty::layout::LayoutError; -use rustc_middle::ty::TyCtxt; +use rustc_middle::ty::{Adt, TyCtxt}; use rustc_span::hygiene::MacroKind; use rustc_span::symbol::{kw, sym, Symbol}; +use rustc_target::abi::{Layout, Primitive, TagEncoding, Variants}; use super::{ collect_paths_for_type, document, ensure_trailing_slash, item_ty_to_strs, notable_traits_decl, @@ -28,16 +30,43 @@ use crate::html::format::{ }; use crate::html::highlight; use crate::html::layout::Page; -use crate::html::markdown::MarkdownSummaryLine; +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 = "
"; -pub(super) fn print_item(cx: &Context<'_>, item: &clean::Item, buf: &mut Buffer, page: &Page<'_>) { +// A component in a `use` path, like `string` in std::string::ToString +#[derive(Serialize)] +struct PathComponent<'a> { + path: String, + name: &'a str, +} + +#[derive(Serialize)] +struct ItemVars<'a> { + page: &'a Page<'a>, + static_root_path: &'a str, + typ: &'a str, + name: &'a str, + item_type: &'a str, + path_components: Vec>, + stability_since_raw: &'a str, + src_href: Option<&'a str>, +} + +pub(super) fn print_item( + cx: &Context<'_>, + templates: &tera::Tera, + item: &clean::Item, + buf: &mut Buffer, + page: &Page<'_>, +) { debug_assert!(!item.is_stripped()); - // Write the breadcrumb trail header for the top - buf.write_str("

"); - let name = match *item.kind { + let typ = match *item.kind { clean::ModuleItem(_) => { if item.is_crate() { "Crate " @@ -69,48 +98,15 @@ pub(super) fn print_item(cx: &Context<'_>, item: &clean::Item, buf: &mut Buffer, unreachable!(); } }; - buf.write_str(name); - if !item.is_primitive() && !item.is_keyword() { - let cur = &cx.current; - let amt = if item.is_mod() { cur.len() - 1 } else { cur.len() }; - for (i, component) in cur.iter().enumerate().take(amt) { - write!( - buf, - "{}::", - "../".repeat(cur.len() - i - 1), - component - ); - } - } - write!(buf, "{}", item.type_(), item.name.as_ref().unwrap()); - write!( - buf, - "", - static_root_path = page.get_static_root_path(), - suffix = page.resource_suffix, - ); - - buf.write_str(""); // in-band - buf.write_str(""); + let mut stability_since_raw = Buffer::new(); render_stability_since_raw( - buf, + &mut stability_since_raw, item.stable_since(cx.tcx()).as_deref(), item.const_stability(cx.tcx()), None, None, ); - buf.write_str( - "\ - \ - []\ - \ - ", - ); + let stability_since_raw: String = stability_since_raw.into_inner(); // Write `src` tag // @@ -118,11 +114,38 @@ pub(super) fn print_item(cx: &Context<'_>, item: &clean::Item, buf: &mut Buffer, // [src] link in the downstream documentation will actually come back to // this page, and this link will be auto-clicked. The `id` attribute is // used to find the link to auto-click. - if cx.include_sources && !item.is_primitive() { - write_srclink(cx, item, buf); - } + let src_href = + if cx.include_sources && !item.is_primitive() { cx.src_href(item) } else { None }; - buf.write_str("

"); // out-of-band + let path_components = if item.is_primitive() || item.is_keyword() { + vec![] + } else { + let cur = &cx.current; + let amt = if item.is_mod() { cur.len() - 1 } else { cur.len() }; + cur.iter() + .enumerate() + .take(amt) + .map(|(i, component)| PathComponent { + path: "../".repeat(cur.len() - i - 1), + name: component, + }) + .collect() + }; + + let item_vars = ItemVars { + page: page, + static_root_path: page.get_static_root_path(), + typ: typ, + name: &item.name.as_ref().unwrap().as_str(), + item_type: &item.type_().to_string(), + path_components: path_components, + stability_since_raw: &stability_since_raw, + src_href: src_href.as_deref(), + }; + + let teractx = tera::Context::from_serialize(item_vars).unwrap(); + let heading = templates.render("print_item.html", &teractx).unwrap(); + buf.write_str(&heading); match *item.kind { clean::ModuleItem(ref m) => item_module(buf, cx, item, &m.items), @@ -171,7 +194,7 @@ fn toggle_close(w: &mut Buffer) { } fn item_module(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, items: &[clean::Item]) { - document(w, cx, item, None); + document(w, cx, item, None, HeadingOffset::H2); let mut indices = (0..items.len()).filter(|i| !items[*i].is_stripped()).collect::>(); @@ -254,9 +277,6 @@ fn item_module(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, items: &[cl debug!("{:?}", indices); let mut curty = None; - // See: https://github.com/rust-lang/rust/issues/88545 - let item_table_block_size = 900usize; - let mut item_table_nth_element = 0usize; for &idx in &indices { let myitem = &items[idx]; @@ -277,18 +297,19 @@ fn item_module(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, items: &[cl write!( w, "

\ - {name}

\n{}", + {name}\ + \n{}", ITEM_TABLE_OPEN, id = cx.derive_id(short.to_owned()), name = name ); - item_table_nth_element = 0; } match *myitem.kind { clean::ExternCrateItem { ref src } => { use crate::html::format::anchor; + w.write_str(ITEM_TABLE_ROW_OPEN); match *src { Some(ref src) => write!( w, @@ -309,6 +330,7 @@ fn item_module(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, items: &[cl ), } w.write_str("
"); + w.write_str(ITEM_TABLE_ROW_CLOSE); } clean::ImportItem(ref import) => { @@ -320,7 +342,7 @@ fn item_module(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, items: &[cl let import_item = clean::Item { def_id: import_def_id.into(), attrs: import_attrs, - cfg: ast_attrs.cfg(cx.sess()), + cfg: ast_attrs.cfg(cx.tcx(), &cx.cache().hidden_cfg), ..myitem.clone() }; @@ -333,6 +355,7 @@ fn item_module(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, items: &[cl let add = if stab.is_some() { " " } else { "" }; + w.write_str(ITEM_TABLE_ROW_OPEN); write!( w, "
\ @@ -345,6 +368,7 @@ fn item_module(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, items: &[cl imp = import.print(cx), stab_tags = stab_tags.unwrap_or_default(), ); + w.write_str(ITEM_TABLE_ROW_CLOSE); } _ => { @@ -365,6 +389,7 @@ fn item_module(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, items: &[cl let add = if stab.is_some() { " " } else { "" }; let doc_value = myitem.doc_value().unwrap_or_default(); + w.write_str(ITEM_TABLE_ROW_OPEN); write!( w, "
\ @@ -387,15 +412,9 @@ fn item_module(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, items: &[cl .collect::>() .join(" "), ); + w.write_str(ITEM_TABLE_ROW_CLOSE); } } - - item_table_nth_element += 1; - if item_table_nth_element > item_table_block_size { - w.write_str(ITEM_TABLE_CLOSE); - w.write_str(ITEM_TABLE_OPEN); - item_table_nth_element = 0; - } } if curty.is_some() { @@ -415,10 +434,7 @@ fn extra_info_tags(item: &clean::Item, parent: &clean::Item, tcx: TyCtxt<'_>) -> // The trailing space after each tag is to space it properly against the rest of the docs. if let Some(depr) = &item.deprecation(tcx) { let mut message = "Deprecated"; - if !stability::deprecation_in_effect( - depr.is_since_rustc_version, - depr.since.map(|s| s.as_str()).as_deref(), - ) { + if !stability::deprecation_in_effect(depr) { message = "Deprecation planned"; } tags += &tag_html("deprecated", "", message); @@ -485,7 +501,7 @@ fn item_function(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, f: &clean:: notable_traits = notable_traits_decl(&f.decl, cx), ); }); - document(w, cx, it, None) + document(w, cx, it, None, HeadingOffset::H2) } fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Trait) { @@ -608,7 +624,7 @@ fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra }); // Trait documentation - document(w, cx, it, None); + document(w, cx, it, None, HeadingOffset::H2); fn write_small_section_header(w: &mut Buffer, id: &str, title: &str, extra_content: &str) { write!( @@ -626,7 +642,7 @@ fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra let item_type = m.type_(); let id = cx.derive_id(format!("{}.{}", item_type, name)); let mut content = Buffer::empty_from(w); - document(&mut content, cx, m, Some(t)); + document(&mut content, cx, m, Some(t), HeadingOffset::H5); let toggled = !content.is_empty(); if toggled { write!(w, "
"); @@ -709,11 +725,10 @@ 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, is_generic: false, .. } + clean::ResolvedPath { ref path, did, .. } | clean::BorrowedRef { - type_: box clean::ResolvedPath { ref path, did, is_generic: false, .. }, - .. - } => { + type_: box clean::ResolvedPath { ref path, did, .. }, .. + } if !path.is_assoc_ty() => { let &mut (prev_did, ref mut has_duplicates) = implementor_dups.entry(path.last()).or_insert((did, false)); if prev_did != did { @@ -841,7 +856,7 @@ fn item_trait_alias(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clea ); }); - document(w, cx, it, None); + document(w, cx, it, None, HeadingOffset::H2); // Render any items associated directly to this alias, as otherwise they // won't be visible anywhere in the docs. It would be nice to also show @@ -863,7 +878,7 @@ fn item_opaque_ty(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean: ); }); - document(w, cx, it, None); + document(w, cx, it, None, HeadingOffset::H2); // Render any items associated directly to this alias, as otherwise they // won't be visible anywhere in the docs. It would be nice to also show @@ -894,7 +909,7 @@ fn item_typedef( ); }); - document(w, cx, it, None); + document(w, cx, it, None, HeadingOffset::H2); let def_id = it.def_id.expect_def_id(); // Render any items associated directly to this alias, as otherwise they @@ -912,7 +927,7 @@ fn item_union(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::Uni }); }); - document(w, cx, it, None); + document(w, cx, it, None, HeadingOffset::H2); let mut fields = s .fields @@ -945,7 +960,7 @@ fn item_union(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::Uni if let Some(stability_class) = field.stability_class(cx.tcx()) { write!(w, "", stab = stability_class); } - document(w, cx, field, Some(it)); + document(w, cx, field, Some(it), HeadingOffset::H3); } } let def_id = it.def_id.expect_def_id(); @@ -1027,7 +1042,7 @@ fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum }); }); - document(w, cx, it, None); + document(w, cx, it, None, HeadingOffset::H2); if !e.variants.is_empty() { write!( @@ -1056,7 +1071,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)); + document(w, cx, variant, Some(it), HeadingOffset::H3); document_non_exhaustive(w, variant); use crate::clean::Variant; @@ -1096,7 +1111,7 @@ 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)); + document(w, cx, field, Some(variant), HeadingOffset::H4); } _ => unreachable!(), } @@ -1123,7 +1138,7 @@ fn item_macro(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Mac None, ); }); - document(w, cx, it, None) + document(w, cx, it, None, HeadingOffset::H2) } fn item_proc_macro(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, m: &clean::ProcMacro) { @@ -1153,11 +1168,11 @@ fn item_proc_macro(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, m: &clean }); } } - document(w, cx, it, None) + document(w, cx, it, None, HeadingOffset::H2) } fn item_primitive(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item) { - document(w, cx, it, None); + document(w, cx, it, None, HeadingOffset::H2); render_assoc_items(w, cx, it, it.def_id.expect_def_id(), AssocItemRender::All) } @@ -1196,7 +1211,7 @@ fn item_constant(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, c: &clean:: } }); - document(w, cx, it, None) + document(w, cx, it, None, HeadingOffset::H2) } fn item_struct(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::Struct) { @@ -1207,7 +1222,7 @@ fn item_struct(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::St }); }); - document(w, cx, it, None); + document(w, cx, it, None, HeadingOffset::H2); let mut fields = s .fields @@ -1243,7 +1258,7 @@ fn item_struct(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::St name = field_name, ty = ty.print(cx) ); - document(w, cx, field, Some(it)); + document(w, cx, field, Some(it), HeadingOffset::H3); } } } @@ -1264,7 +1279,7 @@ fn item_static(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::St typ = s.type_.print(cx) ); }); - document(w, cx, it, None) + document(w, cx, it, None, HeadingOffset::H2) } fn item_foreign_type(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item) { @@ -1279,13 +1294,13 @@ fn item_foreign_type(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item) { ); }); - document(w, cx, it, None); + document(w, cx, it, None, HeadingOffset::H2); render_assoc_items(w, cx, it, it.def_id.expect_def_id(), AssocItemRender::All) } fn item_keyword(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item) { - document(w, cx, it, None) + document(w, cx, it, None, HeadingOffset::H2) } /// Compare two strings treating multi-digit numbers as single units (i.e. natural sort order). @@ -1407,11 +1422,12 @@ 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, is_generic: false, .. } - | clean::BorrowedRef { - type_: box clean::ResolvedPath { ref path, is_generic: false, .. }, - .. - } => implementor_dups[&path.last()].1, + clean::ResolvedPath { ref path, .. } + | clean::BorrowedRef { type_: box clean::ResolvedPath { ref path, .. }, .. } + if !path.is_assoc_ty() => + { + implementor_dups[&path.last()].1 + } _ => false, }; render_impl( @@ -1636,6 +1652,15 @@ fn document_non_exhaustive(w: &mut Buffer, item: &clean::Item) { } fn document_type_layout(w: &mut Buffer, cx: &Context<'_>, ty_def_id: DefId) { + fn write_size_of_layout(w: &mut Buffer, layout: &Layout, tag_size: u64) { + if layout.abi.is_unsized() { + write!(w, "(unsized)"); + } else { + let bytes = layout.size.bytes() - tag_size; + write!(w, "{size} byte{pl}", size = bytes, pl = if bytes == 1 { "" } else { "s" },); + } + } + if !cx.shared.show_type_layout { return; } @@ -1651,22 +1676,46 @@ fn document_type_layout(w: &mut Buffer, cx: &Context<'_>, ty_def_id: DefId) { writeln!( w, "

Note: Most layout information is \ - completely unstable and may be different between compiler versions and platforms. \ + completely unstable and may even differ between compilations. \ The only exception is types with certain repr(...) attributes. \ Please see the Rust Reference’s \ “Type Layout” \ chapter for details on type layout guarantees.

" ); - if ty_layout.layout.abi.is_unsized() { - writeln!(w, "

Size: (unsized)

"); - } else { - let bytes = ty_layout.layout.size.bytes(); - writeln!( - w, - "

Size: {size} byte{pl}

", - size = bytes, - pl = if bytes == 1 { "" } else { "s" }, - ); + w.write_str("

Size: "); + write_size_of_layout(w, ty_layout.layout, 0); + writeln!(w, "

"); + if let Variants::Multiple { variants, tag, tag_encoding, .. } = + &ty_layout.layout.variants + { + if !variants.is_empty() { + w.write_str( + "

Size for each variant:

\ +
    ", + ); + + let adt = if let Adt(adt, _) = ty_layout.ty.kind() { + adt + } else { + span_bug!(tcx.def_span(ty_def_id), "not an adt") + }; + + let tag_size = if let TagEncoding::Niche { .. } = tag_encoding { + 0 + } else if let Primitive::Int(i, _) = tag.value { + i.size().bytes() + } else { + span_bug!(tcx.def_span(ty_def_id), "tag is neither niche nor int") + }; + + for (index, layout) in variants.iter_enumerated() { + let ident = adt.variants[index].ident; + write!(w, "
  • {name}: ", name = ident); + write_size_of_layout(w, layout, tag_size); + writeln!(w, "
  • "); + } + w.write_str("
"); + } } } // This kind of layout error can occur with valid code, e.g. if you try to diff --git a/src/librustdoc/html/render/span_map.rs b/src/librustdoc/html/render/span_map.rs index b35cd45dc9..d517f3ac0e 100644 --- a/src/librustdoc/html/render/span_map.rs +++ b/src/librustdoc/html/render/span_map.rs @@ -1,4 +1,4 @@ -use crate::clean; +use crate::clean::{self, PrimitiveType}; use crate::html::sources; use rustc_data_structures::fx::FxHashMap; @@ -22,6 +22,7 @@ use std::path::{Path, PathBuf}; crate enum LinkFromSrc { Local(clean::Span), External(DefId), + Primitive(PrimitiveType), } /// This function will do at most two things: @@ -45,7 +46,7 @@ crate fn collect_spans_and_sources( if include_sources { if generate_link_to_definition { - intravisit::walk_crate(&mut visitor, tcx.hir().krate()); + tcx.hir().walk_toplevel_module(&mut visitor); } let (krate, sources) = sources::collect_local_sources(tcx, src_root, krate); (krate, sources, visitor.matches) @@ -73,17 +74,20 @@ impl<'tcx> SpanMapVisitor<'tcx> { Some(def_id) } Res::Local(_) => None, + Res::PrimTy(p) => { + // FIXME: Doesn't handle "path-like" primitives like arrays or tuples. + let span = path_span.unwrap_or(path.span); + self.matches.insert(span, LinkFromSrc::Primitive(PrimitiveType::from(p))); + return; + } Res::Err => return, _ => return, }; if let Some(span) = self.tcx.hir().res_span(path.res) { - self.matches.insert( - path_span.unwrap_or_else(|| path.span), - LinkFromSrc::Local(clean::Span::new(span)), - ); - } else if let Some(def_id) = info { self.matches - .insert(path_span.unwrap_or_else(|| path.span), LinkFromSrc::External(def_id)); + .insert(path_span.unwrap_or(path.span), LinkFromSrc::Local(clean::Span::new(span))); + } else if let Some(def_id) = info { + self.matches.insert(path_span.unwrap_or(path.span), LinkFromSrc::External(def_id)); } } } diff --git a/src/librustdoc/html/render/templates.rs b/src/librustdoc/html/render/templates.rs new file mode 100644 index 0000000000..d1f1823944 --- /dev/null +++ b/src/librustdoc/html/render/templates.rs @@ -0,0 +1,20 @@ +use std::error::Error as StdError; + +use crate::error::Error; + +pub(crate) fn load() -> Result { + let mut templates = tera::Tera::default(); + + macro_rules! include_template { + ($file:literal, $fullpath:literal) => { + templates.add_raw_template($file, include_str!($fullpath)).map_err(|e| Error { + file: $file.into(), + error: format!("{}: {}", e, e.source().map(|e| e.to_string()).unwrap_or_default()), + })? + }; + } + + include_template!("page.html", "../templates/page.html"); + include_template!("print_item.html", "../templates/print_item.html"); + Ok(templates) +} diff --git a/src/librustdoc/html/render/write_shared.rs b/src/librustdoc/html/render/write_shared.rs index 99cd98f7ea..e4c2556118 100644 --- a/src/librustdoc/html/render/write_shared.rs +++ b/src/librustdoc/html/render/write_shared.rs @@ -39,8 +39,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-v13-korean-regular.woff" => static_files::noto_sans_kr::REGULAR, - "noto-sans-kr-v13-korean-regular-LICENSE.txt" => static_files::noto_sans_kr::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, "LICENSE-MIT.txt" => static_files::LICENSE_MIT, "LICENSE-APACHE.txt" => static_files::LICENSE_APACHE, "COPYRIGHT.txt" => static_files::COPYRIGHT, @@ -105,10 +106,10 @@ impl Context<'_> { self.dst.join(&filename) } - fn write_shared>( + fn write_shared( &self, resource: SharedResource<'_>, - contents: C, + contents: impl 'static + Send + AsRef<[u8]>, emit: &[EmitType], ) -> Result<(), Error> { if resource.should_emit(emit) { @@ -121,25 +122,23 @@ impl Context<'_> { fn write_minify( &self, resource: SharedResource<'_>, - contents: &str, + contents: impl 'static + Send + AsRef + AsRef<[u8]>, minify: bool, emit: &[EmitType], ) -> Result<(), Error> { - let tmp; - let contents = if minify { - tmp = if resource.extension() == Some(&OsStr::new("css")) { + if minify { + let contents = contents.as_ref(); + 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)) })? } else { minifier::js::minify(contents) }; - tmp.as_bytes() + self.write_shared(resource, contents, emit) } else { - contents.as_bytes() - }; - - self.write_shared(resource, contents, emit) + self.write_shared(resource, contents, emit) + } } } @@ -155,15 +154,21 @@ pub(super) fn write_shared( let lock_file = cx.dst.join(".lock"); let _lock = try_err!(flock::Lock::new(&lock_file, true, true, true), &lock_file); - // The weird `: &_` is to work around a borrowck bug: https://github.com/rust-lang/rust/issues/41078#issuecomment-293646723 - let write_minify = |p, c: &_| { + // Minified resources are usually toolchain resources. If they're not, they should use `cx.write_minify` directly. + fn write_minify( + basename: &'static str, + contents: impl 'static + Send + AsRef + AsRef<[u8]>, + cx: &Context<'_>, + options: &RenderOptions, + ) -> Result<(), Error> { cx.write_minify( - SharedResource::ToolchainSpecific { basename: p }, - c, + SharedResource::ToolchainSpecific { basename }, + contents, options.enable_minification, &options.emit, ) - }; + } + // Toolchain resources should never be dynamic. let write_toolchain = |p: &'static _, c: &'static _| { cx.write_shared(SharedResource::ToolchainSpecific { basename: p }, c, &options.emit) @@ -210,12 +215,12 @@ pub(super) fn write_shared( "details.undocumented > summary::before, details.rustdoc-toggle > summary::before", "toggle-plus.svg", ); - write_minify("rustdoc.css", &rustdoc_css)?; + write_minify("rustdoc.css", rustdoc_css, cx, options)?; // Add all the static files. These may already exist, but we just // overwrite them anyway to make sure that they're fresh and up-to-date. - write_minify("settings.css", static_files::SETTINGS_CSS)?; - write_minify("noscript.css", static_files::NOSCRIPT_CSS)?; + write_minify("settings.css", static_files::SETTINGS_CSS, cx, options)?; + write_minify("noscript.css", static_files::NOSCRIPT_CSS, cx, options)?; // To avoid "light.css" to be overwritten, we'll first run over the received themes and only // then we'll run over the "official" styles. @@ -228,9 +233,9 @@ pub(super) fn write_shared( // Handle the official themes match theme { - "light" => write_minify("light.css", static_files::themes::LIGHT)?, - "dark" => write_minify("dark.css", static_files::themes::DARK)?, - "ayu" => write_minify("ayu.css", static_files::themes::AYU)?, + "light" => write_minify("light.css", static_files::themes::LIGHT, cx, options)?, + "dark" => write_minify("dark.css", static_files::themes::DARK, cx, options)?, + "ayu" => write_minify("ayu.css", static_files::themes::AYU, cx, options)?, _ => { // Handle added third-party themes let filename = format!("{}.{}", theme, extension); @@ -264,26 +269,38 @@ pub(super) fn write_shared( // Maybe we can change the representation to move this out of main.js? write_minify( "main.js", - &static_files::MAIN_JS.replace( - "/* INSERT THEMES HERE */", - &format!(" = {}", serde_json::to_string(&themes).unwrap()), - ), + static_files::MAIN_JS + .replace( + "/* INSERT THEMES HERE */", + &format!(" = {}", serde_json::to_string(&themes).unwrap()), + ) + .replace( + "/* INSERT RUSTDOC_VERSION HERE */", + &format!( + "rustdoc {}", + rustc_interface::util::version_str().unwrap_or("unknown version") + ), + ), + cx, + options, )?; - write_minify("search.js", static_files::SEARCH_JS)?; - write_minify("settings.js", static_files::SETTINGS_JS)?; + write_minify("search.js", static_files::SEARCH_JS, cx, options)?; + write_minify("settings.js", static_files::SETTINGS_JS, cx, options)?; if cx.include_sources { - write_minify("source-script.js", static_files::sidebar::SOURCE_SCRIPT)?; + write_minify("source-script.js", static_files::sidebar::SOURCE_SCRIPT, cx, options)?; } { write_minify( "storage.js", - &format!( + format!( "var resourcesSuffix = \"{}\";{}", cx.shared.resource_suffix, static_files::STORAGE_JS ), + cx, + options, )?; } @@ -292,12 +309,12 @@ pub(super) fn write_shared( // This varies based on the invocation, so it can't go through the write_minify wrapper. cx.write_minify( SharedResource::InvocationSpecific { basename: "theme.css" }, - &buffer, + buffer, options.enable_minification, &options.emit, )?; } - write_minify("normalize.css", static_files::NORMALIZE_CSS)?; + write_minify("normalize.css", static_files::NORMALIZE_CSS, cx, options)?; for (name, contents) in &*FILES_UNVERSIONED { cx.write_shared(SharedResource::Unversioned { name }, contents, &options.emit)?; } @@ -512,7 +529,7 @@ pub(super) fn write_shared( content, &cx.shared.style_files, ); - cx.shared.fs.write(&dst, v.as_bytes())?; + cx.shared.fs.write(dst, v)?; } } @@ -603,7 +620,7 @@ pub(super) fn write_shared( }", ); v.push_str("})()"); - cx.shared.fs.write(&mydst, &v)?; + cx.shared.fs.write(mydst, v)?; } Ok(()) } diff --git a/src/librustdoc/html/sources.rs b/src/librustdoc/html/sources.rs index bb90b195dd..71c64231a2 100644 --- a/src/librustdoc/html/sources.rs +++ b/src/librustdoc/html/sources.rs @@ -208,7 +208,7 @@ impl SourceCollector<'_, 'tcx> { }, &self.cx.shared.style_files, ); - self.cx.shared.fs.write(&cur, v.as_bytes())?; + self.cx.shared.fs.write(cur, v)?; self.emitted_local_sources.insert(p); Ok(()) } diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 23ca6eeaf3..11c54876de 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -75,12 +75,13 @@ font-display: swap; } -/* Avoid using legacy CJK serif fonts in Windows like Batang */ +/* Avoid using legacy CJK serif fonts in Windows like Batang. */ @font-face { font-family: 'Noto Sans KR'; - src: url("noto-sans-kr-v13-korean-regular.woff") format("woff"); + src: url("noto-sans-kr-regular.woff2") format("woff2"), + url("noto-sans-kr-regular.woff") format("woff"); font-display: swap; - unicode-range: U+A960-A97F, U+AC00-D7AF, U+D7B0-D7FF; + unicode-range: U+AC00-D7AF, U+3130-318F, U+1100-11FF, U+A960-A97F, U+D7B0-D7FF; } * { @@ -126,7 +127,7 @@ h2 { h3 { font-size: 1.3em; } -h1, h2, h3, h4 { +h1, h2, h3, h4, h5, h6 { font-weight: 500; margin: 20px 0 15px 0; padding-bottom: 6px; @@ -179,7 +180,7 @@ div.impl-items > div { padding-left: 0; } -h1, h2, h3, h4, +h1, h2, h3, h4, h5, h6, .sidebar, a.source, .search-input, .search-results .result-name, .content table td:first-child > a, .item-left > a, @@ -501,27 +502,31 @@ nav.sub { white-space: pre-wrap; } -.docblock h1, .docblock h2, .docblock h3, .docblock h4, .docblock h5 { +.docblock h1, .docblock h2, .docblock h3, .docblock h4, .docblock h5, .docblock h6 { border-bottom: 1px solid; } -.top-doc .docblock h1 { font-size: 1.3em; } -.top-doc .docblock h2 { font-size: 1.15em; } -.top-doc .docblock h3, +.top-doc .docblock 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, +.top-doc .docblock h6 { font-size: 1em; } -.docblock h1 { font-size: 1em; } -.docblock h2 { font-size: 0.95em; } -.docblock h3, .docblock h4, .docblock h5 { font-size: 0.9em; } +.docblock h5 { font-size: 1em; } +.docblock h6 { font-size: 0.95em; } .docblock { margin-left: 24px; position: relative; } +.docblock > * { + max-width: 100%; + overflow-x: auto; +} + .content .out-of-band { flex-grow: 0; text-align: right; @@ -768,22 +773,16 @@ h2.small-section-header > .anchor { .block a.current.crate { font-weight: 500; } .item-table { - display: grid; - column-gap: 1.2rem; - row-gap: 0.0rem; - grid-template-columns: auto 1fr; - /* align content left */ - justify-items: start; + display: table; +} +.item-row { + display: table-row; } - .item-left, .item-right { - display: block; + display: table-cell; } .item-left { - grid-column: 1; -} -.item-right { - grid-column: 2; + padding-right: 1.2rem; } .search-container { @@ -923,15 +922,24 @@ body.blur > :not(#help) { display: block; margin-right: 0.5rem; } -#help > div > span { +#help span.top, #help span.bottom { + text-align: center; + display: block; + font-size: 18px; + +} +#help span.top { text-align: center; display: block; margin: 10px 0; - font-size: 18px; - border-bottom: 1px solid #ccc; + border-bottom: 1px solid; padding-bottom: 4px; margin-bottom: 6px; } +#help span.bottom { + clear: both; + border-top: 1px solid; +} #help dd { margin: 5px 35px; } #help .infos { padding-left: 0; } #help h1, #help h2 { margin-top: 0; } @@ -1877,6 +1885,9 @@ details.undocumented[open] > summary::before { /* Display an alternating layout on tablets and phones */ .item-table { + display: block; + } + .item-row { display: flex; flex-flow: column wrap; } @@ -1957,4 +1968,8 @@ details.undocumented[open] > summary::before { .docblock { margin-left: 12px; } + + .docblock code { + overflow-wrap: anywhere; + } } diff --git a/src/librustdoc/html/static/css/themes/ayu.css b/src/librustdoc/html/static/css/themes/ayu.css index f9ddef4120..0fd6462a8f 100644 --- a/src/librustdoc/html/static/css/themes/ayu.css +++ b/src/librustdoc/html/static/css/themes/ayu.css @@ -136,7 +136,7 @@ pre, .rustdoc.source .example-wrap { border-right: 1px solid #ffb44c; } -.docblock h1, .docblock h2, .docblock h3, .docblock h4, .docblock h5 { +.docblock h1, .docblock h2, .docblock h3, .docblock h4, .docblock h5, .docblock h6 { border-bottom-color: #5c6773; } @@ -217,7 +217,7 @@ a { color: #c5c5c5; } body.source .example-wrap pre.rust a { - background: #c5c5c5; + background: #333; } .docblock:not(.type-decl) a:not(.srclink):not(.test-arrow), @@ -286,8 +286,8 @@ details.undocumented > summary::before { border-radius: 4px; } -#help > div > span { - border-bottom-color: #5c6773; +#help span.bottom, #help span.top { + border-color: #5c6773; } .since { diff --git a/src/librustdoc/html/static/css/themes/dark.css b/src/librustdoc/html/static/css/themes/dark.css index d9348be699..d863701dd7 100644 --- a/src/librustdoc/html/static/css/themes/dark.css +++ b/src/librustdoc/html/static/css/themes/dark.css @@ -93,7 +93,7 @@ pre, .rustdoc.source .example-wrap { background-color: #0a042f !important; } -.docblock h1, .docblock h2, .docblock h3, .docblock h4, .docblock h5 { +.docblock h1, .docblock h2, .docblock h3, .docblock h4, .docblock h5, .docblock h6 { border-bottom-color: #DDD; } @@ -242,8 +242,8 @@ details.undocumented > summary::before { border-color: #bfbfbf; } -#help > div > span { - border-bottom-color: #bfbfbf; +#help span.bottom, #help span.top { + border-color: #bfbfbf; } #help dt { diff --git a/src/librustdoc/html/static/css/themes/light.css b/src/librustdoc/html/static/css/themes/light.css index 0ffe5929ea..28d2e99a3d 100644 --- a/src/librustdoc/html/static/css/themes/light.css +++ b/src/librustdoc/html/static/css/themes/light.css @@ -93,7 +93,7 @@ pre, .rustdoc.source .example-wrap { background-color: #f6fdb0 !important; } -.docblock h1, .docblock h2, .docblock h3, .docblock h4, .docblock h5 { +.docblock h1, .docblock h2, .docblock h3, .docblock h4, .docblock h5, .docblock h6 { border-bottom-color: #ddd; } @@ -232,8 +232,8 @@ details.undocumented > summary::before { border-color: #bfbfbf; } -#help > div > span { - border-bottom-color: #bfbfbf; +#help span.bottom, #help span.top { + border-color: #bfbfbf; } .since { diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js index 1eebd39256..e396fd9d28 100644 --- a/src/librustdoc/html/static/js/main.js +++ b/src/librustdoc/html/static/js/main.js @@ -911,6 +911,7 @@ function hideThemeButtonState() { }); var book_info = document.createElement("span"); + book_info.className = "top"; book_info.innerHTML = "You can find more information in \ the rustdoc book."; @@ -961,6 +962,14 @@ function hideThemeButtonState() { container.appendChild(div_shortcuts); container.appendChild(div_infos); + var rustdoc_version = document.createElement("span"); + rustdoc_version.className = "bottom"; + var rustdoc_version_code = document.createElement("code"); + rustdoc_version_code.innerText = "/* INSERT RUSTDOC_VERSION HERE */"; + rustdoc_version.appendChild(rustdoc_version_code); + + container.appendChild(rustdoc_version); + popup.appendChild(container); insertAfter(popup, searchState.outputElement()); // So that it's only built once and then it'll do nothing when called! diff --git a/src/librustdoc/html/static_files.rs b/src/librustdoc/html/static_files.rs index 6f3d08ea65..924e3f1d29 100644 --- a/src/librustdoc/html/static_files.rs +++ b/src/librustdoc/html/static_files.rs @@ -70,8 +70,6 @@ crate static RUST_FAVICON_SVG: &[u8] = include_bytes!("static/images/favicon.svg crate static RUST_FAVICON_PNG_16: &[u8] = include_bytes!("static/images/favicon-16x16.png"); crate static RUST_FAVICON_PNG_32: &[u8] = include_bytes!("static/images/favicon-32x32.png"); -crate static PAGE: &str = include_str!("templates/page.html"); - /// The built-in themes given to every documentation site. crate mod themes { /// The "light" theme, selected by default when no setting is available. Used as the basis for @@ -159,15 +157,14 @@ crate mod source_code_pro { } crate mod noto_sans_kr { - /// The file `noto-sans-kr-v13-korean-regular.woff`, the Regular variant of the Noto Sans KR - /// font. - crate static REGULAR: &[u8] = - include_bytes!("static/fonts/noto-sans-kr-v13-korean-regular.woff"); + /// 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-v13-korean-regular-LICENSE.txt`, the license text of the Noto Sans KR - /// font. - crate static LICENSE: &[u8] = - include_bytes!("static/fonts/noto-sans-kr-v13-korean-regular-LICENSE.txt"); + /// 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 sidebar in rustdoc sources. diff --git a/src/librustdoc/html/templates/print_item.html b/src/librustdoc/html/templates/print_item.html new file mode 100644 index 0000000000..5a468f3cc1 --- /dev/null +++ b/src/librustdoc/html/templates/print_item.html @@ -0,0 +1,26 @@ +

{#- -#} + {#- -#} + {{-typ-}} + {#- The breadcrumbs of the item path, like std::string -#} + {%- for component in path_components -%} + {{component.name}}:: + {%- endfor -%} + {{name}} {#- -#} + {#- -#} + {#- -#} + {#- -#} + {{- stability_since_raw | safe -}} + {#- -#} + {#- -#} + [] {#- -#} + {#- -#} + {#- -#} + {%- if src_href -%} + [src] + {%- endif -%} + {#- -#} +

{#- -#} diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index 228d718411..4098f17db8 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -30,9 +30,7 @@ impl JsonRenderer<'_> { .get(&item.def_id) .into_iter() .flatten() - .filter_map(|clean::ItemLink { link, did, .. }| { - did.map(|did| (link.clone(), from_item_id(did.into()))) - }) + .map(|clean::ItemLink { link, did, .. }| (link.clone(), from_item_id((*did).into()))) .collect(); let docs = item.attrs.collapsed_doc_value(); let attrs = item @@ -139,7 +137,7 @@ impl FromWithTcx for GenericArg { match arg { Lifetime(l) => GenericArg::Lifetime(l.0.to_string()), Type(t) => GenericArg::Type(t.into_tcx(tcx)), - Const(c) => GenericArg::Const(c.into_tcx(tcx)), + Const(box c) => GenericArg::Const(c.into_tcx(tcx)), Infer => GenericArg::Infer, } } @@ -220,6 +218,7 @@ fn from_clean_item(item: clean::Item, tcx: TyCtxt<'_>) -> ItemEnum { ConstantItem(c) => ItemEnum::Constant(c.into_tcx(tcx)), MacroItem(m) => ItemEnum::Macro(m.source), ProcMacroItem(m) => ItemEnum::ProcMacro(m.into_tcx(tcx)), + PrimitiveItem(p) => ItemEnum::PrimitiveType(p.as_sym().to_string()), AssocConstItem(t, s) => ItemEnum::AssocConst { type_: t.into_tcx(tcx), default: s }, AssocTypeItem(g, t) => ItemEnum::AssocType { bounds: g.into_iter().map(|x| x.into_tcx(tcx)).collect(), @@ -227,7 +226,7 @@ fn from_clean_item(item: clean::Item, tcx: TyCtxt<'_>) -> ItemEnum { }, // `convert_item` early returns `None` for striped items StrippedItem(_) => unreachable!(), - PrimitiveItem(_) | KeywordItem(_) => { + KeywordItem(_) => { panic!("{:?} is not supported for JSON output", item) } ExternCrateItem { ref src } => ItemEnum::ExternCrate { @@ -326,7 +325,9 @@ impl FromWithTcx for GenericParamDefKind { fn from_tcx(kind: clean::GenericParamDefKind, tcx: TyCtxt<'_>) -> Self { use clean::GenericParamDefKind::*; match kind { - Lifetime => GenericParamDefKind::Lifetime, + Lifetime { outlives } => GenericParamDefKind::Lifetime { + outlives: outlives.into_iter().map(|lt| lt.0.to_string()).collect(), + }, 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)), @@ -363,8 +364,11 @@ impl FromWithTcx for GenericBound { use clean::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); GenericBound::TraitBound { - trait_: trait_.into_tcx(tcx), + trait_, generic_params: generic_params.into_iter().map(|x| x.into_tcx(tcx)).collect(), modifier: from_trait_bound_modifier(modifier), } @@ -387,22 +391,19 @@ impl FromWithTcx for Type { fn from_tcx(ty: clean::Type, tcx: TyCtxt<'_>) -> Self { use clean::Type::*; match ty { - ResolvedPath { path, did, is_generic: _ } => Type::ResolvedPath { + ResolvedPath { path, did } => Type::ResolvedPath { name: path.whole_name(), id: from_item_id(did.into()), args: path.segments.last().map(|args| Box::new(args.clone().args.into_tcx(tcx))), param_names: Vec::new(), }, DynTrait(mut bounds, lt) => { - let (path, id) = match bounds.remove(0).trait_ { - ResolvedPath { path, did, .. } => (path, did), - _ => unreachable!(), - }; + let first_trait = bounds.remove(0).trait_; Type::ResolvedPath { - name: path.whole_name(), - id: from_item_id(id.into()), - args: path + name: first_trait.whole_name(), + id: from_item_id(first_trait.def_id().into()), + args: first_trait .segments .last() .map(|args| Box::new(args.clone().args.into_tcx(tcx))), @@ -423,7 +424,6 @@ impl FromWithTcx for Type { Slice(t) => Type::Slice(Box::new((*t).into_tcx(tcx))), Array(t, s) => Type::Array { type_: Box::new((*t).into_tcx(tcx)), len: s }, ImplTrait(g) => Type::ImplTrait(g.into_iter().map(|x| x.into_tcx(tcx)).collect()), - Never => Type::Never, Infer => Type::Infer, RawPointer(mutability, type_) => Type::RawPointer { mutable: mutability == ast::Mutability::Mut, @@ -434,11 +434,15 @@ impl FromWithTcx for Type { mutable: mutability == ast::Mutability::Mut, type_: Box::new((*type_).into_tcx(tcx)), }, - QPath { name, self_type, trait_, .. } => Type::QualifiedPath { - name: name.to_string(), - self_type: Box::new((*self_type).into_tcx(tcx)), - trait_: Box::new((*trait_).into_tcx(tcx)), - }, + 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); + Type::QualifiedPath { + name: name.to_string(), + self_type: Box::new((*self_type).into_tcx(tcx)), + trait_: Box::new(trait_), + } + } } } } @@ -507,6 +511,11 @@ impl FromWithTcx for Impl { blanket_impl, span: _span, } = 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) + }); Impl { is_unsafe: unsafety == rustc_hir::Unsafety::Unsafe, generics: generics.into_tcx(tcx), @@ -514,7 +523,7 @@ impl FromWithTcx for Impl { .into_iter() .map(|x| x.to_string()) .collect(), - trait_: trait_.map(|x| x.into_tcx(tcx)), + trait_, for_: for_.into_tcx(tcx), items: ids(items), negative: negative_polarity, diff --git a/src/librustdoc/json/mod.rs b/src/librustdoc/json/mod.rs index 8bdf1a5981..0031e3915f 100644 --- a/src/librustdoc/json/mod.rs +++ b/src/librustdoc/json/mod.rs @@ -69,7 +69,21 @@ impl JsonRenderer<'tcx> { .iter() .filter_map(|i| { let item = &i.impl_item; - if item.def_id.is_local() { + + // HACK(hkmatsumoto): For impls of primitive types, we index them + // regardless of whether they're local. This is because users can + // document primitive items in an arbitrary crate by using + // `doc(primitive)`. + let mut is_primitive_impl = false; + if let clean::types::ItemKind::ImplItem(ref impl_) = *item.kind { + if impl_.trait_.is_none() { + if let clean::types::Type::Primitive(_) = impl_.for_ { + is_primitive_impl = true; + } + } + } + + if item.def_id.is_local() || is_primitive_impl { self.item(item.clone()).unwrap(); Some(from_item_id(item.def_id)) } else { @@ -169,6 +183,8 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> { s.impls = self.get_impls(id.expect_def_id()) } else if let types::ItemEnum::Enum(ref mut e) = new_item.inner { e.impls = self.get_impls(id.expect_def_id()) + } else if let types::ItemEnum::Union(ref mut u) = new_item.inner { + u.impls = self.get_impls(id.expect_def_id()) } let removed = self.index.borrow_mut().insert(from_item_id(id), new_item.clone()); @@ -189,6 +205,11 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> { fn after_krate(&mut self) -> Result<(), Error> { debug!("Done with crate"); + + for primitive in Rc::clone(&self.cache).primitive_locations.values() { + self.get_impls(*primitive); + } + let mut index = (*self.index).clone().into_inner(); index.extend(self.get_trait_items()); // This needs to be the default HashMap for compatibility with the public interface for @@ -234,7 +255,7 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> { ) }) .collect(), - format_version: 6, + format_version: types::FORMAT_VERSION, }; let mut p = self.out_path.clone(); p.push(output.index.get(&output.root).unwrap().name.clone().unwrap()); diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index de32e31ca8..dc7dc45136 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -4,8 +4,10 @@ )] #![feature(rustc_private)] #![feature(array_methods)] +#![feature(assert_matches)] #![feature(box_patterns)] #![feature(control_flow_enum)] +#![feature(box_syntax)] #![feature(in_band_lifetimes)] #![feature(nll)] #![feature(test)] @@ -17,8 +19,6 @@ #![recursion_limit = "256"] #![warn(rustc::internal)] -#[macro_use] -extern crate lazy_static; #[macro_use] extern crate tracing; @@ -34,6 +34,7 @@ extern crate rustc_ast; extern crate rustc_ast_lowering; extern crate rustc_ast_pretty; extern crate rustc_attr; +extern crate rustc_const_eval; extern crate rustc_data_structures; extern crate rustc_driver; extern crate rustc_errors; @@ -49,7 +50,6 @@ extern crate rustc_lint; extern crate rustc_lint_defs; extern crate rustc_metadata; extern crate rustc_middle; -extern crate rustc_mir; extern crate rustc_parse; extern crate rustc_passes; extern crate rustc_resolve; @@ -419,8 +419,12 @@ fn opts() -> Vec { "URL", ) }), - unstable("display-warnings", |o| { - o.optflagmulti("", "display-warnings", "to print code warnings when testing doc") + unstable("display-doctest-warnings", |o| { + o.optflagmulti( + "", + "display-doctest-warnings", + "show warnings that originate in doctests", + ) }), stable("crate-version", |o| { o.optopt("", "crate-version", "crate version to print into documentation", "VERSION") @@ -726,6 +730,7 @@ fn main_options(options: config::Options) -> MainResult { let default_passes = options.default_passes; let output_format = options.output_format; // FIXME: fix this clone (especially render_options) + let externs = options.externs.clone(); let manual_passes = options.manual_passes.clone(); let render_options = options.render_options.clone(); let config = core::create_config(options); @@ -743,7 +748,7 @@ fn main_options(options: config::Options) -> MainResult { // We need to hold on to the complete resolver, so we cause everything to be // cloned for the analysis passes to use. Suboptimal, but necessary in the // current architecture. - let resolver = core::create_resolver(queries, &sess); + let resolver = core::create_resolver(externs, queries, sess); if sess.has_errors() { sess.fatal("Compilation failed, aborting rustdoc"); diff --git a/src/librustdoc/markdown.rs b/src/librustdoc/markdown.rs index 80af2a7aaf..47b24d40ed 100644 --- a/src/librustdoc/markdown.rs +++ b/src/librustdoc/markdown.rs @@ -10,7 +10,9 @@ use crate::config::{Options, RenderOptions}; use crate::doctest::{Collector, TestOptions}; use crate::html::escape::Escape; use crate::html::markdown; -use crate::html::markdown::{find_testable_code, ErrorCodes, IdMap, Markdown, MarkdownWithToc}; +use crate::html::markdown::{ + find_testable_code, ErrorCodes, HeadingOffset, IdMap, Markdown, MarkdownWithToc, +}; /// Separate any lines at the start of the file that begin with `# ` or `%`. fn extract_leading_metadata(s: &str) -> (Vec<&str>, &str) { @@ -70,7 +72,16 @@ crate fn render>( let text = if !options.markdown_no_toc { MarkdownWithToc(text, &mut ids, error_codes, edition, &playground).into_string() } else { - Markdown(text, &[], &mut ids, error_codes, edition, &playground).into_string() + Markdown { + content: text, + links: &[], + ids: &mut ids, + error_codes, + edition, + playground: &playground, + heading_offset: HeadingOffset::H1, + } + .into_string() }; let err = write!( @@ -120,7 +131,7 @@ 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_warnings = options.display_warnings; + opts.display_doctest_warnings = options.display_doctest_warnings; let mut collector = Collector::new( Symbol::intern(&options.input.display().to_string()), options.clone(), @@ -138,7 +149,7 @@ crate fn test(options: Options) -> Result<(), String> { crate::doctest::run_tests( options.test_args, options.nocapture, - options.display_warnings, + options.display_doctest_warnings, collector.tests, ); Ok(()) diff --git a/src/librustdoc/passes/bare_urls.rs b/src/librustdoc/passes/bare_urls.rs index 56ef15eb88..37faa67429 100644 --- a/src/librustdoc/passes/bare_urls.rs +++ b/src/librustdoc/passes/bare_urls.rs @@ -2,7 +2,7 @@ use super::Pass; use crate::clean::*; use crate::core::DocContext; use crate::fold::DocFolder; -use crate::html::markdown::opts; +use crate::html::markdown::main_body_opts; use core::ops::Range; use pulldown_cmark::{Event, Parser, Tag}; use regex::Regex; @@ -83,7 +83,7 @@ impl<'a, 'tcx> DocFolder for BareUrlsLinter<'a, 'tcx> { }); }; - let mut p = Parser::new_ext(&dox, opts()).into_offset_iter(); + let mut p = Parser::new_ext(&dox, main_body_opts()).into_offset_iter(); while let Some((event, range)) = p.next() { match event { diff --git a/src/librustdoc/passes/calculate_doc_coverage.rs b/src/librustdoc/passes/calculate_doc_coverage.rs index 92e678e4c0..5e3bd41b85 100644 --- a/src/librustdoc/passes/calculate_doc_coverage.rs +++ b/src/librustdoc/passes/calculate_doc_coverage.rs @@ -2,10 +2,12 @@ use crate::clean; use crate::core::DocContext; use crate::fold::{self, DocFolder}; use crate::html::markdown::{find_testable_code, ErrorCodes}; -use crate::passes::doc_test_lints::{should_have_doc_example, Tests}; +use crate::passes::check_doc_test_visibility::{should_have_doc_example, Tests}; use crate::passes::Pass; +use rustc_hir as hir; use rustc_lint::builtin::MISSING_DOCS; use rustc_middle::lint::LintLevelSource; +use rustc_middle::ty::DefIdTree; use rustc_session::lint; use rustc_span::FileName; use serde::Serialize; @@ -221,10 +223,42 @@ impl<'a, 'b> fold::DocFolder for CoverageCalculator<'a, 'b> { .hir() .local_def_id_to_hir_id(i.def_id.expect_def_id().expect_local()); let (level, source) = self.ctx.tcx.lint_level_at_node(MISSING_DOCS, hir_id); + + // In case we have: + // + // ``` + // enum Foo { Bar(u32) } + // // or: + // struct Bar(u32); + // ``` + // + // there is no need to require documentation on the fields of tuple variants and + // tuple structs. + let should_be_ignored = i + .def_id + .as_def_id() + .and_then(|def_id| self.ctx.tcx.parent(def_id)) + .and_then(|def_id| self.ctx.tcx.hir().get_if_local(def_id)) + .map(|node| { + matches!( + node, + hir::Node::Variant(hir::Variant { + data: hir::VariantData::Tuple(_, _), + .. + }) | hir::Node::Item(hir::Item { + kind: hir::ItemKind::Struct(hir::VariantData::Tuple(_, _), _), + .. + }) + ) + }) + .unwrap_or(false); + // `missing_docs` is allow-by-default, so don't treat this as ignoring the item - // unless the user had an explicit `allow` - let should_have_docs = - level != lint::Level::Allow || matches!(source, LintLevelSource::Default); + // unless the user had an explicit `allow`. + // + let should_have_docs = !should_be_ignored + && (level != lint::Level::Allow || matches!(source, LintLevelSource::Default)); + debug!("counting {:?} {:?} in {:?}", i.type_(), i.name, filename); self.items.entry(filename).or_default().count_item( has_docs, diff --git a/src/librustdoc/passes/check_code_block_syntax.rs b/src/librustdoc/passes/check_code_block_syntax.rs index 781904788e..d2b3c5239c 100644 --- a/src/librustdoc/passes/check_code_block_syntax.rs +++ b/src/librustdoc/passes/check_code_block_syntax.rs @@ -111,9 +111,9 @@ impl<'a, 'tcx> SyntaxChecker<'a, 'tcx> { ); } else if empty_block { diag.span_suggestion( - sp.from_inner(InnerSpan::new(0, 3)), + sp.from_inner(InnerSpan::new(0, 3)).shrink_to_hi(), explanation, - String::from("```text"), + String::from("text"), Applicability::MachineApplicable, ); } diff --git a/src/librustdoc/passes/doc_test_lints.rs b/src/librustdoc/passes/check_doc_test_visibility.rs similarity index 76% rename from src/librustdoc/passes/doc_test_lints.rs rename to src/librustdoc/passes/check_doc_test_visibility.rs index 03bc2b52f1..1f7d605423 100644 --- a/src/librustdoc/passes/doc_test_lints.rs +++ b/src/librustdoc/passes/check_doc_test_visibility.rs @@ -1,6 +1,6 @@ //! This pass is overloaded and runs two different lints. //! -//! - MISSING_DOC_CODE_EXAMPLES: this lint is **UNSTABLE** and looks for public items missing doctests +//! - MISSING_DOC_CODE_EXAMPLES: this lint is **UNSTABLE** and looks for public items missing doctests. //! - PRIVATE_DOC_TESTS: this lint is **STABLE** and looks for private items with doctests. use super::Pass; @@ -10,27 +10,28 @@ use crate::core::DocContext; use crate::fold::DocFolder; use crate::html::markdown::{find_testable_code, ErrorCodes, Ignore, LangString}; use crate::visit_ast::inherits_doc_hidden; +use rustc_hir as hir; use rustc_middle::lint::LintLevelSource; use rustc_session::lint; use rustc_span::symbol::sym; -crate const CHECK_PRIVATE_ITEMS_DOC_TESTS: Pass = Pass { - name: "check-private-items-doc-tests", - run: check_private_items_doc_tests, - description: "check private items doc tests", +crate const CHECK_DOC_TEST_VISIBILITY: Pass = Pass { + name: "check_doc_test_visibility", + run: check_doc_test_visibility, + description: "run various visibility-related lints on doctests", }; -struct PrivateItemDocTestLinter<'a, 'tcx> { +struct DocTestVisibilityLinter<'a, 'tcx> { cx: &'a mut DocContext<'tcx>, } -crate fn check_private_items_doc_tests(krate: Crate, cx: &mut DocContext<'_>) -> Crate { - let mut coll = PrivateItemDocTestLinter { cx }; +crate fn check_doc_test_visibility(krate: Crate, cx: &mut DocContext<'_>) -> Crate { + let mut coll = DocTestVisibilityLinter { cx }; coll.fold_crate(krate) } -impl<'a, 'tcx> DocFolder for PrivateItemDocTestLinter<'a, 'tcx> { +impl<'a, 'tcx> DocFolder for DocTestVisibilityLinter<'a, 'tcx> { fn fold_item(&mut self, item: Item) -> Option { let dox = item.attrs.collapsed_doc_value().unwrap_or_else(String::new); @@ -67,15 +68,35 @@ crate fn should_have_doc_example(cx: &DocContext<'_>, item: &clean::Item) -> boo | clean::ImportItem(_) | clean::PrimitiveItem(_) | clean::KeywordItem(_) + // check for trait impl + | clean::ImplItem(clean::Impl { trait_: Some(_), .. }) ) { return false; } + // The `expect_def_id()` should be okay because `local_def_id_to_hir_id` // would presumably panic if a fake `DefIndex` were passed. let hir_id = cx.tcx.hir().local_def_id_to_hir_id(item.def_id.expect_def_id().expect_local()); + + // check if parent is trait impl + if let Some(parent_hir_id) = cx.tcx.hir().find_parent_node(hir_id) { + if let Some(parent_node) = cx.tcx.hir().find(parent_hir_id) { + if matches!( + parent_node, + hir::Node::Item(hir::Item { + kind: hir::ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }), + .. + }) + ) { + return false; + } + } + } + if cx.tcx.hir().attrs(hir_id).lists(sym::doc).has_word(sym::hidden) || inherits_doc_hidden(cx.tcx, hir_id) + || cx.tcx.hir().span(hir_id).in_derive_expansion() { return false; } diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 178c8c15a1..318c897bcb 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -14,7 +14,7 @@ use rustc_hir::def::{ }; use rustc_hir::def_id::{CrateNum, DefId}; use rustc_middle::ty::TyCtxt; -use rustc_middle::{bug, ty}; +use rustc_middle::{bug, span_bug, ty}; use rustc_resolve::ParentScope; use rustc_session::lint::Lint; use rustc_span::hygiene::{MacroKind, SyntaxContext}; @@ -64,7 +64,7 @@ enum ErrorKind<'a> { impl<'a> From> for ErrorKind<'a> { fn from(err: ResolutionFailure<'a>) -> Self { - ErrorKind::Resolve(Box::new(err)) + ErrorKind::Resolve(box err) } } @@ -98,14 +98,10 @@ impl Res { } } - fn def_id(self) -> DefId { - self.opt_def_id().expect("called def_id() on a primitive") - } - - fn opt_def_id(self) -> Option { + fn def_id(self, tcx: TyCtxt<'_>) -> DefId { match self { - Res::Def(_, id) => Some(id), - Res::Primitive(_) => None, + Res::Def(_, id) => id, + Res::Primitive(prim) => *PrimitiveType::primitive_locations(tcx).get(&prim).unwrap(), } } @@ -237,10 +233,7 @@ enum AnchorFailure { /// link, Rustdoc disallows having a user-specified anchor. /// /// Most of the time this is fine, because you can just link to the page of - /// the item if you want to provide your own anchor. For primitives, though, - /// rustdoc uses the anchor as a side channel to know which page to link to; - /// it doesn't show up in the generated link. Ideally, rustdoc would remove - /// this limitation, allowing you to link to subheaders on primitives. + /// the item if you want to provide your own anchor. RustdocAnchorConflict(Res), } @@ -388,7 +381,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { ty::AssocKind::Const => "associatedconstant", ty::AssocKind::Type => "associatedtype", }; - let fragment = format!("{}#{}.{}", prim_ty.as_sym(), out, item_name); + let fragment = format!("{}.{}", out, item_name); (Res::Primitive(prim_ty), fragment, Some((kind.as_def_kind(), item.def_id))) }) }) @@ -475,14 +468,6 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { return handle_variant(self.cx, res, extra_fragment); } // Not a trait item; just return what we found. - Res::Primitive(ty) => { - if extra_fragment.is_some() { - return Err(ErrorKind::AnchorFailure( - AnchorFailure::RustdocAnchorConflict(res), - )); - } - return Ok((res, Some(ty.as_sym().to_string()))); - } _ => return Ok((res, extra_fragment.clone())), } } @@ -517,6 +502,8 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { let (res, fragment, side_channel) = self.resolve_associated_item(ty_res, item_name, ns, module_id)?; let result = if extra_fragment.is_some() { + // NOTE: can never be a primitive since `side_channel.is_none()` only when `res` + // is a trait (and the side channel DefId is always an associated item). let diag_res = side_channel.map_or(res, |(k, r)| Res::Def(k, r)); Err(ErrorKind::AnchorFailure(AnchorFailure::RustdocAnchorConflict(diag_res))) } else { @@ -772,7 +759,7 @@ fn traits_implemented_by(cx: &mut DocContext<'_>, type_: DefId, module: DefId) - let mut resolver = cx.resolver.borrow_mut(); let in_scope_traits = cx.module_trait_cache.entry(module).or_insert_with(|| { resolver.access(|resolver| { - let parent_scope = &ParentScope::module(resolver.get_module(module), resolver); + let parent_scope = &ParentScope::module(resolver.expect_module(module), resolver); resolver .traits_in_scope(None, parent_scope, SyntaxContext::root(), None) .into_iter() @@ -1152,7 +1139,7 @@ impl LinkCollector<'_, '_> { module_id = DefId { krate, index: CRATE_DEF_INDEX }; } - let (mut res, mut fragment) = self.resolve_with_disambiguator_cached( + let (mut res, fragment) = self.resolve_with_disambiguator_cached( ResolutionInfo { module_id, dis: disambiguator, @@ -1174,16 +1161,7 @@ impl LinkCollector<'_, '_> { if let Some(prim) = resolve_primitive(path_str, TypeNS) { // `prim@char` if matches!(disambiguator, Some(Disambiguator::Primitive)) { - if fragment.is_some() { - anchor_failure( - self.cx, - diag_info, - AnchorFailure::RustdocAnchorConflict(prim), - ); - return None; - } res = prim; - fragment = Some(prim.name(self.cx.tcx).to_string()); } else { // `[char]` when a `char` module is in scope let candidates = vec![res, prim]; @@ -1303,12 +1281,17 @@ impl LinkCollector<'_, '_> { } } - Some(ItemLink { link: ori_link.link, link_text, did: None, fragment }) + Some(ItemLink { + link: ori_link.link, + link_text, + did: res.def_id(self.cx.tcx), + fragment, + }) } Res::Def(kind, id) => { verify(kind, id)?; let id = clean::register_res(self.cx, rustc_hir::def::Res::Def(kind, id)); - Some(ItemLink { link: ori_link.link, link_text, did: Some(id), fragment }) + Some(ItemLink { link: ori_link.link, link_text, did: id, fragment }) } } } @@ -1323,7 +1306,7 @@ impl LinkCollector<'_, '_> { if let Some(ref cached) = self.visited_links.get(&key) { match cached { Some(cached) => { - self.kind_side_channel.set(cached.side_channel.clone()); + self.kind_side_channel.set(cached.side_channel); return Some(cached.res.clone()); } None if cache_resolution_failure => return None, @@ -2069,8 +2052,11 @@ fn anchor_failure(cx: &DocContext<'_>, diag_info: DiagnosticInfo<'_>, failure: A diag.span_label(sp, "invalid anchor"); } if let AnchorFailure::RustdocAnchorConflict(Res::Primitive(_)) = failure { - diag.note("this restriction may be lifted in a future release"); - diag.note("see https://github.com/rust-lang/rust/issues/83083 for more information"); + if let Some(sp) = sp { + span_bug!(sp, "anchors should be allowed now"); + } else { + bug!("anchors should be allowed now"); + } } }); } @@ -2198,10 +2184,11 @@ fn handle_variant( use rustc_middle::ty::DefIdTree; if extra_fragment.is_some() { + // NOTE: `res` can never be a primitive since this function is only called when `tcx.def_kind(res) == DefKind::Variant`. return Err(ErrorKind::AnchorFailure(AnchorFailure::RustdocAnchorConflict(res))); } cx.tcx - .parent(res.def_id()) + .parent(res.def_id(cx.tcx)) .map(|parent| { let parent_def = Res::Def(DefKind::Enum, parent); let variant = cx.tcx.expect_variant_res(res.as_hir_res().unwrap()); diff --git a/src/librustdoc/passes/collect_intra_doc_links/early.rs b/src/librustdoc/passes/collect_intra_doc_links/early.rs index cd90528ab9..d5148fed5c 100644 --- a/src/librustdoc/passes/collect_intra_doc_links/early.rs +++ b/src/librustdoc/passes/collect_intra_doc_links/early.rs @@ -1,3 +1,4 @@ +use ast::visit; use rustc_ast as ast; use rustc_hir::def::Namespace::TypeNS; use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID}; @@ -16,7 +17,7 @@ crate fn load_intra_link_crates(resolver: Resolver, krate: &ast::Crate) -> Resol let mut loader = IntraLinkCrateLoader { current_mod: CRATE_DEF_ID, resolver }; // `walk_crate` doesn't visit the crate itself for some reason. loader.load_links_in_attrs(&krate.attrs, krate.span); - ast::visit::walk_crate(&mut loader, krate); + visit::walk_crate(&mut loader, krate); loader.resolver } @@ -54,7 +55,12 @@ impl IntraLinkCrateLoader { } } -impl ast::visit::Visitor<'_> for IntraLinkCrateLoader { +impl visit::Visitor<'_> for IntraLinkCrateLoader { + fn visit_foreign_item(&mut self, item: &ast::ForeignItem) { + self.load_links_in_attrs(&item.attrs, item.span); + visit::walk_foreign_item(self, item) + } + fn visit_item(&mut self, item: &ast::Item) { use rustc_ast_lowering::ResolverAstLowering; @@ -64,12 +70,29 @@ impl ast::visit::Visitor<'_> for IntraLinkCrateLoader { let old_mod = mem::replace(&mut self.current_mod, new_mod); self.load_links_in_attrs(&item.attrs, item.span); - ast::visit::walk_item(self, item); + visit::walk_item(self, item); self.current_mod = old_mod; } else { self.load_links_in_attrs(&item.attrs, item.span); - ast::visit::walk_item(self, item); + visit::walk_item(self, item); } } + + // NOTE: if doc-comments are ever allowed on function parameters, this will have to implement `visit_param` too. + + fn visit_assoc_item(&mut self, item: &ast::AssocItem, ctxt: visit::AssocCtxt) { + self.load_links_in_attrs(&item.attrs, item.span); + visit::walk_assoc_item(self, item, ctxt) + } + + fn visit_field_def(&mut self, field: &ast::FieldDef) { + self.load_links_in_attrs(&field.attrs, field.span); + visit::walk_field_def(self, field) + } + + fn visit_variant(&mut self, v: &ast::Variant) { + self.load_links_in_attrs(&v.attrs, v.span); + visit::walk_variant(self, v) + } } diff --git a/src/librustdoc/passes/collect_trait_impls.rs b/src/librustdoc/passes/collect_trait_impls.rs index eefe50caa3..319dd7b42b 100644 --- a/src/librustdoc/passes/collect_trait_impls.rs +++ b/src/librustdoc/passes/collect_trait_impls.rs @@ -57,7 +57,9 @@ crate fn collect_trait_impls(krate: Crate, cx: &mut DocContext<'_>) -> Crate { // 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_.def_id() == cx.tcx.lang_items().deref_trait() { + if cleaner.keep_impl(for_) + && trait_.as_ref().map(|t| t.def_id()) == cx.tcx.lang_items().deref_trait() + { let target = items .iter() .find_map(|item| match *item.kind { @@ -78,7 +80,9 @@ crate fn collect_trait_impls(krate: Crate, cx: &mut DocContext<'_>) -> Crate { 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(t)) + || trait_ + .as_ref() + .map_or(false, |t| cleaner.keep_impl_with_def_id(t.def_id().into())) || blanket_impl.is_some() } else { true diff --git a/src/librustdoc/passes/html_tags.rs b/src/librustdoc/passes/html_tags.rs index f29d38e3e0..a3fde92d76 100644 --- a/src/librustdoc/passes/html_tags.rs +++ b/src/librustdoc/passes/html_tags.rs @@ -2,7 +2,7 @@ use super::Pass; use crate::clean::*; use crate::core::DocContext; use crate::fold::DocFolder; -use crate::html::markdown::opts; +use crate::html::markdown::main_body_opts; use core::ops::Range; use pulldown_cmark::{Event, Parser, Tag}; use std::iter::Peekable; @@ -52,7 +52,7 @@ fn drop_tag( continue; } let last_tag_name_low = last_tag_name.to_lowercase(); - if ALLOWED_UNCLOSED.iter().any(|&at| at == last_tag_name_low) { + if ALLOWED_UNCLOSED.contains(&last_tag_name_low.as_str()) { continue; } // `tags` is used as a queue, meaning that everything after `pos` is included inside it. @@ -192,7 +192,7 @@ impl<'a, 'tcx> DocFolder for InvalidHtmlTagsLinter<'a, 'tcx> { let mut is_in_comment = None; let mut in_code_block = false; - let p = Parser::new_ext(&dox, opts()).into_offset_iter(); + let p = Parser::new_ext(&dox, main_body_opts()).into_offset_iter(); for (event, range) in p { match event { @@ -207,7 +207,7 @@ impl<'a, 'tcx> DocFolder for InvalidHtmlTagsLinter<'a, 'tcx> { for (tag, range) in tags.iter().filter(|(t, _)| { let t = t.to_lowercase(); - ALLOWED_UNCLOSED.iter().find(|&&at| at == t).is_none() + !ALLOWED_UNCLOSED.contains(&t.as_str()) }) { report_diag(&format!("unclosed HTML tag `{}`", tag), range); } diff --git a/src/librustdoc/passes/mod.rs b/src/librustdoc/passes/mod.rs index 0e86fe4564..99ac87db4f 100644 --- a/src/librustdoc/passes/mod.rs +++ b/src/librustdoc/passes/mod.rs @@ -33,8 +33,8 @@ crate use self::propagate_doc_cfg::PROPAGATE_DOC_CFG; crate mod collect_intra_doc_links; crate use self::collect_intra_doc_links::COLLECT_INTRA_DOC_LINKS; -mod doc_test_lints; -crate use self::doc_test_lints::CHECK_PRIVATE_ITEMS_DOC_TESTS; +mod check_doc_test_visibility; +crate use self::check_doc_test_visibility::CHECK_DOC_TEST_VISIBILITY; mod collect_trait_impls; crate use self::collect_trait_impls::COLLECT_TRAIT_IMPLS; @@ -79,7 +79,7 @@ crate enum Condition { /// The full list of passes. crate const PASSES: &[Pass] = &[ - CHECK_PRIVATE_ITEMS_DOC_TESTS, + CHECK_DOC_TEST_VISIBILITY, STRIP_HIDDEN, UNINDENT_COMMENTS, STRIP_PRIVATE, @@ -97,7 +97,7 @@ crate const PASSES: &[Pass] = &[ crate const DEFAULT_PASSES: &[ConditionalPass] = &[ ConditionalPass::always(COLLECT_TRAIT_IMPLS), ConditionalPass::always(UNINDENT_COMMENTS), - ConditionalPass::always(CHECK_PRIVATE_ITEMS_DOC_TESTS), + ConditionalPass::always(CHECK_DOC_TEST_VISIBILITY), ConditionalPass::new(STRIP_HIDDEN, WhenNotDocumentHidden), ConditionalPass::new(STRIP_PRIVATE, WhenNotDocumentPrivate), ConditionalPass::new(STRIP_PRIV_IMPORTS, WhenDocumentPrivate), diff --git a/src/librustdoc/passes/stripper.rs b/src/librustdoc/passes/stripper.rs index a93880453b..8b1fd662f8 100644 --- a/src/librustdoc/passes/stripper.rs +++ b/src/librustdoc/passes/stripper.rs @@ -128,13 +128,13 @@ impl<'a> DocFolder for ImplStripper<'a> { return None; } if let Some(did) = imp.for_.def_id() { - if did.is_local() && !imp.for_.is_generic() && !self.retained.contains(&did.into()) + if did.is_local() && !imp.for_.is_assoc_ty() && !self.retained.contains(&did.into()) { debug!("ImplStripper: impl item for stripped type; removing"); return None; } } - if let Some(did) = imp.trait_.def_id() { + if let Some(did) = imp.trait_.as_ref().map(|t| t.def_id()) { if did.is_local() && !self.retained.contains(&did.into()) { debug!("ImplStripper: impl item for stripped trait; removing"); return None; diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index 5082a14da2..3e853456fa 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -6,6 +6,7 @@ use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::DefId; use rustc_hir::Node; +use rustc_hir::CRATE_HIR_ID; use rustc_middle::middle::privacy::AccessLevel; use rustc_middle::ty::TyCtxt; use rustc_span; @@ -15,7 +16,7 @@ use rustc_span::symbol::{kw, sym, Symbol}; use std::mem; -use crate::clean::{self, AttributesExt, NestedAttributesExt}; +use crate::clean::{self, cfg::Cfg, AttributesExt, NestedAttributesExt}; use crate::core; use crate::doctree::*; @@ -71,12 +72,12 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { self.exact_paths.entry(did).or_insert_with(|| def_id_to_path(tcx, did)); } - crate fn visit(mut self, krate: &'tcx hir::Crate<'_>) -> Module<'tcx> { - let span = krate.module().inner; + 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, - &krate.module(), + self.cx.tcx.hir().root_module(), self.cx.tcx.crate_name(LOCAL_CRATE), ); @@ -105,6 +106,29 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { } } } + + self.cx.cache.hidden_cfg = self + .cx + .tcx + .hir() + .attrs(CRATE_HIR_ID) + .iter() + .filter(|attr| attr.has_name(sym::doc)) + .flat_map(|attr| attr.meta_item_list().into_iter().flatten()) + .filter(|attr| attr.has_name(sym::cfg_hide)) + .flat_map(|attr| { + attr.meta_item_list() + .unwrap_or(&[]) + .iter() + .filter_map(|attr| { + Cfg::parse(attr.meta_item()?) + .map_err(|e| self.cx.sess().diagnostic().span_err(e.span, e.msg)) + .ok() + }) + .collect::>() + }) + .collect(); + self.cx.cache.exact_paths = self.exact_paths; top_level_module } diff --git a/src/librustdoc/visit_lib.rs b/src/librustdoc/visit_lib.rs index 3e06b41731..3e98ba08fb 100644 --- a/src/librustdoc/visit_lib.rs +++ b/src/librustdoc/visit_lib.rs @@ -67,7 +67,7 @@ impl<'a, 'tcx> LibEmbargoVisitor<'a, 'tcx> { } } - fn visit_item(&mut self, res: Res) { + 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 }; diff --git a/src/rustdoc-json-types/Cargo.toml b/src/rustdoc-json-types/Cargo.toml index a692f6f896..d60699efd3 100644 --- a/src/rustdoc-json-types/Cargo.toml +++ b/src/rustdoc-json-types/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustdoc-json-types" version = "0.1.0" -edition = "2018" +edition = "2021" [lib] path = "lib.rs" diff --git a/src/rustdoc-json-types/lib.rs b/src/rustdoc-json-types/lib.rs index 38ba87322c..9466f84ffc 100644 --- a/src/rustdoc-json-types/lib.rs +++ b/src/rustdoc-json-types/lib.rs @@ -221,6 +221,8 @@ pub enum ItemEnum { Macro(String), ProcMacro(ProcMacro), + PrimitiveType(String), + AssocConst { #[serde(rename = "type")] type_: Type, @@ -323,7 +325,7 @@ pub struct GenericParamDef { #[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] #[serde(rename_all = "snake_case")] pub enum GenericParamDefKind { - Lifetime, + Lifetime { outlives: Vec }, Type { bounds: Vec, default: Option }, Const { ty: Type, default: Option }, } @@ -386,8 +388,6 @@ pub enum Type { }, /// `impl TraitA + TraitB + ...` ImplTrait(Vec), - /// `!` - Never, /// `_` Infer, /// `*mut u32`, `*u8`, etc. @@ -510,5 +510,8 @@ pub struct Static { pub expr: String, } +/// rustdoc format-version. +pub const FORMAT_VERSION: u32 = 9; + #[cfg(test)] mod tests; diff --git a/src/stage0.json b/src/stage0.json new file mode 100644 index 0000000000..4bff2a98e0 --- /dev/null +++ b/src/stage0.json @@ -0,0 +1,291 @@ +{ + "__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" + }, + "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" + } +} diff --git a/src/stage0.txt b/src/stage0.txt deleted file mode 100644 index a979b1e0c6..0000000000 --- a/src/stage0.txt +++ /dev/null @@ -1,42 +0,0 @@ -# This file describes the stage0 compiler that's used to then bootstrap the Rust -# compiler itself. -# -# Currently Rust always bootstraps from the previous stable release, and in our -# train model this means that the master branch bootstraps from beta, beta -# bootstraps from current stable, and stable bootstraps from the previous stable -# release. -# -# If you're looking at this file on the master branch, you'll likely see that -# rustc is configured to `beta`, whereas if you're looking at a source tarball -# for a stable release you'll likely see `1.x.0` for rustc, with the previous -# stable release's version number. `date` is the date where the release we're -# bootstrapping off was released. - -date: 2021-09-09 -rustc: 1.55.0 - -# We use a nightly rustfmt to format the source because it solves some -# bootstrapping issues with use of new syntax in this repo. If you're looking at -# the beta/stable branch, this key should be omitted, as we don't want to depend -# on rustfmt from nightly there. -#rustfmt: nightly-2021-03-25 - -# When making a stable release the process currently looks like: -# -# 1. Produce stable build, upload it to dev-static -# 2. Produce a beta build from the previous stable build, upload to static -# 3. Produce a nightly build from previous beta, upload to static -# 4. Upload stable build to static, publish full release -# -# This means that there's a small window of time (a few days) where artifacts -# are downloaded from dev-static.rust-lang.org instead of static.rust-lang.org. -# In order to ease this transition we have an extra key which is in the -# configuration file below. When uncommented this will instruct the bootstrap.py -# script to download from dev-static.rust-lang.org. -# -# This key is typically commented out at all times. If you're looking at a -# stable release tarball it should *definitely* be commented out. If you're -# looking at a beta source tarball and it's uncommented we'll shortly comment it -# out. - -#dev: 1 diff --git a/src/test/assembly/asm/aarch64-outline-atomics.rs b/src/test/assembly/asm/aarch64-outline-atomics.rs new file mode 100644 index 0000000000..42cef9bb67 --- /dev/null +++ b/src/test/assembly/asm/aarch64-outline-atomics.rs @@ -0,0 +1,17 @@ +// min-llvm-version: 12.0 +// assembly-output: emit-asm +// compile-flags: -O +// compile-flags: --target aarch64-unknown-linux-gnu +// needs-llvm-components: aarch64 +// only-aarch64 +// only-linux + +#![crate_type = "rlib"] + +use std::sync::atomic::{AtomicI32, Ordering::*}; + +pub fn compare_exchange(a: &AtomicI32) { + // On AArch64 LLVM should outline atomic operations. + // CHECK: __aarch64_cas4_relax + let _ = a.compare_exchange(0, 10, Relaxed, Relaxed); +} diff --git a/src/test/assembly/asm/bpf-types.rs b/src/test/assembly/asm/bpf-types.rs index cc3863d03c..7271ef1128 100644 --- a/src/test/assembly/asm/bpf-types.rs +++ b/src/test/assembly/asm/bpf-types.rs @@ -1,4 +1,4 @@ -// min-llvm-version: 10.0.1 +// min-llvm-version: 13.0 // assembly-output: emit-asm // compile-flags: --target bpfel-unknown-none -C target_feature=+alu32 // needs-llvm-components: bpf diff --git a/src/test/assembly/niche-prefer-zero.rs b/src/test/assembly/niche-prefer-zero.rs new file mode 100644 index 0000000000..0ab37a618d --- /dev/null +++ b/src/test/assembly/niche-prefer-zero.rs @@ -0,0 +1,25 @@ +// Check that niche selection prefers zero and that jumps are optimized away. +// See https://github.com/rust-lang/rust/pull/87794 +// assembly-output: emit-asm +// only-x86 +// compile-flags: -Copt-level=3 + +#![crate_type = "lib"] + +#[repr(u8)] +pub enum Size { + One = 1, + Two = 2, + Three = 3, +} + +#[no_mangle] +pub fn handle(x: Option) -> u8 { + match x { + None => 0, + Some(size) => size as u8, + } +} + +// There should be no jumps in output +// CHECK-NOT: j diff --git a/src/test/assembly/pic-relocation-model.rs b/src/test/assembly/pic-relocation-model.rs new file mode 100644 index 0000000000..72471ffcdb --- /dev/null +++ b/src/test/assembly/pic-relocation-model.rs @@ -0,0 +1,35 @@ +// revisions: x64 +// assembly-output: emit-asm +// [x64] compile-flags: --target x86_64-unknown-linux-gnu -Crelocation-model=pic +// [x64] needs-llvm-components: x86 + + +#![feature(no_core, lang_items)] +#![no_core] +#![crate_type="rlib"] + +#[lang = "sized"] +trait Sized {} +#[lang = "copy"] +trait Copy {} + +// CHECK-LABEL: call_other_fn: +// CHECK: {{(jmpq|callq)}} *other_fn@GOTPCREL(%rip) +#[no_mangle] +pub fn call_other_fn() -> u8 { + unsafe { + other_fn() + } +} + +// CHECK-LABEL: other_fn: +// CHECK: callq *foreign_fn@GOTPCREL(%rip) +#[no_mangle] +#[inline(never)] +pub fn other_fn() -> u8 { + unsafe { + foreign_fn() + } +} + +extern "C" {fn foreign_fn() -> u8;} diff --git a/src/test/assembly/pie-relocation-model.rs b/src/test/assembly/pie-relocation-model.rs new file mode 100644 index 0000000000..e40797e038 --- /dev/null +++ b/src/test/assembly/pie-relocation-model.rs @@ -0,0 +1,38 @@ +// revisions: x64 +// assembly-output: emit-asm +// [x64] compile-flags: --target x86_64-unknown-linux-gnu -Crelocation-model=pie +// [x64] needs-llvm-components: x86 + + +#![feature(no_core, lang_items)] +#![no_core] +#![crate_type="rlib"] + +#[lang = "sized"] +trait Sized {} +#[lang = "copy"] +trait Copy {} + +// CHECK-LABEL: call_other_fn: +// With PIE local functions are called "directly". +// CHECK: {{(jmp|callq)}} other_fn +#[no_mangle] +pub fn call_other_fn() -> u8 { + unsafe { + other_fn() + } +} + +// CHECK-LABEL: other_fn: +// External functions are still called through GOT, since we don't know if the symbol +// is defined in the binary or in the shared library. +// CHECK: callq *foreign_fn@GOTPCREL(%rip) +#[no_mangle] +#[inline(never)] +pub fn other_fn() -> u8 { + unsafe { + foreign_fn() + } +} + +extern "C" {fn foreign_fn() -> u8;} diff --git a/src/test/assembly/x86_64-sse_crc.rs b/src/test/assembly/x86_64-sse_crc.rs new file mode 100644 index 0000000000..cdbf057b80 --- /dev/null +++ b/src/test/assembly/x86_64-sse_crc.rs @@ -0,0 +1,12 @@ +// only-x86_64 +// assembly-output: emit-asm +// compile-flags: --crate-type staticlib -Ctarget-feature=+sse4.2 + +// CHECK-LABEL: banana +// CHECK: crc32 +#[no_mangle] +pub unsafe fn banana(v: u8) -> u32 { + use std::arch::x86_64::*; + let out = !0u32; + _mm_crc32_u8(out, v) +} diff --git a/src/test/codegen-units/partitioning/extern-drop-glue.rs b/src/test/codegen-units/partitioning/extern-drop-glue.rs index 8b0448ec47..c73d2a10a9 100644 --- a/src/test/codegen-units/partitioning/extern-drop-glue.rs +++ b/src/test/codegen-units/partitioning/extern-drop-glue.rs @@ -1,9 +1,10 @@ // -// We specify -C incremental here because we want to test the partitioning for +// We specify incremental here because we want to test the partitioning for // incremental compilation // We specify opt-level=0 because `drop_in_place` is `Internal` when optimizing -// compile-flags:-Zprint-mono-items=lazy -Cincremental=tmp/partitioning-tests/extern-drop-glue +// incremental +// compile-flags:-Zprint-mono-items=lazy // compile-flags:-Zinline-in-all-cgus -Copt-level=0 #![allow(dead_code)] diff --git a/src/test/codegen-units/partitioning/extern-generic.rs b/src/test/codegen-units/partitioning/extern-generic.rs index c96df6e102..638ec079a0 100644 --- a/src/test/codegen-units/partitioning/extern-generic.rs +++ b/src/test/codegen-units/partitioning/extern-generic.rs @@ -1,7 +1,8 @@ // -// We specify -C incremental here because we want to test the partitioning for +// We specify incremental here because we want to test the partitioning for // incremental compilation -// compile-flags:-Zprint-mono-items=eager -Cincremental=tmp/partitioning-tests/extern-generic -Zshare-generics=y +// incremental +// compile-flags:-Zprint-mono-items=eager -Zshare-generics=y #![allow(dead_code)] #![crate_type="lib"] diff --git a/src/test/codegen-units/partitioning/incremental-merging.rs b/src/test/codegen-units/partitioning/incremental-merging.rs index 91ae602293..118b7bdf4d 100644 --- a/src/test/codegen-units/partitioning/incremental-merging.rs +++ b/src/test/codegen-units/partitioning/incremental-merging.rs @@ -1,6 +1,7 @@ -// We specify -C incremental here because we want to test the partitioning for +// We specify incremental here because we want to test the partitioning for // incremental compilation -// compile-flags:-Zprint-mono-items=lazy -Cincremental=tmp/partitioning-tests/incremental-merging +// incremental +// compile-flags:-Zprint-mono-items=lazy // compile-flags:-Ccodegen-units=3 #![crate_type = "rlib"] diff --git a/src/test/codegen-units/partitioning/inlining-from-extern-crate.rs b/src/test/codegen-units/partitioning/inlining-from-extern-crate.rs index b86e325537..1cc21632e4 100644 --- a/src/test/codegen-units/partitioning/inlining-from-extern-crate.rs +++ b/src/test/codegen-units/partitioning/inlining-from-extern-crate.rs @@ -1,7 +1,8 @@ // -// We specify -C incremental here because we want to test the partitioning for +// We specify incremental here because we want to test the partitioning for // incremental compilation -// compile-flags:-Zprint-mono-items=lazy -Cincremental=tmp/partitioning-tests/inlining-from-extern-crate +// incremental +// compile-flags:-Zprint-mono-items=lazy // compile-flags:-Zinline-in-all-cgus #![crate_type="lib"] diff --git a/src/test/codegen-units/partitioning/local-drop-glue.rs b/src/test/codegen-units/partitioning/local-drop-glue.rs index 78d69fdb7d..2fd853a44b 100644 --- a/src/test/codegen-units/partitioning/local-drop-glue.rs +++ b/src/test/codegen-units/partitioning/local-drop-glue.rs @@ -1,8 +1,9 @@ // -// We specify -C incremental here because we want to test the partitioning for +// We specify incremental here because we want to test the partitioning for // incremental compilation // We specify opt-level=0 because `drop_in_place` is `Internal` when optimizing -// compile-flags:-Zprint-mono-items=lazy -Cincremental=tmp/partitioning-tests/local-drop-glue +// incremental +// compile-flags:-Zprint-mono-items=lazy // compile-flags:-Zinline-in-all-cgus -Copt-level=0 #![allow(dead_code)] diff --git a/src/test/codegen-units/partitioning/local-generic.rs b/src/test/codegen-units/partitioning/local-generic.rs index 9a7743bbf4..38aec7291d 100644 --- a/src/test/codegen-units/partitioning/local-generic.rs +++ b/src/test/codegen-units/partitioning/local-generic.rs @@ -1,6 +1,7 @@ -// We specify -C incremental here because we want to test the partitioning for +// We specify incremental here because we want to test the partitioning for // incremental compilation -// compile-flags:-Zprint-mono-items=eager -Cincremental=tmp/partitioning-tests/local-generic +// incremental +// compile-flags:-Zprint-mono-items=eager #![allow(dead_code)] #![crate_type="lib"] diff --git a/src/test/codegen-units/partitioning/local-inlining-but-not-all.rs b/src/test/codegen-units/partitioning/local-inlining-but-not-all.rs index d53f7b6229..318f0c28a5 100644 --- a/src/test/codegen-units/partitioning/local-inlining-but-not-all.rs +++ b/src/test/codegen-units/partitioning/local-inlining-but-not-all.rs @@ -1,7 +1,8 @@ // -// We specify -C incremental here because we want to test the partitioning for +// We specify incremental here because we want to test the partitioning for // incremental compilation -// compile-flags:-Zprint-mono-items=lazy -Cincremental=tmp/partitioning-tests/local-inlining-but-not-all +// incremental +// compile-flags:-Zprint-mono-items=lazy // compile-flags:-Zinline-in-all-cgus=no #![allow(dead_code)] diff --git a/src/test/codegen-units/partitioning/local-inlining.rs b/src/test/codegen-units/partitioning/local-inlining.rs index 1ea804b2f9..841a428e9d 100644 --- a/src/test/codegen-units/partitioning/local-inlining.rs +++ b/src/test/codegen-units/partitioning/local-inlining.rs @@ -1,7 +1,8 @@ // -// We specify -C incremental here because we want to test the partitioning for +// We specify incremental here because we want to test the partitioning for // incremental compilation -// compile-flags:-Zprint-mono-items=lazy -Cincremental=tmp/partitioning-tests/local-inlining +// incremental +// compile-flags:-Zprint-mono-items=lazy // compile-flags:-Zinline-in-all-cgus #![allow(dead_code)] diff --git a/src/test/codegen-units/partitioning/local-transitive-inlining.rs b/src/test/codegen-units/partitioning/local-transitive-inlining.rs index 56d108074e..03c37954d1 100644 --- a/src/test/codegen-units/partitioning/local-transitive-inlining.rs +++ b/src/test/codegen-units/partitioning/local-transitive-inlining.rs @@ -1,7 +1,8 @@ // -// We specify -C incremental here because we want to test the partitioning for +// We specify incremental here because we want to test the partitioning for // incremental compilation -// compile-flags:-Zprint-mono-items=lazy -Cincremental=tmp/partitioning-tests/local-transitive-inlining +// incremental +// compile-flags:-Zprint-mono-items=lazy // compile-flags:-Zinline-in-all-cgus #![allow(dead_code)] diff --git a/src/test/codegen-units/partitioning/methods-are-with-self-type.rs b/src/test/codegen-units/partitioning/methods-are-with-self-type.rs index e67090303a..8220dc12ee 100644 --- a/src/test/codegen-units/partitioning/methods-are-with-self-type.rs +++ b/src/test/codegen-units/partitioning/methods-are-with-self-type.rs @@ -4,9 +4,10 @@ // ignore-test // -// We specify -C incremental here because we want to test the partitioning for +// We specify incremental here because we want to test the partitioning for // incremental compilation -// compile-flags:-Zprint-mono-items=lazy -Cincremental=tmp/partitioning-tests/methods-are-with-self-type +// incremental +// compile-flags:-Zprint-mono-items=lazy #![allow(dead_code)] #![feature(start)] diff --git a/src/test/codegen-units/partitioning/regular-modules.rs b/src/test/codegen-units/partitioning/regular-modules.rs index f9b8f52b0b..ce7fe9c3a4 100644 --- a/src/test/codegen-units/partitioning/regular-modules.rs +++ b/src/test/codegen-units/partitioning/regular-modules.rs @@ -1,6 +1,7 @@ -// We specify -C incremental here because we want to test the partitioning for +// We specify incremental here because we want to test the partitioning for // incremental compilation -// compile-flags:-Zprint-mono-items=eager -Cincremental=tmp/partitioning-tests/regular-modules +// incremental +// compile-flags:-Zprint-mono-items=eager #![allow(dead_code)] #![crate_type="lib"] diff --git a/src/test/codegen-units/partitioning/shared-generics.rs b/src/test/codegen-units/partitioning/shared-generics.rs index 17c1fbb2f7..ebe96bfb74 100644 --- a/src/test/codegen-units/partitioning/shared-generics.rs +++ b/src/test/codegen-units/partitioning/shared-generics.rs @@ -2,7 +2,8 @@ // no-prefer-dynamic // NOTE: We always compile this test with -Copt-level=0 because higher opt-levels // prevent drop-glue from participating in share-generics. -// compile-flags:-Zprint-mono-items=eager -Zshare-generics=yes -Cincremental=tmp/partitioning-tests/shared-generics-exe -Copt-level=0 +// incremental +// compile-flags:-Zprint-mono-items=eager -Zshare-generics=yes -Copt-level=0 #![crate_type="rlib"] diff --git a/src/test/codegen-units/partitioning/statics.rs b/src/test/codegen-units/partitioning/statics.rs index 02d6467577..b11d6696dc 100644 --- a/src/test/codegen-units/partitioning/statics.rs +++ b/src/test/codegen-units/partitioning/statics.rs @@ -1,6 +1,7 @@ -// We specify -C incremental here because we want to test the partitioning for +// We specify incremental here because we want to test the partitioning for // incremental compilation -// compile-flags:-Zprint-mono-items=lazy -Cincremental=tmp/partitioning-tests/statics +// incremental +// compile-flags:-Zprint-mono-items=lazy #![crate_type="rlib"] diff --git a/src/test/codegen-units/partitioning/vtable-through-const.rs b/src/test/codegen-units/partitioning/vtable-through-const.rs index f6ae46b055..cedcca804b 100644 --- a/src/test/codegen-units/partitioning/vtable-through-const.rs +++ b/src/test/codegen-units/partitioning/vtable-through-const.rs @@ -1,8 +1,9 @@ // -// We specify -C incremental here because we want to test the partitioning for +// We specify incremental here because we want to test the partitioning for // incremental compilation -// compile-flags:-Zprint-mono-items=lazy -Cincremental=tmp/partitioning-tests/vtable-through-const +// incremental +// compile-flags:-Zprint-mono-items=lazy // compile-flags:-Zinline-in-all-cgus // This test case makes sure, that references made through constants are diff --git a/src/test/codegen/alloc-optimisation.rs b/src/test/codegen/alloc-optimisation.rs index 5b27f3f454..aee93b93e3 100644 --- a/src/test/codegen/alloc-optimisation.rs +++ b/src/test/codegen/alloc-optimisation.rs @@ -1,4 +1,5 @@ // +// no-system-llvm // min-llvm-version: 10.0.1 // compile-flags: -O #![crate_type="lib"] diff --git a/src/test/codegen/debug-vtable.rs b/src/test/codegen/debug-vtable.rs new file mode 100644 index 0000000000..1c8cc61f20 --- /dev/null +++ b/src/test/codegen/debug-vtable.rs @@ -0,0 +1,57 @@ +// compile-flags: -Cdebuginfo=2 -Copt-level=0 -Ccodegen-units=1 +// ignore-tidy-linelength + +// This test checks the debuginfo for the expected 3 vtables is generated for correct names and number +// of entries. + +// NONMSVC-LABEL: !DIGlobalVariable(name: "::{vtable}" +// MSVC-LABEL: !DIGlobalVariable(name: "impl$::vtable$" +// NONMSVC: !DIDerivedType(tag: DW_TAG_pointer_type, name: "*const ()", +// MSVC: !DIDerivedType(tag: DW_TAG_pointer_type, name: "ptr_const$ >", +// CHECK: !DISubrange(count: 5 + +// NONMSVC-LABEL: !DIGlobalVariable(name: ">::{vtable}" +// MSVC-LABEL: !DIGlobalVariable(name: "impl$ >::vtable$" +// CHECK: !DISubrange(count: 4 + +// NONMSVC-LABEL: !DIGlobalVariable(name: "::{vtable}" +// MSVC-LABEL: !DIGlobalVariable(name: "impl$::vtable$" +// CHECK: !DISubrange(count: 3 + +// NONMSVC-LABEL: !DIGlobalVariable(name: ">)>>::{vtable}" +// MSVC-LABEL: !DIGlobalVariable(name: "impl$,assoc$ > > > > >, {{.*}}, {{.*}}, Some> > > >::vtable$" + +#![crate_type = "lib"] + +pub struct Foo; + +pub trait SomeTrait { + fn method1(&self) -> u32; + fn method2(&self) -> u32; +} + +impl SomeTrait for Foo { + fn method1(&self) -> u32 { 1 } + fn method2(&self) -> u32 { 2 } +} + +pub trait SomeTraitWithGenerics { + fn method1(&self) -> (T, U); +} + +impl SomeTraitWithGenerics for Foo { + fn method1(&self) -> (u64, i8) { (1, 2) } +} + +pub fn foo(x: &Foo) -> (u32, (u64, i8), &dyn Send) { + let y: &dyn SomeTrait = x; + let z: &dyn SomeTraitWithGenerics = x; + (y.method1(), z.method1(), x as &dyn Send) +} + +// Constructing the debuginfo name for the FnOnce vtable below initially caused an ICE on MSVC +// because the trait type contains a late bound region that needed to be erased before the type +// layout for the niche enum `Option<&dyn Fn()>` could be computed. +pub fn bar() -> Box)> { + Box::new(|_x: Option<&dyn Fn()>| {}) +} diff --git a/src/test/codegen/intrinsics/const_eval_select.rs b/src/test/codegen/intrinsics/const_eval_select.rs new file mode 100644 index 0000000000..34e653b4b9 --- /dev/null +++ b/src/test/codegen/intrinsics/const_eval_select.rs @@ -0,0 +1,17 @@ +// compile-flags: -C no-prepopulate-passes + +#![crate_type = "lib"] +#![feature(const_eval_select)] + +use std::intrinsics::const_eval_select; + +const fn foo(_: i32) -> i32 { 1 } + +#[no_mangle] +pub fn hi(n: i32) -> i32 { n } + +#[no_mangle] +pub unsafe fn hey() { + // CHECK: call i32 @hi(i32 + const_eval_select((42,), foo, hi); +} diff --git a/src/test/codegen/panic-in-drop-abort.rs b/src/test/codegen/panic-in-drop-abort.rs new file mode 100644 index 0000000000..39f73c4e39 --- /dev/null +++ b/src/test/codegen/panic-in-drop-abort.rs @@ -0,0 +1,59 @@ +// compile-flags: -Z panic-in-drop=abort -O -Z new-llvm-pass-manager=no + +// Ensure that unwinding code paths are eliminated from the output after +// optimization. + +// This test uses -Z new-llvm-pass-manager=no, because the expected optimization does not happen +// on targets using SEH exceptions (i.e. MSVC) anymore. The core issue is that Rust promises that +// the drop_in_place() function can't unwind, but implements it in a way that *can*, because we +// currently go out of our way to allow longjmps, which also use the unwinding mechanism on MSVC +// targets. We should either forbid longjmps, or not assume nounwind, making this optimization +// incompatible with the current behavior of running cleanuppads on longjmp unwinding. + +// CHECK-NOT: {{(call|invoke).*}}should_not_appear_in_output + +#![crate_type = "lib"] +use std::any::Any; +use std::mem::forget; + +pub struct ExternDrop; +impl Drop for ExternDrop { + #[inline(always)] + fn drop(&mut self) { + // This call may potentially unwind. + extern "Rust" { + fn extern_drop(); + } + unsafe { + extern_drop(); + } + } +} + +struct AssertNeverDrop; +impl Drop for AssertNeverDrop { + #[inline(always)] + fn drop(&mut self) { + // This call should be optimized away as unreachable. + extern "C" { + fn should_not_appear_in_output(); + } + unsafe { + should_not_appear_in_output(); + } + } +} + +#[no_mangle] +pub fn normal_drop(x: ExternDrop) { + let guard = AssertNeverDrop; + drop(x); + forget(guard); +} + +#[no_mangle] +pub fn indirect_drop(x: Box) { + let guard = AssertNeverDrop; + drop(x); + forget(guard); +} diff --git a/src/test/codegen/pic-relocation-model.rs b/src/test/codegen/pic-relocation-model.rs new file mode 100644 index 0000000000..6e1d5a6c3f --- /dev/null +++ b/src/test/codegen/pic-relocation-model.rs @@ -0,0 +1,16 @@ +// compile-flags: -C relocation-model=pic + +#![crate_type = "rlib"] + +// CHECK: define i8 @call_foreign_fn() +#[no_mangle] +pub fn call_foreign_fn() -> u8 { + unsafe { + foreign_fn() + } +} + +// CHECK: declare zeroext i8 @foreign_fn() +extern "C" {fn foreign_fn() -> u8;} + +// CHECK: !{i32 7, !"PIC Level", i32 2} diff --git a/src/test/codegen/pie-relocation-model.rs b/src/test/codegen/pie-relocation-model.rs new file mode 100644 index 0000000000..a843202a94 --- /dev/null +++ b/src/test/codegen/pie-relocation-model.rs @@ -0,0 +1,22 @@ +// compile-flags: -C relocation-model=pie +// only-x86_64-unknown-linux-gnu + +#![crate_type = "rlib"] + +// With PIE we know local functions cannot be interpositioned, we can mark them +// as dso_local. +// CHECK: define dso_local i8 @call_foreign_fn() +#[no_mangle] +pub fn call_foreign_fn() -> u8 { + unsafe { + foreign_fn() + } +} + +// External functions are still marked as non-dso_local, since we don't know if the symbol +// is defined in the binary or in the shared library. +// CHECK: declare zeroext i8 @foreign_fn() +extern "C" {fn foreign_fn() -> u8;} + +// CHECK: !{i32 7, !"PIC Level", i32 2} +// CHECK: !{i32 7, !"PIE Level", i32 2} diff --git a/src/test/codegen/sse42-implies-crc32.rs b/src/test/codegen/sse42-implies-crc32.rs new file mode 100644 index 0000000000..47b1a89934 --- /dev/null +++ b/src/test/codegen/sse42-implies-crc32.rs @@ -0,0 +1,16 @@ +// only-x86_64 +// min-llvm-version: 14.0 +// compile-flags: -Copt-level=3 + +#![crate_type = "lib"] + +#[cfg(target_arch = "x86_64")] +#[target_feature(enable = "sse4.2")] +#[no_mangle] +pub unsafe fn crc32sse(v: u8) -> u32 { + use std::arch::x86_64::*; + let out = !0u32; + _mm_crc32_u8(out, v) +} + +// CHECK: attributes #0 {{.*"target-features"="\+sse4.2,\+crc32"}} diff --git a/src/test/codegen/vtabletype.rs b/src/test/codegen/vtabletype.rs deleted file mode 100644 index 82d65b101b..0000000000 --- a/src/test/codegen/vtabletype.rs +++ /dev/null @@ -1,21 +0,0 @@ -// This test depends on a patch that was committed to upstream LLVM -// after 5.0, then backported to the Rust LLVM fork. - -// ignore-windows -// ignore-macos - -// compile-flags: -g -C no-prepopulate-passes - -// CHECK-LABEL: @main -// CHECK: {{.*}}DICompositeType{{.*}}name: "vtable",{{.*}}vtableHolder:{{.*}} - -pub trait T { -} - -impl T for f64 { -} - -pub fn main() { - let d = 23.0f64; - let td = &d as &T; -} diff --git a/src/test/debuginfo/basic-types.rs b/src/test/debuginfo/basic-types.rs index d300e374be..c8879856b9 100644 --- a/src/test/debuginfo/basic-types.rs +++ b/src/test/debuginfo/basic-types.rs @@ -9,10 +9,6 @@ // This fails on lldb 6.0.1 on x86-64 Fedora 28; so ignore Linux for now. // ignore-linux -// This started failing in windows too. See https://github.com/rust-lang/rust/issues/88796 -// FIXME: fix and unignore this on windows -// ignore-windows - // compile-flags:-g // === GDB TESTS =================================================================================== @@ -132,8 +128,9 @@ // cdb-command:dx f64 // cdb-check:f64 : 3.500000 [Type: double] // cdb-command:.enable_unicode 1 +// FIXME(#88840): The latest version of the Windows SDK broke the visualizer for str. // cdb-command:dx s -// cdb-check:s : "Hello, World!" [Type: str] +// cdb-check:s : [...] [Type: str] #![allow(unused_variables)] #![feature(omit_gdb_pretty_printer_section)] diff --git a/src/test/debuginfo/borrowed-struct.rs b/src/test/debuginfo/borrowed-struct.rs index 7f97d96b8d..fe945266b1 100644 --- a/src/test/debuginfo/borrowed-struct.rs +++ b/src/test/debuginfo/borrowed-struct.rs @@ -63,7 +63,6 @@ // lldbr-check:(f64) *unique_val_interior_ref_2 = 26.5 #![allow(unused_variables)] -#![feature(box_syntax)] #![feature(omit_gdb_pretty_printer_section)] #![omit_gdb_pretty_printer_section] @@ -79,7 +78,7 @@ fn main() { let stack_val_interior_ref_2: &f64 = &stack_val.y; let ref_to_unnamed: &SomeStruct = &SomeStruct { x: 11, y: 24.5 }; - let unique_val: Box<_> = box SomeStruct { x: 13, y: 26.5 }; + let unique_val: Box<_> = Box::new(SomeStruct { x: 13, y: 26.5 }); let unique_val_ref: &SomeStruct = &*unique_val; let unique_val_interior_ref_1: &isize = &unique_val.x; let unique_val_interior_ref_2: &f64 = &unique_val.y; diff --git a/src/test/debuginfo/borrowed-tuple.rs b/src/test/debuginfo/borrowed-tuple.rs index be4895ef53..cc28e49c44 100644 --- a/src/test/debuginfo/borrowed-tuple.rs +++ b/src/test/debuginfo/borrowed-tuple.rs @@ -37,7 +37,6 @@ #![allow(unused_variables)] -#![feature(box_syntax)] #![feature(omit_gdb_pretty_printer_section)] #![omit_gdb_pretty_printer_section] @@ -46,7 +45,7 @@ fn main() { let stack_val_ref: &(i16, f32) = &stack_val; let ref_to_unnamed: &(i16, f32) = &(-15, -20f32); - let unique_val: Box<(i16, f32)> = box (-17, -22f32); + let unique_val: Box<(i16, f32)> = Box::new((-17, -22f32)); let unique_val_ref: &(i16, f32) = &*unique_val; zzz(); // #break diff --git a/src/test/debuginfo/borrowed-unique-basic.rs b/src/test/debuginfo/borrowed-unique-basic.rs index f927a54f02..b39f24e029 100644 --- a/src/test/debuginfo/borrowed-unique-basic.rs +++ b/src/test/debuginfo/borrowed-unique-basic.rs @@ -116,51 +116,50 @@ // lldbr-check:(f64) *f64_ref = 3.5 #![allow(unused_variables)] -#![feature(box_syntax)] #![feature(omit_gdb_pretty_printer_section)] #![omit_gdb_pretty_printer_section] fn main() { - let bool_box: Box = box true; + let bool_box: Box = Box::new(true); let bool_ref: &bool = &*bool_box; - let int_box: Box = box -1; + let int_box: Box = Box::new(-1); let int_ref: &isize = &*int_box; - let char_box: Box = box 'a'; + let char_box: Box = Box::new('a'); let char_ref: &char = &*char_box; - let i8_box: Box = box 68; + let i8_box: Box = Box::new(68); let i8_ref: &i8 = &*i8_box; - let i16_box: Box = box -16; + let i16_box: Box = Box::new(-16); let i16_ref: &i16 = &*i16_box; - let i32_box: Box = box -32; + let i32_box: Box = Box::new(-32); let i32_ref: &i32 = &*i32_box; - let i64_box: Box = box -64; + let i64_box: Box = Box::new(-64); let i64_ref: &i64 = &*i64_box; - let uint_box: Box = box 1; + let uint_box: Box = Box::new(1); let uint_ref: &usize = &*uint_box; - let u8_box: Box = box 100; + let u8_box: Box = Box::new(100); let u8_ref: &u8 = &*u8_box; - let u16_box: Box = box 16; + let u16_box: Box = Box::new(16); let u16_ref: &u16 = &*u16_box; - let u32_box: Box = box 32; + let u32_box: Box = Box::new(32); let u32_ref: &u32 = &*u32_box; - let u64_box: Box = box 64; + let u64_box: Box = Box::new(64); let u64_ref: &u64 = &*u64_box; - let f32_box: Box = box 2.5; + let f32_box: Box = Box::new(2.5); let f32_ref: &f32 = &*f32_box; - let f64_box: Box = box 3.5; + let f64_box: Box = Box::new(3.5); let f64_ref: &f64 = &*f64_box; zzz(); // #break diff --git a/src/test/debuginfo/box.rs b/src/test/debuginfo/box.rs index e443b67ebf..3713c8c135 100644 --- a/src/test/debuginfo/box.rs +++ b/src/test/debuginfo/box.rs @@ -24,13 +24,12 @@ // lldbr-check:((i32, f64)) *b = { 0 = 2 1 = 3.5 } #![allow(unused_variables)] -#![feature(box_syntax)] #![feature(omit_gdb_pretty_printer_section)] #![omit_gdb_pretty_printer_section] fn main() { - let a = box 1; - let b = box (2, 3.5f64); + let a = Box::new(1); + let b = Box::new((2, 3.5f64)); zzz(); // #break } diff --git a/src/test/debuginfo/boxed-struct.rs b/src/test/debuginfo/boxed-struct.rs index 155088c61f..64bc124756 100644 --- a/src/test/debuginfo/boxed-struct.rs +++ b/src/test/debuginfo/boxed-struct.rs @@ -28,7 +28,6 @@ // lldbr-check:(boxed_struct::StructWithDestructor) *boxed_with_dtor = { x = 77 y = 777 z = 7777 w = 77777 } #![allow(unused_variables)] -#![feature(box_syntax)] #![feature(omit_gdb_pretty_printer_section)] #![omit_gdb_pretty_printer_section] @@ -52,9 +51,19 @@ impl Drop for StructWithDestructor { fn main() { - let boxed_with_padding: Box<_> = box StructWithSomePadding { x: 99, y: 999, z: 9999, w: 99999 }; + let boxed_with_padding: Box<_> = Box::new(StructWithSomePadding { + x: 99, + y: 999, + z: 9999, + w: 99999, + }); - let boxed_with_dtor: Box<_> = box StructWithDestructor { x: 77, y: 777, z: 7777, w: 77777 }; + let boxed_with_dtor: Box<_> = Box::new(StructWithDestructor { + x: 77, + y: 777, + z: 7777, + w: 77777, + }); zzz(); // #break } diff --git a/src/test/debuginfo/closure-in-generic-function.rs b/src/test/debuginfo/closure-in-generic-function.rs index 239055b3a7..91d7ddc541 100644 --- a/src/test/debuginfo/closure-in-generic-function.rs +++ b/src/test/debuginfo/closure-in-generic-function.rs @@ -39,7 +39,6 @@ // lldbr-check:(i32) *y = 110 // lldb-command:continue -#![feature(box_syntax)] #![feature(omit_gdb_pretty_printer_section)] #![omit_gdb_pretty_printer_section] diff --git a/src/test/debuginfo/destructured-fn-argument.rs b/src/test/debuginfo/destructured-fn-argument.rs index a776f51907..9cd3874a5d 100644 --- a/src/test/debuginfo/destructured-fn-argument.rs +++ b/src/test/debuginfo/destructured-fn-argument.rs @@ -358,7 +358,6 @@ #![allow(unused_variables)] #![feature(box_patterns)] -#![feature(box_syntax)] #![feature(omit_gdb_pretty_printer_section)] #![omit_gdb_pretty_printer_section] @@ -480,7 +479,7 @@ fn main() { managed_box(&(34, 35)); borrowed_pointer(&(36, 37)); contained_borrowed_pointer((&38, 39)); - unique_pointer(box (40, 41, 42)); + unique_pointer(Box::new((40, 41, 42))); ref_binding((43, 44, 45)); ref_binding_in_tuple((46, (47, 48))); ref_binding_in_struct(Struct { a: 49, b: 50 }); diff --git a/src/test/debuginfo/destructured-for-loop-variable.rs b/src/test/debuginfo/destructured-for-loop-variable.rs index 1532c83dfa..15cb88ef25 100644 --- a/src/test/debuginfo/destructured-for-loop-variable.rs +++ b/src/test/debuginfo/destructured-for-loop-variable.rs @@ -173,7 +173,6 @@ #![allow(unused_variables)] #![feature(box_patterns)] -#![feature(box_syntax)] #![feature(omit_gdb_pretty_printer_section)] #![omit_gdb_pretty_printer_section] @@ -214,7 +213,7 @@ fn main() { y: -300001.5, z: true }, - box 854237.5); + Box::new(854237.5)); for &(v1, &Struct { x: x1, y: ref y1, z: z1 }, diff --git a/src/test/debuginfo/destructured-local.rs b/src/test/debuginfo/destructured-local.rs index 712168b5ba..3a2a889777 100644 --- a/src/test/debuginfo/destructured-local.rs +++ b/src/test/debuginfo/destructured-local.rs @@ -285,7 +285,6 @@ #![allow(unused_variables)] #![feature(box_patterns)] -#![feature(box_syntax)] #![feature(omit_gdb_pretty_printer_section)] #![omit_gdb_pretty_printer_section] @@ -345,7 +344,7 @@ fn main() { let (&cc, _) = (&38, 39); // unique pointer - let box dd = box (40, 41, 42); + let box dd = Box::new((40, 41, 42)); // ref binding let ref ee = (43, 44, 45); diff --git a/src/test/debuginfo/function-names.rs b/src/test/debuginfo/function-names.rs index dec25bb4c2..61d5fc93cd 100644 --- a/src/test/debuginfo/function-names.rs +++ b/src/test/debuginfo/function-names.rs @@ -9,36 +9,37 @@ // gdb-command:info functions -q function_names::main // gdb-check:[...]static fn function_names::main(); // gdb-command:info functions -q function_names::generic_func<* -// gdb-check:[...]static fn function_names::generic_func(i32) -> i32; +// gdb-check:[...]static fn function_names::generic_func(i32) -> i32; // Implementations // gdb-command:info functions -q function_names::.*::impl_function.* -// gdb-check:[...]static fn function_names::GenericStruct::impl_function(); +// gdb-check:[...]static fn function_names::GenericStruct::impl_function(); // gdb-check:[...]static fn function_names::Mod1::TestStruct2::impl_function(); // gdb-check:[...]static fn function_names::TestStruct1::impl_function(); // Trait implementations // gdb-command:info functions -q function_names::.*::trait_function.* -// gdb-check:[...]static fn as function_names::TestTrait1>::trait_function(); -// gdb-check:[...]static fn as function_names::TestTrait1>::trait_function(); -// gdb-check:[...]static fn ::trait_function(); -// gdb-check:[...]static fn ::trait_function(); +// gdb-check:[...]static fn function_names::Mod1::{impl#1}::trait_function(); +// gdb-check:[...]static fn function_names::{impl#1}::trait_function(); +// gdb-check:[...]static fn function_names::{impl#3}::trait_function(); +// gdb-check:[...]static fn function_names::{impl#5}::trait_function3(); +// gdb-check:[...]static fn function_names::{impl#6}::trait_function(); // Closure -// gdb-command:info functions -q function_names::.*::{{closure.* -// gdb-check:[...]static fn function_names::GenericStruct::impl_function::{{closure}}(*mut function_names::{impl#2}::impl_function::{closure#0}); -// gdb-check:[...]static fn function_names::generic_func::{{closure}}(*mut function_names::generic_func::{closure#0}); -// gdb-check:[...]static fn function_names::main::{{closure}}(*mut function_names::main::{closure#0}); +// gdb-command:info functions -q function_names::.*::{closure.* +// gdb-check:[...]static fn function_names::generic_func::{closure#0}(*mut function_names::generic_func::{closure#0}); +// gdb-check:[...]static fn function_names::main::{closure#0}(*mut function_names::main::{closure#0}); +// gdb-check:[...]static fn function_names::{impl#2}::impl_function::{closure#0}(*mut function_names::{impl#2}::impl_function::{closure#0}); // Generator // Generators don't seem to appear in GDB's symbol table. // Const generic parameter // gdb-command:info functions -q function_names::const_generic_fn.* -// gdb-check:[...]static fn function_names::const_generic_fn_bool(); -// gdb-check:[...]static fn function_names::const_generic_fn_non_int(); -// gdb-check:[...]static fn function_names::const_generic_fn_signed_int(); -// gdb-check:[...]static fn function_names::const_generic_fn_unsigned_int(); +// gdb-check:[...]static fn function_names::const_generic_fn_bool(); +// gdb-check:[...]static fn function_names::const_generic_fn_non_int<{CONST#fe3cfa0214ac55c7}>(); +// gdb-check:[...]static fn function_names::const_generic_fn_signed_int<-7>(); +// gdb-check:[...]static fn function_names::const_generic_fn_unsigned_int<14>(); // === CDB TESTS =================================================================================== @@ -103,7 +104,7 @@ fn main() { GenericStruct::::trait_function3(); // Generic function - let _ = generic_func(42); + let _ = generic_func(42i32); // Closure let closure = || { TestStruct1 }; diff --git a/src/test/debuginfo/generic-method-on-generic-struct.rs b/src/test/debuginfo/generic-method-on-generic-struct.rs index 85fe8ac08f..97609ef5d9 100644 --- a/src/test/debuginfo/generic-method-on-generic-struct.rs +++ b/src/test/debuginfo/generic-method-on-generic-struct.rs @@ -123,7 +123,6 @@ // lldbr-check:(f32) arg2 = -10.5 // lldb-command:continue -#![feature(box_syntax)] #![feature(omit_gdb_pretty_printer_section)] #![omit_gdb_pretty_printer_section] @@ -155,7 +154,7 @@ fn main() { let _ = stack.self_by_ref(-1, 2_u16); let _ = stack.self_by_val(-3, -4_i16); - let owned: Box<_> = box Struct { x: 1234.5f64 }; + let owned: Box<_> = Box::new(Struct { x: 1234.5f64 }); let _ = owned.self_by_ref(-5, -6_i32); let _ = owned.self_by_val(-7, -8_i64); let _ = owned.self_owned(-9, -10.5_f32); diff --git a/src/test/debuginfo/method-on-enum.rs b/src/test/debuginfo/method-on-enum.rs index 80f4c2e115..aaa9bd9d6f 100644 --- a/src/test/debuginfo/method-on-enum.rs +++ b/src/test/debuginfo/method-on-enum.rs @@ -107,7 +107,6 @@ // lldb-check:[...]$14 = -10 // lldb-command:continue -#![feature(box_syntax)] #![feature(omit_gdb_pretty_printer_section)] #![omit_gdb_pretty_printer_section] @@ -140,7 +139,7 @@ fn main() { let _ = stack.self_by_ref(-1, -2); let _ = stack.self_by_val(-3, -4); - let owned: Box<_> = box Enum::Variant1{ x: 1799, y: 1799 }; + let owned: Box<_> = Box::new(Enum::Variant1{ x: 1799, y: 1799 }); let _ = owned.self_by_ref(-5, -6); let _ = owned.self_by_val(-7, -8); let _ = owned.self_owned(-9, -10); diff --git a/src/test/debuginfo/method-on-generic-struct.rs b/src/test/debuginfo/method-on-generic-struct.rs index 80cbf7430c..bf04744916 100644 --- a/src/test/debuginfo/method-on-generic-struct.rs +++ b/src/test/debuginfo/method-on-generic-struct.rs @@ -123,8 +123,6 @@ // lldbr-check:(isize) arg2 = -10 // lldb-command:continue - -#![feature(box_syntax)] #![feature(omit_gdb_pretty_printer_section)] #![omit_gdb_pretty_printer_section] @@ -156,7 +154,7 @@ fn main() { let _ = stack.self_by_ref(-1, -2); let _ = stack.self_by_val(-3, -4); - let owned: Box<_> = box Struct { x: 1234.5f64 }; + let owned: Box<_> = Box::new(Struct { x: 1234.5f64 }); let _ = owned.self_by_ref(-5, -6); let _ = owned.self_by_val(-7, -8); let _ = owned.self_owned(-9, -10); diff --git a/src/test/debuginfo/method-on-struct.rs b/src/test/debuginfo/method-on-struct.rs index c764cf6832..deed4f9cc0 100644 --- a/src/test/debuginfo/method-on-struct.rs +++ b/src/test/debuginfo/method-on-struct.rs @@ -121,8 +121,6 @@ // lldbr-check:(isize) arg2 = -10 // lldb-command:continue - -#![feature(box_syntax)] #![feature(omit_gdb_pretty_printer_section)] #![omit_gdb_pretty_printer_section] @@ -154,7 +152,7 @@ fn main() { let _ = stack.self_by_ref(-1, -2); let _ = stack.self_by_val(-3, -4); - let owned: Box<_> = box Struct { x: 200 }; + let owned: Box<_> = Box::new(Struct { x: 200 }); let _ = owned.self_by_ref(-5, -6); let _ = owned.self_by_val(-7, -8); let _ = owned.self_owned(-9, -10); diff --git a/src/test/debuginfo/method-on-trait.rs b/src/test/debuginfo/method-on-trait.rs index 6dcf289677..7ebebfa72b 100644 --- a/src/test/debuginfo/method-on-trait.rs +++ b/src/test/debuginfo/method-on-trait.rs @@ -121,8 +121,6 @@ // lldbr-check:(isize) arg2 = -10 // lldb-command:continue - -#![feature(box_syntax)] #![feature(omit_gdb_pretty_printer_section)] #![omit_gdb_pretty_printer_section] @@ -160,7 +158,7 @@ fn main() { let _ = stack.self_by_ref(-1, -2); let _ = stack.self_by_val(-3, -4); - let owned: Box<_> = box Struct { x: 200 }; + let owned: Box<_> = Box::new(Struct { x: 200 }); let _ = owned.self_by_ref(-5, -6); let _ = owned.self_by_val(-7, -8); let _ = owned.self_owned(-9, -10); diff --git a/src/test/debuginfo/method-on-tuple-struct.rs b/src/test/debuginfo/method-on-tuple-struct.rs index d06b606e97..a5a87b2ad6 100644 --- a/src/test/debuginfo/method-on-tuple-struct.rs +++ b/src/test/debuginfo/method-on-tuple-struct.rs @@ -121,8 +121,6 @@ // lldbr-check:(isize) arg2 = -10 // lldb-command:continue - -#![feature(box_syntax)] #![feature(omit_gdb_pretty_printer_section)] #![omit_gdb_pretty_printer_section] @@ -152,7 +150,7 @@ fn main() { let _ = stack.self_by_ref(-1, -2); let _ = stack.self_by_val(-3, -4); - let owned: Box<_> = box TupleStruct(200, -200.5); + let owned: Box<_> = Box::new(TupleStruct(200, -200.5)); let _ = owned.self_by_ref(-5, -6); let _ = owned.self_by_val(-7, -8); let _ = owned.self_owned(-9, -10); diff --git a/src/test/debuginfo/msvc-pretty-enums.rs b/src/test/debuginfo/msvc-pretty-enums.rs index 67b5da510f..642694355a 100644 --- a/src/test/debuginfo/msvc-pretty-enums.rs +++ b/src/test/debuginfo/msvc-pretty-enums.rs @@ -1,67 +1,45 @@ // only-cdb -// ignore-tidy-linelength // compile-flags:-g -// This started failing recently. See https://github.com/rust-lang/rust/issues/88796 -// FIXME: fix and unignore this -// ignore-windows - // cdb-command: g -// Note: The natvis used to visualize niche-layout enums don't work correctly in cdb -// so the best we can do is to make sure we are generating the right debuginfo. -// Therefore, we use the `!` [format specifier](https://docs.microsoft.com/en-us/visualstudio/debugger/format-specifiers-in-cpp?view=vs-2019#BKMK_Visual_Studio_2012_format_specifiers) -// to disable the natvis for a given expression. We also provide the `-r2` flag -// to expand the expression 2 levels. +// cdb-command: dx a +// cdb-check:a : Some({...}) [Type: enum$ >, 2, 16, Some>] +// cdb-check: [] [Type: enum$ >, 2, 16, Some>] +// cdb-check: [variant] : Some +// cdb-check: [+0x000] __0 : Low (0x2) [Type: msvc_pretty_enums::CStyleEnum] -// cdb-command: dx -r2 a,! -// cdb-check:a,! [Type: enum$ >, 2, 16, Some>] -// cdb-check: [+0x000] dataful_variant [Type: enum$ >, 2, 16, Some>::Some] -// cdb-check: [+0x000] __0 : Low (0x2) [Type: msvc_pretty_enums::CStyleEnum] -// cdb-check: [+0x000] discriminant : 0x2 [Type: enum$ >, 2, 16, Some>::Discriminant$] +// cdb-command: dx b +// cdb-check:b : None [Type: enum$ >, 2, 16, Some>] +// cdb-check: [] [Type: enum$ >, 2, 16, Some>] +// cdb-check: [variant] : None -// cdb-command: dx -r2 b,! -// cdb-check:b,! [Type: enum$ >, 2, 16, Some>] -// cdb-check: [+0x000] dataful_variant [Type: enum$ >, 2, 16, Some>::Some] -// cdb-check: [+0x000] __0 : 0x11 [Type: msvc_pretty_enums::CStyleEnum] -// cdb-check: [+0x000] discriminant : None (0x11) [Type: enum$ >, 2, 16, Some>::Discriminant$] +// cdb-command: dx c +// cdb-check:c : Tag1 [Type: enum$] +// cdb-check: [] [Type: enum$] +// cdb-check: [variant] : Tag1 -// cdb-command: dx -r2 c,! -// cdb-check:c,! [Type: enum$] -// cdb-check: [+0x000] dataful_variant [Type: enum$::Data] -// cdb-check: [+0x000] my_data : 0x11 [Type: msvc_pretty_enums::CStyleEnum] -// cdb-check: [+0x000] discriminant : Tag1 (0x11) [Type: enum$::Discriminant$] +// cdb-command: dx d +// cdb-check:d : Data({...}) [Type: enum$] +// cdb-check: [] [Type: enum$] +// cdb-check: [variant] : Data +// cdb-check: [+0x000] my_data : High (0x10) [Type: msvc_pretty_enums::CStyleEnum] -// cdb-command: dx -r2 d,! -// cdb-check:d,! [Type: enum$] -// cdb-check: [+0x000] dataful_variant [Type: enum$::Data] -// cdb-check: [+0x000] my_data : High (0x10) [Type: msvc_pretty_enums::CStyleEnum] -// cdb-check: [+0x000] discriminant : 0x10 [Type: enum$::Discriminant$] +// cdb-command: dx e +// cdb-check:e : Tag2 [Type: enum$] +// cdb-check: [] [Type: enum$] +// cdb-check: [variant] : Tag2 -// cdb-command: dx -r2 e,! -// cdb-check:e,! [Type: enum$] -// cdb-check: [+0x000] dataful_variant [Type: enum$::Data] -// cdb-check: [+0x000] my_data : 0x13 [Type: msvc_pretty_enums::CStyleEnum] -// cdb-check: [+0x000] discriminant : Tag2 (0x13) [Type: enum$::Discriminant$] +// cdb-command: dx f +// cdb-check:f : Some({...}) [Type: enum$ >, 1, [...], Some>] +// cdb-check: [] [Type: enum$ >, 1, [...], Some>] +// cdb-check: [variant] : Some +// cdb-check: [+0x000] __0 : 0x[...] : 0x1 [Type: unsigned int *] -// cdb-command: dx -r2 f,! -// cdb-check:f,! [Type: enum$ >, 1, [...], Some>] -// cdb-check: [+0x000] dataful_variant [Type: enum$ >, 1, [...], Some>::Some] -// cdb-check: [+0x000] __0 : 0x[...] : 0x1 [Type: unsigned int *] -// cdb-check: [+0x000] discriminant : 0x[...] [Type: enum$ >, 1, [...], Some>::Discriminant$] - -// cdb-command: dx -r2 g,! -// cdb-check:g,! [Type: enum$ >, 1, [...], Some>] -// cdb-check: [+0x000] dataful_variant [Type: enum$ >, 1, [...], Some>::Some] -// cdb-check: [+0x000] __0 : 0x0 [Type: unsigned int *] -// cdb-check: [+0x000] discriminant : None (0x0) [Type: enum$ >, 1, [...], Some>::Discriminant$] - -// cdb-command: dx -r2 h,! -// cdb-check:h,! : Some [Type: enum$ >] -// cdb-check: [+0x000] variant0 [Type: enum$ >::None] -// cdb-check: [+0x000] variant1 [Type: enum$ >::Some] -// cdb-check: [+0x004] __0 : 0xc [Type: unsigned int] -// cdb-check: [+0x000] discriminant : Some (0x1) [Type: core::option::Option] +// cdb-command: dx g +// cdb-check:g : None [Type: enum$ >, 1, [...], Some>] +// cdb-check: [] [Type: enum$ >, 1, [...], Some>] +// cdb-check: [variant] : None // cdb-command: dx h // cdb-check:h : Some [Type: enum$ >] @@ -69,13 +47,6 @@ // cdb-check: [variant] : Some // cdb-check: [+0x004] __0 : 0xc [Type: unsigned int] -// cdb-command: dx -r2 i,! -// cdb-check:i,! : None [Type: enum$ >] -// cdb-check: [+0x000] variant0 [Type: enum$ >::None] -// cdb-check: [+0x000] variant1 [Type: enum$ >::Some] -// cdb-check: [+0x004] __0 : 0x[...] [Type: unsigned int] -// cdb-check: [+0x000] discriminant : None (0x0) [Type: core::option::Option] - // cdb-command: dx i // cdb-check:i : None [Type: enum$ >] // cdb-check: [] [Type: enum$ >] @@ -84,16 +55,17 @@ // cdb-command: dx j // cdb-check:j : High (0x10) [Type: msvc_pretty_enums::CStyleEnum] -// cdb-command: dx -r2 k,! -// cdb-check:k,! [Type: enum$, 1, [...], Some>] -// cdb-check: [+0x000] dataful_variant [Type: enum$, 1, [...], Some>::Some] -// cdb-check: [+0x000] __0 [Type: alloc::string::String] -// cdb-check: [+0x000] discriminant : 0x[...] [Type: enum$, 1, [...], Some>::Discriminant$] +// cdb-command: dx k +// cdb-check:k : Some({...}) [Type: enum$, 1, [...], Some>] +// cdb-check: [] [Type: enum$, 1, [...], Some>] +// cdb-check: [variant] : Some +// cdb-check: [+0x000] __0 : "IAMA optional string!" [Type: alloc::string::String] -// cdb-command: dx -r2 l,! -// cdb-check:l,! : $T2 [Type: enum$ >, Ok>] -// cdb-check: [+0x000] Ok [Type: enum$ >, Ok>::Ok] -// cdb-check: [+0x000] __0 : 0x2a [Type: unsigned int] +// cdb-command: dx l +// cdb-check:l : Ok [Type: enum$ >, Ok>] +// cdb-check: [] [Type: enum$ >, Ok>] +// cdb-check: [variant] : Ok +// cdb-check: [+0x000] __0 : 0x2a [Type: unsigned int] pub enum CStyleEnum { Low = 2, diff --git a/src/test/debuginfo/msvc-scalarpair-params.rs b/src/test/debuginfo/msvc-scalarpair-params.rs new file mode 100644 index 0000000000..3846fb42f8 --- /dev/null +++ b/src/test/debuginfo/msvc-scalarpair-params.rs @@ -0,0 +1,101 @@ +// only-cdb +// compile-flags: -g + +// cdb-command: g + +// cdb-command: dx r1 +// cdb-check:r1 : (0xa..0xc) [Type: core::ops::range::Range] +// cdb-command: dx r2 +// cdb-check:r2 : (0x14..0x1e) [Type: core::ops::range::Range] + +// cdb-command: g + +// cdb-command: dx r1 +// cdb-check:r1 : (0x9..0x64) [Type: core::ops::range::Range] +// cdb-command: dx r2 +// cdb-check:r2 : (0xc..0x5a) [Type: core::ops::range::Range] + +// cdb-command: g + +// cdb-command: dx o1 +// cdb-check:o1 : Some [Type: enum$ >] +// cdb-check: [variant] : Some +// cdb-check: [+0x004] __0 : 0x4d2 [Type: [...]] +// cdb-command: dx o2 +// cdb-check:o2 : Some [Type: enum$ >] +// cdb-check: [variant] : Some +// cdb-check: [+0x008] __0 : 0x162e [Type: unsigned __int64] + +// cdb-command: g + +// cdb-command: dx t1 +// cdb-check:t1 : (0xa, 0x14) [Type: tuple$] +// cdb-check: [0] : 0xa [Type: unsigned int] +// cdb-check: [1] : 0x14 [Type: unsigned int] +// cdb-command: dx t2 +// cdb-check:t2 : (0x1e, 0x28) [Type: tuple$] +// cdb-check: [0] : 0x1e [Type: unsigned __int64] +// cdb-check: [1] : 0x28 [Type: unsigned __int64] + +// cdb-command: g + +// cdb-command: dx s +// cdb-check:s : "this is a static str" [Type: str] +// cdb-check: [len] : 0x14 [Type: unsigned [...]] +// cdb-check: [chars] + +// cdb-command: g + +// cdb-command: dx s +// cdb-check:s : { len=0x5 } [Type: slice$] +// cdb-check: [len] : 0x5 [Type: unsigned [...]] +// cdb-check: [0] : 0x1 [Type: unsigned char] +// cdb-check: [1] : 0x2 [Type: unsigned char] +// cdb-check: [2] : 0x3 [Type: unsigned char] +// cdb-check: [3] : 0x4 [Type: unsigned char] +// cdb-check: [4] : 0x5 [Type: unsigned char] + +use std::ops::Range; + +fn range(r1: Range, r2: Range) { + zzz(); // #break +} + +fn range_mut(mut r1: Range, mut r2: Range) { + if r1.start == 9 { + r1.end = 100; + } + + if r2.start == 12 { + r2.end = 90; + } + + zzz(); // #break +} + +fn option(o1: Option, o2: Option) { + zzz(); // #break +} + +fn tuple(t1: (u32, u32), t2: (u64, u64)) { + zzz(); // #break +} + +fn str(s: &str) { + zzz(); // #break +} + +fn slice(s: &[u8]) { + zzz(); // #break +} + +fn zzz() { } + +fn main() { + range(10..12, 20..30); + range_mut(9..20, 12..80); + option(Some(1234), Some(5678)); + tuple((10, 20), (30, 40)); + str("this is a static str"); + slice(&[1, 2, 3, 4, 5]); +} diff --git a/src/test/debuginfo/mutex.rs b/src/test/debuginfo/mutex.rs index 4a529541ba..00dccf5f90 100644 --- a/src/test/debuginfo/mutex.rs +++ b/src/test/debuginfo/mutex.rs @@ -3,8 +3,6 @@ // cdb-only // min-cdb-version: 10.0.21287.1005 // compile-flags:-g -// FIXME: Failed on update to 10.0.22000.1 -// ignore-windows // === CDB TESTS ================================================================================== // @@ -14,17 +12,17 @@ // cdb-check:m,d [Type: std::sync::mutex::Mutex] // cdb-check: [...] inner [Type: std::sys_common::mutex::MovableMutex] // cdb-check: [...] poison [Type: std::sync::poison::Flag] -// cdb-check: [...] data [Type: core::cell::UnsafeCell] +// cdb-check: [...] data : 0 [Type: core::cell::UnsafeCell] // // cdb-command:dx m.data,d -// cdb-check:m.data,d [Type: core::cell::UnsafeCell] -// cdb-check: [...] value : 0 [Type: int] +// cdb-check:m.data,d : 0 [Type: core::cell::UnsafeCell] +// cdb-check: [] [Type: core::cell::UnsafeCell] // // cdb-command:dx lock,d -// cdb-check:lock,d : Ok [Type: enum$, enum$ >, 0, 1, Poisoned> > >] -// cdb-check: [...] variant$ : Ok (0) [Type: core::result::Result] +// cdb-check:lock,d : Ok [Type: enum$,enum$ >, 0, 1, Poisoned> > >] +// cdb-check: [variant] : Ok // cdb-check: [...] __0 [Type: std::sync::mutex::MutexGuard] use std::sync::Mutex; diff --git a/src/test/debuginfo/pretty-std.rs b/src/test/debuginfo/pretty-std.rs index cb2e6c618b..55a4ecc1c1 100644 --- a/src/test/debuginfo/pretty-std.rs +++ b/src/test/debuginfo/pretty-std.rs @@ -6,10 +6,6 @@ // min-lldb-version: 310 // min-cdb-version: 10.0.18317.1001 -// This started failing recently. See https://github.com/rust-lang/rust/issues/88796 -// FIXME: fix and unignore this -// ignore-windows - // === GDB TESTS =================================================================================== // gdb-command: run @@ -115,9 +111,11 @@ // cdb-check: [11] : 33 '!' [Type: char] // cdb-command: dx os_string -// cdb-check:os_string : "IAMA OS string 😃" [Type: std::ffi::os_str::OsString] +// NOTE: OSString is WTF-8 encoded which Windows debuggers don't understand. Verify the UTF-8 +// portion displays correctly. +// cdb-check:os_string : "IAMA OS string [...]" [Type: std::ffi::os_str::OsString] // cdb-check: [] [Type: std::ffi::os_str::OsString] -// cdb-check: [chars] : "IAMA OS string 😃" +// cdb-check: [chars] : "IAMA OS string [...]" // cdb-command: dx some // cdb-check:some : Some [Type: enum$ >] @@ -131,8 +129,10 @@ // cdb-check: [variant] : None // cdb-command: dx some_string -// NOTE: cdb fails to interpret debug info of Option enums on i686. -// cdb-check:some_string [Type: enum$, 1, [...], Some>] +// cdb-check:some_string : Some({...}) [Type: enum$, 1, [...], Some>] +// cdb-check: [] [Type: enum$, 1, [...], Some>] +// cdb-check: [variant] : Some +// cdb-check: [+0x000] __0 : "IAMA optional string!" [Type: alloc::string::String] // cdb-command: dx linkedlist // cdb-check:linkedlist : { len=0x2 } [Type: alloc::collections::linked_list::LinkedList] diff --git a/src/test/debuginfo/recursive-struct.rs b/src/test/debuginfo/recursive-struct.rs index c0bd673670..eb14af8c58 100644 --- a/src/test/debuginfo/recursive-struct.rs +++ b/src/test/debuginfo/recursive-struct.rs @@ -52,20 +52,20 @@ // gdb-command:print long_cycle4.value // gdb-check:$18 = 29.5 -// gdbr-command:print long_cycle_w_anonymous_types.value +// gdbr-command:print long_cycle_w_anon_types.value // gdb-check:$19 = 30 -// gdbr-command:print long_cycle_w_anonymous_types.next.val.value +// gdbr-command:print long_cycle_w_anon_types.next.val.value // gdb-check:$20 = 31 // gdb-command:continue #![allow(unused_variables)] -#![feature(box_syntax)] #![feature(omit_gdb_pretty_printer_section)] #![omit_gdb_pretty_printer_section] use self::Opt::{Empty, Val}; +use std::boxed::Box as B; enum Opt { Empty, @@ -120,75 +120,75 @@ struct LongCycleWithAnonymousTypes { fn main() { let stack_unique: UniqueNode = UniqueNode { next: Val { - val: box UniqueNode { + val: Box::new(UniqueNode { next: Empty, value: 1, - } + }) }, value: 0, }; - let unique_unique: Box> = box UniqueNode { + let unique_unique: Box> = Box::new(UniqueNode { next: Val { - val: box UniqueNode { + val: Box::new(UniqueNode { next: Empty, value: 3, - } + }) }, value: 2, - }; + }); let vec_unique: [UniqueNode; 1] = [UniqueNode { next: Val { - val: box UniqueNode { + val: Box::new(UniqueNode { next: Empty, value: 7.5, - } + }) }, value: 6.5, }]; let borrowed_unique: &UniqueNode = &UniqueNode { next: Val { - val: box UniqueNode { + val: Box::new(UniqueNode { next: Empty, value: 9.5, - } + }) }, value: 8.5, }; // LONG CYCLE let long_cycle1: LongCycle1 = LongCycle1 { - next: box LongCycle2 { - next: box LongCycle3 { - next: box LongCycle4 { + next: Box::new(LongCycle2 { + next: Box::new(LongCycle3 { + next: Box::new(LongCycle4 { next: None, value: 23, - }, + }), value: 22, - }, + }), value: 21 - }, + }), value: 20 }; let long_cycle2: LongCycle2 = LongCycle2 { - next: box LongCycle3 { - next: box LongCycle4 { + next: Box::new(LongCycle3 { + next: Box::new(LongCycle4 { next: None, value: 26, - }, + }), value: 25, - }, + }), value: 24 }; let long_cycle3: LongCycle3 = LongCycle3 { - next: box LongCycle4 { + next: Box::new(LongCycle4 { next: None, value: 28, - }, + }), value: 27, }; @@ -199,15 +199,15 @@ fn main() { // It's important that LongCycleWithAnonymousTypes is encountered only at the end of the // `box` chain. - let long_cycle_w_anonymous_types = box box box box box LongCycleWithAnonymousTypes { + let long_cycle_w_anon_types = B::new(B::new(B::new(B::new(B::new(LongCycleWithAnonymousTypes { next: Val { - val: box box box box box LongCycleWithAnonymousTypes { + val: Box::new(Box::new(Box::new(Box::new(Box::new(LongCycleWithAnonymousTypes { next: Empty, value: 31, - } + }))))) }, value: 30 - }; + }))))); zzz(); // #break } diff --git a/src/test/debuginfo/self-in-default-method.rs b/src/test/debuginfo/self-in-default-method.rs index e15c08577e..b8b5add099 100644 --- a/src/test/debuginfo/self-in-default-method.rs +++ b/src/test/debuginfo/self-in-default-method.rs @@ -121,7 +121,6 @@ // lldbr-check:(isize) arg2 = -10 // lldb-command:continue -#![feature(box_syntax)] #![feature(omit_gdb_pretty_printer_section)] #![omit_gdb_pretty_printer_section] @@ -154,7 +153,7 @@ fn main() { let _ = stack.self_by_ref(-1, -2); let _ = stack.self_by_val(-3, -4); - let owned: Box<_> = box Struct { x: 200 }; + let owned: Box<_> = Box::new(Struct { x: 200 }); let _ = owned.self_by_ref(-5, -6); let _ = owned.self_by_val(-7, -8); let _ = owned.self_owned(-9, -10); diff --git a/src/test/debuginfo/self-in-generic-default-method.rs b/src/test/debuginfo/self-in-generic-default-method.rs index 7634e3247d..efce449e31 100644 --- a/src/test/debuginfo/self-in-generic-default-method.rs +++ b/src/test/debuginfo/self-in-generic-default-method.rs @@ -121,7 +121,6 @@ // lldbr-check:(f32) arg2 = -10.5 // lldb-command:continue -#![feature(box_syntax)] #![feature(omit_gdb_pretty_printer_section)] #![omit_gdb_pretty_printer_section] @@ -155,7 +154,7 @@ fn main() { let _ = stack.self_by_ref(-1, 2_u16); let _ = stack.self_by_val(-3, -4_i16); - let owned: Box<_> = box Struct { x: 879 }; + let owned: Box<_> = Box::new(Struct { x: 879 }); let _ = owned.self_by_ref(-5, -6_i32); let _ = owned.self_by_val(-7, -8_i64); let _ = owned.self_owned(-9, -10.5_f32); diff --git a/src/test/debuginfo/trait-pointers.rs b/src/test/debuginfo/trait-pointers.rs index a44f30abd6..e12daaf114 100644 --- a/src/test/debuginfo/trait-pointers.rs +++ b/src/test/debuginfo/trait-pointers.rs @@ -5,7 +5,6 @@ // lldb-command:run #![allow(unused_variables)] -#![feature(box_syntax)] #![feature(omit_gdb_pretty_printer_section)] #![omit_gdb_pretty_printer_section] @@ -24,5 +23,5 @@ impl Trait for Struct {} fn main() { let stack_struct = Struct { a:0, b: 1.0 }; let reference: &Trait = &stack_struct as &Trait; - let unique: Box = box Struct { a:2, b: 3.0 } as Box; + let unique: Box = Box::new(Struct { a:2, b: 3.0 }) as Box; } diff --git a/src/test/debuginfo/type-names.rs b/src/test/debuginfo/type-names.rs index 3497f0afb2..2c10360fc9 100644 --- a/src/test/debuginfo/type-names.rs +++ b/src/test/debuginfo/type-names.rs @@ -262,7 +262,6 @@ // cdb-check:struct ForeignType2 * foreign2 = [...] // cdb-check:struct ForeignType1 * foreign1 = [...] -#![feature(box_syntax)] #![allow(unused_variables)] #![feature(omit_gdb_pretty_printer_section)] #![omit_gdb_pretty_printer_section] @@ -373,8 +372,8 @@ fn main() { let tuple2 = ((Struct1, mod1::mod2::Struct3), mod1::Variant1, 'x'); // Box - let box1 = (box 1f32, 0i32); - let box2 = (box mod1::mod2::Variant2(1f32), 0i32); + let box1 = (Box::new(1f32), 0i32); + let box2 = (Box::new(mod1::mod2::Variant2(1f32)), 0i32); // References let ref1 = (&Struct1, 0i32); @@ -404,14 +403,14 @@ fn main() { let slice2 = &*vec2; // Trait Objects - let box_trait = (box 0_isize) as Box; + let box_trait = Box::new(0_isize) as Box; let ref_trait = &0_isize as &dyn Trait1; let mut mut_int1 = 0_isize; let mut_ref_trait = (&mut mut_int1) as &mut dyn Trait1; - let no_principal_trait = (box 0_isize) as Box<(dyn Send + Sync)>; + let no_principal_trait = Box::new(0_isize) as Box<(dyn Send + Sync)>; let has_associated_type_trait = &0_isize as &(dyn Trait3 + Send); - let generic_box_trait = (box 0_isize) as Box>; + let generic_box_trait = Box::new(0_isize) as Box>; let generic_ref_trait = (&0_isize) as &dyn Trait2; let mut generic_mut_ref_trait_impl = 0_isize; diff --git a/src/test/debuginfo/unique-enum.rs b/src/test/debuginfo/unique-enum.rs index 9d938b6e36..d7dfaeefe2 100644 --- a/src/test/debuginfo/unique-enum.rs +++ b/src/test/debuginfo/unique-enum.rs @@ -32,7 +32,6 @@ // lldbr-check:(unique_enum::Univariant) *univariant = { TheOnlyCase = { = 123234 } } #![allow(unused_variables)] -#![feature(box_syntax)] #![feature(omit_gdb_pretty_printer_section)] #![omit_gdb_pretty_printer_section] @@ -59,15 +58,15 @@ fn main() { // 0b01111100011111000111110001111100 = 2088533116 // 0b0111110001111100 = 31868 // 0b01111100 = 124 - let the_a: Box<_> = box ABC::TheA { x: 0, y: 8970181431921507452 }; + let the_a: Box<_> = Box::new(ABC::TheA { x: 0, y: 8970181431921507452 }); // 0b0001000100010001000100010001000100010001000100010001000100010001 = 1229782938247303441 // 0b00010001000100010001000100010001 = 286331153 // 0b0001000100010001 = 4369 // 0b00010001 = 17 - let the_b: Box<_> = box ABC::TheB (0, 286331153, 286331153); + let the_b: Box<_> = Box::new(ABC::TheB (0, 286331153, 286331153)); - let univariant: Box<_> = box Univariant::TheOnlyCase(123234); + let univariant: Box<_> = Box::new(Univariant::TheOnlyCase(123234)); zzz(); // #break } diff --git a/src/test/debuginfo/var-captured-in-nested-closure.rs b/src/test/debuginfo/var-captured-in-nested-closure.rs index a2778fc609..d811915c38 100644 --- a/src/test/debuginfo/var-captured-in-nested-closure.rs +++ b/src/test/debuginfo/var-captured-in-nested-closure.rs @@ -133,7 +133,6 @@ // cdb-check:closure_local : 8 [Type: [...]] #![allow(unused_variables)] -#![feature(box_syntax)] #![feature(omit_gdb_pretty_printer_section)] #![omit_gdb_pretty_printer_section] @@ -154,7 +153,7 @@ fn main() { }; let struct_ref = &a_struct; - let owned: Box<_> = box 6; + let owned: Box<_> = Box::new(6); let mut closure = || { let closure_local = 8; diff --git a/src/test/debuginfo/var-captured-in-sendable-closure.rs b/src/test/debuginfo/var-captured-in-sendable-closure.rs index bd7c2bfe2c..39930e04e4 100644 --- a/src/test/debuginfo/var-captured-in-sendable-closure.rs +++ b/src/test/debuginfo/var-captured-in-sendable-closure.rs @@ -34,7 +34,6 @@ // lldbr-check:(isize) *owned = 5 #![allow(unused_variables)] -#![feature(box_syntax)] #![feature(omit_gdb_pretty_printer_section)] #![omit_gdb_pretty_printer_section] @@ -53,7 +52,7 @@ fn main() { c: 4 }; - let owned: Box<_> = box 5; + let owned: Box<_> = Box::new(5); let closure = move || { zzz(); // #break diff --git a/src/test/debuginfo/var-captured-in-stack-closure.rs b/src/test/debuginfo/var-captured-in-stack-closure.rs index 1bbb79c37a..d68409a9d5 100644 --- a/src/test/debuginfo/var-captured-in-stack-closure.rs +++ b/src/test/debuginfo/var-captured-in-stack-closure.rs @@ -115,7 +115,6 @@ // cdb-command: dx owned // cdb-check:owned : 0x[...] : 6 [Type: [...] *] -#![feature(box_syntax)] #![allow(unused_variables)] #![feature(omit_gdb_pretty_printer_section)] #![omit_gdb_pretty_printer_section] @@ -137,7 +136,7 @@ fn main() { }; let struct_ref = &a_struct; - let owned: Box<_> = box 6; + let owned: Box<_> = Box::new(6); { let mut first_closure = || { diff --git a/src/test/incremental/change_symbol_export_status.rs b/src/test/incremental/change_symbol_export_status.rs index 9b3b381d62..dd3dce4e72 100644 --- a/src/test/incremental/change_symbol_export_status.rs +++ b/src/test/incremental/change_symbol_export_status.rs @@ -1,9 +1,15 @@ -// revisions: rpass1 rpass2 +// revisions: rpass1 rpass2 rpass3 rpass4 // compile-flags: -Zquery-dep-graph +// [rpass1]compile-flags: -Zincremental-ignore-spans +// [rpass2]compile-flags: -Zincremental-ignore-spans +// [rpass3]compile-flags: -Zincremental-relative-spans +// [rpass4]compile-flags: -Zincremental-relative-spans #![feature(rustc_attrs)] -#![rustc_partition_codegened(module = "change_symbol_export_status-mod1", cfg = "rpass2")] +#![rustc_partition_reused(module = "change_symbol_export_status-mod1", cfg = "rpass2")] #![rustc_partition_reused(module = "change_symbol_export_status-mod2", cfg = "rpass2")] +#![rustc_partition_reused(module = "change_symbol_export_status-mod1", cfg = "rpass4")] +#![rustc_partition_reused(module = "change_symbol_export_status-mod2", cfg = "rpass4")] // This test case makes sure that a change in symbol visibility is detected by // our dependency tracking. We do this by changing a module's visibility to @@ -13,13 +19,13 @@ // even from an executable. Plain Rust functions are only exported from Rust // libraries, which our test infrastructure does not support. -#[cfg(rpass1)] +#[cfg(any(rpass1,rpass3))] pub mod mod1 { #[no_mangle] pub fn foo() {} } -#[cfg(rpass2)] +#[cfg(any(rpass2,rpass4))] mod mod1 { #[no_mangle] pub fn foo() {} diff --git a/src/test/incremental/hashes/call_expressions.rs b/src/test/incremental/hashes/call_expressions.rs index d4201400f0..648f71f923 100644 --- a/src/test/incremental/hashes/call_expressions.rs +++ b/src/test/incremental/hashes/call_expressions.rs @@ -6,8 +6,14 @@ // rev3 and make sure that the hash has not changed. // build-pass (FIXME(62277): could be check-pass?) -// revisions: cfail1 cfail2 cfail3 -// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans +// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6 +// compile-flags: -Z query-dep-graph +// [cfail1]compile-flags: -Zincremental-ignore-spans +// [cfail2]compile-flags: -Zincremental-ignore-spans +// [cfail3]compile-flags: -Zincremental-ignore-spans +// [cfail4]compile-flags: -Zincremental-relative-spans +// [cfail5]compile-flags: -Zincremental-relative-spans +// [cfail6]compile-flags: -Zincremental-relative-spans #![allow(warnings)] @@ -19,14 +25,16 @@ fn callee2(_x: u32, _y: i64) {} // Change Callee (Function) -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn change_callee_function() { callee1(1, 2) } -#[cfg(not(cfail1))] +#[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")] +#[rustc_clean(cfg="cfail6")] pub fn change_callee_function() { callee2(1, 2) } @@ -34,14 +42,16 @@ pub fn change_callee_function() { // Change Argument (Function) -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn change_argument_function() { callee1(1, 2) } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail6")] pub fn change_argument_function() { callee1(1, 3) } @@ -50,13 +60,15 @@ pub fn change_argument_function() { // Change Callee Indirectly (Function) mod change_callee_indirectly_function { - #[cfg(cfail1)] + #[cfg(any(cfail1,cfail4))] use super::callee1 as callee; - #[cfg(not(cfail1))] + #[cfg(not(any(cfail1,cfail4)))] use super::callee2 as callee; #[rustc_clean(except="hir_owner_nodes,typeck", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] + #[rustc_clean(except="hir_owner_nodes,typeck", cfg="cfail5")] + #[rustc_clean(cfg="cfail6")] pub fn change_callee_indirectly_function() { callee(1, 2) } @@ -70,15 +82,17 @@ impl Struct { } // Change Callee (Method) -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn change_callee_method() { let s = Struct; s.method1('x', true); } -#[cfg(not(cfail1))] +#[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")] +#[rustc_clean(cfg="cfail6")] pub fn change_callee_method() { let s = Struct; s.method2('x', true); @@ -87,15 +101,17 @@ pub fn change_callee_method() { // Change Argument (Method) -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn change_argument_method() { let s = Struct; s.method1('x', true); } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail6")] pub fn change_argument_method() { let s = Struct; s.method1('y', true); @@ -104,15 +120,17 @@ pub fn change_argument_method() { // Change Callee (Method, UFCS) -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn change_ufcs_callee_method() { let s = Struct; Struct::method1(&s, 'x', true); } -#[cfg(not(cfail1))] +#[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")] +#[rustc_clean(cfg="cfail6")] pub fn change_ufcs_callee_method() { let s = Struct; Struct::method2(&s, 'x', true); @@ -121,32 +139,36 @@ pub fn change_ufcs_callee_method() { // Change Argument (Method, UFCS) -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn change_argument_method_ufcs() { let s = Struct; Struct::method1(&s, 'x', true); } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail6")] pub fn change_argument_method_ufcs() { let s = Struct; - Struct::method1(&s, 'x', false); + Struct::method1(&s, 'x',false); } // Change To UFCS -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn change_to_ufcs() { let s = Struct; - s.method1('x', true); + s.method1('x', true); // ------ } -#[cfg(not(cfail1))] +#[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")] +#[rustc_clean(cfg="cfail6")] // One might think this would be expanded in the hir_owner_nodes/Mir, but it actually // results in slightly different hir_owner/Mir. pub fn change_to_ufcs() { @@ -162,15 +184,15 @@ impl Struct2 { // Change UFCS Callee Indirectly pub mod change_ufcs_callee_indirectly { - #[cfg(cfail1)] + #[cfg(any(cfail1,cfail4))] use super::Struct as Struct; - #[cfg(not(cfail1))] + #[cfg(not(any(cfail1,cfail4)))] use super::Struct2 as Struct; #[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")] + #[rustc_clean(cfg="cfail6")] pub fn change_ufcs_callee_indirectly() { let s = Struct; Struct::method1(&s, 'q', false) diff --git a/src/test/incremental/hashes/closure_expressions.rs b/src/test/incremental/hashes/closure_expressions.rs index 4a00a6c72f..2a4306fc17 100644 --- a/src/test/incremental/hashes/closure_expressions.rs +++ b/src/test/incremental/hashes/closure_expressions.rs @@ -6,8 +6,14 @@ // rev3 and make sure that the hash has not changed. // build-pass (FIXME(62277): could be check-pass?) -// revisions: cfail1 cfail2 cfail3 -// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans -Zmir-opt-level=0 +// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6 +// compile-flags: -Z query-dep-graph -Zmir-opt-level=0 +// [cfail1]compile-flags: -Zincremental-ignore-spans +// [cfail2]compile-flags: -Zincremental-ignore-spans +// [cfail3]compile-flags: -Zincremental-ignore-spans +// [cfail4]compile-flags: -Zincremental-relative-spans +// [cfail5]compile-flags: -Zincremental-relative-spans +// [cfail6]compile-flags: -Zincremental-relative-spans #![allow(warnings)] #![feature(rustc_attrs)] @@ -15,14 +21,16 @@ // Change closure body -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn change_closure_body() { let _ = || 1u32; } -#[cfg(not(cfail1))] +#[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")] +#[rustc_clean(cfg="cfail6")] pub fn change_closure_body() { let _ = || 3u32; } @@ -30,15 +38,17 @@ pub fn change_closure_body() { // Add parameter -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn add_parameter() { let x = 0u32; - let _ = || x + 1; + let _ = | | x + 1; } -#[cfg(not(cfail1))] +#[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")] +#[rustc_clean(cfg="cfail6")] pub fn add_parameter() { let x = 0u32; let _ = |x: u32| x + 1; @@ -47,14 +57,16 @@ pub fn add_parameter() { // Change parameter pattern -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn change_parameter_pattern() { - let _ = |x: (u32,)| x; + let _ = | x : (u32,)| x; } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2", except="hir_owner_nodes, typeck, optimized_mir")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, typeck, optimized_mir")] +#[rustc_clean(cfg="cfail6")] pub fn change_parameter_pattern() { let _ = |(x,): (u32,)| x; } @@ -62,14 +74,16 @@ pub fn change_parameter_pattern() { // Add `move` to closure -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn add_move() { - let _ = || 1; + let _ = || 1; } -#[cfg(not(cfail1))] +#[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="cfail6")] pub fn add_move() { let _ = move || 1; } @@ -77,15 +91,17 @@ pub fn add_move() { // Add type ascription to parameter -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn add_type_ascription_to_parameter() { - let closure = |x| x + 1u32; + let closure = |x | x + 1u32; let _: u32 = closure(1); } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg = "cfail2", except = "hir_owner_nodes, typeck")] #[rustc_clean(cfg = "cfail3")] +#[rustc_clean(cfg = "cfail5", except = "hir_owner_nodes, typeck")] +#[rustc_clean(cfg = "cfail6")] pub fn add_type_ascription_to_parameter() { let closure = |x: u32| x + 1u32; let _: u32 = closure(1); @@ -94,15 +110,17 @@ pub fn add_type_ascription_to_parameter() { // Change parameter type -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn change_parameter_type() { let closure = |x: u32| (x as u64) + 1; let _ = closure(1); } -#[cfg(not(cfail1))] +#[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")] +#[rustc_clean(cfg="cfail6")] pub fn change_parameter_type() { let closure = |x: u16| (x as u64) + 1; let _ = closure(1); diff --git a/src/test/incremental/hashes/consts.rs b/src/test/incremental/hashes/consts.rs index 6e0db6a49a..c85f0bbecd 100644 --- a/src/test/incremental/hashes/consts.rs +++ b/src/test/incremental/hashes/consts.rs @@ -7,7 +7,7 @@ // build-pass (FIXME(62277): could be check-pass?) // revisions: cfail1 cfail2 cfail3 -// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans +// compile-flags: -Z query-dep-graph #![allow(warnings)] #![feature(rustc_attrs)] diff --git a/src/test/incremental/hashes/enum_constructors.rs b/src/test/incremental/hashes/enum_constructors.rs index 26ff6b109d..7522fa5a02 100644 --- a/src/test/incremental/hashes/enum_constructors.rs +++ b/src/test/incremental/hashes/enum_constructors.rs @@ -6,8 +6,14 @@ // rev3 and make sure that the hash has not changed. // build-pass (FIXME(62277): could be check-pass?) -// revisions: cfail1 cfail2 cfail3 -// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans -Zmir-opt-level=0 +// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6 +// compile-flags: -Z query-dep-graph -Zmir-opt-level=0 +// [cfail1]compile-flags: -Zincremental-ignore-spans +// [cfail2]compile-flags: -Zincremental-ignore-spans +// [cfail3]compile-flags: -Zincremental-ignore-spans +// [cfail4]compile-flags: -Zincremental-relative-spans +// [cfail5]compile-flags: -Zincremental-relative-spans +// [cfail6]compile-flags: -Zincremental-relative-spans #![allow(warnings)] #![feature(rustc_attrs)] @@ -24,7 +30,7 @@ pub enum Enum { } // Change field value (struct-like) ----------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn change_field_value_struct_like() -> Enum { Enum::Struct { x: 0, @@ -33,9 +39,11 @@ pub fn change_field_value_struct_like() -> Enum { } } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail6")] pub fn change_field_value_struct_like() -> Enum { Enum::Struct { x: 0, @@ -47,7 +55,7 @@ pub fn change_field_value_struct_like() -> Enum { // Change field order (struct-like) ----------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn change_field_order_struct_like() -> Enum { Enum::Struct { x: 3, @@ -56,9 +64,11 @@ pub fn change_field_order_struct_like() -> Enum { } } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck,optimized_mir")] +#[rustc_clean(cfg="cfail6")] // FIXME(michaelwoerister):Interesting. I would have thought that that changes the MIR. And it // would if it were not all constants pub fn change_field_order_struct_like() -> Enum { @@ -86,18 +96,20 @@ pub enum Enum2 { } // Change constructor path (struct-like) ------------------------------------ -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn change_constructor_path_struct_like() { - let _ = Enum::Struct { + let _ = Enum ::Struct { x: 0, y: 1, z: 2, }; } -#[cfg(not(cfail1))] +#[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")] +#[rustc_clean(cfg="cfail6")] pub fn change_constructor_path_struct_like() { let _ = Enum2::Struct { x: 0, @@ -109,18 +121,20 @@ pub fn change_constructor_path_struct_like() { // Change variant (regular struct) ------------------------------------ -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn change_constructor_variant_struct_like() { - let _ = Enum2::Struct { + let _ = Enum2::Struct { x: 0, y: 1, z: 2, }; } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail6")] pub fn change_constructor_variant_struct_like() { let _ = Enum2::Struct2 { x: 0, @@ -132,9 +146,9 @@ pub fn change_constructor_variant_struct_like() { // Change constructor path indirectly (struct-like) ------------------------- pub mod change_constructor_path_indirectly_struct_like { - #[cfg(cfail1)] + #[cfg(any(cfail1,cfail4))] use super::Enum as TheEnum; - #[cfg(not(cfail1))] + #[cfg(not(any(cfail1,cfail4)))] use super::Enum2 as TheEnum; #[rustc_clean( @@ -143,6 +157,12 @@ pub mod change_constructor_path_indirectly_struct_like { typeck" )] #[rustc_clean(cfg="cfail3")] + #[rustc_clean( + cfg="cfail5", + except="fn_sig,hir_owner,hir_owner_nodes,optimized_mir,\ + typeck" + )] + #[rustc_clean(cfg="cfail6")] pub fn function() -> TheEnum { TheEnum::Struct { x: 0, @@ -156,13 +176,15 @@ pub mod change_constructor_path_indirectly_struct_like { // Change constructor variant indirectly (struct-like) --------------------------- pub mod change_constructor_variant_indirectly_struct_like { use super::Enum2; - #[cfg(cfail1)] + #[cfg(any(cfail1,cfail4))] use super::Enum2::Struct as Variant; - #[cfg(not(cfail1))] + #[cfg(not(any(cfail1,cfail4)))] use super::Enum2::Struct2 as Variant; #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail3")] + #[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")] + #[rustc_clean(cfg="cfail6")] pub fn function() -> Enum2 { Variant { x: 0, @@ -174,14 +196,16 @@ pub mod change_constructor_variant_indirectly_struct_like { // Change field value (tuple-like) ------------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn change_field_value_tuple_like() -> Enum { Enum::Tuple(0, 1, 2) } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail6")] pub fn change_field_value_tuple_like() -> Enum { Enum::Tuple(0, 1, 3) } @@ -189,17 +213,22 @@ pub fn change_field_value_tuple_like() -> Enum { // Change constructor path (tuple-like) -------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn change_constructor_path_tuple_like() { - let _ = Enum::Tuple(0, 1, 2); + let _ = Enum ::Tuple(0, 1, 2); } -#[cfg(not(cfail1))] +#[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" +)] +#[rustc_clean(cfg="cfail6")] pub fn change_constructor_path_tuple_like() { let _ = Enum2::Tuple(0, 1, 2); } @@ -207,17 +236,22 @@ pub fn change_constructor_path_tuple_like() { // Change constructor variant (tuple-like) -------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn change_constructor_variant_tuple_like() { - let _ = Enum2::Tuple(0, 1, 2); + let _ = Enum2::Tuple (0, 1, 2); } -#[cfg(not(cfail1))] +#[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" +)] +#[rustc_clean(cfg="cfail6")] pub fn change_constructor_variant_tuple_like() { let _ = Enum2::Tuple2(0, 1, 2); } @@ -225,9 +259,9 @@ pub fn change_constructor_variant_tuple_like() { // Change constructor path indirectly (tuple-like) --------------------------- pub mod change_constructor_path_indirectly_tuple_like { - #[cfg(cfail1)] + #[cfg(any(cfail1,cfail4))] use super::Enum as TheEnum; - #[cfg(not(cfail1))] + #[cfg(not(any(cfail1,cfail4)))] use super::Enum2 as TheEnum; #[rustc_clean( @@ -236,6 +270,12 @@ pub mod change_constructor_path_indirectly_tuple_like { typeck" )] #[rustc_clean(cfg="cfail3")] + #[rustc_clean( + cfg="cfail5", + except="fn_sig,hir_owner,hir_owner_nodes,optimized_mir,\ + typeck" + )] + #[rustc_clean(cfg="cfail6")] pub fn function() -> TheEnum { TheEnum::Tuple(0, 1, 2) } @@ -246,13 +286,15 @@ pub mod change_constructor_path_indirectly_tuple_like { // Change constructor variant indirectly (tuple-like) --------------------------- pub mod change_constructor_variant_indirectly_tuple_like { use super::Enum2; - #[cfg(cfail1)] + #[cfg(any(cfail1,cfail4))] use super::Enum2::Tuple as Variant; - #[cfg(not(cfail1))] + #[cfg(not(any(cfail1,cfail4)))] use super::Enum2::Tuple2 as Variant; #[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")] + #[rustc_clean(cfg="cfail6")] pub fn function() -> Enum2 { Variant(0, 1, 2) } @@ -272,14 +314,16 @@ pub enum Clike2 { } // Change constructor path (C-like) -------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn change_constructor_path_c_like() { - let _x = Clike::B; + let _x = Clike ::B; } -#[cfg(not(cfail1))] +#[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")] +#[rustc_clean(cfg="cfail6")] pub fn change_constructor_path_c_like() { let _x = Clike2::B; } @@ -287,14 +331,16 @@ pub fn change_constructor_path_c_like() { // Change constructor variant (C-like) -------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn change_constructor_variant_c_like() { let _x = Clike::A; } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail6")] pub fn change_constructor_variant_c_like() { let _x = Clike::C; } @@ -302,9 +348,9 @@ pub fn change_constructor_variant_c_like() { // Change constructor path indirectly (C-like) --------------------------- pub mod change_constructor_path_indirectly_c_like { - #[cfg(cfail1)] + #[cfg(any(cfail1,cfail4))] use super::Clike as TheEnum; - #[cfg(not(cfail1))] + #[cfg(not(any(cfail1,cfail4)))] use super::Clike2 as TheEnum; #[rustc_clean( @@ -313,6 +359,12 @@ pub mod change_constructor_path_indirectly_c_like { typeck" )] #[rustc_clean(cfg="cfail3")] + #[rustc_clean( + cfg="cfail5", + except="fn_sig,hir_owner,hir_owner_nodes,optimized_mir,\ + typeck" + )] + #[rustc_clean(cfg="cfail6")] pub fn function() -> TheEnum { TheEnum::B } @@ -323,13 +375,15 @@ pub mod change_constructor_path_indirectly_c_like { // Change constructor variant indirectly (C-like) --------------------------- pub mod change_constructor_variant_indirectly_c_like { use super::Clike; - #[cfg(cfail1)] + #[cfg(any(cfail1,cfail4))] use super::Clike::A as Variant; - #[cfg(not(cfail1))] + #[cfg(not(any(cfail1,cfail4)))] use super::Clike::B as Variant; #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail3")] + #[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")] + #[rustc_clean(cfg="cfail6")] pub fn function() -> Clike { Variant } diff --git a/src/test/incremental/hashes/enum_defs.rs b/src/test/incremental/hashes/enum_defs.rs index 76bff3cad3..ab9c740844 100644 --- a/src/test/incremental/hashes/enum_defs.rs +++ b/src/test/incremental/hashes/enum_defs.rs @@ -11,8 +11,14 @@ // the same between rev2 and rev3. // build-pass (FIXME(62277): could be check-pass?) -// revisions: cfail1 cfail2 cfail3 -// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans +// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6 +// compile-flags: -Z query-dep-graph +// [cfail1]compile-flags: -Zincremental-ignore-spans +// [cfail2]compile-flags: -Zincremental-ignore-spans +// [cfail3]compile-flags: -Zincremental-ignore-spans +// [cfail4]compile-flags: -Zincremental-relative-spans +// [cfail5]compile-flags: -Zincremental-relative-spans +// [cfail6]compile-flags: -Zincremental-relative-spans #![allow(warnings)] #![feature(rustc_attrs)] @@ -22,12 +28,14 @@ // Change enum visibility ----------------------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] enum EnumVisibility { A } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")] +#[rustc_clean(cfg="cfail6")] pub enum EnumVisibility { A } @@ -35,15 +43,17 @@ pub enum EnumVisibility { // Change name of a c-style variant ------------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] enum EnumChangeNameCStyleVariant { Variant1, Variant2, } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail6")] enum EnumChangeNameCStyleVariant { Variant1, Variant2Changed, @@ -52,15 +62,17 @@ enum EnumChangeNameCStyleVariant { // Change name of a tuple-style variant --------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] enum EnumChangeNameTupleStyleVariant { Variant1, Variant2(u32, f32), } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail6")] enum EnumChangeNameTupleStyleVariant { Variant1, Variant2Changed(u32, f32), @@ -69,15 +81,17 @@ enum EnumChangeNameTupleStyleVariant { // Change name of a struct-style variant -------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] enum EnumChangeNameStructStyleVariant { Variant1, Variant2 { a: u32, b: f32 }, } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail6")] enum EnumChangeNameStructStyleVariant { Variant1, Variant2Changed { a: u32, b: f32 }, @@ -86,31 +100,33 @@ enum EnumChangeNameStructStyleVariant { // Change the value of a c-style variant -------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] enum EnumChangeValueCStyleVariant0 { Variant1, Variant2 = 11, } -#[cfg(not(cfail1))] +#[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")] +#[rustc_clean(cfg="cfail6")] enum EnumChangeValueCStyleVariant0 { Variant1, - - Variant2 = - 22, + Variant2 = 22, } -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] enum EnumChangeValueCStyleVariant1 { Variant1, Variant2, } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail6")] enum EnumChangeValueCStyleVariant1 { Variant1, Variant2 = 11, @@ -119,14 +135,16 @@ enum EnumChangeValueCStyleVariant1 { // Add a c-style variant ------------------------------------------------------ -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] enum EnumAddCStyleVariant { Variant1, } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail6")] enum EnumAddCStyleVariant { Variant1, Variant2, @@ -135,15 +153,17 @@ enum EnumAddCStyleVariant { // Remove a c-style variant --------------------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] enum EnumRemoveCStyleVariant { Variant1, Variant2, } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail6")] enum EnumRemoveCStyleVariant { Variant1, } @@ -151,14 +171,16 @@ enum EnumRemoveCStyleVariant { // Add a tuple-style variant -------------------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] enum EnumAddTupleStyleVariant { Variant1, } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail6")] enum EnumAddTupleStyleVariant { Variant1, Variant2(u32, f32), @@ -167,15 +189,17 @@ enum EnumAddTupleStyleVariant { // Remove a tuple-style variant ----------------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] enum EnumRemoveTupleStyleVariant { Variant1, Variant2(u32, f32), } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail6")] enum EnumRemoveTupleStyleVariant { Variant1, } @@ -183,14 +207,16 @@ enum EnumRemoveTupleStyleVariant { // Add a struct-style variant ------------------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] enum EnumAddStructStyleVariant { Variant1, } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail6")] enum EnumAddStructStyleVariant { Variant1, Variant2 { a: u32, b: f32 }, @@ -199,15 +225,17 @@ enum EnumAddStructStyleVariant { // Remove a struct-style variant ---------------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] enum EnumRemoveStructStyleVariant { Variant1, Variant2 { a: u32, b: f32 }, } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail6")] enum EnumRemoveStructStyleVariant { Variant1, } @@ -215,14 +243,16 @@ enum EnumRemoveStructStyleVariant { // Change the type of a field in a tuple-style variant ------------------------ -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] enum EnumChangeFieldTypeTupleStyleVariant { Variant1(u32, u32), } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")] +#[rustc_clean(cfg="cfail6")] enum EnumChangeFieldTypeTupleStyleVariant { Variant1(u32, u64), @@ -231,15 +261,17 @@ enum EnumChangeFieldTypeTupleStyleVariant { // Change the type of a field in a struct-style variant ----------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] enum EnumChangeFieldTypeStructStyleVariant { Variant1, Variant2 { a: u32, b: u32 }, } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")] +#[rustc_clean(cfg="cfail6")] enum EnumChangeFieldTypeStructStyleVariant { Variant1, Variant2 { @@ -251,14 +283,16 @@ enum EnumChangeFieldTypeStructStyleVariant { // Change the name of a field in a struct-style variant ----------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] enum EnumChangeFieldNameStructStyleVariant { Variant1 { a: u32, b: u32 }, } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail6")] enum EnumChangeFieldNameStructStyleVariant { Variant1 { a: u32, c: u32 }, } @@ -266,14 +300,16 @@ enum EnumChangeFieldNameStructStyleVariant { // Change order of fields in a tuple-style variant ---------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] enum EnumChangeOrderTupleStyleVariant { Variant1(u32, u64), } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")] +#[rustc_clean(cfg="cfail6")] enum EnumChangeOrderTupleStyleVariant { Variant1( u64, @@ -283,14 +319,16 @@ enum EnumChangeOrderTupleStyleVariant { // Change order of fields in a struct-style variant --------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] enum EnumChangeFieldOrderStructStyleVariant { Variant1 { a: u32, b: f32 }, } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail6")] enum EnumChangeFieldOrderStructStyleVariant { Variant1 { b: f32, a: u32 }, } @@ -298,14 +336,16 @@ enum EnumChangeFieldOrderStructStyleVariant { // Add a field to a tuple-style variant --------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] enum EnumAddFieldTupleStyleVariant { Variant1(u32, u32), } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail6")] enum EnumAddFieldTupleStyleVariant { Variant1(u32, u32, u32), } @@ -313,14 +353,16 @@ enum EnumAddFieldTupleStyleVariant { // Add a field to a struct-style variant -------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] enum EnumAddFieldStructStyleVariant { Variant1 { a: u32, b: u32 }, } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail6")] enum EnumAddFieldStructStyleVariant { Variant1 { a: u32, b: u32, c: u32 }, } @@ -328,15 +370,17 @@ enum EnumAddFieldStructStyleVariant { // Add #[must_use] to the enum ------------------------------------------------ -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] enum EnumAddMustUse { Variant1, Variant2, } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] #[must_use] enum EnumAddMustUse { Variant1, @@ -346,15 +390,17 @@ enum EnumAddMustUse { // Add #[repr(C)] to the enum ------------------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] enum EnumAddReprC { Variant1, Variant2, } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2", except="type_of")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="type_of")] +#[rustc_clean(cfg="cfail6")] #[repr(C)] enum EnumAddReprC { Variant1, @@ -364,14 +410,16 @@ enum EnumAddReprC { // Change the name of a type parameter ---------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] enum EnumChangeNameOfTypeParameter { Variant1(S), } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of")] +#[rustc_clean(cfg="cfail6")] enum EnumChangeNameOfTypeParameter { Variant1(T), } @@ -379,15 +427,17 @@ enum EnumChangeNameOfTypeParameter { // Add a type parameter ------------------------------------------------------ -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] enum EnumAddTypeParameter { Variant1(S), Variant2(S), } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of")] +#[rustc_clean(cfg="cfail6")] enum EnumAddTypeParameter { Variant1(S), Variant2(T), @@ -396,14 +446,16 @@ enum EnumAddTypeParameter { // Change the name of a lifetime parameter ------------------------------------ -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] enum EnumChangeNameOfLifetimeParameter<'a> { Variant1(&'a u32), } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,generics_of,type_of")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,generics_of,type_of")] +#[rustc_clean(cfg="cfail6")] enum EnumChangeNameOfLifetimeParameter<'b> { Variant1(&'b u32), } @@ -411,15 +463,17 @@ enum EnumChangeNameOfLifetimeParameter<'b> { // Add a lifetime parameter --------------------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] enum EnumAddLifetimeParameter<'a> { Variant1(&'a u32), Variant2(&'a u32), } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,generics_of,type_of")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,generics_of,type_of")] +#[rustc_clean(cfg="cfail6")] enum EnumAddLifetimeParameter<'a, 'b> { Variant1(&'a u32), Variant2(&'b u32), @@ -428,30 +482,34 @@ enum EnumAddLifetimeParameter<'a, 'b> { // Add a lifetime bound to a lifetime parameter ------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] enum EnumAddLifetimeParameterBound<'a, 'b> { Variant1(&'a u32), Variant2(&'b u32), } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,predicates_of")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,predicates_of")] +#[rustc_clean(cfg="cfail6")] enum EnumAddLifetimeParameterBound<'a, 'b: 'a> { Variant1(&'a u32), Variant2(&'b u32), } // Add a lifetime bound to a type parameter ----------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] enum EnumAddLifetimeBoundToParameter<'a, T> { Variant1(T), Variant2(&'a u32), } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,generics_of,predicates_of")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,generics_of,predicates_of")] +#[rustc_clean(cfg="cfail6")] enum EnumAddLifetimeBoundToParameter<'a, T: 'a> { Variant1(T), Variant2(&'a u32), @@ -460,14 +518,16 @@ enum EnumAddLifetimeBoundToParameter<'a, T: 'a> { // Add a trait bound to a type parameter -------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] enum EnumAddTraitBound { Variant1(S), } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of")] +#[rustc_clean(cfg="cfail6")] enum EnumAddTraitBound { Variant1(T), } @@ -475,15 +535,17 @@ enum EnumAddTraitBound { // Add a lifetime bound to a lifetime parameter in where clause --------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] enum EnumAddLifetimeParameterBoundWhere<'a, 'b> { Variant1(&'a u32), Variant2(&'b u32), } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,predicates_of")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,predicates_of")] +#[rustc_clean(cfg="cfail6")] enum EnumAddLifetimeParameterBoundWhere<'a, 'b> where 'b: 'a { Variant1(&'a u32), Variant2(&'b u32), @@ -492,15 +554,17 @@ enum EnumAddLifetimeParameterBoundWhere<'a, 'b> where 'b: 'a { // Add a lifetime bound to a type parameter in where clause ------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] enum EnumAddLifetimeBoundToParameterWhere<'a, T> { Variant1(T), Variant2(&'a u32), } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,generics_of,predicates_of")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,generics_of,predicates_of")] +#[rustc_clean(cfg="cfail6")] enum EnumAddLifetimeBoundToParameterWhere<'a, T> where T: 'a { Variant1(T), Variant2(&'a u32), @@ -509,14 +573,16 @@ enum EnumAddLifetimeBoundToParameterWhere<'a, T> where T: 'a { // Add a trait bound to a type parameter in where clause ---------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] enum EnumAddTraitBoundWhere { Variant1(S), } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of")] +#[rustc_clean(cfg="cfail6")] enum EnumAddTraitBoundWhere where T: Sync { Variant1(T), } @@ -524,15 +590,17 @@ enum EnumAddTraitBoundWhere where T: Sync { // In an enum with two variants, swap usage of type parameters ---------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] enum EnumSwapUsageTypeParameters { Variant1 { a: A }, Variant2 { a: B }, } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")] +#[rustc_clean(cfg="cfail6")] enum EnumSwapUsageTypeParameters { Variant1 { a: B @@ -545,15 +613,17 @@ enum EnumSwapUsageTypeParameters { // In an enum with two variants, swap usage of lifetime parameters ------------ -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] enum EnumSwapUsageLifetimeParameters<'a, 'b> { Variant1 { a: &'a u32 }, Variant2 { b: &'b u32 }, } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")] +#[rustc_clean(cfg="cfail6")] enum EnumSwapUsageLifetimeParameters<'a, 'b> { Variant1 { a: &'b u32 @@ -572,13 +642,15 @@ struct ReferencedType2; // Change field type in tuple-style variant indirectly by modifying a use statement mod change_field_type_indirectly_tuple_style { - #[cfg(cfail1)] + #[cfg(any(cfail1,cfail4))] use super::ReferencedType1 as FieldType; - #[cfg(not(cfail1))] + #[cfg(not(any(cfail1,cfail4)))] use super::ReferencedType2 as FieldType; #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] + #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")] + #[rustc_clean(cfg="cfail6")] enum TupleStyle { Variant1( FieldType @@ -590,13 +662,15 @@ mod change_field_type_indirectly_tuple_style { // Change field type in record-style variant indirectly by modifying a use statement mod change_field_type_indirectly_struct_style { - #[cfg(cfail1)] + #[cfg(any(cfail1,cfail4))] use super::ReferencedType1 as FieldType; - #[cfg(not(cfail1))] + #[cfg(not(any(cfail1,cfail4)))] use super::ReferencedType2 as FieldType; #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] + #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")] + #[rustc_clean(cfg="cfail6")] enum StructStyle { Variant1 { a: FieldType @@ -613,13 +687,15 @@ trait ReferencedTrait2 {} // Change trait bound of type parameter indirectly by modifying a use statement mod change_trait_bound_indirectly { - #[cfg(cfail1)] + #[cfg(any(cfail1,cfail4))] use super::ReferencedTrait1 as Trait; - #[cfg(not(cfail1))] + #[cfg(not(any(cfail1,cfail4)))] use super::ReferencedTrait2 as Trait; #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,predicates_of")] #[rustc_clean(cfg="cfail3")] + #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,predicates_of")] + #[rustc_clean(cfg="cfail6")] enum Enum { Variant1(T) } @@ -629,13 +705,15 @@ mod change_trait_bound_indirectly { // Change trait bound of type parameter in where clause indirectly by modifying a use statement mod change_trait_bound_indirectly_where { - #[cfg(cfail1)] + #[cfg(any(cfail1,cfail4))] use super::ReferencedTrait1 as Trait; - #[cfg(not(cfail1))] + #[cfg(not(any(cfail1,cfail4)))] use super::ReferencedTrait2 as Trait; #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,predicates_of")] #[rustc_clean(cfg="cfail3")] + #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,predicates_of")] + #[rustc_clean(cfg="cfail6")] enum Enum where T: Trait { Variant1(T) } diff --git a/src/test/incremental/hashes/exported_vs_not.rs b/src/test/incremental/hashes/exported_vs_not.rs index 40b6925bc7..d5fb8a2e53 100644 --- a/src/test/incremental/hashes/exported_vs_not.rs +++ b/src/test/incremental/hashes/exported_vs_not.rs @@ -1,6 +1,12 @@ // build-pass (FIXME(62277): could be check-pass?) -// revisions: cfail1 cfail2 cfail3 -// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans +// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6 +// compile-flags: -Z query-dep-graph +// [cfail1]compile-flags: -Zincremental-ignore-spans +// [cfail2]compile-flags: -Zincremental-ignore-spans +// [cfail3]compile-flags: -Zincremental-ignore-spans +// [cfail4]compile-flags: -Zincremental-relative-spans +// [cfail5]compile-flags: -Zincremental-relative-spans +// [cfail6]compile-flags: -Zincremental-relative-spans #![allow(warnings)] #![feature(rustc_attrs)] @@ -10,14 +16,16 @@ // the hash of the hir_owner_nodes node should change, but not the hash of // either the hir_owner or the Metadata node. -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn body_not_exported_to_metadata() -> u32 { 1 } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail6")] pub fn body_not_exported_to_metadata() -> u32 { 2 } @@ -28,15 +36,17 @@ pub fn body_not_exported_to_metadata() -> u32 { // marked as #[inline]. Only the hash of the hir_owner depnode should be // unaffected by a change to the body. -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] #[inline] pub fn body_exported_to_metadata_because_of_inline() -> u32 { 1 } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail6")] #[inline] pub fn body_exported_to_metadata_because_of_inline() -> u32 { 2 @@ -48,15 +58,17 @@ pub fn body_exported_to_metadata_because_of_inline() -> u32 { // generic. Only the hash of the hir_owner depnode should be // unaffected by a change to the body. -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] #[inline] pub fn body_exported_to_metadata_because_of_generic() -> u32 { 1 } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail6")] #[inline] pub fn body_exported_to_metadata_because_of_generic() -> u32 { 2 diff --git a/src/test/incremental/hashes/extern_mods.rs b/src/test/incremental/hashes/extern_mods.rs index 1160bc376c..4bc98fd7cd 100644 --- a/src/test/incremental/hashes/extern_mods.rs +++ b/src/test/incremental/hashes/extern_mods.rs @@ -6,8 +6,14 @@ // rev3 and make sure that the hash has not changed. // build-pass (FIXME(62277): could be check-pass?) -// revisions: cfail1 cfail2 cfail3 -// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans +// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6 +// compile-flags: -Z query-dep-graph +// [cfail1]compile-flags: -Zincremental-ignore-spans +// [cfail2]compile-flags: -Zincremental-ignore-spans +// [cfail3]compile-flags: -Zincremental-ignore-spans +// [cfail4]compile-flags: -Zincremental-relative-spans +// [cfail5]compile-flags: -Zincremental-relative-spans +// [cfail6]compile-flags: -Zincremental-relative-spans #![allow(warnings)] #![feature(rustc_attrs)] @@ -15,146 +21,168 @@ #![crate_type = "rlib"] // Change function name -------------------------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] extern "C" { pub fn change_function_name1(c: i64) -> i32; } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg = "cfail2", except = "hir_owner")] #[rustc_clean(cfg = "cfail3")] +#[rustc_clean(cfg = "cfail5", except = "hir_owner")] +#[rustc_clean(cfg = "cfail6")] extern "C" { pub fn change_function_name2(c: i64) -> i32; } // Change parameter name ------------------------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] extern "C" { pub fn change_parameter_name(c: i64) -> i32; } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg = "cfail2")] #[rustc_clean(cfg = "cfail3")] +#[rustc_clean(cfg = "cfail5")] +#[rustc_clean(cfg = "cfail6")] extern "C" { pub fn change_parameter_name(d: i64) -> i32; } // Change parameter type ------------------------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] extern "C" { pub fn change_parameter_type(c: i64) -> i32; } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg = "cfail2")] #[rustc_clean(cfg = "cfail3")] +#[rustc_clean(cfg = "cfail5")] +#[rustc_clean(cfg = "cfail6")] extern "C" { pub fn change_parameter_type(c: i32) -> i32; } // Change return type ---------------------------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] extern "C" { pub fn change_return_type(c: i32) -> i32; } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg = "cfail2")] #[rustc_clean(cfg = "cfail3")] +#[rustc_clean(cfg = "cfail5")] +#[rustc_clean(cfg = "cfail6")] extern "C" { - pub fn change_return_type(c: i32) -> i8; + pub fn change_return_type(c: i32) -> i8 ; } // Add parameter --------------------------------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] extern "C" { - pub fn add_parameter(c: i32) -> i32; + pub fn add_parameter(c: i32 ) -> i32; } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg = "cfail2")] #[rustc_clean(cfg = "cfail3")] +#[rustc_clean(cfg = "cfail5")] +#[rustc_clean(cfg = "cfail6")] extern "C" { pub fn add_parameter(c: i32, d: i32) -> i32; } // Add return type ------------------------------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] extern "C" { - pub fn add_return_type(c: i32); + pub fn add_return_type(c: i32) ; } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg = "cfail2")] #[rustc_clean(cfg = "cfail3")] +#[rustc_clean(cfg = "cfail5")] +#[rustc_clean(cfg = "cfail6")] extern "C" { pub fn add_return_type(c: i32) -> i32; } // Make function variadic ------------------------------------------------------ -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] extern "C" { - pub fn make_function_variadic(c: i32); + pub fn make_function_variadic(c: i32 ); } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg = "cfail2")] #[rustc_clean(cfg = "cfail3")] +#[rustc_clean(cfg = "cfail5")] +#[rustc_clean(cfg = "cfail6")] extern "C" { pub fn make_function_variadic(c: i32, ...); } // Change calling convention --------------------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] extern "C" { pub fn change_calling_convention(c: i32); } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg = "cfail2", except = "hir_owner")] #[rustc_clean(cfg = "cfail3")] +#[rustc_clean(cfg = "cfail5", except = "hir_owner")] +#[rustc_clean(cfg = "cfail6")] extern "rust-call" { pub fn change_calling_convention(c: i32); } // Make function public -------------------------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] extern "C" { - fn make_function_public(c: i32); + fn make_function_public(c: i32); } -#[cfg(not(cfail1))] -#[rustc_clean(cfg = "cfail2", except = "hir_owner")] +#[cfg(not(any(cfail1,cfail4)))] +#[rustc_clean(cfg = "cfail2")] #[rustc_clean(cfg = "cfail3")] +#[rustc_clean(cfg = "cfail5")] +#[rustc_clean(cfg = "cfail6")] extern "C" { pub fn make_function_public(c: i32); } // Add function ---------------------------------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] extern "C" { pub fn add_function1(c: i32); } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg = "cfail2", except = "hir_owner")] #[rustc_clean(cfg = "cfail3")] +#[rustc_clean(cfg = "cfail5", except = "hir_owner")] +#[rustc_clean(cfg = "cfail6")] extern "C" { pub fn add_function1(c: i32); pub fn add_function2(); } // Change link-name ------------------------------------------------------------ -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] #[link(name = "foo")] extern "C" { pub fn change_link_name(c: i32); } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg = "cfail2")] #[rustc_clean(cfg = "cfail3")] +#[rustc_clean(cfg = "cfail5")] +#[rustc_clean(cfg = "cfail6")] #[link(name = "bar")] extern "C" { pub fn change_link_name(c: i32); @@ -165,13 +193,15 @@ type c_i64 = i64; // Indirectly change parameter type -------------------------------------------- mod indirectly_change_parameter_type { - #[cfg(cfail1)] + #[cfg(any(cfail1,cfail4))] use super::c_i32 as c_int; - #[cfg(not(cfail1))] + #[cfg(not(any(cfail1,cfail4)))] use super::c_i64 as c_int; #[rustc_clean(cfg = "cfail2")] #[rustc_clean(cfg = "cfail3")] + #[rustc_clean(cfg = "cfail5")] + #[rustc_clean(cfg = "cfail6")] extern "C" { pub fn indirectly_change_parameter_type(c: c_int); } @@ -179,13 +209,15 @@ mod indirectly_change_parameter_type { // Indirectly change return type -------------------------------------------- mod indirectly_change_return_type { - #[cfg(cfail1)] + #[cfg(any(cfail1,cfail4))] use super::c_i32 as c_int; - #[cfg(not(cfail1))] + #[cfg(not(any(cfail1,cfail4)))] use super::c_i64 as c_int; #[rustc_clean(cfg = "cfail2")] #[rustc_clean(cfg = "cfail3")] + #[rustc_clean(cfg = "cfail5")] + #[rustc_clean(cfg = "cfail6")] extern "C" { pub fn indirectly_change_return_type() -> c_int; } diff --git a/src/test/incremental/hashes/for_loops.rs b/src/test/incremental/hashes/for_loops.rs index e1460503d2..5a944d28a0 100644 --- a/src/test/incremental/hashes/for_loops.rs +++ b/src/test/incremental/hashes/for_loops.rs @@ -6,8 +6,14 @@ // rev3 and make sure that the hash has not changed. // build-pass (FIXME(62277): could be check-pass?) -// revisions: cfail1 cfail2 cfail3 -// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans +// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6 +// compile-flags: -Z query-dep-graph +// [cfail1]compile-flags: -Zincremental-ignore-spans +// [cfail2]compile-flags: -Zincremental-ignore-spans +// [cfail3]compile-flags: -Zincremental-ignore-spans +// [cfail4]compile-flags: -Zincremental-relative-spans +// [cfail5]compile-flags: -Zincremental-relative-spans +// [cfail6]compile-flags: -Zincremental-relative-spans #![allow(warnings)] #![feature(rustc_attrs)] @@ -15,7 +21,7 @@ // Change loop body ------------------------------------------------------------ -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn change_loop_body() { let mut _x = 0; for _ in 0..1 { @@ -24,9 +30,11 @@ pub fn change_loop_body() { } } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")] +#[rustc_clean(cfg="cfail6")] pub fn change_loop_body() { let mut _x = 0; for _ in 0..1 { @@ -38,7 +46,7 @@ pub fn change_loop_body() { // Change iteration variable name ---------------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn change_iteration_variable_name() { let mut _x = 0; for _i in 0..1 { @@ -47,9 +55,11 @@ pub fn change_iteration_variable_name() { } } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")] +#[rustc_clean(cfg="cfail6")] pub fn change_iteration_variable_name() { let mut _x = 0; for _a in 0..1 { @@ -61,18 +71,20 @@ pub fn change_iteration_variable_name() { // Change iteration variable pattern ------------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn change_iteration_variable_pattern() { let mut _x = 0; - for _i in &[0, 1, 2] { + for _i in &[0, 1, 2] { _x = 1; break; } } -#[cfg(not(cfail1))] +#[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="cfail6")] pub fn change_iteration_variable_pattern() { let mut _x = 0; for &_i in &[0, 1, 2] { @@ -84,7 +96,7 @@ pub fn change_iteration_variable_pattern() { // Change iterable ------------------------------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn change_iterable() { let mut _x = 0; for _ in &[0, 1, 2] { @@ -93,9 +105,11 @@ pub fn change_iterable() { } } -#[cfg(not(cfail1))] +#[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="cfail6")] pub fn change_iterable() { let mut _x = 0; for _ in &[0, 1, 3] { @@ -107,17 +121,20 @@ pub fn change_iterable() { // Add break ------------------------------------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn add_break() { let mut _x = 0; for _ in 0..1 { _x = 1; + // --- } } -#[cfg(not(cfail1))] +#[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")] +#[rustc_clean(cfg="cfail6")] pub fn add_break() { let mut _x = 0; for _ in 0..1 { @@ -129,18 +146,20 @@ pub fn add_break() { // Add loop label -------------------------------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn add_loop_label() { let mut _x = 0; - for _ in 0..1 { + for _ in 0..1 { _x = 1; break; } } -#[cfg(not(cfail1))] +#[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="cfail6")] pub fn add_loop_label() { let mut _x = 0; 'label: for _ in 0..1 { @@ -152,18 +171,20 @@ pub fn add_loop_label() { // Add loop label to break ----------------------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn add_loop_label_to_break() { let mut _x = 0; 'label: for _ in 0..1 { _x = 1; - break; + break ; } } -#[cfg(not(cfail1))] +#[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="cfail6")] pub fn add_loop_label_to_break() { let mut _x = 0; 'label: for _ in 0..1 { @@ -175,7 +196,7 @@ pub fn add_loop_label_to_break() { // Change break label ---------------------------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn change_break_label() { let mut _x = 0; 'outer: for _ in 0..1 { @@ -186,9 +207,11 @@ pub fn change_break_label() { } } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")] +#[rustc_clean(cfg="cfail6")] pub fn change_break_label() { let mut _x = 0; 'outer: for _ in 0..1 { @@ -202,18 +225,20 @@ pub fn change_break_label() { // Add loop label to continue -------------------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn add_loop_label_to_continue() { let mut _x = 0; 'label: for _ in 0..1 { _x = 1; - continue; + continue ; } } -#[cfg(not(cfail1))] +#[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="cfail6")] pub fn add_loop_label_to_continue() { let mut _x = 0; 'label: for _ in 0..1 { @@ -225,7 +250,7 @@ pub fn add_loop_label_to_continue() { // Change continue label ---------------------------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn change_continue_label() { let mut _x = 0; 'outer: for _ in 0..1 { @@ -236,9 +261,11 @@ pub fn change_continue_label() { } } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")] +#[rustc_clean(cfg="cfail6")] pub fn change_continue_label() { let mut _x = 0; 'outer: for _ in 0..1 { @@ -252,7 +279,7 @@ pub fn change_continue_label() { // Change continue to break ---------------------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn change_continue_to_break() { let mut _x = 0; for _ in 0..1 { @@ -261,13 +288,15 @@ pub fn change_continue_to_break() { } } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")] +#[rustc_clean(cfg="cfail6")] pub fn change_continue_to_break() { let mut _x = 0; for _ in 0..1 { _x = 1; - break; + break ; } } diff --git a/src/test/incremental/hashes/function_interfaces.rs b/src/test/incremental/hashes/function_interfaces.rs index c8530c70f7..4124eada18 100644 --- a/src/test/incremental/hashes/function_interfaces.rs +++ b/src/test/incremental/hashes/function_interfaces.rs @@ -6,8 +6,14 @@ // rev3 and make sure that the hash has not changed. // build-pass (FIXME(62277): could be check-pass?) -// revisions: cfail1 cfail2 cfail3 -// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans +// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6 +// compile-flags: -Z query-dep-graph +// [cfail1]compile-flags: -Zincremental-ignore-spans +// [cfail2]compile-flags: -Zincremental-ignore-spans +// [cfail3]compile-flags: -Zincremental-ignore-spans +// [cfail4]compile-flags: -Zincremental-relative-spans +// [cfail5]compile-flags: -Zincremental-relative-spans +// [cfail6]compile-flags: -Zincremental-relative-spans #![allow(warnings)] #![feature(linkage)] @@ -16,248 +22,310 @@ // Add Parameter --------------------------------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn add_parameter() {} -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean( cfg = "cfail2", except = "hir_owner, hir_owner_nodes, optimized_mir, typeck, fn_sig" )] #[rustc_clean(cfg = "cfail3")] +#[rustc_clean( + cfg = "cfail5", + except = "hir_owner, hir_owner_nodes, optimized_mir, typeck, fn_sig" +)] +#[rustc_clean(cfg = "cfail6")] pub fn add_parameter(p: i32) {} // Add Return Type ------------------------------------------------------------- -#[cfg(cfail1)] -pub fn add_return_type() {} +#[cfg(any(cfail1,cfail4))] +pub fn add_return_type() {} -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes")] #[rustc_clean(cfg = "cfail3")] +#[rustc_clean(cfg = "cfail5", except = "hir_owner, hir_owner_nodes, optimized_mir")] +#[rustc_clean(cfg = "cfail6")] pub fn add_return_type() -> () {} // Change Parameter Type ------------------------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn type_of_parameter(p: i32) {} -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean( cfg = "cfail2", except = "hir_owner, hir_owner_nodes, optimized_mir, typeck, fn_sig" )] #[rustc_clean(cfg = "cfail3")] +#[rustc_clean( + cfg = "cfail5", + except = "hir_owner, hir_owner_nodes, optimized_mir, typeck, fn_sig" +)] +#[rustc_clean(cfg = "cfail6")] pub fn type_of_parameter(p: i64) {} // Change Parameter Type Reference --------------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn type_of_parameter_ref(p: &i32) {} -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean( cfg = "cfail2", except = "hir_owner, hir_owner_nodes, optimized_mir, typeck, fn_sig" )] #[rustc_clean(cfg = "cfail3")] +#[rustc_clean( + cfg = "cfail5", + except = "hir_owner, hir_owner_nodes, optimized_mir, typeck, fn_sig" +)] +#[rustc_clean(cfg = "cfail6")] pub fn type_of_parameter_ref(p: &mut i32) {} // Change Parameter Order ------------------------------------------------------ -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn order_of_parameters(p1: i32, p2: i64) {} -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean( cfg = "cfail2", except = "hir_owner, hir_owner_nodes, optimized_mir, typeck, fn_sig" )] #[rustc_clean(cfg = "cfail3")] +#[rustc_clean( + cfg = "cfail5", + except = "hir_owner, hir_owner_nodes, optimized_mir, typeck, fn_sig" +)] +#[rustc_clean(cfg = "cfail6")] pub fn order_of_parameters(p2: i64, p1: i32) {} // Unsafe ---------------------------------------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn make_unsafe() {} -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean( cfg = "cfail2", except = "hir_owner, hir_owner_nodes, optimized_mir, typeck, fn_sig" )] #[rustc_clean(cfg = "cfail3")] +#[rustc_clean( + cfg = "cfail5", + except = "hir_owner, hir_owner_nodes, optimized_mir, typeck, fn_sig" +)] +#[rustc_clean(cfg = "cfail6")] pub unsafe fn make_unsafe() {} // Extern ---------------------------------------------------------------------- -#[cfg(cfail1)] -pub fn make_extern() {} +#[cfg(any(cfail1,cfail4))] +pub fn make_extern() {} -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes, typeck, fn_sig")] #[rustc_clean(cfg = "cfail3")] +#[rustc_clean(cfg = "cfail5", except = "hir_owner, hir_owner_nodes, typeck, fn_sig")] +#[rustc_clean(cfg = "cfail6")] pub extern "C" fn make_extern() {} // Type Parameter -------------------------------------------------------------- -#[cfg(cfail1)] -pub fn type_parameter() {} +#[cfg(any(cfail1,cfail4))] +pub fn type_parameter () {} -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean( cfg = "cfail2", except = "hir_owner, hir_owner_nodes, generics_of, type_of, predicates_of" )] #[rustc_clean(cfg = "cfail3")] +#[rustc_clean( + cfg = "cfail5", + except = "hir_owner, hir_owner_nodes, generics_of, type_of, predicates_of" +)] +#[rustc_clean(cfg = "cfail6")] pub fn type_parameter() {} // Lifetime Parameter ---------------------------------------------------------- -#[cfg(cfail1)] -pub fn lifetime_parameter() {} +#[cfg(any(cfail1,cfail4))] +pub fn lifetime_parameter () {} -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes, generics_of,fn_sig")] #[rustc_clean(cfg = "cfail3")] +#[rustc_clean(cfg = "cfail5", except = "hir_owner, hir_owner_nodes, generics_of,fn_sig")] +#[rustc_clean(cfg = "cfail6")] pub fn lifetime_parameter<'a>() {} // Trait Bound ----------------------------------------------------------------- -#[cfg(cfail1)] -pub fn trait_bound() {} +#[cfg(any(cfail1,cfail4))] +pub fn trait_bound() {} -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes, predicates_of")] #[rustc_clean(cfg = "cfail3")] pub fn trait_bound() {} // Builtin Bound --------------------------------------------------------------- -#[cfg(cfail1)] -pub fn builtin_bound() {} +#[cfg(any(cfail1,cfail4))] +pub fn builtin_bound() {} -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes, predicates_of")] #[rustc_clean(cfg = "cfail3")] +#[rustc_clean(cfg = "cfail5", except = "hir_owner, hir_owner_nodes, predicates_of")] +#[rustc_clean(cfg = "cfail6")] pub fn builtin_bound() {} // Lifetime Bound -------------------------------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn lifetime_bound<'a, T>() {} -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean( cfg = "cfail2", except = "hir_owner, hir_owner_nodes, generics_of, type_of, predicates_of,fn_sig" )] #[rustc_clean(cfg = "cfail3")] +#[rustc_clean( + cfg = "cfail5", + except = "hir_owner, hir_owner_nodes, generics_of, type_of, predicates_of,fn_sig,optimized_mir" +)] +#[rustc_clean(cfg = "cfail6")] pub fn lifetime_bound<'a, T: 'a>() {} // Second Trait Bound ---------------------------------------------------------- -#[cfg(cfail1)] -pub fn second_trait_bound() {} +#[cfg(any(cfail1,cfail4))] +pub fn second_trait_bound() {} -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes, predicates_of")] #[rustc_clean(cfg = "cfail3")] pub fn second_trait_bound() {} // Second Builtin Bound -------------------------------------------------------- -#[cfg(cfail1)] -pub fn second_builtin_bound() {} +#[cfg(any(cfail1,cfail4))] +pub fn second_builtin_bound() {} -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes, predicates_of")] #[rustc_clean(cfg = "cfail3")] +#[rustc_clean(cfg = "cfail5", except = "hir_owner, hir_owner_nodes, predicates_of")] +#[rustc_clean(cfg = "cfail6")] pub fn second_builtin_bound() {} // Second Lifetime Bound ------------------------------------------------------- -#[cfg(cfail1)] -pub fn second_lifetime_bound<'a, 'b, T: 'a>() {} +#[cfg(any(cfail1,cfail4))] +pub fn second_lifetime_bound<'a, 'b, T: 'a >() {} -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean( cfg = "cfail2", except = "hir_owner, hir_owner_nodes, generics_of, type_of, predicates_of,fn_sig" )] #[rustc_clean(cfg = "cfail3")] +#[rustc_clean( + cfg = "cfail5", + except = "hir_owner, hir_owner_nodes, generics_of, type_of, predicates_of,fn_sig" +)] +#[rustc_clean(cfg = "cfail6")] pub fn second_lifetime_bound<'a, 'b, T: 'a + 'b>() {} // Inline ---------------------------------------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn inline() {} -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg = "cfail2")] #[rustc_clean(cfg = "cfail3")] +#[rustc_clean(cfg = "cfail5")] +#[rustc_clean(cfg = "cfail6")] #[inline] pub fn inline() {} // Inline Never ---------------------------------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] #[inline(always)] pub fn inline_never() {} -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg = "cfail2")] #[rustc_clean(cfg = "cfail3")] +#[rustc_clean(cfg = "cfail5")] +#[rustc_clean(cfg = "cfail6")] #[inline(never)] pub fn inline_never() {} // No Mangle ------------------------------------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn no_mangle() {} -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg = "cfail2")] #[rustc_clean(cfg = "cfail3")] +#[rustc_clean(cfg = "cfail5")] +#[rustc_clean(cfg = "cfail6")] #[no_mangle] pub fn no_mangle() {} // Linkage --------------------------------------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn linkage() {} -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg = "cfail2")] #[rustc_clean(cfg = "cfail3")] +#[rustc_clean(cfg = "cfail5")] +#[rustc_clean(cfg = "cfail6")] #[linkage = "weak_odr"] pub fn linkage() {} // Return Impl Trait ----------------------------------------------------------- -#[cfg(cfail1)] -pub fn return_impl_trait() -> i32 { +#[cfg(any(cfail1,cfail4))] +pub fn return_impl_trait() -> i32 { 0 } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes, typeck, fn_sig")] #[rustc_clean(cfg = "cfail3")] +#[rustc_clean(cfg = "cfail5", except = "hir_owner, hir_owner_nodes, typeck, fn_sig, optimized_mir")] +#[rustc_clean(cfg = "cfail6")] pub fn return_impl_trait() -> impl Clone { 0 } // Change Return Impl Trait ---------------------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn change_return_impl_trait() -> impl Clone { 0u32 } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg = "cfail2")] #[rustc_clean(cfg = "cfail3")] -pub fn change_return_impl_trait() -> impl Copy { +#[rustc_clean(cfg = "cfail5")] +#[rustc_clean(cfg = "cfail6")] +pub fn change_return_impl_trait() -> impl Copy { 0u32 } @@ -267,9 +335,9 @@ pub struct ReferencedType1; pub struct ReferencedType2; pub mod change_return_type_indirectly { - #[cfg(cfail1)] + #[cfg(any(cfail1,cfail4))] use super::ReferencedType1 as ReturnType; - #[cfg(not(cfail1))] + #[cfg(not(any(cfail1,cfail4)))] use super::ReferencedType2 as ReturnType; #[rustc_clean( @@ -277,6 +345,11 @@ pub mod change_return_type_indirectly { except = "hir_owner, hir_owner_nodes, optimized_mir, typeck, fn_sig" )] #[rustc_clean(cfg = "cfail3")] + #[rustc_clean( + cfg = "cfail5", + except = "hir_owner, hir_owner_nodes, optimized_mir, typeck, fn_sig" + )] + #[rustc_clean(cfg = "cfail6")] pub fn indirect_return_type() -> ReturnType { ReturnType {} } @@ -285,9 +358,9 @@ pub mod change_return_type_indirectly { // Change Parameter Type Indirectly -------------------------------------------- pub mod change_parameter_type_indirectly { - #[cfg(cfail1)] + #[cfg(any(cfail1,cfail4))] use super::ReferencedType1 as ParameterType; - #[cfg(not(cfail1))] + #[cfg(not(any(cfail1,cfail4)))] use super::ReferencedType2 as ParameterType; #[rustc_clean( @@ -295,6 +368,11 @@ pub mod change_parameter_type_indirectly { except = "hir_owner, hir_owner_nodes, optimized_mir, typeck, fn_sig" )] #[rustc_clean(cfg = "cfail3")] + #[rustc_clean( + cfg = "cfail5", + except = "hir_owner, hir_owner_nodes, optimized_mir, typeck, fn_sig" + )] + #[rustc_clean(cfg = "cfail6")] pub fn indirect_parameter_type(p: ParameterType) {} } @@ -304,26 +382,30 @@ pub trait ReferencedTrait1 {} pub trait ReferencedTrait2 {} pub mod change_trait_bound_indirectly { - #[cfg(cfail1)] + #[cfg(any(cfail1,cfail4))] use super::ReferencedTrait1 as Trait; - #[cfg(not(cfail1))] + #[cfg(not(any(cfail1,cfail4)))] use super::ReferencedTrait2 as Trait; #[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes, predicates_of")] #[rustc_clean(cfg = "cfail3")] + #[rustc_clean(cfg = "cfail5", except = "hir_owner, hir_owner_nodes, predicates_of")] + #[rustc_clean(cfg = "cfail6")] pub fn indirect_trait_bound(p: T) {} } // Change Trait Bound Indirectly In Where Clause ------------------------------- pub mod change_trait_bound_indirectly_in_where_clause { - #[cfg(cfail1)] + #[cfg(any(cfail1,cfail4))] use super::ReferencedTrait1 as Trait; - #[cfg(not(cfail1))] + #[cfg(not(any(cfail1,cfail4)))] use super::ReferencedTrait2 as Trait; #[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes, predicates_of")] #[rustc_clean(cfg = "cfail3")] + #[rustc_clean(cfg = "cfail5", except = "hir_owner, hir_owner_nodes, predicates_of")] + #[rustc_clean(cfg = "cfail6")] pub fn indirect_trait_bound_where(p: T) where T: Trait, diff --git a/src/test/incremental/hashes/if_expressions.rs b/src/test/incremental/hashes/if_expressions.rs index ddae9c9f03..0c5e73b010 100644 --- a/src/test/incremental/hashes/if_expressions.rs +++ b/src/test/incremental/hashes/if_expressions.rs @@ -6,27 +6,34 @@ // rev3 and make sure that the hash has not changed. // build-pass (FIXME(62277): could be check-pass?) -// revisions: cfail1 cfail2 cfail3 -// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans - +// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6 +// compile-flags: -Z query-dep-graph +// [cfail1]compile-flags: -Zincremental-ignore-spans +// [cfail2]compile-flags: -Zincremental-ignore-spans +// [cfail3]compile-flags: -Zincremental-ignore-spans +// [cfail4]compile-flags: -Zincremental-relative-spans +// [cfail5]compile-flags: -Zincremental-relative-spans +// [cfail6]compile-flags: -Zincremental-relative-spans #![allow(warnings)] #![feature(rustc_attrs)] #![crate_type="rlib"] // Change condition (if) -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn change_condition(x: bool) -> u32 { - if x { + if x { return 1 } return 0 } -#[cfg(not(cfail1))] +#[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")] +#[rustc_clean(cfg="cfail6")] pub fn change_condition(x: bool) -> u32 { if !x { return 1 @@ -36,7 +43,7 @@ pub fn change_condition(x: bool) -> u32 { } // Change then branch (if) -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn change_then_branch(x: bool) -> u32 { if x { return 1 @@ -45,9 +52,11 @@ pub fn change_then_branch(x: bool) -> u32 { return 0 } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail6")] pub fn change_then_branch(x: bool) -> u32 { if x { return 2 @@ -59,7 +68,7 @@ pub fn change_then_branch(x: bool) -> u32 { // Change else branch (if) -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn change_else_branch(x: bool) -> u32 { if x { 1 @@ -68,9 +77,11 @@ pub fn change_else_branch(x: bool) -> u32 { } } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail6")] pub fn change_else_branch(x: bool) -> u32 { if x { 1 @@ -82,20 +93,23 @@ pub fn change_else_branch(x: bool) -> u32 { // Add else branch (if) -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn add_else_branch(x: bool) -> u32 { let mut ret = 1; if x { ret = 2; + /*----*/ } ret } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck")] +#[rustc_clean(cfg="cfail6")] pub fn add_else_branch(x: bool) -> u32 { let mut ret = 1; @@ -110,7 +124,7 @@ pub fn add_else_branch(x: bool) -> u32 { // Change condition (if let) -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn change_condition_if_let(x: Option) -> u32 { if let Some(_x) = x { return 1 @@ -119,11 +133,13 @@ pub fn change_condition_if_let(x: Option) -> u32 { 0 } -#[cfg(not(cfail1))] +#[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")] +#[rustc_clean(cfg="cfail6")] pub fn change_condition_if_let(x: Option) -> u32 { - if let Some(_) = x { + if let Some(_ ) = x { return 1 } @@ -133,18 +149,20 @@ pub fn change_condition_if_let(x: Option) -> u32 { // Change then branch (if let) -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn change_then_branch_if_let(x: Option) -> u32 { if let Some(x) = x { - return x + return x //- } 0 } -#[cfg(not(cfail1))] +#[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")] +#[rustc_clean(cfg="cfail6")] pub fn change_then_branch_if_let(x: Option) -> u32 { if let Some(x) = x { return x + 1 @@ -156,7 +174,7 @@ pub fn change_then_branch_if_let(x: Option) -> u32 { // Change else branch (if let) -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn change_else_branch_if_let(x: Option) -> u32 { if let Some(x) = x { x @@ -165,9 +183,11 @@ pub fn change_else_branch_if_let(x: Option) -> u32 { } } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail6")] pub fn change_else_branch_if_let(x: Option) -> u32 { if let Some(x) = x { x @@ -179,20 +199,23 @@ pub fn change_else_branch_if_let(x: Option) -> u32 { // Add else branch (if let) -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn add_else_branch_if_let(x: Option) -> u32 { let mut ret = 1; if let Some(x) = x { ret = x; + /*----*/ } ret } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck,optimized_mir")] +#[rustc_clean(cfg="cfail6")] pub fn add_else_branch_if_let(x: Option) -> u32 { let mut ret = 1; diff --git a/src/test/incremental/hashes/indexing_expressions.rs b/src/test/incremental/hashes/indexing_expressions.rs index 49ee7a9cac..0532f4a0fd 100644 --- a/src/test/incremental/hashes/indexing_expressions.rs +++ b/src/test/incremental/hashes/indexing_expressions.rs @@ -6,22 +6,30 @@ // rev3 and make sure that the hash has not changed. // build-pass (FIXME(62277): could be check-pass?) -// revisions: cfail1 cfail2 cfail3 -// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans +// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6 +// compile-flags: -Z query-dep-graph +// [cfail1]compile-flags: -Zincremental-ignore-spans +// [cfail2]compile-flags: -Zincremental-ignore-spans +// [cfail3]compile-flags: -Zincremental-ignore-spans +// [cfail4]compile-flags: -Zincremental-relative-spans +// [cfail5]compile-flags: -Zincremental-relative-spans +// [cfail6]compile-flags: -Zincremental-relative-spans #![allow(warnings)] #![feature(rustc_attrs)] #![crate_type="rlib"] // Change simple index -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] fn change_simple_index(slice: &[u32]) -> u32 { slice[3] } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(except="hir_owner_nodes", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(except="hir_owner_nodes", cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] fn change_simple_index(slice: &[u32]) -> u32 { slice[4] } @@ -29,14 +37,16 @@ fn change_simple_index(slice: &[u32]) -> u32 { // Change lower bound -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] fn change_lower_bound(slice: &[u32]) -> &[u32] { &slice[3..5] } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(except="hir_owner_nodes", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(except="hir_owner_nodes", cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] fn change_lower_bound(slice: &[u32]) -> &[u32] { &slice[2..5] } @@ -44,14 +54,16 @@ fn change_lower_bound(slice: &[u32]) -> &[u32] { // Change upper bound -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] fn change_upper_bound(slice: &[u32]) -> &[u32] { &slice[3..5] } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(except="hir_owner_nodes", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(except="hir_owner_nodes", cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] fn change_upper_bound(slice: &[u32]) -> &[u32] { &slice[3..7] } @@ -59,14 +71,16 @@ fn change_upper_bound(slice: &[u32]) -> &[u32] { // Add lower bound -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] fn add_lower_bound(slice: &[u32]) -> &[u32] { - &slice[..4] + &slice[ ..4] } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(except="hir_owner_nodes,typeck", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(except="hir_owner_nodes,typeck", cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] fn add_lower_bound(slice: &[u32]) -> &[u32] { &slice[3..4] } @@ -74,14 +88,16 @@ fn add_lower_bound(slice: &[u32]) -> &[u32] { // Add upper bound -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] fn add_upper_bound(slice: &[u32]) -> &[u32] { - &slice[3..] + &slice[3.. ] } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(except="hir_owner_nodes,typeck", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(except="hir_owner_nodes,typeck", cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] fn add_upper_bound(slice: &[u32]) -> &[u32] { &slice[3..7] } @@ -89,29 +105,33 @@ fn add_upper_bound(slice: &[u32]) -> &[u32] { // Change mutability -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] fn change_mutability(slice: &mut [u32]) -> u32 { (&mut slice[3..5])[0] } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(except="hir_owner_nodes,typeck", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(except="hir_owner_nodes,typeck", cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] fn change_mutability(slice: &mut [u32]) -> u32 { - (&slice[3..5])[0] + (& slice[3..5])[0] } // Exclusive to inclusive range -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] fn exclusive_to_inclusive_range(slice: &[u32]) -> &[u32] { - &slice[3..7] + &slice[3.. 7] } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(except="hir_owner_nodes,typeck", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(except="hir_owner_nodes,typeck", cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] fn exclusive_to_inclusive_range(slice: &[u32]) -> &[u32] { &slice[3..=7] } diff --git a/src/test/incremental/hashes/inherent_impls.rs b/src/test/incremental/hashes/inherent_impls.rs index 284a95f1a6..3a59377e81 100644 --- a/src/test/incremental/hashes/inherent_impls.rs +++ b/src/test/incremental/hashes/inherent_impls.rs @@ -6,8 +6,14 @@ // rev3 and make sure that the hash has not changed. // build-pass (FIXME(62277): could be check-pass?) -// revisions: cfail1 cfail2 cfail3 -// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans +// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6 +// compile-flags: -Z query-dep-graph +// [cfail1]compile-flags: -Zincremental-ignore-spans +// [cfail2]compile-flags: -Zincremental-ignore-spans +// [cfail3]compile-flags: -Zincremental-ignore-spans +// [cfail4]compile-flags: -Zincremental-relative-spans +// [cfail5]compile-flags: -Zincremental-relative-spans +// [cfail6]compile-flags: -Zincremental-relative-spans #![allow(warnings)] @@ -17,36 +23,46 @@ pub struct Foo; // Change Method Name ----------------------------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] impl Foo { pub fn method_name() { } } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2", except="hir_owner,associated_item_def_ids")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner,associated_item_def_ids")] +#[rustc_clean(cfg="cfail6")] impl Foo { #[rustc_clean(cfg="cfail3")] + #[rustc_clean(cfg="cfail6")] pub fn method_name2() { } } // Change Method Body ----------------------------------------------------------- // // This should affect the method itself, but not the impl. -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] impl Foo { - pub fn method_body() { } + //-------------------------------------------------------------------------------------- + //-------------------------- + //-------------------------------------------------------------------------------------- + //-------------------------- + pub fn method_body() { + // ----------------------- + } } -#[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2")] +#[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")] +#[rustc_clean(cfg="cfail6")] impl Foo { - #[rustc_clean( - cfg="cfail2", - except="hir_owner_nodes,optimized_mir,promoted_mir,typeck" - )] + #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,promoted_mir,typeck")] #[rustc_clean(cfg="cfail3")] + #[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,promoted_mir,typeck")] + #[rustc_clean(cfg="cfail6")] pub fn method_body() { println!("Hello, world!"); } @@ -56,21 +72,40 @@ impl Foo { // Change Method Body (inlined) ------------------------------------------------ // // This should affect the method itself, but not the impl. -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] impl Foo { + //------------ + //--------------- + //------------------------------------------------------------ + // + //-------------------------- + //------------ + //--------------- + //------------------------------------------------------------ + // + //-------------------------- #[inline] - pub fn method_body_inlined() { } + pub fn method_body_inlined() { + // ----------------------- + } } -#[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2")] +#[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")] +#[rustc_clean(cfg="cfail6")] impl Foo { #[rustc_clean( cfg="cfail2", except="hir_owner_nodes,optimized_mir,promoted_mir,typeck" )] #[rustc_clean(cfg="cfail3")] + #[rustc_clean( + cfg="cfail5", + except="hir_owner_nodes,optimized_mir,promoted_mir,typeck" + )] + #[rustc_clean(cfg="cfail6")] #[inline] pub fn method_body_inlined() { println!("Hello, world!"); @@ -79,146 +114,209 @@ impl Foo { // Change Method Privacy ------------------------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] impl Foo { + //------------------------------------------------------------------------------ + //-------------------------- + //------------------------------------------------------------------------------ + //-------------------------- pub fn method_privacy() { } } -#[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="hir_owner")] +#[cfg(not(any(cfail1,cfail4)))] +#[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] impl Foo { #[rustc_clean(cfg="cfail2", except="associated_item,hir_owner,hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] - fn method_privacy() { } + #[rustc_clean(cfg="cfail5", except="associated_item,hir_owner,hir_owner_nodes")] + #[rustc_clean(cfg="cfail6")] + fn method_privacy() { } } // Change Method Selfness ----------------------------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] impl Foo { + //------------ + //--------------- + //--------------------------------------------------------------------------------------------- + // + //-------------------------- + //------------ + //--------------- + //--------------------------------------------------------------------------------------------- + // + //-------------------------- pub fn method_selfness() { } } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2", except="hir_owner")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner")] +#[rustc_clean(cfg="cfail6")] impl Foo { #[rustc_clean( cfg="cfail2", except="hir_owner,hir_owner_nodes,fn_sig,generics_of,typeck,associated_item,optimized_mir", )] #[rustc_clean(cfg="cfail3")] + #[rustc_clean( + cfg="cfail5", + except="hir_owner,hir_owner_nodes,fn_sig,generics_of,typeck,associated_item,optimized_mir", + )] + #[rustc_clean(cfg="cfail6")] pub fn method_selfness(&self) { } } // Change Method Selfmutness --------------------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] impl Foo { - pub fn method_selfmutness(&self) { } + //------------------------------------------------------------------------------------------ + //-------------------------- + //------------------------------------------------------------------------------------------ + //-------------------------- + pub fn method_selfmutness(& self) { } } -#[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2")] +#[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")] +#[rustc_clean(cfg="cfail6")] impl Foo { - #[rustc_clean( - cfg="cfail2", - except="hir_owner,hir_owner_nodes,fn_sig,typeck,optimized_mir" - )] + #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,fn_sig,typeck,optimized_mir")] #[rustc_clean(cfg="cfail3")] + #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,fn_sig,typeck,optimized_mir")] + #[rustc_clean(cfg="cfail6")] pub fn method_selfmutness(&mut self) { } } // Add Method To Impl ---------------------------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] impl Foo { pub fn add_method_to_impl1(&self) { } } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2", except="hir_owner,associated_item_def_ids")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner,associated_item_def_ids")] +#[rustc_clean(cfg="cfail6")] impl Foo { #[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] + #[rustc_clean(cfg="cfail5")] + #[rustc_clean(cfg="cfail6")] pub fn add_method_to_impl1(&self) { } #[rustc_clean(cfg="cfail3")] + #[rustc_clean(cfg="cfail6")] pub fn add_method_to_impl2(&self) { } } // Add Method Parameter -------------------------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] impl Foo { - pub fn add_method_parameter(&self) { } + //------------------------------------------------------------------------------------------ + //-------------------------- + //------------------------------------------------------------------------------------------ + //-------------------------- + pub fn add_method_parameter(&self ) { } } -#[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2")] +#[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")] +#[rustc_clean(cfg="cfail6")] impl Foo { - #[rustc_clean( - cfg="cfail2", - except="hir_owner,hir_owner_nodes,fn_sig,typeck,optimized_mir" - )] + #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,fn_sig,typeck,optimized_mir")] #[rustc_clean(cfg="cfail3")] + #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,fn_sig,typeck,optimized_mir")] + #[rustc_clean(cfg="cfail6")] pub fn add_method_parameter(&self, _: i32) { } } // Change Method Parameter Name ------------------------------------------------ -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] impl Foo { + //------------------------------------------------------------------ + //-------------------------- + //------------------------------------------------------------------ + //-------------------------- pub fn change_method_parameter_name(&self, a: i64) { } } -#[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2")] +#[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")] +#[rustc_clean(cfg="cfail6")] impl Foo { #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail3")] + #[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")] + #[rustc_clean(cfg="cfail6")] pub fn change_method_parameter_name(&self, b: i64) { } } // Change Method Return Type --------------------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] impl Foo { + //------------------------------------------------------------------------------------------ + //-------------------------- + //------------------------------------------------------------------------------------------ + //-------------------------- pub fn change_method_return_type(&self) -> u16 { 0 } } -#[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2")] +#[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")] +#[rustc_clean(cfg="cfail6")] impl Foo { - #[rustc_clean( - cfg="cfail2", - except="hir_owner,hir_owner_nodes,fn_sig,optimized_mir,typeck")] + #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,fn_sig,optimized_mir,typeck")] #[rustc_clean(cfg="cfail3")] - pub fn change_method_return_type(&self) -> u8 { 0 } + #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,fn_sig,optimized_mir,typeck")] + #[rustc_clean(cfg="cfail6")] + pub fn change_method_return_type(&self) -> u32 { 0 } } // Make Method #[inline] ------------------------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] impl Foo { + //-------------------------- + //-------------------------- + //-------------------------- + //-------------------------- + //------- pub fn make_method_inline(&self) -> u8 { 0 } } -#[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2")] +#[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")] +#[rustc_clean(cfg="cfail6")] impl Foo { #[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] + #[rustc_clean(cfg="cfail5")] + #[rustc_clean(cfg="cfail6")] #[inline] pub fn make_method_inline(&self) -> u8 { 0 } } @@ -226,85 +324,129 @@ impl Foo { // Change order of parameters ------------------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] impl Foo { + //------------------------------------------------------------------ + //-------------------------- + //------------------------------------------------------------------ + //-------------------------- pub fn change_method_parameter_order(&self, a: i64, b: i64) { } } -#[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2")] +#[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")] +#[rustc_clean(cfg="cfail6")] impl Foo { #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail3")] + #[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")] + #[rustc_clean(cfg="cfail6")] pub fn change_method_parameter_order(&self, b: i64, a: i64) { } } // Make method unsafe ---------------------------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] impl Foo { - pub fn make_method_unsafe(&self) { } + //------------------------------------------------------------------------------------------ + //-------------------------- + //------------------------------------------------------------------------------------------ + //-------------------------- + pub fn make_method_unsafe(&self) { } } -#[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2")] +#[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")] +#[rustc_clean(cfg="cfail6")] impl Foo { - #[rustc_clean( - cfg="cfail2", - except="hir_owner,hir_owner_nodes,fn_sig,typeck,optimized_mir" - )] + #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,fn_sig,typeck,optimized_mir")] #[rustc_clean(cfg="cfail3")] + #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,fn_sig,typeck,optimized_mir")] + #[rustc_clean(cfg="cfail6")] pub unsafe fn make_method_unsafe(&self) { } } // Make method extern ---------------------------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] impl Foo { - pub fn make_method_extern(&self) { } + //---------------------------------------------------------------------------- + //-------------------------- + //---------------------------------------------------------------------------- + //-------------------------- + pub fn make_method_extern(&self) { } } -#[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2")] +#[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")] +#[rustc_clean(cfg="cfail6")] impl Foo { #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,fn_sig,typeck")] #[rustc_clean(cfg="cfail3")] + #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,fn_sig,typeck")] + #[rustc_clean(cfg="cfail6")] pub extern "C" fn make_method_extern(&self) { } } // Change method calling convention -------------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] impl Foo { - pub extern "C" fn change_method_calling_convention(&self) { } + //---------------------------------------------------------------------------- + //-------------------------- + //---------------------------------------------------------------------------- + //-------------------------- + pub extern "C" fn change_method_calling_convention(&self) { } } -#[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2")] +#[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")] +#[rustc_clean(cfg="cfail6")] impl Foo { #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,fn_sig,typeck")] #[rustc_clean(cfg="cfail3")] + #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,fn_sig,typeck")] + #[rustc_clean(cfg="cfail6")] pub extern "system" fn change_method_calling_convention(&self) { } } // Add Lifetime Parameter to Method -------------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] impl Foo { - pub fn add_lifetime_parameter_to_method(&self) { } + // ----------------------------------------------------- + // --------------------------------------------------------- + // ---------------------------------------------------------- + // ------------------------------------------------------- + // ------------------------------------------------------- + // -------------------------------------------------------- + // ---------------------------------------------------------- + // ----------------------------------------------------------- + // ---------------------------------------------------------- + // -------------------------------------------------------------------- + // ------------------------- + // -------------------------------------------------------------------------------- + // ------------------------- + pub fn add_lifetime_parameter_to_method (&self) { } } -#[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2")] +#[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")] +#[rustc_clean(cfg="cfail6")] impl Foo { // Warning: Note that `typeck` are coming up clean here. // The addition or removal of lifetime parameters that don't @@ -317,20 +459,43 @@ impl Foo { // `typeck` appear dirty, that might be the cause. -nmatsakis #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,fn_sig")] #[rustc_clean(cfg="cfail3")] + #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,fn_sig,generics_of")] + #[rustc_clean(cfg="cfail6")] pub fn add_lifetime_parameter_to_method<'a>(&self) { } } // Add Type Parameter To Method ------------------------------------------------ -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] impl Foo { - pub fn add_type_parameter_to_method(&self) { } + // ----------------------------------------------------- + // --------------------------------------------------------------- + // ------------------------------------------------------------- + // ----------------------------------------------------- + // ------------------------------------------------------------- + // --------------------------------------------------- + // ------------------------------------------------------------ + // ------------------------------------------------------ + // ------------------------------------------------- + // ----------- + // -------------- + // ---------------------------------------------------------------------- + // + // ------------------------- + // ----------- + // -------------- + // ---------------------------------------------------------------------- + // + // ------------------------- + pub fn add_type_parameter_to_method (&self) { } } -#[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2")] +#[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")] +#[rustc_clean(cfg="cfail6")] impl Foo { // Warning: Note that `typeck` are coming up clean here. // The addition or removal of type parameters that don't appear in @@ -346,40 +511,83 @@ impl Foo { except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of", )] #[rustc_clean(cfg="cfail3")] + #[rustc_clean( + cfg="cfail5", + except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of", + )] + #[rustc_clean(cfg="cfail6")] pub fn add_type_parameter_to_method(&self) { } } // Add Lifetime Bound to Lifetime Parameter of Method -------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] impl Foo { - pub fn add_lifetime_bound_to_lifetime_param_of_method<'a, 'b>(&self) { } + //------------ + //--------------- + //----------------------------------------------------------------------------- + // + //-------------------------- + //------------ + //--------------- + //----------------------------------------------------------------------------- + // + //-------------------------- + pub fn add_lifetime_bound_to_lifetime_param_of_method<'a, 'b >(&self) { } } -#[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2")] +#[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")] +#[rustc_clean(cfg="cfail6")] impl Foo { #[rustc_clean( cfg="cfail2", except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of,fn_sig" )] #[rustc_clean(cfg="cfail3")] + #[rustc_clean( + cfg="cfail5", + except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of,fn_sig" + )] + #[rustc_clean(cfg="cfail6")] pub fn add_lifetime_bound_to_lifetime_param_of_method<'a, 'b: 'a>(&self) { } } // Add Lifetime Bound to Type Parameter of Method ------------------------------ -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] impl Foo { - pub fn add_lifetime_bound_to_type_param_of_method<'a, T>(&self) { } + // ----------------------------------------------------- + // ---------------------------------------------------------- + // ------------------------------------------------------------- + // ------------------------------------------------- + // ------------------------------------------------------------- + // --------------------------------------------------- + // ------------------------------------------------------------ + // ------------------------------------------------------ + // ------------------------------------------------- + // ----------- + // -------------- + // ---------------------------------------------------------------------------- + // + // ------------------------- + // ----------- + // -------------- + // ---------------------------------------------------------------------------- + // + // ------------------------- + pub fn add_lifetime_bound_to_type_param_of_method<'a, T >(&self) { } } -#[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2")] +#[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")] +#[rustc_clean(cfg="cfail6")] impl Foo { // Warning: Note that `typeck` are coming up clean here. // The addition or removal of bounds that don't appear in the @@ -390,23 +598,45 @@ impl Foo { // generics before the body, then the `HirId` for things in the // body will be affected. So if you start to see `typeck` // appear dirty, that might be the cause. -nmatsakis - #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,generics_of,predicates_of,\ - type_of,fn_sig")] + #[rustc_clean( + cfg="cfail2", + except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of,fn_sig" + )] #[rustc_clean(cfg="cfail3")] + #[rustc_clean( + cfg="cfail5", + except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of,fn_sig" + )] + #[rustc_clean(cfg="cfail6")] pub fn add_lifetime_bound_to_type_param_of_method<'a, T: 'a>(&self) { } } // Add Trait Bound to Type Parameter of Method ------------------------------ -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] impl Foo { - pub fn add_trait_bound_to_type_param_of_method(&self) { } + // ----------------------------------------------------- + // ---------------------------------------------------------- + // ------------------------------------------------------------- + // ------------------------------------------------- + // ------------------------------------------------------------- + // --------------------------------------------------- + // ------------------------------------------------------------ + // ------------------------------------------------------ + // ------------------------------------------------- + // --------------------------------------------------------------------------- + // ------------------------- + // --------------------------------------------------------------------------- + // ------------------------- + pub fn add_trait_bound_to_type_param_of_method(&self) { } } -#[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2")] +#[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")] +#[rustc_clean(cfg="cfail6")] impl Foo { // Warning: Note that `typeck` are coming up clean here. // The addition or removal of bounds that don't appear in the @@ -419,23 +649,34 @@ impl Foo { // appear dirty, that might be the cause. -nmatsakis #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,predicates_of")] #[rustc_clean(cfg="cfail3")] + #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,predicates_of")] + #[rustc_clean(cfg="cfail6")] pub fn add_trait_bound_to_type_param_of_method(&self) { } } // Add #[no_mangle] to Method -------------------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] impl Foo { + //-------------------------- + //-------------------------- + //-------------------------- + //-------------------------- + //---------- pub fn add_no_mangle_to_method(&self) { } } -#[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2")] +#[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")] +#[rustc_clean(cfg="cfail6")] impl Foo { #[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] + #[rustc_clean(cfg="cfail5")] + #[rustc_clean(cfg="cfail6")] #[no_mangle] pub fn add_no_mangle_to_method(&self) { } } @@ -445,71 +686,90 @@ impl Foo { struct Bar(T); // Add Type Parameter To Impl -------------------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] impl Bar { pub fn add_type_parameter_to_impl(&self) { } } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,generics_of")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,generics_of")] +#[rustc_clean(cfg="cfail6")] impl Bar { #[rustc_clean( cfg="cfail2", except="generics_of,fn_sig,typeck,type_of,optimized_mir" )] #[rustc_clean(cfg="cfail3")] + #[rustc_clean( + cfg="cfail5", + except="generics_of,fn_sig,typeck,type_of,optimized_mir" + )] + #[rustc_clean(cfg="cfail6")] pub fn add_type_parameter_to_impl(&self) { } } // Change Self Type of Impl ---------------------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] impl Bar { pub fn change_impl_self_type(&self) { } } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2", except="hir_owner")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner")] +#[rustc_clean(cfg="cfail6")] impl Bar { #[rustc_clean(cfg="cfail2", except="fn_sig,optimized_mir,typeck")] #[rustc_clean(cfg="cfail3")] + #[rustc_clean(cfg="cfail5", except="fn_sig,optimized_mir,typeck")] + #[rustc_clean(cfg="cfail6")] pub fn change_impl_self_type(&self) { } } // Add Lifetime Bound to Impl -------------------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] impl Bar { pub fn add_lifetime_bound_to_impl_parameter(&self) { } } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")] +#[rustc_clean(cfg="cfail6")] impl Bar { #[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] + #[rustc_clean(cfg="cfail5")] + #[rustc_clean(cfg="cfail6")] pub fn add_lifetime_bound_to_impl_parameter(&self) { } } // Add Trait Bound to Impl Parameter ------------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] impl Bar { pub fn add_trait_bound_to_impl_parameter(&self) { } } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")] +#[rustc_clean(cfg="cfail6")] impl Bar { #[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] + #[rustc_clean(cfg="cfail5")] + #[rustc_clean(cfg="cfail6")] pub fn add_trait_bound_to_impl_parameter(&self) { } } @@ -518,12 +778,12 @@ impl Bar { pub fn instantiation_root() { Foo::method_privacy(); - #[cfg(cfail1)] + #[cfg(any(cfail1,cfail4))] { Bar(0u32).change_impl_self_type(); } - #[cfg(not(cfail1))] + #[cfg(not(any(cfail1,cfail4)))] { Bar(0u64).change_impl_self_type(); } diff --git a/src/test/incremental/hashes/inline_asm.rs b/src/test/incremental/hashes/inline_asm.rs index 7fd9975bc2..a5d53258a7 100644 --- a/src/test/incremental/hashes/inline_asm.rs +++ b/src/test/incremental/hashes/inline_asm.rs @@ -6,8 +6,14 @@ // rev3 and make sure that the hash has not changed. // build-pass (FIXME(62277): could be check-pass?) -// revisions: cfail1 cfail2 cfail3 -// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans +// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6 +// compile-flags: -Z query-dep-graph +// [cfail1]compile-flags: -Zincremental-ignore-spans +// [cfail2]compile-flags: -Zincremental-ignore-spans +// [cfail3]compile-flags: -Zincremental-ignore-spans +// [cfail4]compile-flags: -Zincremental-relative-spans +// [cfail5]compile-flags: -Zincremental-relative-spans +// [cfail6]compile-flags: -Zincremental-relative-spans #![allow(warnings)] #![feature(rustc_attrs)] @@ -17,7 +23,7 @@ // Change template -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] pub fn change_template(a: i32) -> i32 { let c: i32; @@ -32,9 +38,11 @@ pub fn change_template(a: i32) -> i32 { c } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")] +#[rustc_clean(cfg="cfail6")] #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] pub fn change_template(a: i32) -> i32 { let c: i32; @@ -52,7 +60,7 @@ pub fn change_template(a: i32) -> i32 { // Change output -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] pub fn change_output(a: i32) -> i32 { let mut _out1: i32 = 0; @@ -68,9 +76,11 @@ pub fn change_output(a: i32) -> i32 { _out1 } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")] +#[rustc_clean(cfg="cfail6")] #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] pub fn change_output(a: i32) -> i32 { let mut _out1: i32 = 0; @@ -89,7 +99,7 @@ pub fn change_output(a: i32) -> i32 { // Change input -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] pub fn change_input(_a: i32, _b: i32) -> i32 { let _out; @@ -104,9 +114,11 @@ pub fn change_input(_a: i32, _b: i32) -> i32 { _out } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")] +#[rustc_clean(cfg="cfail6")] #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] pub fn change_input(_a: i32, _b: i32) -> i32 { let _out; @@ -124,7 +136,7 @@ pub fn change_input(_a: i32, _b: i32) -> i32 { // Change input constraint -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] pub fn change_input_constraint(_a: i32, _b: i32) -> i32 { let _out; @@ -139,9 +151,11 @@ pub fn change_input_constraint(_a: i32, _b: i32) -> i32 { _out } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")] +#[rustc_clean(cfg="cfail6")] #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] pub fn change_input_constraint(_a: i32, _b: i32) -> i32 { let _out; @@ -159,7 +173,7 @@ pub fn change_input_constraint(_a: i32, _b: i32) -> i32 { // Change clobber -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] pub fn change_clobber(_a: i32) -> i32 { let _out; @@ -167,16 +181,18 @@ pub fn change_clobber(_a: i32) -> i32 { llvm_asm!("add 1, $0" : "=r"(_out) : "0"(_a) - : + :/*--*/ : ); } _out } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")] +#[rustc_clean(cfg="cfail6")] #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] pub fn change_clobber(_a: i32) -> i32 { let _out; @@ -194,7 +210,7 @@ pub fn change_clobber(_a: i32) -> i32 { // Change options -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] pub fn change_options(_a: i32) -> i32 { let _out; @@ -203,15 +219,17 @@ pub fn change_options(_a: i32) -> i32 { : "=r"(_out) : "0"(_a) : - : + :/*-------*/ ); } _out } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")] +#[rustc_clean(cfg="cfail6")] #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] pub fn change_options(_a: i32) -> i32 { let _out; diff --git a/src/test/incremental/hashes/let_expressions.rs b/src/test/incremental/hashes/let_expressions.rs index 918e72582d..a9f90ca9fe 100644 --- a/src/test/incremental/hashes/let_expressions.rs +++ b/src/test/incremental/hashes/let_expressions.rs @@ -6,24 +6,30 @@ // rev3 and make sure that the hash has not changed. // build-pass (FIXME(62277): could be check-pass?) -// revisions: cfail1 cfail2 cfail3 -// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans - +// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6 +// compile-flags: -Z query-dep-graph +// [cfail1]compile-flags: -Zincremental-ignore-spans +// [cfail2]compile-flags: -Zincremental-ignore-spans +// [cfail3]compile-flags: -Zincremental-ignore-spans +// [cfail4]compile-flags: -Zincremental-relative-spans +// [cfail5]compile-flags: -Zincremental-relative-spans +// [cfail6]compile-flags: -Zincremental-relative-spans #![allow(warnings)] #![feature(rustc_attrs)] #![crate_type="rlib"] // Change Name ----------------------------------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn change_name() { let _x = 2u64; } -#[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", - except="hir_owner_nodes,optimized_mir")] +#[cfg(not(any(cfail1,cfail4)))] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail6")] pub fn change_name() { let _y = 2u64; } @@ -31,15 +37,16 @@ pub fn change_name() { // Add Type -------------------------------------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn add_type() { - let _x = 2u32; + let _x = 2u32; } -#[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", - except="hir_owner_nodes,typeck")] +#[cfg(not(any(cfail1,cfail4)))] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck")] +#[rustc_clean(cfg="cfail6")] pub fn add_type() { let _x: u32 = 2u32; } @@ -47,31 +54,33 @@ pub fn add_type() { // Change Type ----------------------------------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn change_type() { let _x: u64 = 2; } -#[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", - except="hir_owner_nodes,typeck,optimized_mir")] +#[cfg(not(any(cfail1,cfail4)))] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck,optimized_mir")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck,optimized_mir")] +#[rustc_clean(cfg="cfail6")] pub fn change_type() { - let _x: u8 = 2; + let _x: u8 = 2; } // Change Mutability of Reference Type ----------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn change_mutability_of_reference_type() { - let _x: &u64; + let _x: & u64; } -#[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", - except="hir_owner_nodes,typeck,optimized_mir")] +#[cfg(not(any(cfail1,cfail4)))] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck,optimized_mir")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck,optimized_mir")] +#[rustc_clean(cfg="cfail6")] pub fn change_mutability_of_reference_type() { let _x: &mut u64; } @@ -79,31 +88,33 @@ pub fn change_mutability_of_reference_type() { // Change Mutability of Slot --------------------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn change_mutability_of_slot() { let mut _x: u64 = 0; } -#[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", - except="hir_owner_nodes,typeck,optimized_mir")] +#[cfg(not(any(cfail1,cfail4)))] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck,optimized_mir")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck,optimized_mir")] +#[rustc_clean(cfg="cfail6")] pub fn change_mutability_of_slot() { - let _x: u64 = 0; + let _x: u64 = 0; } // Change Simple Binding to Pattern -------------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn change_simple_binding_to_pattern() { - let _x = (0u8, 'x'); + let _x = (0u8, 'x'); } -#[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", - except="hir_owner_nodes,typeck,optimized_mir")] +#[cfg(not(any(cfail1,cfail4)))] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck,optimized_mir")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck,optimized_mir")] +#[rustc_clean(cfg="cfail6")] pub fn change_simple_binding_to_pattern() { let (_a, _b) = (0u8, 'x'); } @@ -111,15 +122,16 @@ pub fn change_simple_binding_to_pattern() { // Change Name in Pattern ------------------------------------------------------ -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn change_name_in_pattern() { let (_a, _b) = (1u8, 'y'); } -#[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", - except="hir_owner_nodes,optimized_mir")] +#[cfg(not(any(cfail1,cfail4)))] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail6")] pub fn change_name_in_pattern() { let (_a, _c) = (1u8, 'y'); } @@ -127,15 +139,16 @@ pub fn change_name_in_pattern() { // Add `ref` in Pattern -------------------------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn add_ref_in_pattern() { - let (_a, _b) = (1u8, 'y'); + let ( _a, _b) = (1u8, 'y'); } -#[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", - except="hir_owner_nodes,typeck,optimized_mir")] +#[cfg(not(any(cfail1,cfail4)))] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck,optimized_mir")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck,optimized_mir")] +#[rustc_clean(cfg="cfail6")] pub fn add_ref_in_pattern() { let (ref _a, _b) = (1u8, 'y'); } @@ -143,15 +156,16 @@ pub fn add_ref_in_pattern() { // Add `&` in Pattern ---------------------------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn add_amp_in_pattern() { - let (_a, _b) = (&1u8, 'y'); + let ( _a, _b) = (&1u8, 'y'); } -#[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", - except="hir_owner_nodes,typeck,optimized_mir")] +#[cfg(not(any(cfail1,cfail4)))] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck,optimized_mir")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck,optimized_mir")] +#[rustc_clean(cfg="cfail6")] pub fn add_amp_in_pattern() { let (&_a, _b) = (&1u8, 'y'); } @@ -159,15 +173,16 @@ pub fn add_amp_in_pattern() { // Change Mutability of Binding in Pattern ------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn change_mutability_of_binding_in_pattern() { - let (_a, _b) = (99u8, 'q'); + let ( _a, _b) = (99u8, 'q'); } -#[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", - except="hir_owner_nodes,typeck,optimized_mir")] +#[cfg(not(any(cfail1,cfail4)))] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck,optimized_mir")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck,optimized_mir")] +#[rustc_clean(cfg="cfail6")] pub fn change_mutability_of_binding_in_pattern() { let (mut _a, _b) = (99u8, 'q'); } @@ -175,15 +190,16 @@ pub fn change_mutability_of_binding_in_pattern() { // Add Initializer ------------------------------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn add_initializer() { - let _x: i16; + let _x: i16 ; } -#[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", - except="hir_owner_nodes,typeck,optimized_mir")] +#[cfg(not(any(cfail1,cfail4)))] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck,optimized_mir")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck,optimized_mir")] +#[rustc_clean(cfg="cfail6")] pub fn add_initializer() { let _x: i16 = 3i16; } @@ -191,15 +207,16 @@ pub fn add_initializer() { // Change Initializer ---------------------------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn change_initializer() { let _x = 4u16; } -#[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", - except="hir_owner_nodes,optimized_mir")] +#[cfg(not(any(cfail1,cfail4)))] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail6")] pub fn change_initializer() { let _x = 5u16; } diff --git a/src/test/incremental/hashes/loop_expressions.rs b/src/test/incremental/hashes/loop_expressions.rs index 178def016a..6fef31f5b3 100644 --- a/src/test/incremental/hashes/loop_expressions.rs +++ b/src/test/incremental/hashes/loop_expressions.rs @@ -6,8 +6,14 @@ // rev3 and make sure that the hash has not changed. // build-pass (FIXME(62277): could be check-pass?) -// revisions: cfail1 cfail2 cfail3 -// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans +// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6 +// compile-flags: -Z query-dep-graph +// [cfail1]compile-flags: -Zincremental-ignore-spans +// [cfail2]compile-flags: -Zincremental-ignore-spans +// [cfail3]compile-flags: -Zincremental-ignore-spans +// [cfail4]compile-flags: -Zincremental-relative-spans +// [cfail5]compile-flags: -Zincremental-relative-spans +// [cfail6]compile-flags: -Zincremental-relative-spans #![allow(warnings)] #![feature(rustc_attrs)] @@ -15,7 +21,7 @@ // Change loop body -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn change_loop_body() { let mut _x = 0; loop { @@ -24,9 +30,11 @@ pub fn change_loop_body() { } } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")] +#[rustc_clean(cfg="cfail6")] pub fn change_loop_body() { let mut _x = 0; loop { @@ -38,17 +46,20 @@ pub fn change_loop_body() { // Add break -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn add_break() { let mut _x = 0; loop { _x = 1; + //---- } } -#[cfg(not(cfail1))] +#[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")] +#[rustc_clean(cfg="cfail6")] pub fn add_break() { let mut _x = 0; loop { @@ -60,18 +71,20 @@ pub fn add_break() { // Add loop label -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn add_loop_label() { let mut _x = 0; - loop { + /*---*/ loop { _x = 1; break; } } -#[cfg(not(cfail1))] +#[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")] +#[rustc_clean(cfg="cfail6")] pub fn add_loop_label() { let mut _x = 0; 'label: loop { @@ -83,18 +96,20 @@ pub fn add_loop_label() { // Add loop label to break -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn add_loop_label_to_break() { let mut _x = 0; 'label: loop { _x = 1; - break; + break ; } } -#[cfg(not(cfail1))] +#[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")] +#[rustc_clean(cfg="cfail6")] pub fn add_loop_label_to_break() { let mut _x = 0; 'label: loop { @@ -106,7 +121,7 @@ pub fn add_loop_label_to_break() { // Change break label -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn change_break_label() { let mut _x = 0; 'outer: loop { @@ -117,9 +132,11 @@ pub fn change_break_label() { } } -#[cfg(not(cfail1))] +#[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")] +#[rustc_clean(cfg="cfail6")] pub fn change_break_label() { let mut _x = 0; 'outer: loop { @@ -133,18 +150,20 @@ pub fn change_break_label() { // Add loop label to continue -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn add_loop_label_to_continue() { let mut _x = 0; 'label: loop { _x = 1; - continue; + continue ; } } -#[cfg(not(cfail1))] +#[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="cfail6")] pub fn add_loop_label_to_continue() { let mut _x = 0; 'label: loop { @@ -156,7 +175,7 @@ pub fn add_loop_label_to_continue() { // Change continue label -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn change_continue_label() { let mut _x = 0; 'outer: loop { @@ -167,9 +186,11 @@ pub fn change_continue_label() { } } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2", except="hir_owner_nodes, typeck")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, typeck, optimized_mir")] +#[rustc_clean(cfg="cfail6")] pub fn change_continue_label() { let mut _x = 0; 'outer: loop { @@ -183,7 +204,7 @@ pub fn change_continue_label() { // Change continue to break -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn change_continue_to_break() { let mut _x = 0; loop { @@ -192,13 +213,15 @@ pub fn change_continue_to_break() { } } -#[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir, typeck")] +#[cfg(not(any(cfail1,cfail4)))] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, typeck, optimized_mir")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, typeck, optimized_mir")] +#[rustc_clean(cfg="cfail6")] pub fn change_continue_to_break() { let mut _x = 0; loop { _x = 1; - break; + break ; } } diff --git a/src/test/incremental/hashes/match_expressions.rs b/src/test/incremental/hashes/match_expressions.rs index 969f930f57..314461b590 100644 --- a/src/test/incremental/hashes/match_expressions.rs +++ b/src/test/incremental/hashes/match_expressions.rs @@ -6,28 +6,35 @@ // rev3 and make sure that the hash has not changed. // build-pass (FIXME(62277): could be check-pass?) -// revisions: cfail1 cfail2 cfail3 -// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans - +// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6 +// compile-flags: -Z query-dep-graph +// [cfail1]compile-flags: -Zincremental-ignore-spans +// [cfail2]compile-flags: -Zincremental-ignore-spans +// [cfail3]compile-flags: -Zincremental-ignore-spans +// [cfail4]compile-flags: -Zincremental-relative-spans +// [cfail5]compile-flags: -Zincremental-relative-spans +// [cfail6]compile-flags: -Zincremental-relative-spans #![allow(warnings)] #![feature(rustc_attrs)] #![crate_type="rlib"] // Add Arm --------------------------------------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn add_arm(x: u32) -> u32 { match x { 0 => 0, 1 => 1, + /*---*/ _ => 100, } } -#[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", - except="hir_owner_nodes,optimized_mir,typeck")] +#[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")] +#[rustc_clean(cfg="cfail6")] pub fn add_arm(x: u32) -> u32 { match x { 0 => 0, @@ -40,7 +47,7 @@ pub fn add_arm(x: u32) -> u32 { // Change Order Of Arms -------------------------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn change_order_of_arms(x: u32) -> u32 { match x { 0 => 0, @@ -49,10 +56,11 @@ pub fn change_order_of_arms(x: u32) -> u32 { } } -#[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", - except="hir_owner_nodes,optimized_mir")] +#[cfg(not(any(cfail1,cfail4)))] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail6")] pub fn change_order_of_arms(x: u32) -> u32 { match x { 1 => 1, @@ -64,19 +72,20 @@ pub fn change_order_of_arms(x: u32) -> u32 { // Add Guard Clause ------------------------------------------------------------ -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn add_guard_clause(x: u32, y: bool) -> u32 { match x { 0 => 0, - 1 => 1, + 1 => 1, _ => 100, } } -#[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", - except="hir_owner_nodes,optimized_mir,typeck")] +#[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")] +#[rustc_clean(cfg="cfail6")] pub fn add_guard_clause(x: u32, y: bool) -> u32 { match x { 0 => 0, @@ -88,19 +97,20 @@ pub fn add_guard_clause(x: u32, y: bool) -> u32 { // Change Guard Clause ------------------------------------------------------------ -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn change_guard_clause(x: u32, y: bool) -> u32 { match x { 0 => 0, - 1 if y => 1, + 1 if y => 1, _ => 100, } } -#[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", - except="hir_owner_nodes,optimized_mir,typeck")] +#[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")] +#[rustc_clean(cfg="cfail6")] pub fn change_guard_clause(x: u32, y: bool) -> u32 { match x { 0 => 0, @@ -112,19 +122,20 @@ pub fn change_guard_clause(x: u32, y: bool) -> u32 { // Add @-Binding --------------------------------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn add_at_binding(x: u32) -> u32 { match x { 0 => 0, 1 => 1, - _ => x, + _ => x, } } -#[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", - except="hir_owner_nodes,optimized_mir,typeck")] +#[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")] +#[rustc_clean(cfg="cfail6")] pub fn add_at_binding(x: u32) -> u32 { match x { 0 => 0, @@ -136,7 +147,7 @@ pub fn add_at_binding(x: u32) -> u32 { // Change Name of @-Binding ---------------------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn change_name_of_at_binding(x: u32) -> u32 { match x { 0 => 0, @@ -145,10 +156,11 @@ pub fn change_name_of_at_binding(x: u32) -> u32 { } } -#[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", - except="hir_owner_nodes,optimized_mir")] +#[cfg(not(any(cfail1,cfail4)))] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail6")] pub fn change_name_of_at_binding(x: u32) -> u32 { match x { 0 => 0, @@ -160,18 +172,19 @@ pub fn change_name_of_at_binding(x: u32) -> u32 { // Change Simple Binding To Pattern -------------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn change_simple_name_to_pattern(x: u32) -> u32 { match (x, x & 1) { (0, 0) => 0, - a => 1, + a => 1, } } -#[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", - except="hir_owner_nodes,optimized_mir,typeck")] +#[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")] +#[rustc_clean(cfg="cfail6")] pub fn change_simple_name_to_pattern(x: u32) -> u32 { match (x, x & 1) { (0, 0) => 0, @@ -182,7 +195,7 @@ pub fn change_simple_name_to_pattern(x: u32) -> u32 { // Change Name In Pattern ------------------------------------------------------ -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn change_name_in_pattern(x: u32) -> u32 { match (x, x & 1) { (a, 0) => 0, @@ -191,10 +204,11 @@ pub fn change_name_in_pattern(x: u32) -> u32 { } } -#[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", - except="hir_owner_nodes,optimized_mir")] +#[cfg(not(any(cfail1,cfail4)))] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail6")] pub fn change_name_in_pattern(x: u32) -> u32 { match (x, x & 1) { (b, 0) => 0, @@ -206,18 +220,19 @@ pub fn change_name_in_pattern(x: u32) -> u32 { // Change Mutability Of Binding In Pattern ------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn change_mutability_of_binding_in_pattern(x: u32) -> u32 { match (x, x & 1) { - (a, 0) => 0, + ( a, 0) => 0, _ => 1, } } -#[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", - except="hir_owner_nodes,optimized_mir,typeck")] +#[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")] +#[rustc_clean(cfg="cfail6")] pub fn change_mutability_of_binding_in_pattern(x: u32) -> u32 { match (x, x & 1) { (mut a, 0) => 0, @@ -228,18 +243,19 @@ pub fn change_mutability_of_binding_in_pattern(x: u32) -> u32 { // Add `ref` To Binding In Pattern ------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn add_ref_to_binding_in_pattern(x: u32) -> u32 { match (x, x & 1) { - (a, 0) => 0, + ( a, 0) => 0, _ => 1, } } -#[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", - except="hir_owner_nodes,optimized_mir,typeck")] +#[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")] +#[rustc_clean(cfg="cfail6")] pub fn add_ref_to_binding_in_pattern(x: u32) -> u32 { match (x, x & 1) { (ref a, 0) => 0, @@ -250,18 +266,19 @@ pub fn add_ref_to_binding_in_pattern(x: u32) -> u32 { // Add `&` To Binding In Pattern ------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn add_amp_to_binding_in_pattern(x: u32) -> u32 { match (&x, x & 1) { - (a, 0) => 0, + ( a, 0) => 0, _ => 1, } } -#[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", -except="hir_owner_nodes,optimized_mir,typeck")] +#[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")] +#[rustc_clean(cfg="cfail6")] pub fn add_amp_to_binding_in_pattern(x: u32) -> u32 { match (&x, x & 1) { (&a, 0) => 0, @@ -272,7 +289,7 @@ pub fn add_amp_to_binding_in_pattern(x: u32) -> u32 { // Change RHS Of Arm ----------------------------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn change_rhs_of_arm(x: u32) -> u32 { match x { 0 => 0, @@ -281,10 +298,11 @@ pub fn change_rhs_of_arm(x: u32) -> u32 { } } -#[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", - except="hir_owner_nodes,optimized_mir")] +#[cfg(not(any(cfail1,cfail4)))] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail6")] pub fn change_rhs_of_arm(x: u32) -> u32 { match x { 0 => 0, @@ -296,19 +314,20 @@ pub fn change_rhs_of_arm(x: u32) -> u32 { // Add Alternative To Arm ------------------------------------------------------ -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn add_alternative_to_arm(x: u32) -> u32 { match x { - 0 => 0, + 0 => 0, 1 => 1, _ => 2, } } -#[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", - except="hir_owner_nodes,optimized_mir,typeck")] +#[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")] +#[rustc_clean(cfg="cfail6")] pub fn add_alternative_to_arm(x: u32) -> u32 { match x { 0 | 7 => 0, diff --git a/src/test/incremental/hashes/statics.rs b/src/test/incremental/hashes/statics.rs index 6f4089c60f..2b2658b2f5 100644 --- a/src/test/incremental/hashes/statics.rs +++ b/src/test/incremental/hashes/statics.rs @@ -6,8 +6,14 @@ // rev3 and make sure that the hash has not changed. // build-pass (FIXME(62277): could be check-pass?) -// revisions: cfail1 cfail2 cfail3 -// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans +// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6 +// compile-flags: -Z query-dep-graph +// [cfail1]compile-flags: -Zincremental-ignore-spans +// [cfail2]compile-flags: -Zincremental-ignore-spans +// [cfail3]compile-flags: -Zincremental-ignore-spans +// [cfail4]compile-flags: -Zincremental-relative-spans +// [cfail5]compile-flags: -Zincremental-relative-spans +// [cfail6]compile-flags: -Zincremental-relative-spans #![allow(warnings)] #![feature(rustc_attrs)] @@ -17,86 +23,102 @@ // Change static visibility -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] static STATIC_VISIBILITY: u8 = 0; -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")] +#[rustc_clean(cfg="cfail6")] pub static STATIC_VISIBILITY: u8 = 0; // Change static mutability -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] static STATIC_MUTABILITY: u8 = 0; -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")] +#[rustc_clean(cfg="cfail6")] static mut STATIC_MUTABILITY: u8 = 0; // Add linkage attribute -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] static STATIC_LINKAGE: u8 = 0; -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] #[linkage="weak_odr"] static STATIC_LINKAGE: u8 = 0; // Add no_mangle attribute -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] static STATIC_NO_MANGLE: u8 = 0; -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] #[no_mangle] static STATIC_NO_MANGLE: u8 = 0; // Add thread_local attribute -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] static STATIC_THREAD_LOCAL: u8 = 0; -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] #[thread_local] static STATIC_THREAD_LOCAL: u8 = 0; // Change type from i16 to u64 -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] static STATIC_CHANGE_TYPE_1: i16 = 0; -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail6")] static STATIC_CHANGE_TYPE_1: u64 = 0; // Change type from Option to Option -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] static STATIC_CHANGE_TYPE_2: Option = None; -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail6")] static STATIC_CHANGE_TYPE_2: Option = None; // Change value between simple literals #[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail6")] static STATIC_CHANGE_VALUE_1: i16 = { - #[cfg(cfail1)] + #[cfg(any(cfail1,cfail4))] { 1 } - #[cfg(not(cfail1))] + #[cfg(not(any(cfail1,cfail4)))] { 2 } }; @@ -104,31 +126,37 @@ static STATIC_CHANGE_VALUE_1: i16 = { // Change value between expressions #[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail6")] static STATIC_CHANGE_VALUE_2: i16 = { - #[cfg(cfail1)] + #[cfg(any(cfail1,cfail4))] { 1 + 1 } - #[cfg(not(cfail1))] + #[cfg(not(any(cfail1,cfail4)))] { 1 + 2 } }; #[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail6")] static STATIC_CHANGE_VALUE_3: i16 = { - #[cfg(cfail1)] + #[cfg(any(cfail1,cfail4))] { 2 + 3 } - #[cfg(not(cfail1))] + #[cfg(not(any(cfail1,cfail4)))] { 2 * 3 } }; #[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail6")] static STATIC_CHANGE_VALUE_4: i16 = { - #[cfg(cfail1)] + #[cfg(any(cfail1,cfail4))] { 1 + 2 * 3 } - #[cfg(not(cfail1))] + #[cfg(not(any(cfail1,cfail4)))] { 1 + 2 * 4 } }; @@ -138,17 +166,21 @@ struct ReferencedType1; struct ReferencedType2; mod static_change_type_indirectly { - #[cfg(cfail1)] + #[cfg(any(cfail1,cfail4))] use super::ReferencedType1 as Type; - #[cfg(not(cfail1))] + #[cfg(not(any(cfail1,cfail4)))] use super::ReferencedType2 as Type; #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] + #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")] + #[rustc_clean(cfg="cfail6")] static STATIC_CHANGE_TYPE_INDIRECTLY_1: Type = Type; #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] + #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")] + #[rustc_clean(cfg="cfail6")] static STATIC_CHANGE_TYPE_INDIRECTLY_2: Option = None; } diff --git a/src/test/incremental/hashes/struct_constructors.rs b/src/test/incremental/hashes/struct_constructors.rs index edec03d4f0..6a62620463 100644 --- a/src/test/incremental/hashes/struct_constructors.rs +++ b/src/test/incremental/hashes/struct_constructors.rs @@ -6,8 +6,14 @@ // rev3 and make sure that the hash has not changed. // build-pass (FIXME(62277): could be check-pass?) -// revisions: cfail1 cfail2 cfail3 -// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans +// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6 +// compile-flags: -Z query-dep-graph +// [cfail1]compile-flags: -Zincremental-ignore-spans +// [cfail2]compile-flags: -Zincremental-ignore-spans +// [cfail3]compile-flags: -Zincremental-ignore-spans +// [cfail4]compile-flags: -Zincremental-relative-spans +// [cfail5]compile-flags: -Zincremental-relative-spans +// [cfail6]compile-flags: -Zincremental-relative-spans #![allow(warnings)] #![feature(rustc_attrs)] @@ -21,7 +27,7 @@ pub struct RegularStruct { } // Change field value (regular struct) -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn change_field_value_regular_struct() -> RegularStruct { RegularStruct { x: 0, @@ -30,9 +36,11 @@ pub fn change_field_value_regular_struct() -> RegularStruct { } } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail6")] pub fn change_field_value_regular_struct() -> RegularStruct { RegularStruct { x: 0, @@ -44,7 +52,7 @@ pub fn change_field_value_regular_struct() -> RegularStruct { // Change field order (regular struct) -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn change_field_order_regular_struct() -> RegularStruct { RegularStruct { x: 3, @@ -53,9 +61,11 @@ pub fn change_field_order_regular_struct() -> RegularStruct { } } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck,optimized_mir")] +#[rustc_clean(cfg="cfail6")] pub fn change_field_order_regular_struct() -> RegularStruct { RegularStruct { y: 4, @@ -67,7 +77,7 @@ pub fn change_field_order_regular_struct() -> RegularStruct { // Add field (regular struct) -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn add_field_regular_struct() -> RegularStruct { let struct1 = RegularStruct { x: 3, @@ -77,13 +87,16 @@ pub fn add_field_regular_struct() -> RegularStruct { RegularStruct { x: 7, + // -- .. struct1 } } -#[cfg(not(cfail1))] +#[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")] +#[rustc_clean(cfg="cfail6")] pub fn add_field_regular_struct() -> RegularStruct { let struct1 = RegularStruct { x: 3, @@ -101,7 +114,7 @@ pub fn add_field_regular_struct() -> RegularStruct { // Change field label (regular struct) -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn change_field_label_regular_struct() -> RegularStruct { let struct1 = RegularStruct { x: 3, @@ -116,9 +129,11 @@ pub fn change_field_label_regular_struct() -> RegularStruct { } } -#[cfg(not(cfail1))] +#[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")] +#[rustc_clean(cfg="cfail6")] pub fn change_field_label_regular_struct() -> RegularStruct { let struct1 = RegularStruct { x: 3, @@ -142,18 +157,20 @@ pub struct RegularStruct2 { } // Change constructor path (regular struct) -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn change_constructor_path_regular_struct() { - let _ = RegularStruct { + let _ = RegularStruct { x: 0, y: 1, z: 2, }; } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck")] +#[rustc_clean(cfg="cfail6")] pub fn change_constructor_path_regular_struct() { let _ = RegularStruct2 { x: 0, @@ -166,9 +183,9 @@ pub fn change_constructor_path_regular_struct() { // Change constructor path indirectly (regular struct) pub mod change_constructor_path_indirectly_regular_struct { - #[cfg(cfail1)] + #[cfg(any(cfail1,cfail4))] use super::RegularStruct as Struct; - #[cfg(not(cfail1))] + #[cfg(not(any(cfail1,cfail4)))] use super::RegularStruct2 as Struct; #[rustc_clean( @@ -176,6 +193,11 @@ pub mod change_constructor_path_indirectly_regular_struct { except="fn_sig,hir_owner,hir_owner_nodes,optimized_mir,typeck" )] #[rustc_clean(cfg="cfail3")] + #[rustc_clean( + cfg="cfail5", + except="fn_sig,hir_owner,hir_owner_nodes,optimized_mir,typeck" + )] + #[rustc_clean(cfg="cfail6")] pub fn function() -> Struct { Struct { x: 0, @@ -190,14 +212,16 @@ pub mod change_constructor_path_indirectly_regular_struct { pub struct TupleStruct(i32, i64, i16); // Change field value (tuple struct) -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn change_field_value_tuple_struct() -> TupleStruct { TupleStruct(0, 1, 2) } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail6")] pub fn change_field_value_tuple_struct() -> TupleStruct { TupleStruct(0, 1, 3) } @@ -207,14 +231,16 @@ pub fn change_field_value_tuple_struct() -> TupleStruct { pub struct TupleStruct2(u16, u16, u16); // Change constructor path (tuple struct) -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn change_constructor_path_tuple_struct() { - let _ = TupleStruct(0, 1, 2); + let _ = TupleStruct (0, 1, 2); } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck")] +#[rustc_clean(cfg="cfail6")] pub fn change_constructor_path_tuple_struct() { let _ = TupleStruct2(0, 1, 2); } @@ -223,11 +249,16 @@ pub fn change_constructor_path_tuple_struct() { // Change constructor path indirectly (tuple struct) pub mod change_constructor_path_indirectly_tuple_struct { - #[cfg(cfail1)] + #[cfg(any(cfail1,cfail4))] use super::TupleStruct as Struct; - #[cfg(not(cfail1))] + #[cfg(not(any(cfail1,cfail4)))] use super::TupleStruct2 as Struct; + #[rustc_clean( + cfg="cfail5", + except="fn_sig,hir_owner,hir_owner_nodes,optimized_mir,typeck" + )] + #[rustc_clean(cfg="cfail6")] #[rustc_clean( cfg="cfail2", except="fn_sig,hir_owner,hir_owner_nodes,optimized_mir,typeck" diff --git a/src/test/incremental/hashes/struct_defs.rs b/src/test/incremental/hashes/struct_defs.rs index 0ce5aeaaf5..b5d8a3ab34 100644 --- a/src/test/incremental/hashes/struct_defs.rs +++ b/src/test/incremental/hashes/struct_defs.rs @@ -11,42 +11,53 @@ // the same between rev2 and rev3. // build-pass (FIXME(62277): could be check-pass?) -// revisions: cfail1 cfail2 cfail3 -// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans - +// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6 +// compile-flags: -Z query-dep-graph +// [cfail1]compile-flags: -Zincremental-ignore-spans +// [cfail2]compile-flags: -Zincremental-ignore-spans +// [cfail3]compile-flags: -Zincremental-ignore-spans +// [cfail4]compile-flags: -Zincremental-relative-spans +// [cfail5]compile-flags: -Zincremental-relative-spans +// [cfail6]compile-flags: -Zincremental-relative-spans #![allow(warnings)] #![feature(rustc_attrs)] #![crate_type="rlib"] // Layout ---------------------------------------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub struct LayoutPacked; -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(except="type_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(except="type_of", cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] #[repr(packed)] pub struct LayoutPacked; -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] struct LayoutC; -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(except="type_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(except="type_of", cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] #[repr(C)] struct LayoutC; // Tuple Struct Change Field Type ---------------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] struct TupleStructFieldType(i32); -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] // Note that changing the type of a field does not change the type of the struct or enum, but // adding/removing fields or changing a fields name or visibility does. struct TupleStructFieldType( @@ -56,12 +67,14 @@ struct TupleStructFieldType( // Tuple Struct Add Field ------------------------------------------------------ -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] struct TupleStructAddField(i32); -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(except="hir_owner,hir_owner_nodes,type_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(except="hir_owner,hir_owner_nodes,type_of", cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] struct TupleStructAddField( i32, u32 @@ -70,23 +83,27 @@ struct TupleStructAddField( // Tuple Struct Field Visibility ----------------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] struct TupleStructFieldVisibility(char); -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(except="hir_owner,hir_owner_nodes,type_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(except="hir_owner,hir_owner_nodes,type_of", cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] struct TupleStructFieldVisibility(pub char); // Record Struct Field Type ---------------------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] struct RecordStructFieldType { x: f32 } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] // Note that changing the type of a field does not change the type of the struct or enum, but // adding/removing fields or changing a fields name or visibility does. struct RecordStructFieldType { @@ -96,23 +113,27 @@ struct RecordStructFieldType { // Record Struct Field Name ---------------------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] struct RecordStructFieldName { x: f32 } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(except="hir_owner,hir_owner_nodes,type_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(except="hir_owner,hir_owner_nodes,type_of", cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] struct RecordStructFieldName { y: f32 } // Record Struct Add Field ----------------------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] struct RecordStructAddField { x: f32 } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(except="hir_owner,hir_owner_nodes,type_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(except="hir_owner,hir_owner_nodes,type_of", cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] struct RecordStructAddField { x: f32, y: () } @@ -120,12 +141,14 @@ struct RecordStructAddField { // Record Struct Field Visibility ---------------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] struct RecordStructFieldVisibility { x: f32 } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(except="hir_owner,hir_owner_nodes,type_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(except="hir_owner,hir_owner_nodes,type_of", cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] struct RecordStructFieldVisibility { pub x: f32 } @@ -133,34 +156,40 @@ struct RecordStructFieldVisibility { // Add Lifetime Parameter ------------------------------------------------------ -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] struct AddLifetimeParameter<'a>(&'a f32, &'a f64); -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(except="hir_owner,hir_owner_nodes,type_of,generics_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(except="hir_owner,hir_owner_nodes,type_of,generics_of", cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] struct AddLifetimeParameter<'a, 'b>(&'a f32, &'b f64); // Add Lifetime Parameter Bound ------------------------------------------------ -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] struct AddLifetimeParameterBound<'a, 'b>(&'a f32, &'b f64); -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] struct AddLifetimeParameterBound<'a, 'b: 'a>( &'a f32, &'b f64 ); -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] struct AddLifetimeParameterBoundWhereClause<'a, 'b>(&'a f32, &'b f64); -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] struct AddLifetimeParameterBoundWhereClause<'a, 'b>( &'a f32, &'b f64) @@ -169,12 +198,14 @@ struct AddLifetimeParameterBoundWhereClause<'a, 'b>( // Add Type Parameter ---------------------------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] struct AddTypeParameter(T1, T1); -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(except="hir_owner,hir_owner_nodes,type_of,generics_of,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(except="hir_owner,hir_owner_nodes,type_of,generics_of,predicates_of", cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] struct AddTypeParameter( // The field contains the parent's Generics, so it's dirty even though its // type hasn't changed. @@ -185,23 +216,27 @@ struct AddTypeParameter( // Add Type Parameter Bound ---------------------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] struct AddTypeParameterBound(T); -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] struct AddTypeParameterBound( T ); -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] struct AddTypeParameterBoundWhereClause(T); -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] struct AddTypeParameterBoundWhereClause( T ) where T: Sync; @@ -214,17 +249,21 @@ struct AddTypeParameterBoundWhereClause( // Note: there is no #[cfg(...)], so this is ALWAYS compiled #[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] pub struct EmptyStruct; // Visibility ------------------------------------------------------------------ -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] struct Visibility; -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] pub struct Visibility; struct ReferencedType1; @@ -232,13 +271,15 @@ struct ReferencedType2; // Tuple Struct Change Field Type Indirectly ----------------------------------- mod tuple_struct_change_field_type_indirectly { - #[cfg(cfail1)] + #[cfg(any(cfail1,cfail4))] use super::ReferencedType1 as FieldType; - #[cfg(not(cfail1))] + #[cfg(not(any(cfail1,cfail4)))] use super::ReferencedType2 as FieldType; #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] + #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")] + #[rustc_clean(cfg="cfail6")] struct TupleStruct( FieldType ); @@ -247,13 +288,15 @@ mod tuple_struct_change_field_type_indirectly { // Record Struct Change Field Type Indirectly ----------------------------------- mod record_struct_change_field_type_indirectly { - #[cfg(cfail1)] + #[cfg(any(cfail1,cfail4))] use super::ReferencedType1 as FieldType; - #[cfg(not(cfail1))] + #[cfg(not(any(cfail1,cfail4)))] use super::ReferencedType2 as FieldType; #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] + #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")] + #[rustc_clean(cfg="cfail6")] struct RecordStruct { _x: FieldType } @@ -267,24 +310,28 @@ trait ReferencedTrait2 {} // Change Trait Bound Indirectly ----------------------------------------------- mod change_trait_bound_indirectly { - #[cfg(cfail1)] + #[cfg(any(cfail1,cfail4))] use super::ReferencedTrait1 as Trait; - #[cfg(not(cfail1))] + #[cfg(not(any(cfail1,cfail4)))] use super::ReferencedTrait2 as Trait; #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] + #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] + #[rustc_clean(cfg="cfail6")] struct Struct(T); } // Change Trait Bound Indirectly In Where Clause ------------------------------- mod change_trait_bound_indirectly_in_where_clause { - #[cfg(cfail1)] + #[cfg(any(cfail1,cfail4))] use super::ReferencedTrait1 as Trait; - #[cfg(not(cfail1))] + #[cfg(not(any(cfail1,cfail4)))] use super::ReferencedTrait2 as Trait; #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] + #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] + #[rustc_clean(cfg="cfail6")] struct Struct(T) where T : Trait; } diff --git a/src/test/incremental/hashes/trait_defs.rs b/src/test/incremental/hashes/trait_defs.rs index a604ca5ca8..9cbd110d68 100644 --- a/src/test/incremental/hashes/trait_defs.rs +++ b/src/test/incremental/hashes/trait_defs.rs @@ -11,8 +11,14 @@ // the same between rev2 and rev3. // build-pass (FIXME(62277): could be check-pass?) -// revisions: cfail1 cfail2 cfail3 -// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans +// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6 +// compile-flags: -Z query-dep-graph +// [cfail1]compile-flags: -Zincremental-ignore-spans +// [cfail2]compile-flags: -Zincremental-ignore-spans +// [cfail3]compile-flags: -Zincremental-ignore-spans +// [cfail4]compile-flags: -Zincremental-relative-spans +// [cfail5]compile-flags: -Zincremental-relative-spans +// [cfail6]compile-flags: -Zincremental-relative-spans #![allow(warnings)] #![feature(rustc_attrs)] @@ -21,35 +27,41 @@ // Change trait visibility -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] trait TraitVisibility { } -#[cfg(not(cfail1))] +#[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(cfg="cfail6")] pub trait TraitVisibility { } // Change trait unsafety -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] trait TraitUnsafety { } -#[cfg(not(cfail1))] +#[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(cfg="cfail6")] unsafe trait TraitUnsafety { } // Add method -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] trait TraitAddMethod { } -#[cfg(not(cfail1))] +#[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(cfg="cfail6")] pub trait TraitAddMethod { fn method(); } @@ -57,14 +69,16 @@ pub trait TraitAddMethod { // Change name of method -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] trait TraitChangeMethodName { fn method(); } -#[cfg(not(cfail1))] +#[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", cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] trait TraitChangeMethodName { fn methodChanged(); } @@ -72,157 +86,227 @@ trait TraitChangeMethodName { // Add return type to method -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] trait TraitAddReturnType { - fn method(); + //----------------------------------------------------- + //-------------------------- + //----------------------------------------------------- + //-------------------------- + fn method() ; } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] trait TraitAddReturnType { #[rustc_clean(except="hir_owner,fn_sig", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] + #[rustc_clean(except="hir_owner,fn_sig", cfg="cfail5")] + #[rustc_clean(cfg="cfail6")] fn method() -> u32; } // Change return type of method -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] trait TraitChangeReturnType { + // -------------------------------------------------------------------- + // ------------------------- + // -------------------------------------------------------------------- + // ------------------------- fn method() -> u32; } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] trait TraitChangeReturnType { #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] + #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig", cfg="cfail5")] + #[rustc_clean(cfg="cfail6")] fn method() -> u64; } // Add parameter to method -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] trait TraitAddParameterToMethod { - fn method(); + // ---------------------------------------------------- + // ------------------------- + // ---------------------------------------------------- + // ------------------------- + fn method( ); } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] trait TraitAddParameterToMethod { #[rustc_clean(except="hir_owner,fn_sig", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] + #[rustc_clean(except="hir_owner,fn_sig", cfg="cfail5")] + #[rustc_clean(cfg="cfail6")] fn method(a: u32); } // Change name of method parameter -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] trait TraitChangeMethodParameterName { + //------------------------------------------------------ + //---------------------------------------------- + //-------------------------- + //---------------------------------------------- + //-------------------------- fn method(a: u32); + + //------------------------------------------------------------------ + //-------------------------- + //------------------------------------------------------------------ + //-------------------------- fn with_default(x: i32) {} } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] trait TraitChangeMethodParameterName { // FIXME(#38501) This should preferably always be clean. #[rustc_clean(except="hir_owner", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] + #[rustc_clean(except="hir_owner", cfg="cfail5")] + #[rustc_clean(cfg="cfail6")] fn method(b: u32); #[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] + #[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")] + #[rustc_clean(cfg="cfail6")] fn with_default(y: i32) {} } // Change type of method parameter (i32 => i64) -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] trait TraitChangeMethodParameterType { + // ---------------------------------------------------- + // ------------------------- + // ---------------------------------------------------- + // ------------------------- fn method(a: i32); } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] trait TraitChangeMethodParameterType { #[rustc_clean(except="hir_owner,fn_sig", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] + #[rustc_clean(except="hir_owner,fn_sig", cfg="cfail5")] + #[rustc_clean(cfg="cfail6")] fn method(a: i64); } // Change type of method parameter (&i32 => &mut i32) -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] trait TraitChangeMethodParameterTypeRef { - fn method(a: &i32); + // ---------------------------------------------------- + // ------------------------- + // ---------------------------------------------------- + // ------------------------- + fn method(a: & i32); } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] trait TraitChangeMethodParameterTypeRef { #[rustc_clean(except="hir_owner,fn_sig", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] + #[rustc_clean(except="hir_owner,fn_sig", cfg="cfail5")] + #[rustc_clean(cfg="cfail6")] fn method(a: &mut i32); } // Change order of method parameters -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] trait TraitChangeMethodParametersOrder { + // ---------------------------------------------------- + // ------------------------- + // ---------------------------------------------------- + // ------------------------- fn method(a: i32, b: i64); } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] trait TraitChangeMethodParametersOrder { #[rustc_clean(except="hir_owner,fn_sig", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] + #[rustc_clean(except="hir_owner,fn_sig", cfg="cfail5")] + #[rustc_clean(cfg="cfail6")] fn method(b: i64, a: i32); } // Add default implementation to method -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] trait TraitAddMethodAutoImplementation { fn method(); } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(except="hir_owner", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(except="hir_owner", cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] trait TraitAddMethodAutoImplementation { #[rustc_clean(except="hir_owner,associated_item", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] + #[rustc_clean(except="hir_owner,associated_item", cfg="cfail5")] + #[rustc_clean(cfg="cfail6")] fn method() { } } // Change order of methods -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] trait TraitChangeOrderOfMethods { fn method0(); fn method1(); } -#[cfg(not(cfail1))] +#[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", cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] trait TraitChangeOrderOfMethods { fn method1(); fn method0(); @@ -231,134 +315,198 @@ trait TraitChangeOrderOfMethods { // Change mode of self parameter -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] trait TraitChangeModeSelfRefToMut { - fn method(&self); + // ---------------------------------------------------- + // ------------------------- + // ---------------------------------------------------- + // ------------------------- + fn method(& self); } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] trait TraitChangeModeSelfRefToMut { #[rustc_clean(except="hir_owner,fn_sig", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] + #[rustc_clean(except="hir_owner,fn_sig", cfg="cfail5")] + #[rustc_clean(cfg="cfail6")] fn method(&mut self); } -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] trait TraitChangeModeSelfOwnToMut: Sized { - fn method(self) {} + // ---------------------------------------------------------------------------------- + // ------------------------- + // ---------------------------------------------------------------------------------- + // ------------------------- + fn method( self) {} } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] trait TraitChangeModeSelfOwnToMut: Sized { #[rustc_clean(except="hir_owner,hir_owner_nodes,typeck,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] + #[rustc_clean(except="hir_owner,hir_owner_nodes,typeck,optimized_mir", cfg="cfail5")] + #[rustc_clean(cfg="cfail6")] fn method(mut self) {} } -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] trait TraitChangeModeSelfOwnToRef { - fn method(self); + // ---------------------------------------------------------------- + // ------------------------- + // ---------------------------------------------------------------- + // ------------------------- + fn method( self); } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] trait TraitChangeModeSelfOwnToRef { #[rustc_clean(except="hir_owner,fn_sig,generics_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] + #[rustc_clean(except="hir_owner,fn_sig,generics_of", cfg="cfail5")] + #[rustc_clean(cfg="cfail6")] fn method(&self); } // Add unsafe modifier to method -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] trait TraitAddUnsafeModifier { - fn method(); + // ---------------------------------------------------- + // ------------------------- + // ---------------------------------------------------- + // ------------------------- + fn method() ; } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] trait TraitAddUnsafeModifier { #[rustc_clean(except="hir_owner,fn_sig", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] + #[rustc_clean(except="hir_owner,fn_sig", cfg="cfail5")] + #[rustc_clean(cfg="cfail6")] unsafe fn method(); } // Add extern modifier to method -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] trait TraitAddExternModifier { - fn method(); + // ---------------------------------------------------- + // ------------------------- + // ---------------------------------------------------- + // ------------------------- + fn method() ; } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] trait TraitAddExternModifier { #[rustc_clean(except="hir_owner,fn_sig", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] + #[rustc_clean(except="hir_owner,fn_sig", cfg="cfail5")] + #[rustc_clean(cfg="cfail6")] extern "C" fn method(); } // Change extern "C" to extern "stdcall" -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] trait TraitChangeExternCToRustIntrinsic { - extern "C" fn method(); + // ---------------------------------------------------- + // ------------------------- + // ---------------------------------------------------- + // ------------------------- + extern "C" fn method(); } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] trait TraitChangeExternCToRustIntrinsic { #[rustc_clean(except="hir_owner,fn_sig", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] + #[rustc_clean(except="hir_owner,fn_sig", cfg="cfail5")] + #[rustc_clean(cfg="cfail6")] extern "stdcall" fn method(); } // Add type parameter to method -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] trait TraitAddTypeParameterToMethod { - fn method(); + // ------------------------------------------------------------------------------- + // ------------------------- + // ------------------------------------------------------------------------------- + // ------------------------- + fn method (); } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] trait TraitAddTypeParameterToMethod { #[rustc_clean(except="hir_owner,generics_of,predicates_of,type_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] + #[rustc_clean(except="hir_owner,generics_of,predicates_of,type_of", cfg="cfail5")] + #[rustc_clean(cfg="cfail6")] fn method(); } // Add lifetime parameter to method -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] trait TraitAddLifetimeParameterToMethod { - fn method(); + // ---------------------------------------------------------------- + // ------------------------- + // ---------------------------------------------------------------- + // ------------------------- + fn method (); } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] trait TraitAddLifetimeParameterToMethod { #[rustc_clean(except="hir_owner,fn_sig,generics_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] + #[rustc_clean(except="hir_owner,fn_sig,generics_of", cfg="cfail5")] + #[rustc_clean(cfg="cfail6")] fn method<'a>(); } @@ -369,137 +517,220 @@ trait ReferencedTrait0 { } trait ReferencedTrait1 { } // Add trait bound to method type parameter -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] trait TraitAddTraitBoundToMethodTypeParameter { - fn method(); + // --------------------------------------------------------------------------- + // ------------------------- + // --------------------------------------------------------------------------- + // ------------------------- + fn method(); } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] trait TraitAddTraitBoundToMethodTypeParameter { #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] + #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] + #[rustc_clean(cfg="cfail6")] fn method(); } // Add builtin bound to method type parameter -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] trait TraitAddBuiltinBoundToMethodTypeParameter { - fn method(); + // --------------------------------------------------------------------------- + // ------------------------- + // --------------------------------------------------------------------------- + // ------------------------- + fn method(); } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] trait TraitAddBuiltinBoundToMethodTypeParameter { #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] + #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] + #[rustc_clean(cfg="cfail6")] fn method(); } // Add lifetime bound to method lifetime parameter -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] trait TraitAddLifetimeBoundToMethodLifetimeParameter { - fn method<'a, 'b>(a: &'a u32, b: &'b u32); + // ----------- + // ----------------------------------------------------------------------------- + // -------------- + // + // ------------------------- + // ----------- + // ----------------------------------------------------------------------------- + // -------------- + // + // ------------------------- + fn method<'a, 'b >(a: &'a u32, b: &'b u32); } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] trait TraitAddLifetimeBoundToMethodLifetimeParameter { #[rustc_clean( except="hir_owner,hir_owner_nodes,generics_of,predicates_of,fn_sig,type_of", cfg="cfail2", )] #[rustc_clean(cfg="cfail3")] + #[rustc_clean( + except="hir_owner,hir_owner_nodes,generics_of,predicates_of,fn_sig,type_of", + cfg="cfail5", + )] + #[rustc_clean(cfg="cfail6")] fn method<'a, 'b: 'a>(a: &'a u32, b: &'b u32); } // Add second trait bound to method type parameter -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] trait TraitAddSecondTraitBoundToMethodTypeParameter { - fn method(); + // --------------------------------------------------------------------------- + // ------------------------- + // --------------------------------------------------------------------------- + // ------------------------- + fn method(); } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] trait TraitAddSecondTraitBoundToMethodTypeParameter { #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] + #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] + #[rustc_clean(cfg="cfail6")] fn method(); } // Add second builtin bound to method type parameter -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] trait TraitAddSecondBuiltinBoundToMethodTypeParameter { - fn method(); + // --------------------------------------------------------------------------- + // ------------------------- + // --------------------------------------------------------------------------- + // ------------------------- + fn method(); } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] trait TraitAddSecondBuiltinBoundToMethodTypeParameter { #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] + #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] + #[rustc_clean(cfg="cfail6")] fn method(); } // Add second lifetime bound to method lifetime parameter -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] trait TraitAddSecondLifetimeBoundToMethodLifetimeParameter { - fn method<'a, 'b, 'c: 'a>(a: &'a u32, b: &'b u32, c: &'c u32); + // ----------- + // ----------------------------------------------------------------------------- + // -------------- + // + // ------------------------- + // ----------- + // ----------------------------------------------------------------------------- + // -------------- + // + // ------------------------- + fn method<'a, 'b, 'c: 'a >(a: &'a u32, b: &'b u32, c: &'c u32); } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] trait TraitAddSecondLifetimeBoundToMethodLifetimeParameter { #[rustc_clean( except="hir_owner,hir_owner_nodes,generics_of,predicates_of,fn_sig,type_of", cfg="cfail2", )] #[rustc_clean(cfg="cfail3")] + #[rustc_clean( + except="hir_owner,hir_owner_nodes,generics_of,predicates_of,fn_sig,type_of", + cfg="cfail5", + )] + #[rustc_clean(cfg="cfail6")] fn method<'a, 'b, 'c: 'a + 'b>(a: &'a u32, b: &'b u32, c: &'c u32); } // Add associated type -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] trait TraitAddAssociatedType { + //-------------------------- + //-------------------------- + // ------------- - #[rustc_clean(except="hir_owner", cfg="cfail2")] - #[rustc_clean(cfg="cfail3")] + //-------------------------- + //-------------------------- + //-------------------------- + //-------------------------- fn method(); } -#[cfg(not(cfail1))] +#[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", cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] trait TraitAddAssociatedType { + #[rustc_clean(cfg="cfail3")] + #[rustc_clean(cfg="cfail6")] type Associated; + #[rustc_clean(cfg="cfail2")] + #[rustc_clean(cfg="cfail3")] + #[rustc_clean(cfg="cfail5")] + #[rustc_clean(cfg="cfail6")] fn method(); } // Add trait bound to associated type -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] trait TraitAddTraitBoundToAssociatedType { - type Associated; + // --------------------------------------------- + // ------------------------- + // --------------------------------------------- + // ------------------------- + type Associated ; fn method(); } @@ -507,12 +738,16 @@ trait TraitAddTraitBoundToAssociatedType { // Apparently the type bound contributes to the predicates of the trait, but // does not change the associated item itself. -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] trait TraitAddTraitBoundToAssociatedType { #[rustc_clean(except="hir_owner", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] + #[rustc_clean(except="hir_owner", cfg="cfail5")] + #[rustc_clean(cfg="cfail6")] type Associated: ReferencedTrait0; fn method(); @@ -521,19 +756,27 @@ trait TraitAddTraitBoundToAssociatedType { // Add lifetime bound to associated type -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] trait TraitAddLifetimeBoundToAssociatedType<'a> { - type Associated; + // --------------------------------------------- + // ------------------------- + // --------------------------------------------- + // ------------------------- + type Associated ; fn method(); } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] trait TraitAddLifetimeBoundToAssociatedType<'a> { #[rustc_clean(except="hir_owner", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] + #[rustc_clean(except="hir_owner", cfg="cfail5")] + #[rustc_clean(cfg="cfail6")] type Associated: 'a; fn method(); @@ -542,19 +785,23 @@ trait TraitAddLifetimeBoundToAssociatedType<'a> { // Add default to associated type -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] trait TraitAddDefaultToAssociatedType { type Associated; fn method(); } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(except="hir_owner", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(except="hir_owner", cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] trait TraitAddDefaultToAssociatedType { #[rustc_clean(except="hir_owner,associated_item", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] + #[rustc_clean(except="hir_owner,associated_item", cfg="cfail5")] + #[rustc_clean(cfg="cfail6")] type Associated = ReferenceType0; fn method(); @@ -563,14 +810,16 @@ trait TraitAddDefaultToAssociatedType { // Add associated constant -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] trait TraitAddAssociatedConstant { fn method(); } -#[cfg(not(cfail1))] +#[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", cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] trait TraitAddAssociatedConstant { const Value: u32; @@ -580,269 +829,331 @@ trait TraitAddAssociatedConstant { // Add initializer to associated constant -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] trait TraitAddInitializerToAssociatedConstant { const Value: u32; fn method(); } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(except="hir_owner", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(except="hir_owner", cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] trait TraitAddInitializerToAssociatedConstant { #[rustc_clean(except="hir_owner,associated_item", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] + #[rustc_clean(except="hir_owner,associated_item", cfg="cfail5")] + #[rustc_clean(cfg="cfail6")] const Value: u32 = 1; #[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] + #[rustc_clean(cfg="cfail5")] + #[rustc_clean(cfg="cfail6")] fn method(); } // Change type of associated constant -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] trait TraitChangeTypeOfAssociatedConstant { + // ----------------------------------------------------- + // ------------------------- + // ----------------------------------------------------- + // ------------------------- const Value: u32; + // ------------------------- + // ------------------------- + // ------------------------- + // ------------------------- fn method(); } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] trait TraitChangeTypeOfAssociatedConstant { #[rustc_clean(except="hir_owner,type_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] + #[rustc_clean(except="hir_owner,type_of", cfg="cfail5")] + #[rustc_clean(cfg="cfail6")] const Value: f64; #[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] + #[rustc_clean(cfg="cfail5")] + #[rustc_clean(cfg="cfail6")] fn method(); } // Add super trait -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] trait TraitAddSuperTrait { } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(except="hir_owner,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(except="hir_owner,predicates_of", cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] trait TraitAddSuperTrait : ReferencedTrait0 { } // Add builtin bound (Send or Copy) -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] trait TraitAddBuiltiBound { } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(except="hir_owner,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(except="hir_owner,predicates_of", cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] trait TraitAddBuiltiBound : Send { } // Add 'static lifetime bound to trait -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] trait TraitAddStaticLifetimeBound { } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(except="hir_owner,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(except="hir_owner,predicates_of", cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] trait TraitAddStaticLifetimeBound : 'static { } // Add super trait as second bound -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] trait TraitAddTraitAsSecondBound : ReferencedTrait0 { } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(except="hir_owner,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(except="hir_owner,predicates_of", cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] trait TraitAddTraitAsSecondBound : ReferencedTrait0 + ReferencedTrait1 { } -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] trait TraitAddTraitAsSecondBoundFromBuiltin : Send { } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(except="hir_owner,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(except="hir_owner,predicates_of", cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] trait TraitAddTraitAsSecondBoundFromBuiltin : Send + ReferencedTrait0 { } // Add builtin bound as second bound -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] trait TraitAddBuiltinBoundAsSecondBound : ReferencedTrait0 { } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(except="hir_owner,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(except="hir_owner,predicates_of", cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] trait TraitAddBuiltinBoundAsSecondBound : ReferencedTrait0 + Send { } -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] trait TraitAddBuiltinBoundAsSecondBoundFromBuiltin : Send { } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(except="hir_owner,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(except="hir_owner,predicates_of", cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] trait TraitAddBuiltinBoundAsSecondBoundFromBuiltin: Send + Copy { } // Add 'static bounds as second bound -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] trait TraitAddStaticBoundAsSecondBound : ReferencedTrait0 { } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(except="hir_owner,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(except="hir_owner,predicates_of", cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] trait TraitAddStaticBoundAsSecondBound : ReferencedTrait0 + 'static { } -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] trait TraitAddStaticBoundAsSecondBoundFromBuiltin : Send { } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(except="hir_owner,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(except="hir_owner,predicates_of", cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] trait TraitAddStaticBoundAsSecondBoundFromBuiltin : Send + 'static { } // Add type parameter to trait -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] trait TraitAddTypeParameterToTrait { } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(except="hir_owner,generics_of,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(except="hir_owner,generics_of,predicates_of", cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] trait TraitAddTypeParameterToTrait { } // Add lifetime parameter to trait -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] trait TraitAddLifetimeParameterToTrait { } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(except="hir_owner,generics_of,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(except="hir_owner,generics_of,predicates_of", cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] trait TraitAddLifetimeParameterToTrait<'a> { } // Add trait bound to type parameter of trait -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] trait TraitAddTraitBoundToTypeParameterOfTrait { } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] trait TraitAddTraitBoundToTypeParameterOfTrait { } // Add lifetime bound to type parameter of trait -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] trait TraitAddLifetimeBoundToTypeParameterOfTrait<'a, T> { } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,predicates_of", cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] trait TraitAddLifetimeBoundToTypeParameterOfTrait<'a, T: 'a> { } // Add lifetime bound to lifetime parameter of trait -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] trait TraitAddLifetimeBoundToLifetimeParameterOfTrait<'a, 'b> { } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] trait TraitAddLifetimeBoundToLifetimeParameterOfTrait<'a: 'b, 'b> { } // Add builtin bound to type parameter of trait -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] trait TraitAddBuiltinBoundToTypeParameterOfTrait { } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] trait TraitAddBuiltinBoundToTypeParameterOfTrait { } // Add second type parameter to trait -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] trait TraitAddSecondTypeParameterToTrait { } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,predicates_of", cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] trait TraitAddSecondTypeParameterToTrait { } // Add second lifetime parameter to trait -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] trait TraitAddSecondLifetimeParameterToTrait<'a> { } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,predicates_of", cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] trait TraitAddSecondLifetimeParameterToTrait<'a, 'b> { } // Add second trait bound to type parameter of trait -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] trait TraitAddSecondTraitBoundToTypeParameterOfTrait { } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] trait TraitAddSecondTraitBoundToTypeParameterOfTrait { } // Add second lifetime bound to type parameter of trait -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] trait TraitAddSecondLifetimeBoundToTypeParameterOfTrait<'a, 'b, T: 'a> { } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,predicates_of", cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] trait TraitAddSecondLifetimeBoundToTypeParameterOfTrait<'a, 'b, T: 'a + 'b> { } // Add second lifetime bound to lifetime parameter of trait -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] trait TraitAddSecondLifetimeBoundToLifetimeParameterOfTrait<'a: 'b, 'b, 'c> { } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] trait TraitAddSecondLifetimeBoundToLifetimeParameterOfTrait<'a: 'b + 'c, 'b, 'c> { } // Add second builtin bound to type parameter of trait -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] trait TraitAddSecondBuiltinBoundToTypeParameterOfTrait { } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] trait TraitAddSecondBuiltinBoundToTypeParameterOfTrait { } @@ -853,105 +1164,125 @@ struct ReferenceType1 {} // Add trait bound to type parameter of trait in where clause -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] trait TraitAddTraitBoundToTypeParameterOfTraitWhere { } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] trait TraitAddTraitBoundToTypeParameterOfTraitWhere where T: ReferencedTrait0 { } // Add lifetime bound to type parameter of trait in where clause -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] trait TraitAddLifetimeBoundToTypeParameterOfTraitWhere<'a, T> { } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,predicates_of", cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] trait TraitAddLifetimeBoundToTypeParameterOfTraitWhere<'a, T> where T: 'a { } // Add lifetime bound to lifetime parameter of trait in where clause -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] trait TraitAddLifetimeBoundToLifetimeParameterOfTraitWhere<'a, 'b> { } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] trait TraitAddLifetimeBoundToLifetimeParameterOfTraitWhere<'a, 'b> where 'a: 'b { } // Add builtin bound to type parameter of trait in where clause -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] trait TraitAddBuiltinBoundToTypeParameterOfTraitWhere { } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] trait TraitAddBuiltinBoundToTypeParameterOfTraitWhere where T: Send { } // Add second trait bound to type parameter of trait in where clause -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] trait TraitAddSecondTraitBoundToTypeParameterOfTraitWhere where T: ReferencedTrait0 { } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] trait TraitAddSecondTraitBoundToTypeParameterOfTraitWhere where T: ReferencedTrait0 + ReferencedTrait1 { } // Add second lifetime bound to type parameter of trait in where clause -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] trait TraitAddSecondLifetimeBoundToTypeParameterOfTraitWhere<'a, 'b, T> where T: 'a { } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,predicates_of", cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] trait TraitAddSecondLifetimeBoundToTypeParameterOfTraitWhere<'a, 'b, T> where T: 'a + 'b { } // Add second lifetime bound to lifetime parameter of trait in where clause -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] trait TraitAddSecondLifetimeBoundToLifetimeParameterOfTraitWhere<'a, 'b, 'c> where 'a: 'b { } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] trait TraitAddSecondLifetimeBoundToLifetimeParameterOfTraitWhere<'a, 'b, 'c> where 'a: 'b + 'c { } // Add second builtin bound to type parameter of trait in where clause -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] trait TraitAddSecondBuiltinBoundToTypeParameterOfTraitWhere where T: Send { } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] trait TraitAddSecondBuiltinBoundToTypeParameterOfTraitWhere where T: Send + Sync { } // Change return type of method indirectly by modifying a use statement mod change_return_type_of_method_indirectly_use { - #[cfg(cfail1)] + #[cfg(any(cfail1,cfail4))] use super::ReferenceType0 as ReturnType; - #[cfg(not(cfail1))] + #[cfg(not(any(cfail1,cfail4)))] use super::ReferenceType1 as ReturnType; #[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] + #[rustc_clean(cfg="cfail5")] + #[rustc_clean(cfg="cfail6")] trait TraitChangeReturnType { #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] + #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig", cfg="cfail5")] + #[rustc_clean(cfg="cfail6")] fn method() -> ReturnType; } } @@ -960,9 +1291,9 @@ mod change_return_type_of_method_indirectly_use { // Change type of method parameter indirectly by modifying a use statement mod change_method_parameter_type_indirectly_by_use { - #[cfg(cfail1)] + #[cfg(any(cfail1,cfail4))] use super::ReferenceType0 as ArgType; - #[cfg(not(cfail1))] + #[cfg(not(any(cfail1,cfail4)))] use super::ReferenceType1 as ArgType; #[rustc_clean(cfg="cfail2")] @@ -978,9 +1309,9 @@ mod change_method_parameter_type_indirectly_by_use { // Change trait bound of method type parameter indirectly by modifying a use statement mod change_method_parameter_type_bound_indirectly_by_use { - #[cfg(cfail1)] + #[cfg(any(cfail1,cfail4))] use super::ReferencedTrait0 as Bound; - #[cfg(not(cfail1))] + #[cfg(not(any(cfail1,cfail4)))] use super::ReferencedTrait1 as Bound; #[rustc_clean(cfg="cfail2")] @@ -997,16 +1328,20 @@ mod change_method_parameter_type_bound_indirectly_by_use { // Change trait bound of method type parameter in where clause indirectly // by modifying a use statement mod change_method_parameter_type_bound_indirectly_by_use_where { - #[cfg(cfail1)] + #[cfg(any(cfail1,cfail4))] use super::ReferencedTrait0 as Bound; - #[cfg(not(cfail1))] + #[cfg(not(any(cfail1,cfail4)))] use super::ReferencedTrait1 as Bound; #[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] + #[rustc_clean(cfg="cfail5")] + #[rustc_clean(cfg="cfail6")] trait TraitChangeBoundOfMethodTypeParameterWhere { #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] + #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] + #[rustc_clean(cfg="cfail6")] fn method(a: T) where T: Bound; } } @@ -1015,9 +1350,9 @@ mod change_method_parameter_type_bound_indirectly_by_use_where { // Change trait bound of trait type parameter indirectly by modifying a use statement mod change_method_type_parameter_bound_indirectly { - #[cfg(cfail1)] + #[cfg(any(cfail1,cfail4))] use super::ReferencedTrait0 as Bound; - #[cfg(not(cfail1))] + #[cfg(not(any(cfail1,cfail4)))] use super::ReferencedTrait1 as Bound; #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] @@ -1032,13 +1367,15 @@ mod change_method_type_parameter_bound_indirectly { // Change trait bound of trait type parameter in where clause indirectly // by modifying a use statement mod change_method_type_parameter_bound_indirectly_where { - #[cfg(cfail1)] + #[cfg(any(cfail1,cfail4))] use super::ReferencedTrait0 as Bound; - #[cfg(not(cfail1))] + #[cfg(not(any(cfail1,cfail4)))] use super::ReferencedTrait1 as Bound; #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] + #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] + #[rustc_clean(cfg="cfail6")] trait TraitChangeTraitBoundWhere where T: Bound { fn method(a: T); } diff --git a/src/test/incremental/hashes/trait_impls.rs b/src/test/incremental/hashes/trait_impls.rs index 2d547f1748..d623810115 100644 --- a/src/test/incremental/hashes/trait_impls.rs +++ b/src/test/incremental/hashes/trait_impls.rs @@ -6,9 +6,14 @@ // rev3 and make sure that the hash has not changed. // build-pass (FIXME(62277): could be check-pass?) -// revisions: cfail1 cfail2 cfail3 -// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans - +// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6 +// compile-flags: -Z query-dep-graph +// [cfail1]compile-flags: -Zincremental-ignore-spans +// [cfail2]compile-flags: -Zincremental-ignore-spans +// [cfail3]compile-flags: -Zincremental-ignore-spans +// [cfail4]compile-flags: -Zincremental-relative-spans +// [cfail5]compile-flags: -Zincremental-relative-spans +// [cfail6]compile-flags: -Zincremental-relative-spans #![allow(warnings)] #![feature(rustc_attrs)] @@ -19,29 +24,35 @@ struct Foo; // Change Method Name ----------------------------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub trait ChangeMethodNameTrait { fn method_name(); } -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] impl ChangeMethodNameTrait for Foo { fn method_name() { } } -#[cfg(not(cfail1))] +#[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", cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] pub trait ChangeMethodNameTrait { #[rustc_clean(cfg="cfail3")] + #[rustc_clean(cfg="cfail6")] fn method_name2(); } -#[cfg(not(cfail1))] +#[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", cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] impl ChangeMethodNameTrait for Foo { #[rustc_clean(cfg="cfail3")] + #[rustc_clean(cfg="cfail6")] fn method_name2() { } } @@ -53,17 +64,27 @@ pub trait ChangeMethodBodyTrait { fn method_name(); } -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] impl ChangeMethodBodyTrait for Foo { - fn method_name() { } + // ---------------------------------------------------------- + // ------------------------- + // ---------------------------------------------------------- + // ------------------------- + fn method_name() { + // + } } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] impl ChangeMethodBodyTrait for Foo { #[rustc_clean(except="hir_owner_nodes,typeck", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] + #[rustc_clean(except="hir_owner_nodes,typeck", cfg="cfail5")] + #[rustc_clean(cfg="cfail6")] fn method_name() { () } @@ -77,18 +98,28 @@ pub trait ChangeMethodBodyTraitInlined { fn method_name(); } -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] impl ChangeMethodBodyTraitInlined for Foo { + // ------------------------------------------------------------------------ + // ------------------------- + // ------------------------------------------------------------------------ + // ------------------------- #[inline] - fn method_name() { } + fn method_name() { + // ----- + } } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] impl ChangeMethodBodyTraitInlined for Foo { #[rustc_clean(except="hir_owner_nodes,typeck,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] + #[rustc_clean(except="hir_owner_nodes,typeck,optimized_mir", cfg="cfail5")] + #[rustc_clean(cfg="cfail6")] #[inline] fn method_name() { panic!() @@ -97,30 +128,37 @@ impl ChangeMethodBodyTraitInlined for Foo { // Change Method Selfness ------------------------------------------------------ -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub trait ChangeMethodSelfnessTrait { fn method_name(); } -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] impl ChangeMethodSelfnessTrait for Foo { fn method_name() { } } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] pub trait ChangeMethodSelfnessTrait { fn method_name(&self); } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(except="hir_owner", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(except="hir_owner", cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] impl ChangeMethodSelfnessTrait for Foo { #[rustc_clean( except="hir_owner,hir_owner_nodes,associated_item,generics_of,fn_sig,typeck,optimized_mir", cfg="cfail2", )] #[rustc_clean(cfg="cfail3")] + #[rustc_clean( + except="hir_owner,hir_owner_nodes,associated_item,generics_of,fn_sig,typeck,optimized_mir", + cfg="cfail5", + )] + #[rustc_clean(cfg="cfail6")] fn method_name(&self) { () } @@ -128,130 +166,151 @@ impl ChangeMethodSelfnessTrait for Foo { // Change Method Selfness ----------------------------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub trait RemoveMethodSelfnessTrait { fn method_name(&self); } -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] impl RemoveMethodSelfnessTrait for Foo { fn method_name(&self) { } } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] pub trait RemoveMethodSelfnessTrait { fn method_name(); } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(except="hir_owner", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(except="hir_owner", cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] impl RemoveMethodSelfnessTrait for Foo { #[rustc_clean( except="hir_owner,hir_owner_nodes,associated_item,generics_of,fn_sig,typeck,optimized_mir", cfg="cfail2", )] #[rustc_clean(cfg="cfail3")] + #[rustc_clean( + except="hir_owner,hir_owner_nodes,associated_item,generics_of,fn_sig,typeck,optimized_mir", + cfg="cfail5", + )] + #[rustc_clean(cfg="cfail6")] fn method_name() {} } // Change Method Selfmutness ----------------------------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub trait ChangeMethodSelfmutnessTrait { fn method_name(&self); } -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] impl ChangeMethodSelfmutnessTrait for Foo { - fn method_name(&self) { } + // ----------------------------------------------------------------------------------------- + // ------------------------- + // ----------------------------------------------------------------------------------------- + // ------------------------- + fn method_name(& self) {} } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] pub trait ChangeMethodSelfmutnessTrait { fn method_name(&mut self); } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] impl ChangeMethodSelfmutnessTrait for Foo { #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig,typeck,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] + #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig,typeck,optimized_mir", cfg="cfail5")] + #[rustc_clean(cfg="cfail6")] fn method_name(&mut self) {} } // Change item kind ----------------------------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub trait ChangeItemKindTrait { fn name(); } -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] impl ChangeItemKindTrait for Foo { fn name() { } } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] pub trait ChangeItemKindTrait { type name; } -#[cfg(not(cfail1))] +#[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", cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] impl ChangeItemKindTrait for Foo { type name = (); } // Remove item ----------------------------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub trait RemoveItemTrait { type TypeName; fn method_name(); } -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] impl RemoveItemTrait for Foo { type TypeName = (); fn method_name() { } } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] pub trait RemoveItemTrait { type TypeName; } -#[cfg(not(cfail1))] +#[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", cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] impl RemoveItemTrait for Foo { type TypeName = (); } // Add item ----------------------------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub trait AddItemTrait { type TypeName; } -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] impl AddItemTrait for Foo { type TypeName = (); } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] pub trait AddItemTrait { type TypeName; fn method_name(); } -#[cfg(not(cfail1))] +#[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", cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] impl AddItemTrait for Foo { type TypeName = (); fn method_name() { } @@ -259,28 +318,34 @@ impl AddItemTrait for Foo { // Change has-value ----------------------------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub trait ChangeHasValueTrait { fn method_name(); } -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] impl ChangeHasValueTrait for Foo { fn method_name() { } } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(except="hir_owner", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(except="hir_owner", cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] pub trait ChangeHasValueTrait { #[rustc_clean(except="hir_owner,associated_item", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] + #[rustc_clean(except="hir_owner,associated_item", cfg="cfail5")] + #[rustc_clean(cfg="cfail6")] fn method_name() { } } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] impl ChangeHasValueTrait for Foo { fn method_name() { } } @@ -291,69 +356,91 @@ pub trait AddDefaultTrait { fn method_name(); } -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] impl AddDefaultTrait for Foo { - fn method_name() { } + // ------------------------------------------------------------------------------------------- + // ------------------------- + fn method_name() { } } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(except="hir_owner", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(except="hir_owner", cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] impl AddDefaultTrait for Foo { #[rustc_clean(except="hir_owner,hir_owner_nodes,associated_item", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] + #[rustc_clean(except="hir_owner,hir_owner_nodes,associated_item,optimized_mir", cfg="cfail5")] + #[rustc_clean(cfg="cfail6")] default fn method_name() { } } // Add arguments -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub trait AddArgumentTrait { fn method_name(&self); } -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] impl AddArgumentTrait for Foo { - fn method_name(&self) { } + // ----------------------------------------------------------------------------------------- + // ------------------------- + // ----------------------------------------------------------------------------------------- + // ------------------------- + fn method_name(&self ) { } } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] pub trait AddArgumentTrait { fn method_name(&self, x: u32); } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] impl AddArgumentTrait for Foo { #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig,typeck,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] + #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig,typeck,optimized_mir", cfg="cfail5")] + #[rustc_clean(cfg="cfail6")] fn method_name(&self, _x: u32) { } } // Change argument type -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub trait ChangeArgumentTypeTrait { fn method_name(&self, x: u32); } -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] impl ChangeArgumentTypeTrait for Foo { - fn method_name(&self, _x: u32) { } + // ----------------------------------------------------------------------------------------- + // ------------------------- + // ----------------------------------------------------------------------------------------- + // ------------------------- + fn method_name(&self, _x: u32 ) { } } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] pub trait ChangeArgumentTypeTrait { fn method_name(&self, x: char); } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] impl ChangeArgumentTypeTrait for Foo { #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig,typeck,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] + #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig,typeck,optimized_mir", cfg="cfail5")] + #[rustc_clean(cfg="cfail6")] fn method_name(&self, _x: char) { } } @@ -366,21 +453,28 @@ trait AddTypeParameterToImpl { fn id(t: T) -> T; } -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] impl AddTypeParameterToImpl for Bar { fn id(t: u32) -> u32 { t } } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(except="hir_owner,generics_of,impl_trait_ref", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -impl AddTypeParameterToImpl for Bar { +#[rustc_clean(except="hir_owner,generics_of,impl_trait_ref", cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] +impl AddTypeParameterToImpl for Bar { #[rustc_clean( except="hir_owner,hir_owner_nodes,generics_of,fn_sig,type_of,typeck,optimized_mir", cfg="cfail2", )] #[rustc_clean(cfg="cfail3")] - fn id(t: T) -> T { t } + #[rustc_clean( + except="hir_owner,hir_owner_nodes,generics_of,fn_sig,type_of,typeck,optimized_mir", + cfg="cfail5", + )] + #[rustc_clean(cfg="cfail6")] + fn id(t: TTT) -> TTT { t } } @@ -390,17 +484,21 @@ trait ChangeSelfTypeOfImpl { fn id(self) -> Self; } -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] impl ChangeSelfTypeOfImpl for u32 { fn id(self) -> Self { self } } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(except="hir_owner,impl_trait_ref", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(except="hir_owner,impl_trait_ref", cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] impl ChangeSelfTypeOfImpl for u64 { #[rustc_clean(except="fn_sig,typeck,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] + #[rustc_clean(except="fn_sig,typeck,optimized_mir", cfg="cfail5")] + #[rustc_clean(cfg="cfail6")] fn id(self) -> Self { self } } @@ -411,17 +509,21 @@ trait AddLifetimeBoundToImplParameter { fn id(self) -> Self; } -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] impl AddLifetimeBoundToImplParameter for T { fn id(self) -> Self { self } } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] impl AddLifetimeBoundToImplParameter for T { #[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] + #[rustc_clean(cfg="cfail5")] + #[rustc_clean(cfg="cfail6")] fn id(self) -> Self { self } } @@ -432,17 +534,21 @@ trait AddTraitBoundToImplParameter { fn id(self) -> Self; } -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] impl AddTraitBoundToImplParameter for T { fn id(self) -> Self { self } } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] impl AddTraitBoundToImplParameter for T { #[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] + #[rustc_clean(cfg="cfail5")] + #[rustc_clean(cfg="cfail6")] fn id(self) -> Self { self } } @@ -453,17 +559,26 @@ trait AddNoMangleToMethod { fn add_no_mangle_to_method(&self) { } } -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] impl AddNoMangleToMethod for Foo { + // ------------------------- + // ------------------------- + // ------------------------- + // ------------------------- + // --------- fn add_no_mangle_to_method(&self) { } } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] impl AddNoMangleToMethod for Foo { #[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] + #[rustc_clean(cfg="cfail5")] + #[rustc_clean(cfg="cfail6")] #[no_mangle] fn add_no_mangle_to_method(&self) { } } @@ -474,17 +589,26 @@ trait MakeMethodInline { fn make_method_inline(&self) -> u8 { 0 } } -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] impl MakeMethodInline for Foo { + // ------------------------- + // ------------------------- + // ------------------------- + // ------------------------- + // ------ fn make_method_inline(&self) -> u8 { 0 } } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] impl MakeMethodInline for Foo { #[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] + #[rustc_clean(cfg="cfail5")] + #[rustc_clean(cfg="cfail6")] #[inline] fn make_method_inline(&self) -> u8 { 0 } } diff --git a/src/test/incremental/hashes/type_defs.rs b/src/test/incremental/hashes/type_defs.rs index d874be060c..70c199bc3b 100644 --- a/src/test/incremental/hashes/type_defs.rs +++ b/src/test/incremental/hashes/type_defs.rs @@ -12,7 +12,7 @@ // build-pass (FIXME(62277): could be check-pass?) // revisions: cfail1 cfail2 cfail3 -// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans +// compile-flags: -Z query-dep-graph #![allow(warnings)] #![feature(rustc_attrs)] diff --git a/src/test/incremental/hashes/unary_and_binary_exprs.rs b/src/test/incremental/hashes/unary_and_binary_exprs.rs index 687580ec8a..8d8345e10f 100644 --- a/src/test/incremental/hashes/unary_and_binary_exprs.rs +++ b/src/test/incremental/hashes/unary_and_binary_exprs.rs @@ -6,8 +6,14 @@ // rev3 and make sure that the hash has not changed. // build-pass (FIXME(62277): could be check-pass?) -// revisions: cfail1 cfail2 cfail3 -// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans +// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6 +// compile-flags: -Z query-dep-graph +// [cfail1]compile-flags: -Zincremental-ignore-spans +// [cfail2]compile-flags: -Zincremental-ignore-spans +// [cfail3]compile-flags: -Zincremental-ignore-spans +// [cfail4]compile-flags: -Zincremental-relative-spans +// [cfail5]compile-flags: -Zincremental-relative-spans +// [cfail6]compile-flags: -Zincremental-relative-spans #![allow(warnings)] #![feature(rustc_attrs)] @@ -15,44 +21,50 @@ // Change constant operand of negation ----------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn const_negation() -> i32 { -10 } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] pub fn const_negation() -> i32 { - -1 + -1 } // Change constant operand of bitwise not -------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn const_bitwise_not() -> i32 { !100 } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] pub fn const_bitwise_not() -> i32 { - !99 + !99 } // Change variable operand of negation ----------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn var_negation(x: i32, y: i32) -> i32 { -x } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] pub fn var_negation(x: i32, y: i32) -> i32 { -y } @@ -60,14 +72,16 @@ pub fn var_negation(x: i32, y: i32) -> i32 { // Change variable operand of bitwise not -------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn var_bitwise_not(x: i32, y: i32) -> i32 { !x } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] pub fn var_bitwise_not(x: i32, y: i32) -> i32 { !y } @@ -75,14 +89,16 @@ pub fn var_bitwise_not(x: i32, y: i32) -> i32 { // Change variable operand of deref -------------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn var_deref(x: &i32, y: &i32) -> i32 { *x } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] pub fn var_deref(x: &i32, y: &i32) -> i32 { *y } @@ -90,14 +106,16 @@ pub fn var_deref(x: &i32, y: &i32) -> i32 { // Change first constant operand of addition ----------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn first_const_add() -> i32 { 1 + 3 } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] pub fn first_const_add() -> i32 { 2 + 3 } @@ -105,14 +123,16 @@ pub fn first_const_add() -> i32 { // Change second constant operand of addition ----------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn second_const_add() -> i32 { 1 + 2 } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] pub fn second_const_add() -> i32 { 1 + 3 } @@ -120,14 +140,16 @@ pub fn second_const_add() -> i32 { // Change first variable operand of addition ----------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn first_var_add(a: i32, b: i32) -> i32 { a + 2 } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] pub fn first_var_add(a: i32, b: i32) -> i32 { b + 2 } @@ -135,14 +157,16 @@ pub fn first_var_add(a: i32, b: i32) -> i32 { // Change second variable operand of addition ---------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn second_var_add(a: i32, b: i32) -> i32 { 1 + a } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] pub fn second_var_add(a: i32, b: i32) -> i32 { 1 + b } @@ -150,14 +174,16 @@ pub fn second_var_add(a: i32, b: i32) -> i32 { // Change operator from + to - ------------------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn plus_to_minus(a: i32) -> i32 { 1 + a } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] pub fn plus_to_minus(a: i32) -> i32 { 1 - a } @@ -165,14 +191,16 @@ pub fn plus_to_minus(a: i32) -> i32 { // Change operator from + to * ------------------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn plus_to_mult(a: i32) -> i32 { 1 + a } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] pub fn plus_to_mult(a: i32) -> i32 { 1 * a } @@ -180,14 +208,16 @@ pub fn plus_to_mult(a: i32) -> i32 { // Change operator from + to / ------------------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn plus_to_div(a: i32) -> i32 { 1 + a } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] pub fn plus_to_div(a: i32) -> i32 { 1 / a } @@ -195,14 +225,16 @@ pub fn plus_to_div(a: i32) -> i32 { // Change operator from + to % ------------------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn plus_to_mod(a: i32) -> i32 { 1 + a } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] pub fn plus_to_mod(a: i32) -> i32 { 1 % a } @@ -210,14 +242,16 @@ pub fn plus_to_mod(a: i32) -> i32 { // Change operator from && to || ----------------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn and_to_or(a: bool, b: bool) -> bool { a && b } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] pub fn and_to_or(a: bool, b: bool) -> bool { a || b } @@ -225,14 +259,16 @@ pub fn and_to_or(a: bool, b: bool) -> bool { // Change operator from & to | ------------------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn bitwise_and_to_bitwise_or(a: i32) -> i32 { 1 & a } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] pub fn bitwise_and_to_bitwise_or(a: i32) -> i32 { 1 | a } @@ -240,14 +276,16 @@ pub fn bitwise_and_to_bitwise_or(a: i32) -> i32 { // Change operator from & to ^ ------------------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn bitwise_and_to_bitwise_xor(a: i32) -> i32 { 1 & a } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] pub fn bitwise_and_to_bitwise_xor(a: i32) -> i32 { 1 ^ a } @@ -255,14 +293,16 @@ pub fn bitwise_and_to_bitwise_xor(a: i32) -> i32 { // Change operator from & to << ------------------------------------------------ -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn bitwise_and_to_lshift(a: i32) -> i32 { - a & 1 + a & 1 } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] pub fn bitwise_and_to_lshift(a: i32) -> i32 { a << 1 } @@ -270,14 +310,16 @@ pub fn bitwise_and_to_lshift(a: i32) -> i32 { // Change operator from & to >> ------------------------------------------------ -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn bitwise_and_to_rshift(a: i32) -> i32 { - a & 1 + a & 1 } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] pub fn bitwise_and_to_rshift(a: i32) -> i32 { a >> 1 } @@ -285,14 +327,16 @@ pub fn bitwise_and_to_rshift(a: i32) -> i32 { // Change operator from == to != ----------------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn eq_to_uneq(a: i32) -> bool { a == 1 } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] pub fn eq_to_uneq(a: i32) -> bool { a != 1 } @@ -300,44 +344,50 @@ pub fn eq_to_uneq(a: i32) -> bool { // Change operator from == to < ------------------------------------------------ -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn eq_to_lt(a: i32) -> bool { a == 1 } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] pub fn eq_to_lt(a: i32) -> bool { - a < 1 + a < 1 } // Change operator from == to > ------------------------------------------------ -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn eq_to_gt(a: i32) -> bool { a == 1 } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] pub fn eq_to_gt(a: i32) -> bool { - a > 1 + a > 1 } // Change operator from == to <= ----------------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn eq_to_le(a: i32) -> bool { a == 1 } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] pub fn eq_to_le(a: i32) -> bool { a <= 1 } @@ -345,14 +395,16 @@ pub fn eq_to_le(a: i32) -> bool { // Change operator from == to >= ----------------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn eq_to_ge(a: i32) -> bool { a == 1 } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] pub fn eq_to_ge(a: i32) -> bool { a >= 1 } @@ -360,16 +412,18 @@ pub fn eq_to_ge(a: i32) -> bool { // Change type in cast expression ---------------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn type_cast(a: u8) -> u64 { let b = a as i32; let c = b as u64; c } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(except="hir_owner_nodes,optimized_mir,typeck", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(except="hir_owner_nodes,optimized_mir,typeck", cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] pub fn type_cast(a: u8) -> u64 { let b = a as u32; let c = b as u64; @@ -379,14 +433,16 @@ pub fn type_cast(a: u8) -> u64 { // Change value in cast expression --------------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn value_cast(a: u32) -> i32 { 1 as i32 } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] pub fn value_cast(a: u32) -> i32 { 2 as i32 } @@ -394,7 +450,7 @@ pub fn value_cast(a: u32) -> i32 { // Change place in assignment -------------------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn place() -> i32 { let mut x = 10; let mut y = 11; @@ -402,9 +458,11 @@ pub fn place() -> i32 { x } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] pub fn place() -> i32 { let mut x = 10; let mut y = 11; @@ -415,16 +473,18 @@ pub fn place() -> i32 { // Change r-value in assignment ------------------------------------------------ -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn rvalue() -> i32 { let mut x = 10; x = 9; x } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] pub fn rvalue() -> i32 { let mut x = 10; x = 8; @@ -434,14 +494,16 @@ pub fn rvalue() -> i32 { // Change index into slice ----------------------------------------------------- -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn index_to_slice(s: &[u8], i: usize, j: usize) -> u8 { s[i] } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")] +#[rustc_clean(cfg="cfail6")] pub fn index_to_slice(s: &[u8], i: usize, j: usize) -> u8 { s[j] } diff --git a/src/test/incremental/hashes/while_let_loops.rs b/src/test/incremental/hashes/while_let_loops.rs index d385974893..64a6517836 100644 --- a/src/test/incremental/hashes/while_let_loops.rs +++ b/src/test/incremental/hashes/while_let_loops.rs @@ -6,8 +6,14 @@ // rev3 and make sure that the hash has not changed. // build-pass (FIXME(62277): could be check-pass?) -// revisions: cfail1 cfail2 cfail3 -// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans +// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6 +// compile-flags: -Z query-dep-graph +// [cfail1]compile-flags: -Zincremental-ignore-spans +// [cfail2]compile-flags: -Zincremental-ignore-spans +// [cfail3]compile-flags: -Zincremental-ignore-spans +// [cfail4]compile-flags: -Zincremental-relative-spans +// [cfail5]compile-flags: -Zincremental-relative-spans +// [cfail6]compile-flags: -Zincremental-relative-spans #![allow(warnings)] #![feature(rustc_attrs)] @@ -15,7 +21,7 @@ // Change loop body -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn change_loop_body() { let mut _x = 0; while let Some(0u32) = None { @@ -24,9 +30,11 @@ pub fn change_loop_body() { } } -#[cfg(not(cfail1))] +#[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")] +#[rustc_clean(cfg="cfail6")] pub fn change_loop_body() { let mut _x = 0; while let Some(0u32) = None { @@ -38,7 +46,7 @@ pub fn change_loop_body() { // Change loop body -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn change_loop_condition() { let mut _x = 0; while let Some(0u32) = None { @@ -47,9 +55,11 @@ pub fn change_loop_condition() { } } -#[cfg(not(cfail1))] +#[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")] +#[rustc_clean(cfg="cfail6")] pub fn change_loop_condition() { let mut _x = 0; while let Some(1u32) = None { @@ -61,17 +71,20 @@ pub fn change_loop_condition() { // Add break -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn add_break() { let mut _x = 0; while let Some(0u32) = None { _x = 1; + // --- } } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2", except="hir_owner_nodes, typeck")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, typeck")] +#[rustc_clean(cfg="cfail6")] pub fn add_break() { let mut _x = 0; while let Some(0u32) = None { @@ -83,18 +96,20 @@ pub fn add_break() { // Add loop label -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn add_loop_label() { let mut _x = 0; - while let Some(0u32) = None { + while let Some(0u32) = None { _x = 1; break; } } -#[cfg(not(cfail1))] +#[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")] +#[rustc_clean(cfg="cfail6")] pub fn add_loop_label() { let mut _x = 0; 'label: while let Some(0u32) = None { @@ -106,18 +121,20 @@ pub fn add_loop_label() { // Add loop label to break -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn add_loop_label_to_break() { let mut _x = 0; 'label: while let Some(0u32) = None { _x = 1; - break; + break ; } } -#[cfg(not(cfail1))] +#[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")] +#[rustc_clean(cfg="cfail6")] pub fn add_loop_label_to_break() { let mut _x = 0; 'label: while let Some(0u32) = None { @@ -129,7 +146,7 @@ pub fn add_loop_label_to_break() { // Change break label -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn change_break_label() { let mut _x = 0; 'outer: while let Some(0u32) = None { @@ -140,9 +157,11 @@ pub fn change_break_label() { } } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck")] +#[rustc_clean(cfg="cfail6")] pub fn change_break_label() { let mut _x = 0; 'outer: while let Some(0u32) = None { @@ -154,18 +173,20 @@ pub fn change_break_label() { } // Add loop label to continue -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn add_loop_label_to_continue() { let mut _x = 0; 'label: while let Some(0u32) = None { _x = 1; - continue; + continue ; } } -#[cfg(not(cfail1))] +#[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")] +#[rustc_clean(cfg="cfail6")] pub fn add_loop_label_to_continue() { let mut _x = 0; 'label: while let Some(0u32) = None { @@ -177,7 +198,7 @@ pub fn add_loop_label_to_continue() { // Change continue label -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn change_continue_label() { let mut _x = 0; 'outer: while let Some(0u32) = None { @@ -188,9 +209,11 @@ pub fn change_continue_label() { } } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck")] +#[rustc_clean(cfg="cfail6")] pub fn change_continue_label() { let mut _x = 0; 'outer: while let Some(0u32) = None { @@ -204,7 +227,7 @@ pub fn change_continue_label() { // Change continue to break -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn change_continue_to_break() { let mut _x = 0; while let Some(0u32) = None { @@ -213,13 +236,15 @@ pub fn change_continue_to_break() { } } -#[cfg(not(cfail1))] +#[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")] +#[rustc_clean(cfg="cfail6")] pub fn change_continue_to_break() { let mut _x = 0; while let Some(0u32) = None { _x = 1; - break; + break ; } } diff --git a/src/test/incremental/hashes/while_loops.rs b/src/test/incremental/hashes/while_loops.rs index 299622e45c..b8796d3446 100644 --- a/src/test/incremental/hashes/while_loops.rs +++ b/src/test/incremental/hashes/while_loops.rs @@ -6,8 +6,14 @@ // rev3 and make sure that the hash has not changed. // build-pass (FIXME(62277): could be check-pass?) -// revisions: cfail1 cfail2 cfail3 -// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans +// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6 +// compile-flags: -Z query-dep-graph +// [cfail1]compile-flags: -Zincremental-ignore-spans +// [cfail2]compile-flags: -Zincremental-ignore-spans +// [cfail3]compile-flags: -Zincremental-ignore-spans +// [cfail4]compile-flags: -Zincremental-relative-spans +// [cfail5]compile-flags: -Zincremental-relative-spans +// [cfail6]compile-flags: -Zincremental-relative-spans #![allow(warnings)] #![feature(rustc_attrs)] @@ -15,7 +21,7 @@ // Change loop body -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn change_loop_body() { let mut _x = 0; while true { @@ -24,9 +30,11 @@ pub fn change_loop_body() { } } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")] +#[rustc_clean(cfg="cfail6")] pub fn change_loop_body() { let mut _x = 0; while true { @@ -38,18 +46,20 @@ pub fn change_loop_body() { // Change loop body -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn change_loop_condition() { let mut _x = 0; - while true { + while true { _x = 1; break; } } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")] +#[rustc_clean(cfg="cfail6")] pub fn change_loop_condition() { let mut _x = 0; while false { @@ -61,17 +71,20 @@ pub fn change_loop_condition() { // Add break -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn add_break() { let mut _x = 0; while true { _x = 1; + // --- } } -#[cfg(not(cfail1))] +#[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")] +#[rustc_clean(cfg="cfail6")] pub fn add_break() { let mut _x = 0; while true { @@ -83,18 +96,20 @@ pub fn add_break() { // Add loop label -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn add_loop_label() { let mut _x = 0; - while true { + while true { _x = 1; break; } } -#[cfg(not(cfail1))] +#[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")] +#[rustc_clean(cfg="cfail6")] pub fn add_loop_label() { let mut _x = 0; 'label: while true { @@ -106,18 +121,20 @@ pub fn add_loop_label() { // Add loop label to break -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn add_loop_label_to_break() { let mut _x = 0; 'label: while true { _x = 1; - break; + break ; } } -#[cfg(not(cfail1))] +#[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")] +#[rustc_clean(cfg="cfail6")] pub fn add_loop_label_to_break() { let mut _x = 0; 'label: while true { @@ -129,7 +146,7 @@ pub fn add_loop_label_to_break() { // Change break label -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn change_break_label() { let mut _x = 0; 'outer: while true { @@ -140,9 +157,11 @@ pub fn change_break_label() { } } -#[cfg(not(cfail1))] +#[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")] +#[rustc_clean(cfg="cfail6")] pub fn change_break_label() { let mut _x = 0; 'outer: while true { @@ -156,18 +175,20 @@ pub fn change_break_label() { // Add loop label to continue -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn add_loop_label_to_continue() { let mut _x = 0; 'label: while true { _x = 1; - continue; + continue ; } } -#[cfg(not(cfail1))] +#[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")] +#[rustc_clean(cfg="cfail6")] pub fn add_loop_label_to_continue() { let mut _x = 0; 'label: while true { @@ -179,7 +200,7 @@ pub fn add_loop_label_to_continue() { // Change continue label -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn change_continue_label() { let mut _x = 0; 'outer: while true { @@ -190,9 +211,11 @@ pub fn change_continue_label() { } } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck,optimized_mir")] +#[rustc_clean(cfg="cfail6")] pub fn change_continue_label() { let mut _x = 0; 'outer: while true { @@ -206,7 +229,7 @@ pub fn change_continue_label() { // Change continue to break -#[cfg(cfail1)] +#[cfg(any(cfail1,cfail4))] pub fn change_continue_to_break() { let mut _x = 0; while true { @@ -215,13 +238,15 @@ pub fn change_continue_to_break() { } } -#[cfg(not(cfail1))] +#[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")] #[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")] +#[rustc_clean(cfg="cfail6")] pub fn change_continue_to_break() { let mut _x = 0; while true { _x = 1; - break; + break ; } } diff --git a/src/test/incremental/mir-opt.rs b/src/test/incremental/mir-opt.rs new file mode 100644 index 0000000000..5bd863439d --- /dev/null +++ b/src/test/incremental/mir-opt.rs @@ -0,0 +1,11 @@ +// MIR optimizations can create expansions after the TyCtxt has been created. +// This test verifies that those expansions can be decoded correctly. + +// revisions:rpass1 rpass2 +// compile-flags: -Z query-dep-graph -Z mir-opt-level=3 + +fn main() { + if std::env::var("a").is_ok() { + println!("b"); + } +} diff --git a/src/test/incremental/spans_significant_w_debuginfo.rs b/src/test/incremental/spans_significant_w_debuginfo.rs index 8506636e22..639454cc97 100644 --- a/src/test/incremental/spans_significant_w_debuginfo.rs +++ b/src/test/incremental/spans_significant_w_debuginfo.rs @@ -1,16 +1,21 @@ // This test makes sure that just changing a definition's location in the // source file also changes its incr. comp. hash, if debuginfo is enabled. -// revisions:rpass1 rpass2 +// revisions:rpass1 rpass2 rpass3 rpass4 // ignore-asmjs wasm2js does not support source maps yet // compile-flags: -g -Z query-dep-graph +// [rpass3]compile-flags: -Zincremental-relative-spans +// [rpass4]compile-flags: -Zincremental-relative-spans #![feature(rustc_attrs)] +#![rustc_partition_codegened(module = "spans_significant_w_debuginfo", cfg = "rpass2")] +#![rustc_partition_codegened(module = "spans_significant_w_debuginfo", cfg = "rpass4")] -#[cfg(rpass1)] +#[cfg(any(rpass1, rpass3))] pub fn main() {} -#[cfg(rpass2)] -#[rustc_clean(except="hir_owner,hir_owner_nodes,optimized_mir", cfg="rpass2")] +#[cfg(any(rpass2, rpass4))] +#[rustc_clean(except = "hir_owner,hir_owner_nodes,optimized_mir", cfg = "rpass2")] +#[rustc_clean(cfg = "rpass4")] pub fn main() {} diff --git a/src/test/incremental/spans_significant_w_panic.rs b/src/test/incremental/spans_significant_w_panic.rs index a29b61ab15..e9e35791aa 100644 --- a/src/test/incremental/spans_significant_w_panic.rs +++ b/src/test/incremental/spans_significant_w_panic.rs @@ -1,19 +1,29 @@ // This test makes sure that just changing a definition's location in the // source file also changes its incr. comp. hash, if debuginfo is enabled. -// revisions:rpass1 rpass2 +// revisions:rpass1 rpass2 rpass3 rpass4 +// [rpass3]compile-flags: -Zincremental-relative-spans +// [rpass4]compile-flags: -Zincremental-relative-spans // compile-flags: -C overflow-checks=on -Z query-dep-graph #![feature(rustc_attrs)] +#![feature(bench_black_box)] +#![rustc_partition_codegened(module = "spans_significant_w_panic", cfg = "rpass2")] +#![rustc_partition_codegened(module = "spans_significant_w_panic", cfg = "rpass4")] -#[cfg(rpass1)] +#[cfg(any(rpass1, rpass3))] pub fn main() { - let _ = 0u8 + 1; + if std::hint::black_box(false) { + panic!() + } } -#[cfg(rpass2)] -#[rustc_clean(except="hir_owner,hir_owner_nodes,optimized_mir", cfg="rpass2")] +#[cfg(any(rpass2, rpass4))] +#[rustc_clean(except = "hir_owner,hir_owner_nodes,optimized_mir", cfg = "rpass2")] +#[rustc_clean(cfg = "rpass4")] pub fn main() { - let _ = 0u8 + 1; + if std::hint::black_box(false) { + panic!() + } } diff --git a/src/test/incremental/string_constant.rs b/src/test/incremental/string_constant.rs index 866f51d759..cae7b4aab7 100644 --- a/src/test/incremental/string_constant.rs +++ b/src/test/incremental/string_constant.rs @@ -1,5 +1,7 @@ -// revisions: cfail1 cfail2 +// revisions: cfail1 cfail2 cfail3 cfail4 // compile-flags: -Z query-dep-graph +// [cfail3]compile-flags: -Zincremental-relative-spans +// [cfail4]compile-flags: -Zincremental-relative-spans // build-pass (FIXME(62277): could be check-pass?) #![allow(warnings)] @@ -10,15 +12,15 @@ // Therefore, the compiler deduces (correctly) that typeck is not // needed even for callers of `x`. - pub mod x { - #[cfg(cfail1)] + #[cfg(any(cfail1, cfail3))] pub fn x() { println!("{}", "1"); } - #[cfg(cfail2)] - #[rustc_clean(except="hir_owner,hir_owner_nodes,optimized_mir,promoted_mir", cfg="cfail2")] + #[cfg(any(cfail2, cfail4))] + #[rustc_clean(except = "hir_owner,hir_owner_nodes,optimized_mir,promoted_mir", cfg = "cfail2")] + #[rustc_clean(except = "hir_owner_nodes,promoted_mir", cfg = "cfail4")] pub fn x() { println!("{}", "2"); } @@ -27,7 +29,8 @@ pub mod x { pub mod y { use x; - #[rustc_clean(cfg="cfail2")] + #[rustc_clean(cfg = "cfail2")] + #[rustc_clean(cfg = "cfail4")] pub fn y() { x::x(); } @@ -36,7 +39,8 @@ pub mod y { pub mod z { use y; - #[rustc_clean(cfg="cfail2")] + #[rustc_clean(cfg = "cfail2")] + #[rustc_clean(cfg = "cfail4")] pub fn z() { y::y(); } diff --git a/src/test/incremental/thinlto/cgu_keeps_identical_fn.rs b/src/test/incremental/thinlto/cgu_keeps_identical_fn.rs index 0fd5abee11..31f329a7f7 100644 --- a/src/test/incremental/thinlto/cgu_keeps_identical_fn.rs +++ b/src/test/incremental/thinlto/cgu_keeps_identical_fn.rs @@ -3,36 +3,61 @@ // ends up with any spans in its LLVM bitecode, so LLVM is able to skip // re-building any modules which import 'inlined_fn' -// revisions: cfail1 cfail2 cfail3 +// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6 +// [cfail4]compile-flags: -Zincremental-relative-spans +// [cfail5]compile-flags: -Zincremental-relative-spans +// [cfail6]compile-flags: -Zincremental-relative-spans // compile-flags: -Z query-dep-graph -O // build-pass (FIXME(62277): could be check-pass?) #![feature(rustc_attrs)] -#![crate_type="rlib"] - -#![rustc_expected_cgu_reuse(module="cgu_keeps_identical_fn-foo", - cfg="cfail2", - kind="no")] -#![rustc_expected_cgu_reuse(module="cgu_keeps_identical_fn-foo", - cfg="cfail3", - kind="post-lto")] - -#![rustc_expected_cgu_reuse(module="cgu_keeps_identical_fn-bar", - cfg="cfail2", - kind="post-lto")] -#![rustc_expected_cgu_reuse(module="cgu_keeps_identical_fn-bar", - cfg="cfail3", - kind="post-lto")] +#![crate_type = "rlib"] +#![rustc_expected_cgu_reuse(module = "cgu_keeps_identical_fn-foo", cfg = "cfail2", kind = "no")] +#![rustc_expected_cgu_reuse( + module = "cgu_keeps_identical_fn-foo", + cfg = "cfail3", + kind = "post-lto" +)] +#![rustc_expected_cgu_reuse( + module = "cgu_keeps_identical_fn-foo", + cfg = "cfail5", + kind = "post-lto" +)] +#![rustc_expected_cgu_reuse( + module = "cgu_keeps_identical_fn-foo", + cfg = "cfail6", + kind = "post-lto" +)] +#![rustc_expected_cgu_reuse( + module = "cgu_keeps_identical_fn-bar", + cfg = "cfail2", + kind = "post-lto" +)] +#![rustc_expected_cgu_reuse( + module = "cgu_keeps_identical_fn-bar", + cfg = "cfail3", + kind = "post-lto" +)] +#![rustc_expected_cgu_reuse( + module = "cgu_keeps_identical_fn-bar", + cfg = "cfail5", + kind = "post-lto" +)] +#![rustc_expected_cgu_reuse( + module = "cgu_keeps_identical_fn-bar", + cfg = "cfail6", + kind = "post-lto" +)] mod foo { // Trivial functions like this one are imported very reliably by ThinLTO. - #[cfg(cfail1)] + #[cfg(any(cfail1, cfail4))] pub fn inlined_fn() -> u32 { 1234 } - #[cfg(not(cfail1))] + #[cfg(not(any(cfail1, cfail4)))] pub fn inlined_fn() -> u32 { 1234 } diff --git a/src/test/mir-opt/box_expr.main.ElaborateDrops.before.mir b/src/test/mir-opt/box_expr.main.ElaborateDrops.before.mir index cfbd3a5863..c6187879ab 100644 --- a/src/test/mir-opt/box_expr.main.ElaborateDrops.before.mir +++ b/src/test/mir-opt/box_expr.main.ElaborateDrops.before.mir @@ -3,64 +3,78 @@ fn main() -> () { let mut _0: (); // return place in scope 0 at $DIR/box_expr.rs:6:11: 6:11 let _1: std::boxed::Box; // in scope 0 at $DIR/box_expr.rs:7:9: 7:10 - let mut _2: std::boxed::Box; // in scope 0 at $DIR/box_expr.rs:7:13: 7:25 - let _3: (); // in scope 0 at $DIR/box_expr.rs:8:5: 8:12 - let mut _4: std::boxed::Box; // in scope 0 at $DIR/box_expr.rs:8:10: 8:11 + let mut _2: usize; // in scope 0 at $DIR/box_expr.rs:7:13: 7:25 + let mut _3: usize; // in scope 0 at $DIR/box_expr.rs:7:13: 7:25 + let mut _4: *mut u8; // in scope 0 at $DIR/box_expr.rs:7:13: 7:25 + let mut _5: std::boxed::Box; // in scope 0 at $DIR/box_expr.rs:7:13: 7:25 + let _6: (); // in scope 0 at $DIR/box_expr.rs:8:5: 8:12 + let mut _7: std::boxed::Box; // in scope 0 at $DIR/box_expr.rs:8:10: 8:11 scope 1 { debug x => _1; // in scope 1 at $DIR/box_expr.rs:7:9: 7:10 } + scope 2 { + } bb0: { StorageLive(_1); // scope 0 at $DIR/box_expr.rs:7:9: 7:10 - StorageLive(_2); // scope 0 at $DIR/box_expr.rs:7:13: 7:25 - _2 = Box(S); // scope 0 at $DIR/box_expr.rs:7:13: 7:25 - (*_2) = S::new() -> [return: bb1, unwind: bb7]; // scope 0 at $DIR/box_expr.rs:7:17: 7:25 + _2 = SizeOf(S); // scope 2 at $DIR/box_expr.rs:7:13: 7:25 + _3 = AlignOf(S); // scope 2 at $DIR/box_expr.rs:7:13: 7:25 + _4 = alloc::alloc::exchange_malloc(move _2, move _3) -> bb1; // scope 2 at $DIR/box_expr.rs:7:13: 7:25 + // mir::Constant + // + span: $DIR/box_expr.rs:7:13: 7:25 + // + literal: Const { ty: unsafe fn(usize, usize) -> *mut u8 {alloc::alloc::exchange_malloc}, val: Value(Scalar()) } + } + + bb1: { + StorageLive(_5); // scope 0 at $DIR/box_expr.rs:7:13: 7:25 + _5 = ShallowInitBox(move _4, S); // scope 0 at $DIR/box_expr.rs:7:13: 7:25 + (*_5) = S::new() -> [return: bb2, unwind: bb8]; // scope 0 at $DIR/box_expr.rs:7:17: 7:25 // mir::Constant // + span: $DIR/box_expr.rs:7:17: 7:23 // + literal: Const { ty: fn() -> S {S::new}, val: Value(Scalar()) } } - bb1: { - _1 = move _2; // scope 0 at $DIR/box_expr.rs:7:13: 7:25 - drop(_2) -> bb2; // scope 0 at $DIR/box_expr.rs:7:24: 7:25 + bb2: { + _1 = move _5; // scope 0 at $DIR/box_expr.rs:7:13: 7:25 + drop(_5) -> bb3; // scope 0 at $DIR/box_expr.rs:7:24: 7:25 } - bb2: { - StorageDead(_2); // scope 0 at $DIR/box_expr.rs:7:24: 7:25 - StorageLive(_3); // scope 1 at $DIR/box_expr.rs:8:5: 8:12 - StorageLive(_4); // scope 1 at $DIR/box_expr.rs:8:10: 8:11 - _4 = move _1; // scope 1 at $DIR/box_expr.rs:8:10: 8:11 - _3 = std::mem::drop::>(move _4) -> [return: bb3, unwind: bb5]; // scope 1 at $DIR/box_expr.rs:8:5: 8:12 + bb3: { + StorageDead(_5); // scope 0 at $DIR/box_expr.rs:7:24: 7:25 + StorageLive(_6); // scope 1 at $DIR/box_expr.rs:8:5: 8:12 + StorageLive(_7); // scope 1 at $DIR/box_expr.rs:8:10: 8:11 + _7 = move _1; // scope 1 at $DIR/box_expr.rs:8:10: 8:11 + _6 = std::mem::drop::>(move _7) -> [return: bb4, unwind: bb6]; // scope 1 at $DIR/box_expr.rs:8:5: 8:12 // mir::Constant // + span: $DIR/box_expr.rs:8:5: 8:9 // + literal: Const { ty: fn(std::boxed::Box) {std::mem::drop::>}, val: Value(Scalar()) } } - bb3: { - StorageDead(_4); // scope 1 at $DIR/box_expr.rs:8:11: 8:12 - StorageDead(_3); // scope 1 at $DIR/box_expr.rs:8:12: 8:13 + bb4: { + StorageDead(_7); // scope 1 at $DIR/box_expr.rs:8:11: 8:12 + StorageDead(_6); // scope 1 at $DIR/box_expr.rs:8:12: 8:13 _0 = const (); // scope 0 at $DIR/box_expr.rs:6:11: 9:2 - drop(_1) -> bb4; // scope 0 at $DIR/box_expr.rs:9:1: 9:2 + drop(_1) -> bb5; // scope 0 at $DIR/box_expr.rs:9:1: 9:2 } - bb4: { + bb5: { StorageDead(_1); // scope 0 at $DIR/box_expr.rs:9:1: 9:2 return; // scope 0 at $DIR/box_expr.rs:9:2: 9:2 } - bb5 (cleanup): { - drop(_4) -> bb6; // scope 1 at $DIR/box_expr.rs:8:11: 8:12 - } - bb6 (cleanup): { - drop(_1) -> bb8; // scope 0 at $DIR/box_expr.rs:9:1: 9:2 + drop(_7) -> bb7; // scope 1 at $DIR/box_expr.rs:8:11: 8:12 } bb7 (cleanup): { - drop(_2) -> bb8; // scope 0 at $DIR/box_expr.rs:7:24: 7:25 + drop(_1) -> bb9; // scope 0 at $DIR/box_expr.rs:9:1: 9:2 } bb8 (cleanup): { + drop(_5) -> bb9; // scope 0 at $DIR/box_expr.rs:7:24: 7:25 + } + + bb9 (cleanup): { resume; // scope 0 at $DIR/box_expr.rs:6:1: 9:2 } } diff --git a/src/test/mir-opt/const_promotion_extern_static.BAR-promoted[0].SimplifyCfg-elaborate-drops.after.mir b/src/test/mir-opt/const_promotion_extern_static.BAR-promoted[0].SimplifyCfg-elaborate-drops.after.mir index a64c960b9f..bec0fa9c04 100644 --- a/src/test/mir-opt/const_promotion_extern_static.BAR-promoted[0].SimplifyCfg-elaborate-drops.after.mir +++ b/src/test/mir-opt/const_promotion_extern_static.BAR-promoted[0].SimplifyCfg-elaborate-drops.after.mir @@ -1,7 +1,7 @@ // MIR for `BAR::promoted[0]` after SimplifyCfg-elaborate-drops promoted[0] in BAR: &[&i32; 1] = { - let mut _0: &[&i32; 1]; // return place in scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35 + let mut _0: &[&i32; 1]; // return place in scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:44 let mut _1: [&i32; 1]; // in scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35 let mut _2: &i32; // in scope 0 at $DIR/const-promotion-extern-static.rs:9:32: 9:34 let mut _3: &i32; // in scope 0 at $DIR/const-promotion-extern-static.rs:9:33: 9:34 @@ -16,8 +16,8 @@ promoted[0] in BAR: &[&i32; 1] = { // + literal: Const { ty: &i32, val: Value(Scalar(alloc1)) } _2 = &(*_3); // scope 0 at $DIR/const-promotion-extern-static.rs:9:32: 9:34 _1 = [move _2]; // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35 - _0 = &_1; // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35 - return; // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35 + _0 = &_1; // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:44 + return; // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:44 } } diff --git a/src/test/mir-opt/const_promotion_extern_static.BAR.PromoteTemps.diff b/src/test/mir-opt/const_promotion_extern_static.BAR.PromoteTemps.diff index 49d0a7ff45..bdd62f1029 100644 --- a/src/test/mir-opt/const_promotion_extern_static.BAR.PromoteTemps.diff +++ b/src/test/mir-opt/const_promotion_extern_static.BAR.PromoteTemps.diff @@ -3,21 +3,21 @@ static mut BAR: *const &i32 = { let mut _0: *const &i32; // return place in scope 0 at $DIR/const-promotion-extern-static.rs:9:17: 9:28 - let mut _1: &[&i32]; // in scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35 - let mut _2: &[&i32; 1]; // in scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35 + let mut _1: &[&i32]; // in scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:44 + let mut _2: &[&i32; 1]; // in scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:44 let _3: [&i32; 1]; // in scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35 let mut _4: &i32; // in scope 0 at $DIR/const-promotion-extern-static.rs:9:32: 9:34 let _5: &i32; // in scope 0 at $DIR/const-promotion-extern-static.rs:9:33: 9:34 -+ let mut _6: &[&i32; 1]; // in scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35 ++ let mut _6: &[&i32; 1]; // in scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:44 bb0: { - StorageLive(_1); // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35 - StorageLive(_2); // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35 + StorageLive(_1); // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:44 + StorageLive(_2); // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:44 - StorageLive(_3); // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35 - StorageLive(_4); // scope 0 at $DIR/const-promotion-extern-static.rs:9:32: 9:34 - StorageLive(_5); // scope 0 at $DIR/const-promotion-extern-static.rs:9:33: 9:34 - _5 = const {alloc1: &i32}; // scope 0 at $DIR/const-promotion-extern-static.rs:9:33: 9:34 -+ _6 = const BAR::promoted[0]; // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35 ++ _6 = const BAR::promoted[0]; // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:44 // ty::Const - // + ty: &i32 - // + val: Value(Scalar(alloc1)) @@ -28,11 +28,11 @@ - // + literal: Const { ty: &i32, val: Value(Scalar(alloc1)) } - _4 = &(*_5); // scope 0 at $DIR/const-promotion-extern-static.rs:9:32: 9:34 - _3 = [move _4]; // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35 -- _2 = &_3; // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35 -+ // + span: $DIR/const-promotion-extern-static.rs:9:31: 9:35 +- _2 = &_3; // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:44 ++ // + span: $DIR/const-promotion-extern-static.rs:9:31: 9:44 + // + literal: Const { ty: &[&i32; 1], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:6 ~ const_promotion_extern_static[55e6]::BAR), const_param_did: None }, substs_: Some([]), promoted: Some(promoted[0]) }) } -+ _2 = &(*_6); // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35 - _1 = move _2 as &[&i32] (Pointer(Unsize)); // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35 ++ _2 = &(*_6); // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:44 + _1 = move _2 as &[&i32] (Pointer(Unsize)); // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:44 - StorageDead(_4); // scope 0 at $DIR/const-promotion-extern-static.rs:9:34: 9:35 StorageDead(_2); // scope 0 at $DIR/const-promotion-extern-static.rs:9:34: 9:35 _0 = core::slice::::as_ptr(move _1) -> [return: bb1, unwind: bb2]; // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:44 diff --git a/src/test/mir-opt/const_promotion_extern_static.FOO-promoted[0].SimplifyCfg-elaborate-drops.after.mir b/src/test/mir-opt/const_promotion_extern_static.FOO-promoted[0].SimplifyCfg-elaborate-drops.after.mir index 8b3c5d332f..c01b31525b 100644 --- a/src/test/mir-opt/const_promotion_extern_static.FOO-promoted[0].SimplifyCfg-elaborate-drops.after.mir +++ b/src/test/mir-opt/const_promotion_extern_static.FOO-promoted[0].SimplifyCfg-elaborate-drops.after.mir @@ -1,7 +1,7 @@ // MIR for `FOO::promoted[0]` after SimplifyCfg-elaborate-drops promoted[0] in FOO: &[&i32; 1] = { - let mut _0: &[&i32; 1]; // return place in scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:46 + let mut _0: &[&i32; 1]; // return place in scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:55 let mut _1: [&i32; 1]; // in scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:46 let mut _2: &i32; // in scope 0 at $DIR/const-promotion-extern-static.rs:13:32: 13:45 let mut _3: *const i32; // in scope 0 at $DIR/const-promotion-extern-static.rs:13:42: 13:43 @@ -16,8 +16,8 @@ promoted[0] in FOO: &[&i32; 1] = { // + literal: Const { ty: *const i32, val: Value(Scalar(alloc3)) } _2 = &(*_3); // scope 0 at $DIR/const-promotion-extern-static.rs:13:41: 13:43 _1 = [move _2]; // scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:46 - _0 = &_1; // scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:46 - return; // scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:46 + _0 = &_1; // scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:55 + return; // scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:55 } } diff --git a/src/test/mir-opt/const_promotion_extern_static.FOO.PromoteTemps.diff b/src/test/mir-opt/const_promotion_extern_static.FOO.PromoteTemps.diff index f2504ae880..94b337806a 100644 --- a/src/test/mir-opt/const_promotion_extern_static.FOO.PromoteTemps.diff +++ b/src/test/mir-opt/const_promotion_extern_static.FOO.PromoteTemps.diff @@ -3,23 +3,23 @@ static mut FOO: *const &i32 = { let mut _0: *const &i32; // return place in scope 0 at $DIR/const-promotion-extern-static.rs:13:17: 13:28 - let mut _1: &[&i32]; // in scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:46 - let mut _2: &[&i32; 1]; // in scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:46 + let mut _1: &[&i32]; // in scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:55 + let mut _2: &[&i32; 1]; // in scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:55 let _3: [&i32; 1]; // in scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:46 let mut _4: &i32; // in scope 0 at $DIR/const-promotion-extern-static.rs:13:32: 13:45 let _5: *const i32; // in scope 0 at $DIR/const-promotion-extern-static.rs:13:42: 13:43 -+ let mut _6: &[&i32; 1]; // in scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:46 ++ let mut _6: &[&i32; 1]; // in scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:55 scope 1 { } bb0: { - StorageLive(_1); // scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:46 - StorageLive(_2); // scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:46 + StorageLive(_1); // scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:55 + StorageLive(_2); // scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:55 - StorageLive(_3); // scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:46 - StorageLive(_4); // scope 0 at $DIR/const-promotion-extern-static.rs:13:32: 13:45 - StorageLive(_5); // scope 1 at $DIR/const-promotion-extern-static.rs:13:42: 13:43 - _5 = const {alloc3: *const i32}; // scope 1 at $DIR/const-promotion-extern-static.rs:13:42: 13:43 -+ _6 = const FOO::promoted[0]; // scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:46 ++ _6 = const FOO::promoted[0]; // scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:55 // ty::Const - // + ty: *const i32 - // + val: Value(Scalar(alloc3)) @@ -30,11 +30,11 @@ - // + literal: Const { ty: *const i32, val: Value(Scalar(alloc3)) } - _4 = &(*_5); // scope 1 at $DIR/const-promotion-extern-static.rs:13:41: 13:43 - _3 = [move _4]; // scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:46 -- _2 = &_3; // scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:46 -+ // + span: $DIR/const-promotion-extern-static.rs:13:31: 13:46 +- _2 = &_3; // scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:55 ++ // + span: $DIR/const-promotion-extern-static.rs:13:31: 13:55 + // + literal: Const { ty: &[&i32; 1], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:7 ~ const_promotion_extern_static[55e6]::FOO), const_param_did: None }, substs_: Some([]), promoted: Some(promoted[0]) }) } -+ _2 = &(*_6); // scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:46 - _1 = move _2 as &[&i32] (Pointer(Unsize)); // scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:46 ++ _2 = &(*_6); // scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:55 + _1 = move _2 as &[&i32] (Pointer(Unsize)); // scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:55 - StorageDead(_4); // scope 0 at $DIR/const-promotion-extern-static.rs:13:45: 13:46 StorageDead(_2); // scope 0 at $DIR/const-promotion-extern-static.rs:13:45: 13:46 _0 = core::slice::::as_ptr(move _1) -> [return: bb1, unwind: bb2]; // scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:55 diff --git a/src/test/mir-opt/const_prop/boxes.main.ConstProp.diff b/src/test/mir-opt/const_prop/boxes.main.ConstProp.diff index 9fcbd32ca6..342c987343 100644 --- a/src/test/mir-opt/const_prop/boxes.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/boxes.main.ConstProp.diff @@ -6,34 +6,51 @@ let _1: i32; // in scope 0 at $DIR/boxes.rs:12:9: 12:10 let mut _2: i32; // in scope 0 at $DIR/boxes.rs:12:13: 12:22 let mut _3: std::boxed::Box; // in scope 0 at $DIR/boxes.rs:12:14: 12:22 - let mut _4: std::boxed::Box; // in scope 0 at $DIR/boxes.rs:12:14: 12:22 + let mut _4: usize; // in scope 0 at $DIR/boxes.rs:12:14: 12:22 + let mut _5: usize; // in scope 0 at $DIR/boxes.rs:12:14: 12:22 + let mut _6: *mut u8; // in scope 0 at $DIR/boxes.rs:12:14: 12:22 + let mut _7: std::boxed::Box; // in scope 0 at $DIR/boxes.rs:12:14: 12:22 scope 1 { debug x => _1; // in scope 1 at $DIR/boxes.rs:12:9: 12:10 } + scope 2 { + } bb0: { StorageLive(_1); // scope 0 at $DIR/boxes.rs:12:9: 12:10 StorageLive(_2); // scope 0 at $DIR/boxes.rs:12:13: 12:22 StorageLive(_3); // scope 0 at $DIR/boxes.rs:12:14: 12:22 - StorageLive(_4); // scope 0 at $DIR/boxes.rs:12:14: 12:22 - _4 = Box(i32); // scope 0 at $DIR/boxes.rs:12:14: 12:22 - (*_4) = const 42_i32; // scope 0 at $DIR/boxes.rs:12:19: 12:21 - _3 = move _4; // scope 0 at $DIR/boxes.rs:12:14: 12:22 - StorageDead(_4); // scope 0 at $DIR/boxes.rs:12:21: 12:22 - _2 = (*_3); // scope 0 at $DIR/boxes.rs:12:13: 12:22 - _1 = Add(move _2, const 0_i32); // scope 0 at $DIR/boxes.rs:12:13: 12:26 - StorageDead(_2); // scope 0 at $DIR/boxes.rs:12:25: 12:26 - drop(_3) -> [return: bb1, unwind: bb2]; // scope 0 at $DIR/boxes.rs:12:26: 12:27 +- _4 = SizeOf(i32); // scope 2 at $DIR/boxes.rs:12:14: 12:22 +- _5 = AlignOf(i32); // scope 2 at $DIR/boxes.rs:12:14: 12:22 +- _6 = alloc::alloc::exchange_malloc(move _4, move _5) -> bb1; // scope 2 at $DIR/boxes.rs:12:14: 12:22 ++ _4 = const 4_usize; // scope 2 at $DIR/boxes.rs:12:14: 12:22 ++ _5 = const 4_usize; // scope 2 at $DIR/boxes.rs:12:14: 12:22 ++ _6 = alloc::alloc::exchange_malloc(const 4_usize, const 4_usize) -> bb1; // scope 2 at $DIR/boxes.rs:12:14: 12:22 + // mir::Constant + // + span: $DIR/boxes.rs:12:14: 12:22 + // + literal: Const { ty: unsafe fn(usize, usize) -> *mut u8 {alloc::alloc::exchange_malloc}, val: Value(Scalar()) } } bb1: { + StorageLive(_7); // scope 0 at $DIR/boxes.rs:12:14: 12:22 + _7 = ShallowInitBox(move _6, i32); // scope 0 at $DIR/boxes.rs:12:14: 12:22 + (*_7) = const 42_i32; // scope 0 at $DIR/boxes.rs:12:19: 12:21 + _3 = move _7; // scope 0 at $DIR/boxes.rs:12:14: 12:22 + StorageDead(_7); // scope 0 at $DIR/boxes.rs:12:21: 12:22 + _2 = (*_3); // scope 0 at $DIR/boxes.rs:12:13: 12:22 + _1 = Add(move _2, const 0_i32); // scope 0 at $DIR/boxes.rs:12:13: 12:26 + StorageDead(_2); // scope 0 at $DIR/boxes.rs:12:25: 12:26 + drop(_3) -> [return: bb2, unwind: bb3]; // scope 0 at $DIR/boxes.rs:12:26: 12:27 + } + + bb2: { StorageDead(_3); // scope 0 at $DIR/boxes.rs:12:26: 12:27 nop; // scope 0 at $DIR/boxes.rs:11:11: 13:2 StorageDead(_1); // scope 0 at $DIR/boxes.rs:13:1: 13:2 return; // scope 0 at $DIR/boxes.rs:13:2: 13:2 } - bb2 (cleanup): { + bb3 (cleanup): { resume; // scope 0 at $DIR/boxes.rs:11:1: 13:2 } } diff --git a/src/test/mir-opt/const_prop/slice_len.main.ConstProp.32bit.diff b/src/test/mir-opt/const_prop/slice_len.main.ConstProp.32bit.diff index f305d602bb..dfb5b98d5c 100644 --- a/src/test/mir-opt/const_prop/slice_len.main.ConstProp.32bit.diff +++ b/src/test/mir-opt/const_prop/slice_len.main.ConstProp.32bit.diff @@ -12,6 +12,7 @@ let mut _7: usize; // in scope 0 at $DIR/slice_len.rs:5:5: 5:33 let mut _8: bool; // in scope 0 at $DIR/slice_len.rs:5:5: 5:33 let mut _9: &[u32; 3]; // in scope 0 at $DIR/slice_len.rs:5:6: 5:19 + let mut _10: &[u32; 3]; // in scope 0 at $DIR/slice_len.rs:5:6: 5:19 bb0: { StorageLive(_1); // scope 0 at $DIR/slice_len.rs:5:5: 5:33 @@ -27,14 +28,16 @@ // + literal: Const { ty: &[u32; 3], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ slice_len[6547]::main), const_param_did: None }, substs_: Some([]), promoted: Some(promoted[0]) }) } _4 = _9; // scope 0 at $DIR/slice_len.rs:5:6: 5:19 _3 = _4; // scope 0 at $DIR/slice_len.rs:5:6: 5:19 + StorageLive(_10); // scope 0 at $DIR/slice_len.rs:5:6: 5:19 + _10 = _3; // scope 0 at $DIR/slice_len.rs:5:6: 5:19 _2 = move _3 as &[u32] (Pointer(Unsize)); // scope 0 at $DIR/slice_len.rs:5:6: 5:19 StorageDead(_3); // scope 0 at $DIR/slice_len.rs:5:18: 5:19 StorageLive(_6); // scope 0 at $DIR/slice_len.rs:5:31: 5:32 _6 = const 1_usize; // scope 0 at $DIR/slice_len.rs:5:31: 5:32 -- _7 = Len((*_2)); // scope 0 at $DIR/slice_len.rs:5:5: 5:33 + _7 = const 3_usize; // scope 0 at $DIR/slice_len.rs:5:5: 5:33 + StorageDead(_10); // scope 0 at $DIR/slice_len.rs:5:5: 5:33 - _8 = Lt(_6, _7); // scope 0 at $DIR/slice_len.rs:5:5: 5:33 - assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, _6) -> bb1; // scope 0 at $DIR/slice_len.rs:5:5: 5:33 -+ _7 = const 3_usize; // scope 0 at $DIR/slice_len.rs:5:5: 5:33 + _8 = const true; // scope 0 at $DIR/slice_len.rs:5:5: 5:33 + assert(const true, "index out of bounds: the length is {} but the index is {}", const 3_usize, const 1_usize) -> bb1; // scope 0 at $DIR/slice_len.rs:5:5: 5:33 } diff --git a/src/test/mir-opt/const_prop/slice_len.main.ConstProp.64bit.diff b/src/test/mir-opt/const_prop/slice_len.main.ConstProp.64bit.diff index f305d602bb..dfb5b98d5c 100644 --- a/src/test/mir-opt/const_prop/slice_len.main.ConstProp.64bit.diff +++ b/src/test/mir-opt/const_prop/slice_len.main.ConstProp.64bit.diff @@ -12,6 +12,7 @@ let mut _7: usize; // in scope 0 at $DIR/slice_len.rs:5:5: 5:33 let mut _8: bool; // in scope 0 at $DIR/slice_len.rs:5:5: 5:33 let mut _9: &[u32; 3]; // in scope 0 at $DIR/slice_len.rs:5:6: 5:19 + let mut _10: &[u32; 3]; // in scope 0 at $DIR/slice_len.rs:5:6: 5:19 bb0: { StorageLive(_1); // scope 0 at $DIR/slice_len.rs:5:5: 5:33 @@ -27,14 +28,16 @@ // + literal: Const { ty: &[u32; 3], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ slice_len[6547]::main), const_param_did: None }, substs_: Some([]), promoted: Some(promoted[0]) }) } _4 = _9; // scope 0 at $DIR/slice_len.rs:5:6: 5:19 _3 = _4; // scope 0 at $DIR/slice_len.rs:5:6: 5:19 + StorageLive(_10); // scope 0 at $DIR/slice_len.rs:5:6: 5:19 + _10 = _3; // scope 0 at $DIR/slice_len.rs:5:6: 5:19 _2 = move _3 as &[u32] (Pointer(Unsize)); // scope 0 at $DIR/slice_len.rs:5:6: 5:19 StorageDead(_3); // scope 0 at $DIR/slice_len.rs:5:18: 5:19 StorageLive(_6); // scope 0 at $DIR/slice_len.rs:5:31: 5:32 _6 = const 1_usize; // scope 0 at $DIR/slice_len.rs:5:31: 5:32 -- _7 = Len((*_2)); // scope 0 at $DIR/slice_len.rs:5:5: 5:33 + _7 = const 3_usize; // scope 0 at $DIR/slice_len.rs:5:5: 5:33 + StorageDead(_10); // scope 0 at $DIR/slice_len.rs:5:5: 5:33 - _8 = Lt(_6, _7); // scope 0 at $DIR/slice_len.rs:5:5: 5:33 - assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, _6) -> bb1; // scope 0 at $DIR/slice_len.rs:5:5: 5:33 -+ _7 = const 3_usize; // scope 0 at $DIR/slice_len.rs:5:5: 5:33 + _8 = const true; // scope 0 at $DIR/slice_len.rs:5:5: 5:33 + assert(const true, "index out of bounds: the length is {} but the index is {}", const 3_usize, const 1_usize) -> bb1; // scope 0 at $DIR/slice_len.rs:5:5: 5:33 } diff --git a/src/test/mir-opt/coverage_graphviz.main.InstrumentCoverage.0.dot b/src/test/mir-opt/coverage_graphviz.main.InstrumentCoverage.0.dot index eeedbb215c..ca0eb7e845 100644 --- a/src/test/mir-opt/coverage_graphviz.main.InstrumentCoverage.0.dot +++ b/src/test/mir-opt/coverage_graphviz.main.InstrumentCoverage.0.dot @@ -2,10 +2,12 @@ digraph Cov_0_3 { graph [fontname="Courier, monospace"]; node [fontname="Courier, monospace"]; edge [fontname="Courier, monospace"]; - bcb2__Cov_0_3 [shape="none", label=<
bcb2
Expression(bcb0 - bcb1) at 13:10-13:10
13:10-13:10: @4[0]: Coverage::Expression(4294967295) = 1 - 2 for $DIR/coverage_graphviz.rs:13:10 - 13:11
bb4: Goto
>]; - bcb1__Cov_0_3 [shape="none", label=<
bcb1
Counter(bcb1) at 12:13-12:18
12:13-12:18: @3[0]: Coverage::Expression(4294967294) = 2 + 0 for $DIR/coverage_graphviz.rs:15:1 - 15:2
Expression(bcb1 + 0) at 15:2-15:2
15:2-15:2: @3.Return: return
bb3: Return
>]; - bcb0__Cov_0_3 [shape="none", label=<
bcb0
Counter(bcb0) at 9:1-11:17
11:12-11:17: @1.Call: _2 = bar() -> [return: bb2, unwind: bb5]
bb0: FalseUnwind
bb1: Call
bb2: SwitchInt
>]; - bcb2__Cov_0_3 -> bcb0__Cov_0_3 [label=<>]; - bcb0__Cov_0_3 -> bcb2__Cov_0_3 [label=]; - bcb0__Cov_0_3 -> bcb1__Cov_0_3 [label=]; + bcb3__Cov_0_3 [shape="none", label=<
bcb3
Counter(bcb3) at 13:10-13:10
13:10-13:10: @5[0]: Coverage::Counter(2) for $DIR/coverage_graphviz.rs:13:10 - 13:11
bb5: Goto
>]; + bcb2__Cov_0_3 [shape="none", label=<
bcb2
Expression(bcb1:(bcb0 + bcb3) - bcb3) at 12:13-12:18
12:13-12:18: @4[0]: Coverage::Expression(4294967293) = 4294967294 + 0 for $DIR/coverage_graphviz.rs:15:1 - 15:2
Expression(bcb2:(bcb1:(bcb0 + bcb3) - bcb3) + 0) at 15:2-15:2
15:2-15:2: @4.Return: return
bb4: Return
>]; + bcb1__Cov_0_3 [shape="none", label=<
bcb1
Expression(bcb0 + bcb3) at 10:5-11:17
11:12-11:17: @2.Call: _2 = bar() -> [return: bb3, unwind: bb6]
bb1: FalseUnwind
bb2: Call
bb3: SwitchInt
>]; + bcb0__Cov_0_3 [shape="none", label=<
bcb0
Counter(bcb0) at 9:1-9:11
bb0: Goto
>]; + bcb3__Cov_0_3 -> bcb1__Cov_0_3 [label=<>]; + bcb1__Cov_0_3 -> bcb3__Cov_0_3 [label=]; + bcb1__Cov_0_3 -> bcb2__Cov_0_3 [label=]; + bcb0__Cov_0_3 -> bcb1__Cov_0_3 [label=<>]; } diff --git a/src/test/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.diff b/src/test/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.diff index 48a37a8496..7695afded3 100644 --- a/src/test/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.diff +++ b/src/test/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.diff @@ -5,7 +5,7 @@ debug s => _1; // in scope 0 at $DIR/deduplicate_blocks.rs:2:36: 2:37 let mut _0: bool; // return place in scope 0 at $DIR/deduplicate_blocks.rs:2:48: 2:52 let mut _2: &[u8]; // in scope 0 at $DIR/deduplicate_blocks.rs:3:11: 3:23 - let mut _3: &str; // in scope 0 at $DIR/deduplicate_blocks.rs:3:11: 3:12 + let mut _3: &str; // in scope 0 at $DIR/deduplicate_blocks.rs:3:11: 3:23 let mut _4: usize; // in scope 0 at $DIR/deduplicate_blocks.rs:5:9: 5:31 let mut _5: bool; // in scope 0 at $DIR/deduplicate_blocks.rs:5:9: 5:31 let mut _6: usize; // in scope 0 at $DIR/deduplicate_blocks.rs:4:9: 4:37 @@ -19,8 +19,8 @@ bb0: { StorageLive(_2); // scope 0 at $DIR/deduplicate_blocks.rs:3:11: 3:23 - StorageLive(_3); // scope 0 at $DIR/deduplicate_blocks.rs:3:11: 3:12 - _3 = _1; // scope 0 at $DIR/deduplicate_blocks.rs:3:11: 3:12 + StorageLive(_3); // scope 0 at $DIR/deduplicate_blocks.rs:3:11: 3:23 + _3 = _1; // scope 0 at $DIR/deduplicate_blocks.rs:3:11: 3:23 StorageLive(_8); // scope 2 at $DIR/deduplicate_blocks.rs:3:11: 3:23 _8 = _3; // scope 2 at $DIR/deduplicate_blocks.rs:3:11: 3:23 - _2 = transmute::<&str, &[u8]>(move _8) -> bb14; // scope 2 at $DIR/deduplicate_blocks.rs:3:11: 3:23 diff --git a/src/test/mir-opt/funky_arms.float_to_exponential_common.ConstProp.diff b/src/test/mir-opt/funky_arms.float_to_exponential_common.ConstProp.diff index fd29e14a04..000bc63432 100644 --- a/src/test/mir-opt/funky_arms.float_to_exponential_common.ConstProp.diff +++ b/src/test/mir-opt/funky_arms.float_to_exponential_common.ConstProp.diff @@ -7,9 +7,9 @@ debug upper => _3; // in scope 0 at $DIR/funky_arms.rs:11:69: 11:74 let mut _0: std::result::Result<(), std::fmt::Error>; // return place in scope 0 at $DIR/funky_arms.rs:11:85: 11:91 let _4: bool; // in scope 0 at $DIR/funky_arms.rs:15:9: 15:19 - let mut _5: &std::fmt::Formatter; // in scope 0 at $DIR/funky_arms.rs:15:22: 15:25 + let mut _5: &std::fmt::Formatter; // in scope 0 at $DIR/funky_arms.rs:15:22: 15:37 let mut _7: std::option::Option; // in scope 0 at $DIR/funky_arms.rs:24:30: 24:45 - let mut _8: &std::fmt::Formatter; // in scope 0 at $DIR/funky_arms.rs:24:30: 24:33 + let mut _8: &std::fmt::Formatter; // in scope 0 at $DIR/funky_arms.rs:24:30: 24:45 let mut _9: isize; // in scope 0 at $DIR/funky_arms.rs:24:12: 24:27 let mut _11: &mut std::fmt::Formatter; // in scope 0 at $DIR/funky_arms.rs:26:43: 26:46 let mut _12: &T; // in scope 0 at $DIR/funky_arms.rs:26:48: 26:51 @@ -36,8 +36,8 @@ bb0: { StorageLive(_4); // scope 0 at $DIR/funky_arms.rs:15:9: 15:19 - StorageLive(_5); // scope 0 at $DIR/funky_arms.rs:15:22: 15:25 - _5 = &(*_1); // scope 0 at $DIR/funky_arms.rs:15:22: 15:25 + StorageLive(_5); // scope 0 at $DIR/funky_arms.rs:15:22: 15:37 + _5 = &(*_1); // scope 0 at $DIR/funky_arms.rs:15:22: 15:37 _4 = Formatter::sign_plus(move _5) -> bb1; // scope 0 at $DIR/funky_arms.rs:15:22: 15:37 // mir::Constant // + span: $DIR/funky_arms.rs:15:26: 15:35 @@ -62,8 +62,8 @@ bb4: { StorageLive(_7); // scope 2 at $DIR/funky_arms.rs:24:30: 24:45 - StorageLive(_8); // scope 2 at $DIR/funky_arms.rs:24:30: 24:33 - _8 = &(*_1); // scope 2 at $DIR/funky_arms.rs:24:30: 24:33 + StorageLive(_8); // scope 2 at $DIR/funky_arms.rs:24:30: 24:45 + _8 = &(*_1); // scope 2 at $DIR/funky_arms.rs:24:30: 24:45 _7 = Formatter::precision(move _8) -> bb5; // scope 2 at $DIR/funky_arms.rs:24:30: 24:45 // mir::Constant // + span: $DIR/funky_arms.rs:24:34: 24:43 diff --git a/src/test/mir-opt/inline/inline_diverging.h.Inline.diff b/src/test/mir-opt/inline/inline_diverging.h.Inline.diff index e2fad5b60e..f810beeeee 100644 --- a/src/test/mir-opt/inline/inline_diverging.h.Inline.diff +++ b/src/test/mir-opt/inline/inline_diverging.h.Inline.diff @@ -47,7 +47,7 @@ + _4 = &_2; // scope 1 at $DIR/inline-diverging.rs:22:5: 22:22 + StorageLive(_9); // scope 1 at $DIR/inline-diverging.rs:22:5: 22:22 + _9 = const (); // scope 1 at $DIR/inline-diverging.rs:22:5: 22:22 -+ goto -> bb1; // scope 4 at $DIR/inline-diverging.rs:22:5: 22:22 ++ goto -> bb1; // scope 5 at $DIR/inline-diverging.rs:22:5: 22:22 } bb1: { diff --git a/src/test/mir-opt/inline/inline_into_box_place.main.Inline.32bit.diff b/src/test/mir-opt/inline/inline_into_box_place.main.Inline.32bit.diff index 0c220eb91a..137a1de522 100644 --- a/src/test/mir-opt/inline/inline_into_box_place.main.Inline.32bit.diff +++ b/src/test/mir-opt/inline/inline_into_box_place.main.Inline.32bit.diff @@ -4,23 +4,37 @@ fn main() -> () { let mut _0: (); // return place in scope 0 at $DIR/inline-into-box-place.rs:7:11: 7:11 let _1: std::boxed::Box>; // in scope 0 at $DIR/inline-into-box-place.rs:8:9: 8:11 - let mut _2: std::boxed::Box>; // in scope 0 at $DIR/inline-into-box-place.rs:8:29: 8:43 - let mut _3: (); // in scope 0 at $DIR/inline-into-box-place.rs:8:42: 8:43 -+ let mut _4: &mut std::vec::Vec; // in scope 0 at $DIR/inline-into-box-place.rs:8:33: 8:43 + let mut _2: usize; // in scope 0 at $DIR/inline-into-box-place.rs:8:29: 8:43 + let mut _3: usize; // in scope 0 at $DIR/inline-into-box-place.rs:8:29: 8:43 + let mut _4: *mut u8; // in scope 0 at $DIR/inline-into-box-place.rs:8:29: 8:43 + let mut _5: std::boxed::Box>; // in scope 0 at $DIR/inline-into-box-place.rs:8:29: 8:43 + let mut _6: (); // in scope 0 at $DIR/inline-into-box-place.rs:8:42: 8:43 ++ let mut _7: &mut std::vec::Vec; // in scope 0 at $DIR/inline-into-box-place.rs:8:33: 8:43 scope 1 { debug _x => _1; // in scope 1 at $DIR/inline-into-box-place.rs:8:9: 8:11 } -+ scope 2 (inlined Vec::::new) { // at $DIR/inline-into-box-place.rs:8:33: 8:43 + scope 2 { + } ++ scope 3 (inlined Vec::::new) { // at $DIR/inline-into-box-place.rs:8:33: 8:43 + } bb0: { StorageLive(_1); // scope 0 at $DIR/inline-into-box-place.rs:8:9: 8:11 - StorageLive(_2); // scope 0 at $DIR/inline-into-box-place.rs:8:29: 8:43 - _2 = Box(std::vec::Vec); // scope 0 at $DIR/inline-into-box-place.rs:8:29: 8:43 -- (*_2) = Vec::::new() -> [return: bb1, unwind: bb4]; // scope 0 at $DIR/inline-into-box-place.rs:8:33: 8:43 -+ StorageLive(_4); // scope 0 at $DIR/inline-into-box-place.rs:8:33: 8:43 -+ _4 = &mut (*_2); // scope 0 at $DIR/inline-into-box-place.rs:8:33: 8:43 -+ ((*_4).0: alloc::raw_vec::RawVec) = const alloc::raw_vec::RawVec:: { ptr: Unique:: { pointer: {0x4 as *const u32}, _marker: PhantomData:: }, cap: 0_usize, alloc: std::alloc::Global }; // scope 2 at $DIR/inline-into-box-place.rs:8:33: 8:43 + _2 = SizeOf(std::vec::Vec); // scope 2 at $DIR/inline-into-box-place.rs:8:29: 8:43 + _3 = AlignOf(std::vec::Vec); // scope 2 at $DIR/inline-into-box-place.rs:8:29: 8:43 + _4 = alloc::alloc::exchange_malloc(move _2, move _3) -> bb1; // scope 2 at $DIR/inline-into-box-place.rs:8:29: 8:43 + // mir::Constant + // + span: $DIR/inline-into-box-place.rs:8:29: 8:43 + // + literal: Const { ty: unsafe fn(usize, usize) -> *mut u8 {alloc::alloc::exchange_malloc}, val: Value(Scalar()) } + } + + bb1: { + StorageLive(_5); // scope 0 at $DIR/inline-into-box-place.rs:8:29: 8:43 + _5 = ShallowInitBox(move _4, std::vec::Vec); // scope 0 at $DIR/inline-into-box-place.rs:8:29: 8:43 +- (*_5) = Vec::::new() -> [return: bb2, unwind: bb5]; // scope 0 at $DIR/inline-into-box-place.rs:8:33: 8:43 ++ StorageLive(_7); // scope 0 at $DIR/inline-into-box-place.rs:8:33: 8:43 ++ _7 = &mut (*_5); // scope 0 at $DIR/inline-into-box-place.rs:8:33: 8:43 ++ ((*_7).0: alloc::raw_vec::RawVec) = const alloc::raw_vec::RawVec:: { ptr: Unique:: { pointer: {0x4 as *const u32}, _marker: PhantomData:: }, cap: 0_usize, alloc: std::alloc::Global }; // scope 3 at $DIR/inline-into-box-place.rs:8:33: 8:43 + // ty::Const + // + ty: alloc::raw_vec::RawVec + // + val: Value(ByRef { alloc: Allocation { bytes: [4, 0, 0, 0, 0, 0, 0, 0], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [255], len: Size { raw: 8 } }, align: Align { pow2: 2 }, mutability: Not, extra: () }, offset: Size { raw: 0 } }) @@ -30,32 +44,32 @@ - // + literal: Const { ty: fn() -> std::vec::Vec {std::vec::Vec::::new}, val: Value(Scalar()) } - } - -- bb1: { +- bb2: { + // + span: $DIR/inline-into-box-place.rs:8:33: 8:43 + // + user_ty: UserType(0) + // + literal: Const { ty: alloc::raw_vec::RawVec, val: Value(ByRef { alloc: Allocation { bytes: [4, 0, 0, 0, 0, 0, 0, 0], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [255], len: Size { raw: 8 } }, align: Align { pow2: 2 }, mutability: Not, extra: () }, offset: Size { raw: 0 } }) } -+ ((*_4).1: usize) = const 0_usize; // scope 2 at $DIR/inline-into-box-place.rs:8:33: 8:43 -+ StorageDead(_4); // scope 0 at $DIR/inline-into-box-place.rs:8:33: 8:43 - _1 = move _2; // scope 0 at $DIR/inline-into-box-place.rs:8:29: 8:43 - StorageDead(_2); // scope 0 at $DIR/inline-into-box-place.rs:8:42: 8:43 ++ ((*_7).1: usize) = const 0_usize; // scope 3 at $DIR/inline-into-box-place.rs:8:33: 8:43 ++ StorageDead(_7); // scope 0 at $DIR/inline-into-box-place.rs:8:33: 8:43 + _1 = move _5; // scope 0 at $DIR/inline-into-box-place.rs:8:29: 8:43 + StorageDead(_5); // scope 0 at $DIR/inline-into-box-place.rs:8:42: 8:43 _0 = const (); // scope 0 at $DIR/inline-into-box-place.rs:7:11: 9:2 -- drop(_1) -> [return: bb2, unwind: bb3]; // scope 0 at $DIR/inline-into-box-place.rs:9:1: 9:2 -+ drop(_1) -> [return: bb1, unwind: bb2]; // scope 0 at $DIR/inline-into-box-place.rs:9:1: 9:2 +- drop(_1) -> [return: bb3, unwind: bb4]; // scope 0 at $DIR/inline-into-box-place.rs:9:1: 9:2 ++ drop(_1) -> [return: bb2, unwind: bb3]; // scope 0 at $DIR/inline-into-box-place.rs:9:1: 9:2 } -- bb2: { -+ bb1: { +- bb3: { ++ bb2: { StorageDead(_1); // scope 0 at $DIR/inline-into-box-place.rs:9:1: 9:2 return; // scope 0 at $DIR/inline-into-box-place.rs:9:2: 9:2 } -- bb3 (cleanup): { -+ bb2 (cleanup): { +- bb4 (cleanup): { ++ bb3 (cleanup): { resume; // scope 0 at $DIR/inline-into-box-place.rs:7:1: 9:2 - } - -- bb4 (cleanup): { -- _3 = alloc::alloc::box_free::, std::alloc::Global>(move (_2.0: std::ptr::Unique>), move (_2.1: std::alloc::Global)) -> bb3; // scope 0 at $DIR/inline-into-box-place.rs:8:42: 8:43 +- bb5 (cleanup): { +- _6 = alloc::alloc::box_free::, std::alloc::Global>(move (_5.0: std::ptr::Unique>), move (_5.1: std::alloc::Global)) -> bb4; // scope 0 at $DIR/inline-into-box-place.rs:8:42: 8:43 - // mir::Constant - // + span: $DIR/inline-into-box-place.rs:8:42: 8:43 - // + literal: Const { ty: unsafe fn(std::ptr::Unique>, std::alloc::Global) {alloc::alloc::box_free::, std::alloc::Global>}, val: Value(Scalar()) } diff --git a/src/test/mir-opt/inline/inline_into_box_place.main.Inline.64bit.diff b/src/test/mir-opt/inline/inline_into_box_place.main.Inline.64bit.diff index 7f3a72ee5a..26327d0557 100644 --- a/src/test/mir-opt/inline/inline_into_box_place.main.Inline.64bit.diff +++ b/src/test/mir-opt/inline/inline_into_box_place.main.Inline.64bit.diff @@ -4,23 +4,37 @@ fn main() -> () { let mut _0: (); // return place in scope 0 at $DIR/inline-into-box-place.rs:7:11: 7:11 let _1: std::boxed::Box>; // in scope 0 at $DIR/inline-into-box-place.rs:8:9: 8:11 - let mut _2: std::boxed::Box>; // in scope 0 at $DIR/inline-into-box-place.rs:8:29: 8:43 - let mut _3: (); // in scope 0 at $DIR/inline-into-box-place.rs:8:42: 8:43 -+ let mut _4: &mut std::vec::Vec; // in scope 0 at $DIR/inline-into-box-place.rs:8:33: 8:43 + let mut _2: usize; // in scope 0 at $DIR/inline-into-box-place.rs:8:29: 8:43 + let mut _3: usize; // in scope 0 at $DIR/inline-into-box-place.rs:8:29: 8:43 + let mut _4: *mut u8; // in scope 0 at $DIR/inline-into-box-place.rs:8:29: 8:43 + let mut _5: std::boxed::Box>; // in scope 0 at $DIR/inline-into-box-place.rs:8:29: 8:43 + let mut _6: (); // in scope 0 at $DIR/inline-into-box-place.rs:8:42: 8:43 ++ let mut _7: &mut std::vec::Vec; // in scope 0 at $DIR/inline-into-box-place.rs:8:33: 8:43 scope 1 { debug _x => _1; // in scope 1 at $DIR/inline-into-box-place.rs:8:9: 8:11 } -+ scope 2 (inlined Vec::::new) { // at $DIR/inline-into-box-place.rs:8:33: 8:43 + scope 2 { + } ++ scope 3 (inlined Vec::::new) { // at $DIR/inline-into-box-place.rs:8:33: 8:43 + } bb0: { StorageLive(_1); // scope 0 at $DIR/inline-into-box-place.rs:8:9: 8:11 - StorageLive(_2); // scope 0 at $DIR/inline-into-box-place.rs:8:29: 8:43 - _2 = Box(std::vec::Vec); // scope 0 at $DIR/inline-into-box-place.rs:8:29: 8:43 -- (*_2) = Vec::::new() -> [return: bb1, unwind: bb4]; // scope 0 at $DIR/inline-into-box-place.rs:8:33: 8:43 -+ StorageLive(_4); // scope 0 at $DIR/inline-into-box-place.rs:8:33: 8:43 -+ _4 = &mut (*_2); // scope 0 at $DIR/inline-into-box-place.rs:8:33: 8:43 -+ ((*_4).0: alloc::raw_vec::RawVec) = const alloc::raw_vec::RawVec:: { ptr: Unique:: { pointer: {0x4 as *const u32}, _marker: PhantomData:: }, cap: 0_usize, alloc: std::alloc::Global }; // scope 2 at $DIR/inline-into-box-place.rs:8:33: 8:43 + _2 = SizeOf(std::vec::Vec); // scope 2 at $DIR/inline-into-box-place.rs:8:29: 8:43 + _3 = AlignOf(std::vec::Vec); // scope 2 at $DIR/inline-into-box-place.rs:8:29: 8:43 + _4 = alloc::alloc::exchange_malloc(move _2, move _3) -> bb1; // scope 2 at $DIR/inline-into-box-place.rs:8:29: 8:43 + // mir::Constant + // + span: $DIR/inline-into-box-place.rs:8:29: 8:43 + // + literal: Const { ty: unsafe fn(usize, usize) -> *mut u8 {alloc::alloc::exchange_malloc}, val: Value(Scalar()) } + } + + bb1: { + StorageLive(_5); // scope 0 at $DIR/inline-into-box-place.rs:8:29: 8:43 + _5 = ShallowInitBox(move _4, std::vec::Vec); // scope 0 at $DIR/inline-into-box-place.rs:8:29: 8:43 +- (*_5) = Vec::::new() -> [return: bb2, unwind: bb5]; // scope 0 at $DIR/inline-into-box-place.rs:8:33: 8:43 ++ StorageLive(_7); // scope 0 at $DIR/inline-into-box-place.rs:8:33: 8:43 ++ _7 = &mut (*_5); // scope 0 at $DIR/inline-into-box-place.rs:8:33: 8:43 ++ ((*_7).0: alloc::raw_vec::RawVec) = const alloc::raw_vec::RawVec:: { ptr: Unique:: { pointer: {0x4 as *const u32}, _marker: PhantomData:: }, cap: 0_usize, alloc: std::alloc::Global }; // scope 3 at $DIR/inline-into-box-place.rs:8:33: 8:43 + // ty::Const + // + ty: alloc::raw_vec::RawVec + // + val: Value(ByRef { alloc: Allocation { bytes: [4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [65535], len: Size { raw: 16 } }, align: Align { pow2: 3 }, mutability: Not, extra: () }, offset: Size { raw: 0 } }) @@ -30,32 +44,32 @@ - // + literal: Const { ty: fn() -> std::vec::Vec {std::vec::Vec::::new}, val: Value(Scalar()) } - } - -- bb1: { +- bb2: { + // + span: $DIR/inline-into-box-place.rs:8:33: 8:43 + // + user_ty: UserType(0) + // + literal: Const { ty: alloc::raw_vec::RawVec, val: Value(ByRef { alloc: Allocation { bytes: [4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [65535], len: Size { raw: 16 } }, align: Align { pow2: 3 }, mutability: Not, extra: () }, offset: Size { raw: 0 } }) } -+ ((*_4).1: usize) = const 0_usize; // scope 2 at $DIR/inline-into-box-place.rs:8:33: 8:43 -+ StorageDead(_4); // scope 0 at $DIR/inline-into-box-place.rs:8:33: 8:43 - _1 = move _2; // scope 0 at $DIR/inline-into-box-place.rs:8:29: 8:43 - StorageDead(_2); // scope 0 at $DIR/inline-into-box-place.rs:8:42: 8:43 ++ ((*_7).1: usize) = const 0_usize; // scope 3 at $DIR/inline-into-box-place.rs:8:33: 8:43 ++ StorageDead(_7); // scope 0 at $DIR/inline-into-box-place.rs:8:33: 8:43 + _1 = move _5; // scope 0 at $DIR/inline-into-box-place.rs:8:29: 8:43 + StorageDead(_5); // scope 0 at $DIR/inline-into-box-place.rs:8:42: 8:43 _0 = const (); // scope 0 at $DIR/inline-into-box-place.rs:7:11: 9:2 -- drop(_1) -> [return: bb2, unwind: bb3]; // scope 0 at $DIR/inline-into-box-place.rs:9:1: 9:2 -+ drop(_1) -> [return: bb1, unwind: bb2]; // scope 0 at $DIR/inline-into-box-place.rs:9:1: 9:2 +- drop(_1) -> [return: bb3, unwind: bb4]; // scope 0 at $DIR/inline-into-box-place.rs:9:1: 9:2 ++ drop(_1) -> [return: bb2, unwind: bb3]; // scope 0 at $DIR/inline-into-box-place.rs:9:1: 9:2 } -- bb2: { -+ bb1: { +- bb3: { ++ bb2: { StorageDead(_1); // scope 0 at $DIR/inline-into-box-place.rs:9:1: 9:2 return; // scope 0 at $DIR/inline-into-box-place.rs:9:2: 9:2 } -- bb3 (cleanup): { -+ bb2 (cleanup): { +- bb4 (cleanup): { ++ bb3 (cleanup): { resume; // scope 0 at $DIR/inline-into-box-place.rs:7:1: 9:2 - } - -- bb4 (cleanup): { -- _3 = alloc::alloc::box_free::, std::alloc::Global>(move (_2.0: std::ptr::Unique>), move (_2.1: std::alloc::Global)) -> bb3; // scope 0 at $DIR/inline-into-box-place.rs:8:42: 8:43 +- bb5 (cleanup): { +- _6 = alloc::alloc::box_free::, std::alloc::Global>(move (_5.0: std::ptr::Unique>), move (_5.1: std::alloc::Global)) -> bb4; // scope 0 at $DIR/inline-into-box-place.rs:8:42: 8:43 - // mir::Constant - // + span: $DIR/inline-into-box-place.rs:8:42: 8:43 - // + literal: Const { ty: unsafe fn(std::ptr::Unique>, std::alloc::Global) {alloc::alloc::box_free::, std::alloc::Global>}, val: Value(Scalar()) } diff --git a/src/test/mir-opt/inline/inline_shims.clone.Inline.diff b/src/test/mir-opt/inline/inline_shims.clone.Inline.diff index 3bdd4f4ff5..7379d5f219 100644 --- a/src/test/mir-opt/inline/inline_shims.clone.Inline.diff +++ b/src/test/mir-opt/inline/inline_shims.clone.Inline.diff @@ -4,13 +4,13 @@ fn clone(_1: fn(A, B)) -> fn(A, B) { debug f => _1; // in scope 0 at $DIR/inline-shims.rs:5:20: 5:21 let mut _0: fn(A, B); // return place in scope 0 at $DIR/inline-shims.rs:5:36: 5:44 - let mut _2: &fn(A, B); // in scope 0 at $DIR/inline-shims.rs:6:5: 6:6 + let mut _2: &fn(A, B); // in scope 0 at $DIR/inline-shims.rs:6:5: 6:14 + scope 1 (inlined ::clone - shim(fn(A, B))) { // at $DIR/inline-shims.rs:6:5: 6:14 + } bb0: { - StorageLive(_2); // scope 0 at $DIR/inline-shims.rs:6:5: 6:6 - _2 = &_1; // scope 0 at $DIR/inline-shims.rs:6:5: 6:6 + StorageLive(_2); // scope 0 at $DIR/inline-shims.rs:6:5: 6:14 + _2 = &_1; // scope 0 at $DIR/inline-shims.rs:6:5: 6:14 - _0 = ::clone(move _2) -> bb1; // scope 0 at $DIR/inline-shims.rs:6:5: 6:14 - // mir::Constant - // + span: $DIR/inline-shims.rs:6:7: 6:12 diff --git a/src/test/mir-opt/inline/inline_trait_method.test.Inline.after.mir b/src/test/mir-opt/inline/inline_trait_method.test.Inline.after.mir index eada5ac134..0be979901a 100644 --- a/src/test/mir-opt/inline/inline_trait_method.test.Inline.after.mir +++ b/src/test/mir-opt/inline/inline_trait_method.test.Inline.after.mir @@ -3,11 +3,11 @@ fn test(_1: &dyn X) -> u32 { debug x => _1; // in scope 0 at $DIR/inline-trait-method.rs:8:9: 8:10 let mut _0: u32; // return place in scope 0 at $DIR/inline-trait-method.rs:8:23: 8:26 - let mut _2: &dyn X; // in scope 0 at $DIR/inline-trait-method.rs:9:5: 9:6 + let mut _2: &dyn X; // in scope 0 at $DIR/inline-trait-method.rs:9:5: 9:10 bb0: { - StorageLive(_2); // scope 0 at $DIR/inline-trait-method.rs:9:5: 9:6 - _2 = &(*_1); // scope 0 at $DIR/inline-trait-method.rs:9:5: 9:6 + StorageLive(_2); // scope 0 at $DIR/inline-trait-method.rs:9:5: 9:10 + _2 = &(*_1); // scope 0 at $DIR/inline-trait-method.rs:9:5: 9:10 _0 = ::y(move _2) -> bb1; // scope 0 at $DIR/inline-trait-method.rs:9:5: 9:10 // mir::Constant // + span: $DIR/inline-trait-method.rs:9:7: 9:8 diff --git a/src/test/mir-opt/inline/issue_58867_inline_as_ref_as_mut.a.Inline.after.mir b/src/test/mir-opt/inline/issue_58867_inline_as_ref_as_mut.a.Inline.after.mir index 651855f802..1b5153daa8 100644 --- a/src/test/mir-opt/inline/issue_58867_inline_as_ref_as_mut.a.Inline.after.mir +++ b/src/test/mir-opt/inline/issue_58867_inline_as_ref_as_mut.a.Inline.after.mir @@ -5,7 +5,7 @@ fn a(_1: &mut [T]) -> &mut [T] { let mut _0: &mut [T]; // return place in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:2:29: 2:37 let mut _2: &mut [T]; // in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:3:5: 3:15 let mut _3: &mut [T]; // in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:3:5: 3:15 - let mut _4: &mut [T]; // in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:3:5: 3:6 + let mut _4: &mut [T]; // in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:3:5: 3:15 scope 1 (inlined <[T] as AsMut<[T]>>::as_mut) { // at $DIR/issue-58867-inline-as-ref-as-mut.rs:3:5: 3:15 debug self => _4; // in scope 1 at $DIR/issue-58867-inline-as-ref-as-mut.rs:3:5: 3:15 let mut _5: &mut [T]; // in scope 1 at $DIR/issue-58867-inline-as-ref-as-mut.rs:3:5: 3:15 @@ -14,8 +14,8 @@ fn a(_1: &mut [T]) -> &mut [T] { bb0: { StorageLive(_2); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:3:5: 3:15 StorageLive(_3); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:3:5: 3:15 - StorageLive(_4); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:3:5: 3:6 - _4 = &mut (*_1); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:3:5: 3:6 + StorageLive(_4); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:3:5: 3:15 + _4 = &mut (*_1); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:3:5: 3:15 StorageLive(_5); // scope 1 at $DIR/issue-58867-inline-as-ref-as-mut.rs:3:5: 3:15 _5 = &mut (*_4); // scope 1 at $DIR/issue-58867-inline-as-ref-as-mut.rs:3:5: 3:15 _3 = &mut (*_5); // scope 1 at $DIR/issue-58867-inline-as-ref-as-mut.rs:3:5: 3:15 diff --git a/src/test/mir-opt/inline/issue_58867_inline_as_ref_as_mut.b.Inline.after.mir b/src/test/mir-opt/inline/issue_58867_inline_as_ref_as_mut.b.Inline.after.mir index c67ea7e00b..257ddec780 100644 --- a/src/test/mir-opt/inline/issue_58867_inline_as_ref_as_mut.b.Inline.after.mir +++ b/src/test/mir-opt/inline/issue_58867_inline_as_ref_as_mut.b.Inline.after.mir @@ -5,7 +5,7 @@ fn b(_1: &mut Box) -> &mut T { let mut _0: &mut T; // return place in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:7:32: 7:38 let mut _2: &mut T; // in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:8:5: 8:15 let mut _3: &mut T; // in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:8:5: 8:15 - let mut _4: &mut std::boxed::Box; // in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:8:5: 8:6 + let mut _4: &mut std::boxed::Box; // in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:8:5: 8:15 scope 1 (inlined as AsMut>::as_mut) { // at $DIR/issue-58867-inline-as-ref-as-mut.rs:8:5: 8:15 debug self => _4; // in scope 1 at $DIR/issue-58867-inline-as-ref-as-mut.rs:8:5: 8:15 let mut _5: &mut T; // in scope 1 at $DIR/issue-58867-inline-as-ref-as-mut.rs:8:5: 8:15 @@ -15,8 +15,8 @@ fn b(_1: &mut Box) -> &mut T { bb0: { StorageLive(_2); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:8:5: 8:15 StorageLive(_3); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:8:5: 8:15 - StorageLive(_4); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:8:5: 8:6 - _4 = &mut (*_1); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:8:5: 8:6 + StorageLive(_4); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:8:5: 8:15 + _4 = &mut (*_1); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:8:5: 8:15 StorageLive(_5); // scope 1 at $DIR/issue-58867-inline-as-ref-as-mut.rs:8:5: 8:15 StorageLive(_6); // scope 1 at $DIR/issue-58867-inline-as-ref-as-mut.rs:8:5: 8:15 _6 = &mut (*(*_4)); // scope 1 at $DIR/issue-58867-inline-as-ref-as-mut.rs:8:5: 8:15 diff --git a/src/test/mir-opt/inline/issue_58867_inline_as_ref_as_mut.c.Inline.after.mir b/src/test/mir-opt/inline/issue_58867_inline_as_ref_as_mut.c.Inline.after.mir index 16fae453ac..9817e8cd5f 100644 --- a/src/test/mir-opt/inline/issue_58867_inline_as_ref_as_mut.c.Inline.after.mir +++ b/src/test/mir-opt/inline/issue_58867_inline_as_ref_as_mut.c.Inline.after.mir @@ -4,15 +4,15 @@ fn c(_1: &[T]) -> &[T] { debug x => _1; // in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:12:13: 12:14 let mut _0: &[T]; // return place in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:12:25: 12:29 let _2: &[T]; // in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:13:5: 13:15 - let mut _3: &[T]; // in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:13:5: 13:6 + let mut _3: &[T]; // in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:13:5: 13:15 scope 1 (inlined <[T] as AsRef<[T]>>::as_ref) { // at $DIR/issue-58867-inline-as-ref-as-mut.rs:13:5: 13:15 debug self => _3; // in scope 1 at $DIR/issue-58867-inline-as-ref-as-mut.rs:13:5: 13:15 } bb0: { StorageLive(_2); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:13:5: 13:15 - StorageLive(_3); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:13:5: 13:6 - _3 = &(*_1); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:13:5: 13:6 + StorageLive(_3); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:13:5: 13:15 + _3 = &(*_1); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:13:5: 13:15 _2 = _3; // scope 1 at $DIR/issue-58867-inline-as-ref-as-mut.rs:13:5: 13:15 _0 = &(*_2); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:13:5: 13:15 StorageDead(_3); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:13:14: 13:15 diff --git a/src/test/mir-opt/inline/issue_58867_inline_as_ref_as_mut.d.Inline.after.mir b/src/test/mir-opt/inline/issue_58867_inline_as_ref_as_mut.d.Inline.after.mir index e9ca7095a4..e49c91581b 100644 --- a/src/test/mir-opt/inline/issue_58867_inline_as_ref_as_mut.d.Inline.after.mir +++ b/src/test/mir-opt/inline/issue_58867_inline_as_ref_as_mut.d.Inline.after.mir @@ -4,15 +4,15 @@ fn d(_1: &Box) -> &T { debug x => _1; // in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:17:13: 17:14 let mut _0: &T; // return place in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:17:28: 17:30 let _2: &T; // in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:18:5: 18:15 - let mut _3: &std::boxed::Box; // in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:18:5: 18:6 + let mut _3: &std::boxed::Box; // in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:18:5: 18:15 scope 1 (inlined as AsRef>::as_ref) { // at $DIR/issue-58867-inline-as-ref-as-mut.rs:18:5: 18:15 debug self => _3; // in scope 1 at $DIR/issue-58867-inline-as-ref-as-mut.rs:18:5: 18:15 } bb0: { StorageLive(_2); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:18:5: 18:15 - StorageLive(_3); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:18:5: 18:6 - _3 = &(*_1); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:18:5: 18:6 + StorageLive(_3); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:18:5: 18:15 + _3 = &(*_1); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:18:5: 18:15 _2 = &(*(*_3)); // scope 1 at $DIR/issue-58867-inline-as-ref-as-mut.rs:18:5: 18:15 _0 = &(*_2); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:18:5: 18:15 StorageDead(_3); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:18:14: 18:15 diff --git a/src/test/mir-opt/instrument_coverage.main.InstrumentCoverage.diff b/src/test/mir-opt/instrument_coverage.main.InstrumentCoverage.diff index 3539fc8b48..34ba7dfdcc 100644 --- a/src/test/mir-opt/instrument_coverage.main.InstrumentCoverage.diff +++ b/src/test/mir-opt/instrument_coverage.main.InstrumentCoverage.diff @@ -8,38 +8,43 @@ let mut _3: !; // in scope 0 at /the/src/instrument_coverage.rs:12:18: 14:10 bb0: { -+ Coverage::Counter(1) for /the/src/instrument_coverage.rs:10:1 - 12:17; // scope 0 at /the/src/instrument_coverage.rs:11:5: 15:6 - falseUnwind -> [real: bb1, cleanup: bb5]; // scope 0 at /the/src/instrument_coverage.rs:11:5: 15:6 ++ Coverage::Counter(1) for /the/src/instrument_coverage.rs:10:1 - 10:11; // scope 0 at /the/src/instrument_coverage.rs:11:5: 15:6 + goto -> bb1; // scope 0 at /the/src/instrument_coverage.rs:11:5: 15:6 } bb1: { ++ Coverage::Expression(4294967295) = 1 + 2 for /the/src/instrument_coverage.rs:11:5 - 12:17; // scope 0 at /the/src/instrument_coverage.rs:11:5: 15:6 + falseUnwind -> [real: bb2, cleanup: bb6]; // scope 0 at /the/src/instrument_coverage.rs:11:5: 15:6 + } + + bb2: { StorageLive(_2); // scope 0 at /the/src/instrument_coverage.rs:12:12: 12:17 - _2 = bar() -> [return: bb2, unwind: bb5]; // scope 0 at /the/src/instrument_coverage.rs:12:12: 12:17 + _2 = bar() -> [return: bb3, unwind: bb6]; // scope 0 at /the/src/instrument_coverage.rs:12:12: 12:17 // mir::Constant // + span: /the/src/instrument_coverage.rs:12:12: 12:15 // + literal: Const { ty: fn() -> bool {bar}, val: Value(Scalar()) } } - bb2: { - switchInt(move _2) -> [false: bb4, otherwise: bb3]; // scope 0 at /the/src/instrument_coverage.rs:12:12: 12:17 + bb3: { + switchInt(move _2) -> [false: bb5, otherwise: bb4]; // scope 0 at /the/src/instrument_coverage.rs:12:12: 12:17 } - bb3: { -+ Coverage::Expression(4294967294) = 2 + 0 for /the/src/instrument_coverage.rs:16:1 - 16:2; // scope 0 at /the/src/instrument_coverage.rs:16:2: 16:2 -+ Coverage::Counter(2) for /the/src/instrument_coverage.rs:13:13 - 13:18; // scope 0 at /the/src/instrument_coverage.rs:16:2: 16:2 + bb4: { ++ Coverage::Expression(4294967293) = 4294967294 + 0 for /the/src/instrument_coverage.rs:16:1 - 16:2; // scope 0 at /the/src/instrument_coverage.rs:16:2: 16:2 ++ Coverage::Expression(4294967294) = 4294967295 - 2 for /the/src/instrument_coverage.rs:13:13 - 13:18; // scope 0 at /the/src/instrument_coverage.rs:16:2: 16:2 _0 = const (); // scope 0 at /the/src/instrument_coverage.rs:13:13: 13:18 StorageDead(_2); // scope 0 at /the/src/instrument_coverage.rs:14:9: 14:10 return; // scope 0 at /the/src/instrument_coverage.rs:16:2: 16:2 } - bb4: { -+ Coverage::Expression(4294967295) = 1 - 2 for /the/src/instrument_coverage.rs:14:10 - 14:11; // scope 0 at /the/src/instrument_coverage.rs:11:5: 15:6 + bb5: { ++ Coverage::Counter(2) for /the/src/instrument_coverage.rs:14:10 - 14:11; // scope 0 at /the/src/instrument_coverage.rs:11:5: 15:6 _1 = const (); // scope 0 at /the/src/instrument_coverage.rs:14:10: 14:10 StorageDead(_2); // scope 0 at /the/src/instrument_coverage.rs:14:9: 14:10 - goto -> bb0; // scope 0 at /the/src/instrument_coverage.rs:11:5: 15:6 + goto -> bb1; // scope 0 at /the/src/instrument_coverage.rs:11:5: 15:6 } - bb5 (cleanup): { + bb6 (cleanup): { resume; // scope 0 at /the/src/instrument_coverage.rs:10:1: 16:2 } } diff --git a/src/test/mir-opt/issue_62289.test.ElaborateDrops.before.mir b/src/test/mir-opt/issue_62289.test.ElaborateDrops.before.mir index 95efa74289..dde49c77ae 100644 --- a/src/test/mir-opt/issue_62289.test.ElaborateDrops.before.mir +++ b/src/test/mir-opt/issue_62289.test.ElaborateDrops.before.mir @@ -3,106 +3,120 @@ fn test() -> Option> { let mut _0: std::option::Option>; // return place in scope 0 at $DIR/issue-62289.rs:8:14: 8:30 let mut _1: std::boxed::Box; // in scope 0 at $DIR/issue-62289.rs:9:10: 9:21 - let mut _2: std::boxed::Box; // in scope 0 at $DIR/issue-62289.rs:9:10: 9:21 - let mut _3: std::ops::ControlFlow, u32>; // in scope 0 at $DIR/issue-62289.rs:9:15: 9:20 - let mut _4: std::option::Option; // in scope 0 at $DIR/issue-62289.rs:9:15: 9:19 - let mut _5: isize; // in scope 0 at $DIR/issue-62289.rs:9:19: 9:20 - let _6: std::option::Option; // in scope 0 at $DIR/issue-62289.rs:9:19: 9:20 - let mut _7: !; // in scope 0 at $DIR/issue-62289.rs:9:19: 9:20 - let mut _8: std::option::Option; // in scope 0 at $DIR/issue-62289.rs:9:19: 9:20 - let _9: u32; // in scope 0 at $DIR/issue-62289.rs:9:15: 9:20 + let mut _2: usize; // in scope 0 at $DIR/issue-62289.rs:9:10: 9:21 + let mut _3: usize; // in scope 0 at $DIR/issue-62289.rs:9:10: 9:21 + let mut _4: *mut u8; // in scope 0 at $DIR/issue-62289.rs:9:10: 9:21 + let mut _5: std::boxed::Box; // in scope 0 at $DIR/issue-62289.rs:9:10: 9:21 + let mut _6: std::ops::ControlFlow, u32>; // in scope 0 at $DIR/issue-62289.rs:9:15: 9:20 + let mut _7: std::option::Option; // in scope 0 at $DIR/issue-62289.rs:9:15: 9:19 + let mut _8: isize; // in scope 0 at $DIR/issue-62289.rs:9:19: 9:20 + let _9: std::option::Option; // in scope 0 at $DIR/issue-62289.rs:9:19: 9:20 + let mut _10: !; // in scope 0 at $DIR/issue-62289.rs:9:19: 9:20 + let mut _11: std::option::Option; // in scope 0 at $DIR/issue-62289.rs:9:19: 9:20 + let _12: u32; // in scope 0 at $DIR/issue-62289.rs:9:15: 9:20 scope 1 { - debug residual => _6; // in scope 1 at $DIR/issue-62289.rs:9:19: 9:20 - scope 2 { + } + scope 2 { + debug residual => _9; // in scope 2 at $DIR/issue-62289.rs:9:19: 9:20 + scope 3 { } } - scope 3 { - debug val => _9; // in scope 3 at $DIR/issue-62289.rs:9:15: 9:20 - scope 4 { + scope 4 { + debug val => _12; // in scope 4 at $DIR/issue-62289.rs:9:15: 9:20 + scope 5 { } } bb0: { StorageLive(_1); // scope 0 at $DIR/issue-62289.rs:9:10: 9:21 - StorageLive(_2); // scope 0 at $DIR/issue-62289.rs:9:10: 9:21 - _2 = Box(u32); // scope 0 at $DIR/issue-62289.rs:9:10: 9:21 - StorageLive(_3); // scope 0 at $DIR/issue-62289.rs:9:15: 9:20 - StorageLive(_4); // scope 0 at $DIR/issue-62289.rs:9:15: 9:19 - _4 = Option::::None; // scope 0 at $DIR/issue-62289.rs:9:15: 9:19 - _3 = as Try>::branch(move _4) -> [return: bb1, unwind: bb11]; // scope 0 at $DIR/issue-62289.rs:9:15: 9:20 + _2 = SizeOf(u32); // scope 1 at $DIR/issue-62289.rs:9:10: 9:21 + _3 = AlignOf(u32); // scope 1 at $DIR/issue-62289.rs:9:10: 9:21 + _4 = alloc::alloc::exchange_malloc(move _2, move _3) -> bb1; // scope 1 at $DIR/issue-62289.rs:9:10: 9:21 + // mir::Constant + // + span: $DIR/issue-62289.rs:9:10: 9:21 + // + literal: Const { ty: unsafe fn(usize, usize) -> *mut u8 {alloc::alloc::exchange_malloc}, val: Value(Scalar()) } + } + + bb1: { + StorageLive(_5); // scope 0 at $DIR/issue-62289.rs:9:10: 9:21 + _5 = ShallowInitBox(move _4, u32); // scope 0 at $DIR/issue-62289.rs:9:10: 9:21 + StorageLive(_6); // scope 0 at $DIR/issue-62289.rs:9:15: 9:20 + StorageLive(_7); // scope 0 at $DIR/issue-62289.rs:9:15: 9:19 + _7 = Option::::None; // scope 0 at $DIR/issue-62289.rs:9:15: 9:19 + _6 = as Try>::branch(move _7) -> [return: bb2, unwind: bb12]; // scope 0 at $DIR/issue-62289.rs:9:15: 9:20 // mir::Constant // + span: $DIR/issue-62289.rs:9:15: 9:20 // + literal: Const { ty: fn(std::option::Option) -> std::ops::ControlFlow< as std::ops::Try>::Residual, as std::ops::Try>::Output> { as std::ops::Try>::branch}, val: Value(Scalar()) } } - bb1: { - StorageDead(_4); // scope 0 at $DIR/issue-62289.rs:9:19: 9:20 - _5 = discriminant(_3); // scope 0 at $DIR/issue-62289.rs:9:15: 9:20 - switchInt(move _5) -> [0_isize: bb2, 1_isize: bb4, otherwise: bb3]; // scope 0 at $DIR/issue-62289.rs:9:15: 9:20 - } - bb2: { - StorageLive(_9); // scope 0 at $DIR/issue-62289.rs:9:15: 9:20 - _9 = ((_3 as Continue).0: u32); // scope 0 at $DIR/issue-62289.rs:9:15: 9:20 - (*_2) = _9; // scope 4 at $DIR/issue-62289.rs:9:15: 9:20 - StorageDead(_9); // scope 0 at $DIR/issue-62289.rs:9:19: 9:20 - _1 = move _2; // scope 0 at $DIR/issue-62289.rs:9:10: 9:21 - drop(_2) -> [return: bb6, unwind: bb10]; // scope 0 at $DIR/issue-62289.rs:9:20: 9:21 + StorageDead(_7); // scope 0 at $DIR/issue-62289.rs:9:19: 9:20 + _8 = discriminant(_6); // scope 0 at $DIR/issue-62289.rs:9:15: 9:20 + switchInt(move _8) -> [0_isize: bb3, 1_isize: bb5, otherwise: bb4]; // scope 0 at $DIR/issue-62289.rs:9:15: 9:20 } bb3: { - unreachable; // scope 0 at $DIR/issue-62289.rs:9:15: 9:20 + StorageLive(_12); // scope 0 at $DIR/issue-62289.rs:9:15: 9:20 + _12 = ((_6 as Continue).0: u32); // scope 0 at $DIR/issue-62289.rs:9:15: 9:20 + (*_5) = _12; // scope 5 at $DIR/issue-62289.rs:9:15: 9:20 + StorageDead(_12); // scope 0 at $DIR/issue-62289.rs:9:19: 9:20 + _1 = move _5; // scope 0 at $DIR/issue-62289.rs:9:10: 9:21 + drop(_5) -> [return: bb7, unwind: bb11]; // scope 0 at $DIR/issue-62289.rs:9:20: 9:21 } bb4: { - StorageLive(_6); // scope 0 at $DIR/issue-62289.rs:9:19: 9:20 - _6 = ((_3 as Break).0: std::option::Option); // scope 0 at $DIR/issue-62289.rs:9:19: 9:20 - StorageLive(_8); // scope 2 at $DIR/issue-62289.rs:9:19: 9:20 - _8 = _6; // scope 2 at $DIR/issue-62289.rs:9:19: 9:20 - _0 = > as FromResidual>>::from_residual(move _8) -> [return: bb5, unwind: bb11]; // scope 2 at $DIR/issue-62289.rs:9:15: 9:20 + unreachable; // scope 0 at $DIR/issue-62289.rs:9:15: 9:20 + } + + bb5: { + StorageLive(_9); // scope 0 at $DIR/issue-62289.rs:9:19: 9:20 + _9 = ((_6 as Break).0: std::option::Option); // scope 0 at $DIR/issue-62289.rs:9:19: 9:20 + StorageLive(_11); // scope 3 at $DIR/issue-62289.rs:9:19: 9:20 + _11 = _9; // scope 3 at $DIR/issue-62289.rs:9:19: 9:20 + _0 = > as FromResidual>>::from_residual(move _11) -> [return: bb6, unwind: bb12]; // scope 3 at $DIR/issue-62289.rs:9:15: 9:20 // mir::Constant // + span: $DIR/issue-62289.rs:9:19: 9:20 // + literal: Const { ty: fn(std::option::Option) -> std::option::Option> {> as std::ops::FromResidual>>::from_residual}, val: Value(Scalar()) } } - bb5: { - StorageDead(_8); // scope 2 at $DIR/issue-62289.rs:9:19: 9:20 - StorageDead(_6); // scope 0 at $DIR/issue-62289.rs:9:19: 9:20 - drop(_2) -> bb8; // scope 0 at $DIR/issue-62289.rs:9:20: 9:21 - } - bb6: { - StorageDead(_2); // scope 0 at $DIR/issue-62289.rs:9:20: 9:21 - _0 = Option::>::Some(move _1); // scope 0 at $DIR/issue-62289.rs:9:5: 9:22 - drop(_1) -> bb7; // scope 0 at $DIR/issue-62289.rs:9:21: 9:22 + StorageDead(_11); // scope 3 at $DIR/issue-62289.rs:9:19: 9:20 + StorageDead(_9); // scope 0 at $DIR/issue-62289.rs:9:19: 9:20 + drop(_5) -> bb9; // scope 0 at $DIR/issue-62289.rs:9:20: 9:21 } bb7: { - StorageDead(_1); // scope 0 at $DIR/issue-62289.rs:9:21: 9:22 - StorageDead(_3); // scope 0 at $DIR/issue-62289.rs:10:1: 10:2 - goto -> bb9; // scope 0 at $DIR/issue-62289.rs:10:2: 10:2 + StorageDead(_5); // scope 0 at $DIR/issue-62289.rs:9:20: 9:21 + _0 = Option::>::Some(move _1); // scope 0 at $DIR/issue-62289.rs:9:5: 9:22 + drop(_1) -> bb8; // scope 0 at $DIR/issue-62289.rs:9:21: 9:22 } bb8: { - StorageDead(_2); // scope 0 at $DIR/issue-62289.rs:9:20: 9:21 StorageDead(_1); // scope 0 at $DIR/issue-62289.rs:9:21: 9:22 - StorageDead(_3); // scope 0 at $DIR/issue-62289.rs:10:1: 10:2 - goto -> bb9; // scope 0 at $DIR/issue-62289.rs:10:2: 10:2 + StorageDead(_6); // scope 0 at $DIR/issue-62289.rs:10:1: 10:2 + goto -> bb10; // scope 0 at $DIR/issue-62289.rs:10:2: 10:2 } bb9: { + StorageDead(_5); // scope 0 at $DIR/issue-62289.rs:9:20: 9:21 + StorageDead(_1); // scope 0 at $DIR/issue-62289.rs:9:21: 9:22 + StorageDead(_6); // scope 0 at $DIR/issue-62289.rs:10:1: 10:2 + goto -> bb10; // scope 0 at $DIR/issue-62289.rs:10:2: 10:2 + } + + bb10: { return; // scope 0 at $DIR/issue-62289.rs:10:2: 10:2 } - bb10 (cleanup): { - drop(_1) -> bb12; // scope 0 at $DIR/issue-62289.rs:9:21: 9:22 - } - bb11 (cleanup): { - drop(_2) -> bb12; // scope 0 at $DIR/issue-62289.rs:9:20: 9:21 + drop(_1) -> bb13; // scope 0 at $DIR/issue-62289.rs:9:21: 9:22 } bb12 (cleanup): { + drop(_5) -> bb13; // scope 0 at $DIR/issue-62289.rs:9:20: 9:21 + } + + bb13 (cleanup): { resume; // scope 0 at $DIR/issue-62289.rs:8:1: 10:2 } } diff --git a/src/test/mir-opt/issue_76432.test.SimplifyComparisonIntegral.diff b/src/test/mir-opt/issue_76432.test.SimplifyComparisonIntegral.diff index 96adadbe03..97c549dc9c 100644 --- a/src/test/mir-opt/issue_76432.test.SimplifyComparisonIntegral.diff +++ b/src/test/mir-opt/issue_76432.test.SimplifyComparisonIntegral.diff @@ -22,6 +22,7 @@ let mut _20: *const T; // in scope 0 at $DIR/issue_76432.rs:9:70: 9:84 let mut _21: *const T; // in scope 0 at $DIR/issue_76432.rs:9:70: 9:84 let mut _22: !; // in scope 0 at $SRC_DIR/core/src/panic.rs:LL:COL + let mut _23: &[T; 3]; // in scope 0 at $DIR/issue_76432.rs:7:19: 7:29 scope 1 { debug v => _2; // in scope 1 at $DIR/issue_76432.rs:7:9: 7:10 let _13: &T; // in scope 1 at $DIR/issue_76432.rs:9:10: 9:16 @@ -51,16 +52,17 @@ StorageDead(_6); // scope 0 at $DIR/issue_76432.rs:7:28: 7:29 _4 = &_5; // scope 0 at $DIR/issue_76432.rs:7:19: 7:29 _3 = _4; // scope 0 at $DIR/issue_76432.rs:7:19: 7:29 + StorageLive(_23); // scope 0 at $DIR/issue_76432.rs:7:19: 7:29 + _23 = _3; // scope 0 at $DIR/issue_76432.rs:7:19: 7:29 _2 = move _3 as &[T] (Pointer(Unsize)); // scope 0 at $DIR/issue_76432.rs:7:19: 7:29 StorageDead(_3); // scope 0 at $DIR/issue_76432.rs:7:28: 7:29 StorageDead(_4); // scope 0 at $DIR/issue_76432.rs:7:29: 7:30 StorageLive(_9); // scope 1 at $DIR/issue_76432.rs:8:5: 11:6 - _10 = Len((*_2)); // scope 1 at $DIR/issue_76432.rs:9:9: 9:33 + _10 = const 3_usize; // scope 1 at $DIR/issue_76432.rs:9:9: 9:33 + StorageDead(_23); // scope 1 at $DIR/issue_76432.rs:9:9: 9:33 _11 = const 3_usize; // scope 1 at $DIR/issue_76432.rs:9:9: 9:33 -- _12 = Eq(move _10, const 3_usize); // scope 1 at $DIR/issue_76432.rs:9:9: 9:33 -- switchInt(move _12) -> [false: bb1, otherwise: bb2]; // scope 1 at $DIR/issue_76432.rs:9:9: 9:33 -+ nop; // scope 1 at $DIR/issue_76432.rs:9:9: 9:33 -+ switchInt(move _10) -> [3_usize: bb2, otherwise: bb1]; // scope 1 at $DIR/issue_76432.rs:9:9: 9:33 + _12 = const true; // scope 1 at $DIR/issue_76432.rs:9:9: 9:33 + goto -> bb2; // scope 1 at $DIR/issue_76432.rs:9:9: 9:33 } bb1: { diff --git a/src/test/mir-opt/lower_array_len.array_bound.InstCombine.diff b/src/test/mir-opt/lower_array_len.array_bound.InstCombine.diff new file mode 100644 index 0000000000..c7226573d7 --- /dev/null +++ b/src/test/mir-opt/lower_array_len.array_bound.InstCombine.diff @@ -0,0 +1,66 @@ +- // MIR for `array_bound` before InstCombine ++ // MIR for `array_bound` after InstCombine + + fn array_bound(_1: usize, _2: &[u8; N]) -> u8 { + debug index => _1; // in scope 0 at $DIR/lower_array_len.rs:6:36: 6:41 + debug slice => _2; // in scope 0 at $DIR/lower_array_len.rs:6:50: 6:55 + let mut _0: u8; // return place in scope 0 at $DIR/lower_array_len.rs:6:70: 6:72 + let mut _3: bool; // in scope 0 at $DIR/lower_array_len.rs:7:8: 7:27 + let mut _4: usize; // in scope 0 at $DIR/lower_array_len.rs:7:8: 7:13 + let mut _5: usize; // in scope 0 at $DIR/lower_array_len.rs:7:16: 7:27 + let mut _6: &[u8]; // in scope 0 at $DIR/lower_array_len.rs:7:16: 7:27 + let mut _7: &[u8; N]; // in scope 0 at $DIR/lower_array_len.rs:7:16: 7:27 + let _8: usize; // in scope 0 at $DIR/lower_array_len.rs:8:15: 8:20 + let mut _9: usize; // in scope 0 at $DIR/lower_array_len.rs:8:9: 8:21 + let mut _10: bool; // in scope 0 at $DIR/lower_array_len.rs:8:9: 8:21 + let mut _11: &[u8; N]; // in scope 0 at $DIR/lower_array_len.rs:7:16: 7:27 + + bb0: { + StorageLive(_3); // scope 0 at $DIR/lower_array_len.rs:7:8: 7:27 + StorageLive(_4); // scope 0 at $DIR/lower_array_len.rs:7:8: 7:13 + _4 = _1; // scope 0 at $DIR/lower_array_len.rs:7:8: 7:13 + StorageLive(_5); // scope 0 at $DIR/lower_array_len.rs:7:16: 7:27 + StorageLive(_6); // scope 0 at $DIR/lower_array_len.rs:7:16: 7:27 + StorageLive(_7); // scope 0 at $DIR/lower_array_len.rs:7:16: 7:27 +- _7 = &(*_2); // scope 0 at $DIR/lower_array_len.rs:7:16: 7:27 ++ _7 = _2; // scope 0 at $DIR/lower_array_len.rs:7:16: 7:27 + StorageLive(_11); // scope 0 at $DIR/lower_array_len.rs:7:16: 7:27 + _11 = _7; // scope 0 at $DIR/lower_array_len.rs:7:16: 7:27 + _6 = move _7 as &[u8] (Pointer(Unsize)); // scope 0 at $DIR/lower_array_len.rs:7:16: 7:27 + StorageDead(_7); // scope 0 at $DIR/lower_array_len.rs:7:20: 7:21 +- _5 = Len((*_11)); // scope 0 at $DIR/lower_array_len.rs:7:16: 7:27 ++ _5 = const N; // scope 0 at $DIR/lower_array_len.rs:7:16: 7:27 + StorageDead(_11); // scope 0 at $DIR/lower_array_len.rs:7:16: 7:27 + StorageDead(_6); // scope 0 at $DIR/lower_array_len.rs:7:26: 7:27 + _3 = Lt(move _4, move _5); // scope 0 at $DIR/lower_array_len.rs:7:8: 7:27 + StorageDead(_5); // scope 0 at $DIR/lower_array_len.rs:7:26: 7:27 + StorageDead(_4); // scope 0 at $DIR/lower_array_len.rs:7:26: 7:27 + switchInt(move _3) -> [false: bb3, otherwise: bb1]; // scope 0 at $DIR/lower_array_len.rs:7:8: 7:27 + } + + bb1: { + StorageLive(_8); // scope 0 at $DIR/lower_array_len.rs:8:15: 8:20 + _8 = _1; // scope 0 at $DIR/lower_array_len.rs:8:15: 8:20 +- _9 = Len((*_2)); // scope 0 at $DIR/lower_array_len.rs:8:9: 8:21 ++ _9 = const N; // scope 0 at $DIR/lower_array_len.rs:8:9: 8:21 + _10 = Lt(_8, _9); // scope 0 at $DIR/lower_array_len.rs:8:9: 8:21 + assert(move _10, "index out of bounds: the length is {} but the index is {}", move _9, _8) -> bb2; // scope 0 at $DIR/lower_array_len.rs:8:9: 8:21 + } + + bb2: { + _0 = (*_2)[_8]; // scope 0 at $DIR/lower_array_len.rs:8:9: 8:21 + StorageDead(_8); // scope 0 at $DIR/lower_array_len.rs:9:5: 9:6 + goto -> bb4; // scope 0 at $DIR/lower_array_len.rs:7:5: 11:6 + } + + bb3: { + _0 = const 42_u8; // scope 0 at $DIR/lower_array_len.rs:10:9: 10:11 + goto -> bb4; // scope 0 at $DIR/lower_array_len.rs:7:5: 11:6 + } + + bb4: { + StorageDead(_3); // scope 0 at $DIR/lower_array_len.rs:11:5: 11:6 + return; // scope 0 at $DIR/lower_array_len.rs:12:2: 12:2 + } + } + diff --git a/src/test/mir-opt/lower_array_len.array_bound.NormalizeArrayLen.diff b/src/test/mir-opt/lower_array_len.array_bound.NormalizeArrayLen.diff new file mode 100644 index 0000000000..d6c1c92cd9 --- /dev/null +++ b/src/test/mir-opt/lower_array_len.array_bound.NormalizeArrayLen.diff @@ -0,0 +1,68 @@ +- // MIR for `array_bound` before NormalizeArrayLen ++ // MIR for `array_bound` after NormalizeArrayLen + + fn array_bound(_1: usize, _2: &[u8; N]) -> u8 { + debug index => _1; // in scope 0 at $DIR/lower_array_len.rs:6:36: 6:41 + debug slice => _2; // in scope 0 at $DIR/lower_array_len.rs:6:50: 6:55 + let mut _0: u8; // return place in scope 0 at $DIR/lower_array_len.rs:6:70: 6:72 + let mut _3: bool; // in scope 0 at $DIR/lower_array_len.rs:7:8: 7:27 + let mut _4: usize; // in scope 0 at $DIR/lower_array_len.rs:7:8: 7:13 + let mut _5: usize; // in scope 0 at $DIR/lower_array_len.rs:7:16: 7:27 + let mut _6: &[u8]; // in scope 0 at $DIR/lower_array_len.rs:7:16: 7:27 + let mut _7: &[u8; N]; // in scope 0 at $DIR/lower_array_len.rs:7:16: 7:27 + let _8: usize; // in scope 0 at $DIR/lower_array_len.rs:8:15: 8:20 + let mut _9: usize; // in scope 0 at $DIR/lower_array_len.rs:8:9: 8:21 + let mut _10: bool; // in scope 0 at $DIR/lower_array_len.rs:8:9: 8:21 ++ let mut _11: &[u8; N]; // in scope 0 at $DIR/lower_array_len.rs:7:16: 7:27 + + bb0: { + StorageLive(_3); // scope 0 at $DIR/lower_array_len.rs:7:8: 7:27 + StorageLive(_4); // scope 0 at $DIR/lower_array_len.rs:7:8: 7:13 + _4 = _1; // scope 0 at $DIR/lower_array_len.rs:7:8: 7:13 + StorageLive(_5); // scope 0 at $DIR/lower_array_len.rs:7:16: 7:27 + StorageLive(_6); // scope 0 at $DIR/lower_array_len.rs:7:16: 7:27 + StorageLive(_7); // scope 0 at $DIR/lower_array_len.rs:7:16: 7:27 + _7 = &(*_2); // scope 0 at $DIR/lower_array_len.rs:7:16: 7:27 ++ StorageLive(_11); // scope 0 at $DIR/lower_array_len.rs:7:16: 7:27 ++ _11 = _7; // scope 0 at $DIR/lower_array_len.rs:7:16: 7:27 + _6 = move _7 as &[u8] (Pointer(Unsize)); // scope 0 at $DIR/lower_array_len.rs:7:16: 7:27 + StorageDead(_7); // scope 0 at $DIR/lower_array_len.rs:7:20: 7:21 +- _5 = Len((*_6)); // scope 0 at $DIR/lower_array_len.rs:7:16: 7:27 ++ _5 = Len((*_11)); // scope 0 at $DIR/lower_array_len.rs:7:16: 7:27 ++ StorageDead(_11); // scope 0 at $DIR/lower_array_len.rs:7:16: 7:27 + goto -> bb1; // scope 0 at $DIR/lower_array_len.rs:7:16: 7:27 + } + + bb1: { + StorageDead(_6); // scope 0 at $DIR/lower_array_len.rs:7:26: 7:27 + _3 = Lt(move _4, move _5); // scope 0 at $DIR/lower_array_len.rs:7:8: 7:27 + StorageDead(_5); // scope 0 at $DIR/lower_array_len.rs:7:26: 7:27 + StorageDead(_4); // scope 0 at $DIR/lower_array_len.rs:7:26: 7:27 + switchInt(move _3) -> [false: bb4, otherwise: bb2]; // scope 0 at $DIR/lower_array_len.rs:7:8: 7:27 + } + + bb2: { + StorageLive(_8); // scope 0 at $DIR/lower_array_len.rs:8:15: 8:20 + _8 = _1; // scope 0 at $DIR/lower_array_len.rs:8:15: 8:20 + _9 = Len((*_2)); // scope 0 at $DIR/lower_array_len.rs:8:9: 8:21 + _10 = Lt(_8, _9); // scope 0 at $DIR/lower_array_len.rs:8:9: 8:21 + assert(move _10, "index out of bounds: the length is {} but the index is {}", move _9, _8) -> bb3; // scope 0 at $DIR/lower_array_len.rs:8:9: 8:21 + } + + bb3: { + _0 = (*_2)[_8]; // scope 0 at $DIR/lower_array_len.rs:8:9: 8:21 + StorageDead(_8); // scope 0 at $DIR/lower_array_len.rs:9:5: 9:6 + goto -> bb5; // scope 0 at $DIR/lower_array_len.rs:7:5: 11:6 + } + + bb4: { + _0 = const 42_u8; // scope 0 at $DIR/lower_array_len.rs:10:9: 10:11 + goto -> bb5; // scope 0 at $DIR/lower_array_len.rs:7:5: 11:6 + } + + bb5: { + StorageDead(_3); // scope 0 at $DIR/lower_array_len.rs:11:5: 11:6 + return; // scope 0 at $DIR/lower_array_len.rs:12:2: 12:2 + } + } + diff --git a/src/test/mir-opt/lower_array_len.array_bound.SimplifyLocals.diff b/src/test/mir-opt/lower_array_len.array_bound.SimplifyLocals.diff new file mode 100644 index 0000000000..5cf3312cd6 --- /dev/null +++ b/src/test/mir-opt/lower_array_len.array_bound.SimplifyLocals.diff @@ -0,0 +1,73 @@ +- // MIR for `array_bound` before SimplifyLocals ++ // MIR for `array_bound` after SimplifyLocals + + fn array_bound(_1: usize, _2: &[u8; N]) -> u8 { + debug index => _1; // in scope 0 at $DIR/lower_array_len.rs:6:36: 6:41 + debug slice => _2; // in scope 0 at $DIR/lower_array_len.rs:6:50: 6:55 + let mut _0: u8; // return place in scope 0 at $DIR/lower_array_len.rs:6:70: 6:72 + let mut _3: bool; // in scope 0 at $DIR/lower_array_len.rs:7:8: 7:27 + let mut _4: usize; // in scope 0 at $DIR/lower_array_len.rs:7:8: 7:13 + let mut _5: usize; // in scope 0 at $DIR/lower_array_len.rs:7:16: 7:27 +- let mut _6: &[u8]; // in scope 0 at $DIR/lower_array_len.rs:7:16: 7:27 +- let mut _7: &[u8; N]; // in scope 0 at $DIR/lower_array_len.rs:7:16: 7:27 +- let _8: usize; // in scope 0 at $DIR/lower_array_len.rs:8:15: 8:20 +- let mut _9: usize; // in scope 0 at $DIR/lower_array_len.rs:8:9: 8:21 +- let mut _10: bool; // in scope 0 at $DIR/lower_array_len.rs:8:9: 8:21 +- let mut _11: &[u8; N]; // in scope 0 at $DIR/lower_array_len.rs:7:16: 7:27 ++ let _6: usize; // in scope 0 at $DIR/lower_array_len.rs:8:15: 8:20 ++ let mut _7: usize; // in scope 0 at $DIR/lower_array_len.rs:8:9: 8:21 ++ let mut _8: bool; // in scope 0 at $DIR/lower_array_len.rs:8:9: 8:21 + + bb0: { + StorageLive(_3); // scope 0 at $DIR/lower_array_len.rs:7:8: 7:27 + StorageLive(_4); // scope 0 at $DIR/lower_array_len.rs:7:8: 7:13 + _4 = _1; // scope 0 at $DIR/lower_array_len.rs:7:8: 7:13 + StorageLive(_5); // scope 0 at $DIR/lower_array_len.rs:7:16: 7:27 +- StorageLive(_6); // scope 0 at $DIR/lower_array_len.rs:7:16: 7:27 +- StorageLive(_7); // scope 0 at $DIR/lower_array_len.rs:7:16: 7:27 +- _7 = _2; // scope 0 at $DIR/lower_array_len.rs:7:16: 7:27 +- StorageLive(_11); // scope 0 at $DIR/lower_array_len.rs:7:16: 7:27 +- _11 = _7; // scope 0 at $DIR/lower_array_len.rs:7:16: 7:27 +- _6 = move _7 as &[u8] (Pointer(Unsize)); // scope 0 at $DIR/lower_array_len.rs:7:16: 7:27 +- StorageDead(_7); // scope 0 at $DIR/lower_array_len.rs:7:20: 7:21 + _5 = const N; // scope 0 at $DIR/lower_array_len.rs:7:16: 7:27 +- StorageDead(_11); // scope 0 at $DIR/lower_array_len.rs:7:16: 7:27 +- StorageDead(_6); // scope 0 at $DIR/lower_array_len.rs:7:26: 7:27 + _3 = Lt(move _4, move _5); // scope 0 at $DIR/lower_array_len.rs:7:8: 7:27 + StorageDead(_5); // scope 0 at $DIR/lower_array_len.rs:7:26: 7:27 + StorageDead(_4); // scope 0 at $DIR/lower_array_len.rs:7:26: 7:27 + switchInt(move _3) -> [false: bb3, otherwise: bb1]; // scope 0 at $DIR/lower_array_len.rs:7:8: 7:27 + } + + bb1: { +- StorageLive(_8); // scope 0 at $DIR/lower_array_len.rs:8:15: 8:20 +- _8 = _1; // scope 0 at $DIR/lower_array_len.rs:8:15: 8:20 +- _9 = const N; // scope 0 at $DIR/lower_array_len.rs:8:9: 8:21 +- _10 = Lt(_8, _9); // scope 0 at $DIR/lower_array_len.rs:8:9: 8:21 +- assert(move _10, "index out of bounds: the length is {} but the index is {}", move _9, _8) -> bb2; // scope 0 at $DIR/lower_array_len.rs:8:9: 8:21 ++ StorageLive(_6); // scope 0 at $DIR/lower_array_len.rs:8:15: 8:20 ++ _6 = _1; // scope 0 at $DIR/lower_array_len.rs:8:15: 8:20 ++ _7 = const N; // scope 0 at $DIR/lower_array_len.rs:8:9: 8:21 ++ _8 = Lt(_6, _7); // scope 0 at $DIR/lower_array_len.rs:8:9: 8:21 ++ assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, _6) -> bb2; // scope 0 at $DIR/lower_array_len.rs:8:9: 8:21 + } + + bb2: { +- _0 = (*_2)[_8]; // scope 0 at $DIR/lower_array_len.rs:8:9: 8:21 +- StorageDead(_8); // scope 0 at $DIR/lower_array_len.rs:9:5: 9:6 ++ _0 = (*_2)[_6]; // scope 0 at $DIR/lower_array_len.rs:8:9: 8:21 ++ StorageDead(_6); // scope 0 at $DIR/lower_array_len.rs:9:5: 9:6 + goto -> bb4; // scope 0 at $DIR/lower_array_len.rs:7:5: 11:6 + } + + bb3: { + _0 = const 42_u8; // scope 0 at $DIR/lower_array_len.rs:10:9: 10:11 + goto -> bb4; // scope 0 at $DIR/lower_array_len.rs:7:5: 11:6 + } + + bb4: { + StorageDead(_3); // scope 0 at $DIR/lower_array_len.rs:11:5: 11:6 + return; // scope 0 at $DIR/lower_array_len.rs:12:2: 12:2 + } + } + diff --git a/src/test/mir-opt/lower_array_len.array_bound_mut.InstCombine.diff b/src/test/mir-opt/lower_array_len.array_bound_mut.InstCombine.diff new file mode 100644 index 0000000000..5622d48453 --- /dev/null +++ b/src/test/mir-opt/lower_array_len.array_bound_mut.InstCombine.diff @@ -0,0 +1,79 @@ +- // MIR for `array_bound_mut` before InstCombine ++ // MIR for `array_bound_mut` after InstCombine + + fn array_bound_mut(_1: usize, _2: &mut [u8; N]) -> u8 { + debug index => _1; // in scope 0 at $DIR/lower_array_len.rs:17:40: 17:45 + debug slice => _2; // in scope 0 at $DIR/lower_array_len.rs:17:54: 17:59 + let mut _0: u8; // return place in scope 0 at $DIR/lower_array_len.rs:17:78: 17:80 + let mut _3: bool; // in scope 0 at $DIR/lower_array_len.rs:18:8: 18:27 + let mut _4: usize; // in scope 0 at $DIR/lower_array_len.rs:18:8: 18:13 + let mut _5: usize; // in scope 0 at $DIR/lower_array_len.rs:18:16: 18:27 + let mut _6: &[u8]; // in scope 0 at $DIR/lower_array_len.rs:18:16: 18:27 + let mut _7: &[u8; N]; // in scope 0 at $DIR/lower_array_len.rs:18:16: 18:27 + let _8: usize; // in scope 0 at $DIR/lower_array_len.rs:19:15: 19:20 + let mut _9: usize; // in scope 0 at $DIR/lower_array_len.rs:19:9: 19:21 + let mut _10: bool; // in scope 0 at $DIR/lower_array_len.rs:19:9: 19:21 + let _11: usize; // in scope 0 at $DIR/lower_array_len.rs:21:15: 21:16 + let mut _12: usize; // in scope 0 at $DIR/lower_array_len.rs:21:9: 21:17 + let mut _13: bool; // in scope 0 at $DIR/lower_array_len.rs:21:9: 21:17 + let mut _14: &[u8; N]; // in scope 0 at $DIR/lower_array_len.rs:18:16: 18:27 + + bb0: { + StorageLive(_3); // scope 0 at $DIR/lower_array_len.rs:18:8: 18:27 + StorageLive(_4); // scope 0 at $DIR/lower_array_len.rs:18:8: 18:13 + _4 = _1; // scope 0 at $DIR/lower_array_len.rs:18:8: 18:13 + StorageLive(_5); // scope 0 at $DIR/lower_array_len.rs:18:16: 18:27 + StorageLive(_6); // scope 0 at $DIR/lower_array_len.rs:18:16: 18:27 + StorageLive(_7); // scope 0 at $DIR/lower_array_len.rs:18:16: 18:27 + _7 = &(*_2); // scope 0 at $DIR/lower_array_len.rs:18:16: 18:27 + StorageLive(_14); // scope 0 at $DIR/lower_array_len.rs:18:16: 18:27 + _14 = _7; // scope 0 at $DIR/lower_array_len.rs:18:16: 18:27 + _6 = move _7 as &[u8] (Pointer(Unsize)); // scope 0 at $DIR/lower_array_len.rs:18:16: 18:27 + StorageDead(_7); // scope 0 at $DIR/lower_array_len.rs:18:20: 18:21 +- _5 = Len((*_14)); // scope 0 at $DIR/lower_array_len.rs:18:16: 18:27 ++ _5 = const N; // scope 0 at $DIR/lower_array_len.rs:18:16: 18:27 + StorageDead(_14); // scope 0 at $DIR/lower_array_len.rs:18:16: 18:27 + StorageDead(_6); // scope 0 at $DIR/lower_array_len.rs:18:26: 18:27 + _3 = Lt(move _4, move _5); // scope 0 at $DIR/lower_array_len.rs:18:8: 18:27 + StorageDead(_5); // scope 0 at $DIR/lower_array_len.rs:18:26: 18:27 + StorageDead(_4); // scope 0 at $DIR/lower_array_len.rs:18:26: 18:27 + switchInt(move _3) -> [false: bb3, otherwise: bb1]; // scope 0 at $DIR/lower_array_len.rs:18:8: 18:27 + } + + bb1: { + StorageLive(_8); // scope 0 at $DIR/lower_array_len.rs:19:15: 19:20 + _8 = _1; // scope 0 at $DIR/lower_array_len.rs:19:15: 19:20 +- _9 = Len((*_2)); // scope 0 at $DIR/lower_array_len.rs:19:9: 19:21 ++ _9 = const N; // scope 0 at $DIR/lower_array_len.rs:19:9: 19:21 + _10 = Lt(_8, _9); // scope 0 at $DIR/lower_array_len.rs:19:9: 19:21 + assert(move _10, "index out of bounds: the length is {} but the index is {}", move _9, _8) -> bb2; // scope 0 at $DIR/lower_array_len.rs:19:9: 19:21 + } + + bb2: { + _0 = (*_2)[_8]; // scope 0 at $DIR/lower_array_len.rs:19:9: 19:21 + StorageDead(_8); // scope 0 at $DIR/lower_array_len.rs:20:5: 20:6 + goto -> bb5; // scope 0 at $DIR/lower_array_len.rs:18:5: 24:6 + } + + bb3: { + StorageLive(_11); // scope 0 at $DIR/lower_array_len.rs:21:15: 21:16 + _11 = const 0_usize; // scope 0 at $DIR/lower_array_len.rs:21:15: 21:16 +- _12 = Len((*_2)); // scope 0 at $DIR/lower_array_len.rs:21:9: 21:17 ++ _12 = const N; // scope 0 at $DIR/lower_array_len.rs:21:9: 21:17 + _13 = Lt(_11, _12); // scope 0 at $DIR/lower_array_len.rs:21:9: 21:17 + assert(move _13, "index out of bounds: the length is {} but the index is {}", move _12, _11) -> bb4; // scope 0 at $DIR/lower_array_len.rs:21:9: 21:17 + } + + bb4: { + (*_2)[_11] = const 42_u8; // scope 0 at $DIR/lower_array_len.rs:21:9: 21:22 + StorageDead(_11); // scope 0 at $DIR/lower_array_len.rs:21:22: 21:23 + _0 = const 42_u8; // scope 0 at $DIR/lower_array_len.rs:23:9: 23:11 + goto -> bb5; // scope 0 at $DIR/lower_array_len.rs:18:5: 24:6 + } + + bb5: { + StorageDead(_3); // scope 0 at $DIR/lower_array_len.rs:24:5: 24:6 + return; // scope 0 at $DIR/lower_array_len.rs:25:2: 25:2 + } + } + diff --git a/src/test/mir-opt/lower_array_len.array_bound_mut.NormalizeArrayLen.diff b/src/test/mir-opt/lower_array_len.array_bound_mut.NormalizeArrayLen.diff new file mode 100644 index 0000000000..11fc20aa69 --- /dev/null +++ b/src/test/mir-opt/lower_array_len.array_bound_mut.NormalizeArrayLen.diff @@ -0,0 +1,81 @@ +- // MIR for `array_bound_mut` before NormalizeArrayLen ++ // MIR for `array_bound_mut` after NormalizeArrayLen + + fn array_bound_mut(_1: usize, _2: &mut [u8; N]) -> u8 { + debug index => _1; // in scope 0 at $DIR/lower_array_len.rs:17:40: 17:45 + debug slice => _2; // in scope 0 at $DIR/lower_array_len.rs:17:54: 17:59 + let mut _0: u8; // return place in scope 0 at $DIR/lower_array_len.rs:17:78: 17:80 + let mut _3: bool; // in scope 0 at $DIR/lower_array_len.rs:18:8: 18:27 + let mut _4: usize; // in scope 0 at $DIR/lower_array_len.rs:18:8: 18:13 + let mut _5: usize; // in scope 0 at $DIR/lower_array_len.rs:18:16: 18:27 + let mut _6: &[u8]; // in scope 0 at $DIR/lower_array_len.rs:18:16: 18:27 + let mut _7: &[u8; N]; // in scope 0 at $DIR/lower_array_len.rs:18:16: 18:27 + let _8: usize; // in scope 0 at $DIR/lower_array_len.rs:19:15: 19:20 + let mut _9: usize; // in scope 0 at $DIR/lower_array_len.rs:19:9: 19:21 + let mut _10: bool; // in scope 0 at $DIR/lower_array_len.rs:19:9: 19:21 + let _11: usize; // in scope 0 at $DIR/lower_array_len.rs:21:15: 21:16 + let mut _12: usize; // in scope 0 at $DIR/lower_array_len.rs:21:9: 21:17 + let mut _13: bool; // in scope 0 at $DIR/lower_array_len.rs:21:9: 21:17 ++ let mut _14: &[u8; N]; // in scope 0 at $DIR/lower_array_len.rs:18:16: 18:27 + + bb0: { + StorageLive(_3); // scope 0 at $DIR/lower_array_len.rs:18:8: 18:27 + StorageLive(_4); // scope 0 at $DIR/lower_array_len.rs:18:8: 18:13 + _4 = _1; // scope 0 at $DIR/lower_array_len.rs:18:8: 18:13 + StorageLive(_5); // scope 0 at $DIR/lower_array_len.rs:18:16: 18:27 + StorageLive(_6); // scope 0 at $DIR/lower_array_len.rs:18:16: 18:27 + StorageLive(_7); // scope 0 at $DIR/lower_array_len.rs:18:16: 18:27 + _7 = &(*_2); // scope 0 at $DIR/lower_array_len.rs:18:16: 18:27 ++ StorageLive(_14); // scope 0 at $DIR/lower_array_len.rs:18:16: 18:27 ++ _14 = _7; // scope 0 at $DIR/lower_array_len.rs:18:16: 18:27 + _6 = move _7 as &[u8] (Pointer(Unsize)); // scope 0 at $DIR/lower_array_len.rs:18:16: 18:27 + StorageDead(_7); // scope 0 at $DIR/lower_array_len.rs:18:20: 18:21 +- _5 = Len((*_6)); // scope 0 at $DIR/lower_array_len.rs:18:16: 18:27 ++ _5 = Len((*_14)); // scope 0 at $DIR/lower_array_len.rs:18:16: 18:27 ++ StorageDead(_14); // scope 0 at $DIR/lower_array_len.rs:18:16: 18:27 + goto -> bb1; // scope 0 at $DIR/lower_array_len.rs:18:16: 18:27 + } + + bb1: { + StorageDead(_6); // scope 0 at $DIR/lower_array_len.rs:18:26: 18:27 + _3 = Lt(move _4, move _5); // scope 0 at $DIR/lower_array_len.rs:18:8: 18:27 + StorageDead(_5); // scope 0 at $DIR/lower_array_len.rs:18:26: 18:27 + StorageDead(_4); // scope 0 at $DIR/lower_array_len.rs:18:26: 18:27 + switchInt(move _3) -> [false: bb4, otherwise: bb2]; // scope 0 at $DIR/lower_array_len.rs:18:8: 18:27 + } + + bb2: { + StorageLive(_8); // scope 0 at $DIR/lower_array_len.rs:19:15: 19:20 + _8 = _1; // scope 0 at $DIR/lower_array_len.rs:19:15: 19:20 + _9 = Len((*_2)); // scope 0 at $DIR/lower_array_len.rs:19:9: 19:21 + _10 = Lt(_8, _9); // scope 0 at $DIR/lower_array_len.rs:19:9: 19:21 + assert(move _10, "index out of bounds: the length is {} but the index is {}", move _9, _8) -> bb3; // scope 0 at $DIR/lower_array_len.rs:19:9: 19:21 + } + + bb3: { + _0 = (*_2)[_8]; // scope 0 at $DIR/lower_array_len.rs:19:9: 19:21 + StorageDead(_8); // scope 0 at $DIR/lower_array_len.rs:20:5: 20:6 + goto -> bb6; // scope 0 at $DIR/lower_array_len.rs:18:5: 24:6 + } + + bb4: { + StorageLive(_11); // scope 0 at $DIR/lower_array_len.rs:21:15: 21:16 + _11 = const 0_usize; // scope 0 at $DIR/lower_array_len.rs:21:15: 21:16 + _12 = Len((*_2)); // scope 0 at $DIR/lower_array_len.rs:21:9: 21:17 + _13 = Lt(_11, _12); // scope 0 at $DIR/lower_array_len.rs:21:9: 21:17 + assert(move _13, "index out of bounds: the length is {} but the index is {}", move _12, _11) -> bb5; // scope 0 at $DIR/lower_array_len.rs:21:9: 21:17 + } + + bb5: { + (*_2)[_11] = const 42_u8; // scope 0 at $DIR/lower_array_len.rs:21:9: 21:22 + StorageDead(_11); // scope 0 at $DIR/lower_array_len.rs:21:22: 21:23 + _0 = const 42_u8; // scope 0 at $DIR/lower_array_len.rs:23:9: 23:11 + goto -> bb6; // scope 0 at $DIR/lower_array_len.rs:18:5: 24:6 + } + + bb6: { + StorageDead(_3); // scope 0 at $DIR/lower_array_len.rs:24:5: 24:6 + return; // scope 0 at $DIR/lower_array_len.rs:25:2: 25:2 + } + } + diff --git a/src/test/mir-opt/lower_array_len.array_bound_mut.SimplifyLocals.diff b/src/test/mir-opt/lower_array_len.array_bound_mut.SimplifyLocals.diff new file mode 100644 index 0000000000..f72aee0e50 --- /dev/null +++ b/src/test/mir-opt/lower_array_len.array_bound_mut.SimplifyLocals.diff @@ -0,0 +1,96 @@ +- // MIR for `array_bound_mut` before SimplifyLocals ++ // MIR for `array_bound_mut` after SimplifyLocals + + fn array_bound_mut(_1: usize, _2: &mut [u8; N]) -> u8 { + debug index => _1; // in scope 0 at $DIR/lower_array_len.rs:17:40: 17:45 + debug slice => _2; // in scope 0 at $DIR/lower_array_len.rs:17:54: 17:59 + let mut _0: u8; // return place in scope 0 at $DIR/lower_array_len.rs:17:78: 17:80 + let mut _3: bool; // in scope 0 at $DIR/lower_array_len.rs:18:8: 18:27 + let mut _4: usize; // in scope 0 at $DIR/lower_array_len.rs:18:8: 18:13 + let mut _5: usize; // in scope 0 at $DIR/lower_array_len.rs:18:16: 18:27 +- let mut _6: &[u8]; // in scope 0 at $DIR/lower_array_len.rs:18:16: 18:27 +- let mut _7: &[u8; N]; // in scope 0 at $DIR/lower_array_len.rs:18:16: 18:27 +- let _8: usize; // in scope 0 at $DIR/lower_array_len.rs:19:15: 19:20 +- let mut _9: usize; // in scope 0 at $DIR/lower_array_len.rs:19:9: 19:21 +- let mut _10: bool; // in scope 0 at $DIR/lower_array_len.rs:19:9: 19:21 +- let _11: usize; // in scope 0 at $DIR/lower_array_len.rs:21:15: 21:16 +- let mut _12: usize; // in scope 0 at $DIR/lower_array_len.rs:21:9: 21:17 +- let mut _13: bool; // in scope 0 at $DIR/lower_array_len.rs:21:9: 21:17 +- let mut _14: &[u8; N]; // in scope 0 at $DIR/lower_array_len.rs:18:16: 18:27 ++ let _6: usize; // in scope 0 at $DIR/lower_array_len.rs:19:15: 19:20 ++ let mut _7: usize; // in scope 0 at $DIR/lower_array_len.rs:19:9: 19:21 ++ let mut _8: bool; // in scope 0 at $DIR/lower_array_len.rs:19:9: 19:21 ++ let _9: usize; // in scope 0 at $DIR/lower_array_len.rs:21:15: 21:16 ++ let mut _10: usize; // in scope 0 at $DIR/lower_array_len.rs:21:9: 21:17 ++ let mut _11: bool; // in scope 0 at $DIR/lower_array_len.rs:21:9: 21:17 + + bb0: { + StorageLive(_3); // scope 0 at $DIR/lower_array_len.rs:18:8: 18:27 + StorageLive(_4); // scope 0 at $DIR/lower_array_len.rs:18:8: 18:13 + _4 = _1; // scope 0 at $DIR/lower_array_len.rs:18:8: 18:13 + StorageLive(_5); // scope 0 at $DIR/lower_array_len.rs:18:16: 18:27 +- StorageLive(_6); // scope 0 at $DIR/lower_array_len.rs:18:16: 18:27 +- StorageLive(_7); // scope 0 at $DIR/lower_array_len.rs:18:16: 18:27 +- _7 = &(*_2); // scope 0 at $DIR/lower_array_len.rs:18:16: 18:27 +- StorageLive(_14); // scope 0 at $DIR/lower_array_len.rs:18:16: 18:27 +- _14 = _7; // scope 0 at $DIR/lower_array_len.rs:18:16: 18:27 +- _6 = move _7 as &[u8] (Pointer(Unsize)); // scope 0 at $DIR/lower_array_len.rs:18:16: 18:27 +- StorageDead(_7); // scope 0 at $DIR/lower_array_len.rs:18:20: 18:21 + _5 = const N; // scope 0 at $DIR/lower_array_len.rs:18:16: 18:27 +- StorageDead(_14); // scope 0 at $DIR/lower_array_len.rs:18:16: 18:27 +- StorageDead(_6); // scope 0 at $DIR/lower_array_len.rs:18:26: 18:27 + _3 = Lt(move _4, move _5); // scope 0 at $DIR/lower_array_len.rs:18:8: 18:27 + StorageDead(_5); // scope 0 at $DIR/lower_array_len.rs:18:26: 18:27 + StorageDead(_4); // scope 0 at $DIR/lower_array_len.rs:18:26: 18:27 + switchInt(move _3) -> [false: bb3, otherwise: bb1]; // scope 0 at $DIR/lower_array_len.rs:18:8: 18:27 + } + + bb1: { +- StorageLive(_8); // scope 0 at $DIR/lower_array_len.rs:19:15: 19:20 +- _8 = _1; // scope 0 at $DIR/lower_array_len.rs:19:15: 19:20 +- _9 = const N; // scope 0 at $DIR/lower_array_len.rs:19:9: 19:21 +- _10 = Lt(_8, _9); // scope 0 at $DIR/lower_array_len.rs:19:9: 19:21 +- assert(move _10, "index out of bounds: the length is {} but the index is {}", move _9, _8) -> bb2; // scope 0 at $DIR/lower_array_len.rs:19:9: 19:21 ++ StorageLive(_6); // scope 0 at $DIR/lower_array_len.rs:19:15: 19:20 ++ _6 = _1; // scope 0 at $DIR/lower_array_len.rs:19:15: 19:20 ++ _7 = const N; // scope 0 at $DIR/lower_array_len.rs:19:9: 19:21 ++ _8 = Lt(_6, _7); // scope 0 at $DIR/lower_array_len.rs:19:9: 19:21 ++ assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, _6) -> bb2; // scope 0 at $DIR/lower_array_len.rs:19:9: 19:21 + } + + bb2: { +- _0 = (*_2)[_8]; // scope 0 at $DIR/lower_array_len.rs:19:9: 19:21 +- StorageDead(_8); // scope 0 at $DIR/lower_array_len.rs:20:5: 20:6 ++ _0 = (*_2)[_6]; // scope 0 at $DIR/lower_array_len.rs:19:9: 19:21 ++ StorageDead(_6); // scope 0 at $DIR/lower_array_len.rs:20:5: 20:6 + goto -> bb5; // scope 0 at $DIR/lower_array_len.rs:18:5: 24:6 + } + + bb3: { +- StorageLive(_11); // scope 0 at $DIR/lower_array_len.rs:21:15: 21:16 +- _11 = const 0_usize; // scope 0 at $DIR/lower_array_len.rs:21:15: 21:16 +- _12 = const N; // scope 0 at $DIR/lower_array_len.rs:21:9: 21:17 +- _13 = Lt(const 0_usize, _12); // scope 0 at $DIR/lower_array_len.rs:21:9: 21:17 +- assert(move _13, "index out of bounds: the length is {} but the index is {}", move _12, const 0_usize) -> bb4; // scope 0 at $DIR/lower_array_len.rs:21:9: 21:17 ++ StorageLive(_9); // scope 0 at $DIR/lower_array_len.rs:21:15: 21:16 ++ _9 = const 0_usize; // scope 0 at $DIR/lower_array_len.rs:21:15: 21:16 ++ _10 = const N; // scope 0 at $DIR/lower_array_len.rs:21:9: 21:17 ++ _11 = Lt(const 0_usize, _10); // scope 0 at $DIR/lower_array_len.rs:21:9: 21:17 ++ assert(move _11, "index out of bounds: the length is {} but the index is {}", move _10, const 0_usize) -> bb4; // scope 0 at $DIR/lower_array_len.rs:21:9: 21:17 + } + + bb4: { +- (*_2)[_11] = const 42_u8; // scope 0 at $DIR/lower_array_len.rs:21:9: 21:22 +- StorageDead(_11); // scope 0 at $DIR/lower_array_len.rs:21:22: 21:23 ++ (*_2)[_9] = const 42_u8; // scope 0 at $DIR/lower_array_len.rs:21:9: 21:22 ++ StorageDead(_9); // scope 0 at $DIR/lower_array_len.rs:21:22: 21:23 + _0 = const 42_u8; // scope 0 at $DIR/lower_array_len.rs:23:9: 23:11 + goto -> bb5; // scope 0 at $DIR/lower_array_len.rs:18:5: 24:6 + } + + bb5: { + StorageDead(_3); // scope 0 at $DIR/lower_array_len.rs:24:5: 24:6 + return; // scope 0 at $DIR/lower_array_len.rs:25:2: 25:2 + } + } + diff --git a/src/test/mir-opt/lower_array_len.array_len.InstCombine.diff b/src/test/mir-opt/lower_array_len.array_len.InstCombine.diff new file mode 100644 index 0000000000..a818de39bc --- /dev/null +++ b/src/test/mir-opt/lower_array_len.array_len.InstCombine.diff @@ -0,0 +1,27 @@ +- // MIR for `array_len` before InstCombine ++ // MIR for `array_len` after InstCombine + + fn array_len(_1: &[u8; N]) -> usize { + debug arr => _1; // in scope 0 at $DIR/lower_array_len.rs:30:34: 30:37 + let mut _0: usize; // return place in scope 0 at $DIR/lower_array_len.rs:30:52: 30:57 + let mut _2: &[u8]; // in scope 0 at $DIR/lower_array_len.rs:31:5: 31:14 + let mut _3: &[u8; N]; // in scope 0 at $DIR/lower_array_len.rs:31:5: 31:14 + let mut _4: &[u8; N]; // in scope 0 at $DIR/lower_array_len.rs:31:5: 31:14 + + bb0: { + StorageLive(_2); // scope 0 at $DIR/lower_array_len.rs:31:5: 31:14 + StorageLive(_3); // scope 0 at $DIR/lower_array_len.rs:31:5: 31:14 +- _3 = &(*_1); // scope 0 at $DIR/lower_array_len.rs:31:5: 31:14 ++ _3 = _1; // scope 0 at $DIR/lower_array_len.rs:31:5: 31:14 + StorageLive(_4); // scope 0 at $DIR/lower_array_len.rs:31:5: 31:14 + _4 = _3; // scope 0 at $DIR/lower_array_len.rs:31:5: 31:14 + _2 = move _3 as &[u8] (Pointer(Unsize)); // scope 0 at $DIR/lower_array_len.rs:31:5: 31:14 + StorageDead(_3); // scope 0 at $DIR/lower_array_len.rs:31:7: 31:8 +- _0 = Len((*_4)); // scope 0 at $DIR/lower_array_len.rs:31:5: 31:14 ++ _0 = const N; // scope 0 at $DIR/lower_array_len.rs:31:5: 31:14 + StorageDead(_4); // scope 0 at $DIR/lower_array_len.rs:31:5: 31:14 + StorageDead(_2); // scope 0 at $DIR/lower_array_len.rs:31:13: 31:14 + return; // scope 0 at $DIR/lower_array_len.rs:32:2: 32:2 + } + } + diff --git a/src/test/mir-opt/lower_array_len.array_len.NormalizeArrayLen.diff b/src/test/mir-opt/lower_array_len.array_len.NormalizeArrayLen.diff new file mode 100644 index 0000000000..892fdda818 --- /dev/null +++ b/src/test/mir-opt/lower_array_len.array_len.NormalizeArrayLen.diff @@ -0,0 +1,30 @@ +- // MIR for `array_len` before NormalizeArrayLen ++ // MIR for `array_len` after NormalizeArrayLen + + fn array_len(_1: &[u8; N]) -> usize { + debug arr => _1; // in scope 0 at $DIR/lower_array_len.rs:30:34: 30:37 + let mut _0: usize; // return place in scope 0 at $DIR/lower_array_len.rs:30:52: 30:57 + let mut _2: &[u8]; // in scope 0 at $DIR/lower_array_len.rs:31:5: 31:14 + let mut _3: &[u8; N]; // in scope 0 at $DIR/lower_array_len.rs:31:5: 31:14 ++ let mut _4: &[u8; N]; // in scope 0 at $DIR/lower_array_len.rs:31:5: 31:14 + + bb0: { + StorageLive(_2); // scope 0 at $DIR/lower_array_len.rs:31:5: 31:14 + StorageLive(_3); // scope 0 at $DIR/lower_array_len.rs:31:5: 31:14 + _3 = &(*_1); // scope 0 at $DIR/lower_array_len.rs:31:5: 31:14 ++ StorageLive(_4); // scope 0 at $DIR/lower_array_len.rs:31:5: 31:14 ++ _4 = _3; // scope 0 at $DIR/lower_array_len.rs:31:5: 31:14 + _2 = move _3 as &[u8] (Pointer(Unsize)); // scope 0 at $DIR/lower_array_len.rs:31:5: 31:14 + StorageDead(_3); // scope 0 at $DIR/lower_array_len.rs:31:7: 31:8 +- _0 = Len((*_2)); // scope 0 at $DIR/lower_array_len.rs:31:5: 31:14 ++ _0 = Len((*_4)); // scope 0 at $DIR/lower_array_len.rs:31:5: 31:14 ++ StorageDead(_4); // scope 0 at $DIR/lower_array_len.rs:31:5: 31:14 + goto -> bb1; // scope 0 at $DIR/lower_array_len.rs:31:5: 31:14 + } + + bb1: { + StorageDead(_2); // scope 0 at $DIR/lower_array_len.rs:31:13: 31:14 + return; // scope 0 at $DIR/lower_array_len.rs:32:2: 32:2 + } + } + diff --git a/src/test/mir-opt/lower_array_len.array_len.SimplifyLocals.diff b/src/test/mir-opt/lower_array_len.array_len.SimplifyLocals.diff new file mode 100644 index 0000000000..20e2685aba --- /dev/null +++ b/src/test/mir-opt/lower_array_len.array_len.SimplifyLocals.diff @@ -0,0 +1,25 @@ +- // MIR for `array_len` before SimplifyLocals ++ // MIR for `array_len` after SimplifyLocals + + fn array_len(_1: &[u8; N]) -> usize { + debug arr => _1; // in scope 0 at $DIR/lower_array_len.rs:30:34: 30:37 + let mut _0: usize; // return place in scope 0 at $DIR/lower_array_len.rs:30:52: 30:57 +- let mut _2: &[u8]; // in scope 0 at $DIR/lower_array_len.rs:31:5: 31:14 +- let mut _3: &[u8; N]; // in scope 0 at $DIR/lower_array_len.rs:31:5: 31:14 +- let mut _4: &[u8; N]; // in scope 0 at $DIR/lower_array_len.rs:31:5: 31:14 + + bb0: { +- StorageLive(_2); // scope 0 at $DIR/lower_array_len.rs:31:5: 31:14 +- StorageLive(_3); // scope 0 at $DIR/lower_array_len.rs:31:5: 31:14 +- _3 = _1; // scope 0 at $DIR/lower_array_len.rs:31:5: 31:14 +- StorageLive(_4); // scope 0 at $DIR/lower_array_len.rs:31:5: 31:14 +- _4 = _3; // scope 0 at $DIR/lower_array_len.rs:31:5: 31:14 +- _2 = move _3 as &[u8] (Pointer(Unsize)); // scope 0 at $DIR/lower_array_len.rs:31:5: 31:14 +- StorageDead(_3); // scope 0 at $DIR/lower_array_len.rs:31:7: 31:8 + _0 = const N; // scope 0 at $DIR/lower_array_len.rs:31:5: 31:14 +- StorageDead(_4); // scope 0 at $DIR/lower_array_len.rs:31:5: 31:14 +- StorageDead(_2); // scope 0 at $DIR/lower_array_len.rs:31:13: 31:14 + return; // scope 0 at $DIR/lower_array_len.rs:32:2: 32:2 + } + } + diff --git a/src/test/mir-opt/lower_array_len.array_len_by_value.InstCombine.diff b/src/test/mir-opt/lower_array_len.array_len_by_value.InstCombine.diff new file mode 100644 index 0000000000..ce12531e84 --- /dev/null +++ b/src/test/mir-opt/lower_array_len.array_len_by_value.InstCombine.diff @@ -0,0 +1,26 @@ +- // MIR for `array_len_by_value` before InstCombine ++ // MIR for `array_len_by_value` after InstCombine + + fn array_len_by_value(_1: [u8; N]) -> usize { + debug arr => _1; // in scope 0 at $DIR/lower_array_len.rs:37:43: 37:46 + let mut _0: usize; // return place in scope 0 at $DIR/lower_array_len.rs:37:60: 37:65 + let mut _2: &[u8]; // in scope 0 at $DIR/lower_array_len.rs:38:5: 38:14 + let mut _3: &[u8; N]; // in scope 0 at $DIR/lower_array_len.rs:38:5: 38:14 + let mut _4: &[u8; N]; // in scope 0 at $DIR/lower_array_len.rs:38:5: 38:14 + + bb0: { + StorageLive(_2); // scope 0 at $DIR/lower_array_len.rs:38:5: 38:14 + StorageLive(_3); // scope 0 at $DIR/lower_array_len.rs:38:5: 38:14 + _3 = &_1; // scope 0 at $DIR/lower_array_len.rs:38:5: 38:14 + StorageLive(_4); // scope 0 at $DIR/lower_array_len.rs:38:5: 38:14 + _4 = _3; // scope 0 at $DIR/lower_array_len.rs:38:5: 38:14 + _2 = move _3 as &[u8] (Pointer(Unsize)); // scope 0 at $DIR/lower_array_len.rs:38:5: 38:14 + StorageDead(_3); // scope 0 at $DIR/lower_array_len.rs:38:7: 38:8 +- _0 = Len((*_4)); // scope 0 at $DIR/lower_array_len.rs:38:5: 38:14 ++ _0 = const N; // scope 0 at $DIR/lower_array_len.rs:38:5: 38:14 + StorageDead(_4); // scope 0 at $DIR/lower_array_len.rs:38:5: 38:14 + StorageDead(_2); // scope 0 at $DIR/lower_array_len.rs:38:13: 38:14 + return; // scope 0 at $DIR/lower_array_len.rs:39:2: 39:2 + } + } + diff --git a/src/test/mir-opt/lower_array_len.array_len_by_value.NormalizeArrayLen.diff b/src/test/mir-opt/lower_array_len.array_len_by_value.NormalizeArrayLen.diff new file mode 100644 index 0000000000..201fffbf0d --- /dev/null +++ b/src/test/mir-opt/lower_array_len.array_len_by_value.NormalizeArrayLen.diff @@ -0,0 +1,30 @@ +- // MIR for `array_len_by_value` before NormalizeArrayLen ++ // MIR for `array_len_by_value` after NormalizeArrayLen + + fn array_len_by_value(_1: [u8; N]) -> usize { + debug arr => _1; // in scope 0 at $DIR/lower_array_len.rs:37:43: 37:46 + let mut _0: usize; // return place in scope 0 at $DIR/lower_array_len.rs:37:60: 37:65 + let mut _2: &[u8]; // in scope 0 at $DIR/lower_array_len.rs:38:5: 38:14 + let mut _3: &[u8; N]; // in scope 0 at $DIR/lower_array_len.rs:38:5: 38:14 ++ let mut _4: &[u8; N]; // in scope 0 at $DIR/lower_array_len.rs:38:5: 38:14 + + bb0: { + StorageLive(_2); // scope 0 at $DIR/lower_array_len.rs:38:5: 38:14 + StorageLive(_3); // scope 0 at $DIR/lower_array_len.rs:38:5: 38:14 + _3 = &_1; // scope 0 at $DIR/lower_array_len.rs:38:5: 38:14 ++ StorageLive(_4); // scope 0 at $DIR/lower_array_len.rs:38:5: 38:14 ++ _4 = _3; // scope 0 at $DIR/lower_array_len.rs:38:5: 38:14 + _2 = move _3 as &[u8] (Pointer(Unsize)); // scope 0 at $DIR/lower_array_len.rs:38:5: 38:14 + StorageDead(_3); // scope 0 at $DIR/lower_array_len.rs:38:7: 38:8 +- _0 = Len((*_2)); // scope 0 at $DIR/lower_array_len.rs:38:5: 38:14 ++ _0 = Len((*_4)); // scope 0 at $DIR/lower_array_len.rs:38:5: 38:14 ++ StorageDead(_4); // scope 0 at $DIR/lower_array_len.rs:38:5: 38:14 + goto -> bb1; // scope 0 at $DIR/lower_array_len.rs:38:5: 38:14 + } + + bb1: { + StorageDead(_2); // scope 0 at $DIR/lower_array_len.rs:38:13: 38:14 + return; // scope 0 at $DIR/lower_array_len.rs:39:2: 39:2 + } + } + diff --git a/src/test/mir-opt/lower_array_len.array_len_by_value.SimplifyLocals.diff b/src/test/mir-opt/lower_array_len.array_len_by_value.SimplifyLocals.diff new file mode 100644 index 0000000000..7e7b708145 --- /dev/null +++ b/src/test/mir-opt/lower_array_len.array_len_by_value.SimplifyLocals.diff @@ -0,0 +1,25 @@ +- // MIR for `array_len_by_value` before SimplifyLocals ++ // MIR for `array_len_by_value` after SimplifyLocals + + fn array_len_by_value(_1: [u8; N]) -> usize { + debug arr => _1; // in scope 0 at $DIR/lower_array_len.rs:37:43: 37:46 + let mut _0: usize; // return place in scope 0 at $DIR/lower_array_len.rs:37:60: 37:65 +- let mut _2: &[u8]; // in scope 0 at $DIR/lower_array_len.rs:38:5: 38:14 +- let mut _3: &[u8; N]; // in scope 0 at $DIR/lower_array_len.rs:38:5: 38:14 +- let mut _4: &[u8; N]; // in scope 0 at $DIR/lower_array_len.rs:38:5: 38:14 + + bb0: { +- StorageLive(_2); // scope 0 at $DIR/lower_array_len.rs:38:5: 38:14 +- StorageLive(_3); // scope 0 at $DIR/lower_array_len.rs:38:5: 38:14 +- _3 = &_1; // scope 0 at $DIR/lower_array_len.rs:38:5: 38:14 +- StorageLive(_4); // scope 0 at $DIR/lower_array_len.rs:38:5: 38:14 +- _4 = _3; // scope 0 at $DIR/lower_array_len.rs:38:5: 38:14 +- _2 = move _3 as &[u8] (Pointer(Unsize)); // scope 0 at $DIR/lower_array_len.rs:38:5: 38:14 +- StorageDead(_3); // scope 0 at $DIR/lower_array_len.rs:38:7: 38:8 + _0 = const N; // scope 0 at $DIR/lower_array_len.rs:38:5: 38:14 +- StorageDead(_4); // scope 0 at $DIR/lower_array_len.rs:38:5: 38:14 +- StorageDead(_2); // scope 0 at $DIR/lower_array_len.rs:38:13: 38:14 + return; // scope 0 at $DIR/lower_array_len.rs:39:2: 39:2 + } + } + diff --git a/src/test/mir-opt/lower_array_len.rs b/src/test/mir-opt/lower_array_len.rs new file mode 100644 index 0000000000..fc12ee75fc --- /dev/null +++ b/src/test/mir-opt/lower_array_len.rs @@ -0,0 +1,47 @@ +// compile-flags: -Z mir-opt-level=4 + +// EMIT_MIR lower_array_len.array_bound.NormalizeArrayLen.diff +// EMIT_MIR lower_array_len.array_bound.SimplifyLocals.diff +// EMIT_MIR lower_array_len.array_bound.InstCombine.diff +pub fn array_bound(index: usize, slice: &[u8; N]) -> u8 { + if index < slice.len() { + slice[index] + } else { + 42 + } +} + +// EMIT_MIR lower_array_len.array_bound_mut.NormalizeArrayLen.diff +// EMIT_MIR lower_array_len.array_bound_mut.SimplifyLocals.diff +// EMIT_MIR lower_array_len.array_bound_mut.InstCombine.diff +pub fn array_bound_mut(index: usize, slice: &mut [u8; N]) -> u8 { + if index < slice.len() { + slice[index] + } else { + slice[0] = 42; + + 42 + } +} + +// EMIT_MIR lower_array_len.array_len.NormalizeArrayLen.diff +// EMIT_MIR lower_array_len.array_len.SimplifyLocals.diff +// EMIT_MIR lower_array_len.array_len.InstCombine.diff +pub fn array_len(arr: &[u8; N]) -> usize { + arr.len() +} + +// EMIT_MIR lower_array_len.array_len_by_value.NormalizeArrayLen.diff +// EMIT_MIR lower_array_len.array_len_by_value.SimplifyLocals.diff +// EMIT_MIR lower_array_len.array_len_by_value.InstCombine.diff +pub fn array_len_by_value(arr: [u8; N]) -> usize { + arr.len() +} + +fn main() { + let _ = array_bound(3, &[0, 1, 2, 3]); + let mut tmp = [0, 1, 2, 3, 4]; + let _ = array_bound_mut(3, &mut [0, 1, 2, 3]); + let _ = array_len(&[0]); + let _ = array_len_by_value([0, 2]); +} diff --git a/src/test/mir-opt/lower_intrinsics.align_of.LowerIntrinsics.diff b/src/test/mir-opt/lower_intrinsics.align_of.LowerIntrinsics.diff new file mode 100644 index 0000000000..3f5f71f808 --- /dev/null +++ b/src/test/mir-opt/lower_intrinsics.align_of.LowerIntrinsics.diff @@ -0,0 +1,24 @@ +- // MIR for `align_of` before LowerIntrinsics ++ // MIR for `align_of` after LowerIntrinsics + + fn align_of() -> usize { + let mut _0: usize; // return place in scope 0 at $DIR/lower_intrinsics.rs:18:25: 18:30 + + bb0: { +- _0 = std::intrinsics::min_align_of::() -> bb1; // scope 0 at $DIR/lower_intrinsics.rs:19:5: 19:42 +- // mir::Constant +- // + span: $DIR/lower_intrinsics.rs:19:5: 19:40 +- // + literal: Const { ty: extern "rust-intrinsic" fn() -> usize {std::intrinsics::min_align_of::}, val: Value(Scalar()) } ++ _0 = AlignOf(T); // scope 0 at $DIR/lower_intrinsics.rs:19:5: 19:42 ++ goto -> bb1; // scope 0 at $DIR/lower_intrinsics.rs:19:5: 19:42 + } + + bb1: { + return; // scope 0 at $DIR/lower_intrinsics.rs:20:2: 20:2 + } + + bb2 (cleanup): { + resume; // scope 0 at $DIR/lower_intrinsics.rs:18:1: 20:2 + } + } + diff --git a/src/test/mir-opt/lower_intrinsics.discriminant.LowerIntrinsics.diff b/src/test/mir-opt/lower_intrinsics.discriminant.LowerIntrinsics.diff index f427375e5a..d9b441a470 100644 --- a/src/test/mir-opt/lower_intrinsics.discriminant.LowerIntrinsics.diff +++ b/src/test/mir-opt/lower_intrinsics.discriminant.LowerIntrinsics.diff @@ -2,127 +2,127 @@ + // MIR for `discriminant` after LowerIntrinsics fn discriminant(_1: T) -> () { - debug t => _1; // in scope 0 at $DIR/lower_intrinsics.rs:68:24: 68:25 - let mut _0: (); // return place in scope 0 at $DIR/lower_intrinsics.rs:68:30: 68:30 - let _2: ::Discriminant; // in scope 0 at $DIR/lower_intrinsics.rs:69:5: 69:45 - let mut _3: &T; // in scope 0 at $DIR/lower_intrinsics.rs:69:42: 69:44 - let _4: &T; // in scope 0 at $DIR/lower_intrinsics.rs:69:42: 69:44 - let _5: u8; // in scope 0 at $DIR/lower_intrinsics.rs:70:5: 70:45 - let mut _6: &i32; // in scope 0 at $DIR/lower_intrinsics.rs:70:42: 70:44 - let _7: &i32; // in scope 0 at $DIR/lower_intrinsics.rs:70:42: 70:44 - let _8: i32; // in scope 0 at $DIR/lower_intrinsics.rs:70:43: 70:44 - let _9: u8; // in scope 0 at $DIR/lower_intrinsics.rs:71:5: 71:46 - let mut _10: &(); // in scope 0 at $DIR/lower_intrinsics.rs:71:42: 71:45 - let _11: &(); // in scope 0 at $DIR/lower_intrinsics.rs:71:42: 71:45 - let _12: (); // in scope 0 at $DIR/lower_intrinsics.rs:71:43: 71:45 - let _13: isize; // in scope 0 at $DIR/lower_intrinsics.rs:72:5: 72:48 - let mut _14: &E; // in scope 0 at $DIR/lower_intrinsics.rs:72:42: 72:47 - let _15: &E; // in scope 0 at $DIR/lower_intrinsics.rs:72:42: 72:47 - let _16: E; // in scope 0 at $DIR/lower_intrinsics.rs:72:43: 72:47 - let mut _17: &E; // in scope 0 at $DIR/lower_intrinsics.rs:72:42: 72:47 - let mut _18: &(); // in scope 0 at $DIR/lower_intrinsics.rs:71:42: 71:45 - let mut _19: &i32; // in scope 0 at $DIR/lower_intrinsics.rs:70:42: 70:44 + debug t => _1; // in scope 0 at $DIR/lower_intrinsics.rs:73:24: 73:25 + let mut _0: (); // return place in scope 0 at $DIR/lower_intrinsics.rs:73:30: 73:30 + let _2: ::Discriminant; // in scope 0 at $DIR/lower_intrinsics.rs:74:5: 74:45 + let mut _3: &T; // in scope 0 at $DIR/lower_intrinsics.rs:74:42: 74:44 + let _4: &T; // in scope 0 at $DIR/lower_intrinsics.rs:74:42: 74:44 + let _5: u8; // in scope 0 at $DIR/lower_intrinsics.rs:75:5: 75:45 + let mut _6: &i32; // in scope 0 at $DIR/lower_intrinsics.rs:75:42: 75:44 + let _7: &i32; // in scope 0 at $DIR/lower_intrinsics.rs:75:42: 75:44 + let _8: i32; // in scope 0 at $DIR/lower_intrinsics.rs:75:43: 75:44 + let _9: u8; // in scope 0 at $DIR/lower_intrinsics.rs:76:5: 76:46 + let mut _10: &(); // in scope 0 at $DIR/lower_intrinsics.rs:76:42: 76:45 + let _11: &(); // in scope 0 at $DIR/lower_intrinsics.rs:76:42: 76:45 + let _12: (); // in scope 0 at $DIR/lower_intrinsics.rs:76:43: 76:45 + let _13: isize; // in scope 0 at $DIR/lower_intrinsics.rs:77:5: 77:48 + let mut _14: &E; // in scope 0 at $DIR/lower_intrinsics.rs:77:42: 77:47 + let _15: &E; // in scope 0 at $DIR/lower_intrinsics.rs:77:42: 77:47 + let _16: E; // in scope 0 at $DIR/lower_intrinsics.rs:77:43: 77:47 + let mut _17: &E; // in scope 0 at $DIR/lower_intrinsics.rs:77:42: 77:47 + let mut _18: &(); // in scope 0 at $DIR/lower_intrinsics.rs:76:42: 76:45 + let mut _19: &i32; // in scope 0 at $DIR/lower_intrinsics.rs:75:42: 75:44 bb0: { - StorageLive(_2); // scope 0 at $DIR/lower_intrinsics.rs:69:5: 69:45 - StorageLive(_3); // scope 0 at $DIR/lower_intrinsics.rs:69:42: 69:44 - StorageLive(_4); // scope 0 at $DIR/lower_intrinsics.rs:69:42: 69:44 - _4 = &_1; // scope 0 at $DIR/lower_intrinsics.rs:69:42: 69:44 - _3 = &(*_4); // scope 0 at $DIR/lower_intrinsics.rs:69:42: 69:44 -- _2 = discriminant_value::(move _3) -> bb1; // scope 0 at $DIR/lower_intrinsics.rs:69:5: 69:45 + StorageLive(_2); // scope 0 at $DIR/lower_intrinsics.rs:74:5: 74:45 + StorageLive(_3); // scope 0 at $DIR/lower_intrinsics.rs:74:42: 74:44 + StorageLive(_4); // scope 0 at $DIR/lower_intrinsics.rs:74:42: 74:44 + _4 = &_1; // scope 0 at $DIR/lower_intrinsics.rs:74:42: 74:44 + _3 = &(*_4); // scope 0 at $DIR/lower_intrinsics.rs:74:42: 74:44 +- _2 = discriminant_value::(move _3) -> bb1; // scope 0 at $DIR/lower_intrinsics.rs:74:5: 74:45 - // mir::Constant -- // + span: $DIR/lower_intrinsics.rs:69:5: 69:41 +- // + span: $DIR/lower_intrinsics.rs:74:5: 74:41 - // + literal: Const { ty: for<'r> extern "rust-intrinsic" fn(&'r T) -> ::Discriminant {std::intrinsics::discriminant_value::}, val: Value(Scalar()) } -+ _2 = discriminant((*_3)); // scope 0 at $DIR/lower_intrinsics.rs:69:5: 69:45 -+ goto -> bb1; // scope 0 at $DIR/lower_intrinsics.rs:69:5: 69:45 ++ _2 = discriminant((*_3)); // scope 0 at $DIR/lower_intrinsics.rs:74:5: 74:45 ++ goto -> bb1; // scope 0 at $DIR/lower_intrinsics.rs:74:5: 74:45 } bb1: { - StorageDead(_3); // scope 0 at $DIR/lower_intrinsics.rs:69:44: 69:45 - StorageDead(_4); // scope 0 at $DIR/lower_intrinsics.rs:69:45: 69:46 - StorageDead(_2); // scope 0 at $DIR/lower_intrinsics.rs:69:45: 69:46 - StorageLive(_5); // scope 0 at $DIR/lower_intrinsics.rs:70:5: 70:45 - StorageLive(_6); // scope 0 at $DIR/lower_intrinsics.rs:70:42: 70:44 - StorageLive(_7); // scope 0 at $DIR/lower_intrinsics.rs:70:42: 70:44 - _19 = const discriminant::::promoted[2]; // scope 0 at $DIR/lower_intrinsics.rs:70:42: 70:44 + StorageDead(_3); // scope 0 at $DIR/lower_intrinsics.rs:74:44: 74:45 + StorageDead(_4); // scope 0 at $DIR/lower_intrinsics.rs:74:45: 74:46 + StorageDead(_2); // scope 0 at $DIR/lower_intrinsics.rs:74:45: 74:46 + StorageLive(_5); // scope 0 at $DIR/lower_intrinsics.rs:75:5: 75:45 + StorageLive(_6); // scope 0 at $DIR/lower_intrinsics.rs:75:42: 75:44 + StorageLive(_7); // scope 0 at $DIR/lower_intrinsics.rs:75:42: 75:44 + _19 = const discriminant::::promoted[2]; // scope 0 at $DIR/lower_intrinsics.rs:75:42: 75:44 // ty::Const // + ty: &i32 // + val: Unevaluated(discriminant, [T], Some(promoted[2])) // mir::Constant - // + span: $DIR/lower_intrinsics.rs:70:42: 70:44 - // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:27 ~ lower_intrinsics[2872]::discriminant), const_param_did: None }, substs_: Some([T]), promoted: Some(promoted[2]) }) } - _7 = &(*_19); // scope 0 at $DIR/lower_intrinsics.rs:70:42: 70:44 - _6 = &(*_7); // scope 0 at $DIR/lower_intrinsics.rs:70:42: 70:44 -- _5 = discriminant_value::(move _6) -> bb2; // scope 0 at $DIR/lower_intrinsics.rs:70:5: 70:45 + // + span: $DIR/lower_intrinsics.rs:75:42: 75:44 + // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:29 ~ lower_intrinsics[2872]::discriminant), const_param_did: None }, substs_: Some([T]), promoted: Some(promoted[2]) }) } + _7 = &(*_19); // scope 0 at $DIR/lower_intrinsics.rs:75:42: 75:44 + _6 = &(*_7); // scope 0 at $DIR/lower_intrinsics.rs:75:42: 75:44 +- _5 = discriminant_value::(move _6) -> bb2; // scope 0 at $DIR/lower_intrinsics.rs:75:5: 75:45 - // mir::Constant -- // + span: $DIR/lower_intrinsics.rs:70:5: 70:41 +- // + span: $DIR/lower_intrinsics.rs:75:5: 75:41 - // + literal: Const { ty: for<'r> extern "rust-intrinsic" fn(&'r i32) -> ::Discriminant {std::intrinsics::discriminant_value::}, val: Value(Scalar()) } -+ _5 = discriminant((*_6)); // scope 0 at $DIR/lower_intrinsics.rs:70:5: 70:45 -+ goto -> bb2; // scope 0 at $DIR/lower_intrinsics.rs:70:5: 70:45 ++ _5 = discriminant((*_6)); // scope 0 at $DIR/lower_intrinsics.rs:75:5: 75:45 ++ goto -> bb2; // scope 0 at $DIR/lower_intrinsics.rs:75:5: 75:45 } bb2: { - StorageDead(_6); // scope 0 at $DIR/lower_intrinsics.rs:70:44: 70:45 - StorageDead(_7); // scope 0 at $DIR/lower_intrinsics.rs:70:45: 70:46 - StorageDead(_5); // scope 0 at $DIR/lower_intrinsics.rs:70:45: 70:46 - StorageLive(_9); // scope 0 at $DIR/lower_intrinsics.rs:71:5: 71:46 - StorageLive(_10); // scope 0 at $DIR/lower_intrinsics.rs:71:42: 71:45 - StorageLive(_11); // scope 0 at $DIR/lower_intrinsics.rs:71:42: 71:45 - _18 = const discriminant::::promoted[1]; // scope 0 at $DIR/lower_intrinsics.rs:71:42: 71:45 + StorageDead(_6); // scope 0 at $DIR/lower_intrinsics.rs:75:44: 75:45 + StorageDead(_7); // scope 0 at $DIR/lower_intrinsics.rs:75:45: 75:46 + StorageDead(_5); // scope 0 at $DIR/lower_intrinsics.rs:75:45: 75:46 + StorageLive(_9); // scope 0 at $DIR/lower_intrinsics.rs:76:5: 76:46 + StorageLive(_10); // scope 0 at $DIR/lower_intrinsics.rs:76:42: 76:45 + StorageLive(_11); // scope 0 at $DIR/lower_intrinsics.rs:76:42: 76:45 + _18 = const discriminant::::promoted[1]; // scope 0 at $DIR/lower_intrinsics.rs:76:42: 76:45 // ty::Const // + ty: &() // + val: Unevaluated(discriminant, [T], Some(promoted[1])) // mir::Constant - // + span: $DIR/lower_intrinsics.rs:71:42: 71:45 - // + literal: Const { ty: &(), val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:27 ~ lower_intrinsics[2872]::discriminant), const_param_did: None }, substs_: Some([T]), promoted: Some(promoted[1]) }) } - _11 = &(*_18); // scope 0 at $DIR/lower_intrinsics.rs:71:42: 71:45 - _10 = &(*_11); // scope 0 at $DIR/lower_intrinsics.rs:71:42: 71:45 -- _9 = discriminant_value::<()>(move _10) -> bb3; // scope 0 at $DIR/lower_intrinsics.rs:71:5: 71:46 + // + span: $DIR/lower_intrinsics.rs:76:42: 76:45 + // + literal: Const { ty: &(), val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:29 ~ lower_intrinsics[2872]::discriminant), const_param_did: None }, substs_: Some([T]), promoted: Some(promoted[1]) }) } + _11 = &(*_18); // scope 0 at $DIR/lower_intrinsics.rs:76:42: 76:45 + _10 = &(*_11); // scope 0 at $DIR/lower_intrinsics.rs:76:42: 76:45 +- _9 = discriminant_value::<()>(move _10) -> bb3; // scope 0 at $DIR/lower_intrinsics.rs:76:5: 76:46 - // mir::Constant -- // + span: $DIR/lower_intrinsics.rs:71:5: 71:41 +- // + span: $DIR/lower_intrinsics.rs:76:5: 76:41 - // + literal: Const { ty: for<'r> extern "rust-intrinsic" fn(&'r ()) -> <() as std::marker::DiscriminantKind>::Discriminant {std::intrinsics::discriminant_value::<()>}, val: Value(Scalar()) } -+ _9 = discriminant((*_10)); // scope 0 at $DIR/lower_intrinsics.rs:71:5: 71:46 -+ goto -> bb3; // scope 0 at $DIR/lower_intrinsics.rs:71:5: 71:46 ++ _9 = discriminant((*_10)); // scope 0 at $DIR/lower_intrinsics.rs:76:5: 76:46 ++ goto -> bb3; // scope 0 at $DIR/lower_intrinsics.rs:76:5: 76:46 } bb3: { - StorageDead(_10); // scope 0 at $DIR/lower_intrinsics.rs:71:45: 71:46 - StorageDead(_11); // scope 0 at $DIR/lower_intrinsics.rs:71:46: 71:47 - StorageDead(_9); // scope 0 at $DIR/lower_intrinsics.rs:71:46: 71:47 - StorageLive(_13); // scope 0 at $DIR/lower_intrinsics.rs:72:5: 72:48 - StorageLive(_14); // scope 0 at $DIR/lower_intrinsics.rs:72:42: 72:47 - StorageLive(_15); // scope 0 at $DIR/lower_intrinsics.rs:72:42: 72:47 - _17 = const discriminant::::promoted[0]; // scope 0 at $DIR/lower_intrinsics.rs:72:42: 72:47 + StorageDead(_10); // scope 0 at $DIR/lower_intrinsics.rs:76:45: 76:46 + StorageDead(_11); // scope 0 at $DIR/lower_intrinsics.rs:76:46: 76:47 + StorageDead(_9); // scope 0 at $DIR/lower_intrinsics.rs:76:46: 76:47 + StorageLive(_13); // scope 0 at $DIR/lower_intrinsics.rs:77:5: 77:48 + StorageLive(_14); // scope 0 at $DIR/lower_intrinsics.rs:77:42: 77:47 + StorageLive(_15); // scope 0 at $DIR/lower_intrinsics.rs:77:42: 77:47 + _17 = const discriminant::::promoted[0]; // scope 0 at $DIR/lower_intrinsics.rs:77:42: 77:47 // ty::Const // + ty: &E // + val: Unevaluated(discriminant, [T], Some(promoted[0])) // mir::Constant - // + span: $DIR/lower_intrinsics.rs:72:42: 72:47 - // + literal: Const { ty: &E, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:27 ~ lower_intrinsics[2872]::discriminant), const_param_did: None }, substs_: Some([T]), promoted: Some(promoted[0]) }) } - _15 = &(*_17); // scope 0 at $DIR/lower_intrinsics.rs:72:42: 72:47 - _14 = &(*_15); // scope 0 at $DIR/lower_intrinsics.rs:72:42: 72:47 -- _13 = discriminant_value::(move _14) -> bb4; // scope 0 at $DIR/lower_intrinsics.rs:72:5: 72:48 + // + span: $DIR/lower_intrinsics.rs:77:42: 77:47 + // + literal: Const { ty: &E, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:29 ~ lower_intrinsics[2872]::discriminant), const_param_did: None }, substs_: Some([T]), promoted: Some(promoted[0]) }) } + _15 = &(*_17); // scope 0 at $DIR/lower_intrinsics.rs:77:42: 77:47 + _14 = &(*_15); // scope 0 at $DIR/lower_intrinsics.rs:77:42: 77:47 +- _13 = discriminant_value::(move _14) -> bb4; // scope 0 at $DIR/lower_intrinsics.rs:77:5: 77:48 - // mir::Constant -- // + span: $DIR/lower_intrinsics.rs:72:5: 72:41 +- // + span: $DIR/lower_intrinsics.rs:77:5: 77:41 - // + literal: Const { ty: for<'r> extern "rust-intrinsic" fn(&'r E) -> ::Discriminant {std::intrinsics::discriminant_value::}, val: Value(Scalar()) } -+ _13 = discriminant((*_14)); // scope 0 at $DIR/lower_intrinsics.rs:72:5: 72:48 -+ goto -> bb4; // scope 0 at $DIR/lower_intrinsics.rs:72:5: 72:48 ++ _13 = discriminant((*_14)); // scope 0 at $DIR/lower_intrinsics.rs:77:5: 77:48 ++ goto -> bb4; // scope 0 at $DIR/lower_intrinsics.rs:77:5: 77:48 } bb4: { - StorageDead(_14); // scope 0 at $DIR/lower_intrinsics.rs:72:47: 72:48 - StorageDead(_15); // scope 0 at $DIR/lower_intrinsics.rs:72:48: 72:49 - StorageDead(_13); // scope 0 at $DIR/lower_intrinsics.rs:72:48: 72:49 - _0 = const (); // scope 0 at $DIR/lower_intrinsics.rs:68:30: 73:2 - drop(_1) -> bb5; // scope 0 at $DIR/lower_intrinsics.rs:73:1: 73:2 + StorageDead(_14); // scope 0 at $DIR/lower_intrinsics.rs:77:47: 77:48 + StorageDead(_15); // scope 0 at $DIR/lower_intrinsics.rs:77:48: 77:49 + StorageDead(_13); // scope 0 at $DIR/lower_intrinsics.rs:77:48: 77:49 + _0 = const (); // scope 0 at $DIR/lower_intrinsics.rs:73:30: 78:2 + drop(_1) -> bb5; // scope 0 at $DIR/lower_intrinsics.rs:78:1: 78:2 } bb5: { - return; // scope 0 at $DIR/lower_intrinsics.rs:73:2: 73:2 + return; // scope 0 at $DIR/lower_intrinsics.rs:78:2: 78:2 } bb6 (cleanup): { - resume; // scope 0 at $DIR/lower_intrinsics.rs:68:1: 73:2 + resume; // scope 0 at $DIR/lower_intrinsics.rs:73:1: 78:2 } } diff --git a/src/test/mir-opt/lower_intrinsics.f_u64.PreCodegen.before.mir b/src/test/mir-opt/lower_intrinsics.f_u64.PreCodegen.before.mir index 380f6ce9ba..2f3fd9ad28 100644 --- a/src/test/mir-opt/lower_intrinsics.f_u64.PreCodegen.before.mir +++ b/src/test/mir-opt/lower_intrinsics.f_u64.PreCodegen.before.mir @@ -1,32 +1,32 @@ // MIR for `f_u64` before PreCodegen fn f_u64() -> () { - let mut _0: (); // return place in scope 0 at $DIR/lower_intrinsics.rs:34:16: 34:16 - let mut _1: u64; // in scope 0 at $DIR/lower_intrinsics.rs:35:5: 35:21 - scope 1 (inlined f_dispatch::) { // at $DIR/lower_intrinsics.rs:35:5: 35:21 - debug t => _1; // in scope 1 at $DIR/lower_intrinsics.rs:35:5: 35:21 - let _2: (); // in scope 1 at $DIR/lower_intrinsics.rs:35:5: 35:21 - let mut _3: u64; // in scope 1 at $DIR/lower_intrinsics.rs:35:5: 35:21 - scope 2 (inlined std::mem::size_of::) { // at $DIR/lower_intrinsics.rs:35:5: 35:21 + let mut _0: (); // return place in scope 0 at $DIR/lower_intrinsics.rs:39:16: 39:16 + let mut _1: u64; // in scope 0 at $DIR/lower_intrinsics.rs:40:5: 40:21 + scope 1 (inlined f_dispatch::) { // at $DIR/lower_intrinsics.rs:40:5: 40:21 + debug t => _1; // in scope 1 at $DIR/lower_intrinsics.rs:40:5: 40:21 + let _2: (); // in scope 1 at $DIR/lower_intrinsics.rs:40:5: 40:21 + let mut _3: u64; // in scope 1 at $DIR/lower_intrinsics.rs:40:5: 40:21 + scope 2 (inlined std::mem::size_of::) { // at $DIR/lower_intrinsics.rs:40:5: 40:21 } } bb0: { - StorageLive(_1); // scope 0 at $DIR/lower_intrinsics.rs:35:5: 35:21 - _1 = const 0_u64; // scope 0 at $DIR/lower_intrinsics.rs:35:5: 35:21 - StorageLive(_2); // scope 1 at $DIR/lower_intrinsics.rs:35:5: 35:21 - StorageLive(_3); // scope 1 at $DIR/lower_intrinsics.rs:35:5: 35:21 - _3 = move _1; // scope 1 at $DIR/lower_intrinsics.rs:35:5: 35:21 - _2 = f_non_zst::(move _3) -> bb1; // scope 1 at $DIR/lower_intrinsics.rs:35:5: 35:21 + StorageLive(_1); // scope 0 at $DIR/lower_intrinsics.rs:40:5: 40:21 + _1 = const 0_u64; // scope 0 at $DIR/lower_intrinsics.rs:40:5: 40:21 + StorageLive(_2); // scope 1 at $DIR/lower_intrinsics.rs:40:5: 40:21 + StorageLive(_3); // scope 1 at $DIR/lower_intrinsics.rs:40:5: 40:21 + _3 = move _1; // scope 1 at $DIR/lower_intrinsics.rs:40:5: 40:21 + _2 = f_non_zst::(move _3) -> bb1; // scope 1 at $DIR/lower_intrinsics.rs:40:5: 40:21 // mir::Constant - // + span: $DIR/lower_intrinsics.rs:35:5: 35:21 + // + span: $DIR/lower_intrinsics.rs:40:5: 40:21 // + literal: Const { ty: fn(u64) {f_non_zst::}, val: Value(Scalar()) } } bb1: { - StorageDead(_3); // scope 1 at $DIR/lower_intrinsics.rs:35:5: 35:21 - StorageDead(_2); // scope 1 at $DIR/lower_intrinsics.rs:35:5: 35:21 - StorageDead(_1); // scope 0 at $DIR/lower_intrinsics.rs:35:5: 35:21 - return; // scope 0 at $DIR/lower_intrinsics.rs:36:2: 36:2 + StorageDead(_3); // scope 1 at $DIR/lower_intrinsics.rs:40:5: 40:21 + StorageDead(_2); // scope 1 at $DIR/lower_intrinsics.rs:40:5: 40:21 + StorageDead(_1); // scope 0 at $DIR/lower_intrinsics.rs:40:5: 40:21 + return; // scope 0 at $DIR/lower_intrinsics.rs:41:2: 41:2 } } diff --git a/src/test/mir-opt/lower_intrinsics.f_unit.PreCodegen.before.mir b/src/test/mir-opt/lower_intrinsics.f_unit.PreCodegen.before.mir index 2b9ffaaf97..690405c474 100644 --- a/src/test/mir-opt/lower_intrinsics.f_unit.PreCodegen.before.mir +++ b/src/test/mir-opt/lower_intrinsics.f_unit.PreCodegen.before.mir @@ -1,27 +1,27 @@ // MIR for `f_unit` before PreCodegen fn f_unit() -> () { - let mut _0: (); // return place in scope 0 at $DIR/lower_intrinsics.rs:28:17: 28:17 - let mut _1: (); // in scope 0 at $DIR/lower_intrinsics.rs:29:16: 29:18 - scope 1 (inlined f_dispatch::<()>) { // at $DIR/lower_intrinsics.rs:29:5: 29:19 - debug t => _1; // in scope 1 at $DIR/lower_intrinsics.rs:29:5: 29:19 - let _2: (); // in scope 1 at $DIR/lower_intrinsics.rs:29:5: 29:19 - scope 2 (inlined std::mem::size_of::<()>) { // at $DIR/lower_intrinsics.rs:29:5: 29:19 + let mut _0: (); // return place in scope 0 at $DIR/lower_intrinsics.rs:33:17: 33:17 + let mut _1: (); // in scope 0 at $DIR/lower_intrinsics.rs:34:16: 34:18 + scope 1 (inlined f_dispatch::<()>) { // at $DIR/lower_intrinsics.rs:34:5: 34:19 + debug t => _1; // in scope 1 at $DIR/lower_intrinsics.rs:34:5: 34:19 + let _2: (); // in scope 1 at $DIR/lower_intrinsics.rs:34:5: 34:19 + scope 2 (inlined std::mem::size_of::<()>) { // at $DIR/lower_intrinsics.rs:34:5: 34:19 } } bb0: { - StorageLive(_1); // scope 0 at $DIR/lower_intrinsics.rs:29:16: 29:18 - StorageLive(_2); // scope 1 at $DIR/lower_intrinsics.rs:29:5: 29:19 - _2 = f_zst::<()>(const ()) -> bb1; // scope 1 at $DIR/lower_intrinsics.rs:29:5: 29:19 + StorageLive(_1); // scope 0 at $DIR/lower_intrinsics.rs:34:16: 34:18 + StorageLive(_2); // scope 1 at $DIR/lower_intrinsics.rs:34:5: 34:19 + _2 = f_zst::<()>(const ()) -> bb1; // scope 1 at $DIR/lower_intrinsics.rs:34:5: 34:19 // mir::Constant - // + span: $DIR/lower_intrinsics.rs:29:5: 29:19 + // + span: $DIR/lower_intrinsics.rs:34:5: 34:19 // + literal: Const { ty: fn(()) {f_zst::<()>}, val: Value(Scalar()) } } bb1: { - StorageDead(_2); // scope 1 at $DIR/lower_intrinsics.rs:29:5: 29:19 - StorageDead(_1); // scope 0 at $DIR/lower_intrinsics.rs:29:18: 29:19 - return; // scope 0 at $DIR/lower_intrinsics.rs:30:2: 30:2 + StorageDead(_2); // scope 1 at $DIR/lower_intrinsics.rs:34:5: 34:19 + StorageDead(_1); // scope 0 at $DIR/lower_intrinsics.rs:34:18: 34:19 + return; // scope 0 at $DIR/lower_intrinsics.rs:35:2: 35:2 } } diff --git a/src/test/mir-opt/lower_intrinsics.forget.LowerIntrinsics.diff b/src/test/mir-opt/lower_intrinsics.forget.LowerIntrinsics.diff index 096bba64c0..7e1e066366 100644 --- a/src/test/mir-opt/lower_intrinsics.forget.LowerIntrinsics.diff +++ b/src/test/mir-opt/lower_intrinsics.forget.LowerIntrinsics.diff @@ -2,32 +2,32 @@ + // MIR for `forget` after LowerIntrinsics fn forget(_1: T) -> () { - debug t => _1; // in scope 0 at $DIR/lower_intrinsics.rs:18:18: 18:19 - let mut _0: (); // return place in scope 0 at $DIR/lower_intrinsics.rs:18:24: 18:24 - let mut _2: T; // in scope 0 at $DIR/lower_intrinsics.rs:19:30: 19:31 + debug t => _1; // in scope 0 at $DIR/lower_intrinsics.rs:23:18: 23:19 + let mut _0: (); // return place in scope 0 at $DIR/lower_intrinsics.rs:23:24: 23:24 + let mut _2: T; // in scope 0 at $DIR/lower_intrinsics.rs:24:30: 24:31 bb0: { - StorageLive(_2); // scope 0 at $DIR/lower_intrinsics.rs:19:30: 19:31 - _2 = move _1; // scope 0 at $DIR/lower_intrinsics.rs:19:30: 19:31 -- _0 = std::intrinsics::forget::(move _2) -> bb1; // scope 0 at $DIR/lower_intrinsics.rs:19:5: 19:32 + StorageLive(_2); // scope 0 at $DIR/lower_intrinsics.rs:24:30: 24:31 + _2 = move _1; // scope 0 at $DIR/lower_intrinsics.rs:24:30: 24:31 +- _0 = std::intrinsics::forget::(move _2) -> bb1; // scope 0 at $DIR/lower_intrinsics.rs:24:5: 24:32 - // mir::Constant -- // + span: $DIR/lower_intrinsics.rs:19:5: 19:29 +- // + span: $DIR/lower_intrinsics.rs:24:5: 24:29 - // + literal: Const { ty: extern "rust-intrinsic" fn(T) {std::intrinsics::forget::}, val: Value(Scalar()) } -+ _0 = const (); // scope 0 at $DIR/lower_intrinsics.rs:19:5: 19:32 -+ goto -> bb1; // scope 0 at $DIR/lower_intrinsics.rs:19:5: 19:32 ++ _0 = const (); // scope 0 at $DIR/lower_intrinsics.rs:24:5: 24:32 ++ goto -> bb1; // scope 0 at $DIR/lower_intrinsics.rs:24:5: 24:32 } bb1: { - StorageDead(_2); // scope 0 at $DIR/lower_intrinsics.rs:19:31: 19:32 - goto -> bb2; // scope 0 at $DIR/lower_intrinsics.rs:20:1: 20:2 + StorageDead(_2); // scope 0 at $DIR/lower_intrinsics.rs:24:31: 24:32 + goto -> bb2; // scope 0 at $DIR/lower_intrinsics.rs:25:1: 25:2 } bb2: { - return; // scope 0 at $DIR/lower_intrinsics.rs:20:2: 20:2 + return; // scope 0 at $DIR/lower_intrinsics.rs:25:2: 25:2 } bb3 (cleanup): { - resume; // scope 0 at $DIR/lower_intrinsics.rs:18:1: 20:2 + resume; // scope 0 at $DIR/lower_intrinsics.rs:23:1: 25:2 } } diff --git a/src/test/mir-opt/lower_intrinsics.non_const.LowerIntrinsics.diff b/src/test/mir-opt/lower_intrinsics.non_const.LowerIntrinsics.diff index 218b1c9643..276227d8c0 100644 --- a/src/test/mir-opt/lower_intrinsics.non_const.LowerIntrinsics.diff +++ b/src/test/mir-opt/lower_intrinsics.non_const.LowerIntrinsics.diff @@ -2,34 +2,34 @@ + // MIR for `non_const` after LowerIntrinsics fn non_const() -> usize { - let mut _0: usize; // return place in scope 0 at $DIR/lower_intrinsics.rs:55:26: 55:31 - let _1: extern "rust-intrinsic" fn() -> usize {std::intrinsics::size_of::}; // in scope 0 at $DIR/lower_intrinsics.rs:57:9: 57:18 - let mut _2: extern "rust-intrinsic" fn() -> usize {std::intrinsics::size_of::}; // in scope 0 at $DIR/lower_intrinsics.rs:58:5: 58:14 + let mut _0: usize; // return place in scope 0 at $DIR/lower_intrinsics.rs:60:26: 60:31 + let _1: extern "rust-intrinsic" fn() -> usize {std::intrinsics::size_of::}; // in scope 0 at $DIR/lower_intrinsics.rs:62:9: 62:18 + let mut _2: extern "rust-intrinsic" fn() -> usize {std::intrinsics::size_of::}; // in scope 0 at $DIR/lower_intrinsics.rs:63:5: 63:14 scope 1 { - debug size_of_t => _1; // in scope 1 at $DIR/lower_intrinsics.rs:57:9: 57:18 + debug size_of_t => _1; // in scope 1 at $DIR/lower_intrinsics.rs:62:9: 62:18 } bb0: { - StorageLive(_1); // scope 0 at $DIR/lower_intrinsics.rs:57:9: 57:18 - _1 = std::intrinsics::size_of::; // scope 0 at $DIR/lower_intrinsics.rs:57:21: 57:51 + StorageLive(_1); // scope 0 at $DIR/lower_intrinsics.rs:62:9: 62:18 + _1 = std::intrinsics::size_of::; // scope 0 at $DIR/lower_intrinsics.rs:62:21: 62:51 // mir::Constant - // + span: $DIR/lower_intrinsics.rs:57:21: 57:51 + // + span: $DIR/lower_intrinsics.rs:62:21: 62:51 // + literal: Const { ty: extern "rust-intrinsic" fn() -> usize {std::intrinsics::size_of::}, val: Value(Scalar()) } - StorageLive(_2); // scope 1 at $DIR/lower_intrinsics.rs:58:5: 58:14 - _2 = _1; // scope 1 at $DIR/lower_intrinsics.rs:58:5: 58:14 -- _0 = move _2() -> bb1; // scope 1 at $DIR/lower_intrinsics.rs:58:5: 58:16 -+ _0 = SizeOf(T); // scope 1 at $DIR/lower_intrinsics.rs:58:5: 58:16 -+ goto -> bb1; // scope 1 at $DIR/lower_intrinsics.rs:58:5: 58:16 + StorageLive(_2); // scope 1 at $DIR/lower_intrinsics.rs:63:5: 63:14 + _2 = _1; // scope 1 at $DIR/lower_intrinsics.rs:63:5: 63:14 +- _0 = move _2() -> bb1; // scope 1 at $DIR/lower_intrinsics.rs:63:5: 63:16 ++ _0 = SizeOf(T); // scope 1 at $DIR/lower_intrinsics.rs:63:5: 63:16 ++ goto -> bb1; // scope 1 at $DIR/lower_intrinsics.rs:63:5: 63:16 } bb1: { - StorageDead(_2); // scope 1 at $DIR/lower_intrinsics.rs:58:15: 58:16 - StorageDead(_1); // scope 0 at $DIR/lower_intrinsics.rs:59:1: 59:2 - return; // scope 0 at $DIR/lower_intrinsics.rs:59:2: 59:2 + StorageDead(_2); // scope 1 at $DIR/lower_intrinsics.rs:63:15: 63:16 + StorageDead(_1); // scope 0 at $DIR/lower_intrinsics.rs:64:1: 64:2 + return; // scope 0 at $DIR/lower_intrinsics.rs:64:2: 64:2 } bb2 (cleanup): { - resume; // scope 0 at $DIR/lower_intrinsics.rs:55:1: 59:2 + resume; // scope 0 at $DIR/lower_intrinsics.rs:60:1: 64:2 } } diff --git a/src/test/mir-opt/lower_intrinsics.rs b/src/test/mir-opt/lower_intrinsics.rs index d9891465da..8a8880dad0 100644 --- a/src/test/mir-opt/lower_intrinsics.rs +++ b/src/test/mir-opt/lower_intrinsics.rs @@ -14,6 +14,11 @@ pub fn size_of() -> usize { core::intrinsics::size_of::() } +// EMIT_MIR lower_intrinsics.align_of.LowerIntrinsics.diff +pub fn align_of() -> usize { + core::intrinsics::min_align_of::() +} + // EMIT_MIR lower_intrinsics.forget.LowerIntrinsics.diff pub fn forget(t: T) { core::intrinsics::forget(t) diff --git a/src/test/mir-opt/lower_intrinsics.unreachable.LowerIntrinsics.diff b/src/test/mir-opt/lower_intrinsics.unreachable.LowerIntrinsics.diff index a04b79d47d..50711f574f 100644 --- a/src/test/mir-opt/lower_intrinsics.unreachable.LowerIntrinsics.diff +++ b/src/test/mir-opt/lower_intrinsics.unreachable.LowerIntrinsics.diff @@ -2,25 +2,25 @@ + // MIR for `unreachable` after LowerIntrinsics fn unreachable() -> ! { - let mut _0: !; // return place in scope 0 at $DIR/lower_intrinsics.rs:23:25: 23:26 - let mut _1: !; // in scope 0 at $DIR/lower_intrinsics.rs:23:27: 25:2 - let _2: (); // in scope 0 at $DIR/lower_intrinsics.rs:24:14: 24:45 - let mut _3: !; // in scope 0 at $DIR/lower_intrinsics.rs:24:14: 24:45 + let mut _0: !; // return place in scope 0 at $DIR/lower_intrinsics.rs:28:25: 28:26 + let mut _1: !; // in scope 0 at $DIR/lower_intrinsics.rs:28:27: 30:2 + let _2: (); // in scope 0 at $DIR/lower_intrinsics.rs:29:14: 29:45 + let mut _3: !; // in scope 0 at $DIR/lower_intrinsics.rs:29:14: 29:45 scope 1 { } bb0: { - StorageLive(_2); // scope 0 at $DIR/lower_intrinsics.rs:24:5: 24:47 - StorageLive(_3); // scope 1 at $DIR/lower_intrinsics.rs:24:14: 24:45 -- std::intrinsics::unreachable(); // scope 1 at $DIR/lower_intrinsics.rs:24:14: 24:45 + StorageLive(_2); // scope 0 at $DIR/lower_intrinsics.rs:29:5: 29:47 + StorageLive(_3); // scope 1 at $DIR/lower_intrinsics.rs:29:14: 29:45 +- std::intrinsics::unreachable(); // scope 1 at $DIR/lower_intrinsics.rs:29:14: 29:45 - // mir::Constant -- // + span: $DIR/lower_intrinsics.rs:24:14: 24:43 +- // + span: $DIR/lower_intrinsics.rs:29:14: 29:43 - // + literal: Const { ty: unsafe extern "rust-intrinsic" fn() -> ! {std::intrinsics::unreachable}, val: Value(Scalar()) } -+ unreachable; // scope 1 at $DIR/lower_intrinsics.rs:24:14: 24:45 ++ unreachable; // scope 1 at $DIR/lower_intrinsics.rs:29:14: 29:45 } bb1 (cleanup): { - resume; // scope 0 at $DIR/lower_intrinsics.rs:23:1: 25:2 + resume; // scope 0 at $DIR/lower_intrinsics.rs:28:1: 30:2 } } diff --git a/src/test/mir-opt/lower_slice_len.bound.LowerSliceLenCalls.diff b/src/test/mir-opt/lower_slice_len.bound.LowerSliceLenCalls.diff index 25db3b98c2..13241d882f 100644 --- a/src/test/mir-opt/lower_slice_len.bound.LowerSliceLenCalls.diff +++ b/src/test/mir-opt/lower_slice_len.bound.LowerSliceLenCalls.diff @@ -8,7 +8,7 @@ let mut _3: bool; // in scope 0 at $DIR/lower_slice_len.rs:5:8: 5:27 let mut _4: usize; // in scope 0 at $DIR/lower_slice_len.rs:5:8: 5:13 let mut _5: usize; // in scope 0 at $DIR/lower_slice_len.rs:5:16: 5:27 - let mut _6: &[u8]; // in scope 0 at $DIR/lower_slice_len.rs:5:16: 5:21 + let mut _6: &[u8]; // in scope 0 at $DIR/lower_slice_len.rs:5:16: 5:27 let _7: usize; // in scope 0 at $DIR/lower_slice_len.rs:6:15: 6:20 let mut _8: usize; // in scope 0 at $DIR/lower_slice_len.rs:6:9: 6:21 let mut _9: bool; // in scope 0 at $DIR/lower_slice_len.rs:6:9: 6:21 @@ -18,8 +18,8 @@ StorageLive(_4); // scope 0 at $DIR/lower_slice_len.rs:5:8: 5:13 _4 = _1; // scope 0 at $DIR/lower_slice_len.rs:5:8: 5:13 StorageLive(_5); // scope 0 at $DIR/lower_slice_len.rs:5:16: 5:27 - StorageLive(_6); // scope 0 at $DIR/lower_slice_len.rs:5:16: 5:21 - _6 = &(*_2); // scope 0 at $DIR/lower_slice_len.rs:5:16: 5:21 + StorageLive(_6); // scope 0 at $DIR/lower_slice_len.rs:5:16: 5:27 + _6 = &(*_2); // scope 0 at $DIR/lower_slice_len.rs:5:16: 5:27 - _5 = core::slice::::len(move _6) -> bb1; // scope 0 at $DIR/lower_slice_len.rs:5:16: 5:27 - // mir::Constant - // + span: $DIR/lower_slice_len.rs:5:22: 5:25 diff --git a/src/test/mir-opt/no_spurious_drop_after_call.main.ElaborateDrops.before.mir b/src/test/mir-opt/no_spurious_drop_after_call.main.ElaborateDrops.before.mir index 7bdf7b6a64..5c55ee4b9b 100644 --- a/src/test/mir-opt/no_spurious_drop_after_call.main.ElaborateDrops.before.mir +++ b/src/test/mir-opt/no_spurious_drop_after_call.main.ElaborateDrops.before.mir @@ -4,13 +4,13 @@ fn main() -> () { let mut _0: (); // return place in scope 0 at $DIR/no-spurious-drop-after-call.rs:8:11: 8:11 let _1: (); // in scope 0 at $DIR/no-spurious-drop-after-call.rs:9:5: 9:35 let mut _2: std::string::String; // in scope 0 at $DIR/no-spurious-drop-after-call.rs:9:20: 9:34 - let mut _3: &str; // in scope 0 at $DIR/no-spurious-drop-after-call.rs:9:20: 9:22 + let mut _3: &str; // in scope 0 at $DIR/no-spurious-drop-after-call.rs:9:20: 9:34 let _4: &str; // in scope 0 at $DIR/no-spurious-drop-after-call.rs:9:20: 9:22 bb0: { StorageLive(_1); // scope 0 at $DIR/no-spurious-drop-after-call.rs:9:5: 9:35 StorageLive(_2); // scope 0 at $DIR/no-spurious-drop-after-call.rs:9:20: 9:34 - StorageLive(_3); // scope 0 at $DIR/no-spurious-drop-after-call.rs:9:20: 9:22 + StorageLive(_3); // scope 0 at $DIR/no-spurious-drop-after-call.rs:9:20: 9:34 StorageLive(_4); // scope 0 at $DIR/no-spurious-drop-after-call.rs:9:20: 9:22 _4 = const ""; // scope 0 at $DIR/no-spurious-drop-after-call.rs:9:20: 9:22 // ty::Const @@ -19,7 +19,7 @@ fn main() -> () { // mir::Constant // + span: $DIR/no-spurious-drop-after-call.rs:9:20: 9:22 // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [], len: Size { raw: 0 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 0 }) } - _3 = &(*_4); // scope 0 at $DIR/no-spurious-drop-after-call.rs:9:20: 9:22 + _3 = &(*_4); // scope 0 at $DIR/no-spurious-drop-after-call.rs:9:20: 9:34 _2 = ::to_string(move _3) -> bb1; // scope 0 at $DIR/no-spurious-drop-after-call.rs:9:20: 9:34 // mir::Constant // + span: $DIR/no-spurious-drop-after-call.rs:9:23: 9:32 diff --git a/src/test/mir-opt/receiver_ptr_mutability.main.mir_map.0.mir b/src/test/mir-opt/receiver_ptr_mutability.main.mir_map.0.mir index f54c8f8ab4..f1a1f388c5 100644 --- a/src/test/mir-opt/receiver_ptr_mutability.main.mir_map.0.mir +++ b/src/test/mir-opt/receiver_ptr_mutability.main.mir_map.0.mir @@ -10,15 +10,15 @@ fn main() -> () { let mut _0: (); // return place in scope 0 at $DIR/receiver-ptr-mutability.rs:13:11: 13:11 let _1: *mut Test as UserTypeProjection { base: UserType(0), projs: [] }; // in scope 0 at $DIR/receiver-ptr-mutability.rs:14:9: 14:12 let _2: (); // in scope 0 at $DIR/receiver-ptr-mutability.rs:15:5: 15:12 - let mut _3: *const Test; // in scope 0 at $DIR/receiver-ptr-mutability.rs:15:5: 15:8 + let mut _3: *const Test; // in scope 0 at $DIR/receiver-ptr-mutability.rs:15:5: 15:12 let mut _4: *mut Test; // in scope 0 at $DIR/receiver-ptr-mutability.rs:15:5: 15:8 let _6: &&&&*mut Test; // in scope 0 at $DIR/receiver-ptr-mutability.rs:18:34: 18:41 let _7: &&&*mut Test; // in scope 0 at $DIR/receiver-ptr-mutability.rs:18:35: 18:41 let _8: &&*mut Test; // in scope 0 at $DIR/receiver-ptr-mutability.rs:18:36: 18:41 let _9: &*mut Test; // in scope 0 at $DIR/receiver-ptr-mutability.rs:18:37: 18:41 let _10: (); // in scope 0 at $DIR/receiver-ptr-mutability.rs:19:5: 19:16 - let mut _11: *const Test; // in scope 0 at $DIR/receiver-ptr-mutability.rs:19:5: 19:12 - let mut _12: *mut Test; // in scope 0 at $DIR/receiver-ptr-mutability.rs:19:5: 19:12 + let mut _11: *const Test; // in scope 0 at $DIR/receiver-ptr-mutability.rs:19:5: 19:16 + let mut _12: *mut Test; // in scope 0 at $DIR/receiver-ptr-mutability.rs:19:5: 19:16 scope 1 { debug ptr => _1; // in scope 1 at $DIR/receiver-ptr-mutability.rs:14:9: 14:12 let _5: &&&&*mut Test as UserTypeProjection { base: UserType(2), projs: [] }; // in scope 1 at $DIR/receiver-ptr-mutability.rs:18:9: 18:16 @@ -39,10 +39,10 @@ fn main() -> () { FakeRead(ForLet(None), _1); // scope 0 at $DIR/receiver-ptr-mutability.rs:14:9: 14:12 AscribeUserType(_1, o, UserTypeProjection { base: UserType(1), projs: [] }); // scope 0 at $DIR/receiver-ptr-mutability.rs:14:14: 14:23 StorageLive(_2); // scope 1 at $DIR/receiver-ptr-mutability.rs:15:5: 15:12 - StorageLive(_3); // scope 1 at $DIR/receiver-ptr-mutability.rs:15:5: 15:8 + StorageLive(_3); // scope 1 at $DIR/receiver-ptr-mutability.rs:15:5: 15:12 StorageLive(_4); // scope 1 at $DIR/receiver-ptr-mutability.rs:15:5: 15:8 _4 = _1; // scope 1 at $DIR/receiver-ptr-mutability.rs:15:5: 15:8 - _3 = move _4 as *const Test (Pointer(MutToConstPointer)); // scope 1 at $DIR/receiver-ptr-mutability.rs:15:5: 15:8 + _3 = move _4 as *const Test (Pointer(MutToConstPointer)); // scope 1 at $DIR/receiver-ptr-mutability.rs:15:5: 15:12 StorageDead(_4); // scope 1 at $DIR/receiver-ptr-mutability.rs:15:7: 15:8 _2 = Test::x(move _3) -> [return: bb2, unwind: bb4]; // scope 1 at $DIR/receiver-ptr-mutability.rs:15:5: 15:12 // mir::Constant @@ -67,10 +67,10 @@ fn main() -> () { AscribeUserType(_5, o, UserTypeProjection { base: UserType(3), projs: [] }); // scope 1 at $DIR/receiver-ptr-mutability.rs:18:18: 18:31 StorageDead(_6); // scope 1 at $DIR/receiver-ptr-mutability.rs:18:41: 18:42 StorageLive(_10); // scope 2 at $DIR/receiver-ptr-mutability.rs:19:5: 19:16 - StorageLive(_11); // scope 2 at $DIR/receiver-ptr-mutability.rs:19:5: 19:12 - StorageLive(_12); // scope 2 at $DIR/receiver-ptr-mutability.rs:19:5: 19:12 - _12 = (*(*(*(*_5)))); // scope 2 at $DIR/receiver-ptr-mutability.rs:19:5: 19:12 - _11 = move _12 as *const Test (Pointer(MutToConstPointer)); // scope 2 at $DIR/receiver-ptr-mutability.rs:19:5: 19:12 + StorageLive(_11); // scope 2 at $DIR/receiver-ptr-mutability.rs:19:5: 19:16 + StorageLive(_12); // scope 2 at $DIR/receiver-ptr-mutability.rs:19:5: 19:16 + _12 = (*(*(*(*_5)))); // scope 2 at $DIR/receiver-ptr-mutability.rs:19:5: 19:16 + _11 = move _12 as *const Test (Pointer(MutToConstPointer)); // scope 2 at $DIR/receiver-ptr-mutability.rs:19:5: 19:16 StorageDead(_12); // scope 2 at $DIR/receiver-ptr-mutability.rs:19:11: 19:12 _10 = Test::x(move _11) -> [return: bb3, unwind: bb4]; // scope 2 at $DIR/receiver-ptr-mutability.rs:19:5: 19:16 // mir::Constant diff --git a/src/test/mir-opt/remove-never-const.rs b/src/test/mir-opt/remove-never-const.rs index 1673f14b45..017746647a 100644 --- a/src/test/mir-opt/remove-never-const.rs +++ b/src/test/mir-opt/remove-never-const.rs @@ -5,7 +5,6 @@ // Force generation of optimized mir for functions that do not reach codegen. // compile-flags: --emit mir,link -#![feature(const_panic)] #![feature(never_type)] #![warn(const_err)] diff --git a/src/test/mir-opt/remove_never_const.no_codegen.PreCodegen.after.mir b/src/test/mir-opt/remove_never_const.no_codegen.PreCodegen.after.mir index 6f4a024d20..bf62c8441f 100644 --- a/src/test/mir-opt/remove_never_const.no_codegen.PreCodegen.after.mir +++ b/src/test/mir-opt/remove_never_const.no_codegen.PreCodegen.after.mir @@ -1,11 +1,11 @@ // MIR for `no_codegen` after PreCodegen fn no_codegen() -> () { - let mut _0: (); // return place in scope 0 at $DIR/remove-never-const.rs:19:20: 19:20 + let mut _0: (); // return place in scope 0 at $DIR/remove-never-const.rs:18:20: 18:20 scope 1 { } bb0: { - unreachable; // scope 0 at $DIR/remove-never-const.rs:20:13: 20:33 + unreachable; // scope 0 at $DIR/remove-never-const.rs:19:13: 19:33 } } 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 6d6c272197..02f6e55a9a 100644 --- a/src/test/mir-opt/remove_storage_markers.main.RemoveStorageMarkers.diff +++ b/src/test/mir-opt/remove_storage_markers.main.RemoveStorageMarkers.diff @@ -80,7 +80,7 @@ - StorageDead(_7); // scope 3 at $DIR/remove_storage_markers.rs:8:18: 8:19 - 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:8:18: 8:19 +- 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 } diff --git a/src/test/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.mir b/src/test/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.mir index cdf7282c8c..6bb92c5e6b 100644 --- a/src/test/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.mir +++ b/src/test/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.mir @@ -4,7 +4,7 @@ fn main() -> () { let mut _0: (); // return place in scope 0 at $DIR/retag.rs:29:11: 29:11 let mut _1: i32; // in scope 0 at $DIR/retag.rs:30:9: 30:14 let _2: (); // in scope 0 at $DIR/retag.rs:31:5: 37:6 - let mut _4: &Test; // in scope 0 at $DIR/retag.rs:32:17: 32:24 + let mut _4: &Test; // in scope 0 at $DIR/retag.rs:32:17: 32:36 let _5: Test; // in scope 0 at $DIR/retag.rs:32:17: 32:24 let mut _6: &mut i32; // in scope 0 at $DIR/retag.rs:32:29: 32:35 let mut _7: &mut i32; // in scope 0 at $DIR/retag.rs:32:29: 32:35 @@ -15,7 +15,7 @@ fn main() -> () { let mut _17: &i32; // in scope 0 at $DIR/retag.rs:44:16: 44:18 let _18: &i32; // in scope 0 at $DIR/retag.rs:44:16: 44:18 let _19: &i32; // in scope 0 at $DIR/retag.rs:47:5: 47:24 - let mut _20: &Test; // in scope 0 at $DIR/retag.rs:47:5: 47:12 + let mut _20: &Test; // in scope 0 at $DIR/retag.rs:47:5: 47:24 let _21: Test; // in scope 0 at $DIR/retag.rs:47:5: 47:12 let mut _22: &i32; // in scope 0 at $DIR/retag.rs:47:21: 47:23 let _23: &i32; // in scope 0 at $DIR/retag.rs:47:21: 47:23 @@ -60,11 +60,11 @@ fn main() -> () { _1 = const 0_i32; // scope 0 at $DIR/retag.rs:30:17: 30:18 StorageLive(_2); // scope 1 at $DIR/retag.rs:31:5: 37:6 StorageLive(_3); // scope 1 at $DIR/retag.rs:32:13: 32:14 - StorageLive(_4); // scope 1 at $DIR/retag.rs:32:17: 32:24 + StorageLive(_4); // scope 1 at $DIR/retag.rs:32:17: 32:36 StorageLive(_5); // scope 1 at $DIR/retag.rs:32:17: 32:24 _5 = Test(const 0_i32); // scope 1 at $DIR/retag.rs:32:17: 32:24 - _4 = &_5; // scope 1 at $DIR/retag.rs:32:17: 32:24 - Retag(_4); // scope 1 at $DIR/retag.rs:32:17: 32:24 + _4 = &_5; // scope 1 at $DIR/retag.rs:32:17: 32:36 + Retag(_4); // scope 1 at $DIR/retag.rs:32:17: 32:36 StorageLive(_6); // scope 1 at $DIR/retag.rs:32:29: 32:35 StorageLive(_7); // scope 1 at $DIR/retag.rs:32:29: 32:35 _7 = &mut _1; // scope 1 at $DIR/retag.rs:32:29: 32:35 @@ -140,11 +140,11 @@ fn main() -> () { StorageDead(_16); // scope 6 at $DIR/retag.rs:44:18: 44:19 StorageDead(_18); // scope 6 at $DIR/retag.rs:44:19: 44:20 StorageLive(_19); // scope 7 at $DIR/retag.rs:47:5: 47:24 - StorageLive(_20); // scope 7 at $DIR/retag.rs:47:5: 47:12 + StorageLive(_20); // scope 7 at $DIR/retag.rs:47:5: 47:24 StorageLive(_21); // scope 7 at $DIR/retag.rs:47:5: 47:12 _21 = Test(const 0_i32); // scope 7 at $DIR/retag.rs:47:5: 47:12 - _20 = &_21; // scope 7 at $DIR/retag.rs:47:5: 47:12 - Retag(_20); // scope 7 at $DIR/retag.rs:47:5: 47:12 + _20 = &_21; // scope 7 at $DIR/retag.rs:47:5: 47:24 + Retag(_20); // scope 7 at $DIR/retag.rs:47:5: 47:24 StorageLive(_22); // scope 7 at $DIR/retag.rs:47:21: 47:23 StorageLive(_23); // scope 7 at $DIR/retag.rs:47:21: 47:23 _28 = const main::promoted[0]; // scope 7 at $DIR/retag.rs:47:21: 47:23 diff --git a/src/test/mir-opt/simplify_cfg.main.SimplifyCfg-early-opt.diff b/src/test/mir-opt/simplify_cfg.main.SimplifyCfg-early-opt.diff index eac9328500..1c5a890023 100644 --- a/src/test/mir-opt/simplify_cfg.main.SimplifyCfg-early-opt.diff +++ b/src/test/mir-opt/simplify_cfg.main.SimplifyCfg-early-opt.diff @@ -8,40 +8,44 @@ let mut _3: !; // in scope 0 at $DIR/simplify_cfg.rs:9:18: 11:10 bb0: { -- goto -> bb1; // scope 0 at $DIR/simplify_cfg.rs:8:5: 12:6 + goto -> bb1; // scope 0 at $DIR/simplify_cfg.rs:8:5: 12:6 + } + + bb1: { +- goto -> bb2; // scope 0 at $DIR/simplify_cfg.rs:8:5: 12:6 - } - -- bb1: { +- bb2: { StorageLive(_2); // scope 0 at $DIR/simplify_cfg.rs:9:12: 9:17 -- _2 = bar() -> [return: bb2, unwind: bb5]; // scope 0 at $DIR/simplify_cfg.rs:9:12: 9:17 -+ _2 = bar() -> [return: bb1, unwind: bb4]; // scope 0 at $DIR/simplify_cfg.rs:9:12: 9:17 +- _2 = bar() -> [return: bb3, unwind: bb6]; // scope 0 at $DIR/simplify_cfg.rs:9:12: 9:17 ++ _2 = bar() -> [return: bb2, unwind: bb5]; // scope 0 at $DIR/simplify_cfg.rs:9:12: 9:17 // mir::Constant // + span: $DIR/simplify_cfg.rs:9:12: 9:15 // + literal: Const { ty: fn() -> bool {bar}, val: Value(Scalar()) } } -- bb2: { -- switchInt(move _2) -> [false: bb4, otherwise: bb3]; // scope 0 at $DIR/simplify_cfg.rs:9:12: 9:17 -+ bb1: { -+ switchInt(move _2) -> [false: bb3, otherwise: bb2]; // scope 0 at $DIR/simplify_cfg.rs:9:12: 9:17 +- bb3: { +- switchInt(move _2) -> [false: bb5, otherwise: bb4]; // scope 0 at $DIR/simplify_cfg.rs:9:12: 9:17 ++ bb2: { ++ switchInt(move _2) -> [false: bb4, otherwise: bb3]; // scope 0 at $DIR/simplify_cfg.rs:9:12: 9:17 } -- bb3: { -+ bb2: { +- bb4: { ++ bb3: { _0 = const (); // scope 0 at $DIR/simplify_cfg.rs:10:13: 10:18 StorageDead(_2); // scope 0 at $DIR/simplify_cfg.rs:11:9: 11:10 return; // scope 0 at $DIR/simplify_cfg.rs:13:2: 13:2 } -- bb4: { -+ bb3: { +- bb5: { ++ bb4: { _1 = const (); // scope 0 at $DIR/simplify_cfg.rs:11:10: 11:10 StorageDead(_2); // scope 0 at $DIR/simplify_cfg.rs:11:9: 11:10 - goto -> bb0; // scope 0 at $DIR/simplify_cfg.rs:8:5: 12:6 + goto -> bb1; // scope 0 at $DIR/simplify_cfg.rs:8:5: 12:6 } -- bb5 (cleanup): { -+ bb4 (cleanup): { +- bb6 (cleanup): { ++ bb5 (cleanup): { resume; // scope 0 at $DIR/simplify_cfg.rs:7:1: 13:2 } } diff --git a/src/test/mir-opt/simplify_cfg.main.SimplifyCfg-initial.diff b/src/test/mir-opt/simplify_cfg.main.SimplifyCfg-initial.diff index f5ac2a41f5..b079bd7b57 100644 --- a/src/test/mir-opt/simplify_cfg.main.SimplifyCfg-initial.diff +++ b/src/test/mir-opt/simplify_cfg.main.SimplifyCfg-initial.diff @@ -8,38 +8,35 @@ let mut _3: !; // in scope 0 at $DIR/simplify_cfg.rs:9:18: 11:10 bb0: { -- goto -> bb1; // scope 0 at $DIR/simplify_cfg.rs:8:5: 12:6 -+ falseUnwind -> [real: bb1, cleanup: bb5]; // scope 0 at $DIR/simplify_cfg.rs:8:5: 12:6 + goto -> bb1; // scope 0 at $DIR/simplify_cfg.rs:8:5: 12:6 } bb1: { - falseUnwind -> [real: bb2, cleanup: bb11]; // scope 0 at $DIR/simplify_cfg.rs:8:5: 12:6 -- } -- -- bb2: { ++ falseUnwind -> [real: bb2, cleanup: bb6]; // scope 0 at $DIR/simplify_cfg.rs:8:5: 12:6 + } + + bb2: { StorageLive(_2); // scope 0 at $DIR/simplify_cfg.rs:9:12: 9:17 - _2 = bar() -> [return: bb3, unwind: bb11]; // scope 0 at $DIR/simplify_cfg.rs:9:12: 9:17 -+ _2 = bar() -> [return: bb2, unwind: bb5]; // scope 0 at $DIR/simplify_cfg.rs:9:12: 9:17 ++ _2 = bar() -> [return: bb3, unwind: bb6]; // scope 0 at $DIR/simplify_cfg.rs:9:12: 9:17 // mir::Constant // + span: $DIR/simplify_cfg.rs:9:12: 9:15 // + literal: Const { ty: fn() -> bool {bar}, val: Value(Scalar()) } } -- bb3: { -- switchInt(move _2) -> [false: bb5, otherwise: bb4]; // scope 0 at $DIR/simplify_cfg.rs:9:12: 9:17 -+ bb2: { -+ switchInt(move _2) -> [false: bb4, otherwise: bb3]; // scope 0 at $DIR/simplify_cfg.rs:9:12: 9:17 + bb3: { + switchInt(move _2) -> [false: bb5, otherwise: bb4]; // scope 0 at $DIR/simplify_cfg.rs:9:12: 9:17 } -- bb4: { -+ bb3: { + bb4: { _0 = const (); // scope 0 at $DIR/simplify_cfg.rs:10:13: 10:18 - goto -> bb10; // scope 0 at $DIR/simplify_cfg.rs:10:13: 10:18 + StorageDead(_2); // scope 0 at $DIR/simplify_cfg.rs:11:9: 11:10 + return; // scope 0 at $DIR/simplify_cfg.rs:13:2: 13:2 } -- bb5: { + bb5: { - goto -> bb8; // scope 0 at $DIR/simplify_cfg.rs:9:12: 9:17 - } - @@ -52,15 +49,13 @@ - } - - bb8: { -+ bb4: { _1 = const (); // scope 0 at $DIR/simplify_cfg.rs:11:10: 11:10 - goto -> bb9; // scope 0 at $DIR/simplify_cfg.rs:9:9: 11:10 - } - - bb9: { StorageDead(_2); // scope 0 at $DIR/simplify_cfg.rs:11:9: 11:10 -- goto -> bb1; // scope 0 at $DIR/simplify_cfg.rs:8:5: 12:6 -+ goto -> bb0; // scope 0 at $DIR/simplify_cfg.rs:8:5: 12:6 + goto -> bb1; // scope 0 at $DIR/simplify_cfg.rs:8:5: 12:6 } - bb10: { @@ -69,7 +64,7 @@ - } - - bb11 (cleanup): { -+ bb5 (cleanup): { ++ bb6 (cleanup): { resume; // scope 0 at $DIR/simplify_cfg.rs:7:1: 13:2 } } diff --git a/src/test/mir-opt/uniform_array_move_out.move_out_by_subslice.mir_map.0.mir b/src/test/mir-opt/uniform_array_move_out.move_out_by_subslice.mir_map.0.mir index 7f81d9fc48..d7d2cdf9b0 100644 --- a/src/test/mir-opt/uniform_array_move_out.move_out_by_subslice.mir_map.0.mir +++ b/src/test/mir-opt/uniform_array_move_out.move_out_by_subslice.mir_map.0.mir @@ -4,80 +4,108 @@ fn move_out_by_subslice() -> () { let mut _0: (); // return place in scope 0 at $DIR/uniform_array_move_out.rs:10:27: 10:27 let _1: [std::boxed::Box; 2]; // in scope 0 at $DIR/uniform_array_move_out.rs:11:9: 11:10 let mut _2: std::boxed::Box; // in scope 0 at $DIR/uniform_array_move_out.rs:11:14: 11:19 - let mut _3: std::boxed::Box; // in scope 0 at $DIR/uniform_array_move_out.rs:11:14: 11:19 - let mut _4: std::boxed::Box; // in scope 0 at $DIR/uniform_array_move_out.rs:11:21: 11:26 - let mut _5: std::boxed::Box; // in scope 0 at $DIR/uniform_array_move_out.rs:11:21: 11:26 + let mut _3: usize; // in scope 0 at $DIR/uniform_array_move_out.rs:11:14: 11:19 + let mut _4: usize; // in scope 0 at $DIR/uniform_array_move_out.rs:11:14: 11:19 + let mut _5: *mut u8; // in scope 0 at $DIR/uniform_array_move_out.rs:11:14: 11:19 + let mut _6: std::boxed::Box; // in scope 0 at $DIR/uniform_array_move_out.rs:11:14: 11:19 + let mut _7: std::boxed::Box; // in scope 0 at $DIR/uniform_array_move_out.rs:11:21: 11:26 + let mut _8: usize; // in scope 0 at $DIR/uniform_array_move_out.rs:11:21: 11:26 + let mut _9: usize; // in scope 0 at $DIR/uniform_array_move_out.rs:11:21: 11:26 + let mut _10: *mut u8; // in scope 0 at $DIR/uniform_array_move_out.rs:11:21: 11:26 + let mut _11: std::boxed::Box; // in scope 0 at $DIR/uniform_array_move_out.rs:11:21: 11:26 scope 1 { debug a => _1; // in scope 1 at $DIR/uniform_array_move_out.rs:11:9: 11:10 - let _6: [std::boxed::Box; 2]; // in scope 1 at $DIR/uniform_array_move_out.rs:12:10: 12:17 - scope 2 { - debug _y => _6; // in scope 2 at $DIR/uniform_array_move_out.rs:12:10: 12:17 + let _12: [std::boxed::Box; 2]; // in scope 1 at $DIR/uniform_array_move_out.rs:12:10: 12:17 + scope 4 { + debug _y => _12; // in scope 4 at $DIR/uniform_array_move_out.rs:12:10: 12:17 } } + scope 2 { + } + scope 3 { + } bb0: { StorageLive(_1); // scope 0 at $DIR/uniform_array_move_out.rs:11:9: 11:10 StorageLive(_2); // scope 0 at $DIR/uniform_array_move_out.rs:11:14: 11:19 - StorageLive(_3); // scope 0 at $DIR/uniform_array_move_out.rs:11:14: 11:19 - _3 = Box(i32); // scope 0 at $DIR/uniform_array_move_out.rs:11:14: 11:19 - (*_3) = const 1_i32; // scope 0 at $DIR/uniform_array_move_out.rs:11:18: 11:19 - _2 = move _3; // scope 0 at $DIR/uniform_array_move_out.rs:11:14: 11:19 - drop(_3) -> [return: bb1, unwind: bb9]; // scope 0 at $DIR/uniform_array_move_out.rs:11:18: 11:19 + _3 = SizeOf(i32); // scope 2 at $DIR/uniform_array_move_out.rs:11:14: 11:19 + _4 = AlignOf(i32); // scope 2 at $DIR/uniform_array_move_out.rs:11:14: 11:19 + _5 = alloc::alloc::exchange_malloc(move _3, move _4) -> [return: bb1, unwind: bb12]; // scope 2 at $DIR/uniform_array_move_out.rs:11:14: 11:19 + // mir::Constant + // + span: $DIR/uniform_array_move_out.rs:11:14: 11:19 + // + literal: Const { ty: unsafe fn(usize, usize) -> *mut u8 {alloc::alloc::exchange_malloc}, val: Value(Scalar()) } } bb1: { - StorageDead(_3); // scope 0 at $DIR/uniform_array_move_out.rs:11:18: 11:19 - StorageLive(_4); // scope 0 at $DIR/uniform_array_move_out.rs:11:21: 11:26 - StorageLive(_5); // scope 0 at $DIR/uniform_array_move_out.rs:11:21: 11:26 - _5 = Box(i32); // scope 0 at $DIR/uniform_array_move_out.rs:11:21: 11:26 - (*_5) = const 2_i32; // scope 0 at $DIR/uniform_array_move_out.rs:11:25: 11:26 - _4 = move _5; // scope 0 at $DIR/uniform_array_move_out.rs:11:21: 11:26 - drop(_5) -> [return: bb2, unwind: bb8]; // scope 0 at $DIR/uniform_array_move_out.rs:11:25: 11:26 + StorageLive(_6); // scope 0 at $DIR/uniform_array_move_out.rs:11:14: 11:19 + _6 = ShallowInitBox(move _5, i32); // scope 0 at $DIR/uniform_array_move_out.rs:11:14: 11:19 + (*_6) = const 1_i32; // scope 0 at $DIR/uniform_array_move_out.rs:11:18: 11:19 + _2 = move _6; // scope 0 at $DIR/uniform_array_move_out.rs:11:14: 11:19 + drop(_6) -> [return: bb2, unwind: bb11]; // scope 0 at $DIR/uniform_array_move_out.rs:11:18: 11:19 } bb2: { - StorageDead(_5); // scope 0 at $DIR/uniform_array_move_out.rs:11:25: 11:26 - _1 = [move _2, move _4]; // scope 0 at $DIR/uniform_array_move_out.rs:11:13: 11:27 - drop(_4) -> [return: bb3, unwind: bb9]; // scope 0 at $DIR/uniform_array_move_out.rs:11:26: 11:27 + StorageDead(_6); // scope 0 at $DIR/uniform_array_move_out.rs:11:18: 11:19 + StorageLive(_7); // scope 0 at $DIR/uniform_array_move_out.rs:11:21: 11:26 + _8 = SizeOf(i32); // scope 3 at $DIR/uniform_array_move_out.rs:11:21: 11:26 + _9 = AlignOf(i32); // scope 3 at $DIR/uniform_array_move_out.rs:11:21: 11:26 + _10 = alloc::alloc::exchange_malloc(move _8, move _9) -> [return: bb3, unwind: bb11]; // scope 3 at $DIR/uniform_array_move_out.rs:11:21: 11:26 + // mir::Constant + // + span: $DIR/uniform_array_move_out.rs:11:21: 11:26 + // + literal: Const { ty: unsafe fn(usize, usize) -> *mut u8 {alloc::alloc::exchange_malloc}, val: Value(Scalar()) } } bb3: { - StorageDead(_4); // scope 0 at $DIR/uniform_array_move_out.rs:11:26: 11:27 - drop(_2) -> [return: bb4, unwind: bb10]; // scope 0 at $DIR/uniform_array_move_out.rs:11:26: 11:27 + StorageLive(_11); // scope 0 at $DIR/uniform_array_move_out.rs:11:21: 11:26 + _11 = ShallowInitBox(move _10, i32); // scope 0 at $DIR/uniform_array_move_out.rs:11:21: 11:26 + (*_11) = const 2_i32; // scope 0 at $DIR/uniform_array_move_out.rs:11:25: 11:26 + _7 = move _11; // scope 0 at $DIR/uniform_array_move_out.rs:11:21: 11:26 + drop(_11) -> [return: bb4, unwind: bb10]; // scope 0 at $DIR/uniform_array_move_out.rs:11:25: 11:26 } bb4: { - StorageDead(_2); // scope 0 at $DIR/uniform_array_move_out.rs:11:26: 11:27 - FakeRead(ForLet(None), _1); // scope 0 at $DIR/uniform_array_move_out.rs:11:9: 11:10 - StorageLive(_6); // scope 1 at $DIR/uniform_array_move_out.rs:12:10: 12:17 - _6 = move _1[0..2]; // scope 1 at $DIR/uniform_array_move_out.rs:12:10: 12:17 - _0 = const (); // scope 0 at $DIR/uniform_array_move_out.rs:10:27: 13:2 - drop(_6) -> [return: bb5, unwind: bb7]; // scope 1 at $DIR/uniform_array_move_out.rs:13:1: 13:2 + StorageDead(_11); // scope 0 at $DIR/uniform_array_move_out.rs:11:25: 11:26 + _1 = [move _2, move _7]; // scope 0 at $DIR/uniform_array_move_out.rs:11:13: 11:27 + drop(_7) -> [return: bb5, unwind: bb11]; // scope 0 at $DIR/uniform_array_move_out.rs:11:26: 11:27 } bb5: { - StorageDead(_6); // scope 1 at $DIR/uniform_array_move_out.rs:13:1: 13:2 - drop(_1) -> [return: bb6, unwind: bb10]; // scope 0 at $DIR/uniform_array_move_out.rs:13:1: 13:2 + StorageDead(_7); // scope 0 at $DIR/uniform_array_move_out.rs:11:26: 11:27 + drop(_2) -> [return: bb6, unwind: bb12]; // scope 0 at $DIR/uniform_array_move_out.rs:11:26: 11:27 } bb6: { + StorageDead(_2); // scope 0 at $DIR/uniform_array_move_out.rs:11:26: 11:27 + FakeRead(ForLet(None), _1); // scope 0 at $DIR/uniform_array_move_out.rs:11:9: 11:10 + StorageLive(_12); // scope 1 at $DIR/uniform_array_move_out.rs:12:10: 12:17 + _12 = move _1[0..2]; // scope 1 at $DIR/uniform_array_move_out.rs:12:10: 12:17 + _0 = const (); // scope 0 at $DIR/uniform_array_move_out.rs:10:27: 13:2 + drop(_12) -> [return: bb7, unwind: bb9]; // scope 1 at $DIR/uniform_array_move_out.rs:13:1: 13:2 + } + + bb7: { + StorageDead(_12); // scope 1 at $DIR/uniform_array_move_out.rs:13:1: 13:2 + drop(_1) -> [return: bb8, unwind: bb12]; // scope 0 at $DIR/uniform_array_move_out.rs:13:1: 13:2 + } + + bb8: { StorageDead(_1); // scope 0 at $DIR/uniform_array_move_out.rs:13:1: 13:2 return; // scope 0 at $DIR/uniform_array_move_out.rs:13:2: 13:2 } - bb7 (cleanup): { - drop(_1) -> bb10; // scope 0 at $DIR/uniform_array_move_out.rs:13:1: 13:2 - } - - bb8 (cleanup): { - drop(_4) -> bb9; // scope 0 at $DIR/uniform_array_move_out.rs:11:26: 11:27 - } - bb9 (cleanup): { - drop(_2) -> bb10; // scope 0 at $DIR/uniform_array_move_out.rs:11:26: 11:27 + drop(_1) -> bb12; // scope 0 at $DIR/uniform_array_move_out.rs:13:1: 13:2 } bb10 (cleanup): { + drop(_7) -> bb11; // scope 0 at $DIR/uniform_array_move_out.rs:11:26: 11:27 + } + + bb11 (cleanup): { + drop(_2) -> bb12; // scope 0 at $DIR/uniform_array_move_out.rs:11:26: 11:27 + } + + bb12 (cleanup): { resume; // scope 0 at $DIR/uniform_array_move_out.rs:10:1: 13:2 } } diff --git a/src/test/mir-opt/uniform_array_move_out.move_out_from_end.mir_map.0.mir b/src/test/mir-opt/uniform_array_move_out.move_out_from_end.mir_map.0.mir index 62ab494c06..18bc1a17c1 100644 --- a/src/test/mir-opt/uniform_array_move_out.move_out_from_end.mir_map.0.mir +++ b/src/test/mir-opt/uniform_array_move_out.move_out_from_end.mir_map.0.mir @@ -4,80 +4,108 @@ fn move_out_from_end() -> () { let mut _0: (); // return place in scope 0 at $DIR/uniform_array_move_out.rs:4:24: 4:24 let _1: [std::boxed::Box; 2]; // in scope 0 at $DIR/uniform_array_move_out.rs:5:9: 5:10 let mut _2: std::boxed::Box; // in scope 0 at $DIR/uniform_array_move_out.rs:5:14: 5:19 - let mut _3: std::boxed::Box; // in scope 0 at $DIR/uniform_array_move_out.rs:5:14: 5:19 - let mut _4: std::boxed::Box; // in scope 0 at $DIR/uniform_array_move_out.rs:5:21: 5:26 - let mut _5: std::boxed::Box; // in scope 0 at $DIR/uniform_array_move_out.rs:5:21: 5:26 + let mut _3: usize; // in scope 0 at $DIR/uniform_array_move_out.rs:5:14: 5:19 + let mut _4: usize; // in scope 0 at $DIR/uniform_array_move_out.rs:5:14: 5:19 + let mut _5: *mut u8; // in scope 0 at $DIR/uniform_array_move_out.rs:5:14: 5:19 + let mut _6: std::boxed::Box; // in scope 0 at $DIR/uniform_array_move_out.rs:5:14: 5:19 + let mut _7: std::boxed::Box; // in scope 0 at $DIR/uniform_array_move_out.rs:5:21: 5:26 + let mut _8: usize; // in scope 0 at $DIR/uniform_array_move_out.rs:5:21: 5:26 + let mut _9: usize; // in scope 0 at $DIR/uniform_array_move_out.rs:5:21: 5:26 + let mut _10: *mut u8; // in scope 0 at $DIR/uniform_array_move_out.rs:5:21: 5:26 + let mut _11: std::boxed::Box; // in scope 0 at $DIR/uniform_array_move_out.rs:5:21: 5:26 scope 1 { debug a => _1; // in scope 1 at $DIR/uniform_array_move_out.rs:5:9: 5:10 - let _6: std::boxed::Box; // in scope 1 at $DIR/uniform_array_move_out.rs:6:14: 6:16 - scope 2 { - debug _y => _6; // in scope 2 at $DIR/uniform_array_move_out.rs:6:14: 6:16 + let _12: std::boxed::Box; // in scope 1 at $DIR/uniform_array_move_out.rs:6:14: 6:16 + scope 4 { + debug _y => _12; // in scope 4 at $DIR/uniform_array_move_out.rs:6:14: 6:16 } } + scope 2 { + } + scope 3 { + } bb0: { StorageLive(_1); // scope 0 at $DIR/uniform_array_move_out.rs:5:9: 5:10 StorageLive(_2); // scope 0 at $DIR/uniform_array_move_out.rs:5:14: 5:19 - StorageLive(_3); // scope 0 at $DIR/uniform_array_move_out.rs:5:14: 5:19 - _3 = Box(i32); // scope 0 at $DIR/uniform_array_move_out.rs:5:14: 5:19 - (*_3) = const 1_i32; // scope 0 at $DIR/uniform_array_move_out.rs:5:18: 5:19 - _2 = move _3; // scope 0 at $DIR/uniform_array_move_out.rs:5:14: 5:19 - drop(_3) -> [return: bb1, unwind: bb9]; // scope 0 at $DIR/uniform_array_move_out.rs:5:18: 5:19 + _3 = SizeOf(i32); // scope 2 at $DIR/uniform_array_move_out.rs:5:14: 5:19 + _4 = AlignOf(i32); // scope 2 at $DIR/uniform_array_move_out.rs:5:14: 5:19 + _5 = alloc::alloc::exchange_malloc(move _3, move _4) -> [return: bb1, unwind: bb12]; // scope 2 at $DIR/uniform_array_move_out.rs:5:14: 5:19 + // mir::Constant + // + span: $DIR/uniform_array_move_out.rs:5:14: 5:19 + // + literal: Const { ty: unsafe fn(usize, usize) -> *mut u8 {alloc::alloc::exchange_malloc}, val: Value(Scalar()) } } bb1: { - StorageDead(_3); // scope 0 at $DIR/uniform_array_move_out.rs:5:18: 5:19 - StorageLive(_4); // scope 0 at $DIR/uniform_array_move_out.rs:5:21: 5:26 - StorageLive(_5); // scope 0 at $DIR/uniform_array_move_out.rs:5:21: 5:26 - _5 = Box(i32); // scope 0 at $DIR/uniform_array_move_out.rs:5:21: 5:26 - (*_5) = const 2_i32; // scope 0 at $DIR/uniform_array_move_out.rs:5:25: 5:26 - _4 = move _5; // scope 0 at $DIR/uniform_array_move_out.rs:5:21: 5:26 - drop(_5) -> [return: bb2, unwind: bb8]; // scope 0 at $DIR/uniform_array_move_out.rs:5:25: 5:26 + StorageLive(_6); // scope 0 at $DIR/uniform_array_move_out.rs:5:14: 5:19 + _6 = ShallowInitBox(move _5, i32); // scope 0 at $DIR/uniform_array_move_out.rs:5:14: 5:19 + (*_6) = const 1_i32; // scope 0 at $DIR/uniform_array_move_out.rs:5:18: 5:19 + _2 = move _6; // scope 0 at $DIR/uniform_array_move_out.rs:5:14: 5:19 + drop(_6) -> [return: bb2, unwind: bb11]; // scope 0 at $DIR/uniform_array_move_out.rs:5:18: 5:19 } bb2: { - StorageDead(_5); // scope 0 at $DIR/uniform_array_move_out.rs:5:25: 5:26 - _1 = [move _2, move _4]; // scope 0 at $DIR/uniform_array_move_out.rs:5:13: 5:27 - drop(_4) -> [return: bb3, unwind: bb9]; // scope 0 at $DIR/uniform_array_move_out.rs:5:26: 5:27 + StorageDead(_6); // scope 0 at $DIR/uniform_array_move_out.rs:5:18: 5:19 + StorageLive(_7); // scope 0 at $DIR/uniform_array_move_out.rs:5:21: 5:26 + _8 = SizeOf(i32); // scope 3 at $DIR/uniform_array_move_out.rs:5:21: 5:26 + _9 = AlignOf(i32); // scope 3 at $DIR/uniform_array_move_out.rs:5:21: 5:26 + _10 = alloc::alloc::exchange_malloc(move _8, move _9) -> [return: bb3, unwind: bb11]; // scope 3 at $DIR/uniform_array_move_out.rs:5:21: 5:26 + // mir::Constant + // + span: $DIR/uniform_array_move_out.rs:5:21: 5:26 + // + literal: Const { ty: unsafe fn(usize, usize) -> *mut u8 {alloc::alloc::exchange_malloc}, val: Value(Scalar()) } } bb3: { - StorageDead(_4); // scope 0 at $DIR/uniform_array_move_out.rs:5:26: 5:27 - drop(_2) -> [return: bb4, unwind: bb10]; // scope 0 at $DIR/uniform_array_move_out.rs:5:26: 5:27 + StorageLive(_11); // scope 0 at $DIR/uniform_array_move_out.rs:5:21: 5:26 + _11 = ShallowInitBox(move _10, i32); // scope 0 at $DIR/uniform_array_move_out.rs:5:21: 5:26 + (*_11) = const 2_i32; // scope 0 at $DIR/uniform_array_move_out.rs:5:25: 5:26 + _7 = move _11; // scope 0 at $DIR/uniform_array_move_out.rs:5:21: 5:26 + drop(_11) -> [return: bb4, unwind: bb10]; // scope 0 at $DIR/uniform_array_move_out.rs:5:25: 5:26 } bb4: { - StorageDead(_2); // scope 0 at $DIR/uniform_array_move_out.rs:5:26: 5:27 - FakeRead(ForLet(None), _1); // scope 0 at $DIR/uniform_array_move_out.rs:5:9: 5:10 - StorageLive(_6); // scope 1 at $DIR/uniform_array_move_out.rs:6:14: 6:16 - _6 = move _1[1 of 2]; // scope 1 at $DIR/uniform_array_move_out.rs:6:14: 6:16 - _0 = const (); // scope 0 at $DIR/uniform_array_move_out.rs:4:24: 7:2 - drop(_6) -> [return: bb5, unwind: bb7]; // scope 1 at $DIR/uniform_array_move_out.rs:7:1: 7:2 + StorageDead(_11); // scope 0 at $DIR/uniform_array_move_out.rs:5:25: 5:26 + _1 = [move _2, move _7]; // scope 0 at $DIR/uniform_array_move_out.rs:5:13: 5:27 + drop(_7) -> [return: bb5, unwind: bb11]; // scope 0 at $DIR/uniform_array_move_out.rs:5:26: 5:27 } bb5: { - StorageDead(_6); // scope 1 at $DIR/uniform_array_move_out.rs:7:1: 7:2 - drop(_1) -> [return: bb6, unwind: bb10]; // scope 0 at $DIR/uniform_array_move_out.rs:7:1: 7:2 + StorageDead(_7); // scope 0 at $DIR/uniform_array_move_out.rs:5:26: 5:27 + drop(_2) -> [return: bb6, unwind: bb12]; // scope 0 at $DIR/uniform_array_move_out.rs:5:26: 5:27 } bb6: { + StorageDead(_2); // scope 0 at $DIR/uniform_array_move_out.rs:5:26: 5:27 + FakeRead(ForLet(None), _1); // scope 0 at $DIR/uniform_array_move_out.rs:5:9: 5:10 + StorageLive(_12); // scope 1 at $DIR/uniform_array_move_out.rs:6:14: 6:16 + _12 = move _1[1 of 2]; // scope 1 at $DIR/uniform_array_move_out.rs:6:14: 6:16 + _0 = const (); // scope 0 at $DIR/uniform_array_move_out.rs:4:24: 7:2 + drop(_12) -> [return: bb7, unwind: bb9]; // scope 1 at $DIR/uniform_array_move_out.rs:7:1: 7:2 + } + + bb7: { + StorageDead(_12); // scope 1 at $DIR/uniform_array_move_out.rs:7:1: 7:2 + drop(_1) -> [return: bb8, unwind: bb12]; // scope 0 at $DIR/uniform_array_move_out.rs:7:1: 7:2 + } + + bb8: { StorageDead(_1); // scope 0 at $DIR/uniform_array_move_out.rs:7:1: 7:2 return; // scope 0 at $DIR/uniform_array_move_out.rs:7:2: 7:2 } - bb7 (cleanup): { - drop(_1) -> bb10; // scope 0 at $DIR/uniform_array_move_out.rs:7:1: 7:2 - } - - bb8 (cleanup): { - drop(_4) -> bb9; // scope 0 at $DIR/uniform_array_move_out.rs:5:26: 5:27 - } - bb9 (cleanup): { - drop(_2) -> bb10; // scope 0 at $DIR/uniform_array_move_out.rs:5:26: 5:27 + drop(_1) -> bb12; // scope 0 at $DIR/uniform_array_move_out.rs:7:1: 7:2 } bb10 (cleanup): { + drop(_7) -> bb11; // scope 0 at $DIR/uniform_array_move_out.rs:5:26: 5:27 + } + + bb11 (cleanup): { + drop(_2) -> bb12; // scope 0 at $DIR/uniform_array_move_out.rs:5:26: 5:27 + } + + bb12 (cleanup): { resume; // scope 0 at $DIR/uniform_array_move_out.rs:4:1: 7:2 } } diff --git a/src/test/mir-opt/unreachable_asm.main.UnreachablePropagation.diff b/src/test/mir-opt/unreachable_asm.main.UnreachablePropagation.diff index 09eb210f36..c60997be5d 100644 --- a/src/test/mir-opt/unreachable_asm.main.UnreachablePropagation.diff +++ b/src/test/mir-opt/unreachable_asm.main.UnreachablePropagation.diff @@ -59,7 +59,7 @@ StorageDead(_6); // scope 2 at $DIR/unreachable_asm.rs:18:9: 18:10 StorageDead(_5); // scope 2 at $DIR/unreachable_asm.rs:18:9: 18:10 StorageLive(_7); // scope 2 at $DIR/unreachable_asm.rs:21:9: 21:37 - llvm_asm!(LlvmInlineAsmInner { asm: "NOP", asm_str_style: Cooked, outputs: [], inputs: [], clobbers: [], volatile: true, alignstack: false, dialect: Att } : [] : []); // scope 3 at $DIR/unreachable_asm.rs:21:18: 21:35 + llvm_asm!(LlvmInlineAsmInner { asm: "NOP", asm_str_style: Cooked, outputs: [], inputs: [], clobbers: [], volatile: true, alignstack: false, dialect: Att } : [] : []); // scope 3 at $DIR/unreachable_asm.rs:21:18: 21:34 _7 = const (); // scope 3 at $DIR/unreachable_asm.rs:21:9: 21:37 StorageDead(_7); // scope 2 at $DIR/unreachable_asm.rs:21:36: 21:37 StorageLive(_8); // scope 2 at $DIR/unreachable_asm.rs:22:9: 22:21 diff --git a/src/test/mir-opt/unreachable_asm_2.main.UnreachablePropagation.diff b/src/test/mir-opt/unreachable_asm_2.main.UnreachablePropagation.diff index cdb28ca12c..28c5f031db 100644 --- a/src/test/mir-opt/unreachable_asm_2.main.UnreachablePropagation.diff +++ b/src/test/mir-opt/unreachable_asm_2.main.UnreachablePropagation.diff @@ -49,7 +49,7 @@ bb3: { StorageLive(_7); // scope 2 at $DIR/unreachable_asm_2.rs:16:13: 16:41 - llvm_asm!(LlvmInlineAsmInner { asm: "NOP", asm_str_style: Cooked, outputs: [], inputs: [], clobbers: [], volatile: true, alignstack: false, dialect: Att } : [] : []); // scope 3 at $DIR/unreachable_asm_2.rs:16:22: 16:39 + llvm_asm!(LlvmInlineAsmInner { asm: "NOP", asm_str_style: Cooked, outputs: [], inputs: [], clobbers: [], volatile: true, alignstack: false, dialect: Att } : [] : []); // scope 3 at $DIR/unreachable_asm_2.rs:16:22: 16:38 _7 = const (); // scope 3 at $DIR/unreachable_asm_2.rs:16:13: 16:41 StorageDead(_7); // scope 2 at $DIR/unreachable_asm_2.rs:16:40: 16:41 _4 = const 21_i32; // scope 2 at $DIR/unreachable_asm_2.rs:17:13: 17:20 @@ -60,7 +60,7 @@ bb4: { StorageLive(_8); // scope 2 at $DIR/unreachable_asm_2.rs:20:13: 20:41 - llvm_asm!(LlvmInlineAsmInner { asm: "NOP", asm_str_style: Cooked, outputs: [], inputs: [], clobbers: [], volatile: true, alignstack: false, dialect: Att } : [] : []); // scope 4 at $DIR/unreachable_asm_2.rs:20:22: 20:39 + llvm_asm!(LlvmInlineAsmInner { asm: "NOP", asm_str_style: Cooked, outputs: [], inputs: [], clobbers: [], volatile: true, alignstack: false, dialect: Att } : [] : []); // scope 4 at $DIR/unreachable_asm_2.rs:20:22: 20:38 _8 = const (); // scope 4 at $DIR/unreachable_asm_2.rs:20:13: 20:41 StorageDead(_8); // scope 2 at $DIR/unreachable_asm_2.rs:20:40: 20:41 _4 = const 42_i32; // scope 2 at $DIR/unreachable_asm_2.rs:21:13: 21:20 diff --git a/src/test/mir-opt/while_storage.while_loop.PreCodegen.after.mir b/src/test/mir-opt/while_storage.while_loop.PreCodegen.after.mir index 9db77d705f..ec2d161251 100644 --- a/src/test/mir-opt/while_storage.while_loop.PreCodegen.after.mir +++ b/src/test/mir-opt/while_storage.while_loop.PreCodegen.after.mir @@ -9,51 +9,55 @@ fn while_loop(_1: bool) -> () { let mut _5: bool; // in scope 0 at $DIR/while-storage.rs:11:21: 11:22 bb0: { + goto -> bb1; // scope 0 at $DIR/while-storage.rs:10:5: 14:6 + } + + bb1: { StorageLive(_2); // scope 0 at $DIR/while-storage.rs:10:11: 10:22 StorageLive(_3); // scope 0 at $DIR/while-storage.rs:10:20: 10:21 _3 = _1; // scope 0 at $DIR/while-storage.rs:10:20: 10:21 - _2 = get_bool(move _3) -> bb1; // scope 0 at $DIR/while-storage.rs:10:11: 10:22 + _2 = get_bool(move _3) -> bb2; // scope 0 at $DIR/while-storage.rs:10:11: 10:22 // mir::Constant // + span: $DIR/while-storage.rs:10:11: 10:19 // + literal: Const { ty: fn(bool) -> bool {get_bool}, val: Value(Scalar()) } } - bb1: { + bb2: { StorageDead(_3); // scope 0 at $DIR/while-storage.rs:10:21: 10:22 - switchInt(move _2) -> [false: bb6, otherwise: bb2]; // scope 0 at $DIR/while-storage.rs:10:11: 10:22 + switchInt(move _2) -> [false: bb7, otherwise: bb3]; // scope 0 at $DIR/while-storage.rs:10:11: 10:22 } - bb2: { + bb3: { StorageLive(_4); // scope 0 at $DIR/while-storage.rs:11:12: 11:23 StorageLive(_5); // scope 0 at $DIR/while-storage.rs:11:21: 11:22 _5 = _1; // scope 0 at $DIR/while-storage.rs:11:21: 11:22 - _4 = get_bool(move _5) -> bb3; // scope 0 at $DIR/while-storage.rs:11:12: 11:23 + _4 = get_bool(move _5) -> bb4; // scope 0 at $DIR/while-storage.rs:11:12: 11:23 // mir::Constant // + span: $DIR/while-storage.rs:11:12: 11:20 // + literal: Const { ty: fn(bool) -> bool {get_bool}, val: Value(Scalar()) } } - bb3: { - StorageDead(_5); // scope 0 at $DIR/while-storage.rs:11:22: 11:23 - switchInt(move _4) -> [false: bb5, otherwise: bb4]; // scope 0 at $DIR/while-storage.rs:11:12: 11:23 - } - bb4: { - StorageDead(_4); // scope 0 at $DIR/while-storage.rs:13:9: 13:10 - goto -> bb7; // scope 0 at no-location + StorageDead(_5); // scope 0 at $DIR/while-storage.rs:11:22: 11:23 + switchInt(move _4) -> [false: bb6, otherwise: bb5]; // scope 0 at $DIR/while-storage.rs:11:12: 11:23 } bb5: { StorageDead(_4); // scope 0 at $DIR/while-storage.rs:13:9: 13:10 - StorageDead(_2); // scope 0 at $DIR/while-storage.rs:14:5: 14:6 - goto -> bb0; // scope 0 at $DIR/while-storage.rs:10:5: 14:6 + goto -> bb8; // scope 0 at no-location } bb6: { - goto -> bb7; // scope 0 at no-location + StorageDead(_4); // scope 0 at $DIR/while-storage.rs:13:9: 13:10 + StorageDead(_2); // scope 0 at $DIR/while-storage.rs:14:5: 14:6 + goto -> bb1; // scope 0 at $DIR/while-storage.rs:10:5: 14:6 } bb7: { + goto -> bb8; // scope 0 at no-location + } + + bb8: { StorageDead(_2); // scope 0 at $DIR/while-storage.rs:14:5: 14:6 return; // scope 0 at $DIR/while-storage.rs:15:2: 15:2 } diff --git a/src/test/pretty/dollar-crate.pp b/src/test/pretty/dollar-crate.pp index 4eccba06b1..f4be3c1c63 100644 --- a/src/test/pretty/dollar-crate.pp +++ b/src/test/pretty/dollar-crate.pp @@ -10,11 +10,9 @@ extern crate std; fn main() { { - ::std::io::_print(match match () { () => [], } { - ref args => unsafe { - ::core::fmt::Arguments::new_v1(&["rust\n"], - args) - } - }); + ::std::io::_print(::core::fmt::Arguments::new_v1(&["rust\n"], + &match () { + () => [], + })); }; } diff --git a/src/test/pretty/issue-4264.pp b/src/test/pretty/issue-4264.pp index a21ea52012..199aee0562 100644 --- a/src/test/pretty/issue-4264.pp +++ b/src/test/pretty/issue-4264.pp @@ -32,39 +32,29 @@ pub fn bar() ({ ({ let res = ((::alloc::fmt::format as - for<'r> fn(Arguments<'r>) -> String {format})((match (match (() - as - ()) - { - () - => - ([] - as - [ArgumentV1; 0]), - } - as - [ArgumentV1; 0]) - { - ref args - => - unsafe - { - ((::core::fmt::Arguments::new_v1 - as - unsafe fn(&[&'static str], &[ArgumentV1]) -> Arguments {Arguments::new_v1})((&([("test" - as - &str)] - as - [&str; 1]) - as - &[&str; 1]), - (args - as - &[ArgumentV1; 0])) - as - Arguments) - } - } + for<'r> fn(Arguments<'r>) -> String {format})(((::core::fmt::Arguments::new_v1 + as + fn(&[&'static str], &[ArgumentV1]) -> Arguments {Arguments::new_v1})((&([("test" + as + &str)] + as + [&str; 1]) + as + &[&str; 1]), + (&(match (() + as + ()) + { + () + => + ([] + as + [ArgumentV1; 0]), + } + as + [ArgumentV1; 0]) + as + &[ArgumentV1; 0])) as Arguments)) as String); diff --git a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.issue-84561.txt b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.issue-84561.txt index b35f3f54de..f24f7c6940 100644 --- a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.issue-84561.txt +++ b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.issue-84561.txt @@ -31,15 +31,15 @@ 24| 1| println!("{:?}", Foo(1)); 25| 1| 26| 1| assert_ne!(Foo(0), Foo(5), "{}", if is_true { "true message" } else { "false message" }); - ^0 ^0 ^0 ^0 + ^0 ^0 ^0 27| 1| assert_ne!( 28| | Foo(0) 29| | , 30| | Foo(5) 31| | , 32| 0| "{}" - 33| | , - 34| | if + 33| 0| , + 34| 0| if 35| 0| is_true 36| | { 37| 0| "true message" diff --git a/src/test/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs b/src/test/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs index d3862309ce..7c16f7bdaf 100644 --- a/src/test/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs +++ b/src/test/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs @@ -2,11 +2,12 @@ #![deny(warnings)] extern crate rustc_codegen_ssa; -extern crate rustc_errors; -extern crate rustc_middle; extern crate rustc_data_structures; extern crate rustc_driver; +extern crate rustc_errors; extern crate rustc_hir; +extern crate rustc_metadata; +extern crate rustc_middle; extern crate rustc_session; extern crate rustc_span; extern crate rustc_symbol_mangling; @@ -16,8 +17,8 @@ use rustc_codegen_ssa::traits::CodegenBackend; use rustc_codegen_ssa::{CodegenResults, CrateInfo}; use rustc_data_structures::fx::FxHashMap; use rustc_errors::ErrorReported; +use rustc_metadata::EncodedMetadata; use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; -use rustc_middle::middle::cstore::EncodedMetadata; use rustc_middle::ty::TyCtxt; use rustc_session::config::OutputFilenames; use rustc_session::Session; diff --git a/src/test/run-make-fulldeps/obtain-borrowck/driver.rs b/src/test/run-make-fulldeps/obtain-borrowck/driver.rs index 308df0b030..a288b90d79 100644 --- a/src/test/run-make-fulldeps/obtain-borrowck/driver.rs +++ b/src/test/run-make-fulldeps/obtain-borrowck/driver.rs @@ -11,13 +11,14 @@ //! `optimized_mir` and pulls out the MIR bodies with the borrowck information //! from the thread local storage. +extern crate rustc_borrowck; extern crate rustc_driver; extern crate rustc_hir; extern crate rustc_interface; extern crate rustc_middle; -extern crate rustc_mir; extern crate rustc_session; +use rustc_borrowck::consumers::BodyWithBorrowckFacts; use rustc_driver::Compilation; use rustc_hir::def_id::LocalDefId; use rustc_hir::itemlikevisit::ItemLikeVisitor; @@ -26,7 +27,6 @@ use rustc_interface::{Config, Queries}; use rustc_middle::ty::query::query_values::mir_borrowck; use rustc_middle::ty::query::Providers; use rustc_middle::ty::{self, TyCtxt}; -use rustc_mir::consumers::BodyWithBorrowckFacts; use rustc_session::Session; use std::cell::RefCell; use std::collections::HashMap; @@ -48,7 +48,6 @@ fn main() { pub struct CompilerCalls; impl rustc_driver::Callbacks for CompilerCalls { - // In this callback we override the mir_borrowck query. fn config(&mut self, config: &mut Config) { assert!(config.override_queries.is_none()); @@ -64,12 +63,10 @@ impl rustc_driver::Callbacks for CompilerCalls { ) -> Compilation { compiler.session().abort_if_errors(); queries.global_ctxt().unwrap().peek_mut().enter(|tcx| { - // Collect definition ids of MIR bodies. let hir = tcx.hir(); - let krate = hir.krate(); let mut visitor = HirVisitor { bodies: Vec::new() }; - krate.visit_all_item_likes(&mut visitor); + hir.visit_all_item_likes(&mut visitor); // Trigger borrow checking of all bodies. for def_id in visitor.bodies { @@ -108,7 +105,7 @@ thread_local! { } fn mir_borrowck<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> mir_borrowck<'tcx> { - let body_with_facts = rustc_mir::consumers::get_body_with_borrowck_facts( + let body_with_facts = rustc_borrowck::consumers::get_body_with_borrowck_facts( tcx, ty::WithOptConstParam::unknown(def_id), ); @@ -120,7 +117,7 @@ fn mir_borrowck<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> mir_borrowck<'tc assert!(map.insert(def_id, body_with_facts).is_none()); }); let mut providers = Providers::default(); - rustc_mir::provide(&mut providers); + rustc_borrowck::provide(&mut providers); let original_mir_borrowck = providers.mir_borrowck; original_mir_borrowck(tcx, def_id) } diff --git a/src/test/run-make-fulldeps/reproducible-build/Makefile b/src/test/run-make-fulldeps/reproducible-build/Makefile index a17ec212cf..adccc15356 100644 --- a/src/test/run-make-fulldeps/reproducible-build/Makefile +++ b/src/test/run-make-fulldeps/reproducible-build/Makefile @@ -9,9 +9,19 @@ all: \ opt \ link_paths \ remap_paths \ - different_source_dirs \ + different_source_dirs_rlib \ + remap_cwd_rlib \ + remap_cwd_to_empty \ extern_flags +# TODO: Builds of `bin` crate types are not deterministic with debuginfo=2 on +# Windows. +# See: https://github.com/rust-lang/rust/pull/87320#issuecomment-920105533 +# Issue: https://github.com/rust-lang/rust/issues/88982 +# +# different_source_dirs_bin \ +# remap_cwd_bin \ + smoke: rm -rf $(TMPDIR) && mkdir $(TMPDIR) $(RUSTC) linker.rs -O @@ -52,7 +62,19 @@ remap_paths: $(RUSTC) reproducible-build.rs --crate-type rlib --remap-path-prefix=/b=/c cmp "$(TMPDIR)/libreproducible_build.rlib" "$(TMPDIR)/libfoo.rlib" || exit 1 -different_source_dirs: +different_source_dirs_bin: + rm -rf $(TMPDIR) && mkdir $(TMPDIR) + $(RUSTC) reproducible-build-aux.rs + mkdir $(TMPDIR)/test + cp reproducible-build.rs $(TMPDIR)/test + $(RUSTC) reproducible-build.rs --crate-type bin --remap-path-prefix=$$PWD=/b + cp $(TMPDIR)/reproducible-build $(TMPDIR)/foo + (cd $(TMPDIR)/test && $(RUSTC) reproducible-build.rs \ + --remap-path-prefix=$(TMPDIR)/test=/b \ + --crate-type bin) + cmp "$(TMPDIR)/reproducible-build" "$(TMPDIR)/foo" || exit 1 + +different_source_dirs_rlib: rm -rf $(TMPDIR) && mkdir $(TMPDIR) $(RUSTC) reproducible-build-aux.rs mkdir $(TMPDIR)/test @@ -64,6 +86,45 @@ different_source_dirs: --crate-type rlib) cmp "$(TMPDIR)/libreproducible_build.rlib" "$(TMPDIR)/libfoo.rlib" || exit 1 +remap_cwd_bin: + rm -rf $(TMPDIR) && mkdir $(TMPDIR) + $(RUSTC) reproducible-build-aux.rs + mkdir $(TMPDIR)/test + cp reproducible-build.rs $(TMPDIR)/test + $(RUSTC) reproducible-build.rs --crate-type bin -C debuginfo=2 \ + -Z remap-cwd-prefix=. + cp $(TMPDIR)/reproducible-build $(TMPDIR)/first + (cd $(TMPDIR)/test && \ + $(RUSTC) reproducible-build.rs --crate-type bin -C debuginfo=2 \ + -Z remap-cwd-prefix=.) + cmp "$(TMPDIR)/first" "$(TMPDIR)/reproducible-build" || exit 1 + +remap_cwd_rlib: + rm -rf $(TMPDIR) && mkdir $(TMPDIR) + $(RUSTC) reproducible-build-aux.rs + mkdir $(TMPDIR)/test + cp reproducible-build.rs $(TMPDIR)/test + $(RUSTC) reproducible-build.rs --crate-type rlib -C debuginfo=2 \ + -Z remap-cwd-prefix=. + cp $(TMPDIR)/libreproducible_build.rlib $(TMPDIR)/libfirst.rlib + (cd $(TMPDIR)/test && \ + $(RUSTC) reproducible-build.rs --crate-type rlib -C debuginfo=2 \ + -Z remap-cwd-prefix=.) + cmp "$(TMPDIR)/libfirst.rlib" "$(TMPDIR)/libreproducible_build.rlib" || exit 1 + +remap_cwd_to_empty: + rm -rf $(TMPDIR) && mkdir $(TMPDIR) + $(RUSTC) reproducible-build-aux.rs + mkdir $(TMPDIR)/test + cp reproducible-build.rs $(TMPDIR)/test + $(RUSTC) reproducible-build.rs --crate-type rlib -C debuginfo=2 \ + -Z remap-cwd-prefix= + cp $(TMPDIR)/libreproducible_build.rlib $(TMPDIR)/libfirst.rlib + (cd $(TMPDIR)/test && \ + $(RUSTC) reproducible-build.rs --crate-type rlib -C debuginfo=2 \ + -Z remap-cwd-prefix=) + cmp "$(TMPDIR)/libfirst.rlib" "$(TMPDIR)/libreproducible_build.rlib" || exit 1 + extern_flags: rm -rf $(TMPDIR) && mkdir $(TMPDIR) $(RUSTC) reproducible-build-aux.rs diff --git a/src/test/run-make-fulldeps/sepcomp-cci-copies/Makefile b/src/test/run-make-fulldeps/sepcomp-cci-copies/Makefile index 36f913ff3f..77d1d71e9b 100644 --- a/src/test/run-make-fulldeps/sepcomp-cci-copies/Makefile +++ b/src/test/run-make-fulldeps/sepcomp-cci-copies/Makefile @@ -3,7 +3,7 @@ # Check that cross-crate inlined items are inlined in all compilation units # that refer to them, and not in any other compilation units. # Note that we have to pass `-C codegen-units=6` because up to two CGUs may be -# created for each source module (see `rustc_mir::monomorphize::partitioning`). +# created for each source module (see `rustc_const_eval::monomorphize::partitioning`). all: $(RUSTC) cci_lib.rs diff --git a/src/test/run-make-fulldeps/sysroot-crates-are-unstable/test.py b/src/test/run-make-fulldeps/sysroot-crates-are-unstable/test.py index f479bdabb9..cb77eb34fe 100644 --- a/src/test/run-make-fulldeps/sysroot-crates-are-unstable/test.py +++ b/src/test/run-make-fulldeps/sysroot-crates-are-unstable/test.py @@ -17,6 +17,17 @@ def convert_to_string(s): return s +def set_ld_lib_path(): + var = os.environ.get("LD_LIB_PATH_ENVVAR") + rpath = os.environ.get("HOST_RPATH_DIR") + if var and rpath: + path = os.environ.get(var) + if path: + os.environ[var] = rpath + os.pathsep + path + else: + os.environ[var] = rpath + + def exec_command(command, to_input=None): child = None if to_input is None: @@ -50,7 +61,9 @@ def get_all_libs(dir_path): if isfile(join(dir_path, f)) and f.endswith('.rlib') and f not in STABLE_CRATES] +set_ld_lib_path() sysroot = exec_command([os.environ['RUSTC'], '--print', 'sysroot'])[0].replace('\n', '') +assert sysroot, "Could not read the rustc sysroot!" libs = get_all_libs(join(sysroot, 'lib/rustlib/{}/lib'.format(os.environ['TARGET']))) ret = 0 diff --git a/src/test/run-make-fulldeps/target-specs/foo.rs b/src/test/run-make-fulldeps/target-specs/foo.rs index 9ff33e24d0..d576a1dd28 100644 --- a/src/test/run-make-fulldeps/target-specs/foo.rs +++ b/src/test/run-make-fulldeps/target-specs/foo.rs @@ -11,7 +11,7 @@ trait Sized {} auto trait Freeze {} #[lang = "start"] -fn start(_main: *const u8, _argc: isize, _argv: *const *const u8) -> isize { +fn start(_main: fn() -> T, _argc: isize, _argv: *const *const u8) -> isize { 0 } diff --git a/src/test/run-make-fulldeps/tools.mk b/src/test/run-make-fulldeps/tools.mk index a1a076dd74..3934c4725f 100644 --- a/src/test/run-make-fulldeps/tools.mk +++ b/src/test/run-make-fulldeps/tools.mk @@ -101,9 +101,9 @@ endif # Extra flags needed to compile a working executable with the standard library ifdef IS_WINDOWS ifdef IS_MSVC - EXTRACFLAGS := ws2_32.lib userenv.lib advapi32.lib + EXTRACFLAGS := ws2_32.lib userenv.lib advapi32.lib bcrypt.lib else - EXTRACFLAGS := -lws2_32 -luserenv + EXTRACFLAGS := -lws2_32 -luserenv -lbcrypt EXTRACXXFLAGS := -lstdc++ # So this is a bit hacky: we can't use the DLL version of libstdc++ because # it pulls in the DLL version of libgcc, which means that we end up with 2 diff --git a/src/test/run-make/dep-graph/Makefile b/src/test/run-make/dep-graph/Makefile new file mode 100644 index 0000000000..88916022c7 --- /dev/null +++ b/src/test/run-make/dep-graph/Makefile @@ -0,0 +1,12 @@ +-include ../../run-make-fulldeps/tools.mk + +# ignore-cross-compile + +# Just verify that we successfully run and produce dep graphs when requested. + +all: + RUST_DEP_GRAPH=$(TMPDIR)/dep-graph $(RUSTC) \ + -Cincremental=$(TMPDIR)/incr \ + -Zquery-dep-graph -Zdump-dep-graph foo.rs + test -f $(TMPDIR)/dep-graph.txt + test -f $(TMPDIR)/dep-graph.dot diff --git a/src/test/run-make/dep-graph/foo.rs b/src/test/run-make/dep-graph/foo.rs new file mode 100644 index 0000000000..f328e4d9d0 --- /dev/null +++ b/src/test/run-make/dep-graph/foo.rs @@ -0,0 +1 @@ +fn main() {} diff --git a/src/test/run-make/issue-85441/Makefile b/src/test/run-make/issue-85441/Makefile new file mode 100644 index 0000000000..c7ae708c17 --- /dev/null +++ b/src/test/run-make/issue-85441/Makefile @@ -0,0 +1,9 @@ +# only-windows-msvc + +-include ../../run-make-fulldeps/tools.mk + +# Tests that WS2_32.dll is not unnecessarily linked, see issue #85441 + +all: + $(RUSTC) empty.rs + objdump -p $(TMPDIR)/empty.exe | $(CGREP) -v -i "WS2_32.dll" diff --git a/src/test/run-make/issue-85441/empty.rs b/src/test/run-make/issue-85441/empty.rs new file mode 100644 index 0000000000..f328e4d9d0 --- /dev/null +++ b/src/test/run-make/issue-85441/empty.rs @@ -0,0 +1 @@ +fn main() {} diff --git a/src/test/run-make/native-link-modifier-whole-archive/Makefile b/src/test/run-make/native-link-modifier-whole-archive/Makefile new file mode 100644 index 0000000000..799b5f6f5f --- /dev/null +++ b/src/test/run-make/native-link-modifier-whole-archive/Makefile @@ -0,0 +1,39 @@ +# ignore-cross-compile -- compiling C++ code does not work well when cross-compiling + +# This test case makes sure that native libraries are linked with --whole-archive semantics +# when the `-bundle,+whole-archive` modifiers are applied to them. +# +# The test works by checking that the resulting executables produce the expected output, +# part of which is emitted by otherwise unreferenced C code. If +whole-archive didn't work +# that code would never make it into the final executable and we'd thus be missing some +# of the output. + +-include ../../run-make-fulldeps/tools.mk + +all: $(TMPDIR)/$(call BIN,directly_linked) $(TMPDIR)/$(call BIN,indirectly_linked) $(TMPDIR)/$(call BIN,indirectly_linked_via_attr) + $(call RUN,directly_linked) | $(CGREP) 'static-initializer.directly_linked.' + $(call RUN,indirectly_linked) | $(CGREP) 'static-initializer.indirectly_linked.' + $(call RUN,indirectly_linked_via_attr) | $(CGREP) 'static-initializer.native_lib_in_src.' + +# Native lib linked directly into executable +$(TMPDIR)/$(call BIN,directly_linked): $(call NATIVE_STATICLIB,c_static_lib_with_constructor) + $(RUSTC) directly_linked.rs -Z unstable-options -l static:+whole-archive=c_static_lib_with_constructor + +# Native lib linked into RLIB via `-l static:-bundle,+whole-archive`, RLIB linked into executable +$(TMPDIR)/$(call BIN,indirectly_linked): $(TMPDIR)/librlib_with_cmdline_native_lib.rlib + $(RUSTC) indirectly_linked.rs + +# Native lib linked into RLIB via #[link] attribute, RLIB linked into executable +$(TMPDIR)/$(call BIN,indirectly_linked_via_attr): $(TMPDIR)/libnative_lib_in_src.rlib + $(RUSTC) indirectly_linked_via_attr.rs + +# Native lib linked into rlib with via commandline +$(TMPDIR)/librlib_with_cmdline_native_lib.rlib: $(call NATIVE_STATICLIB,c_static_lib_with_constructor) + $(RUSTC) rlib_with_cmdline_native_lib.rs -Z unstable-options --crate-type=rlib -l static:-bundle,+whole-archive=c_static_lib_with_constructor + +# Native lib linked into rlib via `#[link()]` attribute on extern block. +$(TMPDIR)/libnative_lib_in_src.rlib: $(call NATIVE_STATICLIB,c_static_lib_with_constructor) + $(RUSTC) native_lib_in_src.rs --crate-type=rlib + +$(TMPDIR)/libc_static_lib_with_constructor.o: c_static_lib_with_constructor.cpp + $(call COMPILE_OBJ_CXX,$@,$<) diff --git a/src/test/run-make/native-link-modifier-whole-archive/c_static_lib_with_constructor.cpp b/src/test/run-make/native-link-modifier-whole-archive/c_static_lib_with_constructor.cpp new file mode 100644 index 0000000000..c687eb0f09 --- /dev/null +++ b/src/test/run-make/native-link-modifier-whole-archive/c_static_lib_with_constructor.cpp @@ -0,0 +1,11 @@ +#include + +// Since this is a global variable, its constructor will be called before +// main() is executed. But only if the object file containing it actually +// gets linked into the executable. +struct Foo { + Foo() { + printf("static-initializer."); + fflush(stdout); + } +} FOO; diff --git a/src/test/run-make/native-link-modifier-whole-archive/directly_linked.rs b/src/test/run-make/native-link-modifier-whole-archive/directly_linked.rs new file mode 100644 index 0000000000..17518e8b2f --- /dev/null +++ b/src/test/run-make/native-link-modifier-whole-archive/directly_linked.rs @@ -0,0 +1,6 @@ +use std::io::Write; + +fn main() { + print!("directly_linked."); + std::io::stdout().flush().unwrap(); +} diff --git a/src/test/run-make/native-link-modifier-whole-archive/indirectly_linked.rs b/src/test/run-make/native-link-modifier-whole-archive/indirectly_linked.rs new file mode 100644 index 0000000000..c8b83fcfe0 --- /dev/null +++ b/src/test/run-make/native-link-modifier-whole-archive/indirectly_linked.rs @@ -0,0 +1,5 @@ +extern crate rlib_with_cmdline_native_lib; + +fn main() { + rlib_with_cmdline_native_lib::hello(); +} diff --git a/src/test/run-make/native-link-modifier-whole-archive/indirectly_linked_via_attr.rs b/src/test/run-make/native-link-modifier-whole-archive/indirectly_linked_via_attr.rs new file mode 100644 index 0000000000..b9e347609b --- /dev/null +++ b/src/test/run-make/native-link-modifier-whole-archive/indirectly_linked_via_attr.rs @@ -0,0 +1,5 @@ +extern crate native_lib_in_src; + +fn main() { + native_lib_in_src::hello(); +} diff --git a/src/test/run-make/native-link-modifier-whole-archive/native_lib_in_src.rs b/src/test/run-make/native-link-modifier-whole-archive/native_lib_in_src.rs new file mode 100644 index 0000000000..373d89b793 --- /dev/null +++ b/src/test/run-make/native-link-modifier-whole-archive/native_lib_in_src.rs @@ -0,0 +1,15 @@ +#![feature(native_link_modifiers_bundle)] +#![feature(native_link_modifiers_whole_archive)] +#![feature(native_link_modifiers)] + +use std::io::Write; + +#[link(name = "c_static_lib_with_constructor", + kind = "static", + modifiers = "-bundle,+whole-archive")] +extern {} + +pub fn hello() { + print!("native_lib_in_src."); + std::io::stdout().flush().unwrap(); +} diff --git a/src/test/run-make/native-link-modifier-whole-archive/rlib_with_cmdline_native_lib.rs b/src/test/run-make/native-link-modifier-whole-archive/rlib_with_cmdline_native_lib.rs new file mode 100644 index 0000000000..ef2b702dd8 --- /dev/null +++ b/src/test/run-make/native-link-modifier-whole-archive/rlib_with_cmdline_native_lib.rs @@ -0,0 +1,6 @@ +use std::io::Write; + +pub fn hello() { + print!("indirectly_linked."); + std::io::stdout().flush().unwrap(); +} diff --git a/src/test/run-make/raw-dylib-link-ordinal/Makefile b/src/test/run-make/raw-dylib-link-ordinal/Makefile new file mode 100644 index 0000000000..04b257d063 --- /dev/null +++ b/src/test/run-make/raw-dylib-link-ordinal/Makefile @@ -0,0 +1,18 @@ +# Test the behavior of #[link(.., kind = "raw-dylib")] and #[link_ordinal] on windows-msvc + +# only-windows-msvc + +-include ../../run-make-fulldeps/tools.mk + +all: + $(call COMPILE_OBJ,"$(TMPDIR)"/exporter.obj,exporter.c) + $(CC) "$(TMPDIR)"/exporter.obj exporter.def -link -dll -out:"$(TMPDIR)"/exporter.dll + $(RUSTC) --crate-type lib --crate-name raw_dylib_test lib.rs + $(RUSTC) --crate-type bin driver.rs -L "$(TMPDIR)" + "$(TMPDIR)"/driver > "$(TMPDIR)"/output.txt + +ifdef RUSTC_BLESS_TEST + cp "$(TMPDIR)"/output.txt output.txt +else + $(DIFF) output.txt "$(TMPDIR)"/output.txt +endif diff --git a/src/test/run-make/raw-dylib-link-ordinal/driver.rs b/src/test/run-make/raw-dylib-link-ordinal/driver.rs new file mode 100644 index 0000000000..4059ede11f --- /dev/null +++ b/src/test/run-make/raw-dylib-link-ordinal/driver.rs @@ -0,0 +1,5 @@ +extern crate raw_dylib_test; + +fn main() { + raw_dylib_test::library_function(); +} diff --git a/src/test/run-make/raw-dylib-link-ordinal/exporter.c b/src/test/run-make/raw-dylib-link-ordinal/exporter.c new file mode 100644 index 0000000000..a9dd6da661 --- /dev/null +++ b/src/test/run-make/raw-dylib-link-ordinal/exporter.c @@ -0,0 +1,5 @@ +#include + +void exported_function() { + printf("exported_function\n"); +} diff --git a/src/test/run-make/raw-dylib-link-ordinal/exporter.def b/src/test/run-make/raw-dylib-link-ordinal/exporter.def new file mode 100644 index 0000000000..1a4b4c941b --- /dev/null +++ b/src/test/run-make/raw-dylib-link-ordinal/exporter.def @@ -0,0 +1,3 @@ +LIBRARY exporter +EXPORTS + exported_function @13 NONAME diff --git a/src/test/run-make/raw-dylib-link-ordinal/lib.rs b/src/test/run-make/raw-dylib-link-ordinal/lib.rs new file mode 100644 index 0000000000..20609caa5b --- /dev/null +++ b/src/test/run-make/raw-dylib-link-ordinal/lib.rs @@ -0,0 +1,13 @@ +#![feature(raw_dylib)] + +#[link(name = "exporter", kind = "raw-dylib")] +extern { + #[link_ordinal(13)] + fn imported_function(); +} + +pub fn library_function() { + unsafe { + imported_function(); + } +} diff --git a/src/test/run-make/raw-dylib-link-ordinal/output.txt b/src/test/run-make/raw-dylib-link-ordinal/output.txt new file mode 100644 index 0000000000..2d0ed60f21 --- /dev/null +++ b/src/test/run-make/raw-dylib-link-ordinal/output.txt @@ -0,0 +1 @@ +exported_function diff --git a/src/test/rustdoc-gui/code-sidebar-toggle.goml b/src/test/rustdoc-gui/code-sidebar-toggle.goml index 00326e9bbc..6fb92e1966 100644 --- a/src/test/rustdoc-gui/code-sidebar-toggle.goml +++ b/src/test/rustdoc-gui/code-sidebar-toggle.goml @@ -1,5 +1,6 @@ goto: file://|DOC_PATH|/test_docs/index.html click: ".srclink" +wait-for: "#sidebar-toggle" click: "#sidebar-toggle" wait-for: 500 fail: true diff --git a/src/test/rustdoc-gui/docblock-big-code-mobile.goml b/src/test/rustdoc-gui/docblock-big-code-mobile.goml new file mode 100644 index 0000000000..12677a5648 --- /dev/null +++ b/src/test/rustdoc-gui/docblock-big-code-mobile.goml @@ -0,0 +1,9 @@ +// If we have a long ``, we need to ensure that it'll be fully displayed on mobile, meaning +// that it'll be on two lines. +emulate: "iPhone 8" // it has the following size: (375, 667) +goto: file://|DOC_PATH|/test_docs/long_code_block/index.html +// We now check that the block is on two lines: +show-text: true // We need to enable text draw to be able to have the "real" size +// Little explanations for this test: if the text wasn't displayed on two lines, it would take +// around 20px (which is the font size). +assert-property: (".docblock p > code", {"offsetHeight": "42"}) diff --git a/src/test/rustdoc-gui/docblock-table-overflow.goml b/src/test/rustdoc-gui/docblock-table-overflow.goml index 9ab7cd0fa0..10f516d2da 100644 --- a/src/test/rustdoc-gui/docblock-table-overflow.goml +++ b/src/test/rustdoc-gui/docblock-table-overflow.goml @@ -7,3 +7,11 @@ compare-elements-property: (".top-doc .docblock", ".top-doc .docblock > p", ["sc assert-property: (".top-doc .docblock", {"scrollWidth": "816"}) // However, since there is overflow in the , its scroll width is bigger. assert-property: (".top-doc .docblock table", {"scrollWidth": "1573"}) + +// Checking it works on other doc blocks as well... + +// Logically, the ".docblock" and the "

" should have the same scroll width. +compare-elements-property: ("#implementations + details .docblock", "#implementations + details .docblock > p", ["scrollWidth"]) +assert-property: ("#implementations + details .docblock", {"scrollWidth": "816"}) +// However, since there is overflow in the

, its scroll width is bigger. +assert-property: ("#implementations + details .docblock table", {"scrollWidth": "1573"}) diff --git a/src/test/rustdoc-gui/header-size.goml b/src/test/rustdoc-gui/header-size.goml new file mode 100644 index 0000000000..4f45367fc7 --- /dev/null +++ b/src/test/rustdoc-gui/header-size.goml @@ -0,0 +1,99 @@ +// 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/huge-collection-of-constants.goml b/src/test/rustdoc-gui/huge-collection-of-constants.goml new file mode 100644 index 0000000000..924fab1ea9 --- /dev/null +++ b/src/test/rustdoc-gui/huge-collection-of-constants.goml @@ -0,0 +1,5 @@ +goto: file://|DOC_PATH|/test_docs/huge_amount_of_consts/index.html + +// Make sure that the last two entries are more than 12 pixels apart and not stacked on each other. + +compare-elements-position-near-false: ("//*[@class='item-table']//div[last()-1]", "//*[@class='item-table']//div[last()-3]", {"y": 12}) diff --git a/src/test/rustdoc-gui/jump-to-def-background.goml b/src/test/rustdoc-gui/jump-to-def-background.goml new file mode 100644 index 0000000000..3df899e0f2 --- /dev/null +++ b/src/test/rustdoc-gui/jump-to-def-background.goml @@ -0,0 +1,23 @@ +// We check the background color on the jump to definition links in the source code page. +goto: file://|DOC_PATH|/src/link_to_definition/lib.rs.html + +// Set the theme to dark. +local-storage: {"rustdoc-theme": "dark", "rustdoc-preferred-dark-theme": "dark", "rustdoc-use-system-theme": "false"} +// We reload the page so the local storage settings are being used. +reload: + +assert-css: ("body.source .example-wrap pre.rust a", {"background-color": "rgb(51, 51, 51)"}, ALL) + +// Set the theme to ayu. +local-storage: {"rustdoc-theme": "ayu", "rustdoc-preferred-dark-theme": "ayu", "rustdoc-use-system-theme": "false"} +// We reload the page so the local storage settings are being used. +reload: + +assert-css: ("body.source .example-wrap pre.rust a", {"background-color": "rgb(51, 51, 51)"}, ALL) + +// 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: ("body.source .example-wrap pre.rust a", {"background-color": "rgb(238, 238, 238)"}, ALL) diff --git a/src/test/rustdoc-gui/sidebar.goml b/src/test/rustdoc-gui/sidebar.goml index c8ebb8c56f..eacc9f6c15 100644 --- a/src/test/rustdoc-gui/sidebar.goml +++ b/src/test/rustdoc-gui/sidebar.goml @@ -7,12 +7,14 @@ assert-text: (".sidebar-elems > #all-types", "See all test_docs's items") assert-text: (".sidebar-elems > .crate > ul > li > a.current", "test_docs") // And we're also supposed to have the list of items in the current module. assert-text: (".sidebar-elems > .items > ul > li:nth-child(1)", "Modules") -assert-text: (".sidebar-elems > .items > ul > li:nth-child(2)", "Structs") -assert-text: (".sidebar-elems > .items > ul > li:nth-child(3)", "Enums") -assert-text: (".sidebar-elems > .items > ul > li:nth-child(4)", "Traits") -assert-text: (".sidebar-elems > .items > ul > li:nth-child(5)", "Functions") -assert-text: (".sidebar-elems > .items > ul > li:nth-child(6)", "Type Definitions") -assert-text: (".sidebar-elems > .items > ul > li:nth-child(7)", "Keywords") +assert-text: (".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" diff --git a/src/test/rustdoc-gui/src/lib2/lib.rs b/src/test/rustdoc-gui/src/lib2/lib.rs index cb63a9f600..d5835b78d2 100644 --- a/src/test/rustdoc-gui/src/lib2/lib.rs +++ b/src/test/rustdoc-gui/src/lib2/lib.rs @@ -67,6 +67,15 @@ pub mod long_table { /// /// I wanna sqdkfnqds f dsqf qds f dsqf dsq f dsq f qds f qds f qds f dsqq f dsf sqdf dsq fds f dsq f dq f ds fq sd fqds f dsq f sqd fsq df sd fdsqfqsd fdsq f dsq f dsqfd s dfq pub struct Foo; + + /// | This::is::a::kinda::very::long::header::number::one | This::is::a::kinda::very::long::header::number::two | This::is::a::kinda::very::long::header::number::one | This::is::a::kinda::very::long::header::number::two | + /// | ----------- | ----------- | ----------- | ----------- | + /// | This::is::a::kinda::long::content::number::one | This::is::a::kinda::very::long::content::number::two | This::is::a::kinda::long::content::number::one | This::is::a::kinda::very::long::content::number::two | + /// + /// I wanna sqdkfnqds f dsqf qds f dsqf dsq f dsq f qds f qds f qds f dsqq f dsf sqdf dsq fds f dsq f dq f ds fq sd fqds f dsq f sqd fsq df sd fdsqfqsd fdsq f dsq f dsqfd s dfq + impl Foo { + pub fn foo(&self) {} + } } pub mod summary_table { diff --git a/src/test/rustdoc-gui/src/link_to_definition/Cargo.lock b/src/test/rustdoc-gui/src/link_to_definition/Cargo.lock new file mode 100644 index 0000000000..e4b4e52d02 --- /dev/null +++ b/src/test/rustdoc-gui/src/link_to_definition/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "link_to_definition" +version = "0.1.0" diff --git a/src/test/rustdoc-gui/src/link_to_definition/Cargo.toml b/src/test/rustdoc-gui/src/link_to_definition/Cargo.toml new file mode 100644 index 0000000000..cdd294d74d --- /dev/null +++ b/src/test/rustdoc-gui/src/link_to_definition/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "link_to_definition" +version = "0.1.0" +edition = "2018" + +[lib] +path = "lib.rs" diff --git a/src/test/rustdoc-gui/src/link_to_definition/lib.rs b/src/test/rustdoc-gui/src/link_to_definition/lib.rs new file mode 100644 index 0000000000..de9ee66a2b --- /dev/null +++ b/src/test/rustdoc-gui/src/link_to_definition/lib.rs @@ -0,0 +1,6 @@ +pub struct Bar { + pub a: String, + pub b: u32, +} + +pub fn foo(_b: &Bar) {} diff --git a/src/test/rustdoc-gui/src/test_docs/Cargo.toml b/src/test/rustdoc-gui/src/test_docs/Cargo.toml index 7f3c65746f..5f527078e7 100644 --- a/src/test/rustdoc-gui/src/test_docs/Cargo.toml +++ b/src/test/rustdoc-gui/src/test_docs/Cargo.toml @@ -3,5 +3,7 @@ name = "test_docs" version = "0.1.0" edition = "2018" +build = "build.rs" + [lib] path = "lib.rs" diff --git a/src/test/rustdoc-gui/src/test_docs/build.rs b/src/test/rustdoc-gui/src/test_docs/build.rs new file mode 100644 index 0000000000..16c96ded91 --- /dev/null +++ b/src/test/rustdoc-gui/src/test_docs/build.rs @@ -0,0 +1,15 @@ +//! generate 2000 constants for testing + +use std::{fs::write, path::PathBuf}; + +fn main() -> std::io::Result<()> { + let out_dir = std::env::var("OUT_DIR").expect("OUT_DIR is not defined"); + + let mut output = String::new(); + for i in 0..2000 { + let line = format!("/// Some const A{0}\npub const A{0}: isize = 0;\n", i); + output.push_str(&*line); + }; + + write(&[&*out_dir, "huge_amount_of_consts.rs"].iter().collect::(), output) +} diff --git a/src/test/rustdoc-gui/src/test_docs/lib.rs b/src/test/rustdoc-gui/src/test_docs/lib.rs index af4f28047f..89871952c1 100644 --- a/src/test/rustdoc-gui/src/test_docs/lib.rs +++ b/src/test/rustdoc-gui/src/test_docs/lib.rs @@ -116,3 +116,136 @@ pub mod keyword {} /// Just some type alias. pub type SomeType = u32; + +pub mod huge_amount_of_consts { + include!(concat!(env!("OUT_DIR"), "/huge_amount_of_consts.rs")); +} + +/// Very long code text `hereIgoWithLongTextBecauseWhyNotAndWhyWouldntI`. +pub mod long_code_block {} + +/// # Top-doc Prose title +/// +/// Text below title. +/// +/// ## Top-doc Prose sub-heading +/// +/// Text below sub-heading. +/// +/// ### Top-doc Prose sub-sub-heading +/// +/// Text below sub-sub-heading +pub struct HeavilyDocumentedStruct { + /// # Title for field + /// ## Sub-heading for field + pub nothing: (), +} + +/// # Title for struct impl doc +/// +/// Text below heading. +/// +/// ## Sub-heading for struct impl doc +/// +/// Text below sub-heading. +/// +/// ### Sub-sub-heading for struct impl doc +/// +/// Text below sub-sub-heading. +/// +impl HeavilyDocumentedStruct { + /// # Title for struct impl-item doc + /// Text below title. + /// ## Sub-heading for struct impl-item doc + /// Text below sub-heading. + /// ### Sub-sub-heading for struct impl-item doc + /// Text below sub-sub-heading. + pub fn do_nothing() {} +} + +/// # Top-doc Prose title +/// +/// Text below title. +/// +/// ## Top-doc Prose sub-heading +/// +/// Text below sub-heading. +/// +/// ### Top-doc Prose sub-sub-heading +/// +/// Text below sub-sub-heading +pub enum HeavilyDocumentedEnum { + /// # None prose title + /// ## None prose sub-heading + None, + /// # Wrapped prose title + /// ## Wrapped prose sub-heading + Wrapped( + /// # Wrapped.0 prose title + /// ## Wrapped.0 prose sub-heading + String, + String, + ), + Structy { + /// # Structy prose title + /// ## Structy prose sub-heading + alpha: String, + beta: String, + }, +} + +/// # Title for enum impl doc +/// +/// Text below heading. +/// +/// ## Sub-heading for enum impl doc +/// +/// Text below sub-heading. +/// +/// ### Sub-sub-heading for enum impl doc +/// +/// Text below sub-sub-heading. +/// +impl HeavilyDocumentedEnum { + /// # Title for enum impl-item doc + /// Text below title. + /// ## Sub-heading for enum impl-item doc + /// Text below sub-heading. + /// ### Sub-sub-heading for enum impl-item doc + /// Text below sub-sub-heading. + pub fn do_nothing() {} +} + +/// # Top-doc prose title +/// +/// Text below heading. +/// +/// ## Top-doc prose sub-heading +/// +/// Text below heading. +pub union HeavilyDocumentedUnion { + /// # Title for union variant + /// ## Sub-heading for union variant + pub nothing: (), + pub something: f32, +} + +/// # Title for union impl doc +/// ## Sub-heading for union impl doc +impl HeavilyDocumentedUnion { + /// # Title for union impl-item doc + /// ## Sub-heading for union impl-item doc + pub fn do_nothing() {} +} + +/// # Top-doc prose title +/// +/// Text below heading. +/// +/// ## Top-doc prose sub-heading +/// +/// Text below heading. +#[macro_export] +macro_rules! heavily_documented_macro { + () => {}; +} diff --git a/src/test/rustdoc-js-std/multi-query.js b/src/test/rustdoc-js-std/multi-query.js index 01e5406518..1c92d01960 100644 --- a/src/test/rustdoc-js-std/multi-query.js +++ b/src/test/rustdoc-js-std/multi-query.js @@ -2,8 +2,9 @@ const QUERY = 'str,u8'; const EXPECTED = { 'others': [ - { 'path': 'std', 'name': 'str' }, - { 'path': 'std', 'name': 'u8' }, - { 'path': 'std::ffi', 'name': 'CStr' }, + { 'path': 'std', 'name': 'str', 'href': '../std/primitive.str.html' }, + { 'path': 'std', 'name': 'u8', 'href': '../std/primitive.u8.html' }, + { 'path': 'std', 'name': 'str', 'href': '../std/str/index.html' }, + { 'path': 'std', 'name': 'u8', 'href': '../std/u8/index.html' }, ], }; diff --git a/src/test/rustdoc-json/primitive.rs b/src/test/rustdoc-json/primitive.rs new file mode 100644 index 0000000000..3a7d6d18c1 --- /dev/null +++ b/src/test/rustdoc-json/primitive.rs @@ -0,0 +1,14 @@ +// edition:2018 + +#![feature(doc_primitive)] + +#[doc(primitive = "usize")] +mod usize {} + +// @set local_crate_id = primitive.json "$.index[*][?(@.name=='primitive')].crate_id" + +// @has - "$.index[*][?(@.name=='log10')]" +// @!is - "$.index[*][?(@.name=='log10')].crate_id" $local_crate_id +// @has - "$.index[*][?(@.name=='checked_add')]" +// @!is - "$.index[*][?(@.name=='checked_add')]" $local_crate_id +// @!has - "$.index[*][?(@.name=='is_ascii_uppercase')]" diff --git a/src/test/rustdoc-json/primitives.rs b/src/test/rustdoc-json/primitives.rs new file mode 100644 index 0000000000..fd04f04da0 --- /dev/null +++ b/src/test/rustdoc-json/primitives.rs @@ -0,0 +1,22 @@ +#![feature(never_type)] + +// @has primitives.json "$.index[*][?(@.name=='PrimNever')].visibility" \"public\" +// @has - "$.index[*][?(@.name=='PrimNever')].inner.type.kind" \"primitive\" +// @has - "$.index[*][?(@.name=='PrimNever')].inner.type.inner" \"never\" +pub type PrimNever = !; + +// @has - "$.index[*][?(@.name=='PrimStr')].inner.type.kind" \"primitive\" +// @has - "$.index[*][?(@.name=='PrimStr')].inner.type.inner" \"str\" +pub type PrimStr = str; + +// @has - "$.index[*][?(@.name=='PrimBool')].inner.type.kind" \"primitive\" +// @has - "$.index[*][?(@.name=='PrimBool')].inner.type.inner" \"bool\" +pub type PrimBool = bool; + +// @has - "$.index[*][?(@.name=='PrimChar')].inner.type.kind" \"primitive\" +// @has - "$.index[*][?(@.name=='PrimChar')].inner.type.inner" \"char\" +pub type PrimChar = char; + +// @has - "$.index[*][?(@.name=='PrimU8')].inner.type.kind" \"primitive\" +// @has - "$.index[*][?(@.name=='PrimU8')].inner.type.inner" \"u8\" +pub type PrimU8 = u8; diff --git a/src/test/rustdoc-json/structs/with_primitives.rs b/src/test/rustdoc-json/structs/with_primitives.rs index ea98676863..9e64317ec2 100644 --- a/src/test/rustdoc-json/structs/with_primitives.rs +++ b/src/test/rustdoc-json/structs/with_primitives.rs @@ -1,7 +1,7 @@ // @has with_primitives.json "$.index[*][?(@.name=='WithPrimitives')].visibility" \"public\" // @has - "$.index[*][?(@.name=='WithPrimitives')].kind" \"struct\" // @has - "$.index[*][?(@.name=='WithPrimitives')].inner.generics.params[0].name" \"\'a\" -// @has - "$.index[*][?(@.name=='WithPrimitives')].inner.generics.params[0].kind" \"lifetime\" +// @has - "$.index[*][?(@.name=='WithPrimitives')].inner.generics.params[0].kind.lifetime.outlives" [] // @has - "$.index[*][?(@.name=='WithPrimitives')].inner.struct_type" \"plain\" // @has - "$.index[*][?(@.name=='WithPrimitives')].inner.fields_stripped" true pub struct WithPrimitives<'a> { diff --git a/src/test/rustdoc-json/unions/impl.rs b/src/test/rustdoc-json/unions/impl.rs new file mode 100644 index 0000000000..0388b4a8c3 --- /dev/null +++ b/src/test/rustdoc-json/unions/impl.rs @@ -0,0 +1,15 @@ +#![no_std] + +// @has impl.json "$.index[*][?(@.name=='Ux')].visibility" \"public\" +// @has - "$.index[*][?(@.name=='Ux')].kind" \"union\" +pub union Ux { + a: u32, + b: u64 +} + +// @has - "$.index[*][?(@.name=='Num')].visibility" \"public\" +// @has - "$.index[*][?(@.name=='Num')].kind" \"trait\" +pub trait Num {} + +// @count - "$.index[*][?(@.name=='Ux')].inner.impls" 1 +impl Num for Ux {} diff --git a/src/test/rustdoc-ui/ambiguous-inherent-assoc-ty.rs b/src/test/rustdoc-ui/ambiguous-inherent-assoc-ty.rs index 3ad56aebc2..e58bba6405 100644 --- a/src/test/rustdoc-ui/ambiguous-inherent-assoc-ty.rs +++ b/src/test/rustdoc-ui/ambiguous-inherent-assoc-ty.rs @@ -11,7 +11,6 @@ impl Struct { pub const AssocConst: Self::AssocTy = 42; //~^ ERROR ambiguous associated type //~| HELP use fully-qualified syntax - // FIXME: for some reason, the error is shown twice with rustdoc but only once with rustc //~| ERROR ambiguous associated type //~| HELP use fully-qualified syntax } diff --git a/src/test/rustdoc-ui/bounded-hr-lifetime.rs b/src/test/rustdoc-ui/bounded-hr-lifetime.rs new file mode 100644 index 0000000000..b2e000b975 --- /dev/null +++ b/src/test/rustdoc-ui/bounded-hr-lifetime.rs @@ -0,0 +1,9 @@ +// This test ensures that rustdoc doesn't panic on higher-ranked lifetimes +// with bounds, because an error should have already been emitted by rustc. + +pub fn hrlt<'b, 'c>() +where + for<'a: 'b + 'c> &'a (): std::fmt::Debug, + //~^ ERROR lifetime bounds cannot be used in this context +{ +} diff --git a/src/test/rustdoc-ui/bounded-hr-lifetime.stderr b/src/test/rustdoc-ui/bounded-hr-lifetime.stderr new file mode 100644 index 0000000000..d8fcd6cb4b --- /dev/null +++ b/src/test/rustdoc-ui/bounded-hr-lifetime.stderr @@ -0,0 +1,10 @@ +error: lifetime bounds cannot be used in this context + --> $DIR/bounded-hr-lifetime.rs:6:13 + | +LL | for<'a: 'b + 'c> &'a (): std::fmt::Debug, + | ^^ ^^ + +error: Compilation failed, aborting rustdoc + +error: aborting due to 2 previous errors + diff --git a/src/test/rustdoc-ui/coverage/enum-tuple-documented.rs b/src/test/rustdoc-ui/coverage/enum-tuple-documented.rs new file mode 100644 index 0000000000..e9c165b191 --- /dev/null +++ b/src/test/rustdoc-ui/coverage/enum-tuple-documented.rs @@ -0,0 +1,37 @@ +// compile-flags:-Z unstable-options --show-coverage +// check-pass + +// The point of this test is to ensure that the number of "documented" items +// is higher than in `enum-tuple.rs`. + +//! (remember the crate root is still a module) + +/// so check out this enum here +pub enum ThisEnum { + /// VarOne. + VarOne( + /// hello! + String, + ), + /// Var Two. + VarTwo( + /// Hello + String, + /// Bis repetita. + String, + ), +} + +/// Struct. +pub struct ThisStruct( + /// hello + u32, +); + +/// Struct. +pub struct ThisStruct2( + /// hello + u32, + /// Bis repetita. + u8, +); diff --git a/src/test/rustdoc-ui/coverage/enum-tuple-documented.stdout b/src/test/rustdoc-ui/coverage/enum-tuple-documented.stdout new file mode 100644 index 0000000000..82c98f43f3 --- /dev/null +++ b/src/test/rustdoc-ui/coverage/enum-tuple-documented.stdout @@ -0,0 +1,7 @@ ++-------------------------------------+------------+------------+------------+------------+ +| File | Documented | Percentage | Examples | Percentage | ++-------------------------------------+------------+------------+------------+------------+ +| ...overage/enum-tuple-documented.rs | 9 | 100.0% | 0 | 0.0% | ++-------------------------------------+------------+------------+------------+------------+ +| Total | 9 | 100.0% | 0 | 0.0% | ++-------------------------------------+------------+------------+------------+------------+ diff --git a/src/test/rustdoc-ui/coverage/enum-tuple.rs b/src/test/rustdoc-ui/coverage/enum-tuple.rs new file mode 100644 index 0000000000..5fb2054507 --- /dev/null +++ b/src/test/rustdoc-ui/coverage/enum-tuple.rs @@ -0,0 +1,18 @@ +// compile-flags:-Z unstable-options --show-coverage +// check-pass + +//! (remember the crate root is still a module) + +/// so check out this enum here +pub enum ThisEnum { + /// No need to document the field if there is only one in a tuple variant! + VarOne(String), + /// But if there is more than one... still fine! + VarTwo(String, String), +} + +/// Struct. +pub struct ThisStruct(u32); + +/// Struct. +pub struct ThisStruct2(u32, u8); diff --git a/src/test/rustdoc-ui/coverage/enum-tuple.stdout b/src/test/rustdoc-ui/coverage/enum-tuple.stdout new file mode 100644 index 0000000000..a3377d59c0 --- /dev/null +++ b/src/test/rustdoc-ui/coverage/enum-tuple.stdout @@ -0,0 +1,7 @@ ++-------------------------------------+------------+------------+------------+------------+ +| File | Documented | Percentage | Examples | Percentage | ++-------------------------------------+------------+------------+------------+------------+ +| ...ustdoc-ui/coverage/enum-tuple.rs | 6 | 100.0% | 0 | 0.0% | ++-------------------------------------+------------+------------+------------+------------+ +| Total | 6 | 100.0% | 0 | 0.0% | ++-------------------------------------+------------+------------+------------+------------+ diff --git a/src/test/rustdoc-ui/coverage/enums.stdout b/src/test/rustdoc-ui/coverage/enums.stdout index 414d60c86d..64c012c1f6 100644 --- a/src/test/rustdoc-ui/coverage/enums.stdout +++ b/src/test/rustdoc-ui/coverage/enums.stdout @@ -1,7 +1,7 @@ +-------------------------------------+------------+------------+------------+------------+ | File | Documented | Percentage | Examples | Percentage | +-------------------------------------+------------+------------+------------+------------+ -| ...est/rustdoc-ui/coverage/enums.rs | 6 | 66.7% | 0 | 0.0% | +| ...est/rustdoc-ui/coverage/enums.rs | 6 | 75.0% | 0 | 0.0% | +-------------------------------------+------------+------------+------------+------------+ -| Total | 6 | 66.7% | 0 | 0.0% | +| Total | 6 | 75.0% | 0 | 0.0% | +-------------------------------------+------------+------------+------------+------------+ diff --git a/src/test/rustdoc-ui/display-output.rs b/src/test/rustdoc-ui/display-output.rs new file mode 100644 index 0000000000..5e390029dc --- /dev/null +++ b/src/test/rustdoc-ui/display-output.rs @@ -0,0 +1,9 @@ +// check-pass +// compile-flags:-Zunstable-options --display-doctest-warnings --test +// normalize-stdout-test: "src/test/rustdoc-ui" -> "$$DIR" +// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME" + +/// ``` +/// let x = 12; +/// ``` +pub fn foo() {} diff --git a/src/test/rustdoc-ui/display-output.stdout b/src/test/rustdoc-ui/display-output.stdout new file mode 100644 index 0000000000..00467b9359 --- /dev/null +++ b/src/test/rustdoc-ui/display-output.stdout @@ -0,0 +1,24 @@ + +running 1 test +test $DIR/display-output.rs - foo (line 6) ... ok + +successes: + +---- $DIR/display-output.rs - foo (line 6) stdout ---- +warning: unused variable: `x` + --> $DIR/display-output.rs:7:5 + | +LL | let x = 12; + | ^ help: if this is intentional, prefix it with an underscore: `_x` + | + = note: `#[warn(unused_variables)]` on by default + +warning: 1 warning emitted + + + +successes: + $DIR/display-output.rs - foo (line 6) + +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-cfg.rs b/src/test/rustdoc-ui/doc-cfg.rs new file mode 100644 index 0000000000..354d76bc3c --- /dev/null +++ b/src/test/rustdoc-ui/doc-cfg.rs @@ -0,0 +1,9 @@ +#![feature(doc_cfg)] + +#[doc(cfg(), cfg(foo, bar))] +//~^ ERROR +//~^^ ERROR +#[doc(cfg(foo), cfg(bar))] // ok! +#[doc(cfg())] //~ ERROR +#[doc(cfg(foo, bar))] //~ ERROR +pub fn foo() {} diff --git a/src/test/rustdoc-ui/doc-cfg.stderr b/src/test/rustdoc-ui/doc-cfg.stderr new file mode 100644 index 0000000000..b379f6febe --- /dev/null +++ b/src/test/rustdoc-ui/doc-cfg.stderr @@ -0,0 +1,26 @@ +error: `cfg` predicate is not specified + --> $DIR/doc-cfg.rs:3:7 + | +LL | #[doc(cfg(), cfg(foo, bar))] + | ^^^^^ + +error: multiple `cfg` predicates are specified + --> $DIR/doc-cfg.rs:3:23 + | +LL | #[doc(cfg(), cfg(foo, bar))] + | ^^^ + +error: `cfg` predicate is not specified + --> $DIR/doc-cfg.rs:7:7 + | +LL | #[doc(cfg())] + | ^^^^^ + +error: multiple `cfg` predicates are specified + --> $DIR/doc-cfg.rs:8:16 + | +LL | #[doc(cfg(foo, bar))] + | ^^^ + +error: aborting due to 4 previous errors + diff --git a/src/test/rustdoc-ui/doctest-edition.stderr b/src/test/rustdoc-ui/doctest-edition.stderr index 019f259288..1643d60537 100644 --- a/src/test/rustdoc-ui/doctest-edition.stderr +++ b/src/test/rustdoc-ui/doctest-edition.stderr @@ -16,7 +16,7 @@ LL | #![deny(rustdoc::invalid_rust_codeblocks)] help: mark blocks that do not contain Rust code as text | LL | //! ```text - | ~~~~~~~ + | ++++ error: aborting due to previous error diff --git a/src/test/rustdoc-ui/feature-gate-doc_cfg_hide.rs b/src/test/rustdoc-ui/feature-gate-doc_cfg_hide.rs new file mode 100644 index 0000000000..17812018b9 --- /dev/null +++ b/src/test/rustdoc-ui/feature-gate-doc_cfg_hide.rs @@ -0,0 +1,7 @@ +#![doc(cfg_hide(test))] +//~^ ERROR `#[doc(cfg_hide)]` is experimental + +#[cfg(not(test))] +pub fn public_fn() {} +#[cfg(test)] +pub fn internal_use_only() {} diff --git a/src/test/rustdoc-ui/feature-gate-doc_cfg_hide.stderr b/src/test/rustdoc-ui/feature-gate-doc_cfg_hide.stderr new file mode 100644 index 0000000000..ba42c7bbb0 --- /dev/null +++ b/src/test/rustdoc-ui/feature-gate-doc_cfg_hide.stderr @@ -0,0 +1,14 @@ +error[E0658]: `#[doc(cfg_hide)]` is experimental + --> $DIR/feature-gate-doc_cfg_hide.rs:1:1 + | +LL | #![doc(cfg_hide(test))] + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #43781 for more information + = help: add `#![feature(doc_cfg_hide)]` to the crate attributes to enable + +error: Compilation failed, aborting rustdoc + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/rustdoc-ui/intra-doc/anchors.rs b/src/test/rustdoc-ui/intra-doc/anchors.rs index 6785cb7abe..34e11c7c7b 100644 --- a/src/test/rustdoc-ui/intra-doc/anchors.rs +++ b/src/test/rustdoc-ui/intra-doc/anchors.rs @@ -37,13 +37,3 @@ pub fn bar() {} /// Damn enum's variants: [Enum::A#whatever]. //~^ ERROR `Enum::A#whatever` contains an anchor pub fn enum_link() {} - -/// Primitives? -/// -/// [u32#hello] -//~^ ERROR `u32#hello` contains an anchor -pub fn x() {} - -/// [prim@usize#x] -//~^ ERROR `prim@usize#x` contains an anchor -pub mod usize {} diff --git a/src/test/rustdoc-ui/intra-doc/anchors.stderr b/src/test/rustdoc-ui/intra-doc/anchors.stderr index d63e1ee60b..0d226b2775 100644 --- a/src/test/rustdoc-ui/intra-doc/anchors.stderr +++ b/src/test/rustdoc-ui/intra-doc/anchors.stderr @@ -1,19 +1,3 @@ -error: `prim@usize#x` contains an anchor, but links to builtin types are already anchored - --> $DIR/anchors.rs:47:6 - | -LL | /// [prim@usize#x] - | ^^^^^^^^^^-- - | | - | invalid anchor - | -note: the lint level is defined here - --> $DIR/anchors.rs:1:9 - | -LL | #![deny(rustdoc::broken_intra_doc_links)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: this restriction may be lifted in a future release - = note: see https://github.com/rust-lang/rust/issues/83083 for more information - error: `Foo::f#hola` contains an anchor, but links to fields are already anchored --> $DIR/anchors.rs:25:15 | @@ -21,6 +5,12 @@ LL | /// Or maybe [Foo::f#hola]. | ^^^^^^----- | | | invalid anchor + | +note: the lint level is defined here + --> $DIR/anchors.rs:1:9 + | +LL | #![deny(rustdoc::broken_intra_doc_links)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `hello#people#!` contains multiple anchors --> $DIR/anchors.rs:31:28 @@ -38,16 +28,5 @@ LL | /// Damn enum's variants: [Enum::A#whatever]. | | | invalid anchor -error: `u32#hello` contains an anchor, but links to builtin types are already anchored - --> $DIR/anchors.rs:43:6 - | -LL | /// [u32#hello] - | ^^^------ - | | - | invalid anchor - | - = note: this restriction may be lifted in a future release - = note: see https://github.com/rust-lang/rust/issues/83083 for more information - -error: aborting due to 5 previous errors +error: aborting due to 3 previous errors diff --git a/src/test/rustdoc-ui/intra-doc/auxiliary/dep1.rs b/src/test/rustdoc-ui/intra-doc/auxiliary/dep1.rs new file mode 100644 index 0000000000..d11c69f812 --- /dev/null +++ b/src/test/rustdoc-ui/intra-doc/auxiliary/dep1.rs @@ -0,0 +1 @@ +// intentionally empty diff --git a/src/test/rustdoc-ui/intra-doc/auxiliary/dep2.rs b/src/test/rustdoc-ui/intra-doc/auxiliary/dep2.rs new file mode 100644 index 0000000000..d11c69f812 --- /dev/null +++ b/src/test/rustdoc-ui/intra-doc/auxiliary/dep2.rs @@ -0,0 +1 @@ +// intentionally empty diff --git a/src/test/rustdoc-ui/intra-doc/auxiliary/dep3.rs b/src/test/rustdoc-ui/intra-doc/auxiliary/dep3.rs new file mode 100644 index 0000000000..d11c69f812 --- /dev/null +++ b/src/test/rustdoc-ui/intra-doc/auxiliary/dep3.rs @@ -0,0 +1 @@ +// intentionally empty diff --git a/src/test/rustdoc-ui/intra-doc/auxiliary/dep4.rs b/src/test/rustdoc-ui/intra-doc/auxiliary/dep4.rs new file mode 100644 index 0000000000..d11c69f812 --- /dev/null +++ b/src/test/rustdoc-ui/intra-doc/auxiliary/dep4.rs @@ -0,0 +1 @@ +// intentionally empty diff --git a/src/test/rustdoc-ui/intra-doc/extern-crate-load.rs b/src/test/rustdoc-ui/intra-doc/extern-crate-load.rs new file mode 100644 index 0000000000..438c56aa51 --- /dev/null +++ b/src/test/rustdoc-ui/intra-doc/extern-crate-load.rs @@ -0,0 +1,26 @@ +// check-pass +// aux-crate:dep1=dep1.rs +// aux-crate:dep2=dep2.rs +// aux-crate:dep3=dep3.rs +// aux-crate:dep4=dep4.rs +#![deny(rustdoc::broken_intra_doc_links)] + +pub trait Trait { + /// [dep1] + type Item; +} + +pub struct S { + /// [dep2] + pub x: usize, +} + +extern "C" { + /// [dep3] + pub fn printf(); +} + +pub enum E { + /// [dep4] + A +} diff --git a/src/test/rustdoc-ui/intra-doc/warning.stderr b/src/test/rustdoc-ui/intra-doc/warning.stderr index af83b9b195..19399a0df5 100644 --- a/src/test/rustdoc-ui/intra-doc/warning.stderr +++ b/src/test/rustdoc-ui/intra-doc/warning.stderr @@ -88,7 +88,7 @@ LL | #[doc = $f] | ^^^^^^^^^^^ ... LL | f!("Foo\nbar [BarF] bar\nbaz"); - | ------------------------------- in this macro invocation + | ------------------------------ in this macro invocation | = note: the link appears in this line: diff --git a/src/test/rustdoc-ui/invalid-syntax.stderr b/src/test/rustdoc-ui/invalid-syntax.stderr index 5b1846a49d..4c6249cc6d 100644 --- a/src/test/rustdoc-ui/invalid-syntax.stderr +++ b/src/test/rustdoc-ui/invalid-syntax.stderr @@ -14,7 +14,7 @@ LL | | /// ``` help: mark blocks that do not contain Rust code as text | LL | /// ```text - | ~~~~~~~ + | ++++ warning: could not parse code block as Rust code --> $DIR/invalid-syntax.rs:9:5 @@ -32,7 +32,7 @@ LL | | /// ``` help: mark blocks that do not contain Rust code as text | LL | /// ```text - | ~~~~~~~ + | ++++ warning: could not parse code block as Rust code --> $DIR/invalid-syntax.rs:21:5 @@ -47,7 +47,7 @@ LL | | /// ``` help: mark blocks that do not contain Rust code as text | LL | /// ```text - | ~~~~~~~ + | ++++ warning: could not parse code block as Rust code --> $DIR/invalid-syntax.rs:35:5 @@ -123,7 +123,7 @@ LL | | /// ``` help: mark blocks that do not contain Rust code as text | LL | /// ```text - | ~~~~~~~ + | ++++ warning: could not parse code block as Rust code --> $DIR/invalid-syntax.rs:92:9 @@ -148,7 +148,7 @@ LL | | /// ``` help: mark blocks that do not contain Rust code as text | LL | /// ```text - | ~~~~~~~ + | ++++ warning: 12 warnings emitted diff --git a/src/test/rustdoc-ui/lint-missing-doc-code-example.rs b/src/test/rustdoc-ui/lint-missing-doc-code-example.rs index 41e8847792..fac6342cd2 100644 --- a/src/test/rustdoc-ui/lint-missing-doc-code-example.rs +++ b/src/test/rustdoc-ui/lint-missing-doc-code-example.rs @@ -70,6 +70,22 @@ pub union Union { b: f32, } +// no code example and it's fine! +impl Clone for Struct { + fn clone(&self) -> Self { + Self { field: self.field } + } +} + + + +/// doc +/// +/// ``` +/// println!("hello"); +/// ``` +#[derive(Clone)] +pub struct NiceStruct; #[doc(hidden)] pub mod foo { diff --git a/src/test/rustdoc/associated-consts.rs b/src/test/rustdoc/associated-consts.rs new file mode 100644 index 0000000000..6ae5e20632 --- /dev/null +++ b/src/test/rustdoc/associated-consts.rs @@ -0,0 +1,31 @@ +#![crate_name = "foo"] + +pub trait Trait { + const FOO: u32 = 12; + + fn foo(); +} + +pub struct Bar; + +// @has 'foo/struct.Bar.html' +// @has - '//h3[@class="sidebar-title"]' 'Associated Constants' +// @has - '//div[@class="sidebar-elems"]//div[@class="sidebar-links"]/a' 'FOO' +impl Trait for Bar { + const FOO: u32 = 1; + + fn foo() {} +} + +pub enum Foo { + A, +} + +// @has 'foo/enum.Foo.html' +// @has - '//h3[@class="sidebar-title"]' 'Associated Constants' +// @has - '//div[@class="sidebar-elems"]//div[@class="sidebar-links"]/a' 'FOO' +impl Trait for Foo { + const FOO: u32 = 1; + + fn foo() {} +} diff --git a/src/test/rustdoc/auxiliary/issue-15318.rs b/src/test/rustdoc/auxiliary/issue-15318.rs index 83cc31b587..695fa58ef1 100644 --- a/src/test/rustdoc/auxiliary/issue-15318.rs +++ b/src/test/rustdoc/auxiliary/issue-15318.rs @@ -1,6 +1,15 @@ +// no-prefer-dynamic // compile-flags: -Cmetadata=aux - +#![crate_type = "rlib"] #![doc(html_root_url = "http://example.com/")] +#![feature(lang_items)] +#![no_std] + +#[lang = "eh_personality"] +fn foo() {} + +#[panic_handler] +fn bar(_: &core::panic::PanicInfo) -> ! { loop {} } /// dox #[doc(primitive = "pointer")] diff --git a/src/test/rustdoc/auxiliary/primitive-doc.rs b/src/test/rustdoc/auxiliary/primitive-doc.rs index a5b69740dd..e8da852a57 100644 --- a/src/test/rustdoc/auxiliary/primitive-doc.rs +++ b/src/test/rustdoc/auxiliary/primitive-doc.rs @@ -1,5 +1,8 @@ // compile-flags: --crate-type lib --edition 2018 +#![feature(no_core)] +#![no_core] + #[doc(primitive = "usize")] /// This is the built-in type `usize`. mod usize { diff --git a/src/test/rustdoc/check-source-code-urls-to-def-std.rs b/src/test/rustdoc/check-source-code-urls-to-def-std.rs new file mode 100644 index 0000000000..b129ceb5b7 --- /dev/null +++ b/src/test/rustdoc/check-source-code-urls-to-def-std.rs @@ -0,0 +1,17 @@ +// compile-flags: -Zunstable-options --generate-link-to-definition + +#![crate_name = "foo"] + +// @has 'src/foo/check-source-code-urls-to-def-std.rs.html' + +fn babar() {} + +// @has - '//a[@href="{{channel}}/std/primitive.u32.html"]' 'u32' +// @has - '//a[@href="{{channel}}/std/primitive.str.html"]' 'str' +// @has - '//a[@href="{{channel}}/std/primitive.bool.html"]' 'bool' +// @has - '//a[@href="../../src/foo/check-source-code-urls-to-def-std.rs.html#7"]' 'babar' +pub fn foo(a: u32, b: &str, c: String) { + let x = 12; + let y: bool = true; + babar(); +} diff --git a/src/test/rustdoc/check-source-code-urls-to-def.rs b/src/test/rustdoc/check-source-code-urls-to-def.rs index e3ae79ccdb..0cb8e42301 100644 --- a/src/test/rustdoc/check-source-code-urls-to-def.rs +++ b/src/test/rustdoc/check-source-code-urls-to-def.rs @@ -27,6 +27,8 @@ impl Foo { fn babar() {} // @has - '//a/@href' '/struct.String.html' +// @has - '//a/@href' '/primitive.u32.html' +// @has - '//a/@href' '/primitive.str.html' // @count - '//a[@href="../../src/foo/check-source-code-urls-to-def.rs.html#21"]' 5 // @has - '//a[@href="../../source_code/struct.SourceCode.html"]' 'source_code::SourceCode' pub fn foo(a: u32, b: &str, c: String, d: Foo, e: bar::Bar, f: source_code::SourceCode) { @@ -40,5 +42,9 @@ pub fn foo(a: u32, b: &str, c: String, d: Foo, e: bar::Bar, f: source_code::Sour // @has - '//a[@href="../../src/foo/auxiliary/source-code-bar.rs.html#14-16"]' 'bar::sub::Trait' // @has - '//a[@href="../../src/foo/auxiliary/source-code-bar.rs.html#14-16"]' 'Trait' -pub fn foo2(t: &T, v: &V) { +pub fn foo2(t: &T, v: &V, b: bool) { } + +// @has - '//a[@href="../../foo/primitive.bool.html"]' 'bool' +#[doc(primitive = "bool")] +mod whatever {} diff --git a/src/test/rustdoc/cross-crate-primitive-doc.rs b/src/test/rustdoc/cross-crate-primitive-doc.rs index 05376e4680..4ba296ee04 100644 --- a/src/test/rustdoc/cross-crate-primitive-doc.rs +++ b/src/test/rustdoc/cross-crate-primitive-doc.rs @@ -1,9 +1,13 @@ // aux-build:primitive-doc.rs // compile-flags: --extern-html-root-url=primitive_doc=../ -Z unstable-options +// only-linux -#![no_std] +#![feature(no_core)] +#![no_core] extern crate primitive_doc; // @has 'cross_crate_primitive_doc/fn.foo.html' '//a[@href="../primitive_doc/primitive.usize.html"]' 'usize' +// @has 'cross_crate_primitive_doc/fn.foo.html' '//a[@href="../primitive_doc/primitive.usize.html"]' 'link' +/// [link](usize) pub fn foo() -> usize { 0 } diff --git a/src/test/rustdoc/doc-auto-cfg.rs b/src/test/rustdoc/doc-auto-cfg.rs new file mode 100644 index 0000000000..fcdd835456 --- /dev/null +++ b/src/test/rustdoc/doc-auto-cfg.rs @@ -0,0 +1,8 @@ +#![feature(doc_auto_cfg)] + +#![crate_name = "foo"] + +// @has foo/fn.foo.html +// @has - '//*[@class="item-info"]/*[@class="stab portability"]' 'non-test' +#[cfg(not(test))] +pub fn foo() {} diff --git a/src/test/rustdoc/doc-cfg-hide.rs b/src/test/rustdoc/doc-cfg-hide.rs new file mode 100644 index 0000000000..424fa6d6a9 --- /dev/null +++ b/src/test/rustdoc/doc-cfg-hide.rs @@ -0,0 +1,32 @@ +#![crate_name = "oud"] +#![feature(doc_auto_cfg, doc_cfg, doc_cfg_hide)] + +#![doc(cfg_hide(feature = "solecism"))] + +// @has 'oud/struct.Solecism.html' +// @count - '//*[@class="stab portability"]' 0 +// compile-flags:--cfg feature="solecism" +#[cfg(feature = "solecism")] +pub struct Solecism; + +// @has 'oud/struct.Scribacious.html' +// @count - '//*[@class="stab portability"]' 1 +// @matches - '//*[@class="stab portability"]' 'crate feature solecism' +#[cfg(feature = "solecism")] +#[doc(cfg(feature = "solecism"))] +pub struct Scribacious; + +// @has 'oud/struct.Hyperdulia.html' +// @count - '//*[@class="stab portability"]' 1 +// @matches - '//*[@class="stab portability"]' 'crate feature hyperdulia' +// compile-flags:--cfg feature="hyperdulia" +#[cfg(feature = "solecism")] +#[cfg(feature = "hyperdulia")] +pub struct Hyperdulia; + +// @has 'oud/struct.Oystercatcher.html' +// @count - '//*[@class="stab portability"]' 1 +// @matches - '//*[@class="stab portability"]' 'crate features solecism and oystercatcher' +// compile-flags:--cfg feature="oystercatcher" +#[cfg(all(feature = "solecism", feature = "oystercatcher"))] +pub struct Oystercatcher; diff --git a/src/test/rustdoc/doc-cfg-implicit-gate.rs b/src/test/rustdoc/doc-cfg-implicit-gate.rs new file mode 100644 index 0000000000..92804d3729 --- /dev/null +++ b/src/test/rustdoc/doc-cfg-implicit-gate.rs @@ -0,0 +1,7 @@ +// compile-flags:--cfg feature="worricow" +#![crate_name = "xenogenous"] + +// @has 'xenogenous/struct.Worricow.html' +// @count - '//*[@class="stab portability"]' 0 +#[cfg(feature = "worricow")] +pub struct Worricow; diff --git a/src/test/rustdoc/doc-cfg-implicit.rs b/src/test/rustdoc/doc-cfg-implicit.rs new file mode 100644 index 0000000000..5d17a4ede6 --- /dev/null +++ b/src/test/rustdoc/doc-cfg-implicit.rs @@ -0,0 +1,31 @@ +#![crate_name = "funambulism"] +#![feature(doc_auto_cfg, doc_cfg)] + +// @has 'funambulism/struct.Disorbed.html' +// @count - '//*[@class="stab portability"]' 1 +// @matches - '//*[@class="stab portability"]' 'crate feature disorbed' +// compile-flags:--cfg feature="disorbed" +#[cfg(feature = "disorbed")] +pub struct Disorbed; + +// @has 'funambulism/struct.Aesthesia.html' +// @count - '//*[@class="stab portability"]' 1 +// @matches - '//*[@class="stab portability"]' 'crate feature aesthesia' +// compile-flags:--cfg feature="aesthesia" +#[doc(cfg(feature = "aesthesia"))] +pub struct Aesthesia; + +// @has 'funambulism/struct.Pliothermic.html' +// @count - '//*[@class="stab portability"]' 1 +// @matches - '//*[@class="stab portability"]' 'crate feature pliothermic' +// compile-flags:--cfg feature="epopoeist" +#[cfg(feature = "epopoeist")] +#[doc(cfg(feature = "pliothermic"))] +pub struct Pliothermic; + +// @has 'funambulism/struct.Simillimum.html' +// @count - '//*[@class="stab portability"]' 0 +// compile-flags:--cfg feature="simillimum" +#[cfg(feature = "simillimum")] +#[doc(cfg(all()))] +pub struct Simillimum; diff --git a/src/test/rustdoc/external-cross.rs b/src/test/rustdoc/external-cross.rs index 056ed35346..3f8e168829 100644 --- a/src/test/rustdoc/external-cross.rs +++ b/src/test/rustdoc/external-cross.rs @@ -6,5 +6,5 @@ extern crate external_cross; // @has host/struct.NeedMoreDocs.html -// @has - '//h1' 'Cross-crate imported docs' +// @has - '//h2' 'Cross-crate imported docs' pub use external_cross::NeedMoreDocs; diff --git a/src/test/rustdoc/external-doc.rs b/src/test/rustdoc/external-doc.rs index fc29cb252e..bd322d67a3 100644 --- a/src/test/rustdoc/external-doc.rs +++ b/src/test/rustdoc/external-doc.rs @@ -1,6 +1,6 @@ // @has external_doc/struct.IncludeStrDocs.html -// @has - '//h1' 'External Docs' -// @has - '//h2' 'Inline Docs' +// @has - '//h2' 'External Docs' +// @has - '//h3' 'Inline Docs' #[doc = include_str!("auxiliary/external-doc.md")] /// ## Inline Docs pub struct IncludeStrDocs; @@ -8,7 +8,7 @@ pub struct IncludeStrDocs; macro_rules! dir { () => { "auxiliary" } } // @has external_doc/struct.EagerExpansion.html -// @has - '//h1' 'External Docs' +// @has - '//h2' 'External Docs' #[doc = include_str!(concat!(dir!(), "/external-doc.md"))] /// ## Inline Docs pub struct EagerExpansion; diff --git a/src/test/rustdoc/feature-gate-doc_auto_cfg.rs b/src/test/rustdoc/feature-gate-doc_auto_cfg.rs new file mode 100644 index 0000000000..da76381e48 --- /dev/null +++ b/src/test/rustdoc/feature-gate-doc_auto_cfg.rs @@ -0,0 +1,8 @@ +#![feature(doc_cfg)] + +#![crate_name = "foo"] + +// @has foo/fn.foo.html +// @count - '//*[@class="item-info"]/*[@class="stab portability"]' 0 +#[cfg(not(test))] +pub fn foo() {} diff --git a/src/test/rustdoc/hidden-trait-methods-with-document-hidden-items.rs b/src/test/rustdoc/hidden-trait-methods-with-document-hidden-items.rs new file mode 100644 index 0000000000..95b3e9b652 --- /dev/null +++ b/src/test/rustdoc/hidden-trait-methods-with-document-hidden-items.rs @@ -0,0 +1,31 @@ +// compile-flags: -Z unstable-options --document-hidden-items + +// test for trait methods with `doc(hidden)` with `--document-hidden-items` passed. +#![crate_name = "foo"] + +// @has foo/trait.Trait.html +// @has - '//*[@id="associatedtype.Foo"]' 'type Foo' +// @has - '//*[@id="associatedtype.Bar"]' 'type Bar' +// @has - '//*[@id="tymethod.f"]' 'fn f()' +// @has - '//*[@id="tymethod.g"]' 'fn g()' +pub trait Trait { + #[doc(hidden)] + type Foo; + type Bar; + #[doc(hidden)] + fn f(); + fn g(); +} + +// @has foo/struct.S.html +// @has - '//*[@id="associatedtype.Foo"]' 'type Foo' +// @has - '//*[@id="associatedtype.Bar"]' 'type Bar' +// @has - '//*[@id="method.f"]' 'fn f()' +// @has - '//*[@id="method.g"]' 'fn g()' +pub struct S; +impl Trait for S { + type Foo = (); + type Bar = (); + fn f() {} + fn g() {} +} diff --git a/src/test/rustdoc/hidden-trait-methods.rs b/src/test/rustdoc/hidden-trait-methods.rs new file mode 100644 index 0000000000..e924ba7d0a --- /dev/null +++ b/src/test/rustdoc/hidden-trait-methods.rs @@ -0,0 +1,29 @@ +// test for trait methods with `doc(hidden)`. +#![crate_name = "foo"] + +// @has foo/trait.Trait.html +// @!has - '//*[@id="associatedtype.Foo"]' 'type Foo' +// @has - '//*[@id="associatedtype.Bar"]' 'type Bar' +// @!has - '//*[@id="tymethod.f"]' 'fn f()' +// @has - '//*[@id="tymethod.g"]' 'fn g()' +pub trait Trait { + #[doc(hidden)] + type Foo; + type Bar; + #[doc(hidden)] + fn f(); + fn g(); +} + +// @has foo/struct.S.html +// @!has - '//*[@id="associatedtype.Foo"]' 'type Foo' +// @has - '//*[@id="associatedtype.Bar"]' 'type Bar' +// @!has - '//*[@id="method.f"]' 'fn f()' +// @has - '//*[@id="method.g"]' 'fn g()' +pub struct S; +impl Trait for S { + type Foo = (); + type Bar = (); + fn f() {} + fn g() {} +} diff --git a/src/test/rustdoc/intra-doc/anchors.rs b/src/test/rustdoc/intra-doc/anchors.rs index 8ec1a7b4f9..3d4c464960 100644 --- a/src/test/rustdoc/intra-doc/anchors.rs +++ b/src/test/rustdoc/intra-doc/anchors.rs @@ -10,3 +10,15 @@ pub struct Something; /// /// To link to [Something#Anchor!] pub struct SomeOtherType; + +/// Primitives? +/// +/// [u32#hello] +// @has anchors/fn.x.html +// @has - '//a/@href' '{{channel}}/std/primitive.u32.html#hello' +pub fn x() {} + +/// [prim@usize#x] +// @has anchors/usize/index.html +// @has - '//a/@href' '{{channel}}/std/primitive.usize.html#x' +pub mod usize {} diff --git a/src/test/rustdoc/intra-doc/auxiliary/my-core.rs b/src/test/rustdoc/intra-doc/auxiliary/my-core.rs index 54e986be9e..92cfd46188 100644 --- a/src/test/rustdoc/intra-doc/auxiliary/my-core.rs +++ b/src/test/rustdoc/intra-doc/auxiliary/my-core.rs @@ -2,6 +2,10 @@ #![no_core] #![crate_type="rlib"] +#[doc(primitive = "char")] +/// Some char docs +mod char {} + #[lang = "char"] impl char { pub fn len_utf8(self) -> usize { diff --git a/src/test/rustdoc/intra-doc/prim-methods-external-core.rs b/src/test/rustdoc/intra-doc/prim-methods-external-core.rs index 9347d7bb42..9d869984bb 100644 --- a/src/test/rustdoc/intra-doc/prim-methods-external-core.rs +++ b/src/test/rustdoc/intra-doc/prim-methods-external-core.rs @@ -1,7 +1,7 @@ // aux-build:my-core.rs // build-aux-docs // ignore-cross-compile -// ignore-windows +// only-linux #![deny(broken_intra_doc_links)] #![feature(no_core, lang_items)] @@ -9,8 +9,8 @@ #![crate_type = "rlib"] // @has prim_methods_external_core/index.html -// @has - '//*[@id="main"]//a[@href="{{channel}}/std/primitive.char.html"]' 'char' -// @has - '//*[@id="main"]//a[@href="{{channel}}/std/primitive.char.html#method.len_utf8"]' 'char::len_utf8' +// @has - '//*[@id="main"]//a[@href="../my_core/primitive.char.html"]' 'char' +// @has - '//*[@id="main"]//a[@href="../my_core/primitive.char.html#method.len_utf8"]' 'char::len_utf8' //! A [`char`] and its [`char::len_utf8`]. diff --git a/src/test/rustdoc/intra-doc/prim-methods-local.rs b/src/test/rustdoc/intra-doc/prim-methods-local.rs index 124faa9a63..cfb3c3842a 100644 --- a/src/test/rustdoc/intra-doc/prim-methods-local.rs +++ b/src/test/rustdoc/intra-doc/prim-methods-local.rs @@ -5,10 +5,13 @@ // @has prim_methods_local/index.html -// @has - '//*[@id="main"]//a[@href="{{channel}}/std/primitive.char.html"]' 'char' -// @has - '//*[@id="main"]//a[@href="{{channel}}/std/primitive.char.html#method.len_utf8"]' 'char::len_utf8' +// @has - '//*[@id="main"]//a[@href="primitive.char.html"]' 'char' +// @has - '//*[@id="main"]//a[@href="primitive.char.html#method.len_utf8"]' 'char::len_utf8' -//! A [`char`] and its [`char::len_utf8`]. +//! A [prim@`char`] and its [`char::len_utf8`]. + +#[doc(primitive = "char")] +mod char {} #[lang = "char"] impl char { diff --git a/src/test/rustdoc/intra-link-prim-self.rs b/src/test/rustdoc/intra-link-prim-self.rs index 4744c84b62..8c47f7ef77 100644 --- a/src/test/rustdoc/intra-link-prim-self.rs +++ b/src/test/rustdoc/intra-link-prim-self.rs @@ -7,8 +7,8 @@ /// [Self::f] /// [Self::MAX] // @has intra_link_prim_self/primitive.usize.html -// @has - '//a[@href="{{channel}}/std/primitive.usize.html#method.f"]' 'Self::f' -// @has - '//a[@href="{{channel}}/std/primitive.usize.html#associatedconstant.MAX"]' 'Self::MAX' +// @has - '//a[@href="primitive.usize.html#method.f"]' 'Self::f' +// @has - '//a[@href="primitive.usize.html#associatedconstant.MAX"]' 'Self::MAX' impl usize { /// Some docs pub fn f() {} diff --git a/src/test/rustdoc/issue-15318-2.rs b/src/test/rustdoc/issue-15318-2.rs index 2af811ad5b..f7f5052a36 100644 --- a/src/test/rustdoc/issue-15318-2.rs +++ b/src/test/rustdoc/issue-15318-2.rs @@ -1,5 +1,6 @@ // aux-build:issue-15318.rs // ignore-cross-compile +#![no_std] extern crate issue_15318; diff --git a/src/test/rustdoc/issue-42760.rs b/src/test/rustdoc/issue-42760.rs index b07dc3f6e9..4944f81570 100644 --- a/src/test/rustdoc/issue-42760.rs +++ b/src/test/rustdoc/issue-42760.rs @@ -1,5 +1,5 @@ // @has issue_42760/struct.NonGen.html -// @has - '//h1' 'Example' +// @has - '//h2' 'Example' /// Item docs. /// diff --git a/src/test/rustdoc/issue-89309-heading-levels.rs b/src/test/rustdoc/issue-89309-heading-levels.rs new file mode 100644 index 0000000000..bb706c28ff --- /dev/null +++ b/src/test/rustdoc/issue-89309-heading-levels.rs @@ -0,0 +1,29 @@ +#![crate_name = "foo"] + +// @has foo/trait.Read.html +// @has - '//h2' 'Trait examples' +/// # Trait examples +pub trait Read { + // @has - '//h5' 'Function examples' + /// # Function examples + fn read(&mut self, buf: &mut [u8]) -> Result; +} + +pub struct Foo; + +// @has foo/struct.Foo.html +impl Foo { + // @has - '//h5' 'Implementation header' + /// # Implementation header + pub fn bar(&self) -> usize { + 1 + } +} + +impl Read for Foo { + // @has - '//h5' 'Trait implementation header' + /// # Trait implementation header + fn read(&mut self, buf: &mut [u8]) -> Result { + Ok(1) + } +} diff --git a/src/test/rustdoc/macro-document-private-duplicate.rs b/src/test/rustdoc/macro-document-private-duplicate.rs index 460785ed97..7576c1326b 100644 --- a/src/test/rustdoc/macro-document-private-duplicate.rs +++ b/src/test/rustdoc/macro-document-private-duplicate.rs @@ -1,3 +1,5 @@ +// ignore-test (fails spuriously, see issue #89228) + // FIXME: If two macros in the same module have the same name // (yes, that's a thing), rustdoc lists both of them on the index page, // but only documents the first one on the page for the macro. diff --git a/src/test/rustdoc/macro_rules-matchers.rs b/src/test/rustdoc/macro_rules-matchers.rs index 5f8340e731..efc3b21e6d 100644 --- a/src/test/rustdoc/macro_rules-matchers.rs +++ b/src/test/rustdoc/macro_rules-matchers.rs @@ -6,37 +6,31 @@ // @has 'foo/macro.todo.html' // @has - '//span[@class="macro"]' 'macro_rules!' // @has - '//span[@class="ident"]' 'todo' -// Note: count = 2 * ('=' + '>') + '+' = 2 * (1 + 1) + 1 = 5 -// @count - '//pre[@class="rust macro"]//span[@class="op"]' 5 +// Note: the only op is the `+` +// @count - '//pre[@class="rust macro"]//span[@class="op"]' 1 -// @has - '{ ()' -// @has - '//span[@class="op"]' '=' -// @has - '//span[@class="op"]' '>' -// @has - '{ ... };' - -// @has - '($(' +// @has - '{ () => { ... }; ($(' // @has - '//span[@class="macro-nonterminal"]' '$' // @has - '//span[@class="macro-nonterminal"]' 'arg' // @has - ':' // @has - '//span[@class="ident"]' 'tt' // @has - '),' // @has - '//span[@class="op"]' '+' -// @has - ')' +// @has - ') => { ... }; }' pub use std::todo; mod mod1 { // @has 'foo/macro.macro1.html' // @has - 'macro_rules!' // @has - 'macro1' - // @has - '{ ()' - // @has - '($(' + // @has - '{ () => { ... }; ($(' // @has - '//span[@class="macro-nonterminal"]' '$' // @has - '//span[@class="macro-nonterminal"]' 'arg' // @has - ':' // @has - 'expr' // @has - '),' // @has - '+' - // @has - ')' + // @has - ') => { ... }; }' #[macro_export] macro_rules! macro1 { () => {}; diff --git a/src/test/rustdoc/no_std-primitive.rs b/src/test/rustdoc/no_std-primitive.rs new file mode 100644 index 0000000000..22fd392dd3 --- /dev/null +++ b/src/test/rustdoc/no_std-primitive.rs @@ -0,0 +1,6 @@ +#![no_std] + +/// Link to [intra-doc link][u8] +// @has 'no_std_primitive/fn.foo.html' '//a[@href="{{channel}}/core/primitive.u8.html"]' 'intra-doc link' +// @has - '//a[@href="{{channel}}/core/primitive.u8.html"]' 'u8' +pub fn foo() -> u8 {} diff --git a/src/test/rustdoc/primitive/no_std.rs b/src/test/rustdoc/primitive/no_std.rs new file mode 100644 index 0000000000..f0f70cb6c1 --- /dev/null +++ b/src/test/rustdoc/primitive/no_std.rs @@ -0,0 +1,16 @@ +#![no_std] +#![deny(warnings)] +#![deny(rustdoc::broken_intra_doc_links)] + +// @has no_std/fn.foo.html '//a/[@href="{{channel}}/core/primitive.u8.html"]' 'u8' +// @has no_std/fn.foo.html '//a/[@href="{{channel}}/core/primitive.u8.html"]' 'primitive link' +/// Link to [primitive link][u8] +pub fn foo() -> u8 {} + +// Test that all primitives can be linked to. +/// [isize] [i8] [i16] [i32] [i64] [i128] +/// [usize] [u8] [u16] [u32] [u64] [u128] +/// [f32] [f64] +/// [char] [bool] [str] [slice] [array] [tuple] [unit] +/// [pointer] [reference] [fn] [never] +pub fn bar() {} diff --git a/src/test/rustdoc/short-docblock.rs b/src/test/rustdoc/short-docblock.rs index 74fa783174..17c44eab09 100644 --- a/src/test/rustdoc/short-docblock.rs +++ b/src/test/rustdoc/short-docblock.rs @@ -2,7 +2,7 @@ // @has foo/index.html '//*[@class="item-right docblock-short"]/p' 'fooo' // @!has foo/index.html '//*[@class="item-right docblock-short"]/p/h1' 'fooo' -// @has foo/fn.foo.html '//h1[@id="fooo"]/a[@href="#fooo"]' 'fooo' +// @has foo/fn.foo.html '//h2[@id="fooo"]/a[@href="#fooo"]' 'fooo' /// # fooo /// @@ -11,7 +11,7 @@ pub fn foo() {} // @has foo/index.html '//*[@class="item-right docblock-short"]/p' 'mooood' // @!has foo/index.html '//*[@class="item-right docblock-short"]/p/h2' 'mooood' -// @has foo/foo/index.html '//h2[@id="mooood"]/a[@href="#mooood"]' 'mooood' +// @has foo/foo/index.html '//h3[@id="mooood"]/a[@href="#mooood"]' 'mooood' /// ## mooood /// diff --git a/src/test/rustdoc/smart-punct.rs b/src/test/rustdoc/smart-punct.rs index 5319892c99..7ae5bd6994 100644 --- a/src/test/rustdoc/smart-punct.rs +++ b/src/test/rustdoc/smart-punct.rs @@ -21,7 +21,7 @@ //! ``` // @has "foo/index.html" "//p" "This is the “start” of the ‘document’! How’d you know that “it’s” the start?" -// @has "foo/index.html" "//h1" "Header with “smart punct’”" +// @has "foo/index.html" "//h2" "Header with “smart punct’”" // @has "foo/index.html" '//a[@href="https://www.rust-lang.org"]' "link with “smart punct’” – yessiree!" // @has "foo/index.html" '//code' "this inline code -- it shouldn't have \"smart punct\"" // @has "foo/index.html" '//pre' "let x = \"don't smart-punct me -- please!\";" diff --git a/src/test/rustdoc/synthetic_auto/no-redundancy.rs b/src/test/rustdoc/synthetic_auto/no-redundancy.rs index f727c9a47f..16ab876e82 100644 --- a/src/test/rustdoc/synthetic_auto/no-redundancy.rs +++ b/src/test/rustdoc/synthetic_auto/no-redundancy.rs @@ -10,7 +10,7 @@ where // @has no_redundancy/struct.Outer.html // @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ -// "impl Send for Outer where T: Copy + Send" +// "impl Send for Outer where T: Send + Copy" pub struct Outer { inner_field: Inner, } diff --git a/src/test/rustdoc/table-in-docblock.rs b/src/test/rustdoc/table-in-docblock.rs new file mode 100644 index 0000000000..858b589196 --- /dev/null +++ b/src/test/rustdoc/table-in-docblock.rs @@ -0,0 +1,16 @@ +#![crate_name = "foo"] + +// @has foo/struct.Foo.html +// @count - '//*[@class="docblock"]/div/table' 2 +// @!has - '//*[@class="docblock"]/table' +/// | hello | hello2 | +/// | ----- | ------ | +/// | data | data2 | +pub struct Foo; + +impl Foo { + /// | hello | hello2 | + /// | ----- | ------ | + /// | data | data2 | + pub fn foo(&self) {} +} diff --git a/src/test/rustdoc/type-layout.rs b/src/test/rustdoc/type-layout.rs index 272911de68..0868486fa5 100644 --- a/src/test/rustdoc/type-layout.rs +++ b/src/test/rustdoc/type-layout.rs @@ -52,3 +52,21 @@ pub struct Unsized([u8]); // @!has type_layout/trait.MyTrait.html 'Size: ' pub trait MyTrait {} + +// @has type_layout/enum.Variants.html 'Size: ' +// @has - '2 bytes' +// @has - 'A: 0 bytes' +// @has - 'B: 1 byte' +pub enum Variants { + A, + B(u8), +} + +// @has type_layout/enum.WithNiche.html 'Size: ' +// @has - //p '4 bytes' +// @has - 'None: 0 bytes' +// @has - 'Some: 4 bytes' +pub enum WithNiche { + None, + Some(std::num::NonZeroU32), +} diff --git a/src/test/ui-fulldeps/auxiliary/issue-40001-plugin.rs b/src/test/ui-fulldeps/auxiliary/issue-40001-plugin.rs index 0b68d5e04f..8051c58898 100644 --- a/src/test/ui-fulldeps/auxiliary/issue-40001-plugin.rs +++ b/src/test/ui-fulldeps/auxiliary/issue-40001-plugin.rs @@ -1,4 +1,4 @@ -#![feature(box_syntax, plugin, rustc_private)] +#![feature(plugin, rustc_private)] #![crate_type = "dylib"] extern crate rustc_ast_pretty; @@ -21,7 +21,7 @@ use rustc_span::source_map; #[no_mangle] fn __rustc_plugin_registrar(reg: &mut Registry) { reg.lint_store.register_lints(&[&MISSING_ALLOWED_ATTR]); - reg.lint_store.register_late_pass(|| box MissingAllowedAttrPass); + reg.lint_store.register_late_pass(|| Box::new(MissingAllowedAttrPass)); } declare_lint! { diff --git a/src/test/ui-fulldeps/auxiliary/lint-for-crate-rpass.rs b/src/test/ui-fulldeps/auxiliary/lint-for-crate-rpass.rs index 0015a82612..e726f8402e 100644 --- a/src/test/ui-fulldeps/auxiliary/lint-for-crate-rpass.rs +++ b/src/test/ui-fulldeps/auxiliary/lint-for-crate-rpass.rs @@ -1,7 +1,6 @@ // force-host #![feature(rustc_private)] -#![feature(box_syntax)] extern crate rustc_driver; extern crate rustc_hir; @@ -14,6 +13,7 @@ extern crate rustc_ast; use rustc_ast::attr; use rustc_driver::plugin::Registry; use rustc_lint::{LateContext, LateLintPass, LintContext, LintPass}; +use rustc_span::def_id::CRATE_DEF_ID; use rustc_span::symbol::Symbol; macro_rules! fake_lint_pass { @@ -27,13 +27,14 @@ macro_rules! fake_lint_pass { } impl LateLintPass<'_> for $struct { - fn check_crate(&mut self, cx: &LateContext, krate: &rustc_hir::Crate) { + fn check_crate(&mut self, cx: &LateContext) { let attrs = cx.tcx.hir().attrs(rustc_hir::CRATE_HIR_ID); + let span = cx.tcx.def_span(CRATE_DEF_ID); $( if !cx.sess().contains_name(attrs, $attr) { cx.lint(CRATE_NOT_OKAY, |lint| { let msg = format!("crate is not marked with #![{}]", $attr); - lint.build(&msg).set_span(krate.module().inner).emit() + lint.build(&msg).set_span(span).emit() }); } )* @@ -73,7 +74,7 @@ fn __rustc_plugin_registrar(reg: &mut Registry) { &CRATE_NOT_GREY, &CRATE_NOT_GREEN, ]); - reg.lint_store.register_late_pass(|| box PassOkay); - reg.lint_store.register_late_pass(|| box PassRedBlue); - reg.lint_store.register_late_pass(|| box PassGreyGreen); + reg.lint_store.register_late_pass(|| Box::new(PassOkay)); + reg.lint_store.register_late_pass(|| Box::new(PassRedBlue)); + reg.lint_store.register_late_pass(|| Box::new(PassGreyGreen)); } diff --git a/src/test/ui-fulldeps/auxiliary/lint-for-crate.rs b/src/test/ui-fulldeps/auxiliary/lint-for-crate.rs index 87c90b5364..4bbed50298 100644 --- a/src/test/ui-fulldeps/auxiliary/lint-for-crate.rs +++ b/src/test/ui-fulldeps/auxiliary/lint-for-crate.rs @@ -1,7 +1,6 @@ // force-host #![feature(rustc_private)] -#![feature(box_syntax)] extern crate rustc_driver; extern crate rustc_hir; @@ -9,13 +8,13 @@ extern crate rustc_hir; extern crate rustc_lint; #[macro_use] extern crate rustc_session; -extern crate rustc_span; extern crate rustc_ast; +extern crate rustc_span; use rustc_driver::plugin::Registry; -use rustc_lint::{LateContext, LateLintPass, LintArray, LintContext, LintPass}; +use rustc_lint::{LateContext, LateLintPass, LintContext}; +use rustc_span::def_id::CRATE_DEF_ID; use rustc_span::symbol::Symbol; -use rustc_ast::attr; declare_lint! { CRATE_NOT_OKAY, @@ -26,13 +25,12 @@ declare_lint! { declare_lint_pass!(Pass => [CRATE_NOT_OKAY]); impl<'tcx> LateLintPass<'tcx> for Pass { - fn check_crate(&mut self, cx: &LateContext, krate: &rustc_hir::Crate) { + fn check_crate(&mut self, cx: &LateContext) { let attrs = cx.tcx.hir().attrs(rustc_hir::CRATE_HIR_ID); + let span = cx.tcx.def_span(CRATE_DEF_ID); if !cx.sess().contains_name(attrs, Symbol::intern("crate_okay")) { cx.lint(CRATE_NOT_OKAY, |lint| { - lint.build("crate is not marked with #![crate_okay]") - .set_span(krate.module().inner) - .emit() + lint.build("crate is not marked with #![crate_okay]").set_span(span).emit() }); } } @@ -41,5 +39,5 @@ impl<'tcx> LateLintPass<'tcx> for Pass { #[no_mangle] fn __rustc_plugin_registrar(reg: &mut Registry) { reg.lint_store.register_lints(&[&CRATE_NOT_OKAY]); - reg.lint_store.register_late_pass(|| box Pass); + reg.lint_store.register_late_pass(|| Box::new(Pass)); } diff --git a/src/test/ui-fulldeps/auxiliary/lint-group-plugin-test.rs b/src/test/ui-fulldeps/auxiliary/lint-group-plugin-test.rs index f6ae560411..253855fd2e 100644 --- a/src/test/ui-fulldeps/auxiliary/lint-group-plugin-test.rs +++ b/src/test/ui-fulldeps/auxiliary/lint-group-plugin-test.rs @@ -1,6 +1,6 @@ // force-host -#![feature(box_syntax, rustc_private)] +#![feature(rustc_private)] // Load rustc as a plugin to get macros. extern crate rustc_driver; @@ -36,7 +36,7 @@ impl<'tcx> LateLintPass<'tcx> for Pass { #[no_mangle] fn __rustc_plugin_registrar(reg: &mut Registry) { reg.lint_store.register_lints(&[&TEST_LINT, &PLEASE_LINT]); - reg.lint_store.register_late_pass(|| box Pass); + reg.lint_store.register_late_pass(|| Box::new(Pass)); reg.lint_store.register_group( true, "lint_me", diff --git a/src/test/ui-fulldeps/auxiliary/lint-plugin-test.rs b/src/test/ui-fulldeps/auxiliary/lint-plugin-test.rs index 32326bc8a5..42368ec36a 100644 --- a/src/test/ui-fulldeps/auxiliary/lint-plugin-test.rs +++ b/src/test/ui-fulldeps/auxiliary/lint-plugin-test.rs @@ -1,6 +1,6 @@ // force-host -#![feature(box_syntax, rustc_private)] +#![feature(rustc_private)] extern crate rustc_ast; @@ -31,5 +31,5 @@ impl EarlyLintPass for Pass { #[no_mangle] fn __rustc_plugin_registrar(reg: &mut Registry) { reg.lint_store.register_lints(&[&TEST_LINT]); - reg.lint_store.register_early_pass(|| box Pass); + reg.lint_store.register_early_pass(|| Box::new(Pass)); } diff --git a/src/test/ui-fulldeps/auxiliary/lint-tool-test.rs b/src/test/ui-fulldeps/auxiliary/lint-tool-test.rs index 42c1c851de..81feddf571 100644 --- a/src/test/ui-fulldeps/auxiliary/lint-tool-test.rs +++ b/src/test/ui-fulldeps/auxiliary/lint-tool-test.rs @@ -1,4 +1,4 @@ -#![feature(box_syntax, rustc_private)] +#![feature(rustc_private)] extern crate rustc_ast; @@ -46,7 +46,7 @@ impl EarlyLintPass for Pass { #[no_mangle] fn __rustc_plugin_registrar(reg: &mut Registry) { reg.lint_store.register_lints(&[&TEST_RUSTC_TOOL_LINT, &TEST_LINT, &TEST_GROUP]); - reg.lint_store.register_early_pass(|| box Pass); + reg.lint_store.register_early_pass(|| Box::new(Pass)); reg.lint_store.register_group( true, "clippy::group", diff --git a/src/test/ui-fulldeps/auxiliary/outlive-expansion-phase.rs b/src/test/ui-fulldeps/auxiliary/outlive-expansion-phase.rs index d0eedf23ca..e83dfe8046 100644 --- a/src/test/ui-fulldeps/auxiliary/outlive-expansion-phase.rs +++ b/src/test/ui-fulldeps/auxiliary/outlive-expansion-phase.rs @@ -1,6 +1,6 @@ // force-host -#![feature(box_syntax, rustc_private)] +#![feature(rustc_private)] extern crate rustc_middle; extern crate rustc_driver; @@ -20,5 +20,5 @@ impl Drop for Foo { #[no_mangle] fn __rustc_plugin_registrar(_: &mut Registry) { thread_local!(static FOO: RefCell>> = RefCell::new(None)); - FOO.with(|s| *s.borrow_mut() = Some(box Foo { foo: 10 } as Box)); + FOO.with(|s| *s.borrow_mut() = Some(Box::new(Foo { foo: 10 }) as Box)); } diff --git a/src/test/ui-fulldeps/deriving-encodable-decodable-box.rs b/src/test/ui-fulldeps/deriving-encodable-decodable-box.rs index 119fa3d6fa..fab2031d95 100644 --- a/src/test/ui-fulldeps/deriving-encodable-decodable-box.rs +++ b/src/test/ui-fulldeps/deriving-encodable-decodable-box.rs @@ -1,7 +1,6 @@ // run-pass #![allow(unused_imports)] -#![feature(box_syntax)] #![feature(rustc_private)] extern crate rustc_macros; diff --git a/src/test/ui-fulldeps/hash-stable-is-unstable.rs b/src/test/ui-fulldeps/hash-stable-is-unstable.rs index d93e21cf79..1be08191bc 100644 --- a/src/test/ui-fulldeps/hash-stable-is-unstable.rs +++ b/src/test/ui-fulldeps/hash-stable-is-unstable.rs @@ -2,10 +2,10 @@ extern crate rustc_data_structures; //~^ use of unstable library feature 'rustc_private' -extern crate rustc_middle; -//~^ use of unstable library feature 'rustc_private' extern crate rustc_macros; //~^ use of unstable library feature 'rustc_private' +extern crate rustc_query_system; +//~^ use of unstable library feature 'rustc_private' use rustc_macros::HashStable; //~^ use of unstable library feature 'rustc_private' diff --git a/src/test/ui-fulldeps/hash-stable-is-unstable.stderr b/src/test/ui-fulldeps/hash-stable-is-unstable.stderr index 212f63f709..d25657691e 100644 --- a/src/test/ui-fulldeps/hash-stable-is-unstable.stderr +++ b/src/test/ui-fulldeps/hash-stable-is-unstable.stderr @@ -10,7 +10,7 @@ LL | extern crate rustc_data_structures; error[E0658]: use of unstable library feature 'rustc_private': this crate is being loaded from the sysroot, an unstable location; did you mean to load this crate from crates.io via `Cargo.toml` instead? --> $DIR/hash-stable-is-unstable.rs:5:1 | -LL | extern crate rustc_middle; +LL | extern crate rustc_macros; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: see issue #27812 for more information @@ -19,8 +19,8 @@ LL | extern crate rustc_middle; error[E0658]: use of unstable library feature 'rustc_private': this crate is being loaded from the sysroot, an unstable location; did you mean to load this crate from crates.io via `Cargo.toml` instead? --> $DIR/hash-stable-is-unstable.rs:7:1 | -LL | extern crate rustc_macros; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | extern crate rustc_query_system; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: see issue #27812 for more information = help: add `#![feature(rustc_private)]` to the crate attributes to enable diff --git a/src/test/ui-fulldeps/internal-lints/lint_pass_impl_without_macro.stderr b/src/test/ui-fulldeps/internal-lints/lint_pass_impl_without_macro.stderr index 66f37f1a34..9df6be65eb 100644 --- a/src/test/ui-fulldeps/internal-lints/lint_pass_impl_without_macro.stderr +++ b/src/test/ui-fulldeps/internal-lints/lint_pass_impl_without_macro.stderr @@ -18,7 +18,7 @@ LL | impl LintPass for Custom { | ^^^^^^^^ ... LL | custom_lint_pass_macro!(); - | -------------------------- in this macro invocation + | ------------------------- in this macro invocation | = help: try using `declare_lint_pass!` or `impl_lint_pass!` instead = note: this error originates in the macro `custom_lint_pass_macro` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui-fulldeps/issue-76270-panic-in-libproc-macro.stderr b/src/test/ui-fulldeps/issue-76270-panic-in-libproc-macro.stderr index e472242ce4..5cc292dbb4 100644 --- a/src/test/ui-fulldeps/issue-76270-panic-in-libproc-macro.stderr +++ b/src/test/ui-fulldeps/issue-76270-panic-in-libproc-macro.stderr @@ -2,7 +2,7 @@ error: proc macro panicked --> $DIR/issue-76270-panic-in-libproc-macro.rs:15:1 | LL | proc_macro_panic::panic_in_libproc_macro!(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: message: `""` is not a valid identifier diff --git a/src/test/ui/alignment-gep-tup-like-1.rs b/src/test/ui/alignment-gep-tup-like-1.rs index adbd05ed8c..eb503dcf3b 100644 --- a/src/test/ui/alignment-gep-tup-like-1.rs +++ b/src/test/ui/alignment-gep-tup-like-1.rs @@ -3,8 +3,6 @@ #![allow(non_camel_case_types)] #![allow(dead_code)] -#![feature(box_syntax)] - struct pair { a: A, b: B } @@ -25,10 +23,10 @@ impl Invokable for Invoker { } fn f(a: A, b: u16) -> Box+'static> { - box Invoker { + Box::new(Invoker { a: a, b: b, - } as Box+'static> + }) as Box+'static> } pub fn main() { diff --git a/src/test/ui/annotate-snippet/multispan.stderr b/src/test/ui/annotate-snippet/multispan.stderr index 4ac31e32ba..baed54c59a 100644 --- a/src/test/ui/annotate-snippet/multispan.stderr +++ b/src/test/ui/annotate-snippet/multispan.stderr @@ -2,41 +2,41 @@ error: hello to you, too! --> $DIR/multispan.rs:15:5 | LL | hello!(hi); - | ^^^^^^^^^^^ + | ^^^^^^^^^^ | error: hello to you, too! --> $DIR/multispan.rs:18:5 | LL | hello!(hi hi); - | ^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ | error: hello to you, too! --> $DIR/multispan.rs:21:5 | LL | hello!(hi hi hi); - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ | error: hello to you, too! --> $DIR/multispan.rs:24:5 | LL | hello!(hi hey hi yo hi beep beep hi hi); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | error: hello to you, too! --> $DIR/multispan.rs:25:5 | LL | hello!(hi there, hi how are you? hi... hi.); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | error: hello to you, too! --> $DIR/multispan.rs:26:5 | LL | hello!(whoah. hi di hi di ho); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | error: hello to you, too! --> $DIR/multispan.rs:27:5 | LL | hello!(hi good hi and good bye); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | diff --git a/src/test/ui/anon-params/anon-params-denied-2018.stderr b/src/test/ui/anon-params/anon-params-denied-2018.stderr index 55905e5ca6..bb60c898e8 100644 --- a/src/test/ui/anon-params/anon-params-denied-2018.stderr +++ b/src/test/ui/anon-params/anon-params-denied-2018.stderr @@ -8,15 +8,15 @@ LL | fn foo(i32); help: if this is a `self` type, give it a parameter name | LL | fn foo(self: i32); - | ~~~~~~~~~ + | +++++ help: if this is a parameter name, give it a type | LL | fn foo(i32: TypeName); - | ~~~~~~~~~~~~~ + | ++++++++++ help: if this is a type, explicitly ignore the parameter name | LL | fn foo(_: i32); - | ~~~~~~ + | ++ error: expected one of `:`, `@`, or `|`, found `)` --> $DIR/anon-params-denied-2018.rs:9:29 @@ -28,7 +28,7 @@ LL | fn foo_with_ref(&mut i32); help: if this is a `self` type, give it a parameter name | LL | fn foo_with_ref(self: &mut i32); - | ~~~~~~~~~~~~~~ + | +++++ help: if this is a parameter name, give it a type | LL | fn foo_with_ref(i32: &mut TypeName); @@ -36,7 +36,7 @@ LL | fn foo_with_ref(i32: &mut TypeName); help: if this is a type, explicitly ignore the parameter name | LL | fn foo_with_ref(_: &mut i32); - | ~~~~~~~~~~~ + | ++ error: expected one of `(`, `...`, `..=`, `..`, `::`, `:`, `{`, or `|`, found `)` --> $DIR/anon-params-denied-2018.rs:12:47 @@ -96,15 +96,15 @@ LL | fn bar_with_default_impl(String, String) {} help: if this is a `self` type, give it a parameter name | LL | fn bar_with_default_impl(self: String, String) {} - | ~~~~~~~~~~~~ + | +++++ help: if this is a parameter name, give it a type | LL | fn bar_with_default_impl(String: TypeName, String) {} - | ~~~~~~~~~~~~~~~~ + | ++++++++++ help: if this is a type, explicitly ignore the parameter name | LL | fn bar_with_default_impl(_: String, String) {} - | ~~~~~~~~~ + | ++ error: expected one of `:`, `@`, or `|`, found `)` --> $DIR/anon-params-denied-2018.rs:22:44 @@ -116,11 +116,11 @@ LL | fn bar_with_default_impl(String, String) {} help: if this is a parameter name, give it a type | LL | fn bar_with_default_impl(String, String: TypeName) {} - | ~~~~~~~~~~~~~~~~ + | ++++++++++ help: if this is a type, explicitly ignore the parameter name | LL | fn bar_with_default_impl(String, _: String) {} - | ~~~~~~~~~ + | ++ error: expected one of `:`, `@`, or `|`, found `,` --> $DIR/anon-params-denied-2018.rs:27:22 @@ -132,11 +132,11 @@ LL | fn baz(a:usize, b, c: usize) -> usize { help: if this is a parameter name, give it a type | LL | fn baz(a:usize, b: TypeName, c: usize) -> usize { - | ~~~~~~~~~~~ + | ++++++++++ help: if this is a type, explicitly ignore the parameter name | LL | fn baz(a:usize, _: b, c: usize) -> usize { - | ~~~~ + | ++ error: aborting due to 9 previous errors diff --git a/src/test/ui/anon-params/anon-params-deprecated.stderr b/src/test/ui/anon-params/anon-params-deprecated.stderr index 98d52d659a..474b14f59e 100644 --- a/src/test/ui/anon-params/anon-params-deprecated.stderr +++ b/src/test/ui/anon-params/anon-params-deprecated.stderr @@ -1,4 +1,4 @@ -warning: anonymous parameters are deprecated and will be removed in the next edition. +warning: anonymous parameters are deprecated and will be removed in the next edition --> $DIR/anon-params-deprecated.rs:9:12 | LL | fn foo(i32); @@ -12,7 +12,7 @@ LL | #![warn(anonymous_parameters)] = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! = note: for more information, see issue #41686 -warning: anonymous parameters are deprecated and will be removed in the next edition. +warning: anonymous parameters are deprecated and will be removed in the next edition --> $DIR/anon-params-deprecated.rs:12:30 | LL | fn bar_with_default_impl(String, String) {} @@ -21,7 +21,7 @@ LL | fn bar_with_default_impl(String, String) {} = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! = note: for more information, see issue #41686 -warning: anonymous parameters are deprecated and will be removed in the next edition. +warning: anonymous parameters are deprecated and will be removed in the next edition --> $DIR/anon-params-deprecated.rs:12:38 | LL | fn bar_with_default_impl(String, String) {} diff --git a/src/test/ui/array-slice-vec/slice_binary_search.rs b/src/test/ui/array-slice-vec/slice_binary_search.rs index 1223696017..4d8022ecba 100644 --- a/src/test/ui/array-slice-vec/slice_binary_search.rs +++ b/src/test/ui/array-slice-vec/slice_binary_search.rs @@ -2,6 +2,7 @@ // Test binary_search_by_key lifetime. Issue #34683 +#[allow(dead_code)] #[derive(Debug)] struct Assignment { topic: String, diff --git a/src/test/ui/array-slice-vec/vec-dst.rs b/src/test/ui/array-slice-vec/vec-dst.rs index e741201652..c58ddbc423 100644 --- a/src/test/ui/array-slice-vec/vec-dst.rs +++ b/src/test/ui/array-slice-vec/vec-dst.rs @@ -1,11 +1,9 @@ // run-pass -#![feature(box_syntax)] - pub fn main() { - // Tests for indexing into box/& [T; n] + // Tests for indexing into Box<[T; n]>/& [T; n] let x: [isize; 3] = [1, 2, 3]; - let mut x: Box<[isize; 3]> = box x; + let mut x: Box<[isize; 3]> = x.into(); assert_eq!(x[0], 1); assert_eq!(x[1], 2); assert_eq!(x[2], 3); diff --git a/src/test/ui/array-slice-vec/vec-mut-iter-borrow.stderr b/src/test/ui/array-slice-vec/vec-mut-iter-borrow.stderr index 679fd89977..0ec263c850 100644 --- a/src/test/ui/array-slice-vec/vec-mut-iter-borrow.stderr +++ b/src/test/ui/array-slice-vec/vec-mut-iter-borrow.stderr @@ -7,7 +7,7 @@ LL | for x in &mut xs { | first mutable borrow occurs here | first borrow later used here LL | xs.push(1) - | ^^ second mutable borrow occurs here + | ^^^^^^^^^^ second mutable borrow occurs here error: aborting due to previous error diff --git a/src/test/ui/array-slice-vec/vector-no-ann-2.rs b/src/test/ui/array-slice-vec/vector-no-ann-2.rs index dd8f402f3f..e2055f551a 100644 --- a/src/test/ui/array-slice-vec/vector-no-ann-2.rs +++ b/src/test/ui/array-slice-vec/vector-no-ann-2.rs @@ -2,6 +2,6 @@ // pretty-expanded FIXME #23616 -#![feature(box_syntax)] - -pub fn main() { let _quux: Box> = box Vec::new(); } +pub fn main() { + let _quux: Box> = Box::new(Vec::new()); +} diff --git a/src/test/ui/asm/aarch64/bad-options.rs b/src/test/ui/asm/aarch64/bad-options.rs new file mode 100644 index 0000000000..8775eba4a7 --- /dev/null +++ b/src/test/ui/asm/aarch64/bad-options.rs @@ -0,0 +1,39 @@ +// only-aarch64 + +#![feature(asm, global_asm)] + +fn main() { + let mut foo = 0; + unsafe { + asm!("", options(nomem, readonly)); + //~^ ERROR the `nomem` and `readonly` options are mutually exclusive + asm!("", options(pure, nomem, noreturn)); + //~^ ERROR the `pure` and `noreturn` options are mutually exclusive + //~^^ ERROR asm with the `pure` option must have at least one output + asm!("{}", in(reg) foo, options(pure, nomem)); + //~^ ERROR asm with the `pure` option must have at least one output + asm!("{}", out(reg) foo, options(noreturn)); + //~^ ERROR asm outputs are not allowed with the `noreturn` option + } + + unsafe { + asm!("", clobber_abi("foo")); + //~^ 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("x0") foo, clobber_abi("C")); + } +} + +global_asm!("", options(nomem)); +//~^ ERROR expected one of +global_asm!("", options(readonly)); +//~^ ERROR expected one of +global_asm!("", options(noreturn)); +//~^ ERROR expected one of +global_asm!("", options(pure)); +//~^ ERROR expected one of +global_asm!("", options(nostack)); +//~^ ERROR expected one of +global_asm!("", options(preserves_flags)); +//~^ ERROR expected one of diff --git a/src/test/ui/asm/aarch64/bad-options.stderr b/src/test/ui/asm/aarch64/bad-options.stderr new file mode 100644 index 0000000000..21bcc4a9c7 --- /dev/null +++ b/src/test/ui/asm/aarch64/bad-options.stderr @@ -0,0 +1,84 @@ +error: the `nomem` and `readonly` options are mutually exclusive + --> $DIR/bad-options.rs:8:18 + | +LL | asm!("", options(nomem, readonly)); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: the `pure` and `noreturn` options are mutually exclusive + --> $DIR/bad-options.rs:10:18 + | +LL | asm!("", options(pure, nomem, noreturn)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: asm with the `pure` option must have at least one output + --> $DIR/bad-options.rs:10:18 + | +LL | asm!("", options(pure, nomem, noreturn)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: asm with the `pure` option must have at least one output + --> $DIR/bad-options.rs:13:33 + | +LL | asm!("{}", in(reg) foo, options(pure, nomem)); + | ^^^^^^^^^^^^^^^^^^^^ + +error: asm outputs are not allowed with the `noreturn` option + --> $DIR/bad-options.rs:15:20 + | +LL | asm!("{}", out(reg) foo, options(noreturn)); + | ^^^^^^^^^^^^ + +error: asm with `clobber_abi` must specify explicit registers for outputs + --> $DIR/bad-options.rs:22:20 + | +LL | asm!("{}", out(reg) foo, clobber_abi("C")); + | ^^^^^^^^^^^^ ---------------- clobber_abi + | | + | generic outputs + +error: expected one of `)`, `att_syntax`, or `raw`, found `nomem` + --> $DIR/bad-options.rs:28: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 + | +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 + | +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 + | +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 + | +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 + | +LL | global_asm!("", options(preserves_flags)); + | ^^^^^^^^^^^^^^^ expected one of `)`, `att_syntax`, or `raw` + +error: invalid ABI for `clobber_abi` + --> $DIR/bad-options.rs:20:18 + | +LL | asm!("", clobber_abi("foo")); + | ^^^^^^^^^^^^^^^^^^ + | + = note: the following ABIs are supported on this target: `C`, `system`, `efiapi` + +error: aborting due to 13 previous errors + diff --git a/src/test/ui/asm/aarch64/bad-reg.rs b/src/test/ui/asm/aarch64/bad-reg.rs new file mode 100644 index 0000000000..22d0499a1c --- /dev/null +++ b/src/test/ui/asm/aarch64/bad-reg.rs @@ -0,0 +1,59 @@ +// only-aarch64 +// compile-flags: -C target-feature=+fp + +#![feature(asm)] + +fn main() { + let mut foo = 0; + let mut bar = 0; + unsafe { + // Bad register/register class + + asm!("{}", in(foo) foo); + //~^ ERROR invalid register class `foo`: unknown register class + asm!("", in("foo") foo); + //~^ ERROR invalid register `foo`: unknown register + asm!("{:z}", in(reg) foo); + //~^ ERROR invalid asm template modifier for this register class + asm!("{:r}", in(vreg) foo); + //~^ ERROR invalid asm template modifier for this register class + asm!("{:r}", in(vreg_low16) foo); + //~^ ERROR invalid asm template modifier for this register class + asm!("{:a}", const 0); + //~^ ERROR asm template modifiers are not allowed for `const` arguments + asm!("{:a}", sym main); + //~^ ERROR asm template modifiers are not allowed for `sym` arguments + asm!("", in("x29") foo); + //~^ ERROR invalid register `x29`: the frame pointer cannot be used as an operand + asm!("", in("sp") foo); + //~^ ERROR invalid register `sp`: the stack pointer cannot be used as an operand + asm!("", in("xzr") foo); + //~^ ERROR invalid register `xzr`: the zero register cannot be used as an operand + asm!("", in("x18") foo); + //~^ ERROR invalid register `x18`: x18 is used as a reserved register on some targets and cannot be used as an operand for inline asm + asm!("", in("x19") foo); + //~^ ERROR invalid register `x19`: x19 is used internally by LLVM and cannot be used as an operand for inline asm + + asm!("", in("p0") foo); + //~^ ERROR register class `preg` can only be used as a clobber, not as an input or output + asm!("", out("p0") _); + asm!("{}", in(preg) foo); + //~^ ERROR register class `preg` can only be used as a clobber, not as an input or output + asm!("{}", out(preg) _); + //~^ ERROR register class `preg` can only be used as a clobber, not as an input or output + + // Explicit register conflicts + // (except in/lateout which don't conflict) + + asm!("", in("x0") foo, in("w0") bar); + //~^ ERROR register `x0` conflicts with register `x0` + asm!("", in("x0") foo, out("x0") bar); + //~^ ERROR register `x0` conflicts with register `x0` + asm!("", in("w0") foo, lateout("w0") bar); + asm!("", in("v0") foo, in("q0") bar); + //~^ ERROR register `v0` conflicts with register `v0` + asm!("", in("v0") foo, out("q0") bar); + //~^ ERROR register `v0` conflicts with register `v0` + asm!("", in("v0") foo, lateout("q0") bar); + } +} diff --git a/src/test/ui/asm/aarch64/bad-reg.stderr b/src/test/ui/asm/aarch64/bad-reg.stderr new file mode 100644 index 0000000000..091e6077ef --- /dev/null +++ b/src/test/ui/asm/aarch64/bad-reg.stderr @@ -0,0 +1,152 @@ +error: invalid register class `foo`: unknown register class + --> $DIR/bad-reg.rs:12:20 + | +LL | asm!("{}", in(foo) foo); + | ^^^^^^^^^^^ + +error: invalid register `foo`: unknown register + --> $DIR/bad-reg.rs:14:18 + | +LL | asm!("", in("foo") foo); + | ^^^^^^^^^^^^^ + +error: invalid asm template modifier for this register class + --> $DIR/bad-reg.rs:16:15 + | +LL | asm!("{:z}", in(reg) foo); + | ^^^^ ----------- argument + | | + | template modifier + | + = note: the `reg` register class supports the following template modifiers: `w`, `x` + +error: invalid asm template modifier for this register class + --> $DIR/bad-reg.rs:18:15 + | +LL | asm!("{:r}", in(vreg) foo); + | ^^^^ ------------ argument + | | + | template modifier + | + = note: the `vreg` register class supports the following template modifiers: `b`, `h`, `s`, `d`, `q`, `v` + +error: invalid asm template modifier for this register class + --> $DIR/bad-reg.rs:20:15 + | +LL | asm!("{:r}", in(vreg_low16) foo); + | ^^^^ ------------------ argument + | | + | template modifier + | + = note: the `vreg_low16` register class supports the following template modifiers: `b`, `h`, `s`, `d`, `q`, `v` + +error: asm template modifiers are not allowed for `const` arguments + --> $DIR/bad-reg.rs:22:15 + | +LL | asm!("{:a}", const 0); + | ^^^^ ------- argument + | | + | template modifier + +error: asm template modifiers are not allowed for `sym` arguments + --> $DIR/bad-reg.rs:24:15 + | +LL | asm!("{:a}", sym main); + | ^^^^ -------- argument + | | + | template modifier + +error: invalid register `x29`: the frame pointer cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:26:18 + | +LL | asm!("", in("x29") foo); + | ^^^^^^^^^^^^^ + +error: invalid register `sp`: the stack pointer cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:28:18 + | +LL | asm!("", in("sp") foo); + | ^^^^^^^^^^^^ + +error: invalid register `xzr`: the zero register cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:30:18 + | +LL | asm!("", in("xzr") foo); + | ^^^^^^^^^^^^^ + +error: invalid register `x18`: x18 is used as a reserved register on some targets and cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:32:18 + | +LL | asm!("", in("x18") foo); + | ^^^^^^^^^^^^^ + +error: invalid register `x19`: x19 is used internally by LLVM and cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:34:18 + | +LL | asm!("", in("x19") foo); + | ^^^^^^^^^^^^^ + +error: register class `preg` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:37:18 + | +LL | asm!("", in("p0") foo); + | ^^^^^^^^^^^^ + +error: register class `preg` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:40:20 + | +LL | asm!("{}", in(preg) foo); + | ^^^^^^^^^^^^ + +error: register class `preg` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:42:20 + | +LL | asm!("{}", out(preg) _); + | ^^^^^^^^^^^ + +error: register `x0` conflicts with register `x0` + --> $DIR/bad-reg.rs:48:32 + | +LL | asm!("", in("x0") foo, in("w0") bar); + | ------------ ^^^^^^^^^^^^ register `x0` + | | + | register `x0` + +error: register `x0` conflicts with register `x0` + --> $DIR/bad-reg.rs:50:32 + | +LL | asm!("", in("x0") foo, out("x0") bar); + | ------------ ^^^^^^^^^^^^^ register `x0` + | | + | register `x0` + | +help: use `lateout` instead of `out` to avoid conflict + --> $DIR/bad-reg.rs:50:18 + | +LL | asm!("", in("x0") foo, out("x0") bar); + | ^^^^^^^^^^^^ + +error: register `v0` conflicts with register `v0` + --> $DIR/bad-reg.rs:53:32 + | +LL | asm!("", in("v0") foo, in("q0") bar); + | ------------ ^^^^^^^^^^^^ register `v0` + | | + | register `v0` + +error: register `v0` conflicts with register `v0` + --> $DIR/bad-reg.rs:55:32 + | +LL | asm!("", in("v0") foo, out("q0") bar); + | ------------ ^^^^^^^^^^^^^ register `v0` + | | + | register `v0` + | +help: use `lateout` instead of `out` to avoid conflict + --> $DIR/bad-reg.rs:55:18 + | +LL | asm!("", in("v0") foo, out("q0") bar); + | ^^^^^^^^^^^^ + +error: aborting due to 19 previous errors + diff --git a/src/test/ui/asm/aarch64/const.rs b/src/test/ui/asm/aarch64/const.rs new file mode 100644 index 0000000000..906dcb0eba --- /dev/null +++ b/src/test/ui/asm/aarch64/const.rs @@ -0,0 +1,42 @@ +// min-llvm-version: 10.0.1 +// only-aarch64 +// run-pass +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + +#![feature(asm, global_asm)] + +fn const_generic() -> usize { + unsafe { + let a: usize; + asm!("mov {}, {}", out(reg) a, const X); + a + } +} + +const fn constfn(x: usize) -> usize { + x +} + +fn main() { + unsafe { + let a: usize; + asm!("mov {}, {}", out(reg) a, const 5); + assert_eq!(a, 5); + + let b: usize; + asm!("mov {}, {}", out(reg) b, const constfn(5)); + assert_eq!(b, 5); + + let c: usize; + asm!("mov {}, {}", out(reg) c, const constfn(5) + constfn(5)); + assert_eq!(c, 10); + } + + let d = const_generic::<5>(); + assert_eq!(d, 5); +} + +global_asm!("mov x0, {}", const 5); +global_asm!("mov x0, {}", const constfn(5)); +global_asm!("mov x0, {}", const constfn(5) + constfn(5)); diff --git a/src/test/ui/asm/aarch64/duplicate-options.fixed b/src/test/ui/asm/aarch64/duplicate-options.fixed new file mode 100644 index 0000000000..d95c646e9f --- /dev/null +++ b/src/test/ui/asm/aarch64/duplicate-options.fixed @@ -0,0 +1,26 @@ +// only-aarch64 +// run-rustfix + +#![feature(asm, global_asm)] + +fn main() { + unsafe { + asm!("", options(nomem, )); + //~^ ERROR the `nomem` option was already provided + asm!("", options(preserves_flags, )); + //~^ ERROR the `preserves_flags` option was already provided + asm!("", options(nostack, preserves_flags), options()); + //~^ ERROR the `nostack` option was already provided + asm!("", options(nostack, ), options(), options()); + //~^ ERROR the `nostack` option was already provided + //~| ERROR the `nostack` option was already provided + //~| ERROR the `nostack` option was already provided + asm!( + "", + options(nomem, noreturn), + options(preserves_flags, ), //~ ERROR the `noreturn` option was already provided + options( nostack), //~ ERROR the `nomem` option was already provided + options(), //~ ERROR the `noreturn` option was already provided + ); + } +} diff --git a/src/test/ui/asm/aarch64/duplicate-options.rs b/src/test/ui/asm/aarch64/duplicate-options.rs new file mode 100644 index 0000000000..eec356463d --- /dev/null +++ b/src/test/ui/asm/aarch64/duplicate-options.rs @@ -0,0 +1,26 @@ +// only-aarch64 +// run-rustfix + +#![feature(asm, global_asm)] + +fn main() { + unsafe { + asm!("", options(nomem, nomem)); + //~^ ERROR the `nomem` option was already provided + asm!("", options(preserves_flags, preserves_flags)); + //~^ ERROR the `preserves_flags` option was already provided + asm!("", options(nostack, preserves_flags), options(nostack)); + //~^ ERROR the `nostack` option was already provided + asm!("", options(nostack, nostack), options(nostack), options(nostack)); + //~^ ERROR the `nostack` option was already provided + //~| ERROR the `nostack` option was already provided + //~| ERROR the `nostack` option was already provided + asm!( + "", + options(nomem, noreturn), + options(preserves_flags, noreturn), //~ ERROR the `noreturn` option was already provided + options(nomem, nostack), //~ ERROR the `nomem` option was already provided + options(noreturn), //~ ERROR the `noreturn` option was already provided + ); + } +} diff --git a/src/test/ui/asm/aarch64/duplicate-options.stderr b/src/test/ui/asm/aarch64/duplicate-options.stderr new file mode 100644 index 0000000000..5063b0c123 --- /dev/null +++ b/src/test/ui/asm/aarch64/duplicate-options.stderr @@ -0,0 +1,56 @@ +error: the `nomem` option was already provided + --> $DIR/duplicate-options.rs:8:33 + | +LL | asm!("", options(nomem, nomem)); + | ^^^^^ this option was already provided + +error: the `preserves_flags` option was already provided + --> $DIR/duplicate-options.rs:10:43 + | +LL | asm!("", options(preserves_flags, preserves_flags)); + | ^^^^^^^^^^^^^^^ this option was already provided + +error: the `nostack` option was already provided + --> $DIR/duplicate-options.rs:12:61 + | +LL | asm!("", options(nostack, preserves_flags), options(nostack)); + | ^^^^^^^ this option was already provided + +error: the `nostack` option was already provided + --> $DIR/duplicate-options.rs:14:35 + | +LL | asm!("", options(nostack, nostack), options(nostack), options(nostack)); + | ^^^^^^^ this option was already provided + +error: the `nostack` option was already provided + --> $DIR/duplicate-options.rs:14:53 + | +LL | asm!("", options(nostack, nostack), options(nostack), options(nostack)); + | ^^^^^^^ this option was already provided + +error: the `nostack` option was already provided + --> $DIR/duplicate-options.rs:14:71 + | +LL | asm!("", options(nostack, nostack), options(nostack), options(nostack)); + | ^^^^^^^ this option was already provided + +error: the `noreturn` option was already provided + --> $DIR/duplicate-options.rs:21:38 + | +LL | options(preserves_flags, noreturn), + | ^^^^^^^^ this option was already provided + +error: the `nomem` option was already provided + --> $DIR/duplicate-options.rs:22:21 + | +LL | options(nomem, nostack), + | ^^^^^ this option was already provided + +error: the `noreturn` option was already provided + --> $DIR/duplicate-options.rs:23:21 + | +LL | options(noreturn), + | ^^^^^^^^ this option was already provided + +error: aborting due to 9 previous errors + diff --git a/src/test/ui/asm/aarch64/interpolated-idents.rs b/src/test/ui/asm/aarch64/interpolated-idents.rs new file mode 100644 index 0000000000..1cdf096566 --- /dev/null +++ b/src/test/ui/asm/aarch64/interpolated-idents.rs @@ -0,0 +1,24 @@ +// only-aarch64 + +#![feature(asm)] + +macro_rules! m { + ($in:ident $out:ident $lateout:ident $inout:ident $inlateout:ident $const:ident $sym:ident + $pure:ident $nomem:ident $readonly:ident $preserves_flags:ident + $noreturn:ident $nostack:ident $options:ident) => { + unsafe { + asm!("", $in(x) x, $out(x) x, $lateout(x) x, $inout(x) x, $inlateout(x) x, + //~^ ERROR asm outputs are not allowed with the `noreturn` option + const x, sym x, + $options($pure, $nomem, $readonly, $preserves_flags, $noreturn, $nostack)); + //~^ ERROR the `nomem` and `readonly` options are mutually exclusive + //~| ERROR the `pure` and `noreturn` options are mutually exclusive + } + }; +} + +fn main() { + m!(in out lateout inout inlateout const sym + pure nomem readonly preserves_flags + noreturn nostack options); +} diff --git a/src/test/ui/asm/aarch64/interpolated-idents.stderr b/src/test/ui/asm/aarch64/interpolated-idents.stderr new file mode 100644 index 0000000000..2df17f2e03 --- /dev/null +++ b/src/test/ui/asm/aarch64/interpolated-idents.stderr @@ -0,0 +1,51 @@ +error: the `nomem` and `readonly` options are mutually exclusive + --> $DIR/interpolated-idents.rs:13:13 + | +LL | $options($pure, $nomem, $readonly, $preserves_flags, $noreturn, $nostack)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | / m!(in out lateout inout inlateout const sym +LL | | pure nomem readonly preserves_flags +LL | | noreturn nostack options); + | |________________________________- in this macro invocation + | + = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: the `pure` and `noreturn` options are mutually exclusive + --> $DIR/interpolated-idents.rs:13:13 + | +LL | $options($pure, $nomem, $readonly, $preserves_flags, $noreturn, $nostack)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | / m!(in out lateout inout inlateout const sym +LL | | pure nomem readonly preserves_flags +LL | | noreturn nostack options); + | |________________________________- in this macro invocation + | + = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: asm outputs are not allowed with the `noreturn` option + --> $DIR/interpolated-idents.rs:10:32 + | +LL | asm!("", $in(x) x, $out(x) x, $lateout(x) x, $inout(x) x, $inlateout(x) x, + | ^^^^^^^^^ ^^^^^^^^^^^^^ ^^^^^^^^^^^ ^^^^^^^^^^^^^^^ +... +LL | m!(in out lateout inout inlateout const sym + | _____- + | |_____| + | |_____| + | |_____| + | | +LL | | pure nomem readonly preserves_flags +LL | | noreturn nostack options); + | | - + | |________________________________| + | |________________________________in this macro invocation + | |________________________________in this macro invocation + | |________________________________in this macro invocation + | in this macro invocation + | + = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 3 previous errors + diff --git a/src/test/ui/asm/aarch64/parse-error.rs b/src/test/ui/asm/aarch64/parse-error.rs new file mode 100644 index 0000000000..faa5e37b78 --- /dev/null +++ b/src/test/ui/asm/aarch64/parse-error.rs @@ -0,0 +1,135 @@ +// only-aarch64 + +#![feature(asm, global_asm)] + +fn main() { + let mut foo = 0; + let mut bar = 0; + unsafe { + asm!(); + //~^ ERROR requires at least a template string argument + asm!(foo); + //~^ ERROR asm template must be a string literal + asm!("{}" foo); + //~^ ERROR expected token: `,` + asm!("{}", foo); + //~^ ERROR expected operand, clobber_abi, options, or additional template string + asm!("{}", in foo); + //~^ ERROR expected `(`, found `foo` + asm!("{}", in(reg foo)); + //~^ ERROR expected `)`, found `foo` + asm!("{}", in(reg)); + //~^ ERROR expected expression, found end of macro arguments + asm!("{}", inout(=) foo => bar); + //~^ ERROR expected register class or explicit register + asm!("{}", inout(reg) foo =>); + //~^ ERROR expected expression, found end of macro arguments + asm!("{}", in(reg) foo => bar); + //~^ ERROR expected one of `!`, `,`, `.`, `::`, `?`, `{`, or an operator, found `=>` + asm!("{}", sym foo + bar); + //~^ ERROR argument to `sym` must be a path expression + asm!("", options(foo)); + //~^ ERROR expected one of + asm!("", options(nomem foo)); + //~^ ERROR expected one of + asm!("", options(nomem, foo)); + //~^ ERROR expected one of + asm!("{}", options(), const foo); + //~^ ERROR arguments are not allowed after options + //~^^ ERROR attempt to use a non-constant value in a constant + asm!("", clobber_abi(foo)); + //~^ ERROR expected string literal + asm!("", clobber_abi("C" foo)); + //~^ ERROR expected `)`, found `foo` + asm!("", clobber_abi("C", foo)); + //~^ ERROR expected `)`, found `,` + 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 + asm!("", options(), clobber_abi("C")); + //~^ 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 + //~^^^ ERROR attempt to use a non-constant value in a constant + //~^^^^ ERROR attempt to use a non-constant value in a constant + asm!("", a = in("x0") foo); + //~^ ERROR explicit register arguments cannot have names + asm!("{a}", in("x0") foo, a = const bar); + //~^ ERROR named arguments cannot follow explicit register arguments + //~^^ ERROR attempt to use a non-constant value in a constant + asm!("{a}", in("x0") foo, a = const bar); + //~^ ERROR named arguments cannot follow explicit register arguments + //~^^ ERROR attempt to use a non-constant value in a constant + asm!("{1}", in("x0") foo, const bar); + //~^ ERROR positional arguments cannot follow named arguments or explicit register arguments + //~^^ ERROR attempt to use a non-constant value in a constant + asm!("", options(), ""); + //~^ ERROR expected one of + asm!("{}", in(reg) foo, "{}", out(reg) foo); + //~^ ERROR expected one of + asm!(format!("{{{}}}", 0), in(reg) foo); + //~^ ERROR asm template must be a string literal + asm!("{1}", format!("{{{}}}", 0), in(reg) foo, out(reg) bar); + //~^ ERROR asm template must be a string literal + asm!("{}", in(reg) _); + //~^ ERROR _ cannot be used for input operands + asm!("{}", inout(reg) _); + //~^ ERROR _ cannot be used for input operands + asm!("{}", inlateout(reg) _); + //~^ ERROR _ cannot be used for input operands + } +} + +const FOO: i32 = 1; +const BAR: i32 = 2; +global_asm!(); +//~^ ERROR requires at least a template string argument +global_asm!(FOO); +//~^ ERROR asm template must be a string literal +global_asm!("{}" FOO); +//~^ ERROR expected token: `,` +global_asm!("{}", FOO); +//~^ ERROR expected operand, options, or additional template string +global_asm!("{}", const); +//~^ ERROR expected expression, found end of macro arguments +global_asm!("{}", const(reg) FOO); +//~^ ERROR expected one of +global_asm!("", options(FOO)); +//~^ ERROR expected one of +global_asm!("", options(nomem FOO)); +//~^ ERROR expected one of +global_asm!("", options(nomem, FOO)); +//~^ ERROR expected one of +global_asm!("{}", options(), const FOO); +//~^ ERROR arguments are not allowed after options +global_asm!("", clobber_abi(FOO)); +//~^ ERROR expected string literal +global_asm!("", clobber_abi("C" FOO)); +//~^ ERROR expected `)`, found `FOO` +global_asm!("", clobber_abi("C", FOO)); +//~^ ERROR expected `)`, found `,` +global_asm!("{}", clobber_abi("C"), const FOO); +//~^ ERROR arguments are not allowed after clobber_abi +//~^^ ERROR `clobber_abi` cannot be used with `global_asm!` +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 +global_asm!("", options(), ""); +//~^ ERROR expected one of +global_asm!("{}", const FOO, "{}", const FOO); +//~^ ERROR expected one of +global_asm!(format!("{{{}}}", 0), const FOO); +//~^ ERROR asm template must be a string literal +global_asm!("{1}", format!("{{{}}}", 0), const FOO, const BAR); +//~^ ERROR asm template must be a string literal diff --git a/src/test/ui/asm/aarch64/parse-error.stderr b/src/test/ui/asm/aarch64/parse-error.stderr new file mode 100644 index 0000000000..6f318c9b9c --- /dev/null +++ b/src/test/ui/asm/aarch64/parse-error.stderr @@ -0,0 +1,462 @@ +error: requires at least a template string argument + --> $DIR/parse-error.rs:9:9 + | +LL | asm!(); + | ^^^^^^ + +error: asm template must be a string literal + --> $DIR/parse-error.rs:11:14 + | +LL | asm!(foo); + | ^^^ + +error: expected token: `,` + --> $DIR/parse-error.rs:13:19 + | +LL | asm!("{}" foo); + | ^^^ expected `,` + +error: expected operand, clobber_abi, options, or additional template string + --> $DIR/parse-error.rs:15:20 + | +LL | asm!("{}", foo); + | ^^^ expected operand, clobber_abi, options, or additional template string + +error: expected `(`, found `foo` + --> $DIR/parse-error.rs:17:23 + | +LL | asm!("{}", in foo); + | ^^^ expected `(` + +error: expected `)`, found `foo` + --> $DIR/parse-error.rs:19:27 + | +LL | asm!("{}", in(reg foo)); + | ^^^ expected `)` + +error: expected expression, found end of macro arguments + --> $DIR/parse-error.rs:21:27 + | +LL | asm!("{}", in(reg)); + | ^ expected expression + +error: expected register class or explicit register + --> $DIR/parse-error.rs:23:26 + | +LL | asm!("{}", inout(=) foo => bar); + | ^ + +error: expected expression, found end of macro arguments + --> $DIR/parse-error.rs:25:37 + | +LL | asm!("{}", inout(reg) foo =>); + | ^ expected expression + +error: expected one of `!`, `,`, `.`, `::`, `?`, `{`, or an operator, found `=>` + --> $DIR/parse-error.rs:27:32 + | +LL | asm!("{}", in(reg) foo => bar); + | ^^ expected one of 7 possible tokens + +error: argument to `sym` must be a path expression + --> $DIR/parse-error.rs:29:24 + | +LL | asm!("{}", sym foo + bar); + | ^^^^^^^^^ + +error: expected one of `)`, `att_syntax`, `nomem`, `noreturn`, `nostack`, `preserves_flags`, `pure`, `raw`, or `readonly`, found `foo` + --> $DIR/parse-error.rs:31:26 + | +LL | asm!("", options(foo)); + | ^^^ expected one of 9 possible tokens + +error: expected one of `)` or `,`, found `foo` + --> $DIR/parse-error.rs:33:32 + | +LL | asm!("", options(nomem foo)); + | ^^^ expected one of `)` or `,` + +error: expected one of `)`, `att_syntax`, `nomem`, `noreturn`, `nostack`, `preserves_flags`, `pure`, `raw`, or `readonly`, found `foo` + --> $DIR/parse-error.rs:35:33 + | +LL | asm!("", options(nomem, foo)); + | ^^^ expected one of 9 possible tokens + +error: arguments are not allowed after options + --> $DIR/parse-error.rs:37:31 + | +LL | asm!("{}", options(), const foo); + | --------- ^^^^^^^^^ argument + | | + | previous options + +error: expected string literal + --> $DIR/parse-error.rs:40:30 + | +LL | asm!("", clobber_abi(foo)); + | ^^^ not a string literal + +error: expected `)`, found `foo` + --> $DIR/parse-error.rs:42:34 + | +LL | asm!("", clobber_abi("C" foo)); + | ^^^ expected `)` + +error: expected `)`, found `,` + --> $DIR/parse-error.rs:44:33 + | +LL | asm!("", clobber_abi("C", foo)); + | ^ expected `)` + +error: arguments are not allowed after clobber_abi + --> $DIR/parse-error.rs:46:38 + | +LL | asm!("{}", clobber_abi("C"), const foo); + | ---------------- ^^^^^^^^^ argument + | | + | clobber_abi + +error: clobber_abi is not allowed after options + --> $DIR/parse-error.rs:49:29 + | +LL | asm!("", options(), clobber_abi("C")); + | --------- ^^^^^^^^^^^^^^^^ + | | + | options + +error: clobber_abi is not allowed after options + --> $DIR/parse-error.rs:51: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 + | +LL | asm!("{a}", a = const foo, a = const bar); + | ------------- ^^^^^^^^^^^^^ duplicate argument + | | + | previously here + +error: argument never used + --> $DIR/parse-error.rs:55:36 + | +LL | asm!("{a}", a = const foo, a = const bar); + | ^^^^^^^^^^^^^ argument never used + | + = 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 + | +LL | asm!("", a = in("x0") foo); + | ^^^^^^^^^^^^^^^^ + +error: named arguments cannot follow explicit register arguments + --> $DIR/parse-error.rs:62:35 + | +LL | asm!("{a}", in("x0") foo, a = const bar); + | ------------ ^^^^^^^^^^^^^ named argument + | | + | explicit register argument + +error: named arguments cannot follow explicit register arguments + --> $DIR/parse-error.rs:65:35 + | +LL | asm!("{a}", in("x0") foo, a = const bar); + | ------------ ^^^^^^^^^^^^^ named argument + | | + | explicit register argument + +error: positional arguments cannot follow named arguments or explicit register arguments + --> $DIR/parse-error.rs:68:35 + | +LL | asm!("{1}", in("x0") foo, const bar); + | ------------ ^^^^^^^^^ positional argument + | | + | 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 + | +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 + | +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 + | +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 + | +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 + | +LL | asm!("{}", in(reg) _); + | ^ + +error: _ cannot be used for input operands + --> $DIR/parse-error.rs:81:31 + | +LL | asm!("{}", inout(reg) _); + | ^ + +error: _ cannot be used for input operands + --> $DIR/parse-error.rs:83:35 + | +LL | asm!("{}", inlateout(reg) _); + | ^ + +error: requires at least a template string argument + --> $DIR/parse-error.rs:90:1 + | +LL | global_asm!(); + | ^^^^^^^^^^^^^ + +error: asm template must be a string literal + --> $DIR/parse-error.rs:92:13 + | +LL | global_asm!(FOO); + | ^^^ + +error: expected token: `,` + --> $DIR/parse-error.rs:94:18 + | +LL | global_asm!("{}" FOO); + | ^^^ expected `,` + +error: expected operand, options, or additional template string + --> $DIR/parse-error.rs:96: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 + | +LL | global_asm!("{}", const); + | ^ expected expression + +error: expected one of `,`, `.`, `?`, or an operator, found `FOO` + --> $DIR/parse-error.rs:100: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 + | +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 + | +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 + | +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 + | +LL | global_asm!("{}", options(), const FOO); + | --------- ^^^^^^^^^ argument + | | + | previous options + +error: expected string literal + --> $DIR/parse-error.rs:110:29 + | +LL | global_asm!("", clobber_abi(FOO)); + | ^^^ not a string literal + +error: expected `)`, found `FOO` + --> $DIR/parse-error.rs:112:33 + | +LL | global_asm!("", clobber_abi("C" FOO)); + | ^^^ expected `)` + +error: expected `)`, found `,` + --> $DIR/parse-error.rs:114:32 + | +LL | global_asm!("", clobber_abi("C", FOO)); + | ^ expected `)` + +error: arguments are not allowed after clobber_abi + --> $DIR/parse-error.rs:116:37 + | +LL | global_asm!("{}", clobber_abi("C"), const FOO); + | ---------------- ^^^^^^^^^ argument + | | + | clobber_abi + +error: `clobber_abi` cannot be used with `global_asm!` + --> $DIR/parse-error.rs:116:19 + | +LL | global_asm!("{}", clobber_abi("C"), const FOO); + | ^^^^^^^^^^^^^^^^ + +error: clobber_abi is not allowed after options + --> $DIR/parse-error.rs:119:28 + | +LL | global_asm!("", options(), clobber_abi("C")); + | --------- ^^^^^^^^^^^^^^^^ + | | + | options + +error: clobber_abi is not allowed after options + --> $DIR/parse-error.rs:121: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 + | +LL | global_asm!("{a}", a = const FOO, a = const BAR); + | ------------- ^^^^^^^^^^^^^ duplicate argument + | | + | previously here + +error: argument never used + --> $DIR/parse-error.rs:125:35 + | +LL | global_asm!("{a}", a = const FOO, a = const BAR); + | ^^^^^^^^^^^^^ argument never used + | + = 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 + | +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 + | +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 + | +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 + | +LL | global_asm!("{1}", format!("{{{}}}", 0), const FOO, const BAR); + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0435]: attempt to use a non-constant value in a constant + --> $DIR/parse-error.rs:37:37 + | +LL | let mut foo = 0; + | ---------- help: consider using `const` instead of `let`: `const foo` +... +LL | asm!("{}", options(), const foo); + | ^^^ non-constant value + +error[E0435]: attempt to use a non-constant value in a constant + --> $DIR/parse-error.rs:46:44 + | +LL | let mut foo = 0; + | ---------- help: consider using `const` instead of `let`: `const foo` +... +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 + | +LL | let mut foo = 0; + | ---------- help: consider using `const` instead of `let`: `const foo` +... +LL | asm!("{a}", a = const foo, a = const bar); + | ^^^ non-constant value + +error[E0435]: attempt to use a non-constant value in a constant + --> $DIR/parse-error.rs:55:46 + | +LL | let mut bar = 0; + | ---------- help: consider using `const` instead of `let`: `const bar` +... +LL | asm!("{a}", a = const foo, a = const bar); + | ^^^ non-constant value + +error[E0435]: attempt to use a non-constant value in a constant + --> $DIR/parse-error.rs:62:45 + | +LL | let mut bar = 0; + | ---------- help: consider using `const` instead of `let`: `const bar` +... +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 + | +LL | let mut bar = 0; + | ---------- help: consider using `const` instead of `let`: `const bar` +... +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 + | +LL | let mut bar = 0; + | ---------- help: consider using `const` instead of `let`: `const bar` +... +LL | asm!("{1}", in("x0") foo, const bar); + | ^^^ non-constant value + +error: aborting due to 66 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 new file mode 100644 index 0000000000..58feb52653 --- /dev/null +++ b/src/test/ui/asm/aarch64/srcloc.rs @@ -0,0 +1,121 @@ +// min-llvm-version: 10.0.1 +// only-aarch64 +// build-fail +// compile-flags: -Ccodegen-units=1 +#![feature(asm)] + +// Checks that inline asm errors are mapped to the correct line in the source code. + +fn main() { + unsafe { + asm!("invalid_instruction"); + //~^ ERROR: unrecognized instruction mnemonic + + asm!(" + invalid_instruction + "); + //~^^ ERROR: unrecognized instruction mnemonic + + asm!(r#" + invalid_instruction + "#); + //~^^ ERROR: unrecognized instruction mnemonic + + asm!(" + mov x0, x0 + invalid_instruction + mov x0, x0 + "); + //~^^^ ERROR: unrecognized instruction mnemonic + + asm!(r#" + mov x0, x0 + invalid_instruction + mov x0, x0 + "#); + //~^^^ ERROR: unrecognized instruction mnemonic + + asm!(concat!("invalid", "_", "instruction")); + //~^ ERROR: unrecognized instruction mnemonic + + asm!( + "invalid_instruction", + ); + //~^^ ERROR: unrecognized instruction mnemonic + + asm!( + "mov x0, x0", + "invalid_instruction", + "mov x0, x0", + ); + //~^^^ ERROR: unrecognized instruction mnemonic + + asm!( + "mov x0, x0\n", + "invalid_instruction", + "mov x0, x0", + ); + //~^^^ ERROR: unrecognized instruction mnemonic + + asm!( + "mov x0, x0", + concat!("invalid", "_", "instruction"), + "mov x0, x0", + ); + //~^^^ ERROR: unrecognized instruction mnemonic + + asm!( + concat!("mov x0", ", ", "x0"), + concat!("invalid", "_", "instruction"), + concat!("mov x0", ", ", "x0"), + ); + //~^^^ ERROR: unrecognized instruction mnemonic + + // Make sure template strings get separated + asm!( + "invalid_instruction1", + "invalid_instruction2", + ); + //~^^^ ERROR: unrecognized instruction mnemonic + //~^^^ ERROR: unrecognized instruction mnemonic + + asm!( + concat!( + "invalid", "_", "instruction1", "\n", + "invalid", "_", "instruction2", + ), + ); + //~^^^^^ ERROR: unrecognized instruction mnemonic + //~^^^^^^ ERROR: unrecognized instruction mnemonic + + asm!( + concat!( + "invalid", "_", "instruction1", "\n", + "invalid", "_", "instruction2", + ), + concat!( + "invalid", "_", "instruction3", "\n", + "invalid", "_", "instruction4", + ), + ); + //~^^^^^^^^^ ERROR: unrecognized instruction mnemonic + //~^^^^^^^^^^ ERROR: unrecognized instruction mnemonic + //~^^^^^^^ ERROR: unrecognized instruction mnemonic + //~^^^^^^^^ ERROR: unrecognized instruction mnemonic + + asm!( + concat!( + "invalid", "_", "instruction1", "\n", + "invalid", "_", "instruction2", "\n", + ), + concat!( + "invalid", "_", "instruction3", "\n", + "invalid", "_", "instruction4", "\n", + ), + ); + //~^^^^^^^^^ ERROR: unrecognized instruction mnemonic + //~^^^^^^^^^^ ERROR: unrecognized instruction mnemonic + //~^^^^^^^ ERROR: unrecognized instruction mnemonic + //~^^^^^^^^ ERROR: unrecognized instruction mnemonic + } +} diff --git a/src/test/ui/asm/aarch64/srcloc.stderr b/src/test/ui/asm/aarch64/srcloc.stderr new file mode 100644 index 0000000000..96dab1bce0 --- /dev/null +++ b/src/test/ui/asm/aarch64/srcloc.stderr @@ -0,0 +1,278 @@ +error: unrecognized instruction mnemonic + --> $DIR/srcloc.rs:11:15 + | +LL | asm!("invalid_instruction"); + | ^ + | +note: instantiated into assembly here + --> :1:2 + | +LL | invalid_instruction + | ^ + +error: unrecognized instruction mnemonic + --> $DIR/srcloc.rs:15:13 + | +LL | invalid_instruction + | ^ + | +note: instantiated into assembly here + --> :2:13 + | +LL | invalid_instruction + | ^ + +error: unrecognized instruction mnemonic + --> $DIR/srcloc.rs:20:13 + | +LL | invalid_instruction + | ^ + | +note: instantiated into assembly here + --> :2:13 + | +LL | invalid_instruction + | ^ + +error: unrecognized instruction mnemonic + --> $DIR/srcloc.rs:26:13 + | +LL | invalid_instruction + | ^ + | +note: instantiated into assembly here + --> :3:13 + | +LL | invalid_instruction + | ^ + +error: unrecognized instruction mnemonic + --> $DIR/srcloc.rs:33:13 + | +LL | invalid_instruction + | ^ + | +note: instantiated into assembly here + --> :3:13 + | +LL | invalid_instruction + | ^ + +error: unrecognized instruction mnemonic + --> $DIR/srcloc.rs:38:14 + | +LL | asm!(concat!("invalid", "_", "instruction")); + | ^ + | +note: instantiated into assembly here + --> :1:2 + | +LL | invalid_instruction + | ^ + +error: unrecognized instruction mnemonic + --> $DIR/srcloc.rs:42:14 + | +LL | "invalid_instruction", + | ^ + | +note: instantiated into assembly here + --> :1:2 + | +LL | invalid_instruction + | ^ + +error: unrecognized instruction mnemonic + --> $DIR/srcloc.rs:48:14 + | +LL | "invalid_instruction", + | ^ + | +note: instantiated into assembly here + --> :2:1 + | +LL | invalid_instruction + | ^ + +error: unrecognized instruction mnemonic + --> $DIR/srcloc.rs:55:14 + | +LL | "invalid_instruction", + | ^ + | +note: instantiated into assembly here + --> :3:1 + | +LL | invalid_instruction + | ^ + +error: unrecognized instruction mnemonic + --> $DIR/srcloc.rs:62:13 + | +LL | concat!("invalid", "_", "instruction"), + | ^ + | +note: instantiated into assembly here + --> :2:1 + | +LL | invalid_instruction + | ^ + +error: unrecognized instruction mnemonic + --> $DIR/srcloc.rs:69:13 + | +LL | concat!("invalid", "_", "instruction"), + | ^ + | +note: instantiated into assembly here + --> :2:1 + | +LL | invalid_instruction + | ^ + +error: unrecognized instruction mnemonic + --> $DIR/srcloc.rs:76:14 + | +LL | "invalid_instruction1", + | ^ + | +note: instantiated into assembly here + --> :1:2 + | +LL | invalid_instruction1 + | ^ + +error: unrecognized instruction mnemonic + --> $DIR/srcloc.rs:77:14 + | +LL | "invalid_instruction2", + | ^ + | +note: instantiated into assembly here + --> :2:1 + | +LL | invalid_instruction2 + | ^ + +error: unrecognized instruction mnemonic + --> $DIR/srcloc.rs:83:13 + | +LL | concat!( + | ^ + | +note: instantiated into assembly here + --> :1:2 + | +LL | invalid_instruction1 + | ^ + +error: unrecognized instruction mnemonic + --> $DIR/srcloc.rs:83:13 + | +LL | concat!( + | ^ + | +note: instantiated into assembly here + --> :2:1 + | +LL | invalid_instruction2 + | ^ + +error: unrecognized instruction mnemonic + --> $DIR/srcloc.rs:92:13 + | +LL | concat!( + | ^ + | +note: instantiated into assembly here + --> :1:2 + | +LL | invalid_instruction1 + | ^ + +error: unrecognized instruction mnemonic + --> $DIR/srcloc.rs:92:13 + | +LL | concat!( + | ^ + | +note: instantiated into assembly here + --> :2:1 + | +LL | invalid_instruction2 + | ^ + +error: unrecognized instruction mnemonic + --> $DIR/srcloc.rs:96:13 + | +LL | concat!( + | ^ + | +note: instantiated into assembly here + --> :3:1 + | +LL | invalid_instruction3 + | ^ + +error: unrecognized instruction mnemonic + --> $DIR/srcloc.rs:96:13 + | +LL | concat!( + | ^ + | +note: instantiated into assembly here + --> :4:1 + | +LL | invalid_instruction4 + | ^ + +error: unrecognized instruction mnemonic + --> $DIR/srcloc.rs:107:13 + | +LL | concat!( + | ^ + | +note: instantiated into assembly here + --> :1:2 + | +LL | invalid_instruction1 + | ^ + +error: unrecognized instruction mnemonic + --> $DIR/srcloc.rs:107:13 + | +LL | concat!( + | ^ + | +note: instantiated into assembly here + --> :2:1 + | +LL | invalid_instruction2 + | ^ + +error: unrecognized instruction mnemonic + --> $DIR/srcloc.rs:111:13 + | +LL | concat!( + | ^ + | +note: instantiated into assembly here + --> :4:1 + | +LL | invalid_instruction3 + | ^ + +error: unrecognized instruction mnemonic + --> $DIR/srcloc.rs:111:13 + | +LL | concat!( + | ^ + | +note: instantiated into assembly here + --> :5:1 + | +LL | invalid_instruction4 + | ^ + +error: aborting due to 23 previous errors + diff --git a/src/test/ui/asm/aarch64/sym.rs b/src/test/ui/asm/aarch64/sym.rs new file mode 100644 index 0000000000..6fd1192eec --- /dev/null +++ b/src/test/ui/asm/aarch64/sym.rs @@ -0,0 +1,80 @@ +// min-llvm-version: 10.0.1 +// only-aarch64 +// only-linux +// run-pass + +#![feature(asm, thread_local)] + +extern "C" fn f1() -> i32 { + 111 +} + +// The compiler will generate a shim to hide the caller location parameter. +#[track_caller] +fn f2() -> i32 { + 222 +} + +macro_rules! call { + ($func:path) => { + unsafe { + let result: i32; + asm!("bl {}", sym $func, + out("w0") result, + out("x20") _, out("x21") _, out("x22") _, + out("x23") _, out("x24") _, out("x25") _, + out("x26") _, out("x27") _, out("x28") _, + ); + result + } + } +} + +macro_rules! static_addr { + ($s:expr) => { + unsafe { + let result: *const u32; + asm!( + // ADRP gives the address of a 4KB page from a PC-relative address + "adrp {out}, {sym}", + // We then add the remaining lower 12 bits + "add {out}, {out}, #:lo12:{sym}", + out = out(reg) result, + sym = sym $s); + result + } + } +} +macro_rules! static_tls_addr { + ($s:expr) => { + unsafe { + let result: *const u32; + asm!( + // Load the thread pointer register + "mrs {out}, TPIDR_EL0", + // Add the top 12 bits of the symbol's offset + "add {out}, {out}, :tprel_hi12:{sym}", + // And the bottom 12 bits + "add {out}, {out}, :tprel_lo12_nc:{sym}", + out = out(reg) result, + sym = sym $s + ); + result + } + } +} + +static S1: u32 = 111; +#[thread_local] +static S2: u32 = 222; + +fn main() { + assert_eq!(call!(f1), 111); + assert_eq!(call!(f2), 222); + assert_eq!(static_addr!(S1), &S1 as *const u32); + assert_eq!(static_tls_addr!(S2), &S2 as *const u32); + std::thread::spawn(|| { + assert_eq!(static_addr!(S1), &S1 as *const u32); + assert_eq!(static_tls_addr!(S2), &S2 as *const u32); + }).join().unwrap(); +} diff --git a/src/test/ui/asm/aarch64/type-check-2.rs b/src/test/ui/asm/aarch64/type-check-2.rs new file mode 100644 index 0000000000..cf25dcb930 --- /dev/null +++ b/src/test/ui/asm/aarch64/type-check-2.rs @@ -0,0 +1,84 @@ +// only-aarch64 + +#![feature(asm, repr_simd, never_type)] + +#[repr(simd)] +#[derive(Clone, Copy)] +struct SimdType(f32, f32, f32, f32); + +#[repr(simd)] +struct SimdNonCopy(f32, f32, f32, f32); + +fn main() { + unsafe { + // Inputs must be initialized + + let x: u64; + asm!("{}", in(reg) x); + //~^ ERROR use of possibly-uninitialized variable: `x` + let mut y: u64; + asm!("{}", inout(reg) y); + //~^ ERROR use of possibly-uninitialized variable: `y` + let _ = y; + + // Outputs require mutable places + + let v: Vec = vec![0, 1, 2]; + asm!("{}", in(reg) v[0]); + asm!("{}", out(reg) v[0]); + //~^ ERROR cannot borrow `v` as mutable, as it is not declared as mutable + asm!("{}", inout(reg) v[0]); + //~^ ERROR cannot borrow `v` as mutable, as it is not declared as mutable + + // Sym operands must point to a function or static + + const C: i32 = 0; + static S: i32 = 0; + asm!("{}", sym S); + asm!("{}", sym main); + asm!("{}", sym C); + //~^ ERROR asm `sym` operand must point to a fn or static + asm!("{}", sym x); + //~^ ERROR asm `sym` operand must point to a fn or static + + // Register operands must be Copy + + asm!("{:v}", in(vreg) SimdNonCopy(0.0, 0.0, 0.0, 0.0)); + //~^ ERROR arguments for inline assembly must be copyable + + // Register operands must be integers, floats, SIMD vectors, pointers or + // function pointers. + + asm!("{}", in(reg) 0i64); + asm!("{}", in(reg) 0f64); + asm!("{:v}", in(vreg) SimdType(0.0, 0.0, 0.0, 0.0)); + asm!("{}", in(reg) 0 as *const u8); + asm!("{}", in(reg) 0 as *mut u8); + asm!("{}", in(reg) main as fn()); + asm!("{}", in(reg) |x: i32| x); + //~^ ERROR cannot use value of type + asm!("{}", in(reg) vec![0]); + //~^ ERROR cannot use value of type `Vec` for inline assembly + asm!("{}", in(reg) (1, 2, 3)); + //~^ ERROR cannot use value of type `(i32, i32, i32)` for inline assembly + asm!("{}", in(reg) [1, 2, 3]); + //~^ ERROR cannot use value of type `[i32; 3]` for inline assembly + + // Register inputs (but not outputs) allow references and function types + + let mut f = main; + let mut r = &mut 0; + asm!("{}", in(reg) f); + asm!("{}", inout(reg) f); + //~^ ERROR cannot use value of type `fn() {main}` for inline assembly + asm!("{}", in(reg) r); + asm!("{}", inout(reg) r); + //~^ ERROR cannot use value of type `&mut i32` for inline assembly + let _ = (f, r); + + // Type checks ignore never type + + let u: ! = unreachable!(); + asm!("{}", in(reg) u); + } +} diff --git a/src/test/ui/asm/aarch64/type-check-2.stderr b/src/test/ui/asm/aarch64/type-check-2.stderr new file mode 100644 index 0000000000..cea26d73ab --- /dev/null +++ b/src/test/ui/asm/aarch64/type-check-2.stderr @@ -0,0 +1,103 @@ +error: arguments for inline assembly must be copyable + --> $DIR/type-check-2.rs:46:31 + | +LL | asm!("{:v}", in(vreg) SimdNonCopy(0.0, 0.0, 0.0, 0.0)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `SimdNonCopy` does not implement the Copy trait + +error: cannot use value of type `[closure@$DIR/type-check-2.rs:58:28: 58:38]` for inline assembly + --> $DIR/type-check-2.rs:58:28 + | +LL | asm!("{}", in(reg) |x: i32| x); + | ^^^^^^^^^^ + | + = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly + +error: cannot use value of type `Vec` for inline assembly + --> $DIR/type-check-2.rs:60:28 + | +LL | asm!("{}", in(reg) vec![0]); + | ^^^^^^^ + | + = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly + = note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: cannot use value of type `(i32, i32, i32)` for inline assembly + --> $DIR/type-check-2.rs:62:28 + | +LL | asm!("{}", in(reg) (1, 2, 3)); + | ^^^^^^^^^ + | + = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly + +error: cannot use value of type `[i32; 3]` for inline assembly + --> $DIR/type-check-2.rs:64:28 + | +LL | asm!("{}", in(reg) [1, 2, 3]); + | ^^^^^^^^^ + | + = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly + +error: cannot use value of type `fn() {main}` for inline assembly + --> $DIR/type-check-2.rs:72:31 + | +LL | asm!("{}", inout(reg) f); + | ^ + | + = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly + +error: cannot use value of type `&mut i32` for inline assembly + --> $DIR/type-check-2.rs:75:31 + | +LL | asm!("{}", inout(reg) r); + | ^ + | + = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly + +error: asm `sym` operand must point to a fn or static + --> $DIR/type-check-2.rs:39:24 + | +LL | asm!("{}", sym C); + | ^ + +error: asm `sym` operand must point to a fn or static + --> $DIR/type-check-2.rs:41:24 + | +LL | asm!("{}", sym x); + | ^ + +error[E0381]: use of possibly-uninitialized variable: `x` + --> $DIR/type-check-2.rs:17:28 + | +LL | asm!("{}", in(reg) x); + | ^ use of possibly-uninitialized `x` + +error[E0381]: use of possibly-uninitialized variable: `y` + --> $DIR/type-check-2.rs:20:9 + | +LL | asm!("{}", inout(reg) y); + | ^^^^^^^^^^^^^^^^^^^^^^^^ use of possibly-uninitialized `y` + +error[E0596]: cannot borrow `v` as mutable, as it is not declared as mutable + --> $DIR/type-check-2.rs:28:29 + | +LL | let v: Vec = vec![0, 1, 2]; + | - help: consider changing this to be mutable: `mut v` +LL | asm!("{}", in(reg) v[0]); +LL | asm!("{}", out(reg) v[0]); + | ^ cannot borrow as mutable + +error[E0596]: cannot borrow `v` as mutable, as it is not declared as mutable + --> $DIR/type-check-2.rs:30:31 + | +LL | let v: Vec = vec![0, 1, 2]; + | - help: consider changing this to be mutable: `mut v` +... +LL | asm!("{}", inout(reg) v[0]); + | ^ cannot borrow as mutable + +error: aborting due to 13 previous errors + +Some errors have detailed explanations: E0381, E0596. +For more information about an error, try `rustc --explain E0381`. diff --git a/src/test/ui/asm/aarch64/type-check-3.rs b/src/test/ui/asm/aarch64/type-check-3.rs new file mode 100644 index 0000000000..d0d5954ca4 --- /dev/null +++ b/src/test/ui/asm/aarch64/type-check-3.rs @@ -0,0 +1,115 @@ +// only-aarch64 +// compile-flags: -C target-feature=+neon + +#![feature(asm, global_asm, repr_simd, stdsimd)] + +use std::arch::aarch64::float64x2_t; + +#[repr(simd)] +#[derive(Copy, Clone)] +struct Simd256bit(f64, f64,f64, f64); + +fn main() { + let f64x2: float64x2_t = unsafe { std::mem::transmute(0i128) }; + let f64x4 = Simd256bit(0.0, 0.0, 0.0, 0.0); + + unsafe { + // Types must be listed in the register class. + + // Success cases + asm!("{:w}", in(reg) 0u8); + asm!("{:w}", in(reg) 0u16); + asm!("{:w}", in(reg) 0u32); + asm!("{:w}", in(reg) 0f32); + asm!("{}", in(reg) 0i64); + asm!("{}", in(reg) 0f64); + + asm!("{:b}", in(vreg) 0u8); + asm!("{:h}", in(vreg) 0u16); + asm!("{:s}", in(vreg) 0u32); + asm!("{:s}", in(vreg) 0f32); + asm!("{:d}", in(vreg) 0u64); + asm!("{:d}", in(vreg) 0f64); + asm!("{:q}", in(vreg) f64x2); + asm!("{:v}", in(vreg) f64x2); + + // Should be the same as vreg + asm!("{:q}", in(vreg_low16) f64x2); + + // Template modifiers of a different size to the argument are fine + asm!("{:w}", in(reg) 0u64); + asm!("{:x}", in(reg) 0u32); + asm!("{:b}", in(vreg) 0u64); + asm!("{:d}", in(vreg_low16) f64x2); + + + // Template modifier suggestions for sub-registers + + asm!("{}", in(reg) 0u8); + //~^ WARN formatting may not be suitable for sub-register argument + asm!("{}", in(reg) 0u16); + //~^ WARN formatting may not be suitable for sub-register argument + asm!("{}", in(reg) 0i32); + //~^ WARN formatting may not be suitable for sub-register argument + asm!("{}", in(reg) 0f32); + //~^ WARN formatting may not be suitable for sub-register argument + + asm!("{}", in(vreg) 0i16); + //~^ WARN formatting may not be suitable for sub-register argument + asm!("{}", in(vreg) 0f32); + //~^ WARN formatting may not be suitable for sub-register argument + asm!("{}", in(vreg) 0f64); + //~^ WARN formatting may not be suitable for sub-register argument + asm!("{}", in(vreg_low16) 0f64); + //~^ WARN formatting may not be suitable for sub-register argument + + asm!("{0} {0}", in(reg) 0i16); + //~^ WARN formatting may not be suitable for sub-register argument + asm!("{0} {0:x}", in(reg) 0i16); + //~^ WARN formatting may not be suitable for sub-register argument + + // Invalid registers + + asm!("{}", in(reg) 0i128); + //~^ ERROR type `i128` cannot be used with this register class + asm!("{}", in(reg) f64x2); + //~^ ERROR type `float64x2_t` cannot be used with this register class + asm!("{}", in(vreg) f64x4); + //~^ ERROR type `Simd256bit` cannot be used with this register class + + // Split inout operands must have compatible types + + let mut val_i16: i16; + let mut val_f32: f32; + let mut val_u32: u32; + let mut val_u64: u64; + let mut val_ptr: *mut u8; + asm!("{:x}", inout(reg) 0u16 => val_i16); + asm!("{:x}", inout(reg) 0u32 => val_f32); + //~^ ERROR incompatible types for asm inout argument + asm!("{:x}", inout(reg) 0u32 => val_ptr); + //~^ ERROR incompatible types for asm inout argument + asm!("{:x}", inout(reg) main => val_u32); + //~^ ERROR incompatible types for asm inout argument + asm!("{:x}", inout(reg) 0u64 => val_ptr); + asm!("{:x}", inout(reg) main => val_u64); + } +} + +// Constants must be... constant + +static S: i32 = 1; +const fn const_foo(x: i32) -> i32 { + x +} +const fn const_bar(x: T) -> T { + x +} +global_asm!("{}", const S); +//~^ ERROR constants cannot refer to statics +global_asm!("{}", const const_foo(0)); +global_asm!("{}", const const_foo(S)); +//~^ ERROR constants cannot refer to statics +global_asm!("{}", const const_bar(0)); +global_asm!("{}", const const_bar(S)); +//~^ ERROR constants cannot refer to statics diff --git a/src/test/ui/asm/aarch64/type-check-3.stderr b/src/test/ui/asm/aarch64/type-check-3.stderr new file mode 100644 index 0000000000..c31a62ae79 --- /dev/null +++ b/src/test/ui/asm/aarch64/type-check-3.stderr @@ -0,0 +1,172 @@ +warning: formatting may not be suitable for sub-register argument + --> $DIR/type-check-3.rs:48:15 + | +LL | asm!("{}", in(reg) 0u8); + | ^^ --- for this argument + | + = note: `#[warn(asm_sub_register)]` on by default + = help: use the `w` modifier to have the register formatted as `w0` + = 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 + | +LL | asm!("{}", in(reg) 0u16); + | ^^ ---- for this argument + | + = help: use the `w` modifier to have the register formatted as `w0` + = 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 + | +LL | asm!("{}", in(reg) 0i32); + | ^^ ---- for this argument + | + = help: use the `w` modifier to have the register formatted as `w0` + = 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 + | +LL | asm!("{}", in(reg) 0f32); + | ^^ ---- for this argument + | + = help: use the `w` modifier to have the register formatted as `w0` + = 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 + | +LL | asm!("{}", in(vreg) 0i16); + | ^^ ---- for this argument + | + = help: use the `h` modifier to have the register formatted as `h0` + = 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 + | +LL | asm!("{}", in(vreg) 0f32); + | ^^ ---- for this argument + | + = help: use the `s` modifier to have the register formatted as `s0` + = 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 + | +LL | asm!("{}", in(vreg) 0f64); + | ^^ ---- for this argument + | + = help: use the `d` modifier to have the register formatted as `d0` + = 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 + | +LL | asm!("{}", in(vreg_low16) 0f64); + | ^^ ---- for this argument + | + = help: use the `d` modifier to have the register formatted as `d0` + = 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 + | +LL | asm!("{0} {0}", in(reg) 0i16); + | ^^^ ^^^ ---- for this argument + | + = help: use the `w` modifier to have the register formatted as `w0` + = 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 + | +LL | asm!("{0} {0:x}", in(reg) 0i16); + | ^^^ ---- for this argument + | + = help: use the `w` modifier to have the register formatted as `w0` + = 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 + | +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 + | +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 + | +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 + | +LL | asm!("{:x}", inout(reg) 0u32 => val_f32); + | ^^^^ ^^^^^^^ type `f32` + | | + | type `u32` + | + = 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 + | +LL | asm!("{:x}", inout(reg) 0u32 => val_ptr); + | ^^^^ ^^^^^^^ type `*mut u8` + | | + | type `u32` + | + = 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 + | +LL | asm!("{:x}", inout(reg) main => val_u32); + | ^^^^ ^^^^^^^ type `u32` + | | + | type `fn()` + | + = 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 + | +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 + | +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 + | +LL | global_asm!("{}", const const_bar(S)); + | ^ + | + = help: consider extracting the value of the `static` to a `const`, and referring to that + +error: aborting due to 9 previous errors; 10 warnings emitted + +For more information about this error, try `rustc --explain E0013`. diff --git a/src/test/ui/asm/bad-arch.mirunsafeck.stderr b/src/test/ui/asm/bad-arch.mirunsafeck.stderr index d86e53c062..4aa2718075 100644 --- a/src/test/ui/asm/bad-arch.mirunsafeck.stderr +++ b/src/test/ui/asm/bad-arch.mirunsafeck.stderr @@ -2,13 +2,13 @@ error[E0472]: inline assembly is unsupported on this target --> $DIR/bad-arch.rs:22:9 | LL | asm!(""); - | ^^^^^^^^^ + | ^^^^^^^^ error[E0472]: inline assembly is unsupported on this target --> $DIR/bad-arch.rs:27:1 | LL | global_asm!(""); - | ^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^ | = note: this error originates in the macro `global_asm` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/asm/bad-arch.thirunsafeck.stderr b/src/test/ui/asm/bad-arch.thirunsafeck.stderr index d86e53c062..4aa2718075 100644 --- a/src/test/ui/asm/bad-arch.thirunsafeck.stderr +++ b/src/test/ui/asm/bad-arch.thirunsafeck.stderr @@ -2,13 +2,13 @@ error[E0472]: inline assembly is unsupported on this target --> $DIR/bad-arch.rs:22:9 | LL | asm!(""); - | ^^^^^^^^^ + | ^^^^^^^^ error[E0472]: inline assembly is unsupported on this target --> $DIR/bad-arch.rs:27:1 | LL | global_asm!(""); - | ^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^ | = note: this error originates in the macro `global_asm` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/asm/bad-template.aarch64_mirunsafeck.stderr b/src/test/ui/asm/bad-template.aarch64_mirunsafeck.stderr new file mode 100644 index 0000000000..3b1d922a7f --- /dev/null +++ b/src/test/ui/asm/bad-template.aarch64_mirunsafeck.stderr @@ -0,0 +1,187 @@ +error: invalid reference to argument at index 0 + --> $DIR/bad-template.rs:31:15 + | +LL | asm!("{}"); + | ^^ from here + | + = note: no arguments were given + +error: invalid reference to argument at index 1 + --> $DIR/bad-template.rs:33:15 + | +LL | asm!("{1}", in(reg) foo); + | ^^^ from here + | + = note: there is 1 argument + +error: argument never used + --> $DIR/bad-template.rs:33:21 + | +LL | asm!("{1}", in(reg) foo); + | ^^^^^^^^^^^ argument never used + | + = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {0} */"` + +error: there is no argument named `a` + --> $DIR/bad-template.rs:36:15 + | +LL | asm!("{a}"); + | ^^^ + +error: invalid reference to argument at index 0 + --> $DIR/bad-template.rs:38:15 + | +LL | asm!("{}", a = in(reg) foo); + | ^^ --------------- named argument + | | + | from here + | + = note: no positional arguments were given +note: named arguments cannot be referenced by position + --> $DIR/bad-template.rs:38:20 + | +LL | asm!("{}", a = in(reg) foo); + | ^^^^^^^^^^^^^^^ + +error: named argument never used + --> $DIR/bad-template.rs:38:20 + | +LL | asm!("{}", a = in(reg) foo); + | ^^^^^^^^^^^^^^^ named argument never used + | + = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"` + +error: invalid reference to argument at index 1 + --> $DIR/bad-template.rs:41:15 + | +LL | asm!("{1}", a = in(reg) foo); + | ^^^ from here + | + = note: no positional arguments were given + +error: named argument never used + --> $DIR/bad-template.rs:41:21 + | +LL | asm!("{1}", a = in(reg) foo); + | ^^^^^^^^^^^^^^^ named argument never used + | + = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"` + +error: invalid reference to argument at index 0 + --> $DIR/bad-template.rs:48:15 + | +LL | asm!("{}", in("x0") foo); + | ^^ ------------ explicit register argument + | | + | from here + | + = note: no positional arguments were given +note: explicit register arguments cannot be used in the asm template + --> $DIR/bad-template.rs:48:20 + | +LL | asm!("{}", in("x0") foo); + | ^^^^^^^^^^^^ + +error: asm template modifier must be a single character + --> $DIR/bad-template.rs:50:17 + | +LL | asm!("{:foo}", in(reg) foo); + | ^^^ + +error: multiple unused asm arguments + --> $DIR/bad-template.rs:52:18 + | +LL | asm!("", in(reg) 0, in(reg) 1); + | ^^^^^^^^^ ^^^^^^^^^ argument never used + | | + | argument never used + | + = help: if these arguments are intentionally unused, consider using them in an asm comment: `"/* {0} {1} */"` + +error: invalid reference to argument at index 0 + --> $DIR/bad-template.rs:58:14 + | +LL | global_asm!("{}"); + | ^^ from here + | + = note: no arguments were given + +error: invalid reference to argument at index 1 + --> $DIR/bad-template.rs:60:14 + | +LL | global_asm!("{1}", const FOO); + | ^^^ from here + | + = note: there is 1 argument + +error: argument never used + --> $DIR/bad-template.rs:60:20 + | +LL | global_asm!("{1}", const FOO); + | ^^^^^^^^^ argument never used + | + = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {0} */"` + +error: there is no argument named `a` + --> $DIR/bad-template.rs:63:14 + | +LL | global_asm!("{a}"); + | ^^^ + +error: invalid reference to argument at index 0 + --> $DIR/bad-template.rs:65:14 + | +LL | global_asm!("{}", a = const FOO); + | ^^ ------------- named argument + | | + | from here + | + = note: no positional arguments were given +note: named arguments cannot be referenced by position + --> $DIR/bad-template.rs:65:19 + | +LL | global_asm!("{}", a = const FOO); + | ^^^^^^^^^^^^^ + +error: named argument never used + --> $DIR/bad-template.rs:65:19 + | +LL | global_asm!("{}", a = const FOO); + | ^^^^^^^^^^^^^ named argument never used + | + = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"` + +error: invalid reference to argument at index 1 + --> $DIR/bad-template.rs:68:14 + | +LL | global_asm!("{1}", a = const FOO); + | ^^^ from here + | + = note: no positional arguments were given + +error: named argument never used + --> $DIR/bad-template.rs:68:20 + | +LL | global_asm!("{1}", a = const FOO); + | ^^^^^^^^^^^^^ named argument never used + | + = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"` + +error: asm template modifier must be a single character + --> $DIR/bad-template.rs:71:16 + | +LL | global_asm!("{:foo}", const FOO); + | ^^^ + +error: multiple unused asm arguments + --> $DIR/bad-template.rs:73:17 + | +LL | global_asm!("", const FOO, const FOO); + | ^^^^^^^^^ ^^^^^^^^^ argument never used + | | + | argument never used + | + = help: if these arguments are intentionally unused, consider using them in an asm comment: `"/* {0} {1} */"` + +error: aborting due to 21 previous errors + diff --git a/src/test/ui/asm/bad-template.aarch64_thirunsafeck.stderr b/src/test/ui/asm/bad-template.aarch64_thirunsafeck.stderr new file mode 100644 index 0000000000..3b1d922a7f --- /dev/null +++ b/src/test/ui/asm/bad-template.aarch64_thirunsafeck.stderr @@ -0,0 +1,187 @@ +error: invalid reference to argument at index 0 + --> $DIR/bad-template.rs:31:15 + | +LL | asm!("{}"); + | ^^ from here + | + = note: no arguments were given + +error: invalid reference to argument at index 1 + --> $DIR/bad-template.rs:33:15 + | +LL | asm!("{1}", in(reg) foo); + | ^^^ from here + | + = note: there is 1 argument + +error: argument never used + --> $DIR/bad-template.rs:33:21 + | +LL | asm!("{1}", in(reg) foo); + | ^^^^^^^^^^^ argument never used + | + = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {0} */"` + +error: there is no argument named `a` + --> $DIR/bad-template.rs:36:15 + | +LL | asm!("{a}"); + | ^^^ + +error: invalid reference to argument at index 0 + --> $DIR/bad-template.rs:38:15 + | +LL | asm!("{}", a = in(reg) foo); + | ^^ --------------- named argument + | | + | from here + | + = note: no positional arguments were given +note: named arguments cannot be referenced by position + --> $DIR/bad-template.rs:38:20 + | +LL | asm!("{}", a = in(reg) foo); + | ^^^^^^^^^^^^^^^ + +error: named argument never used + --> $DIR/bad-template.rs:38:20 + | +LL | asm!("{}", a = in(reg) foo); + | ^^^^^^^^^^^^^^^ named argument never used + | + = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"` + +error: invalid reference to argument at index 1 + --> $DIR/bad-template.rs:41:15 + | +LL | asm!("{1}", a = in(reg) foo); + | ^^^ from here + | + = note: no positional arguments were given + +error: named argument never used + --> $DIR/bad-template.rs:41:21 + | +LL | asm!("{1}", a = in(reg) foo); + | ^^^^^^^^^^^^^^^ named argument never used + | + = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"` + +error: invalid reference to argument at index 0 + --> $DIR/bad-template.rs:48:15 + | +LL | asm!("{}", in("x0") foo); + | ^^ ------------ explicit register argument + | | + | from here + | + = note: no positional arguments were given +note: explicit register arguments cannot be used in the asm template + --> $DIR/bad-template.rs:48:20 + | +LL | asm!("{}", in("x0") foo); + | ^^^^^^^^^^^^ + +error: asm template modifier must be a single character + --> $DIR/bad-template.rs:50:17 + | +LL | asm!("{:foo}", in(reg) foo); + | ^^^ + +error: multiple unused asm arguments + --> $DIR/bad-template.rs:52:18 + | +LL | asm!("", in(reg) 0, in(reg) 1); + | ^^^^^^^^^ ^^^^^^^^^ argument never used + | | + | argument never used + | + = help: if these arguments are intentionally unused, consider using them in an asm comment: `"/* {0} {1} */"` + +error: invalid reference to argument at index 0 + --> $DIR/bad-template.rs:58:14 + | +LL | global_asm!("{}"); + | ^^ from here + | + = note: no arguments were given + +error: invalid reference to argument at index 1 + --> $DIR/bad-template.rs:60:14 + | +LL | global_asm!("{1}", const FOO); + | ^^^ from here + | + = note: there is 1 argument + +error: argument never used + --> $DIR/bad-template.rs:60:20 + | +LL | global_asm!("{1}", const FOO); + | ^^^^^^^^^ argument never used + | + = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {0} */"` + +error: there is no argument named `a` + --> $DIR/bad-template.rs:63:14 + | +LL | global_asm!("{a}"); + | ^^^ + +error: invalid reference to argument at index 0 + --> $DIR/bad-template.rs:65:14 + | +LL | global_asm!("{}", a = const FOO); + | ^^ ------------- named argument + | | + | from here + | + = note: no positional arguments were given +note: named arguments cannot be referenced by position + --> $DIR/bad-template.rs:65:19 + | +LL | global_asm!("{}", a = const FOO); + | ^^^^^^^^^^^^^ + +error: named argument never used + --> $DIR/bad-template.rs:65:19 + | +LL | global_asm!("{}", a = const FOO); + | ^^^^^^^^^^^^^ named argument never used + | + = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"` + +error: invalid reference to argument at index 1 + --> $DIR/bad-template.rs:68:14 + | +LL | global_asm!("{1}", a = const FOO); + | ^^^ from here + | + = note: no positional arguments were given + +error: named argument never used + --> $DIR/bad-template.rs:68:20 + | +LL | global_asm!("{1}", a = const FOO); + | ^^^^^^^^^^^^^ named argument never used + | + = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"` + +error: asm template modifier must be a single character + --> $DIR/bad-template.rs:71:16 + | +LL | global_asm!("{:foo}", const FOO); + | ^^^ + +error: multiple unused asm arguments + --> $DIR/bad-template.rs:73:17 + | +LL | global_asm!("", const FOO, const FOO); + | ^^^^^^^^^ ^^^^^^^^^ argument never used + | | + | argument never used + | + = help: if these arguments are intentionally unused, consider using them in an asm comment: `"/* {0} {1} */"` + +error: aborting due to 21 previous errors + diff --git a/src/test/ui/asm/bad-template.rs b/src/test/ui/asm/bad-template.rs index 5aed2c62f0..fca77e7aa7 100644 --- a/src/test/ui/asm/bad-template.rs +++ b/src/test/ui/asm/bad-template.rs @@ -1,8 +1,29 @@ -// only-x86_64 -// revisions: mirunsafeck thirunsafeck -// [thirunsafeck]compile-flags: -Z thir-unsafeck +// revisions: x86_64_mirunsafeck aarch64_mirunsafeck x86_64_thirunsafeck aarch64_thirunsafeck -#![feature(asm, global_asm)] +// [x86_64_thirunsafeck] compile-flags: -Z thir-unsafeck --target x86_64-unknown-linux-gnu +// [aarch64_thirunsafeck] compile-flags: -Z thir-unsafeck --target aarch64-unknown-linux-gnu +// [x86_64_mirunsafeck] compile-flags: --target x86_64-unknown-linux-gnu +// [aarch64_mirunsafeck] compile-flags: --target aarch64-unknown-linux-gnu + +// [x86_64_thirunsafeck] needs-llvm-components: x86 +// [x86_64_mirunsafeck] needs-llvm-components: x86 +// [aarch64_thirunsafeck] needs-llvm-components: aarch64 +// [aarch64_mirunsafeck] needs-llvm-components: aarch64 + +#![feature(no_core, lang_items, rustc_attrs)] +#![no_core] + +#[rustc_builtin_macro] +macro_rules! asm { + () => {}; +} +#[rustc_builtin_macro] +macro_rules! global_asm { + () => {}; +} + +#[lang = "sized"] +trait Sized {} fn main() { let mut foo = 0; @@ -20,8 +41,12 @@ fn main() { asm!("{1}", a = in(reg) foo); //~^ ERROR invalid reference to argument at index 1 //~^^ ERROR named argument never used + #[cfg(any(x86_64_thirunsafeck, x86_64_mirunsafeck))] asm!("{}", in("eax") foo); - //~^ ERROR invalid reference to argument at index 0 + //[x86_64_thirunsafeck,x86_64_mirunsafeck]~^ ERROR invalid reference to argument at index 0 + #[cfg(any(aarch64_thirunsafeck, aarch64_mirunsafeck))] + asm!("{}", in("x0") foo); + //[aarch64_thirunsafeck,aarch64_mirunsafeck]~^ ERROR invalid reference to argument at index 0 asm!("{:foo}", in(reg) foo); //~^ ERROR asm template modifier must be a single character asm!("", in(reg) 0, in(reg) 1); diff --git a/src/test/ui/asm/bad-template.thirunsafeck.stderr b/src/test/ui/asm/bad-template.x86_64_mirunsafeck.stderr similarity index 85% rename from src/test/ui/asm/bad-template.thirunsafeck.stderr rename to src/test/ui/asm/bad-template.x86_64_mirunsafeck.stderr index 13ef032ab1..3b69186f1e 100644 --- a/src/test/ui/asm/bad-template.thirunsafeck.stderr +++ b/src/test/ui/asm/bad-template.x86_64_mirunsafeck.stderr @@ -1,5 +1,5 @@ error: invalid reference to argument at index 0 - --> $DIR/bad-template.rs:10:15 + --> $DIR/bad-template.rs:31:15 | LL | asm!("{}"); | ^^ from here @@ -7,7 +7,7 @@ LL | asm!("{}"); = note: no arguments were given error: invalid reference to argument at index 1 - --> $DIR/bad-template.rs:12:15 + --> $DIR/bad-template.rs:33:15 | LL | asm!("{1}", in(reg) foo); | ^^^ from here @@ -15,7 +15,7 @@ LL | asm!("{1}", in(reg) foo); = note: there is 1 argument error: argument never used - --> $DIR/bad-template.rs:12:21 + --> $DIR/bad-template.rs:33:21 | LL | asm!("{1}", in(reg) foo); | ^^^^^^^^^^^ argument never used @@ -23,13 +23,13 @@ LL | asm!("{1}", in(reg) foo); = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {0} */"` error: there is no argument named `a` - --> $DIR/bad-template.rs:15:15 + --> $DIR/bad-template.rs:36:15 | LL | asm!("{a}"); | ^^^ error: invalid reference to argument at index 0 - --> $DIR/bad-template.rs:17:15 + --> $DIR/bad-template.rs:38:15 | LL | asm!("{}", a = in(reg) foo); | ^^ --------------- named argument @@ -38,13 +38,13 @@ LL | asm!("{}", a = in(reg) foo); | = note: no positional arguments were given note: named arguments cannot be referenced by position - --> $DIR/bad-template.rs:17:20 + --> $DIR/bad-template.rs:38:20 | LL | asm!("{}", a = in(reg) foo); | ^^^^^^^^^^^^^^^ error: named argument never used - --> $DIR/bad-template.rs:17:20 + --> $DIR/bad-template.rs:38:20 | LL | asm!("{}", a = in(reg) foo); | ^^^^^^^^^^^^^^^ named argument never used @@ -52,7 +52,7 @@ LL | asm!("{}", a = in(reg) foo); = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"` error: invalid reference to argument at index 1 - --> $DIR/bad-template.rs:20:15 + --> $DIR/bad-template.rs:41:15 | LL | asm!("{1}", a = in(reg) foo); | ^^^ from here @@ -60,7 +60,7 @@ LL | asm!("{1}", a = in(reg) foo); = note: no positional arguments were given error: named argument never used - --> $DIR/bad-template.rs:20:21 + --> $DIR/bad-template.rs:41:21 | LL | asm!("{1}", a = in(reg) foo); | ^^^^^^^^^^^^^^^ named argument never used @@ -68,7 +68,7 @@ LL | asm!("{1}", a = in(reg) foo); = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"` error: invalid reference to argument at index 0 - --> $DIR/bad-template.rs:23:15 + --> $DIR/bad-template.rs:45:15 | LL | asm!("{}", in("eax") foo); | ^^ ------------- explicit register argument @@ -77,19 +77,19 @@ LL | asm!("{}", in("eax") foo); | = note: no positional arguments were given note: explicit register arguments cannot be used in the asm template - --> $DIR/bad-template.rs:23:20 + --> $DIR/bad-template.rs:45:20 | LL | asm!("{}", in("eax") foo); | ^^^^^^^^^^^^^ error: asm template modifier must be a single character - --> $DIR/bad-template.rs:25:17 + --> $DIR/bad-template.rs:50:17 | LL | asm!("{:foo}", in(reg) foo); | ^^^ error: multiple unused asm arguments - --> $DIR/bad-template.rs:27:18 + --> $DIR/bad-template.rs:52:18 | LL | asm!("", in(reg) 0, in(reg) 1); | ^^^^^^^^^ ^^^^^^^^^ argument never used @@ -99,7 +99,7 @@ LL | asm!("", in(reg) 0, in(reg) 1); = help: if these arguments are intentionally unused, consider using them in an asm comment: `"/* {0} {1} */"` error: invalid reference to argument at index 0 - --> $DIR/bad-template.rs:33:14 + --> $DIR/bad-template.rs:58:14 | LL | global_asm!("{}"); | ^^ from here @@ -107,7 +107,7 @@ LL | global_asm!("{}"); = note: no arguments were given error: invalid reference to argument at index 1 - --> $DIR/bad-template.rs:35:14 + --> $DIR/bad-template.rs:60:14 | LL | global_asm!("{1}", const FOO); | ^^^ from here @@ -115,7 +115,7 @@ LL | global_asm!("{1}", const FOO); = note: there is 1 argument error: argument never used - --> $DIR/bad-template.rs:35:20 + --> $DIR/bad-template.rs:60:20 | LL | global_asm!("{1}", const FOO); | ^^^^^^^^^ argument never used @@ -123,13 +123,13 @@ LL | global_asm!("{1}", const FOO); = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {0} */"` error: there is no argument named `a` - --> $DIR/bad-template.rs:38:14 + --> $DIR/bad-template.rs:63:14 | LL | global_asm!("{a}"); | ^^^ error: invalid reference to argument at index 0 - --> $DIR/bad-template.rs:40:14 + --> $DIR/bad-template.rs:65:14 | LL | global_asm!("{}", a = const FOO); | ^^ ------------- named argument @@ -138,13 +138,13 @@ LL | global_asm!("{}", a = const FOO); | = note: no positional arguments were given note: named arguments cannot be referenced by position - --> $DIR/bad-template.rs:40:19 + --> $DIR/bad-template.rs:65:19 | LL | global_asm!("{}", a = const FOO); | ^^^^^^^^^^^^^ error: named argument never used - --> $DIR/bad-template.rs:40:19 + --> $DIR/bad-template.rs:65:19 | LL | global_asm!("{}", a = const FOO); | ^^^^^^^^^^^^^ named argument never used @@ -152,7 +152,7 @@ LL | global_asm!("{}", a = const FOO); = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"` error: invalid reference to argument at index 1 - --> $DIR/bad-template.rs:43:14 + --> $DIR/bad-template.rs:68:14 | LL | global_asm!("{1}", a = const FOO); | ^^^ from here @@ -160,7 +160,7 @@ LL | global_asm!("{1}", a = const FOO); = note: no positional arguments were given error: named argument never used - --> $DIR/bad-template.rs:43:20 + --> $DIR/bad-template.rs:68:20 | LL | global_asm!("{1}", a = const FOO); | ^^^^^^^^^^^^^ named argument never used @@ -168,13 +168,13 @@ LL | global_asm!("{1}", a = const FOO); = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"` error: asm template modifier must be a single character - --> $DIR/bad-template.rs:46:16 + --> $DIR/bad-template.rs:71:16 | LL | global_asm!("{:foo}", const FOO); | ^^^ error: multiple unused asm arguments - --> $DIR/bad-template.rs:48:17 + --> $DIR/bad-template.rs:73:17 | LL | global_asm!("", const FOO, const FOO); | ^^^^^^^^^ ^^^^^^^^^ argument never used diff --git a/src/test/ui/asm/bad-template.mirunsafeck.stderr b/src/test/ui/asm/bad-template.x86_64_thirunsafeck.stderr similarity index 85% rename from src/test/ui/asm/bad-template.mirunsafeck.stderr rename to src/test/ui/asm/bad-template.x86_64_thirunsafeck.stderr index 13ef032ab1..3b69186f1e 100644 --- a/src/test/ui/asm/bad-template.mirunsafeck.stderr +++ b/src/test/ui/asm/bad-template.x86_64_thirunsafeck.stderr @@ -1,5 +1,5 @@ error: invalid reference to argument at index 0 - --> $DIR/bad-template.rs:10:15 + --> $DIR/bad-template.rs:31:15 | LL | asm!("{}"); | ^^ from here @@ -7,7 +7,7 @@ LL | asm!("{}"); = note: no arguments were given error: invalid reference to argument at index 1 - --> $DIR/bad-template.rs:12:15 + --> $DIR/bad-template.rs:33:15 | LL | asm!("{1}", in(reg) foo); | ^^^ from here @@ -15,7 +15,7 @@ LL | asm!("{1}", in(reg) foo); = note: there is 1 argument error: argument never used - --> $DIR/bad-template.rs:12:21 + --> $DIR/bad-template.rs:33:21 | LL | asm!("{1}", in(reg) foo); | ^^^^^^^^^^^ argument never used @@ -23,13 +23,13 @@ LL | asm!("{1}", in(reg) foo); = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {0} */"` error: there is no argument named `a` - --> $DIR/bad-template.rs:15:15 + --> $DIR/bad-template.rs:36:15 | LL | asm!("{a}"); | ^^^ error: invalid reference to argument at index 0 - --> $DIR/bad-template.rs:17:15 + --> $DIR/bad-template.rs:38:15 | LL | asm!("{}", a = in(reg) foo); | ^^ --------------- named argument @@ -38,13 +38,13 @@ LL | asm!("{}", a = in(reg) foo); | = note: no positional arguments were given note: named arguments cannot be referenced by position - --> $DIR/bad-template.rs:17:20 + --> $DIR/bad-template.rs:38:20 | LL | asm!("{}", a = in(reg) foo); | ^^^^^^^^^^^^^^^ error: named argument never used - --> $DIR/bad-template.rs:17:20 + --> $DIR/bad-template.rs:38:20 | LL | asm!("{}", a = in(reg) foo); | ^^^^^^^^^^^^^^^ named argument never used @@ -52,7 +52,7 @@ LL | asm!("{}", a = in(reg) foo); = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"` error: invalid reference to argument at index 1 - --> $DIR/bad-template.rs:20:15 + --> $DIR/bad-template.rs:41:15 | LL | asm!("{1}", a = in(reg) foo); | ^^^ from here @@ -60,7 +60,7 @@ LL | asm!("{1}", a = in(reg) foo); = note: no positional arguments were given error: named argument never used - --> $DIR/bad-template.rs:20:21 + --> $DIR/bad-template.rs:41:21 | LL | asm!("{1}", a = in(reg) foo); | ^^^^^^^^^^^^^^^ named argument never used @@ -68,7 +68,7 @@ LL | asm!("{1}", a = in(reg) foo); = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"` error: invalid reference to argument at index 0 - --> $DIR/bad-template.rs:23:15 + --> $DIR/bad-template.rs:45:15 | LL | asm!("{}", in("eax") foo); | ^^ ------------- explicit register argument @@ -77,19 +77,19 @@ LL | asm!("{}", in("eax") foo); | = note: no positional arguments were given note: explicit register arguments cannot be used in the asm template - --> $DIR/bad-template.rs:23:20 + --> $DIR/bad-template.rs:45:20 | LL | asm!("{}", in("eax") foo); | ^^^^^^^^^^^^^ error: asm template modifier must be a single character - --> $DIR/bad-template.rs:25:17 + --> $DIR/bad-template.rs:50:17 | LL | asm!("{:foo}", in(reg) foo); | ^^^ error: multiple unused asm arguments - --> $DIR/bad-template.rs:27:18 + --> $DIR/bad-template.rs:52:18 | LL | asm!("", in(reg) 0, in(reg) 1); | ^^^^^^^^^ ^^^^^^^^^ argument never used @@ -99,7 +99,7 @@ LL | asm!("", in(reg) 0, in(reg) 1); = help: if these arguments are intentionally unused, consider using them in an asm comment: `"/* {0} {1} */"` error: invalid reference to argument at index 0 - --> $DIR/bad-template.rs:33:14 + --> $DIR/bad-template.rs:58:14 | LL | global_asm!("{}"); | ^^ from here @@ -107,7 +107,7 @@ LL | global_asm!("{}"); = note: no arguments were given error: invalid reference to argument at index 1 - --> $DIR/bad-template.rs:35:14 + --> $DIR/bad-template.rs:60:14 | LL | global_asm!("{1}", const FOO); | ^^^ from here @@ -115,7 +115,7 @@ LL | global_asm!("{1}", const FOO); = note: there is 1 argument error: argument never used - --> $DIR/bad-template.rs:35:20 + --> $DIR/bad-template.rs:60:20 | LL | global_asm!("{1}", const FOO); | ^^^^^^^^^ argument never used @@ -123,13 +123,13 @@ LL | global_asm!("{1}", const FOO); = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {0} */"` error: there is no argument named `a` - --> $DIR/bad-template.rs:38:14 + --> $DIR/bad-template.rs:63:14 | LL | global_asm!("{a}"); | ^^^ error: invalid reference to argument at index 0 - --> $DIR/bad-template.rs:40:14 + --> $DIR/bad-template.rs:65:14 | LL | global_asm!("{}", a = const FOO); | ^^ ------------- named argument @@ -138,13 +138,13 @@ LL | global_asm!("{}", a = const FOO); | = note: no positional arguments were given note: named arguments cannot be referenced by position - --> $DIR/bad-template.rs:40:19 + --> $DIR/bad-template.rs:65:19 | LL | global_asm!("{}", a = const FOO); | ^^^^^^^^^^^^^ error: named argument never used - --> $DIR/bad-template.rs:40:19 + --> $DIR/bad-template.rs:65:19 | LL | global_asm!("{}", a = const FOO); | ^^^^^^^^^^^^^ named argument never used @@ -152,7 +152,7 @@ LL | global_asm!("{}", a = const FOO); = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"` error: invalid reference to argument at index 1 - --> $DIR/bad-template.rs:43:14 + --> $DIR/bad-template.rs:68:14 | LL | global_asm!("{1}", a = const FOO); | ^^^ from here @@ -160,7 +160,7 @@ LL | global_asm!("{1}", a = const FOO); = note: no positional arguments were given error: named argument never used - --> $DIR/bad-template.rs:43:20 + --> $DIR/bad-template.rs:68:20 | LL | global_asm!("{1}", a = const FOO); | ^^^^^^^^^^^^^ named argument never used @@ -168,13 +168,13 @@ LL | global_asm!("{1}", a = const FOO); = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"` error: asm template modifier must be a single character - --> $DIR/bad-template.rs:46:16 + --> $DIR/bad-template.rs:71:16 | LL | global_asm!("{:foo}", const FOO); | ^^^ error: multiple unused asm arguments - --> $DIR/bad-template.rs:48:17 + --> $DIR/bad-template.rs:73:17 | LL | global_asm!("", const FOO, const FOO); | ^^^^^^^^^ ^^^^^^^^^ argument never used diff --git a/src/test/ui/asm/issue-72570.rs b/src/test/ui/asm/issue-72570.rs index 678534657c..960f7427e3 100644 --- a/src/test/ui/asm/issue-72570.rs +++ b/src/test/ui/asm/issue-72570.rs @@ -1,5 +1,5 @@ // compile-flags: -Zsave-analysis -// only-x86_64 +// needs-asm-support // Also test for #72960 #![feature(asm)] diff --git a/src/test/ui/asm/issue-87802.rs b/src/test/ui/asm/issue-87802.rs index b1fc13b6a7..5b6453c42c 100644 --- a/src/test/ui/asm/issue-87802.rs +++ b/src/test/ui/asm/issue-87802.rs @@ -1,4 +1,7 @@ -// only-x86_64 +// needs-asm-support +// ignore-nvptx64 +// ignore-spirv +// ignore-wasm32 // Make sure rustc doesn't ICE on asm! when output type is !. #![feature(asm)] diff --git a/src/test/ui/asm/issue-87802.stderr b/src/test/ui/asm/issue-87802.stderr index 1eb72b68a7..de3e28fdd1 100644 --- a/src/test/ui/asm/issue-87802.stderr +++ b/src/test/ui/asm/issue-87802.stderr @@ -1,5 +1,5 @@ error: cannot use value of type `!` for inline assembly - --> $DIR/issue-87802.rs:9:36 + --> $DIR/issue-87802.rs:12:36 | LL | asm!("/* {0} */", out(reg) x); | ^ diff --git a/src/test/ui/asm/issue-89305.rs b/src/test/ui/asm/issue-89305.rs new file mode 100644 index 0000000000..bdcf3f305e --- /dev/null +++ b/src/test/ui/asm/issue-89305.rs @@ -0,0 +1,14 @@ +// Regression test for #89305, where a variable was erroneously reported +// as both unused and possibly-uninitialized. + +// check-pass + +#![feature(asm)] +#![warn(unused)] + +fn main() { + unsafe { + let x: () = asm!("nop"); + //~^ WARNING: unused variable: `x` + } +} diff --git a/src/test/ui/asm/issue-89305.stderr b/src/test/ui/asm/issue-89305.stderr new file mode 100644 index 0000000000..9cc127b44d --- /dev/null +++ b/src/test/ui/asm/issue-89305.stderr @@ -0,0 +1,15 @@ +warning: unused variable: `x` + --> $DIR/issue-89305.rs:11: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 + | +LL | #![warn(unused)] + | ^^^^^^ + = note: `#[warn(unused_variables)]` implied by `#[warn(unused)]` + +warning: 1 warning emitted + diff --git a/src/test/ui/asm/naked-functions-ffi.rs b/src/test/ui/asm/naked-functions-ffi.rs index 5b2a8ed303..f6725605b9 100644 --- a/src/test/ui/asm/naked-functions-ffi.rs +++ b/src/test/ui/asm/naked-functions-ffi.rs @@ -1,5 +1,5 @@ // check-pass -// only-x86_64 +// needs-asm-support #![feature(asm)] #![feature(naked_functions)] #![crate_type = "lib"] diff --git a/src/test/ui/asm/naked-functions-unused.aarch64.stderr b/src/test/ui/asm/naked-functions-unused.aarch64.stderr new file mode 100644 index 0000000000..a898ab19a7 --- /dev/null +++ b/src/test/ui/asm/naked-functions-unused.aarch64.stderr @@ -0,0 +1,69 @@ +error: unused variable: `a` + --> $DIR/naked-functions-unused.rs:15:32 + | +LL | pub extern "C" fn function(a: usize, b: usize) -> usize { + | ^ help: if this is intentional, prefix it with an underscore: `_a` + | +note: the lint level is defined here + --> $DIR/naked-functions-unused.rs:4:9 + | +LL | #![deny(unused)] + | ^^^^^^ + = note: `#[deny(unused_variables)]` implied by `#[deny(unused)]` + +error: unused variable: `b` + --> $DIR/naked-functions-unused.rs:15:42 + | +LL | pub extern "C" fn function(a: usize, b: usize) -> usize { + | ^ help: if this is intentional, prefix it with an underscore: `_b` + +error: unused variable: `a` + --> $DIR/naked-functions-unused.rs:24:38 + | +LL | pub extern "C" fn associated(a: usize, b: usize) -> usize { + | ^ help: if this is intentional, prefix it with an underscore: `_a` + +error: unused variable: `b` + --> $DIR/naked-functions-unused.rs:24:48 + | +LL | pub extern "C" fn associated(a: usize, b: usize) -> usize { + | ^ help: if this is intentional, prefix it with an underscore: `_b` + +error: unused variable: `a` + --> $DIR/naked-functions-unused.rs:30:41 + | +LL | pub extern "C" fn method(&self, a: usize, b: usize) -> usize { + | ^ help: if this is intentional, prefix it with an underscore: `_a` + +error: unused variable: `b` + --> $DIR/naked-functions-unused.rs:30:51 + | +LL | pub extern "C" fn method(&self, a: usize, b: usize) -> usize { + | ^ help: if this is intentional, prefix it with an underscore: `_b` + +error: unused variable: `a` + --> $DIR/naked-functions-unused.rs:38:40 + | +LL | extern "C" fn trait_associated(a: usize, b: usize) -> usize { + | ^ help: if this is intentional, prefix it with an underscore: `_a` + +error: unused variable: `b` + --> $DIR/naked-functions-unused.rs:38:50 + | +LL | extern "C" fn trait_associated(a: usize, b: usize) -> usize { + | ^ help: if this is intentional, prefix it with an underscore: `_b` + +error: unused variable: `a` + --> $DIR/naked-functions-unused.rs:44:43 + | +LL | extern "C" fn trait_method(&self, a: usize, b: usize) -> usize { + | ^ help: if this is intentional, prefix it with an underscore: `_a` + +error: unused variable: `b` + --> $DIR/naked-functions-unused.rs:44:53 + | +LL | extern "C" fn trait_method(&self, a: usize, b: usize) -> usize { + | ^ help: if this is intentional, prefix it with an underscore: `_b` + +error: aborting due to 10 previous errors + diff --git a/src/test/ui/asm/naked-functions-unused.rs b/src/test/ui/asm/naked-functions-unused.rs index e1f2362bb6..4c5c2ac1c1 100644 --- a/src/test/ui/asm/naked-functions-unused.rs +++ b/src/test/ui/asm/naked-functions-unused.rs @@ -1,16 +1,18 @@ -// only-x86_64 +// revisions: x86_64 aarch64 +//[x86_64] only-x86_64 +//[aarch64] only-aarch64 #![deny(unused)] #![feature(asm)] #![feature(naked_functions)] #![crate_type = "lib"] pub trait Trait { - extern "sysv64" fn trait_associated(a: usize, b: usize) -> usize; - extern "sysv64" fn trait_method(&self, a: usize, b: usize) -> usize; + extern "C" fn trait_associated(a: usize, b: usize) -> usize; + extern "C" fn trait_method(&self, a: usize, b: usize) -> usize; } pub mod normal { - pub extern "sysv64" fn function(a: usize, b: usize) -> usize { + pub extern "C" fn function(a: usize, b: usize) -> usize { //~^ ERROR unused variable: `a` //~| ERROR unused variable: `b` unsafe { asm!("", options(noreturn)); } @@ -19,13 +21,13 @@ pub mod normal { pub struct Normal; impl Normal { - pub extern "sysv64" fn associated(a: usize, b: usize) -> usize { + pub extern "C" fn associated(a: usize, b: usize) -> usize { //~^ ERROR unused variable: `a` //~| ERROR unused variable: `b` unsafe { asm!("", options(noreturn)); } } - pub extern "sysv64" fn method(&self, a: usize, b: usize) -> usize { + pub extern "C" fn method(&self, a: usize, b: usize) -> usize { //~^ ERROR unused variable: `a` //~| ERROR unused variable: `b` unsafe { asm!("", options(noreturn)); } @@ -33,13 +35,13 @@ pub mod normal { } impl super::Trait for Normal { - extern "sysv64" fn trait_associated(a: usize, b: usize) -> usize { + extern "C" fn trait_associated(a: usize, b: usize) -> usize { //~^ ERROR unused variable: `a` //~| ERROR unused variable: `b` unsafe { asm!("", options(noreturn)); } } - extern "sysv64" fn trait_method(&self, a: usize, b: usize) -> usize { + extern "C" fn trait_method(&self, a: usize, b: usize) -> usize { //~^ ERROR unused variable: `a` //~| ERROR unused variable: `b` unsafe { asm!("", options(noreturn)); } @@ -49,7 +51,7 @@ pub mod normal { pub mod naked { #[naked] - pub extern "sysv64" fn function(a: usize, b: usize) -> usize { + pub extern "C" fn function(a: usize, b: usize) -> usize { unsafe { asm!("", options(noreturn)); } } @@ -57,24 +59,24 @@ pub mod naked { impl Naked { #[naked] - pub extern "sysv64" fn associated(a: usize, b: usize) -> usize { + pub extern "C" fn associated(a: usize, b: usize) -> usize { unsafe { asm!("", options(noreturn)); } } #[naked] - pub extern "sysv64" fn method(&self, a: usize, b: usize) -> usize { + pub extern "C" fn method(&self, a: usize, b: usize) -> usize { unsafe { asm!("", options(noreturn)); } } } impl super::Trait for Naked { #[naked] - extern "sysv64" fn trait_associated(a: usize, b: usize) -> usize { + extern "C" fn trait_associated(a: usize, b: usize) -> usize { unsafe { asm!("", options(noreturn)); } } #[naked] - extern "sysv64" fn trait_method(&self, a: usize, b: usize) -> usize { + extern "C" fn trait_method(&self, a: usize, b: usize) -> usize { unsafe { asm!("", options(noreturn)); } } } diff --git a/src/test/ui/asm/naked-functions-unused.stderr b/src/test/ui/asm/naked-functions-unused.stderr deleted file mode 100644 index 840353366b..0000000000 --- a/src/test/ui/asm/naked-functions-unused.stderr +++ /dev/null @@ -1,69 +0,0 @@ -error: unused variable: `a` - --> $DIR/naked-functions-unused.rs:13:37 - | -LL | pub extern "sysv64" fn function(a: usize, b: usize) -> usize { - | ^ help: if this is intentional, prefix it with an underscore: `_a` - | -note: the lint level is defined here - --> $DIR/naked-functions-unused.rs:2:9 - | -LL | #![deny(unused)] - | ^^^^^^ - = note: `#[deny(unused_variables)]` implied by `#[deny(unused)]` - -error: unused variable: `b` - --> $DIR/naked-functions-unused.rs:13:47 - | -LL | pub extern "sysv64" fn function(a: usize, b: usize) -> usize { - | ^ help: if this is intentional, prefix it with an underscore: `_b` - -error: unused variable: `a` - --> $DIR/naked-functions-unused.rs:22:43 - | -LL | pub extern "sysv64" fn associated(a: usize, b: usize) -> usize { - | ^ help: if this is intentional, prefix it with an underscore: `_a` - -error: unused variable: `b` - --> $DIR/naked-functions-unused.rs:22:53 - | -LL | pub extern "sysv64" fn associated(a: usize, b: usize) -> usize { - | ^ help: if this is intentional, prefix it with an underscore: `_b` - -error: unused variable: `a` - --> $DIR/naked-functions-unused.rs:28:46 - | -LL | pub extern "sysv64" fn method(&self, a: usize, b: usize) -> usize { - | ^ help: if this is intentional, prefix it with an underscore: `_a` - -error: unused variable: `b` - --> $DIR/naked-functions-unused.rs:28:56 - | -LL | pub extern "sysv64" fn method(&self, a: usize, b: usize) -> usize { - | ^ help: if this is intentional, prefix it with an underscore: `_b` - -error: unused variable: `a` - --> $DIR/naked-functions-unused.rs:36:45 - | -LL | extern "sysv64" fn trait_associated(a: usize, b: usize) -> usize { - | ^ help: if this is intentional, prefix it with an underscore: `_a` - -error: unused variable: `b` - --> $DIR/naked-functions-unused.rs:36:55 - | -LL | extern "sysv64" fn trait_associated(a: usize, b: usize) -> usize { - | ^ help: if this is intentional, prefix it with an underscore: `_b` - -error: unused variable: `a` - --> $DIR/naked-functions-unused.rs:42:48 - | -LL | extern "sysv64" fn trait_method(&self, a: usize, b: usize) -> usize { - | ^ help: if this is intentional, prefix it with an underscore: `_a` - -error: unused variable: `b` - --> $DIR/naked-functions-unused.rs:42:58 - | -LL | extern "sysv64" fn trait_method(&self, a: usize, b: usize) -> usize { - | ^ help: if this is intentional, prefix it with an underscore: `_b` - -error: aborting due to 10 previous errors - diff --git a/src/test/ui/asm/naked-functions-unused.x86_64.stderr b/src/test/ui/asm/naked-functions-unused.x86_64.stderr new file mode 100644 index 0000000000..a898ab19a7 --- /dev/null +++ b/src/test/ui/asm/naked-functions-unused.x86_64.stderr @@ -0,0 +1,69 @@ +error: unused variable: `a` + --> $DIR/naked-functions-unused.rs:15:32 + | +LL | pub extern "C" fn function(a: usize, b: usize) -> usize { + | ^ help: if this is intentional, prefix it with an underscore: `_a` + | +note: the lint level is defined here + --> $DIR/naked-functions-unused.rs:4:9 + | +LL | #![deny(unused)] + | ^^^^^^ + = note: `#[deny(unused_variables)]` implied by `#[deny(unused)]` + +error: unused variable: `b` + --> $DIR/naked-functions-unused.rs:15:42 + | +LL | pub extern "C" fn function(a: usize, b: usize) -> usize { + | ^ help: if this is intentional, prefix it with an underscore: `_b` + +error: unused variable: `a` + --> $DIR/naked-functions-unused.rs:24:38 + | +LL | pub extern "C" fn associated(a: usize, b: usize) -> usize { + | ^ help: if this is intentional, prefix it with an underscore: `_a` + +error: unused variable: `b` + --> $DIR/naked-functions-unused.rs:24:48 + | +LL | pub extern "C" fn associated(a: usize, b: usize) -> usize { + | ^ help: if this is intentional, prefix it with an underscore: `_b` + +error: unused variable: `a` + --> $DIR/naked-functions-unused.rs:30:41 + | +LL | pub extern "C" fn method(&self, a: usize, b: usize) -> usize { + | ^ help: if this is intentional, prefix it with an underscore: `_a` + +error: unused variable: `b` + --> $DIR/naked-functions-unused.rs:30:51 + | +LL | pub extern "C" fn method(&self, a: usize, b: usize) -> usize { + | ^ help: if this is intentional, prefix it with an underscore: `_b` + +error: unused variable: `a` + --> $DIR/naked-functions-unused.rs:38:40 + | +LL | extern "C" fn trait_associated(a: usize, b: usize) -> usize { + | ^ help: if this is intentional, prefix it with an underscore: `_a` + +error: unused variable: `b` + --> $DIR/naked-functions-unused.rs:38:50 + | +LL | extern "C" fn trait_associated(a: usize, b: usize) -> usize { + | ^ help: if this is intentional, prefix it with an underscore: `_b` + +error: unused variable: `a` + --> $DIR/naked-functions-unused.rs:44:43 + | +LL | extern "C" fn trait_method(&self, a: usize, b: usize) -> usize { + | ^ help: if this is intentional, prefix it with an underscore: `_a` + +error: unused variable: `b` + --> $DIR/naked-functions-unused.rs:44:53 + | +LL | extern "C" fn trait_method(&self, a: usize, b: usize) -> usize { + | ^ help: if this is intentional, prefix it with an underscore: `_b` + +error: aborting due to 10 previous errors + diff --git a/src/test/ui/asm/naked-functions.rs b/src/test/ui/asm/naked-functions.rs index 72918a1411..803311d423 100644 --- a/src/test/ui/asm/naked-functions.rs +++ b/src/test/ui/asm/naked-functions.rs @@ -1,4 +1,8 @@ -// only-x86_64 +// needs-asm-support +// ignore-nvptx64 +// ignore-spirv +// ignore-wasm32 + #![feature(asm)] #![feature(llvm_asm)] #![feature(naked_functions)] diff --git a/src/test/ui/asm/naked-functions.stderr b/src/test/ui/asm/naked-functions.stderr index 3b54757cfe..465db634aa 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:127:14 + --> $DIR/naked-functions.rs:131:14 | LL | asm!("", options(readonly, nostack), options(pure)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^ error: patterns not allowed in naked function parameters - --> $DIR/naked-functions.rs:14:5 + --> $DIR/naked-functions.rs:18:5 | LL | mut a: u32, | ^^^^^ error: patterns not allowed in naked function parameters - --> $DIR/naked-functions.rs:16:5 + --> $DIR/naked-functions.rs:20:5 | LL | &b: &i32, | ^^ error: patterns not allowed in naked function parameters - --> $DIR/naked-functions.rs:18:6 + --> $DIR/naked-functions.rs:22:6 | LL | (None | Some(_)): Option>, | ^^^^^^^^^^^^^^ error: patterns not allowed in naked function parameters - --> $DIR/naked-functions.rs:20:5 + --> $DIR/naked-functions.rs:24:5 | LL | P { x, y }: P, | ^^^^^^^^^^ error: referencing function parameters is not allowed in naked functions - --> $DIR/naked-functions.rs:30:5 + --> $DIR/naked-functions.rs:34: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:27:1 + --> $DIR/naked-functions.rs:31:1 | LL | / pub unsafe extern "C" fn inc(a: u32) -> u32 { LL | | @@ -53,7 +53,7 @@ LL | | } = note: for more information, see issue #32408 error: referencing function parameters is not allowed in naked functions - --> $DIR/naked-functions.rs:36:31 + --> $DIR/naked-functions.rs:40: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:36:23 + --> $DIR/naked-functions.rs:40: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 warning: naked functions must contain a single asm block - --> $DIR/naked-functions.rs:43:1 + --> $DIR/naked-functions.rs:47: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 warning: only `const` and `sym` operands are supported in naked functions - --> $DIR/naked-functions.rs:63:10 + --> $DIR/naked-functions.rs:67:10 | LL | in(reg) a, | ^^^^^^^^^ @@ -102,7 +102,7 @@ LL | out(reg) e, = note: for more information, see issue #32408 warning: asm in naked functions must use `noreturn` option - --> $DIR/naked-functions.rs:60:5 + --> $DIR/naked-functions.rs:64:5 | LL | / asm!("/* {0} {1} {2} {3} {4} {5} {6} */", LL | | @@ -111,13 +111,13 @@ LL | | in(reg) a, ... | LL | | sym G, LL | | ); - | |______^ + | |_____^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #32408 warning: naked functions must contain a single asm block - --> $DIR/naked-functions.rs:50:1 + --> $DIR/naked-functions.rs:54:1 | LL | / pub unsafe extern "C" fn unsupported_operands() { LL | | @@ -141,7 +141,7 @@ LL | | } = note: for more information, see issue #32408 warning: naked functions must contain a single asm block - --> $DIR/naked-functions.rs:76:1 + --> $DIR/naked-functions.rs:80:1 | LL | / pub extern "C" fn missing_assembly() { LL | | @@ -153,34 +153,34 @@ LL | | } = note: for more information, see issue #32408 warning: asm in naked functions must use `noreturn` option - --> $DIR/naked-functions.rs:85:5 + --> $DIR/naked-functions.rs:89:5 | LL | asm!(""); - | ^^^^^^^^^ + | ^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #32408 warning: asm in naked functions must use `noreturn` option - --> $DIR/naked-functions.rs:88:5 + --> $DIR/naked-functions.rs:92:5 | LL | asm!(""); - | ^^^^^^^^^ + | ^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #32408 warning: asm in naked functions must use `noreturn` option - --> $DIR/naked-functions.rs:91:5 + --> $DIR/naked-functions.rs:95:5 | LL | asm!(""); - | ^^^^^^^^^ + | ^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #32408 warning: naked functions must contain a single asm block - --> $DIR/naked-functions.rs:82:1 + --> $DIR/naked-functions.rs:86:1 | LL | / pub extern "C" fn too_many_asm_blocks() { LL | | @@ -188,13 +188,13 @@ LL | | LL | | asm!(""); ... | LL | | asm!(""); - | | --------- multiple asm blocks are unsupported in naked functions + | | -------- multiple asm blocks are unsupported in naked functions ... | LL | | asm!(""); - | | --------- multiple asm blocks are unsupported in naked functions + | | -------- multiple asm blocks are unsupported in naked functions ... | LL | | asm!("", options(noreturn)); - | | ---------------------------- multiple asm blocks are unsupported in naked functions + | | --------------------------- multiple asm blocks are unsupported in naked functions LL | | } | |_^ | @@ -202,7 +202,7 @@ LL | | } = note: for more information, see issue #32408 error: referencing function parameters is not allowed in naked functions - --> $DIR/naked-functions.rs:102:11 + --> $DIR/naked-functions.rs:106: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:99:5 + --> $DIR/naked-functions.rs:103:5 | LL | / pub extern "C" fn inner(y: usize) -> usize { LL | | @@ -225,10 +225,10 @@ LL | | } = note: for more information, see issue #32408 warning: the LLVM-style inline assembly is unsupported in naked functions - --> $DIR/naked-functions.rs:112:5 + --> $DIR/naked-functions.rs:116:5 | LL | llvm_asm!(""); - | ^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #32408 @@ -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:109:1 + --> $DIR/naked-functions.rs:113:1 | LL | / unsafe extern "C" fn llvm() -> ! { LL | | @@ -252,34 +252,34 @@ LL | | } = note: for more information, see issue #32408 warning: asm options unsupported in naked functions: `nomem`, `preserves_flags` - --> $DIR/naked-functions.rs:120:5 + --> $DIR/naked-functions.rs:124:5 | LL | asm!("", options(nomem, preserves_flags, noreturn)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #32408 warning: asm options unsupported in naked functions: `nostack`, `pure`, `readonly` - --> $DIR/naked-functions.rs:127:5 + --> $DIR/naked-functions.rs:131:5 | LL | asm!("", options(readonly, nostack), options(pure)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #32408 warning: asm in naked functions must use `noreturn` option - --> $DIR/naked-functions.rs:127:5 + --> $DIR/naked-functions.rs:131:5 | LL | asm!("", options(readonly, nostack), options(pure)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #32408 warning: Rust ABI is unsupported in naked functions - --> $DIR/naked-functions.rs:136:15 + --> $DIR/naked-functions.rs:140: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:142:29 + --> $DIR/naked-functions.rs:146:29 | LL | pub unsafe extern "Rust" fn rust_abi() { | ^^^^^^^^ warning: naked functions cannot be inlined - --> $DIR/naked-functions.rs:176:1 + --> $DIR/naked-functions.rs:180:1 | LL | #[inline] | ^^^^^^^^^ @@ -302,7 +302,7 @@ LL | #[inline] = note: for more information, see issue #32408 warning: naked functions cannot be inlined - --> $DIR/naked-functions.rs:184:1 + --> $DIR/naked-functions.rs:188:1 | LL | #[inline(always)] | ^^^^^^^^^^^^^^^^^ @@ -311,7 +311,7 @@ LL | #[inline(always)] = note: for more information, see issue #32408 warning: naked functions cannot be inlined - --> $DIR/naked-functions.rs:192:1 + --> $DIR/naked-functions.rs:196:1 | LL | #[inline(never)] | ^^^^^^^^^^^^^^^^ @@ -320,7 +320,7 @@ LL | #[inline(never)] = note: for more information, see issue #32408 warning: naked functions cannot be inlined - --> $DIR/naked-functions.rs:200:1 + --> $DIR/naked-functions.rs:204:1 | LL | #[inline] | ^^^^^^^^^ @@ -329,7 +329,7 @@ LL | #[inline] = note: for more information, see issue #32408 warning: naked functions cannot be inlined - --> $DIR/naked-functions.rs:203:1 + --> $DIR/naked-functions.rs:207:1 | LL | #[inline(always)] | ^^^^^^^^^^^^^^^^^ @@ -338,7 +338,7 @@ LL | #[inline(always)] = note: for more information, see issue #32408 warning: naked functions cannot be inlined - --> $DIR/naked-functions.rs:206:1 + --> $DIR/naked-functions.rs:210: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 9f487bd806..82c47945a7 100644 --- a/src/test/ui/asm/named-asm-labels.rs +++ b/src/test/ui/asm/named-asm-labels.rs @@ -1,4 +1,7 @@ -// only-x86_64 +// needs-asm-support +// ignore-nvptx64 +// ignore-spirv +// ignore-wasm32 // Tests that the use of named labels in the `asm!` macro are linted against // except for in `#[naked]` fns. @@ -99,9 +102,6 @@ fn main() { asm!("\x41\x42\x43\x3A\x20\x6E\x6F\x70"); //~ ERROR avoid using named labels // Non-label colons - should pass - // (most of these are stolen from other places) - asm!("{:l}", in(reg) 0i64); - asm!("{:e}", in(reg) 0f32); asm!("mov rax, qword ptr fs:[0]"); // Comments diff --git a/src/test/ui/asm/named-asm-labels.stderr b/src/test/ui/asm/named-asm-labels.stderr index 396f0a1942..75c848cdc5 100644 --- a/src/test/ui/asm/named-asm-labels.stderr +++ b/src/test/ui/asm/named-asm-labels.stderr @@ -1,5 +1,5 @@ error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:19:15 + --> $DIR/named-asm-labels.rs:22:15 | LL | asm!("bar: nop"); | ^^^ @@ -9,7 +9,7 @@ LL | asm!("bar: nop"); = note: see the asm section of the unstable book for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:22:15 + --> $DIR/named-asm-labels.rs:25:15 | LL | asm!("abcd:"); | ^^^^ @@ -18,7 +18,7 @@ LL | asm!("abcd:"); = note: see the asm section of the unstable book for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:25:15 + --> $DIR/named-asm-labels.rs:28:15 | LL | asm!("foo: bar1: nop"); | ^^^ ^^^^ @@ -27,7 +27,7 @@ LL | asm!("foo: bar1: nop"); = note: see the asm section of the unstable book for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:29:15 + --> $DIR/named-asm-labels.rs:32:15 | LL | asm!("foo1: nop", "nop"); | ^^^^ @@ -36,7 +36,7 @@ LL | asm!("foo1: nop", "nop"); = note: see the asm section of the unstable book for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:30:15 + --> $DIR/named-asm-labels.rs:33:15 | LL | asm!("foo2: foo3: nop", "nop"); | ^^^^ ^^^^ @@ -45,7 +45,7 @@ LL | asm!("foo2: foo3: nop", "nop"); = note: see the asm section of the unstable book for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:32:22 + --> $DIR/named-asm-labels.rs:35:22 | LL | asm!("nop", "foo4: nop"); | ^^^^ @@ -54,7 +54,7 @@ LL | asm!("nop", "foo4: nop"); = note: see the asm section of the unstable book for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:33:15 + --> $DIR/named-asm-labels.rs:36:15 | LL | asm!("foo5: nop", "foo6: nop"); | ^^^^ @@ -63,7 +63,7 @@ LL | asm!("foo5: nop", "foo6: nop"); = note: see the asm section of the unstable book for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:33:28 + --> $DIR/named-asm-labels.rs:36:28 | LL | asm!("foo5: nop", "foo6: nop"); | ^^^^ @@ -72,7 +72,7 @@ LL | asm!("foo5: nop", "foo6: nop"); = note: see the asm section of the unstable book for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:38:15 + --> $DIR/named-asm-labels.rs:41:15 | LL | asm!("foo7: nop; foo8: nop"); | ^^^^ ^^^^ @@ -81,7 +81,7 @@ LL | asm!("foo7: nop; foo8: nop"); = note: see the asm section of the unstable book for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:40:15 + --> $DIR/named-asm-labels.rs:43:15 | LL | asm!("foo9: nop; nop"); | ^^^^ @@ -90,7 +90,7 @@ LL | asm!("foo9: nop; nop"); = note: see the asm section of the unstable book for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:41:20 + --> $DIR/named-asm-labels.rs:44:20 | LL | asm!("nop; foo10: nop"); | ^^^^^ @@ -99,7 +99,7 @@ LL | asm!("nop; foo10: nop"); = note: see the asm section of the unstable book for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:44:15 + --> $DIR/named-asm-labels.rs:47:15 | LL | asm!("bar2: nop\n bar3: nop"); | ^^^^ ^^^^ @@ -108,7 +108,7 @@ LL | asm!("bar2: nop\n bar3: nop"); = note: see the asm section of the unstable book for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:46:15 + --> $DIR/named-asm-labels.rs:49:15 | LL | asm!("bar4: nop\n nop"); | ^^^^ @@ -117,7 +117,7 @@ LL | asm!("bar4: nop\n nop"); = note: see the asm section of the unstable book for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:47:21 + --> $DIR/named-asm-labels.rs:50:21 | LL | asm!("nop\n bar5: nop"); | ^^^^ @@ -126,7 +126,7 @@ LL | asm!("nop\n bar5: nop"); = note: see the asm section of the unstable book for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:48:21 + --> $DIR/named-asm-labels.rs:51:21 | LL | asm!("nop\n bar6: bar7: nop"); | ^^^^ ^^^^ @@ -135,7 +135,7 @@ LL | asm!("nop\n bar6: bar7: nop"); = note: see the asm section of the unstable book for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:54:13 + --> $DIR/named-asm-labels.rs:57:13 | LL | blah2: nop | ^^^^^ @@ -146,7 +146,7 @@ LL | blah3: nop = note: see the asm section of the unstable book for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:63:19 + --> $DIR/named-asm-labels.rs:66:19 | LL | nop ; blah4: nop | ^^^^^ @@ -155,7 +155,7 @@ LL | nop ; blah4: nop = note: see the asm section of the unstable book for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:77:15 + --> $DIR/named-asm-labels.rs:80:15 | LL | asm!("blah1: 2bar: nop"); | ^^^^^ @@ -164,7 +164,7 @@ LL | asm!("blah1: 2bar: nop"); = note: see the asm section of the unstable book for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:80:15 + --> $DIR/named-asm-labels.rs:83:15 | LL | asm!("def: def: nop"); | ^^^ @@ -173,7 +173,7 @@ LL | asm!("def: def: nop"); = note: see the asm section of the unstable book for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:81:15 + --> $DIR/named-asm-labels.rs:84:15 | LL | asm!("def: nop\ndef: nop"); | ^^^ @@ -182,7 +182,7 @@ LL | asm!("def: nop\ndef: nop"); = note: see the asm section of the unstable book for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:82:15 + --> $DIR/named-asm-labels.rs:85:15 | LL | asm!("def: nop; def: nop"); | ^^^ @@ -191,7 +191,7 @@ LL | asm!("def: nop; def: nop"); = note: see the asm section of the unstable book for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:90:15 + --> $DIR/named-asm-labels.rs:93:15 | LL | asm!("fooo\u{003A} nop"); | ^^^^^^^^^^^^^^^^ @@ -200,7 +200,7 @@ LL | asm!("fooo\u{003A} nop"); = note: see the asm section of the unstable book for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:91:15 + --> $DIR/named-asm-labels.rs:94:15 | LL | asm!("foooo\x3A nop"); | ^^^^^^^^^^^^^ @@ -209,7 +209,7 @@ LL | asm!("foooo\x3A nop"); = note: see the asm section of the unstable book for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:94:15 + --> $DIR/named-asm-labels.rs:97:15 | LL | asm!("fooooo:\u{000A} nop"); | ^^^^^^ @@ -218,7 +218,7 @@ LL | asm!("fooooo:\u{000A} nop"); = note: see the asm section of the unstable book for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:95:15 + --> $DIR/named-asm-labels.rs:98:15 | LL | asm!("foooooo:\x0A nop"); | ^^^^^^^ @@ -227,7 +227,7 @@ LL | asm!("foooooo:\x0A nop"); = note: see the asm section of the unstable book for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:99:14 + --> $DIR/named-asm-labels.rs:102:14 | LL | asm!("\x41\x42\x43\x3A\x20\x6E\x6F\x70"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/asm/noreturn.rs b/src/test/ui/asm/noreturn.rs index 5e1ee93bfb..cb92ff0ad1 100644 --- a/src/test/ui/asm/noreturn.rs +++ b/src/test/ui/asm/noreturn.rs @@ -1,4 +1,4 @@ -// only-x86_64 +// needs-asm-support // check-pass #![feature(asm, never_type)] diff --git a/src/test/ui/asm/rustfix-asm.fixed b/src/test/ui/asm/rustfix-asm.fixed index 9251afd3f0..1d5d2038aa 100644 --- a/src/test/ui/asm/rustfix-asm.fixed +++ b/src/test/ui/asm/rustfix-asm.fixed @@ -1,5 +1,5 @@ // run-rustfix -// only-x86_64 +// needs-asm-support #![feature(asm, llvm_asm)] #![allow(deprecated)] // llvm_asm! diff --git a/src/test/ui/asm/rustfix-asm.rs b/src/test/ui/asm/rustfix-asm.rs index 1e3bfd0770..12be0e666e 100644 --- a/src/test/ui/asm/rustfix-asm.rs +++ b/src/test/ui/asm/rustfix-asm.rs @@ -1,5 +1,5 @@ // run-rustfix -// only-x86_64 +// needs-asm-support #![feature(asm, llvm_asm)] #![allow(deprecated)] // llvm_asm! diff --git a/src/test/ui/asm/rustfix-asm.stderr b/src/test/ui/asm/rustfix-asm.stderr index 14927f3eb2..babb154ccf 100644 --- a/src/test/ui/asm/rustfix-asm.stderr +++ b/src/test/ui/asm/rustfix-asm.stderr @@ -2,7 +2,7 @@ error: the legacy LLVM-style asm! syntax is no longer supported --> $DIR/rustfix-asm.rs:11:9 | LL | asm!("" :: "r" (x)); - | ----^^^^^^^^^^^^^^^^ + | ----^^^^^^^^^^^^^^^ | | | help: replace with: `llvm_asm!` | @@ -13,7 +13,7 @@ error: the legacy LLVM-style asm! syntax is no longer supported --> $DIR/rustfix-asm.rs:13:9 | LL | asm!("" : "=r" (y)); - | ----^^^^^^^^^^^^^^^^ + | ----^^^^^^^^^^^^^^^ | | | help: replace with: `llvm_asm!` | diff --git a/src/test/ui/asm/type-check-1.rs b/src/test/ui/asm/type-check-1.rs index 5e38fb70a4..bbbe798d15 100644 --- a/src/test/ui/asm/type-check-1.rs +++ b/src/test/ui/asm/type-check-1.rs @@ -1,4 +1,7 @@ -// only-x86_64 +// needs-asm-support +// ignore-nvptx64 +// ignore-spirv +// ignore-wasm32 #![feature(asm, global_asm)] @@ -49,6 +52,8 @@ fn main() { //~^ ERROR mismatched types asm!("{}", const 0 as *mut u8); //~^ ERROR mismatched types + asm!("{}", const &0); + //~^ ERROR mismatched types } } diff --git a/src/test/ui/asm/type-check-1.stderr b/src/test/ui/asm/type-check-1.stderr index 5edbcf4a2a..c9080a3c03 100644 --- a/src/test/ui/asm/type-check-1.stderr +++ b/src/test/ui/asm/type-check-1.stderr @@ -1,5 +1,5 @@ error[E0435]: attempt to use a non-constant value in a constant - --> $DIR/type-check-1.rs:34:26 + --> $DIR/type-check-1.rs:37:26 | LL | let x = 0; | ----- help: consider using `const` instead of `let`: `const x` @@ -8,7 +8,7 @@ LL | asm!("{}", const x); | ^ non-constant value error[E0435]: attempt to use a non-constant value in a constant - --> $DIR/type-check-1.rs:37:36 + --> $DIR/type-check-1.rs:40:36 | LL | let x = 0; | ----- help: consider using `const` instead of `let`: `const x` @@ -17,7 +17,7 @@ LL | asm!("{}", const const_foo(x)); | ^ non-constant value error[E0435]: attempt to use a non-constant value in a constant - --> $DIR/type-check-1.rs:40:36 + --> $DIR/type-check-1.rs:43:36 | LL | let x = 0; | ----- help: consider using `const` instead of `let`: `const x` @@ -26,13 +26,13 @@ LL | asm!("{}", const const_bar(x)); | ^ non-constant value error[E0308]: mismatched types - --> $DIR/type-check-1.rs:48:26 + --> $DIR/type-check-1.rs:51:26 | LL | asm!("{}", const 0f32); | ^^^^ expected integer, found `f32` error[E0308]: mismatched types - --> $DIR/type-check-1.rs:50:26 + --> $DIR/type-check-1.rs:53:26 | LL | asm!("{}", const 0 as *mut u8); | ^^^^^^^^^^^^ expected integer, found *-ptr @@ -40,20 +40,32 @@ LL | asm!("{}", const 0 as *mut u8); = note: expected type `{integer}` found raw pointer `*mut u8` +error[E0308]: mismatched types + --> $DIR/type-check-1.rs:55:26 + | +LL | asm!("{}", const &0); + | ^^ expected integer, found `&{integer}` + | +help: consider removing the borrow + | +LL - asm!("{}", const &0); +LL + asm!("{}", const 0); + | + error: invalid asm output - --> $DIR/type-check-1.rs:10:29 + --> $DIR/type-check-1.rs:13:29 | LL | asm!("{}", out(reg) 1 + 2); | ^^^^^ cannot assign to this expression error: invalid asm output - --> $DIR/type-check-1.rs:12:31 + --> $DIR/type-check-1.rs:15:31 | LL | asm!("{}", inout(reg) 1 + 2); | ^^^^^ cannot assign to this expression error[E0277]: the size for values of type `[u64]` cannot be known at compilation time - --> $DIR/type-check-1.rs:18:28 + --> $DIR/type-check-1.rs:21:28 | LL | asm!("{}", in(reg) v[..]); | ^^^^^ doesn't have a size known at compile-time @@ -62,7 +74,7 @@ LL | asm!("{}", in(reg) v[..]); = note: all inline asm arguments must have a statically known size error[E0277]: the size for values of type `[u64]` cannot be known at compilation time - --> $DIR/type-check-1.rs:20:29 + --> $DIR/type-check-1.rs:23:29 | LL | asm!("{}", out(reg) v[..]); | ^^^^^ doesn't have a size known at compile-time @@ -71,7 +83,7 @@ LL | asm!("{}", out(reg) v[..]); = note: all inline asm arguments must have a statically known size error[E0277]: the size for values of type `[u64]` cannot be known at compilation time - --> $DIR/type-check-1.rs:22:31 + --> $DIR/type-check-1.rs:25:31 | LL | asm!("{}", inout(reg) v[..]); | ^^^^^ doesn't have a size known at compile-time @@ -80,13 +92,13 @@ LL | asm!("{}", inout(reg) v[..]); = note: all inline asm arguments must have a statically known size error[E0308]: mismatched types - --> $DIR/type-check-1.rs:60:25 + --> $DIR/type-check-1.rs:65:25 | LL | global_asm!("{}", const 0f32); | ^^^^ expected integer, found `f32` error[E0308]: mismatched types - --> $DIR/type-check-1.rs:62:25 + --> $DIR/type-check-1.rs:67:25 | LL | global_asm!("{}", const 0 as *mut u8); | ^^^^^^^^^^^^ expected integer, found *-ptr @@ -94,7 +106,7 @@ LL | global_asm!("{}", const 0 as *mut u8); = note: expected type `{integer}` found raw pointer `*mut u8` -error: aborting due to 12 previous errors +error: aborting due to 13 previous errors Some errors have detailed explanations: E0277, E0308, E0435. For more information about an error, try `rustc --explain E0277`. diff --git a/src/test/ui/asm/type-check-4.rs b/src/test/ui/asm/type-check-4.rs index 2be627c116..c982666200 100644 --- a/src/test/ui/asm/type-check-4.rs +++ b/src/test/ui/asm/type-check-4.rs @@ -1,4 +1,7 @@ -// only-x86_64 +// needs-asm-support +// ignore-nvptx64 +// ignore-spirv +// ignore-wasm32 #![feature(asm)] diff --git a/src/test/ui/asm/type-check-4.stderr b/src/test/ui/asm/type-check-4.stderr index 8035bbefc1..c97cd171b1 100644 --- a/src/test/ui/asm/type-check-4.stderr +++ b/src/test/ui/asm/type-check-4.stderr @@ -1,16 +1,16 @@ error[E0506]: cannot assign to `a` because it is borrowed - --> $DIR/type-check-4.rs:11:9 + --> $DIR/type-check-4.rs:14:9 | LL | let p = &a; | -- borrow of `a` occurs here LL | asm!("{}", out(reg) a); - | ^^^^^^^^^^^^^^^^^^^^^^^ assignment to borrowed `a` occurs here + | ^^^^^^^^^^^^^^^^^^^^^^ assignment to borrowed `a` occurs here LL | LL | println!("{}", p); | - borrow later used here error[E0503]: cannot use `a` because it was mutably borrowed - --> $DIR/type-check-4.rs:19:28 + --> $DIR/type-check-4.rs:22:28 | LL | let p = &mut a; | ------ borrow of `a` occurs here diff --git a/src/test/ui/asm/bad-options.rs b/src/test/ui/asm/x86_64/bad-options.rs similarity index 100% rename from src/test/ui/asm/bad-options.rs rename to src/test/ui/asm/x86_64/bad-options.rs diff --git a/src/test/ui/asm/bad-options.stderr b/src/test/ui/asm/x86_64/bad-options.stderr similarity index 100% rename from src/test/ui/asm/bad-options.stderr rename to src/test/ui/asm/x86_64/bad-options.stderr diff --git a/src/test/ui/asm/bad-reg.rs b/src/test/ui/asm/x86_64/bad-reg.rs similarity index 92% rename from src/test/ui/asm/bad-reg.rs rename to src/test/ui/asm/x86_64/bad-reg.rs index 06af08fab8..91d0f8c33f 100644 --- a/src/test/ui/asm/bad-reg.rs +++ b/src/test/ui/asm/x86_64/bad-reg.rs @@ -21,10 +21,6 @@ fn main() { //~^ ERROR asm template modifiers are not allowed for `const` arguments asm!("{:a}", sym main); //~^ ERROR asm template modifiers are not allowed for `sym` arguments - asm!("{}", in(zmm_reg) foo); - //~^ ERROR register class `zmm_reg` requires the `avx512f` target feature - asm!("", in("zmm0") foo); - //~^ ERROR register class `zmm_reg` requires the `avx512f` target feature asm!("", in("ebp") foo); //~^ ERROR invalid register `ebp`: the frame pointer cannot be used as an operand asm!("", in("rsp") foo); diff --git a/src/test/ui/asm/bad-reg.stderr b/src/test/ui/asm/x86_64/bad-reg.stderr similarity index 87% rename from src/test/ui/asm/bad-reg.stderr rename to src/test/ui/asm/x86_64/bad-reg.stderr index 14740bf62f..102a17e981 100644 --- a/src/test/ui/asm/bad-reg.stderr +++ b/src/test/ui/asm/x86_64/bad-reg.stderr @@ -46,86 +46,74 @@ LL | asm!("{:a}", sym main); | | | template modifier -error: register class `zmm_reg` requires the `avx512f` target feature - --> $DIR/bad-reg.rs:24:20 - | -LL | asm!("{}", in(zmm_reg) foo); - | ^^^^^^^^^^^^^^^ - -error: register class `zmm_reg` requires the `avx512f` target feature - --> $DIR/bad-reg.rs:26:18 - | -LL | asm!("", in("zmm0") foo); - | ^^^^^^^^^^^^^^ - error: invalid register `ebp`: the frame pointer cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:28:18 + --> $DIR/bad-reg.rs:24:18 | LL | asm!("", in("ebp") foo); | ^^^^^^^^^^^^^ error: invalid register `rsp`: the stack pointer cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:30:18 + --> $DIR/bad-reg.rs:26:18 | LL | asm!("", in("rsp") foo); | ^^^^^^^^^^^^^ error: invalid register `ip`: the instruction pointer cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:32:18 + --> $DIR/bad-reg.rs:28:18 | LL | asm!("", in("ip") foo); | ^^^^^^^^^^^^ error: invalid register `k0`: the k0 AVX mask register cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:34:18 + --> $DIR/bad-reg.rs:30:18 | LL | asm!("", in("k0") foo); | ^^^^^^^^^^^^ error: invalid register `ah`: high byte registers cannot be used as an operand on x86_64 - --> $DIR/bad-reg.rs:36:18 + --> $DIR/bad-reg.rs:32:18 | LL | asm!("", in("ah") foo); | ^^^^^^^^^^^^ error: register class `x87_reg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:39:18 + --> $DIR/bad-reg.rs:35:18 | LL | asm!("", in("st(2)") foo); | ^^^^^^^^^^^^^^^ error: register class `mmx_reg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:41:18 + --> $DIR/bad-reg.rs:37:18 | LL | asm!("", in("mm0") foo); | ^^^^^^^^^^^^^ error: register class `x87_reg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:45:20 + --> $DIR/bad-reg.rs:41:20 | LL | asm!("{}", in(x87_reg) foo); | ^^^^^^^^^^^^^^^ error: register class `mmx_reg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:47:20 + --> $DIR/bad-reg.rs:43:20 | LL | asm!("{}", in(mmx_reg) foo); | ^^^^^^^^^^^^^^^ error: register class `x87_reg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:49:20 + --> $DIR/bad-reg.rs:45:20 | LL | asm!("{}", out(x87_reg) _); | ^^^^^^^^^^^^^^ error: register class `mmx_reg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:51:20 + --> $DIR/bad-reg.rs:47:20 | LL | asm!("{}", out(mmx_reg) _); | ^^^^^^^^^^^^^^ error: register `al` conflicts with register `ax` - --> $DIR/bad-reg.rs:57:33 + --> $DIR/bad-reg.rs:53:33 | LL | asm!("", in("eax") foo, in("al") bar); | ------------- ^^^^^^^^^^^^ register `al` @@ -133,7 +121,7 @@ LL | asm!("", in("eax") foo, in("al") bar); | register `ax` error: register `ax` conflicts with register `ax` - --> $DIR/bad-reg.rs:59:33 + --> $DIR/bad-reg.rs:55:33 | LL | asm!("", in("rax") foo, out("rax") bar); | ------------- ^^^^^^^^^^^^^^ register `ax` @@ -141,13 +129,13 @@ LL | asm!("", in("rax") foo, out("rax") bar); | register `ax` | help: use `lateout` instead of `out` to avoid conflict - --> $DIR/bad-reg.rs:59:18 + --> $DIR/bad-reg.rs:55:18 | LL | asm!("", in("rax") foo, out("rax") bar); | ^^^^^^^^^^^^^ error: register `ymm0` conflicts with register `xmm0` - --> $DIR/bad-reg.rs:62:34 + --> $DIR/bad-reg.rs:58:34 | LL | asm!("", in("xmm0") foo, in("ymm0") bar); | -------------- ^^^^^^^^^^^^^^ register `ymm0` @@ -155,7 +143,7 @@ LL | asm!("", in("xmm0") foo, in("ymm0") bar); | register `xmm0` error: register `ymm0` conflicts with register `xmm0` - --> $DIR/bad-reg.rs:64:34 + --> $DIR/bad-reg.rs:60:34 | LL | asm!("", in("xmm0") foo, out("ymm0") bar); | -------------- ^^^^^^^^^^^^^^^ register `ymm0` @@ -163,10 +151,10 @@ LL | asm!("", in("xmm0") foo, out("ymm0") bar); | register `xmm0` | help: use `lateout` instead of `out` to avoid conflict - --> $DIR/bad-reg.rs:64:18 + --> $DIR/bad-reg.rs:60:18 | LL | asm!("", in("xmm0") foo, out("ymm0") bar); | ^^^^^^^^^^^^^^ -error: aborting due to 23 previous errors +error: aborting due to 21 previous errors diff --git a/src/test/ui/asm/const.rs b/src/test/ui/asm/x86_64/const.rs similarity index 100% rename from src/test/ui/asm/const.rs rename to src/test/ui/asm/x86_64/const.rs diff --git a/src/test/ui/asm/duplicate-options.fixed b/src/test/ui/asm/x86_64/duplicate-options.fixed similarity index 100% rename from src/test/ui/asm/duplicate-options.fixed rename to src/test/ui/asm/x86_64/duplicate-options.fixed diff --git a/src/test/ui/asm/duplicate-options.rs b/src/test/ui/asm/x86_64/duplicate-options.rs similarity index 100% rename from src/test/ui/asm/duplicate-options.rs rename to src/test/ui/asm/x86_64/duplicate-options.rs diff --git a/src/test/ui/asm/duplicate-options.stderr b/src/test/ui/asm/x86_64/duplicate-options.stderr similarity index 100% rename from src/test/ui/asm/duplicate-options.stderr rename to src/test/ui/asm/x86_64/duplicate-options.stderr diff --git a/src/test/ui/asm/interpolated-idents.rs b/src/test/ui/asm/x86_64/interpolated-idents.rs similarity index 100% rename from src/test/ui/asm/interpolated-idents.rs rename to src/test/ui/asm/x86_64/interpolated-idents.rs diff --git a/src/test/ui/asm/interpolated-idents.stderr b/src/test/ui/asm/x86_64/interpolated-idents.stderr similarity index 77% rename from src/test/ui/asm/interpolated-idents.stderr rename to src/test/ui/asm/x86_64/interpolated-idents.stderr index 5de8d20547..6ac2ac5a77 100644 --- a/src/test/ui/asm/interpolated-idents.stderr +++ b/src/test/ui/asm/x86_64/interpolated-idents.stderr @@ -7,7 +7,7 @@ LL | $options($pure, $nomem, $readonly, $preserves_flags, $noretur LL | / m!(in out lateout inout inlateout const sym LL | | pure nomem readonly preserves_flags LL | | noreturn nostack att_syntax options); - | |____________________________________________- in this macro invocation + | |___________________________________________- in this macro invocation | = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -20,7 +20,7 @@ LL | $options($pure, $nomem, $readonly, $preserves_flags, $noretur LL | / m!(in out lateout inout inlateout const sym LL | | pure nomem readonly preserves_flags LL | | noreturn nostack att_syntax options); - | |____________________________________________- in this macro invocation + | |___________________________________________- in this macro invocation | = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -38,12 +38,12 @@ LL | m!(in out lateout inout inlateout const sym | | LL | | pure nomem readonly preserves_flags LL | | noreturn nostack att_syntax options); - | | - - | |____________________________________________| - | |____________________________________________in this macro invocation - | |____________________________________________in this macro invocation - | |____________________________________________in this macro invocation - | in this macro invocation + | | - + | |___________________________________________| + | |___________________________________________in this macro invocation + | |___________________________________________in this macro invocation + | |___________________________________________in this macro invocation + | in this macro invocation | = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/asm/issue-82869.rs b/src/test/ui/asm/x86_64/issue-82869.rs similarity index 100% rename from src/test/ui/asm/issue-82869.rs rename to src/test/ui/asm/x86_64/issue-82869.rs diff --git a/src/test/ui/asm/issue-82869.stderr b/src/test/ui/asm/x86_64/issue-82869.stderr similarity index 100% rename from src/test/ui/asm/issue-82869.stderr rename to src/test/ui/asm/x86_64/issue-82869.stderr diff --git a/src/test/ui/asm/parse-error.rs b/src/test/ui/asm/x86_64/parse-error.rs similarity index 95% rename from src/test/ui/asm/parse-error.rs rename to src/test/ui/asm/x86_64/parse-error.rs index 3ec3c72d38..fa14c52cf0 100644 --- a/src/test/ui/asm/parse-error.rs +++ b/src/test/ui/asm/x86_64/parse-error.rs @@ -76,6 +76,12 @@ fn main() { //~^ ERROR asm template must be a string literal asm!("{1}", format!("{{{}}}", 0), in(reg) foo, out(reg) bar); //~^ ERROR asm template must be a string literal + asm!("{}", in(reg) _); + //~^ ERROR _ cannot be used for input operands + asm!("{}", inout(reg) _); + //~^ ERROR _ cannot be used for input operands + asm!("{}", inlateout(reg) _); + //~^ ERROR _ cannot be used for input operands } } diff --git a/src/test/ui/asm/parse-error.stderr b/src/test/ui/asm/x86_64/parse-error.stderr similarity index 91% rename from src/test/ui/asm/parse-error.stderr rename to src/test/ui/asm/x86_64/parse-error.stderr index 423003c99d..91a6baa4af 100644 --- a/src/test/ui/asm/parse-error.stderr +++ b/src/test/ui/asm/x86_64/parse-error.stderr @@ -2,7 +2,7 @@ error: requires at least a template string argument --> $DIR/parse-error.rs:9:9 | LL | asm!(); - | ^^^^^^^ + | ^^^^^^ error: asm template must be a string literal --> $DIR/parse-error.rs:11:14 @@ -214,62 +214,80 @@ 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 + | +LL | asm!("{}", in(reg) _); + | ^ + +error: _ cannot be used for input operands + --> $DIR/parse-error.rs:81:31 + | +LL | asm!("{}", inout(reg) _); + | ^ + +error: _ cannot be used for input operands + --> $DIR/parse-error.rs:83:35 + | +LL | asm!("{}", inlateout(reg) _); + | ^ + error: requires at least a template string argument - --> $DIR/parse-error.rs:84:1 + --> $DIR/parse-error.rs:90:1 | LL | global_asm!(); - | ^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ error: asm template must be a string literal - --> $DIR/parse-error.rs:86:13 + --> $DIR/parse-error.rs:92:13 | LL | global_asm!(FOO); | ^^^ error: expected token: `,` - --> $DIR/parse-error.rs:88:18 + --> $DIR/parse-error.rs:94:18 | LL | global_asm!("{}" FOO); | ^^^ expected `,` error: expected operand, options, or additional template string - --> $DIR/parse-error.rs:90:19 + --> $DIR/parse-error.rs:96:19 | LL | global_asm!("{}", FOO); | ^^^ expected operand, options, or additional template string error: expected expression, found end of macro arguments - --> $DIR/parse-error.rs:92:24 + --> $DIR/parse-error.rs:98:24 | LL | global_asm!("{}", const); | ^ expected expression error: expected one of `,`, `.`, `?`, or an operator, found `FOO` - --> $DIR/parse-error.rs:94:30 + --> $DIR/parse-error.rs:100: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:96:25 + --> $DIR/parse-error.rs:102: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:98:25 + --> $DIR/parse-error.rs:104: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:100:25 + --> $DIR/parse-error.rs:106: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:102:30 + --> $DIR/parse-error.rs:108:30 | LL | global_asm!("{}", options(), const FOO); | --------- ^^^^^^^^^ argument @@ -277,25 +295,25 @@ LL | global_asm!("{}", options(), const FOO); | previous options error: expected string literal - --> $DIR/parse-error.rs:104:29 + --> $DIR/parse-error.rs:110:29 | LL | global_asm!("", clobber_abi(FOO)); | ^^^ not a string literal error: expected `)`, found `FOO` - --> $DIR/parse-error.rs:106:33 + --> $DIR/parse-error.rs:112:33 | LL | global_asm!("", clobber_abi("C" FOO)); | ^^^ expected `)` error: expected `)`, found `,` - --> $DIR/parse-error.rs:108:32 + --> $DIR/parse-error.rs:114:32 | LL | global_asm!("", clobber_abi("C", FOO)); | ^ expected `)` error: arguments are not allowed after clobber_abi - --> $DIR/parse-error.rs:110:37 + --> $DIR/parse-error.rs:116:37 | LL | global_asm!("{}", clobber_abi("C"), const FOO); | ---------------- ^^^^^^^^^ argument @@ -303,13 +321,13 @@ LL | global_asm!("{}", clobber_abi("C"), const FOO); | clobber_abi error: `clobber_abi` cannot be used with `global_asm!` - --> $DIR/parse-error.rs:110:19 + --> $DIR/parse-error.rs:116:19 | LL | global_asm!("{}", clobber_abi("C"), const FOO); | ^^^^^^^^^^^^^^^^ error: clobber_abi is not allowed after options - --> $DIR/parse-error.rs:113:28 + --> $DIR/parse-error.rs:119:28 | LL | global_asm!("", options(), clobber_abi("C")); | --------- ^^^^^^^^^^^^^^^^ @@ -317,7 +335,7 @@ LL | global_asm!("", options(), clobber_abi("C")); | options error: clobber_abi is not allowed after options - --> $DIR/parse-error.rs:115:30 + --> $DIR/parse-error.rs:121:30 | LL | global_asm!("{}", options(), clobber_abi("C"), const FOO); | --------- ^^^^^^^^^^^^^^^^ @@ -325,7 +343,7 @@ LL | global_asm!("{}", options(), clobber_abi("C"), const FOO); | options error: clobber_abi specified multiple times - --> $DIR/parse-error.rs:117:35 + --> $DIR/parse-error.rs:123:35 | LL | global_asm!("", clobber_abi("C"), clobber_abi("C")); | ---------------- ^^^^^^^^^^^^^^^^ @@ -333,7 +351,7 @@ LL | global_asm!("", clobber_abi("C"), clobber_abi("C")); | clobber_abi previously specified here error: duplicate argument named `a` - --> $DIR/parse-error.rs:119:35 + --> $DIR/parse-error.rs:125:35 | LL | global_asm!("{a}", a = const FOO, a = const BAR); | ------------- ^^^^^^^^^^^^^ duplicate argument @@ -341,7 +359,7 @@ LL | global_asm!("{a}", a = const FOO, a = const BAR); | previously here error: argument never used - --> $DIR/parse-error.rs:119:35 + --> $DIR/parse-error.rs:125:35 | LL | global_asm!("{a}", a = const FOO, a = const BAR); | ^^^^^^^^^^^^^ argument never used @@ -349,19 +367,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:122:28 + --> $DIR/parse-error.rs:128: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:124:30 + --> $DIR/parse-error.rs:130: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:126:13 + --> $DIR/parse-error.rs:132:13 | LL | global_asm!(format!("{{{}}}", 0), const FOO); | ^^^^^^^^^^^^^^^^^^^^ @@ -369,7 +387,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:128:20 + --> $DIR/parse-error.rs:134:20 | LL | global_asm!("{1}", format!("{{{}}}", 0), const FOO, const BAR); | ^^^^^^^^^^^^^^^^^^^^ @@ -439,6 +457,6 @@ LL | let mut bar = 0; LL | asm!("{1}", in("eax") foo, const bar); | ^^^ non-constant value -error: aborting due to 63 previous errors +error: aborting due to 66 previous errors For more information about this error, try `rustc --explain E0435`. diff --git a/src/test/ui/asm/srcloc.rs b/src/test/ui/asm/x86_64/srcloc.rs similarity index 100% rename from src/test/ui/asm/srcloc.rs rename to src/test/ui/asm/x86_64/srcloc.rs diff --git a/src/test/ui/asm/srcloc.stderr b/src/test/ui/asm/x86_64/srcloc.stderr similarity index 100% rename from src/test/ui/asm/srcloc.stderr rename to src/test/ui/asm/x86_64/srcloc.stderr diff --git a/src/test/ui/asm/sym.rs b/src/test/ui/asm/x86_64/sym.rs similarity index 100% rename from src/test/ui/asm/sym.rs rename to src/test/ui/asm/x86_64/sym.rs diff --git a/src/test/ui/asm/x86_64/target-feature-attr.rs b/src/test/ui/asm/x86_64/target-feature-attr.rs new file mode 100644 index 0000000000..4f82cd8aab --- /dev/null +++ b/src/test/ui/asm/x86_64/target-feature-attr.rs @@ -0,0 +1,40 @@ +// only-x86_64 + +#![feature(asm, avx512_target_feature)] + +#[target_feature(enable = "avx")] +unsafe fn foo() { + let mut x = 1; + let y = 2; + asm!("vaddps {2:y}, {0:y}, {1:y}", in(ymm_reg) x, in(ymm_reg) y, lateout(ymm_reg) x); + assert_eq!(x, 3); +} + +unsafe fn bar() { + let mut x = 1; + let y = 2; + asm!("vaddps {2:y}, {0:y}, {1:y}", in(ymm_reg) x, in(ymm_reg) y, lateout(ymm_reg) x); + //~^ ERROR: register class `ymm_reg` requires the `avx` target feature + //~| ERROR: register class `ymm_reg` requires the `avx` target feature + //~| ERROR: register class `ymm_reg` requires the `avx` target feature + assert_eq!(x, 3); +} + +#[target_feature(enable = "avx512bw")] +unsafe fn baz() { + let x = 1; + asm!("/* {0} */", in(kreg) x); +} + +unsafe fn baz2() { + let x = 1; + asm!("/* {0} */", in(kreg) x); + //~^ ERROR: register class `kreg` requires at least one of the following target features: avx512bw, avx512f +} + +fn main() { + unsafe { + foo(); + bar(); + } +} diff --git a/src/test/ui/asm/x86_64/target-feature-attr.stderr b/src/test/ui/asm/x86_64/target-feature-attr.stderr new file mode 100644 index 0000000000..295c8a97ed --- /dev/null +++ b/src/test/ui/asm/x86_64/target-feature-attr.stderr @@ -0,0 +1,26 @@ +error: register class `ymm_reg` requires the `avx` target feature + --> $DIR/target-feature-attr.rs:16:40 + | +LL | asm!("vaddps {2:y}, {0:y}, {1:y}", in(ymm_reg) x, in(ymm_reg) y, lateout(ymm_reg) x); + | ^^^^^^^^^^^^^ + +error: register class `ymm_reg` requires the `avx` target feature + --> $DIR/target-feature-attr.rs:16:55 + | +LL | asm!("vaddps {2:y}, {0:y}, {1:y}", in(ymm_reg) x, in(ymm_reg) y, lateout(ymm_reg) x); + | ^^^^^^^^^^^^^ + +error: register class `ymm_reg` requires the `avx` target feature + --> $DIR/target-feature-attr.rs:16:70 + | +LL | asm!("vaddps {2:y}, {0:y}, {1:y}", in(ymm_reg) x, in(ymm_reg) y, lateout(ymm_reg) x); + | ^^^^^^^^^^^^^^^^^^ + +error: register class `kreg` requires at least one of the following target features: avx512bw, avx512f + --> $DIR/target-feature-attr.rs:31:23 + | +LL | asm!("/* {0} */", in(kreg) x); + | ^^^^^^^^^^ + +error: aborting due to 4 previous errors + diff --git a/src/test/ui/asm/type-check-2.rs b/src/test/ui/asm/x86_64/type-check-2.rs similarity index 93% rename from src/test/ui/asm/type-check-2.rs rename to src/test/ui/asm/x86_64/type-check-2.rs index c70a880281..2311f86d34 100644 --- a/src/test/ui/asm/type-check-2.rs +++ b/src/test/ui/asm/x86_64/type-check-2.rs @@ -26,10 +26,6 @@ fn main() { asm!("{}", inout(reg) v[0]); //~^ ERROR cannot borrow `v` as mutable, as it is not declared as mutable - // This currently causes an ICE: https://github.com/rust-lang/rust/issues/81857 - // asm!("{}", const &0); - // ERROR asm `const` arguments must be integer or floating-point values - // Sym operands must point to a function or static const C: i32 = 0; diff --git a/src/test/ui/asm/type-check-2.stderr b/src/test/ui/asm/x86_64/type-check-2.stderr similarity index 91% rename from src/test/ui/asm/type-check-2.stderr rename to src/test/ui/asm/x86_64/type-check-2.stderr index 1354a9dd84..9e73c9a8d6 100644 --- a/src/test/ui/asm/type-check-2.stderr +++ b/src/test/ui/asm/x86_64/type-check-2.stderr @@ -1,13 +1,13 @@ error: arguments for inline assembly must be copyable - --> $DIR/type-check-2.rs:46:32 + --> $DIR/type-check-2.rs:42:32 | LL | asm!("{}", in(xmm_reg) SimdNonCopy(0.0, 0.0, 0.0, 0.0)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `SimdNonCopy` does not implement the Copy trait -error: cannot use value of type `[closure@$DIR/type-check-2.rs:58:28: 58:38]` for inline assembly - --> $DIR/type-check-2.rs:58:28 +error: cannot use value of type `[closure@$DIR/type-check-2.rs:54:28: 54:38]` for inline assembly + --> $DIR/type-check-2.rs:54:28 | LL | asm!("{}", in(reg) |x: i32| x); | ^^^^^^^^^^ @@ -15,7 +15,7 @@ LL | asm!("{}", in(reg) |x: i32| x); = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly error: cannot use value of type `Vec` for inline assembly - --> $DIR/type-check-2.rs:60:28 + --> $DIR/type-check-2.rs:56:28 | LL | asm!("{}", in(reg) vec![0]); | ^^^^^^^ @@ -24,7 +24,7 @@ LL | asm!("{}", in(reg) vec![0]); = note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info) error: cannot use value of type `(i32, i32, i32)` for inline assembly - --> $DIR/type-check-2.rs:62:28 + --> $DIR/type-check-2.rs:58:28 | LL | asm!("{}", in(reg) (1, 2, 3)); | ^^^^^^^^^ @@ -32,7 +32,7 @@ LL | asm!("{}", in(reg) (1, 2, 3)); = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly error: cannot use value of type `[i32; 3]` for inline assembly - --> $DIR/type-check-2.rs:64:28 + --> $DIR/type-check-2.rs:60:28 | LL | asm!("{}", in(reg) [1, 2, 3]); | ^^^^^^^^^ @@ -40,7 +40,7 @@ LL | asm!("{}", in(reg) [1, 2, 3]); = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly error: cannot use value of type `fn() {main}` for inline assembly - --> $DIR/type-check-2.rs:72:31 + --> $DIR/type-check-2.rs:68:31 | LL | asm!("{}", inout(reg) f); | ^ @@ -48,7 +48,7 @@ LL | asm!("{}", inout(reg) f); = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly error: cannot use value of type `&mut i32` for inline assembly - --> $DIR/type-check-2.rs:75:31 + --> $DIR/type-check-2.rs:71:31 | LL | asm!("{}", inout(reg) r); | ^ @@ -56,13 +56,13 @@ LL | asm!("{}", inout(reg) r); = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly error: asm `sym` operand must point to a fn or static - --> $DIR/type-check-2.rs:39:24 + --> $DIR/type-check-2.rs:35:24 | LL | asm!("{}", sym C); | ^ error: asm `sym` operand must point to a fn or static - --> $DIR/type-check-2.rs:41:24 + --> $DIR/type-check-2.rs:37:24 | LL | asm!("{}", sym x); | ^ @@ -77,7 +77,7 @@ error[E0381]: use of possibly-uninitialized variable: `y` --> $DIR/type-check-2.rs:16:9 | LL | asm!("{}", inout(reg) y); - | ^^^^^^^^^^^^^^^^^^^^^^^^^ use of possibly-uninitialized `y` + | ^^^^^^^^^^^^^^^^^^^^^^^^ use of possibly-uninitialized `y` error[E0596]: cannot borrow `v` as mutable, as it is not declared as mutable --> $DIR/type-check-2.rs:24:29 diff --git a/src/test/ui/asm/type-check-3.rs b/src/test/ui/asm/x86_64/type-check-3.rs similarity index 100% rename from src/test/ui/asm/type-check-3.rs rename to src/test/ui/asm/x86_64/type-check-3.rs diff --git a/src/test/ui/asm/type-check-3.stderr b/src/test/ui/asm/x86_64/type-check-3.stderr similarity index 100% rename from src/test/ui/asm/type-check-3.stderr rename to src/test/ui/asm/x86_64/type-check-3.stderr diff --git a/src/test/ui/assignment-operator-unimplemented.stderr b/src/test/ui/assignment-operator-unimplemented.stderr index 5304b09de5..73c9f86e00 100644 --- a/src/test/ui/assignment-operator-unimplemented.stderr +++ b/src/test/ui/assignment-operator-unimplemented.stderr @@ -6,7 +6,22 @@ LL | a += *b; | | | cannot use `+=` on type `Foo` | - = note: an implementation of `std::ops::AddAssign` might be missing for `Foo` +note: an implementation of `AddAssign<_>` might be missing for `Foo` + --> $DIR/assignment-operator-unimplemented.rs:1:1 + | +LL | struct Foo; + | ^^^^^^^^^^^ must implement `AddAssign<_>` +note: the following trait must be implemented + --> $SRC_DIR/core/src/ops/arith.rs:LL:COL + | +LL | / pub trait AddAssign { +LL | | /// Performs the `+=` operation. +LL | | /// +LL | | /// # Example +... | +LL | | fn add_assign(&mut self, rhs: Rhs); +LL | | } + | |_^ error: aborting due to previous error diff --git a/src/test/ui/associated-consts/associated-const-ambiguity-report.stderr b/src/test/ui/associated-consts/associated-const-ambiguity-report.stderr index d4c12b8e06..60cf9a533c 100644 --- a/src/test/ui/associated-consts/associated-const-ambiguity-report.stderr +++ b/src/test/ui/associated-consts/associated-const-ambiguity-report.stderr @@ -16,12 +16,12 @@ LL | const ID: i32 = 3; | ^^^^^^^^^^^^^^^^^^ help: disambiguate the associated constant for candidate #1 | -LL | const X: i32 = Foo::ID; - | ~~~~~ +LL | const X: i32 = ::ID; + | ~~~~~~~~~~~~~~ help: disambiguate the associated constant for candidate #2 | -LL | const X: i32 = Bar::ID; - | ~~~~~ +LL | const X: i32 = ::ID; + | ~~~~~~~~~~~~~~ error: aborting due to previous error diff --git a/src/test/ui/associated-consts/associated-const-impl-wrong-lifetime.stderr b/src/test/ui/associated-consts/associated-const-impl-wrong-lifetime.stderr index 0cce10b54a..f71fb2ee18 100644 --- a/src/test/ui/associated-consts/associated-const-impl-wrong-lifetime.stderr +++ b/src/test/ui/associated-consts/associated-const-impl-wrong-lifetime.stderr @@ -6,7 +6,7 @@ LL | const NAME: &'a str = "unit"; | = note: expected reference `&'static str` found reference `&'a str` -note: the lifetime `'a` as defined on the impl at 6:6... +note: the lifetime `'a` as defined here... --> $DIR/associated-const-impl-wrong-lifetime.rs:6:6 | LL | impl<'a> Foo for &'a () { diff --git a/src/test/ui/associated-consts/associated-const-in-trait.stderr b/src/test/ui/associated-consts/associated-const-in-trait.stderr index 7b45941082..fc949f2494 100644 --- a/src/test/ui/associated-consts/associated-const-in-trait.stderr +++ b/src/test/ui/associated-consts/associated-const-in-trait.stderr @@ -4,7 +4,6 @@ error[E0038]: the trait `Trait` cannot be made into an object LL | impl dyn Trait { | ^^^^^^^^^ `Trait` cannot be made into an object | - = help: consider moving `N` to another trait note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit --> $DIR/associated-const-in-trait.rs:6:11 | @@ -12,6 +11,7 @@ LL | trait Trait { | ----- this trait cannot be made into an object... LL | const N: usize; | ^ ...because it contains this associated `const` + = help: consider moving `N` to another trait error: aborting due to previous error diff --git a/src/test/ui/associated-consts/defaults-not-assumed-fail.stderr b/src/test/ui/associated-consts/defaults-not-assumed-fail.stderr index 984a8713c9..7406b2ddee 100644 --- a/src/test/ui/associated-consts/defaults-not-assumed-fail.stderr +++ b/src/test/ui/associated-consts/defaults-not-assumed-fail.stderr @@ -20,7 +20,7 @@ error: erroneous constant used --> $DIR/defaults-not-assumed-fail.rs:34:5 | LL | assert_eq!(<() as Tr>::B, 0); // causes the error above - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors | = warning: this was previously accepted 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 diff --git a/src/test/ui/associated-item/issue-48027.stderr b/src/test/ui/associated-item/issue-48027.stderr index 77915a80a7..7b158f1d75 100644 --- a/src/test/ui/associated-item/issue-48027.stderr +++ b/src/test/ui/associated-item/issue-48027.stderr @@ -21,7 +21,6 @@ error[E0038]: the trait `Bar` cannot be made into an object LL | impl dyn Bar {} | ^^^^^^^ `Bar` cannot be made into an object | - = help: consider moving `X` to another trait note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit --> $DIR/issue-48027.rs:2:11 | @@ -29,6 +28,7 @@ LL | trait Bar { | --- this trait cannot be made into an object... LL | const X: usize; | ^ ...because it contains this associated `const` + = help: consider moving `X` to another trait error: aborting due to 2 previous errors diff --git a/src/test/ui/associated-type-bounds/super-trait-referencing-self.rs b/src/test/ui/associated-type-bounds/supertrait-referencing-self.rs similarity index 100% rename from src/test/ui/associated-type-bounds/super-trait-referencing-self.rs rename to src/test/ui/associated-type-bounds/supertrait-referencing-self.rs diff --git a/src/test/ui/associated-type-bounds/super-trait-referencing.rs b/src/test/ui/associated-type-bounds/supertrait-referencing.rs similarity index 100% rename from src/test/ui/associated-type-bounds/super-trait-referencing.rs rename to src/test/ui/associated-type-bounds/supertrait-referencing.rs diff --git a/src/test/ui/associated-type-bounds/super-trait-where-referencing-self.rs b/src/test/ui/associated-type-bounds/supertrait-where-referencing-self.rs similarity index 100% rename from src/test/ui/associated-type-bounds/super-trait-where-referencing-self.rs rename to src/test/ui/associated-type-bounds/supertrait-where-referencing-self.rs diff --git a/src/test/ui/associated-type-bounds/traits-assoc-type-macros.rs b/src/test/ui/associated-type-bounds/traits-assoc-type-macros.rs index ad5c6aed97..d854dce382 100644 --- a/src/test/ui/associated-type-bounds/traits-assoc-type-macros.rs +++ b/src/test/ui/associated-type-bounds/traits-assoc-type-macros.rs @@ -1,5 +1,5 @@ // check-pass -// compile-flags:-Cincremental=tmp/traits-assoc-type-macros +// incremental // This test case makes sure that we can compile with incremental compilation // enabled when there are macros, traits, inheritance and associated types involved. diff --git a/src/test/ui/associated-types/associated-type-projection-ambig-between-bound-and-where-clause.stderr b/src/test/ui/associated-types/associated-type-projection-ambig-between-bound-and-where-clause.stderr index 474b3c5c71..19fc2f652c 100644 --- a/src/test/ui/associated-types/associated-type-projection-ambig-between-bound-and-where-clause.stderr +++ b/src/test/ui/associated-types/associated-type-projection-ambig-between-bound-and-where-clause.stderr @@ -13,11 +13,11 @@ LL | fn a(_: C::Color) { help: use fully qualified syntax to disambiguate | LL | fn a(_: ::Color) { - | ~~~~~~~~~~~~~~~~~ + | ~~~~~~~~~~~~ help: use fully qualified syntax to disambiguate | LL | fn a(_: ::Color) { - | ~~~~~~~~~~~~~~~~~~~~~ + | ~~~~~~~~~~~~~~~~ error[E0221]: ambiguous associated type `Color` in bounds of `C` --> $DIR/associated-type-projection-ambig-between-bound-and-where-clause.rs:20:12 @@ -34,11 +34,11 @@ LL | fn b(_: C::Color) where C : Vehicle+Box { help: use fully qualified syntax to disambiguate | LL | fn b(_: ::Color) where C : Vehicle+Box { - | ~~~~~~~~~~~~~~~~~ + | ~~~~~~~~~~~~ help: use fully qualified syntax to disambiguate | LL | fn b(_: ::Color) where C : Vehicle+Box { - | ~~~~~~~~~~~~~~~~~~~~~ + | ~~~~~~~~~~~~~~~~ error[E0221]: ambiguous associated type `Color` in bounds of `C` --> $DIR/associated-type-projection-ambig-between-bound-and-where-clause.rs:24:12 @@ -55,11 +55,11 @@ LL | fn c(_: C::Color) where C : Vehicle, C : Box { help: use fully qualified syntax to disambiguate | LL | fn c(_: ::Color) where C : Vehicle, C : Box { - | ~~~~~~~~~~~~~~~~~ + | ~~~~~~~~~~~~ help: use fully qualified syntax to disambiguate | LL | fn c(_: ::Color) where C : Vehicle, C : Box { - | ~~~~~~~~~~~~~~~~~~~~~ + | ~~~~~~~~~~~~~~~~ error[E0221]: ambiguous associated type `Color` in bounds of `X` --> $DIR/associated-type-projection-ambig-between-bound-and-where-clause.rs:35:20 @@ -76,11 +76,11 @@ LL | fn e(&self, _: X::Color) where X : Box; help: use fully qualified syntax to disambiguate | LL | fn e(&self, _: ::Color) where X : Box; - | ~~~~~~~~~~~~~~~~~ + | ~~~~~~~~~~~~ help: use fully qualified syntax to disambiguate | LL | fn e(&self, _: ::Color) where X : Box; - | ~~~~~~~~~~~~~~~~~~~~~ + | ~~~~~~~~~~~~~~~~ error[E0221]: ambiguous associated type `Color` in bounds of `X` --> $DIR/associated-type-projection-ambig-between-bound-and-where-clause.rs:38:20 @@ -97,11 +97,11 @@ LL | fn f(&self, _: X::Color) where X : Box { } help: use fully qualified syntax to disambiguate | LL | fn f(&self, _: ::Color) where X : Box { } - | ~~~~~~~~~~~~~~~~~ + | ~~~~~~~~~~~~ help: use fully qualified syntax to disambiguate | LL | fn f(&self, _: ::Color) where X : Box { } - | ~~~~~~~~~~~~~~~~~~~~~ + | ~~~~~~~~~~~~~~~~ error[E0221]: ambiguous associated type `Color` in bounds of `X` --> $DIR/associated-type-projection-ambig-between-bound-and-where-clause.rs:30:20 @@ -118,11 +118,11 @@ LL | fn d(&self, _: X::Color) where X : Box { } help: use fully qualified syntax to disambiguate | LL | fn d(&self, _: ::Color) where X : Box { } - | ~~~~~~~~~~~~~~~~~ + | ~~~~~~~~~~~~ help: use fully qualified syntax to disambiguate | LL | fn d(&self, _: ::Color) where X : Box { } - | ~~~~~~~~~~~~~~~~~~~~~ + | ~~~~~~~~~~~~~~~~ error: aborting due to 6 previous errors diff --git a/src/test/ui/associated-types/associated-type-projection-from-multiple-supertraits.stderr b/src/test/ui/associated-types/associated-type-projection-from-multiple-supertraits.stderr index e6e95336bb..66a4899c77 100644 --- a/src/test/ui/associated-types/associated-type-projection-from-multiple-supertraits.stderr +++ b/src/test/ui/associated-types/associated-type-projection-from-multiple-supertraits.stderr @@ -21,11 +21,11 @@ LL | fn dent(c: C, color: C::Color) { help: use fully qualified syntax to disambiguate | LL | fn dent(c: C, color: ::Color) { - | ~~~~~~~~~~~~~~~~~~~~~ + | ~~~~~~~~~~~~~~~~ help: use fully qualified syntax to disambiguate | LL | fn dent(c: C, color: ::Color) { - | ~~~~~~~~~~~~~~~~~ + | ~~~~~~~~~~~~ error[E0222]: ambiguous associated type `Color` in bounds of `BoxCar` --> $DIR/associated-type-projection-from-multiple-supertraits.rs:23:37 @@ -74,11 +74,11 @@ LL | fn paint(c: C, d: C::Color) { help: use fully qualified syntax to disambiguate | LL | fn paint(c: C, d: ::Color) { - | ~~~~~~~~~~~~~~~~~~~~~ + | ~~~~~~~~~~~~~~~~ help: use fully qualified syntax to disambiguate | LL | fn paint(c: C, d: ::Color) { - | ~~~~~~~~~~~~~~~~~ + | ~~~~~~~~~~~~ error[E0191]: the value of the associated types `Color` (from trait `Box`), `Color` (from trait `Vehicle`) must be specified --> $DIR/associated-type-projection-from-multiple-supertraits.rs:32:32 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 edcd2bf85a..e66c6b35ca 100644 --- a/src/test/ui/associated-types/associated-types-bound-failure.stderr +++ b/src/test/ui/associated-types/associated-types-bound-failure.stderr @@ -2,7 +2,9 @@ error[E0277]: the trait bound `::R: ToInt` is not satisfied --> $DIR/associated-types-bound-failure.rs:19:19 | LL | ToInt::to_int(&g.get()) - | ^^^^^^^^ the trait `ToInt` is not implemented for `::R` + | ------------- ^^^^^^^^ the trait `ToInt` is not implemented for `::R` + | | + | required by a bound introduced by this call | note: required by `ToInt::to_int` --> $DIR/associated-types-bound-failure.rs:6:5 diff --git a/src/test/ui/associated-types/associated-types-doubleendediterator-object.rs b/src/test/ui/associated-types/associated-types-doubleendediterator-object.rs index 96ba2ee3b6..05498ba63e 100644 --- a/src/test/ui/associated-types/associated-types-doubleendediterator-object.rs +++ b/src/test/ui/associated-types/associated-types-doubleendediterator-object.rs @@ -1,5 +1,4 @@ // run-pass -#![feature(box_syntax)] fn pairwise_sub(mut t: Box>) -> isize { let mut result = 0; diff --git a/src/test/ui/associated-types/associated-types-path-1.stderr b/src/test/ui/associated-types/associated-types-path-1.stderr index 8f94b24e7b..6512d60b2c 100644 --- a/src/test/ui/associated-types/associated-types-path-1.stderr +++ b/src/test/ui/associated-types/associated-types-path-1.stderr @@ -19,11 +19,11 @@ LL | pub fn f2(a: T, x: T::A) {} help: use fully qualified syntax to disambiguate | LL | pub fn f2(a: T, x: ::A) {} - | ~~~~~~~~~~~~~ + | ~~~~~~~~~~~~ help: use fully qualified syntax to disambiguate | LL | pub fn f2(a: T, x: ::A) {} - | ~~~~~~~~~~~~~ + | ~~~~~~~~~~~~ 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 c993e1d272..912dedfdce 100644 --- a/src/test/ui/associated-types/associated-types-path-2.rs +++ b/src/test/ui/associated-types/associated-types-path-2.rs @@ -28,13 +28,11 @@ 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 c4ea4ae6bc..15a5245d54 100644 --- a/src/test/ui/associated-types/associated-types-path-2.stderr +++ b/src/test/ui/associated-types/associated-types-path-2.stderr @@ -7,13 +7,15 @@ LL | f1(2i32, 4i32); help: change the type of the numeric literal from `i32` to `u32` | LL | f1(2i32, 4u32); - | ~~~~ + | ~~~ error[E0277]: the trait bound `u32: Foo` is not satisfied - --> $DIR/associated-types-path-2.rs:29:5 + --> $DIR/associated-types-path-2.rs:29:14 | LL | f1(2u32, 4u32); - | ^^ the trait `Foo` is not implemented for `u32` + | -- ^^^^ the trait `Foo` is not implemented for `u32` + | | + | required by a bound introduced by this call | note: required by a bound in `f1` --> $DIR/associated-types-path-2.rs:13:14 @@ -22,16 +24,12 @@ LL | pub fn f1(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:29:5 - | -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:5 + --> $DIR/associated-types-path-2.rs:34:14 | 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 | note: required by a bound in `f1` --> $DIR/associated-types-path-2.rs:13:14 @@ -39,14 +37,8 @@ note: required by a bound in `f1` LL | pub fn f1(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:5 - | -LL | f1(2u32, 4i32); - | ^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `u32` - error[E0308]: mismatched types - --> $DIR/associated-types-path-2.rs:41:18 + --> $DIR/associated-types-path-2.rs:39:18 | LL | let _: i32 = f2(2i32); | --- ^^^^^^^^ expected `i32`, found `u32` @@ -56,9 +48,9 @@ LL | let _: i32 = f2(2i32); help: you can convert a `u32` to an `i32` and panic if the converted value doesn't fit | LL | let _: i32 = f2(2i32).try_into().unwrap(); - | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ -error: aborting due to 6 previous errors +error: aborting due to 4 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-project-from-hrtb-in-fn.stderr b/src/test/ui/associated-types/associated-types-project-from-hrtb-in-fn.stderr index 989624bdd9..c508006c3a 100644 --- a/src/test/ui/associated-types/associated-types-project-from-hrtb-in-fn.stderr +++ b/src/test/ui/associated-types/associated-types-project-from-hrtb-in-fn.stderr @@ -2,7 +2,12 @@ error[E0212]: cannot use the associated type of a trait with uninferred generic --> $DIR/associated-types-project-from-hrtb-in-fn.rs:13:8 | LL | x: I::A) - | ^^^^ help: use a fully qualified path with inferred lifetimes: `>::A` + | ^^^^ + | +help: use a fully qualified path with inferred lifetimes + | +LL | x: >::A) + | ~~~~~~~~~~~~~~~~~~~~ error: aborting due to previous error diff --git a/src/test/ui/associated-types/associated-types-project-from-hrtb-in-trait-method.stderr b/src/test/ui/associated-types/associated-types-project-from-hrtb-in-trait-method.stderr index d457f9f846..48433b1528 100644 --- a/src/test/ui/associated-types/associated-types-project-from-hrtb-in-trait-method.stderr +++ b/src/test/ui/associated-types/associated-types-project-from-hrtb-in-trait-method.stderr @@ -2,13 +2,23 @@ error[E0212]: cannot use the associated type of a trait with uninferred generic --> $DIR/associated-types-project-from-hrtb-in-trait-method.rs:13:32 | LL | fn some_method(&self, arg: I::A); - | ^^^^ help: use a fully qualified path with inferred lifetimes: `>::A` + | ^^^^ + | +help: use a fully qualified path with inferred lifetimes + | +LL | fn some_method(&self, arg: >::A); + | ~~~~~~~~~~~~~~~~~~~~ error[E0212]: cannot use the associated type of a trait with uninferred generic parameters --> $DIR/associated-types-project-from-hrtb-in-trait-method.rs:32:24 | LL | fn mango(&self) -> X::Assoc { - | ^^^^^^^^ help: use a fully qualified path with inferred lifetimes: `>::Assoc` + | ^^^^^^^^ + | +help: use a fully qualified path with inferred lifetimes + | +LL | fn mango(&self) -> >::Assoc { + | ~~~~~~~~~~~~~~~~~~~ error: aborting due to 2 previous errors diff --git a/src/test/ui/associated-types/cache/project-fn-ret-contravariant.transmute.nll.stderr b/src/test/ui/associated-types/cache/project-fn-ret-contravariant.transmute.nll.stderr index 558f394ef8..f532c96ed2 100644 --- a/src/test/ui/associated-types/cache/project-fn-ret-contravariant.transmute.nll.stderr +++ b/src/test/ui/associated-types/cache/project-fn-ret-contravariant.transmute.nll.stderr @@ -5,8 +5,6 @@ LL | fn baz<'a,'b>(x: &'a u32) -> &'static u32 { | -- lifetime `'a` defined here LL | bar(foo, x) | ^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static` - | - = help: consider replacing `'a` with `'static` error: aborting due to previous error diff --git a/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.nll.stderr b/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.nll.stderr index db82c9fd43..c417cdd543 100644 --- a/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.nll.stderr +++ b/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.nll.stderr @@ -6,8 +6,6 @@ LL | fn baz<'a, 'b>(x: Type<'a>) -> Type<'static> { ... LL | bar(foo, x) | ^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static` - | - = help: consider replacing `'a` with `'static` error: aborting due to previous error diff --git a/src/test/ui/associated-types/higher-ranked-projection.bad.nll.stderr b/src/test/ui/associated-types/higher-ranked-projection.bad.nll.stderr index e3bd0c2276..de254b7a16 100644 --- a/src/test/ui/associated-types/higher-ranked-projection.bad.nll.stderr +++ b/src/test/ui/associated-types/higher-ranked-projection.bad.nll.stderr @@ -6,6 +6,11 @@ LL | foo(()); | = note: expected reference `&'a ()` found reference `&()` +note: the lifetime requirement is introduced here + --> $DIR/higher-ranked-projection.rs:15:33 + | +LL | where for<'a> &'a T: Mirror + | ^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/associated-types/hr-associated-type-bound-2.stderr b/src/test/ui/associated-types/hr-associated-type-bound-2.stderr index 079989f233..fe9b4d630b 100644 --- a/src/test/ui/associated-types/hr-associated-type-bound-2.stderr +++ b/src/test/ui/associated-types/hr-associated-type-bound-2.stderr @@ -9,7 +9,7 @@ LL | | type U = str; LL | | } | |_^ | - = help: consider adding a `#![recursion_limit="256"]` attribute to your crate (`hr_associated_type_bound_2`) + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`hr_associated_type_bound_2`) note: required because of the requirements on the impl of `for<'b> X<'b>` for `u32` --> $DIR/hr-associated-type-bound-2.rs:11:6 | @@ -24,7 +24,7 @@ error[E0275]: overflow evaluating the requirement `for<'b> u32: X<'b>` LL | type U = str; | ^^^^^^^^^^^^^ | - = help: consider adding a `#![recursion_limit="256"]` attribute to your crate (`hr_associated_type_bound_2`) + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`hr_associated_type_bound_2`) note: required because of the requirements on the impl of `for<'b> X<'b>` for `u32` --> $DIR/hr-associated-type-bound-2.rs:11:6 | diff --git a/src/test/ui/associated-types/impl-wf-cycle-1.stderr b/src/test/ui/associated-types/impl-wf-cycle-1.stderr index 1d8d2b0149..73167d0831 100644 --- a/src/test/ui/associated-types/impl-wf-cycle-1.stderr +++ b/src/test/ui/associated-types/impl-wf-cycle-1.stderr @@ -15,7 +15,7 @@ note: required because of the requirements on the impl of `Grault` for `(T,)` | LL | impl Grault for (T,) | ^^^^^^ ^^^^ - = note: 1 redundant requirements hidden + = note: 1 redundant requirement hidden = note: required because of the requirements on the impl of `Grault` for `(T,)` error[E0275]: overflow evaluating the requirement `<(T,) as Grault>::A == _` @@ -29,7 +29,7 @@ note: required because of the requirements on the impl of `Grault` for `(T,)` | LL | impl Grault for (T,) | ^^^^^^ ^^^^ - = note: 1 redundant requirements hidden + = note: 1 redundant requirement hidden = note: required because of the requirements on the impl of `Grault` for `(T,)` error[E0275]: overflow evaluating the requirement `<(T,) as Grault>::A == _` @@ -43,7 +43,7 @@ note: required because of the requirements on the impl of `Grault` for `(T,)` | LL | impl Grault for (T,) | ^^^^^^ ^^^^ - = note: 1 redundant requirements hidden + = note: 1 redundant requirement hidden = note: required because of the requirements on the impl of `Grault` for `(T,)` error: aborting due to 3 previous errors diff --git a/src/test/ui/issues/issue-19883.rs b/src/test/ui/associated-types/issue-19883.rs similarity index 100% rename from src/test/ui/issues/issue-19883.rs rename to src/test/ui/associated-types/issue-19883.rs diff --git a/src/test/ui/issues/issue-19883.stderr b/src/test/ui/associated-types/issue-19883.stderr similarity index 100% rename from src/test/ui/issues/issue-19883.stderr rename to src/test/ui/associated-types/issue-19883.stderr diff --git a/src/test/ui/issues/issue-21363.rs b/src/test/ui/associated-types/issue-21363.rs similarity index 100% rename from src/test/ui/issues/issue-21363.rs rename to src/test/ui/associated-types/issue-21363.rs diff --git a/src/test/ui/associated-types/issue-22560.stderr b/src/test/ui/associated-types/issue-22560.stderr index d2193cc4a4..c5c70f226f 100644 --- a/src/test/ui/associated-types/issue-22560.stderr +++ b/src/test/ui/associated-types/issue-22560.stderr @@ -32,7 +32,7 @@ LL | type Test = dyn Add + Sub; | | | first non-auto trait | - = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Add<[type error]> + Sub<[type error]> {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Add<[type error]> + Sub<[type error]> {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error[E0191]: the value of the associated types `Output` (from trait `Add`), `Output` (from trait `Sub`) must be specified diff --git a/src/test/ui/associated-types/issue-27675-unchecked-bounds.stderr b/src/test/ui/associated-types/issue-27675-unchecked-bounds.stderr index e36572740f..22daaf3291 100644 --- a/src/test/ui/associated-types/issue-27675-unchecked-bounds.stderr +++ b/src/test/ui/associated-types/issue-27675-unchecked-bounds.stderr @@ -2,7 +2,9 @@ error[E0277]: the trait bound `T: Copy` is not satisfied --> $DIR/issue-27675-unchecked-bounds.rs:15:31 | LL | copy::>(t) - | ^ the trait `Copy` is not implemented for `T` + | ------------------------- ^ the trait `Copy` is not implemented for `T` + | | + | required by a bound introduced by this call | note: required by a bound in `copy` --> $DIR/issue-27675-unchecked-bounds.rs:10:12 diff --git a/src/test/ui/associated-types/issue-36499.stderr b/src/test/ui/associated-types/issue-36499.stderr index ff450f60ac..610798d880 100644 --- a/src/test/ui/associated-types/issue-36499.stderr +++ b/src/test/ui/associated-types/issue-36499.stderr @@ -1,8 +1,14 @@ -error: expected expression, found `+` +error: leading `+` is not supported --> $DIR/issue-36499.rs:4:9 | LL | 2 + +2; - | ^ expected expression + | ^ unexpected `+` + | +help: try removing the `+` + | +LL - 2 + +2; +LL + 2 + 2; + | error: aborting due to previous error diff --git a/src/test/ui/associated-types/missing-associated-types.stderr b/src/test/ui/associated-types/missing-associated-types.stderr index 340d4e2418..8c52736b02 100644 --- a/src/test/ui/associated-types/missing-associated-types.stderr +++ b/src/test/ui/associated-types/missing-associated-types.stderr @@ -6,7 +6,7 @@ LL | type Foo = dyn Add + Sub + X + Y; | | | first non-auto trait | - = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Add + Sub + X + Y {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Add + Sub + X + Y {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error[E0191]: the value of the associated types `A` (from trait `Y`), `Output` (from trait `Add`), `Output` (from trait `Mul`), `Output` (from trait `Sub`) must be specified @@ -35,7 +35,7 @@ LL | type Bar = dyn Add + Sub + X + Z; | | | first non-auto trait | - = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Add + Sub + X + Z {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Add + Sub + X + Z {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error[E0191]: the value of the associated types `A` (from trait `Z`), `B` (from trait `Z`), `Output` (from trait `Add`), `Output` (from trait `Div`), `Output` (from trait `Div`), `Output` (from trait `Mul`), `Output` (from trait `Sub`) must be specified @@ -71,7 +71,7 @@ LL | type Baz = dyn Add + Sub + Y; | | | first non-auto trait | - = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Add + Sub + Y {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Add + Sub + Y {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error[E0191]: the value of the associated types `A` (from trait `Y`), `Output` (from trait `Add`), `Output` (from trait `Sub`) must be specified @@ -99,7 +99,7 @@ LL | type Bat = dyn Add + Sub + Fine; | | | first non-auto trait | - = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Add + Sub + Fine {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Add + Sub + Fine {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error[E0191]: the value of the associated types `Output` (from trait `Add`), `Output` (from trait `Sub`) must be specified diff --git a/src/test/ui/auxiliary/issue-72470-lib.rs b/src/test/ui/async-await/auxiliary/issue-72470-lib.rs similarity index 100% rename from src/test/ui/auxiliary/issue-72470-lib.rs rename to src/test/ui/async-await/auxiliary/issue-72470-lib.rs diff --git a/src/test/ui/async-await/issue-61452.stderr b/src/test/ui/async-await/issue-61452.stderr index f2dec87baf..2d3bb48e03 100644 --- a/src/test/ui/async-await/issue-61452.stderr +++ b/src/test/ui/async-await/issue-61452.stderr @@ -4,7 +4,7 @@ error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable LL | pub async fn f(x: Option) { | - help: consider changing this to be mutable: `mut x` LL | x.take(); - | ^ cannot borrow as mutable + | ^^^^^^^^ cannot borrow as mutable error[E0384]: cannot assign twice to immutable variable `x` --> $DIR/issue-61452.rs:9:5 diff --git a/src/test/ui/async-await/issue-64130-non-send-future-diags.rs b/src/test/ui/async-await/issue-64130-non-send-future-diags.rs index 656ade67c7..b652d23915 100644 --- a/src/test/ui/async-await/issue-64130-non-send-future-diags.rs +++ b/src/test/ui/async-await/issue-64130-non-send-future-diags.rs @@ -1,4 +1,6 @@ // edition:2018 +#![feature(must_not_suspend)] +#![allow(must_not_suspend)] // This tests the basic example case for the async-await-specific 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 472fffa61b..81e026dc54 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,12 +1,12 @@ error: future cannot be sent between threads safely - --> $DIR/issue-64130-non-send-future-diags.rs:21:5 + --> $DIR/issue-64130-non-send-future-diags.rs:23:5 | LL | is_send(foo()); | ^^^^^^^ future returned by `foo` is not `Send` | = help: within `impl Future`, 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:15:5 + --> $DIR/issue-64130-non-send-future-diags.rs:17:5 | LL | let g = x.lock().unwrap(); | - has type `MutexGuard<'_, u32>` which is not `Send` @@ -15,7 +15,7 @@ LL | baz().await; LL | } | - `g` is later dropped here note: required by a bound in `is_send` - --> $DIR/issue-64130-non-send-future-diags.rs:7:15 + --> $DIR/issue-64130-non-send-future-diags.rs:9:15 | LL | fn is_send(t: T) { } | ^^^^ required by this bound in `is_send` diff --git a/src/test/ui/async-await/issue-71137.rs b/src/test/ui/async-await/issue-71137.rs index ebb392a453..7695e0325f 100644 --- a/src/test/ui/async-await/issue-71137.rs +++ b/src/test/ui/async-await/issue-71137.rs @@ -1,4 +1,6 @@ // edition:2018 +#![feature(must_not_suspend)] +#![allow(must_not_suspend)] use std::future::Future; use std::sync::Mutex; diff --git a/src/test/ui/async-await/issue-71137.stderr b/src/test/ui/async-await/issue-71137.stderr index 8903c09c17..c9a2d7587b 100644 --- a/src/test/ui/async-await/issue-71137.stderr +++ b/src/test/ui/async-await/issue-71137.stderr @@ -1,12 +1,12 @@ error: future cannot be sent between threads safely - --> $DIR/issue-71137.rs:20:3 + --> $DIR/issue-71137.rs:22:3 | LL | fake_spawn(wrong_mutex()); | ^^^^^^^^^^ future returned by `wrong_mutex` is not `Send` | = help: within `impl Future`, 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:12:5 + --> $DIR/issue-71137.rs:14:5 | LL | let mut guard = m.lock().unwrap(); | --------- has type `MutexGuard<'_, i32>` which is not `Send` @@ -16,7 +16,7 @@ LL | *guard += 1; LL | } | - `mut guard` is later dropped here note: required by a bound in `fake_spawn` - --> $DIR/issue-71137.rs:6:27 + --> $DIR/issue-71137.rs:8:27 | LL | fn fake_spawn(f: F) { } | ^^^^ required by this bound in `fake_spawn` diff --git a/src/test/ui/async-await/issue-72442.rs b/src/test/ui/async-await/issue-72442.rs index 61c8c8c159..2280154c71 100644 --- a/src/test/ui/async-await/issue-72442.rs +++ b/src/test/ui/async-await/issue-72442.rs @@ -1,5 +1,5 @@ // edition:2018 -// compile-flags:-Cincremental=tmp/issue-72442 +// incremental use std::fs::File; use std::future::Future; diff --git a/src/test/ui/async-await/issue-72442.stderr b/src/test/ui/async-await/issue-72442.stderr index b79b6bc449..919abf6460 100644 --- a/src/test/ui/async-await/issue-72442.stderr +++ b/src/test/ui/async-await/issue-72442.stderr @@ -2,7 +2,9 @@ error[E0277]: the trait bound `Option<&str>: AsRef` is not satisfied --> $DIR/issue-72442.rs:12:36 | LL | let mut f = File::open(path.to_str())?; - | ^^^^^^^^^^^^^ the trait `AsRef` is not implemented for `Option<&str>` + | ---------- ^^^^^^^^^^^^^ the trait `AsRef` is not implemented for `Option<&str>` + | | + | required by a bound introduced by this call | note: required by a bound in `File::open` --> $SRC_DIR/std/src/fs.rs:LL:COL diff --git a/src/test/ui/issue-72470-llvm-dominate.rs b/src/test/ui/async-await/issue-72470-llvm-dominate.rs similarity index 100% rename from src/test/ui/issue-72470-llvm-dominate.rs rename to src/test/ui/async-await/issue-72470-llvm-dominate.rs diff --git a/src/test/ui/async-await/issue-73541-2.stderr b/src/test/ui/async-await/issue-73541-2.stderr index 495c5f6bf2..4c9741f6f3 100644 --- a/src/test/ui/async-await/issue-73541-2.stderr +++ b/src/test/ui/async-await/issue-73541-2.stderr @@ -8,7 +8,7 @@ LL | continue 'a | ^^ unreachable label `'a` ... LL | b!(); - | ----- in this macro invocation + | ---- in this macro invocation | = note: labels are unreachable through functions, closures, async blocks and modules = note: this error originates in the macro `b` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/async-await/issue-76547.nll.stderr b/src/test/ui/async-await/issue-76547.nll.stderr index 2456d6a147..0ac2a39666 100644 --- a/src/test/ui/async-await/issue-76547.nll.stderr +++ b/src/test/ui/async-await/issue-76547.nll.stderr @@ -1,20 +1,22 @@ error: lifetime may not live long enough - --> $DIR/issue-76547.rs:19:14 + --> $DIR/issue-76547.rs:20:13 | LL | async fn fut(bufs: &mut [&mut [u8]]) { - | ^^^^ - - let's call the lifetime of this reference `'2` - | | | - | | let's call the lifetime of this reference `'1` - | assignment requires that `'1` must outlive `'2` + | - - let's call the lifetime of this reference `'2` + | | + | let's call the lifetime of this reference `'1` +LL | ListFut(bufs).await + | ^^^^ this usage requires that `'1` must outlive `'2` error: lifetime may not live long enough - --> $DIR/issue-76547.rs:33:15 + --> $DIR/issue-76547.rs:34:14 | LL | async fn fut2(bufs: &mut [&mut [u8]]) -> i32 { - | ^^^^ - - let's call the lifetime of this reference `'2` - | | | - | | let's call the lifetime of this reference `'1` - | assignment requires that `'1` must outlive `'2` + | - - let's call the lifetime of this reference `'2` + | | + | let's call the lifetime of this reference `'1` +LL | ListFut2(bufs).await + | ^^^^ this usage requires that `'1` must outlive `'2` error: aborting due to 2 previous errors diff --git a/src/test/ui/async-await/issues/issue-54752-async-block.stderr b/src/test/ui/async-await/issues/issue-54752-async-block.stderr index e39a049e2d..0aea56ddb7 100644 --- a/src/test/ui/async-await/issues/issue-54752-async-block.stderr +++ b/src/test/ui/async-await/issues/issue-54752-async-block.stderr @@ -2,9 +2,14 @@ warning: unnecessary parentheses around assigned value --> $DIR/issue-54752-async-block.rs:6:22 | LL | fn main() { let _a = (async { }); } - | ^^^^^^^^^^^^ help: remove these parentheses + | ^ ^ | = note: `#[warn(unused_parens)]` on by default +help: remove these parentheses + | +LL - fn main() { let _a = (async { }); } +LL + fn main() { let _a = async { }; } + | warning: 1 warning emitted diff --git a/src/test/ui/async-await/issues/issue-61187.stderr b/src/test/ui/async-await/issues/issue-61187.stderr index 4d361c824d..163053471b 100644 --- a/src/test/ui/async-await/issues/issue-61187.stderr +++ b/src/test/ui/async-await/issues/issue-61187.stderr @@ -4,7 +4,7 @@ error[E0596]: cannot borrow `data` as mutable, as it is not declared as mutable LL | async fn response(data: Vec) { | ---- help: consider changing this to be mutable: `mut data` LL | data.reverse(); - | ^^^^ cannot borrow as mutable + | ^^^^^^^^^^^^^^ cannot borrow as mutable error: aborting due to previous error diff --git a/src/test/ui/async-await/issues/issue-62097.nll.stderr b/src/test/ui/async-await/issues/issue-62097.nll.stderr index e71bcf5822..786f621326 100644 --- a/src/test/ui/async-await/issues/issue-62097.nll.stderr +++ b/src/test/ui/async-await/issues/issue-62097.nll.stderr @@ -20,9 +20,15 @@ error[E0521]: borrowed data escapes outside of associated function --> $DIR/issue-62097.rs:13:9 | LL | pub async fn run_dummy_fn(&self) { - | ----- `self` is a reference that is only valid in the associated function body + | ----- + | | + | `self` is a reference that is only valid in the associated function body + | let's call the lifetime of this reference `'1` LL | foo(|| self.bar()).await; - | ^^^^^^^^^^^^^^^^^^ `self` escapes the associated function body here + | ^^^^^^^^^^^^^^^^^^ + | | + | `self` escapes the associated function body here + | argument requires that `'1` must outlive `'static` error: aborting due to 2 previous errors diff --git a/src/test/ui/async-await/issues/issue-64964.rs b/src/test/ui/async-await/issues/issue-64964.rs index 5313d1715c..6d6eff4864 100644 --- a/src/test/ui/async-await/issues/issue-64964.rs +++ b/src/test/ui/async-await/issues/issue-64964.rs @@ -1,5 +1,6 @@ // check-pass -// compile-flags: -Z query-dep-graph -C incremental=tmp/issue-64964 +// incremental +// compile-flags: -Z query-dep-graph // edition:2018 // Regression test for ICE related to `await`ing in a method + incr. comp. (#64964) diff --git a/src/test/ui/async-await/issues/issue-65159.rs b/src/test/ui/async-await/issues/issue-65159.rs index 1dbf5db6c3..df2ca02570 100644 --- a/src/test/ui/async-await/issues/issue-65159.rs +++ b/src/test/ui/async-await/issues/issue-65159.rs @@ -6,7 +6,6 @@ async fn copy() -> Result<()> //~^ ERROR this enum takes 2 generic arguments { Ok(()) - //~^ ERROR type annotations needed } fn main() { } diff --git a/src/test/ui/async-await/issues/issue-65159.stderr b/src/test/ui/async-await/issues/issue-65159.stderr index ff46bcb898..45f5ec40cd 100644 --- a/src/test/ui/async-await/issues/issue-65159.stderr +++ b/src/test/ui/async-await/issues/issue-65159.stderr @@ -16,13 +16,6 @@ help: add missing generic argument LL | async fn copy() -> Result<(), E> | +++ -error[E0282]: type annotations needed - --> $DIR/issue-65159.rs:8:5 - | -LL | Ok(()) - | ^^ cannot infer type for type parameter `E` declared on the enum `Result` +error: aborting due to previous error -error: aborting due to 2 previous errors - -Some errors have detailed explanations: E0107, E0282. -For more information about an error, try `rustc --explain E0107`. +For more information about this error, try `rustc --explain E0107`. diff --git a/src/test/ui/attributes/extented-attribute-macro-error.rs b/src/test/ui/attributes/extented-attribute-macro-error.rs new file mode 100644 index 0000000000..f5f75f9f4d --- /dev/null +++ b/src/test/ui/attributes/extented-attribute-macro-error.rs @@ -0,0 +1,8 @@ +// normalize-stderr-test: "couldn't read.*" -> "couldn't read the file" + +#![feature(extended_key_value_attributes)] +#![doc = include_str!("../not_existing_file.md")] +struct Documented {} +//~^^ ERROR couldn't read + +fn main() {} diff --git a/src/test/ui/attributes/extented-attribute-macro-error.stderr b/src/test/ui/attributes/extented-attribute-macro-error.stderr new file mode 100644 index 0000000000..e4deeacd0f --- /dev/null +++ b/src/test/ui/attributes/extented-attribute-macro-error.stderr @@ -0,0 +1,10 @@ +error: couldn't read the file + --> $DIR/extented-attribute-macro-error.rs:4:10 + | +LL | #![doc = include_str!("../not_existing_file.md")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this error originates in the macro `include_str` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + diff --git a/src/test/ui/attributes/key-value-expansion.stderr b/src/test/ui/attributes/key-value-expansion.stderr index 03ca515265..ef59381f5f 100644 --- a/src/test/ui/attributes/key-value-expansion.stderr +++ b/src/test/ui/attributes/key-value-expansion.stderr @@ -11,22 +11,18 @@ LL | bug!("bug" + stringify!(found)); | ^^^^^^^^^^^^^^^^^^^^^^^^^ ... LL | bug!(); - | ------- in this macro invocation + | ------ in this macro invocation | = 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(match match (&"u8",) { - (arg0,) => - [::core::fmt::ArgumentV1::new(arg0, - ::core::fmt::Display::fmt)], - } { - ref args => unsafe { - ::core::fmt::Arguments::new_v1(&[""], - args) - } - }); + ::alloc::fmt::format(::core::fmt::Arguments::new_v1(&[""], + &match (&"u8",) { + (arg0,) => + [::core::fmt::ArgumentV1::new(arg0, + ::core::fmt::Display::fmt)], + })); res }.as_str()` --> $DIR/key-value-expansion.rs:48:23 @@ -35,7 +31,7 @@ LL | doc_comment! {format!("{coor}", coor = stringify!($t1)).as_str()} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ... LL | some_macro!(u8); - | ---------------- in this macro invocation + | --------------- in this macro invocation | = note: this error originates in the macro `some_macro` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/attributes/nonterminal-expansion.stderr b/src/test/ui/attributes/nonterminal-expansion.stderr index 9bf36f3c58..52376ac191 100644 --- a/src/test/ui/attributes/nonterminal-expansion.stderr +++ b/src/test/ui/attributes/nonterminal-expansion.stderr @@ -5,7 +5,7 @@ LL | #[repr(align($n))] | ^^ ... LL | pass_nonterminal!(n!()); - | ------------------------ in this macro invocation + | ----------------------- in this macro invocation | = note: this error originates in the macro `pass_nonterminal` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -16,7 +16,7 @@ LL | #[repr(align($n))] | ^^^^^^^^^ ... LL | pass_nonterminal!(n!()); - | ------------------------ in this macro invocation + | ----------------------- in this macro invocation | = note: this error originates in the macro `pass_nonterminal` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/attributes/register-attr-tool-fail.stderr b/src/test/ui/attributes/register-attr-tool-fail.stderr index 77acfcd87c..8f6977cb55 100644 --- a/src/test/ui/attributes/register-attr-tool-fail.stderr +++ b/src/test/ui/attributes/register-attr-tool-fail.stderr @@ -30,13 +30,13 @@ error: malformed `register_attr` attribute input --> $DIR/register-attr-tool-fail.rs:4:1 | LL | #![register_attr] - | ^^^^^^^^^^^^^^^^^ help: must be of the form: `#[register_attr(attr1, attr2, ...)]` + | ^^^^^^^^^^^^^^^^^ help: must be of the form: `#![register_attr(attr1, attr2, ...)]` error: malformed `register_tool` attribute input --> $DIR/register-attr-tool-fail.rs:5:1 | LL | #![register_tool] - | ^^^^^^^^^^^^^^^^^ help: must be of the form: `#[register_tool(tool1, tool2, ...)]` + | ^^^^^^^^^^^^^^^^^ help: must be of the form: `#![register_tool(tool1, tool2, ...)]` error: aborting due to 6 previous errors diff --git a/src/test/ui/auto-traits/auto-trait-validation.fixed b/src/test/ui/auto-traits/auto-trait-validation.fixed new file mode 100644 index 0000000000..da878ac622 --- /dev/null +++ b/src/test/ui/auto-traits/auto-trait-validation.fixed @@ -0,0 +1,13 @@ +#![feature(auto_traits)] + +// run-rustfix + +auto trait Generic {} +//~^ auto traits cannot have generic parameters [E0567] +auto trait Bound {} +//~^ auto traits cannot have super traits or lifetime bounds [E0568] +auto trait LifetimeBound {} +//~^ auto traits cannot have super traits or lifetime bounds [E0568] +auto trait MyTrait { } +//~^ auto traits cannot have associated items [E0380] +fn main() {} diff --git a/src/test/ui/auto-traits/auto-trait-validation.rs b/src/test/ui/auto-traits/auto-trait-validation.rs index a997b044c8..d43055e270 100644 --- a/src/test/ui/auto-traits/auto-trait-validation.rs +++ b/src/test/ui/auto-traits/auto-trait-validation.rs @@ -1,9 +1,13 @@ #![feature(auto_traits)] +// run-rustfix + auto trait Generic {} //~^ auto traits cannot have generic parameters [E0567] auto trait Bound : Copy {} -//~^ auto traits cannot have super traits [E0568] +//~^ auto traits cannot have super traits or lifetime bounds [E0568] +auto trait LifetimeBound : 'static {} +//~^ auto traits cannot have super traits or lifetime bounds [E0568] auto trait MyTrait { fn foo() {} } -//~^ auto traits cannot have methods or associated items [E0380] +//~^ auto traits cannot have associated items [E0380] fn main() {} diff --git a/src/test/ui/auto-traits/auto-trait-validation.stderr b/src/test/ui/auto-traits/auto-trait-validation.stderr index 4040e66c6a..2c380e5b09 100644 --- a/src/test/ui/auto-traits/auto-trait-validation.stderr +++ b/src/test/ui/auto-traits/auto-trait-validation.stderr @@ -1,28 +1,37 @@ error[E0567]: auto traits cannot have generic parameters - --> $DIR/auto-trait-validation.rs:3:19 + --> $DIR/auto-trait-validation.rs:5:19 | LL | auto trait Generic {} | -------^^^ help: remove the parameters | | | auto trait cannot have generic parameters -error[E0568]: auto traits cannot have super traits - --> $DIR/auto-trait-validation.rs:5:20 +error[E0568]: auto traits cannot have super traits or lifetime bounds + --> $DIR/auto-trait-validation.rs:7:17 | LL | auto trait Bound : Copy {} - | ----- ^^^^ help: remove the super traits + | -----^^^^^^^ help: remove the super traits or lifetime bounds | | - | auto trait cannot have super traits + | auto trait cannot have super traits or lifetime bounds -error[E0380]: auto traits cannot have methods or associated items - --> $DIR/auto-trait-validation.rs:7:25 +error[E0568]: auto traits cannot have super traits or lifetime bounds + --> $DIR/auto-trait-validation.rs:9:25 + | +LL | auto trait LifetimeBound : 'static {} + | -------------^^^^^^^^^^ help: remove the super traits or lifetime bounds + | | + | auto trait cannot have super traits or lifetime bounds + +error[E0380]: auto traits cannot have associated items + --> $DIR/auto-trait-validation.rs:11:25 | LL | auto trait MyTrait { fn foo() {} } - | ------- ^^^ - | | - | auto trait cannot have items + | ------- ---^^^----- + | | | + | | help: remove these associated items + | auto trait cannot have associated items -error: aborting due to 3 previous errors +error: aborting due to 4 previous errors Some errors have detailed explanations: E0380, E0567, E0568. For more information about an error, try `rustc --explain E0380`. diff --git a/src/test/ui/auto-traits/issue-23080-2.stderr b/src/test/ui/auto-traits/issue-23080-2.stderr index efeceafdd2..267a712f62 100644 --- a/src/test/ui/auto-traits/issue-23080-2.stderr +++ b/src/test/ui/auto-traits/issue-23080-2.stderr @@ -1,10 +1,10 @@ -error[E0380]: auto traits cannot have methods or associated items +error[E0380]: auto traits cannot have associated items --> $DIR/issue-23080-2.rs:5:10 | LL | unsafe auto trait Trait { - | ----- auto trait cannot have items + | ----- auto trait cannot have associated items LL | type Output; - | ^^^^^^ + | -----^^^^^^- help: remove these associated items error: aborting due to previous error diff --git a/src/test/ui/auto-traits/issue-23080.stderr b/src/test/ui/auto-traits/issue-23080.stderr index 73ecb1c362..c1b16b2f40 100644 --- a/src/test/ui/auto-traits/issue-23080.stderr +++ b/src/test/ui/auto-traits/issue-23080.stderr @@ -1,10 +1,13 @@ -error[E0380]: auto traits cannot have methods or associated items +error[E0380]: auto traits cannot have associated items --> $DIR/issue-23080.rs:5:8 | -LL | unsafe auto trait Trait { - | ----- auto trait cannot have items -LL | fn method(&self) { - | ^^^^^^ +LL | unsafe auto trait Trait { + | ----- auto trait cannot have associated items +LL | fn method(&self) { + | _____- ^^^^^^ +LL | | println!("Hello"); +LL | | } + | |_____- help: remove these associated items error: aborting due to previous error diff --git a/src/test/ui/auto-traits/issue-84075.rs b/src/test/ui/auto-traits/issue-84075.rs new file mode 100644 index 0000000000..a6afe24ea4 --- /dev/null +++ b/src/test/ui/auto-traits/issue-84075.rs @@ -0,0 +1,16 @@ +// Regression test for issue #84075. + +#![feature(auto_traits)] + +auto trait Magic where Self: Copy {} //~ ERROR E0568 +impl Magic for T {} + +fn copy(x: T) -> (T, T) { (x, x) } + +#[derive(Debug)] +struct NoClone; + +fn main() { + let (a, b) = copy(NoClone); + println!("{:?} {:?}", a, b); +} diff --git a/src/test/ui/auto-traits/issue-84075.stderr b/src/test/ui/auto-traits/issue-84075.stderr new file mode 100644 index 0000000000..02dca598ec --- /dev/null +++ b/src/test/ui/auto-traits/issue-84075.stderr @@ -0,0 +1,11 @@ +error[E0568]: auto traits cannot have super traits or lifetime bounds + --> $DIR/issue-84075.rs:5:18 + | +LL | auto trait Magic where Self: Copy {} + | ----- ^^^^^^^^^^^^^^^^ help: remove the super traits or lifetime bounds + | | + | auto trait cannot have super traits or lifetime bounds + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0568`. diff --git a/src/test/ui/auto-traits/typeck-auto-trait-no-supertraits-2.rs b/src/test/ui/auto-traits/typeck-auto-trait-no-supertraits-2.rs index 6cceaf821f..98359ef51b 100644 --- a/src/test/ui/auto-traits/typeck-auto-trait-no-supertraits-2.rs +++ b/src/test/ui/auto-traits/typeck-auto-trait-no-supertraits-2.rs @@ -2,6 +2,7 @@ #![feature(negative_impls)] auto trait Magic : Sized where Option : Magic {} //~ ERROR E0568 +//~^ ERROR E0568 impl Magic for T {} fn copy(x: T) -> (T, T) { (x, x) } diff --git a/src/test/ui/auto-traits/typeck-auto-trait-no-supertraits-2.stderr b/src/test/ui/auto-traits/typeck-auto-trait-no-supertraits-2.stderr index 63b3300f6d..4827916fa5 100644 --- a/src/test/ui/auto-traits/typeck-auto-trait-no-supertraits-2.stderr +++ b/src/test/ui/auto-traits/typeck-auto-trait-no-supertraits-2.stderr @@ -1,11 +1,19 @@ -error[E0568]: auto traits cannot have super traits - --> $DIR/typeck-auto-trait-no-supertraits-2.rs:4:20 +error[E0568]: auto traits cannot have super traits or lifetime bounds + --> $DIR/typeck-auto-trait-no-supertraits-2.rs:4:17 | LL | auto trait Magic : Sized where Option : Magic {} - | ----- ^^^^^ help: remove the super traits + | -----^^^^^^^^ help: remove the super traits or lifetime bounds | | - | auto trait cannot have super traits + | auto trait cannot have super traits or lifetime bounds -error: aborting due to previous error +error[E0568]: auto traits cannot have super traits or lifetime bounds + --> $DIR/typeck-auto-trait-no-supertraits-2.rs:4:26 + | +LL | auto trait Magic : Sized where Option : Magic {} + | ----- ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove the super traits or lifetime bounds + | | + | auto trait cannot have super traits or lifetime bounds + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0568`. diff --git a/src/test/ui/auto-traits/typeck-auto-trait-no-supertraits.stderr b/src/test/ui/auto-traits/typeck-auto-trait-no-supertraits.stderr index 796638fc54..d7716f4b61 100644 --- a/src/test/ui/auto-traits/typeck-auto-trait-no-supertraits.stderr +++ b/src/test/ui/auto-traits/typeck-auto-trait-no-supertraits.stderr @@ -1,10 +1,10 @@ -error[E0568]: auto traits cannot have super traits - --> $DIR/typeck-auto-trait-no-supertraits.rs:28:19 +error[E0568]: auto traits cannot have super traits or lifetime bounds + --> $DIR/typeck-auto-trait-no-supertraits.rs:28:17 | LL | auto trait Magic: Copy {} - | ----- ^^^^ help: remove the super traits + | -----^^^^^^ help: remove the super traits or lifetime bounds | | - | auto trait cannot have super traits + | auto trait cannot have super traits or lifetime bounds error: aborting due to previous error diff --git a/src/test/ui/autoderef-full-lval.rs b/src/test/ui/autoderef-full-lval.rs index f07a2c107b..0fadc5c982 100644 --- a/src/test/ui/autoderef-full-lval.rs +++ b/src/test/ui/autoderef-full-lval.rs @@ -1,23 +1,23 @@ -#![feature(box_syntax)] - struct Clam { x: Box, y: Box, } + + struct Fish { a: Box, } fn main() { - let a: Clam = Clam{x: box 1, y: box 2}; - let b: Clam = Clam{x: box 10, y: box 20}; + let a: Clam = Clam{ x: Box::new(1), y: Box::new(2) }; + let b: Clam = Clam{ x: Box::new(10), y: Box::new(20) }; let z: isize = a.x + b.y; //~^ ERROR cannot add `Box` to `Box` println!("{}", z); assert_eq!(z, 21); - let forty: Fish = Fish{a: box 40}; - let two: Fish = Fish{a: box 2}; + let forty: Fish = Fish{ a: Box::new(40) }; + let two: Fish = Fish{ a: Box::new(2) }; let answer: isize = forty.a + two.a; //~^ ERROR cannot add `Box` to `Box` println!("{}", answer); diff --git a/src/test/ui/autoref-autoderef/autoderef-method-on-trait.rs b/src/test/ui/autoref-autoderef/autoderef-method-on-trait.rs index fadb0784e7..af747cc76e 100644 --- a/src/test/ui/autoref-autoderef/autoderef-method-on-trait.rs +++ b/src/test/ui/autoref-autoderef/autoderef-method-on-trait.rs @@ -1,6 +1,5 @@ // run-pass #![allow(non_camel_case_types)] -#![feature(box_syntax)] trait double { fn double(self: Box) -> usize; @@ -11,6 +10,6 @@ impl double for usize { } pub fn main() { - let x: Box<_> = box (box 3usize as Box); + let x: Box<_> = Box::new(Box::new(3usize) as Box); assert_eq!(x.double(), 6); } diff --git a/src/test/ui/autoref-autoderef/autoderef-method-priority.rs b/src/test/ui/autoref-autoderef/autoderef-method-priority.rs index a218f85eba..88a5140dc7 100644 --- a/src/test/ui/autoref-autoderef/autoderef-method-priority.rs +++ b/src/test/ui/autoref-autoderef/autoderef-method-priority.rs @@ -1,6 +1,5 @@ // run-pass #![allow(non_camel_case_types)] -#![feature(box_syntax)] trait double { fn double(self) -> usize; @@ -15,6 +14,6 @@ impl double for Box { } pub fn main() { - let x: Box<_> = box 3; + let x: Box<_> = Box::new(3); assert_eq!(x.double(), 6); } diff --git a/src/test/ui/autoref-autoderef/autoderef-method-twice-but-not-thrice.rs b/src/test/ui/autoref-autoderef/autoderef-method-twice-but-not-thrice.rs index 9fda3b2c09..3657e61d42 100644 --- a/src/test/ui/autoref-autoderef/autoderef-method-twice-but-not-thrice.rs +++ b/src/test/ui/autoref-autoderef/autoderef-method-twice-but-not-thrice.rs @@ -1,6 +1,5 @@ // run-pass #![allow(non_camel_case_types)] -#![feature(box_syntax)] trait double { fn double(self: Box) -> usize; @@ -11,6 +10,6 @@ impl double for Box { } pub fn main() { - let x: Box>>>> = box box box box box 3; + let x: Box>>>> = Box::new(Box::new(Box::new(Box::new(Box::new(3))))); assert_eq!(x.double(), 6); } diff --git a/src/test/ui/autoref-autoderef/autoderef-method-twice.rs b/src/test/ui/autoref-autoderef/autoderef-method-twice.rs index f53dc8d103..ed86b31b8b 100644 --- a/src/test/ui/autoref-autoderef/autoderef-method-twice.rs +++ b/src/test/ui/autoref-autoderef/autoderef-method-twice.rs @@ -1,6 +1,5 @@ // run-pass #![allow(non_camel_case_types)] -#![feature(box_syntax)] trait double { fn double(self: Box) -> usize; @@ -11,6 +10,6 @@ impl double for usize { } pub fn main() { - let x: Box> = box box 3; + let x: Box> = Box::new(Box::new(3)); assert_eq!(x.double(), 6); } diff --git a/src/test/ui/autoref-autoderef/autoderef-method.rs b/src/test/ui/autoref-autoderef/autoderef-method.rs index 262050fa47..5b7965e955 100644 --- a/src/test/ui/autoref-autoderef/autoderef-method.rs +++ b/src/test/ui/autoref-autoderef/autoderef-method.rs @@ -1,6 +1,5 @@ // run-pass #![allow(non_camel_case_types)] -#![feature(box_syntax)] trait double { fn double(self: Box) -> usize; @@ -11,6 +10,6 @@ impl double for usize { } pub fn main() { - let x: Box<_> = box 3; + let x: Box<_> = Box::new(3); assert_eq!(x.double(), 6); } diff --git a/src/test/ui/autoref-autoderef/autoref-intermediate-types-issue-3585.rs b/src/test/ui/autoref-autoderef/autoref-intermediate-types-issue-3585.rs index 70ef7ce87e..3bdc248ff0 100644 --- a/src/test/ui/autoref-autoderef/autoref-intermediate-types-issue-3585.rs +++ b/src/test/ui/autoref-autoderef/autoref-intermediate-types-issue-3585.rs @@ -1,5 +1,4 @@ // run-pass -#![feature(box_syntax)] trait Foo { fn foo(&self) -> String; @@ -18,6 +17,6 @@ impl Foo for usize { } pub fn main() { - let x: Box<_> = box 3; + let x: Box<_> = Box::new(3); assert_eq!(x.foo(), "box 3".to_string()); } diff --git a/src/test/ui/autoref-autoderef/issue-38940.stderr b/src/test/ui/autoref-autoderef/issue-38940.stderr index 0671cede73..a560334314 100644 --- a/src/test/ui/autoref-autoderef/issue-38940.stderr +++ b/src/test/ui/autoref-autoderef/issue-38940.stderr @@ -4,7 +4,7 @@ error[E0055]: reached the recursion limit while auto-dereferencing `J` LL | let x: &Bottom = &t; | ^^ deref recursion limit reached | - = help: consider adding a `#![recursion_limit="20"]` attribute to your crate (`issue_38940`) + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "20"]` attribute to your crate (`issue_38940`) error[E0308]: mismatched types --> $DIR/issue-38940.rs:43:22 diff --git a/src/test/ui/binding/expr-match-generic-unique1.rs b/src/test/ui/binding/expr-match-generic-unique1.rs index 5a5f75eea3..c5f38d8155 100644 --- a/src/test/ui/binding/expr-match-generic-unique1.rs +++ b/src/test/ui/binding/expr-match-generic-unique1.rs @@ -1,5 +1,4 @@ // run-pass -#![feature(box_syntax)] fn test_generic(expected: Box, eq: F) where F: FnOnce(Box, Box) -> bool { let actual: Box = match true { @@ -13,7 +12,7 @@ fn test_box() { fn compare_box(b1: Box, b2: Box) -> bool { return *b1 == *b2; } - test_generic::(box true, compare_box); + test_generic::(Box::new(true), compare_box); } pub fn main() { test_box(); } diff --git a/src/test/ui/binding/expr-match-generic-unique2.rs b/src/test/ui/binding/expr-match-generic-unique2.rs index 1d236135cd..8977ca68ef 100644 --- a/src/test/ui/binding/expr-match-generic-unique2.rs +++ b/src/test/ui/binding/expr-match-generic-unique2.rs @@ -1,5 +1,4 @@ // run-pass -#![feature(box_syntax)] fn test_generic(expected: T, eq: F) where F: FnOnce(T, T) -> bool { let actual: T = match true { @@ -11,7 +10,7 @@ fn test_generic(expected: T, eq: F) where F: FnOnce(T, T) -> bool { fn test_vec() { fn compare_box(v1: Box, v2: Box) -> bool { return v1 == v2; } - test_generic::, _>(box 1, compare_box); + test_generic::, _>(Box::new(1), compare_box); } pub fn main() { test_vec(); } diff --git a/src/test/ui/binding/expr-match-unique.rs b/src/test/ui/binding/expr-match-unique.rs index a999541207..eec9e1f8b4 100644 --- a/src/test/ui/binding/expr-match-unique.rs +++ b/src/test/ui/binding/expr-match-unique.rs @@ -1,9 +1,8 @@ // run-pass -#![feature(box_syntax)] // Tests for match as expressions resulting in boxed types fn test_box() { - let res: Box<_> = match true { true => { box 100 }, _ => panic!() }; + let res: Box<_> = match true { true => { Box::new(100) }, _ => panic!() }; assert_eq!(*res, 100); } diff --git a/src/test/ui/binding/func-arg-incomplete-pattern.rs b/src/test/ui/binding/func-arg-incomplete-pattern.rs index 98dd51811d..eb94ee48f9 100644 --- a/src/test/ui/binding/func-arg-incomplete-pattern.rs +++ b/src/test/ui/binding/func-arg-incomplete-pattern.rs @@ -3,8 +3,6 @@ // Test that we do not leak when the arg pattern must drop part of the // argument (in this case, the `y` field). -#![feature(box_syntax)] - struct Foo { x: Box, y: Box, @@ -16,9 +14,9 @@ fn foo(Foo {x, ..}: Foo) -> *const usize { } pub fn main() { - let obj: Box<_> = box 1; + let obj: Box<_> = Box::new(1); let objptr: *const usize = &*obj; - let f = Foo {x: obj, y: box 2}; + let f = Foo { x: obj, y: Box::new(2) }; let xptr = foo(f); assert_eq!(objptr, xptr); } diff --git a/src/test/ui/binding/func-arg-ref-pattern.rs b/src/test/ui/binding/func-arg-ref-pattern.rs index f46eeb7a02..2d75c12140 100644 --- a/src/test/ui/binding/func-arg-ref-pattern.rs +++ b/src/test/ui/binding/func-arg-ref-pattern.rs @@ -5,7 +5,6 @@ // pattern. #![feature(box_patterns)] -#![feature(box_syntax)] fn getaddr(box ref x: Box) -> *const usize { let addr: *const usize = &*x; @@ -17,11 +16,11 @@ fn checkval(box ref x: Box) -> usize { } pub fn main() { - let obj: Box<_> = box 1; + let obj: Box<_> = Box::new(1); let objptr: *const usize = &*obj; let xptr = getaddr(obj); assert_eq!(objptr, xptr); - let obj = box 22; + let obj = Box::new(22); assert_eq!(checkval(obj), 22); } diff --git a/src/test/ui/binding/let-assignability.rs b/src/test/ui/binding/let-assignability.rs index 5bb375d285..b85f4a96a6 100644 --- a/src/test/ui/binding/let-assignability.rs +++ b/src/test/ui/binding/let-assignability.rs @@ -1,8 +1,7 @@ // run-pass -#![feature(box_syntax)] fn f() { - let a: Box<_> = box 1; + let a: Box<_> = Box::new(1); let b: &isize = &*a; println!("{}", b); } diff --git a/src/test/ui/binding/match-implicit-copy-unique.rs b/src/test/ui/binding/match-implicit-copy-unique.rs index a7e8109b46..74ffe2ecdb 100644 --- a/src/test/ui/binding/match-implicit-copy-unique.rs +++ b/src/test/ui/binding/match-implicit-copy-unique.rs @@ -1,16 +1,15 @@ // run-pass #![allow(non_shorthand_field_patterns)] -#![feature(box_syntax)] struct Pair { a: Box, b: Box } pub fn main() { - let mut x: Box<_> = box Pair {a: box 10, b: box 20}; + let mut x: Box<_> = Box::new(Pair { a: Box::new(10), b: Box::new(20) }); let x_internal = &mut *x; match *x_internal { Pair {a: ref mut a, b: ref mut _b} => { assert_eq!(**a, 10); - *a = box 30; + *a = Box::new(30); assert_eq!(**a, 30); } } diff --git a/src/test/ui/binding/match-unique-bind.rs b/src/test/ui/binding/match-unique-bind.rs index f5361b118b..507478983f 100644 --- a/src/test/ui/binding/match-unique-bind.rs +++ b/src/test/ui/binding/match-unique-bind.rs @@ -1,9 +1,8 @@ // run-pass #![feature(box_patterns)] -#![feature(box_syntax)] pub fn main() { - match box 100 { + match Box::new(100) { box x => { println!("{}", x); assert_eq!(x, 100); diff --git a/src/test/ui/binding/match-value-binding-in-guard-3291.rs b/src/test/ui/binding/match-value-binding-in-guard-3291.rs index 4b209b20a1..0d750da79e 100644 --- a/src/test/ui/binding/match-value-binding-in-guard-3291.rs +++ b/src/test/ui/binding/match-value-binding-in-guard-3291.rs @@ -1,8 +1,6 @@ // run-pass // pretty-expanded FIXME #23616 -#![feature(box_syntax)] - fn foo(x: Option>, b: bool) -> isize { match x { None => { 1 } @@ -12,8 +10,8 @@ fn foo(x: Option>, b: bool) -> isize { } pub fn main() { - foo(Some(box 22), true); - foo(Some(box 22), false); + foo(Some(Box::new(22)), true); + foo(Some(Box::new(22)), false); foo(None, true); foo(None, false); } diff --git a/src/test/ui/binop/binop-move-semantics.stderr b/src/test/ui/binop/binop-move-semantics.stderr index 7721f8827d..2cd6d1abfd 100644 --- a/src/test/ui/binop/binop-move-semantics.stderr +++ b/src/test/ui/binop/binop-move-semantics.stderr @@ -30,7 +30,7 @@ LL | x | - value moved here LL | + LL | x.clone(); - | ^ value borrowed here after move + | ^^^^^^^^^ value borrowed here after move | help: consider further restricting this bound | diff --git a/src/test/ui/binop/issue-28837.stderr b/src/test/ui/binop/issue-28837.stderr index 07f67bc3de..10f243bab1 100644 --- a/src/test/ui/binop/issue-28837.stderr +++ b/src/test/ui/binop/issue-28837.stderr @@ -6,7 +6,22 @@ LL | a + a; | | | A | - = note: an implementation of `std::ops::Add` might be missing for `A` +note: an implementation of `Add<_>` might be missing for `A` + --> $DIR/issue-28837.rs:1:1 + | +LL | struct A; + | ^^^^^^^^^ must implement `Add<_>` +note: the following trait must be implemented + --> $SRC_DIR/core/src/ops/arith.rs:LL:COL + | +LL | / pub trait Add { +LL | | /// The resulting type after applying the `+` operator. +LL | | #[stable(feature = "rust1", since = "1.0.0")] +LL | | type Output; +... | +LL | | fn add(self, rhs: Rhs) -> Self::Output; +LL | | } + | |_^ error[E0369]: cannot subtract `A` from `A` --> $DIR/issue-28837.rs:8:7 @@ -16,7 +31,22 @@ LL | a - a; | | | A | - = note: an implementation of `std::ops::Sub` might be missing for `A` +note: an implementation of `Sub<_>` might be missing for `A` + --> $DIR/issue-28837.rs:1:1 + | +LL | struct A; + | ^^^^^^^^^ must implement `Sub<_>` +note: the following trait must be implemented + --> $SRC_DIR/core/src/ops/arith.rs:LL:COL + | +LL | / pub trait Sub { +LL | | /// The resulting type after applying the `-` operator. +LL | | #[stable(feature = "rust1", since = "1.0.0")] +LL | | type Output; +... | +LL | | fn sub(self, rhs: Rhs) -> Self::Output; +LL | | } + | |_^ error[E0369]: cannot multiply `A` by `A` --> $DIR/issue-28837.rs:10:7 @@ -26,7 +56,22 @@ LL | a * a; | | | A | - = note: an implementation of `std::ops::Mul` might be missing for `A` +note: an implementation of `Mul<_>` might be missing for `A` + --> $DIR/issue-28837.rs:1:1 + | +LL | struct A; + | ^^^^^^^^^ must implement `Mul<_>` +note: the following trait must be implemented + --> $SRC_DIR/core/src/ops/arith.rs:LL:COL + | +LL | / pub trait Mul { +LL | | /// The resulting type after applying the `*` operator. +LL | | #[stable(feature = "rust1", since = "1.0.0")] +LL | | type Output; +... | +LL | | fn mul(self, rhs: Rhs) -> Self::Output; +LL | | } + | |_^ error[E0369]: cannot divide `A` by `A` --> $DIR/issue-28837.rs:12:7 @@ -36,7 +81,22 @@ LL | a / a; | | | A | - = note: an implementation of `std::ops::Div` might be missing for `A` +note: an implementation of `Div<_>` might be missing for `A` + --> $DIR/issue-28837.rs:1:1 + | +LL | struct A; + | ^^^^^^^^^ must implement `Div<_>` +note: the following trait must be implemented + --> $SRC_DIR/core/src/ops/arith.rs:LL:COL + | +LL | / pub trait Div { +LL | | /// The resulting type after applying the `/` operator. +LL | | #[stable(feature = "rust1", since = "1.0.0")] +LL | | type Output; +... | +LL | | fn div(self, rhs: Rhs) -> Self::Output; +LL | | } + | |_^ error[E0369]: cannot mod `A` by `A` --> $DIR/issue-28837.rs:14:7 @@ -46,7 +106,22 @@ LL | a % a; | | | A | - = note: an implementation of `std::ops::Rem` might be missing for `A` +note: an implementation of `Rem<_>` might be missing for `A` + --> $DIR/issue-28837.rs:1:1 + | +LL | struct A; + | ^^^^^^^^^ must implement `Rem<_>` +note: the following trait must be implemented + --> $SRC_DIR/core/src/ops/arith.rs:LL:COL + | +LL | / pub trait Rem { +LL | | /// The resulting type after applying the `%` operator. +LL | | #[stable(feature = "rust1", since = "1.0.0")] +LL | | type Output; +... | +LL | | fn rem(self, rhs: Rhs) -> Self::Output; +LL | | } + | |_^ error[E0369]: no implementation for `A & A` --> $DIR/issue-28837.rs:16:7 @@ -56,7 +131,22 @@ LL | a & a; | | | A | - = note: an implementation of `std::ops::BitAnd` might be missing for `A` +note: an implementation of `BitAnd<_>` might be missing for `A` + --> $DIR/issue-28837.rs:1:1 + | +LL | struct A; + | ^^^^^^^^^ must implement `BitAnd<_>` +note: the following trait must be implemented + --> $SRC_DIR/core/src/ops/bit.rs:LL:COL + | +LL | / pub trait BitAnd { +LL | | /// The resulting type after applying the `&` operator. +LL | | #[stable(feature = "rust1", since = "1.0.0")] +LL | | type Output; +... | +LL | | fn bitand(self, rhs: Rhs) -> Self::Output; +LL | | } + | |_^ error[E0369]: no implementation for `A | A` --> $DIR/issue-28837.rs:18:7 @@ -66,7 +156,22 @@ LL | a | a; | | | A | - = note: an implementation of `std::ops::BitOr` might be missing for `A` +note: an implementation of `BitOr<_>` might be missing for `A` + --> $DIR/issue-28837.rs:1:1 + | +LL | struct A; + | ^^^^^^^^^ must implement `BitOr<_>` +note: the following trait must be implemented + --> $SRC_DIR/core/src/ops/bit.rs:LL:COL + | +LL | / pub trait BitOr { +LL | | /// The resulting type after applying the `|` operator. +LL | | #[stable(feature = "rust1", since = "1.0.0")] +LL | | type Output; +... | +LL | | fn bitor(self, rhs: Rhs) -> Self::Output; +LL | | } + | |_^ error[E0369]: no implementation for `A << A` --> $DIR/issue-28837.rs:20:7 @@ -76,7 +181,22 @@ LL | a << a; | | | A | - = note: an implementation of `std::ops::Shl` might be missing for `A` +note: an implementation of `Shl<_>` might be missing for `A` + --> $DIR/issue-28837.rs:1:1 + | +LL | struct A; + | ^^^^^^^^^ must implement `Shl<_>` +note: the following trait must be implemented + --> $SRC_DIR/core/src/ops/bit.rs:LL:COL + | +LL | / pub trait Shl { +LL | | /// The resulting type after applying the `<<` operator. +LL | | #[stable(feature = "rust1", since = "1.0.0")] +LL | | type Output; +... | +LL | | fn shl(self, rhs: Rhs) -> Self::Output; +LL | | } + | |_^ error[E0369]: no implementation for `A >> A` --> $DIR/issue-28837.rs:22:7 @@ -86,7 +206,22 @@ LL | a >> a; | | | A | - = note: an implementation of `std::ops::Shr` might be missing for `A` +note: an implementation of `Shr<_>` might be missing for `A` + --> $DIR/issue-28837.rs:1:1 + | +LL | struct A; + | ^^^^^^^^^ must implement `Shr<_>` +note: the following trait must be implemented + --> $SRC_DIR/core/src/ops/bit.rs:LL:COL + | +LL | / pub trait Shr { +LL | | /// The resulting type after applying the `>>` operator. +LL | | #[stable(feature = "rust1", since = "1.0.0")] +LL | | type Output; +... | +LL | | fn shr(self, rhs: Rhs) -> Self::Output; +LL | | } + | |_^ error[E0369]: binary operation `==` cannot be applied to type `A` --> $DIR/issue-28837.rs:24:7 @@ -96,7 +231,15 @@ LL | a == a; | | | A | - = note: an implementation of `std::cmp::PartialEq` might be missing for `A` +note: an implementation of `PartialEq<_>` might be missing for `A` + --> $DIR/issue-28837.rs:1:1 + | +LL | struct A; + | ^^^^^^^^^ must implement `PartialEq<_>` +help: consider annotating `A` with `#[derive(PartialEq)]` + | +LL | #[derive(PartialEq)] + | error[E0369]: binary operation `!=` cannot be applied to type `A` --> $DIR/issue-28837.rs:26:7 @@ -106,7 +249,15 @@ LL | a != a; | | | A | - = note: an implementation of `std::cmp::PartialEq` might be missing for `A` +note: an implementation of `PartialEq<_>` might be missing for `A` + --> $DIR/issue-28837.rs:1:1 + | +LL | struct A; + | ^^^^^^^^^ must implement `PartialEq<_>` +help: consider annotating `A` with `#[derive(PartialEq)]` + | +LL | #[derive(PartialEq)] + | error[E0369]: binary operation `<` cannot be applied to type `A` --> $DIR/issue-28837.rs:28:7 @@ -116,7 +267,15 @@ LL | a < a; | | | A | - = note: an implementation of `std::cmp::PartialOrd` might be missing for `A` +note: an implementation of `PartialOrd<_>` might be missing for `A` + --> $DIR/issue-28837.rs:1:1 + | +LL | struct A; + | ^^^^^^^^^ must implement `PartialOrd<_>` +help: consider annotating `A` with `#[derive(PartialOrd)]` + | +LL | #[derive(PartialOrd)] + | error[E0369]: binary operation `<=` cannot be applied to type `A` --> $DIR/issue-28837.rs:30:7 @@ -126,7 +285,15 @@ LL | a <= a; | | | A | - = note: an implementation of `std::cmp::PartialOrd` might be missing for `A` +note: an implementation of `PartialOrd<_>` might be missing for `A` + --> $DIR/issue-28837.rs:1:1 + | +LL | struct A; + | ^^^^^^^^^ must implement `PartialOrd<_>` +help: consider annotating `A` with `#[derive(PartialOrd)]` + | +LL | #[derive(PartialOrd)] + | error[E0369]: binary operation `>` cannot be applied to type `A` --> $DIR/issue-28837.rs:32:7 @@ -136,7 +303,15 @@ LL | a > a; | | | A | - = note: an implementation of `std::cmp::PartialOrd` might be missing for `A` +note: an implementation of `PartialOrd<_>` might be missing for `A` + --> $DIR/issue-28837.rs:1:1 + | +LL | struct A; + | ^^^^^^^^^ must implement `PartialOrd<_>` +help: consider annotating `A` with `#[derive(PartialOrd)]` + | +LL | #[derive(PartialOrd)] + | error[E0369]: binary operation `>=` cannot be applied to type `A` --> $DIR/issue-28837.rs:34:7 @@ -146,7 +321,15 @@ LL | a >= a; | | | A | - = note: an implementation of `std::cmp::PartialOrd` might be missing for `A` +note: an implementation of `PartialOrd<_>` might be missing for `A` + --> $DIR/issue-28837.rs:1:1 + | +LL | struct A; + | ^^^^^^^^^ must implement `PartialOrd<_>` +help: consider annotating `A` with `#[derive(PartialOrd)]` + | +LL | #[derive(PartialOrd)] + | error: aborting due to 15 previous errors diff --git a/src/test/ui/binop/issue-77910-1.stderr b/src/test/ui/binop/issue-77910-1.stderr index ed71b99da0..db854ae80d 100644 --- a/src/test/ui/binop/issue-77910-1.stderr +++ b/src/test/ui/binop/issue-77910-1.stderr @@ -2,7 +2,7 @@ error[E0369]: binary operation `==` cannot be applied to type `for<'r> fn(&'r i3 --> $DIR/issue-77910-1.rs:8:5 | LL | assert_eq!(foo, y); - | ^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^ | | | for<'r> fn(&'r i32) -> &'r i32 {foo} | _ @@ -13,7 +13,7 @@ error[E0277]: `for<'r> fn(&'r i32) -> &'r i32 {foo}` doesn't implement `Debug` --> $DIR/issue-77910-1.rs:8:5 | LL | assert_eq!(foo, y); - | ^^^^^^^^^^^^^^^^^^^ `for<'r> fn(&'r i32) -> &'r i32 {foo}` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | ^^^^^^^^^^^^^^^^^^ `for<'r> fn(&'r i32) -> &'r i32 {foo}` cannot be formatted using `{:?}` because it doesn't implement `Debug` | = help: the trait `Debug` is not implemented for `for<'r> fn(&'r i32) -> &'r i32 {foo}` = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/block-result/consider-removing-last-semi.fixed b/src/test/ui/block-result/consider-removing-last-semi.fixed index a2ecb73ac5..36a769fe52 100644 --- a/src/test/ui/block-result/consider-removing-last-semi.fixed +++ b/src/test/ui/block-result/consider-removing-last-semi.fixed @@ -10,4 +10,11 @@ pub fn g() -> String { //~ ERROR mismatched types "removeme".to_string() } +pub fn macro_tests() -> u32 { //~ ERROR mismatched types + macro_rules! mac { + () => (1); + } + mac!() +} + fn main() {} diff --git a/src/test/ui/block-result/consider-removing-last-semi.rs b/src/test/ui/block-result/consider-removing-last-semi.rs index 4991d24b26..b9a7314890 100644 --- a/src/test/ui/block-result/consider-removing-last-semi.rs +++ b/src/test/ui/block-result/consider-removing-last-semi.rs @@ -10,4 +10,11 @@ pub fn g() -> String { //~ ERROR mismatched types "removeme".to_string(); } +pub fn macro_tests() -> u32 { //~ ERROR mismatched types + macro_rules! mac { + () => (1); + } + mac!(); +} + fn main() {} diff --git a/src/test/ui/block-result/consider-removing-last-semi.stderr b/src/test/ui/block-result/consider-removing-last-semi.stderr index 7c3d0165c6..99a367bfcc 100644 --- a/src/test/ui/block-result/consider-removing-last-semi.stderr +++ b/src/test/ui/block-result/consider-removing-last-semi.stderr @@ -20,6 +20,17 @@ LL | "this won't work".to_string(); LL | "removeme".to_string(); | - help: consider removing this semicolon -error: aborting due to 2 previous errors +error[E0308]: mismatched types + --> $DIR/consider-removing-last-semi.rs:13:25 + | +LL | pub fn macro_tests() -> u32 { + | ----------- ^^^ expected `u32`, found `()` + | | + | implicitly returns `()` as its body has no tail or `return` expression +... +LL | mac!(); + | - help: consider removing this semicolon + +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/block-result/issue-13428.stderr b/src/test/ui/block-result/issue-13428.stderr index 60aa2c5a6b..2f24679cc9 100644 --- a/src/test/ui/block-result/issue-13428.stderr +++ b/src/test/ui/block-result/issue-13428.stderr @@ -5,9 +5,6 @@ LL | fn foo() -> String { | --- ^^^^^^ expected struct `String`, found `()` | | | implicitly returns `()` as its body has no tail or `return` expression -... -LL | ; - | - help: consider removing this semicolon error[E0308]: mismatched types --> $DIR/issue-13428.rs:11:13 diff --git a/src/test/ui/borrowck/borrow-tuple-fields.rs b/src/test/ui/borrowck/borrow-tuple-fields.rs index 3e24a1b29c..c628fa49ed 100644 --- a/src/test/ui/borrowck/borrow-tuple-fields.rs +++ b/src/test/ui/borrowck/borrow-tuple-fields.rs @@ -1,13 +1,13 @@ -#![feature(box_syntax)] - - - struct Foo(Box, isize); struct Bar(isize, isize); + + + + fn main() { - let x: (Box<_>, _) = (box 1, 2); + let x: (Box<_>, _) = (Box::new(1), 2); let r = &x.0; let y = x; //~ ERROR cannot move out of `x` because it is borrowed @@ -23,7 +23,7 @@ fn main() { let b = &mut x.0; //~ ERROR cannot borrow `x.0` as mutable more than once at a time a.use_ref(); - let x = Foo(box 1, 2); + let x = Foo(Box::new(1), 2); let r = &x.0; let y = x; //~ ERROR cannot move out of `x` because it is borrowed r.use_ref(); diff --git a/src/test/ui/borrowck/borrow-tuple-fields.stderr b/src/test/ui/borrowck/borrow-tuple-fields.stderr index 503ea49d74..ad628abcbf 100644 --- a/src/test/ui/borrowck/borrow-tuple-fields.stderr +++ b/src/test/ui/borrowck/borrow-tuple-fields.stderr @@ -7,7 +7,7 @@ LL | let y = x; | ^ move out of `x` occurs here LL | LL | r.use_ref(); - | - borrow later used here + | ----------- borrow later used here error[E0502]: cannot borrow `x.0` as mutable because it is also borrowed as immutable --> $DIR/borrow-tuple-fields.rs:18:13 @@ -17,7 +17,7 @@ LL | let a = &x.0; LL | let b = &mut x.0; | ^^^^^^^^ mutable borrow occurs here LL | a.use_ref(); - | - immutable borrow later used here + | ----------- immutable borrow later used here error[E0499]: cannot borrow `x.0` as mutable more than once at a time --> $DIR/borrow-tuple-fields.rs:23:13 @@ -27,7 +27,7 @@ LL | let a = &mut x.0; LL | let b = &mut x.0; | ^^^^^^^^ second mutable borrow occurs here LL | a.use_ref(); - | - first borrow later used here + | ----------- first borrow later used here error[E0505]: cannot move out of `x` because it is borrowed --> $DIR/borrow-tuple-fields.rs:28:13 @@ -37,7 +37,7 @@ LL | let r = &x.0; LL | let y = x; | ^ move out of `x` occurs here LL | r.use_ref(); - | - borrow later used here + | ----------- borrow later used here error[E0502]: cannot borrow `x.0` as mutable because it is also borrowed as immutable --> $DIR/borrow-tuple-fields.rs:33:13 @@ -47,7 +47,7 @@ LL | let a = &x.0; LL | let b = &mut x.0; | ^^^^^^^^ mutable borrow occurs here LL | a.use_ref(); - | - immutable borrow later used here + | ----------- immutable borrow later used here error[E0499]: cannot borrow `x.0` as mutable more than once at a time --> $DIR/borrow-tuple-fields.rs:38:13 @@ -57,7 +57,7 @@ LL | let a = &mut x.0; LL | let b = &mut x.0; | ^^^^^^^^ second mutable borrow occurs here LL | a.use_mut(); - | - first borrow later used here + | ----------- first borrow later used here error: aborting due to 6 previous errors diff --git a/src/test/ui/borrowck/borrowck-argument.stderr b/src/test/ui/borrowck/borrowck-argument.stderr index cf15833140..d4d646e390 100644 --- a/src/test/ui/borrowck/borrowck-argument.stderr +++ b/src/test/ui/borrowck/borrowck-argument.stderr @@ -4,7 +4,7 @@ error[E0596]: cannot borrow `arg` as mutable, as it is not declared as mutable LL | fn func(arg: S) { | --- help: consider changing this to be mutable: `mut arg` LL | arg.mutate(); - | ^^^ cannot borrow as mutable + | ^^^^^^^^^^^^ cannot borrow as mutable error[E0596]: cannot borrow `arg` as mutable, as it is not declared as mutable --> $DIR/borrowck-argument.rs:15:9 @@ -12,7 +12,7 @@ error[E0596]: cannot borrow `arg` as mutable, as it is not declared as mutable LL | fn method(&self, arg: S) { | --- help: consider changing this to be mutable: `mut arg` LL | arg.mutate(); - | ^^^ cannot borrow as mutable + | ^^^^^^^^^^^^ cannot borrow as mutable error[E0596]: cannot borrow `arg` as mutable, as it is not declared as mutable --> $DIR/borrowck-argument.rs:21:9 @@ -20,13 +20,13 @@ error[E0596]: cannot borrow `arg` as mutable, as it is not declared as mutable LL | fn default(&self, arg: S) { | --- help: consider changing this to be mutable: `mut arg` LL | arg.mutate(); - | ^^^ cannot borrow as mutable + | ^^^^^^^^^^^^ cannot borrow as mutable error[E0596]: cannot borrow `arg` as mutable, as it is not declared as mutable --> $DIR/borrowck-argument.rs:32:17 | LL | (|arg: S| { arg.mutate() })(s); - | --- ^^^ cannot borrow as mutable + | --- ^^^^^^^^^^^^ cannot borrow as mutable | | | help: consider changing this to be mutable: `mut arg` diff --git a/src/test/ui/borrowck/borrowck-auto-mut-ref-to-immut-var.stderr b/src/test/ui/borrowck/borrowck-auto-mut-ref-to-immut-var.stderr index 3ed76c13f6..186ecddd6d 100644 --- a/src/test/ui/borrowck/borrowck-auto-mut-ref-to-immut-var.stderr +++ b/src/test/ui/borrowck/borrowck-auto-mut-ref-to-immut-var.stderr @@ -4,7 +4,7 @@ error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable LL | let x = Foo { x: 3 }; | - help: consider changing this to be mutable: `mut x` LL | x.printme(); - | ^ cannot borrow as mutable + | ^^^^^^^^^^^ cannot borrow as mutable error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-bad-nested-calls-free.rs b/src/test/ui/borrowck/borrowck-bad-nested-calls-free.rs index 3abc56153b..b0bb9a0351 100644 --- a/src/test/ui/borrowck/borrowck-bad-nested-calls-free.rs +++ b/src/test/ui/borrowck/borrowck-bad-nested-calls-free.rs @@ -1,10 +1,10 @@ // Test that we detect nested calls that could free pointers evaluated // for earlier arguments. -#![feature(box_syntax)] + fn rewrite(v: &mut Box) -> usize { - *v = box 22; + *v = Box::new(22); **v } @@ -13,7 +13,7 @@ fn add(v: &usize, w: usize) -> usize { } fn implicit() { - let mut a: Box<_> = box 1; + let mut a: Box<_> = Box::new(1); // Note the danger here: // @@ -26,7 +26,7 @@ fn implicit() { } fn explicit() { - let mut a: Box<_> = box 1; + let mut a: Box<_> = Box::new(1); add( &*a, rewrite(&mut a)); //~ ERROR cannot borrow diff --git a/src/test/ui/borrowck/borrowck-bad-nested-calls-move.rs b/src/test/ui/borrowck/borrowck-bad-nested-calls-move.rs index fd8df78a5d..b2afb6391c 100644 --- a/src/test/ui/borrowck/borrowck-bad-nested-calls-move.rs +++ b/src/test/ui/borrowck/borrowck-bad-nested-calls-move.rs @@ -1,10 +1,10 @@ // Test that we detect nested calls that could free pointers evaluated // for earlier arguments. -#![feature(box_syntax)] + fn rewrite(v: &mut Box) -> usize { - *v = box 22; + *v = Box::new(22); **v } @@ -13,7 +13,7 @@ fn add(v: &usize, w: Box) -> usize { } fn implicit() { - let mut a: Box<_> = box 1; + let mut a: Box<_> = Box::new(1); // Note the danger here: // @@ -26,7 +26,7 @@ fn implicit() { } fn explicit() { - let mut a: Box<_> = box 1; + let mut a: Box<_> = Box::new(1); add( &*a, a); //~ ERROR cannot move diff --git a/src/test/ui/borrowck/borrowck-borrow-from-expr-block.rs b/src/test/ui/borrowck/borrowck-borrow-from-expr-block.rs index 15c6e8bf21..24efadc305 100644 --- a/src/test/ui/borrowck/borrowck-borrow-from-expr-block.rs +++ b/src/test/ui/borrowck/borrowck-borrow-from-expr-block.rs @@ -1,5 +1,4 @@ // run-pass -#![feature(box_syntax)] fn borrow(x: &isize, f: F) where F: FnOnce(&isize) { f(x) @@ -14,5 +13,5 @@ fn test1(x: &Box) { } pub fn main() { - test1(&box 22); + test1(&Box::new(22)); } diff --git a/src/test/ui/borrowck/borrowck-borrow-immut-deref-of-box-as-mut.rs b/src/test/ui/borrowck/borrowck-borrow-immut-deref-of-box-as-mut.rs index bc820ee9f9..6b5544a8a3 100644 --- a/src/test/ui/borrowck/borrowck-borrow-immut-deref-of-box-as-mut.rs +++ b/src/test/ui/borrowck/borrowck-borrow-immut-deref-of-box-as-mut.rs @@ -1,5 +1,3 @@ -#![feature(box_syntax)] - struct A; impl A { @@ -7,8 +5,10 @@ impl A { } } + + pub fn main() { - let a: Box<_> = box A; + let a: Box<_> = Box::new(A); a.foo(); //~^ ERROR cannot borrow `*a` as mutable, as `a` is not declared as mutable [E0596] } diff --git a/src/test/ui/borrowck/borrowck-borrow-immut-deref-of-box-as-mut.stderr b/src/test/ui/borrowck/borrowck-borrow-immut-deref-of-box-as-mut.stderr index 7d7e305a31..237071e16f 100644 --- a/src/test/ui/borrowck/borrowck-borrow-immut-deref-of-box-as-mut.stderr +++ b/src/test/ui/borrowck/borrowck-borrow-immut-deref-of-box-as-mut.stderr @@ -1,10 +1,10 @@ error[E0596]: cannot borrow `*a` as mutable, as `a` is not declared as mutable --> $DIR/borrowck-borrow-immut-deref-of-box-as-mut.rs:12:5 | -LL | let a: Box<_> = box A; +LL | let a: Box<_> = Box::new(A); | - help: consider changing this to be mutable: `mut a` LL | a.foo(); - | ^ cannot borrow as mutable + | ^^^^^^^ cannot borrow as mutable error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-borrow-mut-object-twice.stderr b/src/test/ui/borrowck/borrowck-borrow-mut-object-twice.stderr index fa0ae318e7..42b6c34cd2 100644 --- a/src/test/ui/borrowck/borrowck-borrow-mut-object-twice.stderr +++ b/src/test/ui/borrowck/borrowck-borrow-mut-object-twice.stderr @@ -2,11 +2,11 @@ error[E0499]: cannot borrow `*x` as mutable more than once at a time --> $DIR/borrowck-borrow-mut-object-twice.rs:13:5 | LL | let y = x.f1(); - | - first mutable borrow occurs here + | ------ first mutable borrow occurs here LL | x.f2(); - | ^ second mutable borrow occurs here + | ^^^^^^ second mutable borrow occurs here LL | y.use_ref(); - | - first borrow later used here + | ----------- first borrow later used here error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-borrow-overloaded-auto-deref.stderr b/src/test/ui/borrowck/borrowck-borrow-overloaded-auto-deref.stderr index 426d5bc472..fdf6568d83 100644 --- a/src/test/ui/borrowck/borrowck-borrow-overloaded-auto-deref.stderr +++ b/src/test/ui/borrowck/borrowck-borrow-overloaded-auto-deref.stderr @@ -58,7 +58,7 @@ error[E0596]: cannot borrow data in an `Rc` as mutable --> $DIR/borrowck-borrow-overloaded-auto-deref.rs:72:5 | LL | x.set(0, 0); - | ^ cannot borrow as mutable + | ^^^^^^^^^^^ cannot borrow as mutable | = help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `Rc` @@ -66,7 +66,7 @@ error[E0596]: cannot borrow data in an `Rc` as mutable --> $DIR/borrowck-borrow-overloaded-auto-deref.rs:76:5 | LL | x.set(0, 0); - | ^ cannot borrow as mutable + | ^^^^^^^^^^^ cannot borrow as mutable | = help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `Rc` @@ -74,7 +74,7 @@ error[E0596]: cannot borrow data in an `Rc` as mutable --> $DIR/borrowck-borrow-overloaded-auto-deref.rs:84:5 | LL | x.y_mut() - | ^ cannot borrow as mutable + | ^^^^^^^^^ cannot borrow as mutable | = help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `Rc` @@ -82,7 +82,7 @@ error[E0596]: cannot borrow data in an `Rc` as mutable --> $DIR/borrowck-borrow-overloaded-auto-deref.rs:88:5 | LL | x.y_mut() - | ^ cannot borrow as mutable + | ^^^^^^^^^ cannot borrow as mutable | = help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `Rc` @@ -90,7 +90,7 @@ error[E0596]: cannot borrow data in an `Rc` as mutable --> $DIR/borrowck-borrow-overloaded-auto-deref.rs:92:6 | LL | *x.y_mut() = 3; - | ^ cannot borrow as mutable + | ^^^^^^^^^ cannot borrow as mutable | = help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `Rc` @@ -98,7 +98,7 @@ error[E0596]: cannot borrow data in an `Rc` as mutable --> $DIR/borrowck-borrow-overloaded-auto-deref.rs:96:6 | LL | *x.y_mut() = 3; - | ^ cannot borrow as mutable + | ^^^^^^^^^ cannot borrow as mutable | = help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `Rc` @@ -106,7 +106,7 @@ error[E0596]: cannot borrow data in an `Rc` as mutable --> $DIR/borrowck-borrow-overloaded-auto-deref.rs:100:6 | LL | *x.y_mut() = 3; - | ^ cannot borrow as mutable + | ^^^^^^^^^ cannot borrow as mutable | = help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `Rc` diff --git a/src/test/ui/borrowck/borrowck-borrowed-uniq-rvalue.rs b/src/test/ui/borrowck/borrowck-borrowed-uniq-rvalue.rs index a78c66f47c..1d05845fc6 100644 --- a/src/test/ui/borrowck/borrowck-borrowed-uniq-rvalue.rs +++ b/src/test/ui/borrowck/borrowck-borrowed-uniq-rvalue.rs @@ -1,15 +1,15 @@ -//buggy.rs - -#![feature(box_syntax)] - use std::collections::HashMap; + + + + fn main() { let tmp: Box<_>; let mut buggy_map: HashMap = HashMap::new(); buggy_map.insert(42, &*Box::new(1)); //~ ERROR temporary value dropped while borrowed // but it is ok if we use a temporary - tmp = box 2; + tmp = Box::new(2); buggy_map.insert(43, &*tmp); } diff --git a/src/test/ui/borrowck/borrowck-borrowed-uniq-rvalue.stderr b/src/test/ui/borrowck/borrowck-borrowed-uniq-rvalue.stderr index c91a4377b4..01379ed851 100644 --- a/src/test/ui/borrowck/borrowck-borrowed-uniq-rvalue.stderr +++ b/src/test/ui/borrowck/borrowck-borrowed-uniq-rvalue.stderr @@ -7,7 +7,7 @@ LL | buggy_map.insert(42, &*Box::new(1)); | creates a temporary which is freed while still in use ... LL | buggy_map.insert(43, &*tmp); - | --------- borrow later used here + | --------------------------- borrow later used here | = note: consider using a `let` binding to create a longer lived value diff --git a/src/test/ui/borrowck/borrowck-box-sensitivity.rs b/src/test/ui/borrowck/borrowck-box-sensitivity.rs index e5591f5003..e880f876f9 100644 --- a/src/test/ui/borrowck/borrowck-box-sensitivity.rs +++ b/src/test/ui/borrowck/borrowck-box-sensitivity.rs @@ -3,8 +3,6 @@ // run-pass -#![feature(box_syntax)] - struct A { x: Box, y: isize, @@ -26,97 +24,97 @@ struct D { } fn copy_after_move() { - let a: Box<_> = box A { x: box 0, y: 1 }; + let a: Box<_> = Box::new(A { x: Box::new(0), y: 1 }); let _x = a.x; let _y = a.y; } fn move_after_move() { - let a: Box<_> = box B { x: box 0, y: box 1 }; + let a: Box<_> = Box::new(B { x: Box::new(0), y: Box::new(1) }); let _x = a.x; let _y = a.y; } fn borrow_after_move() { - let a: Box<_> = box A { x: box 0, y: 1 }; + let a: Box<_> = Box::new(A { x: Box::new(0), y: 1 }); let _x = a.x; let _y = &a.y; } fn move_after_borrow() { - let a: Box<_> = box B { x: box 0, y: box 1 }; + let a: Box<_> = Box::new(B { x: Box::new(0), y: Box::new(1) }); let _x = &a.x; let _y = a.y; use_imm(_x); } fn copy_after_mut_borrow() { - let mut a: Box<_> = box A { x: box 0, y: 1 }; + let mut a: Box<_> = Box::new(A { x: Box::new(0), y: 1 }); let _x = &mut a.x; let _y = a.y; use_mut(_x); } fn move_after_mut_borrow() { - let mut a: Box<_> = box B { x: box 0, y: box 1 }; + let mut a: Box<_> = Box::new(B { x: Box::new(0), y: Box::new(1) }); let _x = &mut a.x; let _y = a.y; use_mut(_x); } fn borrow_after_mut_borrow() { - let mut a: Box<_> = box A { x: box 0, y: 1 }; + let mut a: Box<_> = Box::new(A { x: Box::new(0), y: 1 }); let _x = &mut a.x; let _y = &a.y; use_mut(_x); } fn mut_borrow_after_borrow() { - let mut a: Box<_> = box A { x: box 0, y: 1 }; + let mut a: Box<_> = Box::new(A { x: Box::new(0), y: 1 }); let _x = &a.x; let _y = &mut a.y; use_imm(_x); } fn copy_after_move_nested() { - let a: Box<_> = box C { x: box A { x: box 0, y: 1 }, y: 2 }; + let a: Box<_> = Box::new(C { x: Box::new(A { x: Box::new(0), y: 1 }), y: 2 }); let _x = a.x.x; let _y = a.y; } fn move_after_move_nested() { - let a: Box<_> = box D { x: box A { x: box 0, y: 1 }, y: box 2 }; + let a: Box<_> = Box::new(D { x: Box::new(A { x: Box::new(0), y: 1 }), y: Box::new(2) }); let _x = a.x.x; let _y = a.y; } fn borrow_after_move_nested() { - let a: Box<_> = box C { x: box A { x: box 0, y: 1 }, y: 2 }; + let a: Box<_> = Box::new(C { x: Box::new(A { x: Box::new(0), y: 1 }), y: 2 }); let _x = a.x.x; let _y = &a.y; } fn move_after_borrow_nested() { - let a: Box<_> = box D { x: box A { x: box 0, y: 1 }, y: box 2 }; + let a: Box<_> = Box::new(D { x: Box::new(A { x: Box::new(0), y: 1 }), y: Box::new(2) }); let _x = &a.x.x; let _y = a.y; use_imm(_x); } fn copy_after_mut_borrow_nested() { - let mut a: Box<_> = box C { x: box A { x: box 0, y: 1 }, y: 2 }; + let mut a: Box<_> = Box::new(C { x: Box::new(A { x: Box::new(0), y: 1 }), y: 2 }); let _x = &mut a.x.x; let _y = a.y; use_mut(_x); } fn move_after_mut_borrow_nested() { - let mut a: Box<_> = box D { x: box A { x: box 0, y: 1 }, y: box 2 }; + let mut a: Box<_> = Box::new(D { x: Box::new(A { x: Box::new(0), y: 1 }), y: Box::new(2) }); let _x = &mut a.x.x; let _y = a.y; use_mut(_x); } fn borrow_after_mut_borrow_nested() { - let mut a: Box<_> = box C { x: box A { x: box 0, y: 1 }, y: 2 }; + let mut a: Box<_> = Box::new(C { x: Box::new(A { x: Box::new(0), y: 1 }), y: 2 }); let _x = &mut a.x.x; let _y = &a.y; use_mut(_x); } fn mut_borrow_after_borrow_nested() { - let mut a: Box<_> = box C { x: box A { x: box 0, y: 1 }, y: 2 }; + let mut a: Box<_> = Box::new(C { x: Box::new(A { x: Box::new(0), y: 1 }), y: 2 }); let _x = &a.x.x; let _y = &mut a.y; use_imm(_x); diff --git a/src/test/ui/borrowck/borrowck-closures-mut-and-imm.rs b/src/test/ui/borrowck/borrowck-closures-mut-and-imm.rs index 2dc405ffcd..a8225f2faf 100644 --- a/src/test/ui/borrowck/borrowck-closures-mut-and-imm.rs +++ b/src/test/ui/borrowck/borrowck-closures-mut-and-imm.rs @@ -1,8 +1,6 @@ // Tests that two closures cannot simultaneously have mutable // and immutable access to the variable. Issue #6801. -#![feature(box_syntax)] - fn get(x: &isize) -> isize { *x } @@ -11,6 +9,8 @@ fn set(x: &mut isize) { *x = 4; } + + fn a() { let mut x = 3; let c1 = || x = 4; @@ -52,7 +52,7 @@ fn e() { } fn f() { - let mut x: Box<_> = box 3; + let mut x: Box<_> = Box::new(3); let c1 = || get(&*x); *x = 5; //~^ ERROR cannot assign to `*x` because it is borrowed @@ -64,7 +64,7 @@ fn g() { f: Box } - let mut x: Box<_> = box Foo { f: box 3 }; + let mut x: Box<_> = Box::new(Foo { f: Box::new(3) }); let c1 = || get(&*x.f); *x.f = 5; //~^ ERROR cannot assign to `*x.f` because it is borrowed @@ -76,7 +76,7 @@ fn h() { f: Box } - let mut x: Box<_> = box Foo { f: box 3 }; + let mut x: Box<_> = Box::new(Foo { f: Box::new(3) }); let c1 = || get(&*x.f); let c2 = || *x.f = 5; //~^ ERROR cannot borrow `x` as mutable because it is also borrowed as immutable diff --git a/src/test/ui/borrowck/borrowck-closures-two-mut-fail.rs b/src/test/ui/borrowck/borrowck-closures-two-mut-fail.rs index 2a1757231d..63a75cdff4 100644 --- a/src/test/ui/borrowck/borrowck-closures-two-mut-fail.rs +++ b/src/test/ui/borrowck/borrowck-closures-two-mut-fail.rs @@ -2,7 +2,7 @@ // access to the variable, whether that mutable access be used // for direct assignment or for taking mutable ref. Issue #6801. -#![feature(box_syntax)] + @@ -48,7 +48,7 @@ fn g() { f: Box } - let mut x: Box<_> = box Foo { f: box 3 }; + let mut x: Box<_> = Box::new(Foo { f: Box::new(3) }); let c1 = to_fn_mut(|| set(&mut *x.f)); let c2 = to_fn_mut(|| set(&mut *x.f)); //~^ ERROR cannot borrow `x` as mutable more than once diff --git a/src/test/ui/borrowck/borrowck-closures-two-mut.rs b/src/test/ui/borrowck/borrowck-closures-two-mut.rs index 5fe51654f3..cdff8f9e89 100644 --- a/src/test/ui/borrowck/borrowck-closures-two-mut.rs +++ b/src/test/ui/borrowck/borrowck-closures-two-mut.rs @@ -2,7 +2,7 @@ // access to the variable, whether that mutable access be used // for direct assignment or for taking mutable ref. Issue #6801. -#![feature(box_syntax)] + fn to_fn_mut(f: F) -> F { f } @@ -44,7 +44,7 @@ fn g() { f: Box } - let mut x: Box<_> = box Foo { f: box 3 }; + let mut x: Box<_> = Box::new(Foo { f: Box::new(3) }); let c1 = to_fn_mut(|| set(&mut *x.f)); let c2 = to_fn_mut(|| set(&mut *x.f)); //~^ ERROR cannot borrow `x` as mutable more than once diff --git a/src/test/ui/borrowck/borrowck-closures-unique-imm.stderr b/src/test/ui/borrowck/borrowck-closures-unique-imm.stderr index b8bbb31a35..0c5fd39b71 100644 --- a/src/test/ui/borrowck/borrowck-closures-unique-imm.stderr +++ b/src/test/ui/borrowck/borrowck-closures-unique-imm.stderr @@ -6,7 +6,7 @@ LL | let p = &this.x; LL | &mut this.x; | ^^^^^^^^^^^ mutable borrow occurs here LL | p.use_ref(); - | - immutable borrow later used here + | ----------- immutable borrow later used here error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-closures-use-after-free.rs b/src/test/ui/borrowck/borrowck-closures-use-after-free.rs index e9f65c4ff7..be5f1f873d 100644 --- a/src/test/ui/borrowck/borrowck-closures-use-after-free.rs +++ b/src/test/ui/borrowck/borrowck-closures-use-after-free.rs @@ -2,8 +2,6 @@ // cannot also be supplied a borrowed version of that // variable's contents. Issue #11192. -#![feature(box_syntax)] - struct Foo { x: isize } @@ -14,10 +12,12 @@ impl Drop for Foo { } } + + fn main() { - let mut ptr: Box<_> = box Foo { x: 0 }; + let mut ptr: Box<_> = Box::new(Foo { x: 0 }); let mut test = |foo: &Foo| { - ptr = box Foo { x: ptr.x + 1 }; + ptr = Box::new(Foo { x: ptr.x + 1 }); }; test(&*ptr); //~ ERROR cannot borrow `*ptr` } diff --git a/src/test/ui/borrowck/borrowck-closures-use-after-free.stderr b/src/test/ui/borrowck/borrowck-closures-use-after-free.stderr index a6dbcf3607..30900a3b6d 100644 --- a/src/test/ui/borrowck/borrowck-closures-use-after-free.stderr +++ b/src/test/ui/borrowck/borrowck-closures-use-after-free.stderr @@ -3,7 +3,7 @@ error[E0502]: cannot borrow `*ptr` as immutable because it is also borrowed as m | LL | let mut test = |foo: &Foo| { | ----------- mutable borrow occurs here -LL | ptr = box Foo { x: ptr.x + 1 }; +LL | ptr = Box::new(Foo { x: ptr.x + 1 }); | --- first borrow occurs due to use of `ptr` in closure LL | }; LL | test(&*ptr); diff --git a/src/test/ui/borrowck/borrowck-describe-lvalue.stderr b/src/test/ui/borrowck/borrowck-describe-lvalue.stderr index 4b9c5a2a98..f909dbc408 100644 --- a/src/test/ui/borrowck/borrowck-describe-lvalue.stderr +++ b/src/test/ui/borrowck/borrowck-describe-lvalue.stderr @@ -41,7 +41,7 @@ error[E0503]: cannot use `f.x` because it was mutably borrowed --> $DIR/borrowck-describe-lvalue.rs:37:9 | LL | let x = f.x(); - | - borrow of `f` occurs here + | ----- borrow of `f` occurs here LL | f.x; | ^^^ use of borrowed `f` LL | drop(x); @@ -51,7 +51,7 @@ error[E0503]: cannot use `g.0` because it was mutably borrowed --> $DIR/borrowck-describe-lvalue.rs:44:9 | LL | let x = g.x(); - | - borrow of `g` occurs here + | ----- borrow of `g` occurs here LL | g.0; | ^^^ use of borrowed `g` LL | drop(x); @@ -71,7 +71,7 @@ error[E0503]: cannot use `e.0` because it was mutably borrowed --> $DIR/borrowck-describe-lvalue.rs:59:20 | LL | let x = e.x(); - | - borrow of `e` occurs here + | ----- borrow of `e` occurs here LL | match e { LL | Baz::X(value) => value | ^^^^^ use of borrowed `e` @@ -93,7 +93,7 @@ error[E0503]: cannot use `f.x` because it was mutably borrowed --> $DIR/borrowck-describe-lvalue.rs:74:9 | LL | let x = f.x(); - | - borrow of `*f` occurs here + | ----- borrow of `*f` occurs here LL | f.x; | ^^^ use of borrowed `*f` LL | drop(x); @@ -103,7 +103,7 @@ error[E0503]: cannot use `g.0` because it was mutably borrowed --> $DIR/borrowck-describe-lvalue.rs:81:9 | LL | let x = g.x(); - | - borrow of `*g` occurs here + | ----- borrow of `*g` occurs here LL | g.0; | ^^^ use of borrowed `*g` LL | drop(x); @@ -123,7 +123,7 @@ error[E0503]: cannot use `e.0` because it was mutably borrowed --> $DIR/borrowck-describe-lvalue.rs:96:20 | LL | let x = e.x(); - | - borrow of `*e` occurs here + | ----- borrow of `*e` occurs here LL | match *e { LL | Baz::X(value) => value | ^^^^^ use of borrowed `*e` diff --git a/src/test/ui/borrowck/borrowck-field-sensitivity-rpass.rs b/src/test/ui/borrowck/borrowck-field-sensitivity-rpass.rs index cb1ba90de8..dd6708582c 100644 --- a/src/test/ui/borrowck/borrowck-field-sensitivity-rpass.rs +++ b/src/test/ui/borrowck/borrowck-field-sensitivity-rpass.rs @@ -3,89 +3,87 @@ #![allow(unused_variables)] // pretty-expanded FIXME #23616 -#![feature(box_syntax)] - struct A { a: isize, b: Box } struct B { a: Box, b: Box } fn move_after_copy() { - let x = A { a: 1, b: box 2 }; + let x = A { a: 1, b: Box::new(2) }; drop(x.a); drop(x.b); } fn move_after_fu_copy() { - let x = A { a: 1, b: box 2 }; - let _y = A { b: box 3, .. x }; + let x = A { a: 1, b: Box::new(2) }; + let _y = A { b: Box::new(3), .. x }; drop(x.b); } fn fu_move_after_copy() { - let x = A { a: 1, b: box 2 }; + let x = A { a: 1, b: Box::new(2) }; drop(x.a); let _y = A { a: 3, .. x }; } fn fu_move_after_fu_copy() { - let x = A { a: 1, b: box 2 }; - let _y = A { b: box 3, .. x }; + let x = A { a: 1, b: Box::new(2) }; + let _y = A { b: Box::new(3), .. x }; let _z = A { a: 4, .. x }; } fn copy_after_move() { - let x = A { a: 1, b: box 2 }; + let x = A { a: 1, b: Box::new(2) }; drop(x.b); drop(x.a); } fn copy_after_fu_move() { - let x = A { a: 1, b: box 2 }; + let x = A { a: 1, b: Box::new(2) }; let y = A { a: 3, .. x }; drop(x.a); } fn fu_copy_after_move() { - let x = A { a: 1, b: box 2 }; + let x = A { a: 1, b: Box::new(2) }; drop(x.b); - let _y = A { b: box 3, .. x }; + let _y = A { b: Box::new(3), .. x }; } fn fu_copy_after_fu_move() { - let x = A { a: 1, b: box 2 }; + let x = A { a: 1, b: Box::new(2) }; let _y = A { a: 3, .. x }; - let _z = A { b: box 3, .. x }; + let _z = A { b: Box::new(3), .. x }; } fn borrow_after_move() { - let x = A { a: 1, b: box 2 }; + let x = A { a: 1, b: Box::new(2) }; drop(x.b); let p = &x.a; drop(*p); } fn borrow_after_fu_move() { - let x = A { a: 1, b: box 2 }; + let x = A { a: 1, b: Box::new(2) }; let _y = A { a: 3, .. x }; let p = &x.a; drop(*p); } fn move_after_borrow() { - let x = A { a: 1, b: box 2 }; + let x = A { a: 1, b: Box::new(2) }; let p = &x.a; drop(x.b); drop(*p); } fn fu_move_after_borrow() { - let x = A { a: 1, b: box 2 }; + let x = A { a: 1, b: Box::new(2) }; let p = &x.a; let _y = A { a: 3, .. x }; drop(*p); } fn mut_borrow_after_mut_borrow() { - let mut x = A { a: 1, b: box 2 }; + let mut x = A { a: 1, b: Box::new(2) }; let p = &mut x.a; let q = &mut x.b; drop(*p); @@ -93,134 +91,134 @@ fn mut_borrow_after_mut_borrow() { } fn move_after_move() { - let x = B { a: box 1, b: box 2 }; + let x = B { a: Box::new(1), b: Box::new(2) }; drop(x.a); drop(x.b); } fn move_after_fu_move() { - let x = B { a: box 1, b: box 2 }; - let y = B { a: box 3, .. x }; + let x = B { a: Box::new(1), b: Box::new(2) }; + let y = B { a: Box::new(3), .. x }; drop(x.a); } fn fu_move_after_move() { - let x = B { a: box 1, b: box 2 }; + let x = B { a: Box::new(1), b: Box::new(2) }; drop(x.a); - let z = B { a: box 3, .. x }; + let z = B { a: Box::new(3), .. x }; drop(z.b); } fn fu_move_after_fu_move() { - let x = B { a: box 1, b: box 2 }; - let _y = B { b: box 3, .. x }; - let _z = B { a: box 4, .. x }; + let x = B { a: Box::new(1), b: Box::new(2) }; + let _y = B { b: Box::new(3), .. x }; + let _z = B { a: Box::new(4), .. x }; } fn copy_after_assign_after_move() { - let mut x = A { a: 1, b: box 2 }; + let mut x = A { a: 1, b: Box::new(2) }; drop(x.b); - x = A { a: 3, b: box 4 }; + x = A { a: 3, b: Box::new(4) }; drop(*x.b); } fn copy_after_assign_after_fu_move() { - let mut x = A { a: 1, b: box 2 }; + let mut x = A { a: 1, b: Box::new(2) }; let _y = A { a: 3, .. x }; - x = A { a: 3, b: box 4 }; + x = A { a: 3, b: Box::new(4) }; drop(*x.b); } fn copy_after_field_assign_after_move() { - let mut x = A { a: 1, b: box 2 }; + let mut x = A { a: 1, b: Box::new(2) }; drop(x.b); - x.b = box 3; + x.b = Box::new(3); drop(*x.b); } fn copy_after_field_assign_after_fu_move() { - let mut x = A { a: 1, b: box 2 }; + let mut x = A { a: 1, b: Box::new(2) }; let _y = A { a: 3, .. x }; - x.b = box 3; + x.b = Box::new(3); drop(*x.b); } fn borrow_after_assign_after_move() { - let mut x = A { a: 1, b: box 2 }; + let mut x = A { a: 1, b: Box::new(2) }; drop(x.b); - x = A { a: 3, b: box 4 }; + x = A { a: 3, b: Box::new(4) }; let p = &x.b; drop(**p); } fn borrow_after_assign_after_fu_move() { - let mut x = A { a: 1, b: box 2 }; + let mut x = A { a: 1, b: Box::new(2) }; let _y = A { a: 3, .. x }; - x = A { a: 3, b: box 4 }; + x = A { a: 3, b: Box::new(4) }; let p = &x.b; drop(**p); } fn borrow_after_field_assign_after_move() { - let mut x = A { a: 1, b: box 2 }; + let mut x = A { a: 1, b: Box::new(2) }; drop(x.b); - x.b = box 3; + x.b = Box::new(3); let p = &x.b; drop(**p); } fn borrow_after_field_assign_after_fu_move() { - let mut x = A { a: 1, b: box 2 }; + let mut x = A { a: 1, b: Box::new(2) }; let _y = A { a: 3, .. x }; - x.b = box 3; + x.b = Box::new(3); let p = &x.b; drop(**p); } fn move_after_assign_after_move() { - let mut x = A { a: 1, b: box 2 }; + let mut x = A { a: 1, b: Box::new(2) }; let _y = x.b; - x = A { a: 3, b: box 4 }; + x = A { a: 3, b: Box::new(4) }; drop(x.b); } fn move_after_assign_after_fu_move() { - let mut x = A { a: 1, b: box 2 }; + let mut x = A { a: 1, b: Box::new(2) }; let _y = A { a: 3, .. x }; - x = A { a: 3, b: box 4 }; + x = A { a: 3, b: Box::new(4) }; drop(x.b); } fn move_after_field_assign_after_move() { - let mut x = A { a: 1, b: box 2 }; + let mut x = A { a: 1, b: Box::new(2) }; drop(x.b); - x.b = box 3; + x.b = Box::new(3); drop(x.b); } fn move_after_field_assign_after_fu_move() { - let mut x = A { a: 1, b: box 2 }; + let mut x = A { a: 1, b: Box::new(2) }; let _y = A { a: 3, .. x }; - x.b = box 3; + x.b = Box::new(3); drop(x.b); } fn copy_after_assign_after_uninit() { let mut x: A; - x = A { a: 1, b: box 2 }; + x = A { a: 1, b: Box::new(2) }; drop(x.a); } fn borrow_after_assign_after_uninit() { let mut x: A; - x = A { a: 1, b: box 2 }; + x = A { a: 1, b: Box::new(2) }; let p = &x.a; drop(*p); } fn move_after_assign_after_uninit() { let mut x: A; - x = A { a: 1, b: box 2 }; + x = A { a: 1, b: Box::new(2) }; drop(x.b); } diff --git a/src/test/ui/borrowck/borrowck-field-sensitivity.rs b/src/test/ui/borrowck/borrowck-field-sensitivity.rs index ab607c2acb..50edfb6ba2 100644 --- a/src/test/ui/borrowck/borrowck-field-sensitivity.rs +++ b/src/test/ui/borrowck/borrowck-field-sensitivity.rs @@ -1,49 +1,49 @@ -#![feature(box_syntax)] - struct A { a: isize, b: Box } + + fn deref_after_move() { - let x = A { a: 1, b: box 2 }; + let x = A { a: 1, b: Box::new(2) }; drop(x.b); drop(*x.b); //~ ERROR use of moved value: `x.b` } fn deref_after_fu_move() { - let x = A { a: 1, b: box 2 }; + let x = A { a: 1, b: Box::new(2) }; let y = A { a: 3, .. x }; drop(*x.b); //~ ERROR use of moved value: `x.b` } fn borrow_after_move() { - let x = A { a: 1, b: box 2 }; + let x = A { a: 1, b: Box::new(2) }; drop(x.b); let p = &x.b; //~ ERROR borrow of moved value: `x.b` drop(**p); } fn borrow_after_fu_move() { - let x = A { a: 1, b: box 2 }; + let x = A { a: 1, b: Box::new(2) }; let _y = A { a: 3, .. x }; let p = &x.b; //~ ERROR borrow of moved value: `x.b` drop(**p); } fn move_after_borrow() { - let x = A { a: 1, b: box 2 }; + let x = A { a: 1, b: Box::new(2) }; let p = &x.b; drop(x.b); //~ ERROR cannot move out of `x.b` because it is borrowed drop(**p); } fn fu_move_after_borrow() { - let x = A { a: 1, b: box 2 }; + let x = A { a: 1, b: Box::new(2) }; let p = &x.b; let _y = A { a: 3, .. x }; //~ ERROR cannot move out of `x.b` because it is borrowed drop(**p); } fn mut_borrow_after_mut_borrow() { - let mut x = A { a: 1, b: box 2 }; + let mut x = A { a: 1, b: Box::new(2) }; let p = &mut x.a; let q = &mut x.a; //~ ERROR cannot borrow `x.a` as mutable more than once at a time drop(*p); @@ -51,25 +51,25 @@ fn mut_borrow_after_mut_borrow() { } fn move_after_move() { - let x = A { a: 1, b: box 2 }; + let x = A { a: 1, b: Box::new(2) }; drop(x.b); drop(x.b); //~ ERROR use of moved value: `x.b` } fn move_after_fu_move() { - let x = A { a: 1, b: box 2 }; + let x = A { a: 1, b: Box::new(2) }; let _y = A { a: 3, .. x }; drop(x.b); //~ ERROR use of moved value: `x.b` } fn fu_move_after_move() { - let x = A { a: 1, b: box 2 }; + let x = A { a: 1, b: Box::new(2) }; drop(x.b); let _z = A { a: 3, .. x }; //~ ERROR use of moved value: `x.b` } fn fu_move_after_fu_move() { - let x = A { a: 1, b: box 2 }; + let x = A { a: 1, b: Box::new(2) }; let _y = A { a: 3, .. x }; let _z = A { a: 4, .. x }; //~ ERROR use of moved value: `x.b` } @@ -91,7 +91,7 @@ fn borrow_after_field_assign_after_uninit() { fn move_after_field_assign_after_uninit() { let mut x: A; - x.b = box 1; //~ ERROR assign to part of possibly-uninitialized variable: `x` + x.b = Box::new(1); //~ ERROR assign to part of possibly-uninitialized variable: `x` drop(x.b); } diff --git a/src/test/ui/borrowck/borrowck-field-sensitivity.stderr b/src/test/ui/borrowck/borrowck-field-sensitivity.stderr index f1601336fc..bb4d2f0601 100644 --- a/src/test/ui/borrowck/borrowck-field-sensitivity.stderr +++ b/src/test/ui/borrowck/borrowck-field-sensitivity.stderr @@ -123,7 +123,7 @@ LL | x.a = 1; error[E0381]: assign to part of possibly-uninitialized variable: `x` --> $DIR/borrowck-field-sensitivity.rs:94:5 | -LL | x.b = box 1; +LL | x.b = Box::new(1); | ^^^ use of possibly-uninitialized `x` error: aborting due to 14 previous errors diff --git a/src/test/ui/borrowck/borrowck-for-loop-correct-cmt-for-pattern.rs b/src/test/ui/borrowck/borrowck-for-loop-correct-cmt-for-pattern.rs index de75368578..389b8a43c0 100644 --- a/src/test/ui/borrowck/borrowck-for-loop-correct-cmt-for-pattern.rs +++ b/src/test/ui/borrowck/borrowck-for-loop-correct-cmt-for-pattern.rs @@ -1,6 +1,6 @@ // Issue #16205. -#![feature(box_syntax)] + struct Foo { a: [Box; 3], @@ -13,12 +13,12 @@ fn main() { } let f = Foo { - a: [box 3, box 4, box 5], + a: [Box::new(3), Box::new(4), Box::new(5)], }; for &a in &f.a { //~ ERROR cannot move out } - let x: Option> = Some(box 1); + let x: Option> = Some(Box::new(1)); for &a in x.iter() { //~ ERROR cannot move out } } diff --git a/src/test/ui/borrowck/borrowck-for-loop-head-linkage.nll.stderr b/src/test/ui/borrowck/borrowck-for-loop-head-linkage.nll.stderr deleted file mode 100644 index 3468f29fb1..0000000000 --- a/src/test/ui/borrowck/borrowck-for-loop-head-linkage.nll.stderr +++ /dev/null @@ -1,27 +0,0 @@ -error[E0502]: cannot borrow `vector` as mutable because it is also borrowed as immutable - --> $DIR/borrowck-for-loop-head-linkage.rs:7:9 - | -LL | for &x in &vector { - | ------- - | | - | immutable borrow occurs here - | immutable borrow later used here -LL | let cap = vector.capacity(); -LL | vector.extend(repeat(0)); - | ^^^^^^ mutable borrow occurs here - -error[E0502]: cannot borrow `vector` as mutable because it is also borrowed as immutable - --> $DIR/borrowck-for-loop-head-linkage.rs:8:9 - | -LL | for &x in &vector { - | ------- - | | - | immutable borrow occurs here - | immutable borrow later used here -... -LL | vector[1] = 5; - | ^^^^^^ mutable borrow occurs here - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0502`. diff --git a/src/test/ui/borrowck/borrowck-in-static.stderr b/src/test/ui/borrowck/borrowck-in-static.stderr index f73c787346..30e74c5ec9 100644 --- a/src/test/ui/borrowck/borrowck-in-static.stderr +++ b/src/test/ui/borrowck/borrowck-in-static.stderr @@ -4,7 +4,10 @@ error[E0507]: cannot move out of `x`, a captured variable in an `Fn` closure LL | let x = Box::new(0); | - captured outer variable LL | Box::new(|| x) - | ^ move occurs because `x` has type `Box`, which does not implement the `Copy` trait + | ---^ + | | | + | | move occurs because `x` has type `Box`, which does not implement the `Copy` trait + | captured by this `Fn` closure error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-insert-during-each.stderr b/src/test/ui/borrowck/borrowck-insert-during-each.stderr index a1ac45795f..99d08e905d 100644 --- a/src/test/ui/borrowck/borrowck-insert-during-each.stderr +++ b/src/test/ui/borrowck/borrowck-insert-during-each.stderr @@ -16,15 +16,17 @@ LL | | }) error[E0500]: closure requires unique access to `f` but it is already borrowed --> $DIR/borrowck-insert-during-each.rs:18:9 | -LL | f.foo( - | - --- first borrow later used by call - | | - | borrow occurs here -LL | -LL | |a| { - | ^^^ closure construction occurs here -LL | f.n.insert(*a); - | --- second borrow occurs due to use of `f` in closure +LL | f.foo( + | - --- first borrow later used by call + | _____| + | | +LL | | +LL | | |a| { + | | ^^^ closure construction occurs here +LL | | f.n.insert(*a); + | | --- second borrow occurs due to use of `f` in closure +LL | | }) + | |__________- borrow occurs here error: aborting due to 2 previous errors diff --git a/src/test/ui/borrowck/borrowck-issue-14498.rs b/src/test/ui/borrowck/borrowck-issue-14498.rs index e8c9019264..003533a518 100644 --- a/src/test/ui/borrowck/borrowck-issue-14498.rs +++ b/src/test/ui/borrowck/borrowck-issue-14498.rs @@ -4,14 +4,14 @@ // Also includes tests of the errors reported when the Box in question // is immutable (#14270). -#![feature(box_syntax)] + struct A { a: isize } struct B<'a> { a: Box<&'a mut isize> } fn indirect_write_to_imm_box() { let mut x: isize = 1; - let y: Box<_> = box &mut x; + let y: Box<_> = Box::new(&mut x); let p = &y; ***p = 2; //~ ERROR cannot assign to `***p` drop(p); @@ -19,7 +19,7 @@ fn indirect_write_to_imm_box() { fn borrow_in_var_from_var() { let mut x: isize = 1; - let mut y: Box<_> = box &mut x; + let mut y: Box<_> = Box::new(&mut x); let p = &y; let q = &***p; **y = 2; //~ ERROR cannot assign to `**y` because it is borrowed @@ -29,7 +29,7 @@ fn borrow_in_var_from_var() { fn borrow_in_var_from_var_via_imm_box() { let mut x: isize = 1; - let y: Box<_> = box &mut x; + let y: Box<_> = Box::new(&mut x); let p = &y; let q = &***p; **y = 2; //~ ERROR cannot assign to `**y` because it is borrowed @@ -39,7 +39,7 @@ fn borrow_in_var_from_var_via_imm_box() { fn borrow_in_var_from_field() { let mut x = A { a: 1 }; - let mut y: Box<_> = box &mut x.a; + let mut y: Box<_> = Box::new(&mut x.a); let p = &y; let q = &***p; **y = 2; //~ ERROR cannot assign to `**y` because it is borrowed @@ -49,7 +49,7 @@ fn borrow_in_var_from_field() { fn borrow_in_var_from_field_via_imm_box() { let mut x = A { a: 1 }; - let y: Box<_> = box &mut x.a; + let y: Box<_> = Box::new(&mut x.a); let p = &y; let q = &***p; **y = 2; //~ ERROR cannot assign to `**y` because it is borrowed @@ -59,7 +59,7 @@ fn borrow_in_var_from_field_via_imm_box() { fn borrow_in_field_from_var() { let mut x: isize = 1; - let mut y = B { a: box &mut x }; + let mut y = B { a: Box::new(&mut x) }; let p = &y.a; let q = &***p; **y.a = 2; //~ ERROR cannot assign to `**y.a` because it is borrowed @@ -69,7 +69,7 @@ fn borrow_in_field_from_var() { fn borrow_in_field_from_var_via_imm_box() { let mut x: isize = 1; - let y = B { a: box &mut x }; + let y = B { a: Box::new(&mut x) }; let p = &y.a; let q = &***p; **y.a = 2; //~ ERROR cannot assign to `**y.a` because it is borrowed @@ -79,7 +79,7 @@ fn borrow_in_field_from_var_via_imm_box() { fn borrow_in_field_from_field() { let mut x = A { a: 1 }; - let mut y = B { a: box &mut x.a }; + let mut y = B { a: Box::new(&mut x.a) }; let p = &y.a; let q = &***p; **y.a = 2; //~ ERROR cannot assign to `**y.a` because it is borrowed @@ -89,7 +89,7 @@ fn borrow_in_field_from_field() { fn borrow_in_field_from_field_via_imm_box() { let mut x = A { a: 1 }; - let y = B { a: box &mut x.a }; + let y = B { a: Box::new(&mut x.a) }; let p = &y.a; let q = &***p; **y.a = 2; //~ ERROR cannot assign to `**y.a` because it is borrowed diff --git a/src/test/ui/borrowck/borrowck-issue-2657-1.rs b/src/test/ui/borrowck/borrowck-issue-2657-1.rs index c38293740e..0fb2267b98 100644 --- a/src/test/ui/borrowck/borrowck-issue-2657-1.rs +++ b/src/test/ui/borrowck/borrowck-issue-2657-1.rs @@ -1,9 +1,9 @@ -#![feature(box_syntax)] - +trait Fake { fn use_mut(&mut self) { } fn use_ref(&self) { } } +impl Fake for T { } fn main() { - let x: Option> = Some(box 1); + let x: Option> = Some(Box::new(1)); match x { Some(ref _y) => { let _a = x; //~ ERROR cannot move @@ -12,6 +12,3 @@ fn main() { _ => {} } } - -trait Fake { fn use_mut(&mut self) { } fn use_ref(&self) { } } -impl Fake for T { } diff --git a/src/test/ui/borrowck/borrowck-issue-2657-1.stderr b/src/test/ui/borrowck/borrowck-issue-2657-1.stderr index 4ea4eb8f00..390bb9384f 100644 --- a/src/test/ui/borrowck/borrowck-issue-2657-1.stderr +++ b/src/test/ui/borrowck/borrowck-issue-2657-1.stderr @@ -6,7 +6,7 @@ LL | Some(ref _y) => { LL | let _a = x; | ^ move out of `x` occurs here LL | _y.use_ref(); - | -- borrow later used here + | ------------ borrow later used here error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-issue-2657-2.rs b/src/test/ui/borrowck/borrowck-issue-2657-2.rs index cea5611048..7dbac02154 100644 --- a/src/test/ui/borrowck/borrowck-issue-2657-2.rs +++ b/src/test/ui/borrowck/borrowck-issue-2657-2.rs @@ -1,7 +1,7 @@ -#![feature(box_syntax)] - fn main() { - let x: Option> = Some(box 1); + + let x: Option> = Some(Box::new(1)); + match x { Some(ref y) => { let _b = *y; //~ ERROR cannot move out diff --git a/src/test/ui/borrowck/borrowck-lend-flow-if.rs b/src/test/ui/borrowck/borrowck-lend-flow-if.rs index 1150346f75..19a0dd0c6b 100644 --- a/src/test/ui/borrowck/borrowck-lend-flow-if.rs +++ b/src/test/ui/borrowck/borrowck-lend-flow-if.rs @@ -4,7 +4,7 @@ // either genuine or would require more advanced changes. The latter // cases are noted. -#![feature(box_syntax)] + fn borrow(_v: &isize) {} fn borrow_mut(_v: &mut isize) {} @@ -13,15 +13,15 @@ fn for_func(_f: F) where F: FnOnce() -> bool { panic!() } fn produce() -> T { panic!(); } fn inc(v: &mut Box) { - *v = box (**v + 1); + *v = Box::new(**v + 1); } fn pre_freeze_cond() { // In this instance, the freeze is conditional and starts before // the mut borrow. - let u = box 0; - let mut v: Box<_> = box 3; + let u = Box::new(0); + let mut v: Box<_> = Box::new(3); let mut _w = &u; if cond() { _w = &v; @@ -34,8 +34,8 @@ fn pre_freeze_else() { // In this instance, the freeze and mut borrow are on separate sides // of the if. - let u = box 0; - let mut v: Box<_> = box 3; + let u = Box::new(0); + let mut v: Box<_> = Box::new(3); let mut _w = &u; if cond() { _w = &v; diff --git a/src/test/ui/borrowck/borrowck-lend-flow-if.stderr b/src/test/ui/borrowck/borrowck-lend-flow-if.stderr index 68a82bdb57..e47efc0e0b 100644 --- a/src/test/ui/borrowck/borrowck-lend-flow-if.stderr +++ b/src/test/ui/borrowck/borrowck-lend-flow-if.stderr @@ -7,7 +7,7 @@ LL | } LL | borrow_mut(&mut *v); | ^^^^^^^ mutable borrow occurs here LL | _w.use_ref(); - | -- immutable borrow later used here + | ------------ immutable borrow later used here error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-lend-flow-loop.rs b/src/test/ui/borrowck/borrowck-lend-flow-loop.rs index b650df91ca..548ffbd515 100644 --- a/src/test/ui/borrowck/borrowck-lend-flow-loop.rs +++ b/src/test/ui/borrowck/borrowck-lend-flow-loop.rs @@ -1,18 +1,18 @@ -#![feature(box_syntax)] - fn borrow(_v: &isize) {} fn borrow_mut(_v: &mut isize) {} fn cond() -> bool { panic!() } fn produce() -> T { panic!(); } + fn inc(v: &mut Box) { - *v = box (**v + 1); + *v = Box::new(**v + 1); } + fn loop_overarching_alias_mut() { // In this instance, the borrow ends on the line before the loop - let mut v: Box<_> = box 3; + let mut v: Box<_> = Box::new(3); let mut x = &mut v; **x += 1; loop { @@ -23,18 +23,18 @@ fn loop_overarching_alias_mut() { fn block_overarching_alias_mut() { // In this instance, the borrow encompasses the entire closure call. - let mut v: Box<_> = box 3; + let mut v: Box<_> = Box::new(3); let mut x = &mut v; for _ in 0..3 { borrow(&*v); //~ ERROR cannot borrow } - *x = box 5; + *x = Box::new(5); } fn loop_aliased_mut() { // In this instance, the borrow ends right after each assignment to _x - let mut v: Box<_> = box 3; - let mut w: Box<_> = box 4; + let mut v: Box<_> = Box::new(3); + let mut w: Box<_> = Box::new(4); let mut _x = &w; loop { borrow_mut(&mut *v); // OK @@ -45,8 +45,8 @@ fn loop_aliased_mut() { fn while_aliased_mut() { // In this instance, the borrow ends right after each assignment to _x - let mut v: Box<_> = box 3; - let mut w: Box<_> = box 4; + let mut v: Box<_> = Box::new(3); + let mut w: Box<_> = Box::new(4); let mut _x = &w; while cond() { borrow_mut(&mut *v); // OK @@ -58,8 +58,8 @@ fn while_aliased_mut() { fn loop_aliased_mut_break() { // In this instance, the borrow ends right after each assignment to _x - let mut v: Box<_> = box 3; - let mut w: Box<_> = box 4; + let mut v: Box<_> = Box::new(3); + let mut w: Box<_> = Box::new(4); let mut _x = &w; loop { borrow_mut(&mut *v); @@ -72,8 +72,8 @@ fn loop_aliased_mut_break() { fn while_aliased_mut_break() { // In this instance, the borrow ends right after each assignment to _x - let mut v: Box<_> = box 3; - let mut w: Box<_> = box 4; + let mut v: Box<_> = Box::new(3); + let mut w: Box<_> = Box::new(4); let mut _x = &w; while cond() { borrow_mut(&mut *v); @@ -84,8 +84,8 @@ fn while_aliased_mut_break() { } fn while_aliased_mut_cond(cond: bool, cond2: bool) { - let mut v: Box<_> = box 3; - let mut w: Box<_> = box 4; + let mut v: Box<_> = Box::new(3); + let mut w: Box<_> = Box::new(4); let mut x = &mut w; while cond { **x += 1; diff --git a/src/test/ui/borrowck/borrowck-lend-flow-loop.stderr b/src/test/ui/borrowck/borrowck-lend-flow-loop.stderr index f02c357f48..df7c86b856 100644 --- a/src/test/ui/borrowck/borrowck-lend-flow-loop.stderr +++ b/src/test/ui/borrowck/borrowck-lend-flow-loop.stderr @@ -7,7 +7,7 @@ LL | for _ in 0..3 { LL | borrow(&*v); | ^^^ immutable borrow occurs here LL | } -LL | *x = box 5; +LL | *x = Box::new(5); | -- mutable borrow later used here error[E0502]: cannot borrow `*v` as immutable because it is also borrowed as mutable diff --git a/src/test/ui/borrowck/borrowck-lend-flow.rs b/src/test/ui/borrowck/borrowck-lend-flow.rs index 0eb62ede5d..564c57044a 100644 --- a/src/test/ui/borrowck/borrowck-lend-flow.rs +++ b/src/test/ui/borrowck/borrowck-lend-flow.rs @@ -4,7 +4,7 @@ // either genuine or would require more advanced changes. The latter // cases are noted. -#![feature(box_syntax)] + fn borrow(_v: &isize) {} fn borrow_mut(_v: &mut isize) {} @@ -13,13 +13,13 @@ fn for_func(_f: F) where F: FnOnce() -> bool { panic!() } fn produce() -> T { panic!(); } fn inc(v: &mut Box) { - *v = box (**v + 1); + *v = Box::new(**v + 1); } fn pre_freeze() { // In this instance, the freeze starts before the mut borrow. - let mut v: Box<_> = box 3; + let mut v: Box<_> = Box::new(3); let _w = &v; borrow_mut(&mut *v); //~ ERROR cannot borrow _w.use_ref(); @@ -28,7 +28,7 @@ fn pre_freeze() { fn post_freeze() { // In this instance, the const alias starts after the borrow. - let mut v: Box<_> = box 3; + let mut v: Box<_> = Box::new(3); borrow_mut(&mut *v); let _w = &v; } diff --git a/src/test/ui/borrowck/borrowck-lend-flow.stderr b/src/test/ui/borrowck/borrowck-lend-flow.stderr index 07b11b3e72..40c14f54cb 100644 --- a/src/test/ui/borrowck/borrowck-lend-flow.stderr +++ b/src/test/ui/borrowck/borrowck-lend-flow.stderr @@ -6,7 +6,7 @@ LL | let _w = &v; LL | borrow_mut(&mut *v); | ^^^^^^^ mutable borrow occurs here LL | _w.use_ref(); - | -- immutable borrow later used here + | ------------ immutable borrow later used here error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-loan-blocks-move-cc.rs b/src/test/ui/borrowck/borrowck-loan-blocks-move-cc.rs index 9fa46563fd..e536d40409 100644 --- a/src/test/ui/borrowck/borrowck-loan-blocks-move-cc.rs +++ b/src/test/ui/borrowck/borrowck-loan-blocks-move-cc.rs @@ -1,5 +1,3 @@ -#![feature(box_syntax)] - use std::thread; @@ -8,8 +6,10 @@ fn borrow(v: &isize, f: F) where F: FnOnce(&isize) { f(v); } + + fn box_imm() { - let v: Box<_> = box 3; + let v: Box<_> = Box::new(3); let w = &v; thread::spawn(move|| { //~^ ERROR cannot move out of `v` because it is borrowed @@ -19,7 +19,7 @@ fn box_imm() { } fn box_imm_explicit() { - let v: Box<_> = box 3; + let v: Box<_> = Box::new(3); let w = &v; thread::spawn(move|| { //~^ ERROR cannot move diff --git a/src/test/ui/borrowck/borrowck-loan-blocks-move-cc.stderr b/src/test/ui/borrowck/borrowck-loan-blocks-move-cc.stderr index ac25502ad0..3548da35b6 100644 --- a/src/test/ui/borrowck/borrowck-loan-blocks-move-cc.stderr +++ b/src/test/ui/borrowck/borrowck-loan-blocks-move-cc.stderr @@ -10,7 +10,7 @@ LL | println!("v={}", *v); | -- move occurs due to use in closure LL | }); LL | w.use_ref(); - | - borrow later used here + | ----------- borrow later used here error[E0505]: cannot move out of `v` because it is borrowed --> $DIR/borrowck-loan-blocks-move-cc.rs:24:19 @@ -24,7 +24,7 @@ LL | println!("v={}", *v); | -- move occurs due to use in closure LL | }); LL | w.use_ref(); - | - borrow later used here + | ----------- borrow later used here error: aborting due to 2 previous errors diff --git a/src/test/ui/borrowck/borrowck-loan-blocks-move.rs b/src/test/ui/borrowck/borrowck-loan-blocks-move.rs index bde73219f7..f3f443721b 100644 --- a/src/test/ui/borrowck/borrowck-loan-blocks-move.rs +++ b/src/test/ui/borrowck/borrowck-loan-blocks-move.rs @@ -1,12 +1,12 @@ -#![feature(box_syntax)] - - - fn take(_v: Box) { } + + + + fn box_imm() { - let v = box 3; + let v = Box::new(3); let w = &v; take(v); //~ ERROR cannot move out of `v` because it is borrowed w.use_ref(); diff --git a/src/test/ui/borrowck/borrowck-loan-blocks-move.stderr b/src/test/ui/borrowck/borrowck-loan-blocks-move.stderr index 615660febb..b5c6b101f7 100644 --- a/src/test/ui/borrowck/borrowck-loan-blocks-move.stderr +++ b/src/test/ui/borrowck/borrowck-loan-blocks-move.stderr @@ -6,7 +6,7 @@ LL | let w = &v; LL | take(v); | ^ move out of `v` occurs here LL | w.use_ref(); - | - borrow later used here + | ----------- borrow later used here error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-loan-blocks-mut-uniq.rs b/src/test/ui/borrowck/borrowck-loan-blocks-mut-uniq.rs index da30bfa29b..33d6af3031 100644 --- a/src/test/ui/borrowck/borrowck-loan-blocks-mut-uniq.rs +++ b/src/test/ui/borrowck/borrowck-loan-blocks-mut-uniq.rs @@ -1,14 +1,14 @@ -#![feature(box_syntax)] - fn borrow(v: &isize, f: F) where F: FnOnce(&isize) { f(v); } + + fn box_imm() { - let mut v: Box<_> = box 3; + let mut v: Box<_> = Box::new(3); borrow(&*v, |w| { //~ ERROR cannot borrow `v` as mutable - v = box 4; + v = Box::new(4); assert_eq!(*v, 3); assert_eq!(*w, 4); }) diff --git a/src/test/ui/borrowck/borrowck-loan-blocks-mut-uniq.stderr b/src/test/ui/borrowck/borrowck-loan-blocks-mut-uniq.stderr index 1d1522a15b..fa5308c290 100644 --- a/src/test/ui/borrowck/borrowck-loan-blocks-mut-uniq.stderr +++ b/src/test/ui/borrowck/borrowck-loan-blocks-mut-uniq.stderr @@ -7,7 +7,7 @@ LL | borrow(&*v, | immutable borrow later used by call LL | |w| { | ^^^ mutable borrow occurs here -LL | v = box 4; +LL | v = Box::new(4); | - second borrow occurs due to use of `v` in closure error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-loan-in-overloaded-op.rs b/src/test/ui/borrowck/borrowck-loan-in-overloaded-op.rs index 1baa94edfb..b8f1650fcd 100644 --- a/src/test/ui/borrowck/borrowck-loan-in-overloaded-op.rs +++ b/src/test/ui/borrowck/borrowck-loan-in-overloaded-op.rs @@ -1,5 +1,5 @@ #![feature(box_patterns)] -#![feature(box_syntax)] + use std::ops::Add; @@ -12,12 +12,12 @@ impl Add for Foo { fn add(self, f: Foo) -> Foo { let Foo(box i) = self; let Foo(box j) = f; - Foo(box (i + j)) + Foo(Box::new(i + j)) } } fn main() { - let x = Foo(box 3); + let x = Foo(Box::new(3)); let _y = {x} + x.clone(); // the `{x}` forces a move to occur //~^ ERROR borrow of moved value: `x` } diff --git a/src/test/ui/borrowck/borrowck-loan-in-overloaded-op.stderr b/src/test/ui/borrowck/borrowck-loan-in-overloaded-op.stderr index 095ae7f56b..0dd720ff6c 100644 --- a/src/test/ui/borrowck/borrowck-loan-in-overloaded-op.stderr +++ b/src/test/ui/borrowck/borrowck-loan-in-overloaded-op.stderr @@ -1,10 +1,10 @@ error[E0382]: borrow of moved value: `x` --> $DIR/borrowck-loan-in-overloaded-op.rs:21:20 | -LL | let x = Foo(box 3); +LL | let x = Foo(Box::new(3)); | - move occurs because `x` has type `Foo`, which does not implement the `Copy` trait LL | let _y = {x} + x.clone(); // the `{x}` forces a move to occur - | - ^ value borrowed here after move + | - ^^^^^^^^^ value borrowed here after move | | | value moved here diff --git a/src/test/ui/borrowck/borrowck-loan-rcvr-overloaded-op.stderr b/src/test/ui/borrowck/borrowck-loan-rcvr-overloaded-op.stderr index aa874c34a2..1d8d04c918 100644 --- a/src/test/ui/borrowck/borrowck-loan-rcvr-overloaded-op.stderr +++ b/src/test/ui/borrowck/borrowck-loan-rcvr-overloaded-op.stderr @@ -17,7 +17,7 @@ LL | let q = &mut p; | ------ mutable borrow occurs here ... LL | p.times(3); - | ^ immutable borrow occurs here + | ^^^^^^^^^^ immutable borrow occurs here LL | LL | *q + 3; // OK to use the new alias `q` | -- mutable borrow later used here diff --git a/src/test/ui/borrowck/borrowck-loan-rcvr.stderr b/src/test/ui/borrowck/borrowck-loan-rcvr.stderr index 489ec7d04e..74cad575d2 100644 --- a/src/test/ui/borrowck/borrowck-loan-rcvr.stderr +++ b/src/test/ui/borrowck/borrowck-loan-rcvr.stderr @@ -1,13 +1,15 @@ error[E0502]: cannot borrow `p` as mutable because it is also borrowed as immutable --> $DIR/borrowck-loan-rcvr.rs:23:14 | -LL | p.blockm(|| { - | - ------ ^^ mutable borrow occurs here - | | | - | | immutable borrow later used by call - | immutable borrow occurs here -LL | p.x = 10; - | --- second borrow occurs due to use of `p` in closure +LL | p.blockm(|| { + | - ------ ^^ mutable borrow occurs here + | | | + | _____| immutable borrow later used by call + | | +LL | | p.x = 10; + | | --- second borrow occurs due to use of `p` in closure +LL | | }) + | |______- immutable borrow occurs here error[E0502]: cannot borrow `p` as immutable because it is also borrowed as mutable --> $DIR/borrowck-loan-rcvr.rs:34:5 @@ -15,7 +17,7 @@ error[E0502]: cannot borrow `p` as immutable because it is also borrowed as muta LL | let l = &mut p; | ------ mutable borrow occurs here LL | p.impurem(); - | ^ immutable borrow occurs here + | ^^^^^^^^^^^ immutable borrow occurs here LL | LL | l.x += 1; | -------- mutable borrow later used here diff --git a/src/test/ui/borrowck/borrowck-macro-interaction-issue-6304.rs b/src/test/ui/borrowck/borrowck-macro-interaction-issue-6304.rs index 628e49f574..4e969f6ed8 100644 --- a/src/test/ui/borrowck/borrowck-macro-interaction-issue-6304.rs +++ b/src/test/ui/borrowck/borrowck-macro-interaction-issue-6304.rs @@ -6,9 +6,7 @@ // Check that we do not ICE when compiling this // macro, which reuses the expression `$id` - #![feature(box_patterns)] -#![feature(box_syntax)] struct Foo { a: isize @@ -23,7 +21,7 @@ impl Foo { macro_rules! declare { ($id:expr, $rest:expr) => ({ self.check_id($id); - box Bar::Bar2($id, $rest) + Box::new(Bar::Bar2($id, $rest)) }) } match s { diff --git a/src/test/ui/borrowck/borrowck-move-by-capture-ok.rs b/src/test/ui/borrowck/borrowck-move-by-capture-ok.rs index 98e4b88189..e7a48ebf6c 100644 --- a/src/test/ui/borrowck/borrowck-move-by-capture-ok.rs +++ b/src/test/ui/borrowck/borrowck-move-by-capture-ok.rs @@ -1,8 +1,7 @@ // run-pass -#![feature(box_syntax)] pub fn main() { - let bar: Box<_> = box 3; + let bar: Box<_> = Box::new(3); let h = || -> isize { *bar }; assert_eq!(h(), 3); } diff --git a/src/test/ui/borrowck/borrowck-move-by-capture.rs b/src/test/ui/borrowck/borrowck-move-by-capture.rs index a825ed5e89..f26edef17f 100644 --- a/src/test/ui/borrowck/borrowck-move-by-capture.rs +++ b/src/test/ui/borrowck/borrowck-move-by-capture.rs @@ -1,10 +1,10 @@ -#![feature(box_syntax,unboxed_closures)] +#![feature(unboxed_closures)] fn to_fn_mut>(f: F) -> F { f } fn to_fn_once>(f: F) -> F { f } pub fn main() { - let bar: Box<_> = box 3; + let bar: Box<_> = Box::new(3); let _g = to_fn_mut(|| { let _h = to_fn_once(move || -> isize { *bar }); //~ ERROR cannot move out of }); diff --git a/src/test/ui/borrowck/borrowck-move-by-capture.stderr b/src/test/ui/borrowck/borrowck-move-by-capture.stderr index 628f206e0a..257ec3fbb7 100644 --- a/src/test/ui/borrowck/borrowck-move-by-capture.stderr +++ b/src/test/ui/borrowck/borrowck-move-by-capture.stderr @@ -1,15 +1,18 @@ error[E0507]: cannot move out of `bar`, a captured variable in an `FnMut` closure --> $DIR/borrowck-move-by-capture.rs:9:29 | -LL | let bar: Box<_> = box 3; - | --- captured outer variable -LL | let _g = to_fn_mut(|| { -LL | let _h = to_fn_once(move || -> isize { *bar }); - | ^^^^^^^^^^^^^^^^ ---- - | | | - | | move occurs because `bar` has type `Box`, which does not implement the `Copy` trait - | | move occurs due to use in closure - | move out of `bar` occurs here +LL | let bar: Box<_> = Box::new(3); + | --- captured outer variable +LL | let _g = to_fn_mut(|| { + | ________________________- +LL | | let _h = to_fn_once(move || -> isize { *bar }); + | | ^^^^^^^^^^^^^^^^ ---- + | | | | + | | | move occurs because `bar` has type `Box`, which does not implement the `Copy` trait + | | | move occurs due to use in closure + | | move out of `bar` occurs here +LL | | }); + | |_____- captured by this `FnMut` closure error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-move-error-with-note.rs b/src/test/ui/borrowck/borrowck-move-error-with-note.rs index 7ef59f50c0..ef38cbb63a 100644 --- a/src/test/ui/borrowck/borrowck-move-error-with-note.rs +++ b/src/test/ui/borrowck/borrowck-move-error-with-note.rs @@ -1,14 +1,14 @@ -#![feature(box_syntax)] - enum Foo { Foo1(Box, Box), Foo2(Box), Foo3, } + + fn blah() { - let f = &Foo::Foo1(box 1, box 2); - match *f { //~ ERROR cannot move out of + let f = &Foo::Foo1(Box::new(1), Box::new(2)); + match *f { //~ ERROR cannot move out of Foo::Foo1(num1, num2) => (), Foo::Foo2(num) => (), @@ -42,8 +42,8 @@ struct A { fn free(_: T) {} fn blah2() { - let a = &A { a: box 1 }; - match a.a { //~ ERROR cannot move out of + let a = &A { a: Box::new(1) }; + match a.a { //~ ERROR cannot move out of n => { free(n) } diff --git a/src/test/ui/borrowck/borrowck-move-from-subpath-of-borrowed-path.rs b/src/test/ui/borrowck/borrowck-move-from-subpath-of-borrowed-path.rs index e058c80651..71405f7a73 100644 --- a/src/test/ui/borrowck/borrowck-move-from-subpath-of-borrowed-path.rs +++ b/src/test/ui/borrowck/borrowck-move-from-subpath-of-borrowed-path.rs @@ -3,10 +3,10 @@ -#![feature(box_syntax)] + fn main() { - let a: Box> = box box 2; + let a: Box> = Box::new(Box::new(2)); let b = &a; let z = *a; //~ ERROR: cannot move out of `*a` because it is borrowed diff --git a/src/test/ui/borrowck/borrowck-move-from-subpath-of-borrowed-path.stderr b/src/test/ui/borrowck/borrowck-move-from-subpath-of-borrowed-path.stderr index e4840fba67..b305e3c0a1 100644 --- a/src/test/ui/borrowck/borrowck-move-from-subpath-of-borrowed-path.stderr +++ b/src/test/ui/borrowck/borrowck-move-from-subpath-of-borrowed-path.stderr @@ -7,7 +7,7 @@ LL | LL | let z = *a; | ^^ move out of `*a` occurs here LL | b.use_ref(); - | - borrow later used here + | ----------- borrow later used here error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-move-moved-value-into-closure.rs b/src/test/ui/borrowck/borrowck-move-moved-value-into-closure.rs index 233d0a733e..72e7b5a716 100644 --- a/src/test/ui/borrowck/borrowck-move-moved-value-into-closure.rs +++ b/src/test/ui/borrowck/borrowck-move-moved-value-into-closure.rs @@ -1,11 +1,11 @@ -#![feature(box_syntax)] - fn call_f isize>(f: F) -> isize { f() } + + fn main() { - let t: Box<_> = box 3; + let t: Box<_> = Box::new(3); call_f(move|| { *t + 1 }); call_f(move|| { *t + 1 }); //~ ERROR use of moved value diff --git a/src/test/ui/borrowck/borrowck-move-moved-value-into-closure.stderr b/src/test/ui/borrowck/borrowck-move-moved-value-into-closure.stderr index 1ac4999e6e..edd597fe30 100644 --- a/src/test/ui/borrowck/borrowck-move-moved-value-into-closure.stderr +++ b/src/test/ui/borrowck/borrowck-move-moved-value-into-closure.stderr @@ -1,7 +1,7 @@ error[E0382]: use of moved value: `t` --> $DIR/borrowck-move-moved-value-into-closure.rs:11:12 | -LL | let t: Box<_> = box 3; +LL | let t: Box<_> = Box::new(3); | - move occurs because `t` has type `Box`, which does not implement the `Copy` trait LL | LL | call_f(move|| { *t + 1 }); diff --git a/src/test/ui/borrowck/borrowck-move-mut-base-ptr.stderr b/src/test/ui/borrowck/borrowck-move-mut-base-ptr.stderr index 77f5b72e51..d5ff0c501c 100644 --- a/src/test/ui/borrowck/borrowck-move-mut-base-ptr.stderr +++ b/src/test/ui/borrowck/borrowck-move-mut-base-ptr.stderr @@ -7,7 +7,7 @@ LL | let t1 = t0; | ^^ move out of `t0` occurs here LL | *t1 = 22; LL | p.use_ref(); - | - borrow later used here + | ----------- borrow later used here error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-move-out-of-overloaded-auto-deref.stderr b/src/test/ui/borrowck/borrowck-move-out-of-overloaded-auto-deref.stderr index 0a29d2bb1d..7974506507 100644 --- a/src/test/ui/borrowck/borrowck-move-out-of-overloaded-auto-deref.stderr +++ b/src/test/ui/borrowck/borrowck-move-out-of-overloaded-auto-deref.stderr @@ -2,7 +2,7 @@ error[E0507]: cannot move out of an `Rc` --> $DIR/borrowck-move-out-of-overloaded-auto-deref.rs:4:14 | LL | let _x = Rc::new(vec![1, 2]).into_iter(); - | ^^^^^^^^^^^^^^^^^^^ move occurs because value has type `Vec`, which does not implement the `Copy` trait + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ move occurs because value has type `Vec`, which does not implement the `Copy` trait error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-move-subcomponent.rs b/src/test/ui/borrowck/borrowck-move-subcomponent.rs index 4185632c4e..38abd19322 100644 --- a/src/test/ui/borrowck/borrowck-move-subcomponent.rs +++ b/src/test/ui/borrowck/borrowck-move-subcomponent.rs @@ -1,7 +1,7 @@ // Tests that the borrow checker checks all components of a path when moving // out. -#![feature(box_syntax)] + struct S { x : Box @@ -10,7 +10,7 @@ struct S { fn f(_: T) {} fn main() { - let a : S = S { x : box 1 }; + let a : S = S { x : Box::new(1) }; let pb = &a; let S { x: ax } = a; //~ ERROR cannot move out f(pb); diff --git a/src/test/ui/borrowck/borrowck-multiple-captures.rs b/src/test/ui/borrowck/borrowck-multiple-captures.rs index 9f09f8442c..57b3819ac5 100644 --- a/src/test/ui/borrowck/borrowck-multiple-captures.rs +++ b/src/test/ui/borrowck/borrowck-multiple-captures.rs @@ -1,13 +1,13 @@ -#![feature(box_syntax)] - use std::thread; + fn borrow(_: &T) { } + fn different_vars_after_borrows() { - let x1: Box<_> = box 1; + let x1: Box<_> = Box::new(1); let p1 = &x1; - let x2: Box<_> = box 2; + let x2: Box<_> = Box::new(2); let p2 = &x2; thread::spawn(move|| { //~^ ERROR cannot move out of `x1` because it is borrowed @@ -20,9 +20,9 @@ fn different_vars_after_borrows() { } fn different_vars_after_moves() { - let x1: Box<_> = box 1; + let x1: Box<_> = Box::new(1); drop(x1); - let x2: Box<_> = box 2; + let x2: Box<_> = Box::new(2); drop(x2); thread::spawn(move|| { //~^ ERROR use of moved value: `x1` @@ -33,7 +33,7 @@ fn different_vars_after_moves() { } fn same_var_after_borrow() { - let x: Box<_> = box 1; + let x: Box<_> = Box::new(1); let p = &x; thread::spawn(move|| { //~^ ERROR cannot move out of `x` because it is borrowed @@ -44,7 +44,7 @@ fn same_var_after_borrow() { } fn same_var_after_move() { - let x: Box<_> = box 1; + let x: Box<_> = Box::new(1); drop(x); thread::spawn(move|| { //~^ ERROR use of moved value: `x` diff --git a/src/test/ui/borrowck/borrowck-multiple-captures.stderr b/src/test/ui/borrowck/borrowck-multiple-captures.stderr index e159878619..86d2955e23 100644 --- a/src/test/ui/borrowck/borrowck-multiple-captures.stderr +++ b/src/test/ui/borrowck/borrowck-multiple-captures.stderr @@ -30,7 +30,7 @@ LL | borrow(&*p2); error[E0382]: use of moved value: `x1` --> $DIR/borrowck-multiple-captures.rs:27:19 | -LL | let x1: Box<_> = box 1; +LL | let x1: Box<_> = Box::new(1); | -- move occurs because `x1` has type `Box`, which does not implement the `Copy` trait LL | drop(x1); | -- value moved here @@ -44,7 +44,7 @@ LL | drop(x1); error[E0382]: use of moved value: `x2` --> $DIR/borrowck-multiple-captures.rs:27:19 | -LL | let x2: Box<_> = box 2; +LL | let x2: Box<_> = Box::new(2); | -- move occurs because `x2` has type `Box`, which does not implement the `Copy` trait LL | drop(x2); | -- value moved here @@ -91,7 +91,7 @@ LL | drop(x); error[E0382]: use of moved value: `x` --> $DIR/borrowck-multiple-captures.rs:49:19 | -LL | let x: Box<_> = box 1; +LL | let x: Box<_> = Box::new(1); | - move occurs because `x` has type `Box`, which does not implement the `Copy` trait LL | drop(x); | - value moved here diff --git a/src/test/ui/borrowck/borrowck-mut-borrow-linear-errors.stderr b/src/test/ui/borrowck/borrowck-mut-borrow-linear-errors.stderr index a409077793..15ac737606 100644 --- a/src/test/ui/borrowck/borrowck-mut-borrow-linear-errors.stderr +++ b/src/test/ui/borrowck/borrowck-mut-borrow-linear-errors.stderr @@ -5,8 +5,9 @@ LL | 1 => { addr.push(&mut x); } | ^^^^^^ second mutable borrow occurs here LL | 2 => { addr.push(&mut x); } LL | _ => { addr.push(&mut x); } - | ---- ------ first mutable borrow occurs here - | | + | ----------------- + | | | + | | first mutable borrow occurs here | first borrow later used here error[E0499]: cannot borrow `x` as mutable more than once at a time @@ -15,8 +16,9 @@ error[E0499]: cannot borrow `x` as mutable more than once at a time LL | 2 => { addr.push(&mut x); } | ^^^^^^ second mutable borrow occurs here LL | _ => { addr.push(&mut x); } - | ---- ------ first mutable borrow occurs here - | | + | ----------------- + | | | + | | first mutable borrow occurs here | first borrow later used here error[E0499]: cannot borrow `x` as mutable more than once at a time diff --git a/src/test/ui/borrowck/borrowck-mut-borrow-of-mut-base-ptr.stderr b/src/test/ui/borrowck/borrowck-mut-borrow-of-mut-base-ptr.stderr index f2baee0937..ef811b8490 100644 --- a/src/test/ui/borrowck/borrowck-mut-borrow-of-mut-base-ptr.stderr +++ b/src/test/ui/borrowck/borrowck-mut-borrow-of-mut-base-ptr.stderr @@ -7,7 +7,7 @@ LL | let mut t2 = &mut t0; | ^^^^^^^ mutable borrow occurs here LL | **t2 += 1; // Mutates `*t0` LL | p.use_ref(); - | - immutable borrow later used here + | ----------- immutable borrow later used here error[E0499]: cannot borrow `t0` as mutable more than once at a time --> $DIR/borrowck-mut-borrow-of-mut-base-ptr.rs:19:18 @@ -18,7 +18,7 @@ LL | let mut t2 = &mut t0; | ^^^^^^^ second mutable borrow occurs here LL | **t2 += 1; // Mutates `*t0` but not through `*p` LL | p.use_mut(); - | - first borrow later used here + | ----------- first borrow later used here error: aborting due to 2 previous errors diff --git a/src/test/ui/borrowck/borrowck-mut-uniq.rs b/src/test/ui/borrowck/borrowck-mut-uniq.rs index 80b3484e0f..255b4995b6 100644 --- a/src/test/ui/borrowck/borrowck-mut-uniq.rs +++ b/src/test/ui/borrowck/borrowck-mut-uniq.rs @@ -1,5 +1,4 @@ // run-pass -#![feature(box_syntax)] use std::mem::swap; @@ -20,7 +19,7 @@ fn iter_ints(x: &Ints, mut f: F) -> bool where F: FnMut(&isize) -> bool { } pub fn main() { - let mut ints: Box<_> = box Ints {sum: box 0, values: Vec::new()}; + let mut ints: Box<_> = Box::new(Ints {sum: Box::new(0), values: Vec::new()}); add_int(&mut *ints, 22); add_int(&mut *ints, 44); diff --git a/src/test/ui/borrowck/borrowck-no-cycle-in-exchange-heap.rs b/src/test/ui/borrowck/borrowck-no-cycle-in-exchange-heap.rs index 4c1ff98ce6..f035049d82 100644 --- a/src/test/ui/borrowck/borrowck-no-cycle-in-exchange-heap.rs +++ b/src/test/ui/borrowck/borrowck-no-cycle-in-exchange-heap.rs @@ -1,5 +1,3 @@ -#![feature(box_syntax)] - struct Node_ { a: Box } @@ -8,8 +6,10 @@ enum Cycle { Node(Node_), Empty, } + fn main() { - let mut x: Box<_> = box Cycle::Node(Node_ {a: box Cycle::Empty}); + let mut x: Box<_> = Box::new(Cycle::Node(Node_ {a: Box::new(Cycle::Empty)})); + // Create a cycle! match *x { Cycle::Node(ref mut y) => { diff --git a/src/test/ui/borrowck/borrowck-object-lifetime.nll.stderr b/src/test/ui/borrowck/borrowck-object-lifetime.nll.stderr deleted file mode 100644 index 49c3f861ea..0000000000 --- a/src/test/ui/borrowck/borrowck-object-lifetime.nll.stderr +++ /dev/null @@ -1,23 +0,0 @@ -error[E0502]: cannot borrow `*x` as mutable because it is also borrowed as immutable - --> $DIR/borrowck-object-lifetime.rs:20:13 - | -LL | let y = x.borrowed(); - | - immutable borrow occurs here -LL | let z = x.mut_borrowed(); - | ^ mutable borrow occurs here -LL | y.use_ref(); - | - immutable borrow later used here - -error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable - --> $DIR/borrowck-object-lifetime.rs:26:13 - | -LL | let y = x.borrowed(); - | - immutable borrow occurs here -LL | let z = &mut x; - | ^^^^^^ mutable borrow occurs here -LL | y.use_ref(); - | - immutable borrow later used here - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0502`. diff --git a/src/test/ui/borrowck/borrowck-object-lifetime.stderr b/src/test/ui/borrowck/borrowck-object-lifetime.stderr index cf94c74dec..215ed760ae 100644 --- a/src/test/ui/borrowck/borrowck-object-lifetime.stderr +++ b/src/test/ui/borrowck/borrowck-object-lifetime.stderr @@ -2,21 +2,21 @@ error[E0502]: cannot borrow `*x` as mutable because it is also borrowed as immut --> $DIR/borrowck-object-lifetime.rs:20:13 | LL | let y = x.borrowed(); - | - immutable borrow occurs here + | ------------ immutable borrow occurs here LL | let z = x.mut_borrowed(); | ^^^^^^^^^^^^^^^^ mutable borrow occurs here LL | y.use_ref(); - | - immutable borrow later used here + | ----------- immutable borrow later used here error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable --> $DIR/borrowck-object-lifetime.rs:26:13 | LL | let y = x.borrowed(); - | - immutable borrow occurs here + | ------------ immutable borrow occurs here LL | let z = &mut x; | ^^^^^^ mutable borrow occurs here LL | y.use_ref(); - | - immutable borrow later used here + | ----------- immutable borrow later used here error: aborting due to 2 previous errors diff --git a/src/test/ui/borrowck/borrowck-overloaded-index-autoderef.stderr b/src/test/ui/borrowck/borrowck-overloaded-index-autoderef.stderr index 978e129172..087f2ac799 100644 --- a/src/test/ui/borrowck/borrowck-overloaded-index-autoderef.stderr +++ b/src/test/ui/borrowck/borrowck-overloaded-index-autoderef.stderr @@ -6,7 +6,7 @@ LL | let p = &mut f[&s]; LL | let q = &f[&s]; | ^ immutable borrow occurs here LL | p.use_mut(); - | - mutable borrow later used here + | ----------- mutable borrow later used here error[E0499]: cannot borrow `*f` as mutable more than once at a time --> $DIR/borrowck-overloaded-index-autoderef.rs:43:18 @@ -16,7 +16,7 @@ LL | let p = &mut f[&s]; LL | let q = &mut f[&s]; | ^ second mutable borrow occurs here LL | p.use_mut(); - | - first borrow later used here + | ----------- first borrow later used here error[E0499]: cannot borrow `f.foo` as mutable more than once at a time --> $DIR/borrowck-overloaded-index-autoderef.rs:53:18 @@ -26,7 +26,7 @@ LL | let p = &mut f.foo[&s]; LL | let q = &mut f.foo[&s]; | ^^^^^ second mutable borrow occurs here LL | p.use_mut(); - | - first borrow later used here + | ----------- first borrow later used here error[E0502]: cannot borrow `f.foo` as mutable because it is also borrowed as immutable --> $DIR/borrowck-overloaded-index-autoderef.rs:65:18 @@ -36,7 +36,7 @@ LL | let p = &f.foo[&s]; LL | let q = &mut f.foo[&s]; | ^^^^^ mutable borrow occurs here LL | p.use_ref(); - | - immutable borrow later used here + | ----------- immutable borrow later used here error[E0506]: cannot assign to `f.foo` because it is borrowed --> $DIR/borrowck-overloaded-index-autoderef.rs:71:5 @@ -46,7 +46,7 @@ LL | let p = &f.foo[&s]; LL | f.foo = g; | ^^^^^^^^^ assignment to borrowed `f.foo` occurs here LL | p.use_ref(); - | - borrow later used here + | ----------- borrow later used here error[E0506]: cannot assign to `*f` because it is borrowed --> $DIR/borrowck-overloaded-index-autoderef.rs:77:5 @@ -56,7 +56,7 @@ LL | let p = &f.foo[&s]; LL | *f = g; | ^^^^^^ assignment to borrowed `*f` occurs here LL | p.use_ref(); - | - borrow later used here + | ----------- borrow later used here error[E0506]: cannot assign to `f.foo` because it is borrowed --> $DIR/borrowck-overloaded-index-autoderef.rs:83:5 @@ -66,7 +66,7 @@ LL | let p = &mut f.foo[&s]; LL | f.foo = g; | ^^^^^^^^^ assignment to borrowed `f.foo` occurs here LL | p.use_mut(); - | - borrow later used here + | ----------- borrow later used here error[E0506]: cannot assign to `*f` because it is borrowed --> $DIR/borrowck-overloaded-index-autoderef.rs:89:5 @@ -76,7 +76,7 @@ LL | let p = &mut f.foo[&s]; LL | *f = g; | ^^^^^^ assignment to borrowed `*f` occurs here LL | p.use_mut(); - | - borrow later used here + | ----------- borrow later used here error: aborting due to 8 previous errors diff --git a/src/test/ui/borrowck/borrowck-overloaded-index-move-from-vec.rs b/src/test/ui/borrowck/borrowck-overloaded-index-move-from-vec.rs index ddf6354c97..344d75cc58 100644 --- a/src/test/ui/borrowck/borrowck-overloaded-index-move-from-vec.rs +++ b/src/test/ui/borrowck/borrowck-overloaded-index-move-from-vec.rs @@ -1,5 +1,3 @@ -#![feature(box_syntax)] - use std::ops::Index; struct MyVec { @@ -14,8 +12,10 @@ impl Index for MyVec { } } + + fn main() { - let v = MyVec::> { data: vec![box 1, box 2, box 3] }; + let v = MyVec::> { data: vec![Box::new(1), Box::new(2), Box::new(3)] }; let good = &v[0]; // Shouldn't fail here let bad = v[0]; //~^ ERROR cannot move out of index of `MyVec>` diff --git a/src/test/ui/borrowck/borrowck-report-with-custom-diagnostic.stderr b/src/test/ui/borrowck/borrowck-report-with-custom-diagnostic.stderr index db73d4c04a..d05996413d 100644 --- a/src/test/ui/borrowck/borrowck-report-with-custom-diagnostic.stderr +++ b/src/test/ui/borrowck/borrowck-report-with-custom-diagnostic.stderr @@ -8,7 +8,7 @@ LL | let z = &x; | ^^ immutable borrow occurs here ... LL | y.use_mut(); - | - mutable borrow later used here + | ----------- mutable borrow later used here error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable --> $DIR/borrowck-report-with-custom-diagnostic.rs:21:21 @@ -20,7 +20,7 @@ LL | let z = &mut x; | ^^^^^^ mutable borrow occurs here ... LL | y.use_ref(); - | - immutable borrow later used here + | ----------- immutable borrow later used here error[E0499]: cannot borrow `x` as mutable more than once at a time --> $DIR/borrowck-report-with-custom-diagnostic.rs:36:17 @@ -32,7 +32,7 @@ LL | let z = &mut x; | ^^^^^^ second mutable borrow occurs here ... LL | y.use_mut(); - | - first borrow later used here + | ----------- first borrow later used here error: aborting due to 3 previous errors diff --git a/src/test/ui/borrowck/borrowck-swap-mut-base-ptr.stderr b/src/test/ui/borrowck/borrowck-swap-mut-base-ptr.stderr index 1c55953c91..b39215b9aa 100644 --- a/src/test/ui/borrowck/borrowck-swap-mut-base-ptr.stderr +++ b/src/test/ui/borrowck/borrowck-swap-mut-base-ptr.stderr @@ -7,7 +7,7 @@ LL | swap(&mut t0, &mut t1); | ^^^^^^^ mutable borrow occurs here LL | *t1 = 22; LL | p.use_ref(); - | - immutable borrow later used here + | ----------- immutable borrow later used here error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-union-borrow-nested.stderr b/src/test/ui/borrowck/borrowck-union-borrow-nested.stderr index 61569b9cac..4bd7d54cff 100644 --- a/src/test/ui/borrowck/borrowck-union-borrow-nested.stderr +++ b/src/test/ui/borrowck/borrowck-union-borrow-nested.stderr @@ -6,7 +6,7 @@ LL | let ra = &mut u.s.a; LL | let b = u.c; | ^^^ use of borrowed `u.s.a` LL | ra.use_mut(); - | -- borrow later used here + | ------------ borrow later used here error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-uniq-via-lend.rs b/src/test/ui/borrowck/borrowck-uniq-via-lend.rs index f62880788e..25d3e0b548 100644 --- a/src/test/ui/borrowck/borrowck-uniq-via-lend.rs +++ b/src/test/ui/borrowck/borrowck-uniq-via-lend.rs @@ -1,17 +1,17 @@ -#![feature(box_syntax)] - - - fn borrow(_v: &isize) {} + + + + fn local() { - let mut v: Box<_> = box 3; + let mut v: Box<_> = Box::new(3); borrow(&*v); } fn local_rec() { struct F { f: Box } - let mut v = F {f: box 3}; + let mut v = F {f: Box::new(3)}; borrow(&*v.f); } @@ -19,35 +19,35 @@ fn local_recs() { struct F { f: G } struct G { g: H } struct H { h: Box } - let mut v = F {f: G {g: H {h: box 3}}}; + let mut v = F {f: G {g: H {h: Box::new(3)}}}; borrow(&*v.f.g.h); } fn aliased_imm() { - let mut v: Box<_> = box 3; + let mut v: Box<_> = Box::new(3); let w = &v; borrow(&*v); w.use_ref(); } fn aliased_mut() { - let mut v: Box<_> = box 3; + let mut v: Box<_> = Box::new(3); let w = &mut v; borrow(&*v); //~ ERROR cannot borrow `*v` w.use_mut(); } fn aliased_other() { - let mut v: Box<_> = box 3; - let mut w: Box<_> = box 4; + let mut v: Box<_> = Box::new(3); + let mut w: Box<_> = Box::new(4); let x = &mut w; borrow(&*v); x.use_mut(); } fn aliased_other_reassign() { - let mut v: Box<_> = box 3; - let mut w: Box<_> = box 4; + let mut v: Box<_> = Box::new(3); + let mut w: Box<_> = Box::new(4); let mut x = &mut w; x = &mut v; borrow(&*v); //~ ERROR cannot borrow `*v` diff --git a/src/test/ui/borrowck/borrowck-uniq-via-lend.stderr b/src/test/ui/borrowck/borrowck-uniq-via-lend.stderr index 923edc8eda..6dbe4c74b5 100644 --- a/src/test/ui/borrowck/borrowck-uniq-via-lend.stderr +++ b/src/test/ui/borrowck/borrowck-uniq-via-lend.stderr @@ -6,7 +6,7 @@ LL | let w = &mut v; LL | borrow(&*v); | ^^^ immutable borrow occurs here LL | w.use_mut(); - | - mutable borrow later used here + | ----------- mutable borrow later used here error[E0502]: cannot borrow `*v` as immutable because it is also borrowed as mutable --> $DIR/borrowck-uniq-via-lend.rs:53:12 @@ -16,7 +16,7 @@ LL | x = &mut v; LL | borrow(&*v); | ^^^ immutable borrow occurs here LL | x.use_mut(); - | - mutable borrow later used here + | ----------- mutable borrow later used here error: aborting due to 2 previous errors diff --git a/src/test/ui/borrowck/borrowck-unused-mut-locals.rs b/src/test/ui/borrowck/borrowck-unused-mut-locals.rs index fd0e346e2b..23ef975cbb 100644 --- a/src/test/ui/borrowck/borrowck-unused-mut-locals.rs +++ b/src/test/ui/borrowck/borrowck-unused-mut-locals.rs @@ -1,4 +1,5 @@ // run-pass +#![allow(dead_code)] #![deny(unused_mut)] #[derive(Debug)] diff --git a/src/test/ui/borrowck/borrowck-use-mut-borrow-rpass.rs b/src/test/ui/borrowck/borrowck-use-mut-borrow-rpass.rs index bcd1d3ccd8..1cf763f66f 100644 --- a/src/test/ui/borrowck/borrowck-use-mut-borrow-rpass.rs +++ b/src/test/ui/borrowck/borrowck-use-mut-borrow-rpass.rs @@ -1,41 +1,39 @@ // run-pass // pretty-expanded FIXME #23616 -#![feature(box_syntax)] - struct A { a: isize, b: Box } fn field_copy_after_field_borrow() { - let mut x = A { a: 1, b: box 2 }; + let mut x = A { a: 1, b: Box::new(2) }; let p = &mut x.b; drop(x.a); **p = 3; } fn fu_field_copy_after_field_borrow() { - let mut x = A { a: 1, b: box 2 }; + let mut x = A { a: 1, b: Box::new(2) }; let p = &mut x.b; - let y = A { b: box 3, .. x }; + let y = A { b: Box::new(3), .. x }; drop(y); **p = 4; } fn field_deref_after_field_borrow() { - let mut x = A { a: 1, b: box 2 }; + let mut x = A { a: 1, b: Box::new(2) }; let p = &mut x.a; drop(*x.b); *p = 3; } fn field_move_after_field_borrow() { - let mut x = A { a: 1, b: box 2 }; + let mut x = A { a: 1, b: Box::new(2) }; let p = &mut x.a; drop(x.b); *p = 3; } fn fu_field_move_after_field_borrow() { - let mut x = A { a: 1, b: box 2 }; + let mut x = A { a: 1, b: Box::new(2) }; let p = &mut x.a; let y = A { a: 3, .. x }; drop(y); diff --git a/src/test/ui/borrowck/borrowck-use-mut-borrow.rs b/src/test/ui/borrowck/borrowck-use-mut-borrow.rs index 95b165d6ef..94f88395ff 100644 --- a/src/test/ui/borrowck/borrowck-use-mut-borrow.rs +++ b/src/test/ui/borrowck/borrowck-use-mut-borrow.rs @@ -1,10 +1,10 @@ -#![feature(box_syntax)] - #[derive(Copy, Clone)] struct A { a: isize, b: isize } struct B { a: isize, b: Box } + + fn var_copy_after_var_borrow() { let mut x: isize = 1; let p = &mut x; @@ -50,21 +50,21 @@ fn fu_field_copy_after_field_borrow() { } fn var_deref_after_var_borrow() { - let mut x: Box = box 1; + let mut x: Box = Box::new(1); let p = &mut x; drop(*x); //~ ERROR cannot use `*x` because it was mutably borrowed **p = 2; } fn field_deref_after_var_borrow() { - let mut x = B { a: 1, b: box 2 }; + let mut x = B { a: 1, b: Box::new(2) }; let p = &mut x; drop(*x.b); //~ ERROR cannot use `*x.b` because it was mutably borrowed p.a = 3; } fn field_deref_after_field_borrow() { - let mut x = B { a: 1, b: box 2 }; + let mut x = B { a: 1, b: Box::new(2) }; let p = &mut x.b; drop(*x.b); //~ ERROR cannot use `*x.b` because it was mutably borrowed **p = 3; diff --git a/src/test/ui/borrowck/borrowck-vec-pattern-loan-from-mut.stderr b/src/test/ui/borrowck/borrowck-vec-pattern-loan-from-mut.stderr index 5141fcc1bb..eb0f24b9b7 100644 --- a/src/test/ui/borrowck/borrowck-vec-pattern-loan-from-mut.stderr +++ b/src/test/ui/borrowck/borrowck-vec-pattern-loan-from-mut.stderr @@ -5,8 +5,9 @@ LL | let vb: &mut [isize] = &mut v; | ------ first mutable borrow occurs here ... LL | v.push(tail[0] + tail[1]); - | ^ ------- first borrow later used here - | | + | ^^^^^^^-------^^^^^^^^^^^ + | | | + | | first borrow later used here | second mutable borrow occurs here error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-vec-pattern-nesting.rs b/src/test/ui/borrowck/borrowck-vec-pattern-nesting.rs index 67b6c12ba8..8a9296c597 100644 --- a/src/test/ui/borrowck/borrowck-vec-pattern-nesting.rs +++ b/src/test/ui/borrowck/borrowck-vec-pattern-nesting.rs @@ -1,12 +1,12 @@ #![feature(box_patterns)] -#![feature(box_syntax)] + fn a() { - let mut vec = [box 1, box 2, box 3]; + let mut vec = [Box::new(1), Box::new(2), Box::new(3)]; match vec { [box ref _a, _, _] => { //~^ NOTE borrow of `vec[_]` occurs here - vec[0] = box 4; //~ ERROR cannot assign + vec[0] = Box::new(4); //~ ERROR cannot assign //~^ NOTE assignment to borrowed `vec[_]` occurs here _a.use_ref(); //~^ NOTE borrow later used here @@ -15,12 +15,12 @@ fn a() { } fn b() { - let mut vec = vec![box 1, box 2, box 3]; + let mut vec = vec![Box::new(1), Box::new(2), Box::new(3)]; let vec: &mut [Box] = &mut vec; match vec { &mut [ref _b @ ..] => { //~^ borrow of `vec[_]` occurs here - vec[0] = box 4; //~ ERROR cannot assign + vec[0] = Box::new(4); //~ ERROR cannot assign //~^ NOTE assignment to borrowed `vec[_]` occurs here _b.use_ref(); //~^ NOTE borrow later used here @@ -29,7 +29,7 @@ fn b() { } fn c() { - let mut vec = vec![box 1, box 2, box 3]; + let mut vec = vec![Box::new(1), Box::new(2), Box::new(3)]; let vec: &mut [Box] = &mut vec; match vec { //~^ ERROR cannot move out @@ -50,7 +50,7 @@ fn c() { } fn d() { - let mut vec = vec![box 1, box 2, box 3]; + let mut vec = vec![Box::new(1), Box::new(2), Box::new(3)]; let vec: &mut [Box] = &mut vec; match vec { //~^ ERROR cannot move out @@ -69,7 +69,7 @@ fn d() { } fn e() { - let mut vec = vec![box 1, box 2, box 3]; + let mut vec = vec![Box::new(1), Box::new(2), Box::new(3)]; let vec: &mut [Box] = &mut vec; match vec { //~^ ERROR cannot move out diff --git a/src/test/ui/borrowck/borrowck-vec-pattern-nesting.stderr b/src/test/ui/borrowck/borrowck-vec-pattern-nesting.stderr index 36f8f5c9ad..ddd89afe5b 100644 --- a/src/test/ui/borrowck/borrowck-vec-pattern-nesting.stderr +++ b/src/test/ui/borrowck/borrowck-vec-pattern-nesting.stderr @@ -4,11 +4,11 @@ error[E0506]: cannot assign to `vec[_]` because it is borrowed LL | [box ref _a, _, _] => { | ------ borrow of `vec[_]` occurs here LL | -LL | vec[0] = box 4; +LL | vec[0] = Box::new(4); | ^^^^^^ assignment to borrowed `vec[_]` occurs here LL | LL | _a.use_ref(); - | -- borrow later used here + | ------------ borrow later used here error[E0506]: cannot assign to `vec[_]` because it is borrowed --> $DIR/borrowck-vec-pattern-nesting.rs:23:13 @@ -16,11 +16,11 @@ error[E0506]: cannot assign to `vec[_]` because it is borrowed LL | &mut [ref _b @ ..] => { | ----------- borrow of `vec[_]` occurs here LL | -LL | vec[0] = box 4; +LL | vec[0] = Box::new(4); | ^^^^^^ assignment to borrowed `vec[_]` occurs here LL | LL | _b.use_ref(); - | -- borrow later used here + | ------------ borrow later used here error[E0508]: cannot move out of type `[Box]`, a non-copy slice --> $DIR/borrowck-vec-pattern-nesting.rs:34:11 diff --git a/src/test/ui/borrowck/fsu-moves-and-copies.rs b/src/test/ui/borrowck/fsu-moves-and-copies.rs index 6a0b4ed17b..85e0a840a1 100644 --- a/src/test/ui/borrowck/fsu-moves-and-copies.rs +++ b/src/test/ui/borrowck/fsu-moves-and-copies.rs @@ -5,7 +5,7 @@ // Issue 4691: Ensure that functional-struct-updates operates // correctly and moves rather than copy when appropriate. -#![feature(box_syntax, core)] +#![feature(core)] struct ncint { v: isize } fn ncint(v: isize) -> ncint { ncint { v: v } } @@ -17,7 +17,7 @@ impl NoFoo { struct MoveFoo { copied: isize, moved: Box, } impl MoveFoo { - fn new(x:isize,y:isize) -> MoveFoo { MoveFoo { copied: x, moved: box y } } + fn new(x:isize,y:isize) -> MoveFoo { MoveFoo { copied: x, moved: Box::new(y) } } } struct DropNoFoo { inner: NoFoo } @@ -53,8 +53,8 @@ fn test0() { // Case 2: Owned let f = DropMoveFoo::new(5, 6); - let b = DropMoveFoo { inner: MoveFoo { moved: box 7, ..f.inner }}; - let c = DropMoveFoo { inner: MoveFoo { moved: box 8, ..f.inner }}; + let b = DropMoveFoo { inner: MoveFoo { moved: Box::new(7), ..f.inner }}; + let c = DropMoveFoo { inner: MoveFoo { moved: Box::new(8), ..f.inner }}; assert_eq!(f.inner.copied, 5); assert_eq!(*f.inner.moved, 6); @@ -69,7 +69,7 @@ fn test1() { // copying move-by-default fields from `f`, so it moves: let f = MoveFoo::new(11, 12); - let b = MoveFoo {moved: box 13, ..f}; + let b = MoveFoo {moved: Box::new(13), ..f}; let c = MoveFoo {copied: 14, ..f}; assert_eq!(b.copied, 11); assert_eq!(*b.moved, 13); diff --git a/src/test/ui/borrowck/index-mut-help-with-impl.stderr b/src/test/ui/borrowck/index-mut-help-with-impl.stderr index 89391f4099..69dca7e7b5 100644 --- a/src/test/ui/borrowck/index-mut-help-with-impl.stderr +++ b/src/test/ui/borrowck/index-mut-help-with-impl.stderr @@ -2,7 +2,7 @@ error[E0596]: cannot borrow data in a `&` reference as mutable --> $DIR/index-mut-help-with-impl.rs:9:5 | LL | Index::index(&v, 1..2).make_ascii_uppercase(); - | ^^^^^^^^^^^^^^^^^^^^^^ cannot borrow as mutable + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot borrow as mutable error: aborting due to previous error diff --git a/src/test/ui/borrowck/index-mut-help.stderr b/src/test/ui/borrowck/index-mut-help.stderr index 52b9ad496e..057c6ee15f 100644 --- a/src/test/ui/borrowck/index-mut-help.stderr +++ b/src/test/ui/borrowck/index-mut-help.stderr @@ -2,7 +2,7 @@ error[E0596]: cannot borrow data in an index of `HashMap<&str, String>` as mutab --> $DIR/index-mut-help.rs:11:5 | LL | map["peter"].clear(); - | ^^^^^^^^^^^^ cannot borrow as mutable + | ^^^^^^^^^^^^^^^^^^^^ cannot borrow as mutable | = help: trait `IndexMut` is required to modify indexed content, but it is not implemented for `HashMap<&str, String>` diff --git a/src/test/ui/borrowck/issue-17263.rs b/src/test/ui/borrowck/issue-17263.rs index 7e9ff68548..4f560b065f 100644 --- a/src/test/ui/borrowck/issue-17263.rs +++ b/src/test/ui/borrowck/issue-17263.rs @@ -1,14 +1,12 @@ // check-pass -#![feature(box_syntax)] - struct Foo { a: isize, b: isize } fn main() { - let mut x: Box<_> = box Foo { a: 1, b: 2 }; + let mut x: Box<_> = Box::new(Foo { a: 1, b: 2 }); let (a, b) = (&mut x.a, &mut x.b); - let mut foo: Box<_> = box Foo { a: 1, b: 2 }; + let mut foo: Box<_> = Box::new(Foo { a: 1, b: 2 }); let (c, d) = (&mut foo.a, &foo.b); // We explicitly use the references created above to illustrate that the diff --git a/src/test/ui/borrowck/issue-42344.stderr b/src/test/ui/borrowck/issue-42344.stderr index 5cffa1b512..29b4c8c38d 100644 --- a/src/test/ui/borrowck/issue-42344.stderr +++ b/src/test/ui/borrowck/issue-42344.stderr @@ -2,7 +2,7 @@ error[E0596]: cannot borrow `*TAB[_]` as mutable, as `TAB` is an immutable stati --> $DIR/issue-42344.rs:4:5 | LL | TAB[0].iter_mut(); - | ^^^^^^ cannot borrow as mutable + | ^^^^^^^^^^^^^^^^^ cannot borrow as mutable error: aborting due to previous error diff --git a/src/test/ui/borrowck/issue-51117.stderr b/src/test/ui/borrowck/issue-51117.stderr index f8a9608ad3..ef1a16ea95 100644 --- a/src/test/ui/borrowck/issue-51117.stderr +++ b/src/test/ui/borrowck/issue-51117.stderr @@ -4,7 +4,7 @@ error[E0499]: cannot borrow `*bar` as mutable more than once at a time LL | Some(baz) => { | --- first mutable borrow occurs here LL | bar.take(); - | ^^^ second mutable borrow occurs here + | ^^^^^^^^^^ second mutable borrow occurs here LL | drop(baz); | --- first borrow later used here diff --git a/src/test/ui/borrowck/issue-81365-10.stderr b/src/test/ui/borrowck/issue-81365-10.stderr index 891f70ed7f..27123ef2be 100644 --- a/src/test/ui/borrowck/issue-81365-10.stderr +++ b/src/test/ui/borrowck/issue-81365-10.stderr @@ -2,7 +2,7 @@ error[E0506]: cannot assign to `self.container_field` because it is borrowed --> $DIR/issue-81365-10.rs:21:9 | LL | let first = &self.deref().target_field; - | ---- borrow of `self.container_field` occurs here + | ------------ borrow of `self.container_field` occurs here LL | self.container_field = true; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ assignment to borrowed `self.container_field` occurs here LL | first; diff --git a/src/test/ui/borrowck/issue-81365-5.stderr b/src/test/ui/borrowck/issue-81365-5.stderr index 7c0e9f43bd..8201894c6d 100644 --- a/src/test/ui/borrowck/issue-81365-5.stderr +++ b/src/test/ui/borrowck/issue-81365-5.stderr @@ -2,7 +2,7 @@ error[E0506]: cannot assign to `self.container_field` because it is borrowed --> $DIR/issue-81365-5.rs:28:9 | LL | let first = self.get(); - | ---- borrow of `self.container_field` occurs here + | ---------- borrow of `self.container_field` occurs here LL | self.container_field = true; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ assignment to borrowed `self.container_field` occurs here LL | first; diff --git a/src/test/ui/borrowck/issue-82032.stderr b/src/test/ui/borrowck/issue-82032.stderr index f272477a9f..25f343117a 100644 --- a/src/test/ui/borrowck/issue-82032.stderr +++ b/src/test/ui/borrowck/issue-82032.stderr @@ -7,7 +7,7 @@ LL | for v in self.0.values() { | | help: use mutable method: `values_mut()` | this iterator yields `&` references LL | v.flush(); - | ^ `v` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | ^^^^^^^^^ `v` is a `&` reference, so the data it refers to cannot be borrowed as mutable error: aborting due to previous error diff --git a/src/test/ui/borrowck/issue-82126-mismatched-subst-and-hir.rs b/src/test/ui/borrowck/issue-82126-mismatched-subst-and-hir.rs index 569769b821..dd0320bc53 100644 --- a/src/test/ui/borrowck/issue-82126-mismatched-subst-and-hir.rs +++ b/src/test/ui/borrowck/issue-82126-mismatched-subst-and-hir.rs @@ -17,7 +17,6 @@ async fn buy_lock(generator: &Mutex) -> LockedMarket<'_> { //~^ ERROR this struct takes 0 lifetime arguments but 1 lifetime argument was supplied //~^^ ERROR this struct takes 1 generic argument but 0 generic arguments were supplied LockedMarket(generator.lock().unwrap().buy()) - //~^ ERROR cannot return value referencing temporary value } struct LockedMarket(T); diff --git a/src/test/ui/borrowck/issue-82126-mismatched-subst-and-hir.stderr b/src/test/ui/borrowck/issue-82126-mismatched-subst-and-hir.stderr index 4bd0667304..d2b927fb66 100644 --- a/src/test/ui/borrowck/issue-82126-mismatched-subst-and-hir.stderr +++ b/src/test/ui/borrowck/issue-82126-mismatched-subst-and-hir.stderr @@ -7,7 +7,7 @@ LL | async fn buy_lock(generator: &Mutex) -> LockedMarket<'_> | expected 0 lifetime arguments | note: struct defined here, with 0 lifetime parameters - --> $DIR/issue-82126-mismatched-subst-and-hir.rs:23:8 + --> $DIR/issue-82126-mismatched-subst-and-hir.rs:22:8 | LL | struct LockedMarket(T); | ^^^^^^^^^^^^ @@ -19,7 +19,7 @@ LL | async fn buy_lock(generator: &Mutex) -> LockedMarket<'_> | ^^^^^^^^^^^^ expected 1 generic argument | note: struct defined here, with 1 generic parameter: `T` - --> $DIR/issue-82126-mismatched-subst-and-hir.rs:23:8 + --> $DIR/issue-82126-mismatched-subst-and-hir.rs:22:8 | LL | struct LockedMarket(T); | ^^^^^^^^^^^^ - @@ -28,16 +28,6 @@ help: add missing generic argument LL | async fn buy_lock(generator: &Mutex) -> LockedMarket<'_, T> { | +++ -error[E0515]: cannot return value referencing temporary value - --> $DIR/issue-82126-mismatched-subst-and-hir.rs:19:5 - | -LL | LockedMarket(generator.lock().unwrap().buy()) - | ^^^^^^^^^^^^^-------------------------^^^^^^^ - | | | - | | temporary value created here - | returns a value referencing data owned by the current function +error: aborting due to 2 previous errors -error: aborting due to 3 previous errors - -Some errors have detailed explanations: E0107, E0515. -For more information about an error, try `rustc --explain E0107`. +For more information about this error, try `rustc --explain E0107`. diff --git a/src/test/ui/borrowck/issue-82462.rs b/src/test/ui/borrowck/issue-82462.rs new file mode 100644 index 0000000000..5a3c64255c --- /dev/null +++ b/src/test/ui/borrowck/issue-82462.rs @@ -0,0 +1,21 @@ +struct DroppingSlice<'a>(&'a [i32]); + +impl Drop for DroppingSlice<'_> { + fn drop(&mut self) { + println!("hi from slice"); + } +} + +impl DroppingSlice<'_> { + fn iter(&self) -> std::slice::Iter<'_, i32> { + self.0.iter() + } +} + +fn main() { + let mut v = vec![1, 2, 3, 4]; + for x in DroppingSlice(&*v).iter() { + v.push(*x); //~ERROR + break; + } +} diff --git a/src/test/ui/borrowck/issue-82462.stderr b/src/test/ui/borrowck/issue-82462.stderr new file mode 100644 index 0000000000..a2c291f779 --- /dev/null +++ b/src/test/ui/borrowck/issue-82462.stderr @@ -0,0 +1,22 @@ +error[E0502]: cannot borrow `v` as mutable because it is also borrowed as immutable + --> $DIR/issue-82462.rs:18:9 + | +LL | for x in DroppingSlice(&*v).iter() { + | ------------------ + | | | + | | immutable borrow occurs here + | a temporary with access to the immutable borrow is created here ... +LL | v.push(*x); + | ^^^^^^^^^^ mutable borrow occurs here +LL | break; +LL | } + | - ... and the immutable borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `DroppingSlice` + | +help: consider adding semicolon after the expression so its temporaries are dropped sooner, before the local variables declared by the block are dropped + | +LL | }; + | + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0502`. diff --git a/src/test/ui/borrowck/issue-85581.stderr b/src/test/ui/borrowck/issue-85581.stderr index 29c0429f2a..59ca4867fd 100644 --- a/src/test/ui/borrowck/issue-85581.stderr +++ b/src/test/ui/borrowck/issue-85581.stderr @@ -7,7 +7,7 @@ LL | match heap.peek_mut() { | first mutable borrow occurs here | a temporary with access to the first borrow is created here ... LL | Some(_) => { heap.pop(); }, - | ^^^^ second mutable borrow occurs here + | ^^^^^^^^^^ second mutable borrow occurs here ... LL | } | - ... and the first borrow might be used here, when that temporary is dropped and runs the destructor for type `Option>` diff --git a/src/test/ui/borrowck/issue-85765.stderr b/src/test/ui/borrowck/issue-85765.stderr index af83c6ea6d..80acaa7d21 100644 --- a/src/test/ui/borrowck/issue-85765.stderr +++ b/src/test/ui/borrowck/issue-85765.stderr @@ -5,7 +5,7 @@ LL | let rofl: &Vec> = &mut test; | ---- help: consider changing this to be a mutable reference: `&mut Vec>` LL | LL | rofl.push(Vec::new()); - | ^^^^ `rofl` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | ^^^^^^^^^^^^^^^^^^^^^ `rofl` is a `&` reference, so the data it refers to cannot be borrowed as mutable error[E0594]: cannot assign to `*r`, which is behind a `&` reference --> $DIR/issue-85765.rs:12:5 diff --git a/src/test/ui/borrowck/issue-87456-point-to-closure.rs b/src/test/ui/borrowck/issue-87456-point-to-closure.rs new file mode 100644 index 0000000000..9fc12ba749 --- /dev/null +++ b/src/test/ui/borrowck/issue-87456-point-to-closure.rs @@ -0,0 +1,14 @@ +// Regression test for #87456. + +fn take_mut(_val: impl FnMut()) {} + +fn main() { + let val = String::new(); + //~^ NOTE: captured outer variable + take_mut(|| { + //~^ NOTE: captured by this `FnMut` closure + let _foo: String = val; + //~^ ERROR: cannot move out of `val`, a captured variable in an `FnMut` closure [E0507] + //~| NOTE: move occurs because + }) +} diff --git a/src/test/ui/borrowck/issue-87456-point-to-closure.stderr b/src/test/ui/borrowck/issue-87456-point-to-closure.stderr new file mode 100644 index 0000000000..fd38ad7bb0 --- /dev/null +++ b/src/test/ui/borrowck/issue-87456-point-to-closure.stderr @@ -0,0 +1,22 @@ +error[E0507]: cannot move out of `val`, a captured variable in an `FnMut` closure + --> $DIR/issue-87456-point-to-closure.rs:10:28 + | +LL | let val = String::new(); + | --- captured outer variable +LL | +LL | take_mut(|| { + | ______________- +LL | | +LL | | let _foo: String = val; + | | ^^^ + | | | + | | move occurs because `val` has type `String`, which does not implement the `Copy` trait + | | help: consider borrowing here: `&val` +LL | | +LL | | +LL | | }) + | |_____- captured by this `FnMut` closure + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0507`. diff --git a/src/test/ui/borrowck/issue-88434-minimal-example.rs b/src/test/ui/borrowck/issue-88434-minimal-example.rs new file mode 100644 index 0000000000..db348a50aa --- /dev/null +++ b/src/test/ui/borrowck/issue-88434-minimal-example.rs @@ -0,0 +1,13 @@ +#![feature(const_fn_trait_bound)] +// Regression test related to issue 88434 + +const _CONST: &() = &f(&|_| {}); + +const fn f(_: &F) +where + F: FnMut(&u8), +{ + panic!() //~ ERROR evaluation of constant value failed +} + +fn main() { } diff --git a/src/test/ui/borrowck/issue-88434-minimal-example.stderr b/src/test/ui/borrowck/issue-88434-minimal-example.stderr new file mode 100644 index 0000000000..845e1bdba8 --- /dev/null +++ b/src/test/ui/borrowck/issue-88434-minimal-example.stderr @@ -0,0 +1,17 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/issue-88434-minimal-example.rs:10:5 + | +LL | const _CONST: &() = &f(&|_| {}); + | ---------- inside `_CONST` at $DIR/issue-88434-minimal-example.rs:4:22 +... +LL | panic!() + | ^^^^^^^^ + | | + | the evaluated program panicked at 'explicit panic', $DIR/issue-88434-minimal-example.rs:10:5 + | inside `f::<[closure@$DIR/issue-88434-minimal-example.rs:4:25: 4:31]>` at $SRC_DIR/std/src/panic.rs:LL:COL + | + = note: this error originates in the macro `$crate::panic::panic_2015` (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 E0080`. diff --git a/src/test/ui/borrowck/issue-88434-removal-index-should-be-less.rs b/src/test/ui/borrowck/issue-88434-removal-index-should-be-less.rs new file mode 100644 index 0000000000..4db073c66b --- /dev/null +++ b/src/test/ui/borrowck/issue-88434-removal-index-should-be-less.rs @@ -0,0 +1,13 @@ +#![feature(const_fn_trait_bound)] +// Regression test for issue 88434 + +const _CONST: &[u8] = &f(&[], |_| {}); + +const fn f(_: &[u8], _: F) -> &[u8] +where + F: FnMut(&u8), +{ + panic!() //~ ERROR evaluation of constant value failed +} + +fn main() { } diff --git a/src/test/ui/borrowck/issue-88434-removal-index-should-be-less.stderr b/src/test/ui/borrowck/issue-88434-removal-index-should-be-less.stderr new file mode 100644 index 0000000000..8cbb6a6340 --- /dev/null +++ b/src/test/ui/borrowck/issue-88434-removal-index-should-be-less.stderr @@ -0,0 +1,17 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/issue-88434-removal-index-should-be-less.rs:10:5 + | +LL | const _CONST: &[u8] = &f(&[], |_| {}); + | -------------- inside `_CONST` at $DIR/issue-88434-removal-index-should-be-less.rs:4:24 +... +LL | panic!() + | ^^^^^^^^ + | | + | the evaluated program panicked at 'explicit panic', $DIR/issue-88434-removal-index-should-be-less.rs:10:5 + | inside `f::<[closure@$DIR/issue-88434-removal-index-should-be-less.rs:4:31: 4:37]>` at $SRC_DIR/std/src/panic.rs:LL:COL + | + = note: this error originates in the macro `$crate::panic::panic_2015` (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 E0080`. diff --git a/src/test/ui/borrowck/move-error-snippets.stderr b/src/test/ui/borrowck/move-error-snippets.stderr index e7ecd0079f..78f99e9041 100644 --- a/src/test/ui/borrowck/move-error-snippets.stderr +++ b/src/test/ui/borrowck/move-error-snippets.stderr @@ -10,7 +10,7 @@ LL | let a = $c; ::: $DIR/move-error-snippets.rs:21:1 | LL | sss!(); - | ------- in this macro invocation + | ------ in this macro invocation | = note: this error originates in the macro `aaa` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/borrowck/mut-borrow-of-mut-ref.stderr b/src/test/ui/borrowck/mut-borrow-of-mut-ref.stderr index e4c51bb77c..2ffe7ff641 100644 --- a/src/test/ui/borrowck/mut-borrow-of-mut-ref.stderr +++ b/src/test/ui/borrowck/mut-borrow-of-mut-ref.stderr @@ -53,7 +53,7 @@ error[E0596]: cannot borrow `f` as mutable, as it is not declared as mutable --> $DIR/mut-borrow-of-mut-ref.rs:35:5 | LL | f.bar(); - | ^ cannot borrow as mutable + | ^^^^^^^ cannot borrow as mutable | help: consider making the binding mutable | diff --git a/src/test/ui/borrowck/mut-borrow-outside-loop.stderr b/src/test/ui/borrowck/mut-borrow-outside-loop.stderr index 4fcb693f1b..e6895b27f3 100644 --- a/src/test/ui/borrowck/mut-borrow-outside-loop.stderr +++ b/src/test/ui/borrowck/mut-borrow-outside-loop.stderr @@ -6,7 +6,7 @@ LL | let first = &mut void; LL | let second = &mut void; | ^^^^^^^^^ second mutable borrow occurs here LL | first.use_mut(); - | ----- first borrow later used here + | --------------- first borrow later used here error[E0499]: cannot borrow `inner_void` as mutable more than once at a time --> $DIR/mut-borrow-outside-loop.rs:15:28 @@ -17,7 +17,7 @@ LL | let inner_second = &mut inner_void; | ^^^^^^^^^^^^^^^ second mutable borrow occurs here LL | inner_second.use_mut(); LL | inner_first.use_mut(); - | ----------- first borrow later used here + | --------------------- first borrow later used here error: aborting due to 2 previous errors 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 ad39b3601b..536fd43ef7 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 @@ -24,12 +24,12 @@ LL | fn wrong_bound1<'b,'c,'d:'a+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d | = note: expected fn pointer `fn(&'a isize, Inv<'c>, Inv<'c>, Inv<'_>)` found fn pointer `fn(&'a isize, Inv<'_>, Inv<'c>, Inv<'_>)` -note: the lifetime `'c` as defined on the method body at 27:24... +note: the lifetime `'c` as defined here... --> $DIR/regions-bound-missing-bound-in-impl.rs:27:24 | LL | fn wrong_bound1<'b,'c,'d:'a+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>) { | ^^ -note: ...does not necessarily outlive the lifetime `'c` as defined on the method body at 27:24 +note: ...does not necessarily outlive the lifetime `'c` as defined here --> $DIR/regions-bound-missing-bound-in-impl.rs:27:24 | LL | fn wrong_bound1<'b,'c,'d:'a+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>) { @@ -43,12 +43,12 @@ LL | fn wrong_bound1<'b,'c,'d:'a+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d | = note: expected fn pointer `fn(&'a isize, Inv<'c>, Inv<'c>, Inv<'_>)` found fn pointer `fn(&'a isize, Inv<'_>, Inv<'c>, Inv<'_>)` -note: the lifetime `'c` as defined on the method body at 27:24... +note: the lifetime `'c` as defined here... --> $DIR/regions-bound-missing-bound-in-impl.rs:27:24 | LL | fn wrong_bound1<'b,'c,'d:'a+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>) { | ^^ -note: ...does not necessarily outlive the lifetime `'c` as defined on the method body at 27:24 +note: ...does not necessarily outlive the lifetime `'c` as defined here --> $DIR/regions-bound-missing-bound-in-impl.rs:27:24 | LL | fn wrong_bound1<'b,'c,'d:'a+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>) { diff --git a/src/test/ui/borrowck/two-phase-across-loop.stderr b/src/test/ui/borrowck/two-phase-across-loop.stderr index d4e515d12b..95896c6bbf 100644 --- a/src/test/ui/borrowck/two-phase-across-loop.stderr +++ b/src/test/ui/borrowck/two-phase-across-loop.stderr @@ -2,7 +2,7 @@ error[E0499]: cannot borrow `foo` as mutable more than once at a time --> $DIR/two-phase-across-loop.rs:17:22 | LL | strings.push(foo.get_string()); - | ^^^ `foo` was mutably borrowed here in the previous iteration of the loop + | ^^^^^^^^^^^^^^^^ `foo` was mutably borrowed here in the previous iteration of the loop error: aborting due to previous error diff --git a/src/test/ui/borrowck/two-phase-cannot-nest-mut-self-calls.stderr b/src/test/ui/borrowck/two-phase-cannot-nest-mut-self-calls.stderr index 9bfd8b994b..a89bb94153 100644 --- a/src/test/ui/borrowck/two-phase-cannot-nest-mut-self-calls.stderr +++ b/src/test/ui/borrowck/two-phase-cannot-nest-mut-self-calls.stderr @@ -1,13 +1,18 @@ error[E0502]: cannot borrow `vec` as mutable because it is also borrowed as immutable --> $DIR/two-phase-cannot-nest-mut-self-calls.rs:16:9 | -LL | vec.get({ - | --- --- immutable borrow later used by call - | | - | immutable borrow occurs here -LL | -LL | vec.push(2); - | ^^^ mutable borrow occurs here +LL | vec.get({ + | - --- immutable borrow later used by call + | _____| + | | +LL | | +LL | | vec.push(2); + | | ^^^^^^^^^^^ mutable borrow occurs here +LL | | +LL | | +LL | | 0 +LL | | }); + | |______- immutable borrow occurs here error: aborting due to previous error diff --git a/src/test/ui/borrowck/two-phase-multi-mut.stderr b/src/test/ui/borrowck/two-phase-multi-mut.stderr index 33fa4a3a15..2e53e17a31 100644 --- a/src/test/ui/borrowck/two-phase-multi-mut.stderr +++ b/src/test/ui/borrowck/two-phase-multi-mut.stderr @@ -12,8 +12,9 @@ error[E0499]: cannot borrow `foo` as mutable more than once at a time --> $DIR/two-phase-multi-mut.rs:11:16 | LL | foo.method(&mut foo); - | --- ------ ^^^^^^^^ second mutable borrow occurs here - | | | + | -----------^^^^^^^^- + | | | | + | | | second mutable borrow occurs here | | first borrow later used by call | first mutable borrow occurs here diff --git a/src/test/ui/borrowck/two-phase-reservation-sharing-interference-2.migrate2015.stderr b/src/test/ui/borrowck/two-phase-reservation-sharing-interference-2.migrate2015.stderr index e4fceb197b..6cff53399c 100644 --- a/src/test/ui/borrowck/two-phase-reservation-sharing-interference-2.migrate2015.stderr +++ b/src/test/ui/borrowck/two-phase-reservation-sharing-interference-2.migrate2015.stderr @@ -27,8 +27,9 @@ LL | let shared = &v; | -- immutable borrow occurs here LL | LL | v.push(shared.len()); - | ^ ------ immutable borrow later used here - | | + | ^^^^^^^------------^ + | | | + | | immutable borrow later used here | mutable borrow occurs here | = note: `#[warn(mutable_borrow_reservation_conflict)]` on by default diff --git a/src/test/ui/borrowck/two-phase-reservation-sharing-interference-2.migrate2018.stderr b/src/test/ui/borrowck/two-phase-reservation-sharing-interference-2.migrate2018.stderr index e4fceb197b..6cff53399c 100644 --- a/src/test/ui/borrowck/two-phase-reservation-sharing-interference-2.migrate2018.stderr +++ b/src/test/ui/borrowck/two-phase-reservation-sharing-interference-2.migrate2018.stderr @@ -27,8 +27,9 @@ LL | let shared = &v; | -- immutable borrow occurs here LL | LL | v.push(shared.len()); - | ^ ------ immutable borrow later used here - | | + | ^^^^^^^------------^ + | | | + | | immutable borrow later used here | mutable borrow occurs here | = note: `#[warn(mutable_borrow_reservation_conflict)]` on by default diff --git a/src/test/ui/borrowck/two-phase-reservation-sharing-interference-2.nll2015.stderr b/src/test/ui/borrowck/two-phase-reservation-sharing-interference-2.nll2015.stderr index 52017394e8..0ae6fe78c6 100644 --- a/src/test/ui/borrowck/two-phase-reservation-sharing-interference-2.nll2015.stderr +++ b/src/test/ui/borrowck/two-phase-reservation-sharing-interference-2.nll2015.stderr @@ -5,8 +5,9 @@ LL | let shared = &v; | -- immutable borrow occurs here LL | LL | v.extend(shared); - | ^ ------ immutable borrow later used here - | | + | ^^^^^^^^^------^ + | | | + | | immutable borrow later used here | mutable borrow occurs here error[E0502]: cannot borrow `v` as mutable because it is also borrowed as immutable @@ -26,8 +27,9 @@ LL | let shared = &v; | -- immutable borrow occurs here LL | LL | v.push(shared.len()); - | ^ ------ immutable borrow later used here - | | + | ^^^^^^^------------^ + | | | + | | immutable borrow later used here | mutable borrow occurs here error: aborting due to 3 previous errors diff --git a/src/test/ui/borrowck/two-phase-reservation-sharing-interference-2.nll2018.stderr b/src/test/ui/borrowck/two-phase-reservation-sharing-interference-2.nll2018.stderr index 52017394e8..0ae6fe78c6 100644 --- a/src/test/ui/borrowck/two-phase-reservation-sharing-interference-2.nll2018.stderr +++ b/src/test/ui/borrowck/two-phase-reservation-sharing-interference-2.nll2018.stderr @@ -5,8 +5,9 @@ LL | let shared = &v; | -- immutable borrow occurs here LL | LL | v.extend(shared); - | ^ ------ immutable borrow later used here - | | + | ^^^^^^^^^------^ + | | | + | | immutable borrow later used here | mutable borrow occurs here error[E0502]: cannot borrow `v` as mutable because it is also borrowed as immutable @@ -26,8 +27,9 @@ LL | let shared = &v; | -- immutable borrow occurs here LL | LL | v.push(shared.len()); - | ^ ------ immutable borrow later used here - | | + | ^^^^^^^------------^ + | | | + | | immutable borrow later used here | mutable borrow occurs here error: aborting due to 3 previous errors diff --git a/src/test/ui/borrowck/two-phase-reservation-sharing-interference-future-compat-lint.nll.stderr b/src/test/ui/borrowck/two-phase-reservation-sharing-interference-future-compat-lint.nll.stderr index d2ea5ab207..52e8de3c4a 100644 --- a/src/test/ui/borrowck/two-phase-reservation-sharing-interference-future-compat-lint.nll.stderr +++ b/src/test/ui/borrowck/two-phase-reservation-sharing-interference-future-compat-lint.nll.stderr @@ -5,8 +5,9 @@ LL | let shared = &v; | -- immutable borrow occurs here LL | LL | v.push(shared.len()); - | ^ ------ immutable borrow later used here - | | + | ^^^^^^^------------^ + | | | + | | immutable borrow later used here | mutable borrow occurs here error[E0502]: cannot borrow `v` as mutable because it is also borrowed as immutable @@ -16,8 +17,9 @@ LL | let shared = &v; | -- immutable borrow occurs here LL | LL | v.push(shared.len()); - | ^ ------ immutable borrow later used here - | | + | ^^^^^^^------------^ + | | | + | | immutable borrow later used here | mutable borrow occurs here error[E0502]: cannot borrow `v` as mutable because it is also borrowed as immutable @@ -27,8 +29,9 @@ LL | let shared = &v; | -- immutable borrow occurs here LL | LL | v.push(shared.len()); - | ^ ------ immutable borrow later used here - | | + | ^^^^^^^------------^ + | | | + | | immutable borrow later used here | mutable borrow occurs here error: aborting due to 3 previous errors diff --git a/src/test/ui/borrowck/two-phase-reservation-sharing-interference-future-compat-lint.stderr b/src/test/ui/borrowck/two-phase-reservation-sharing-interference-future-compat-lint.stderr index 03f49d2d92..aab21c9e78 100644 --- a/src/test/ui/borrowck/two-phase-reservation-sharing-interference-future-compat-lint.stderr +++ b/src/test/ui/borrowck/two-phase-reservation-sharing-interference-future-compat-lint.stderr @@ -5,8 +5,9 @@ LL | let shared = &v; | -- immutable borrow occurs here LL | LL | v.push(shared.len()); - | ^ ------ immutable borrow later used here - | | + | ^^^^^^^------------^ + | | | + | | immutable borrow later used here | mutable borrow occurs here | note: the lint level is defined here @@ -24,8 +25,9 @@ LL | let shared = &v; | -- immutable borrow occurs here LL | LL | v.push(shared.len()); - | ^ ------ immutable borrow later used here - | | + | ^^^^^^^------------^ + | | | + | | immutable borrow later used here | mutable borrow occurs here | note: the lint level is defined here diff --git a/src/test/ui/borrowck/two-phase-sneaky.stderr b/src/test/ui/borrowck/two-phase-sneaky.stderr index c66f3cbed9..cffbf0706f 100644 --- a/src/test/ui/borrowck/two-phase-sneaky.stderr +++ b/src/test/ui/borrowck/two-phase-sneaky.stderr @@ -7,7 +7,7 @@ LL | v[0].push_str({ | first mutable borrow occurs here LL | LL | v.push(format!("foo")); - | ^ second mutable borrow occurs here + | ^^^^^^^^^^^^^^^^^^^^^^ second mutable borrow occurs here error: aborting due to previous error diff --git a/src/test/ui/borrowck/two-phase-surprise-no-conflict.stderr b/src/test/ui/borrowck/two-phase-surprise-no-conflict.stderr index 7d0e156675..5a240d9001 100644 --- a/src/test/ui/borrowck/two-phase-surprise-no-conflict.stderr +++ b/src/test/ui/borrowck/two-phase-surprise-no-conflict.stderr @@ -13,7 +13,7 @@ error[E0502]: cannot borrow `*self` as mutable because it is also borrowed as im --> $DIR/two-phase-surprise-no-conflict.rs:57:17 | LL | self.hash_expr(&self.cx_mut.body(eid).value); - | ^^^^^---------^^-----------^^^^^^^^^^^^^^^^^ + | ^^^^^---------^^---------------------^^^^^^^ | | | | | | | immutable borrow occurs here | | immutable borrow later used by call @@ -23,8 +23,9 @@ error[E0499]: cannot borrow `reg.sess_mut` as mutable more than once at a time --> $DIR/two-phase-surprise-no-conflict.rs:119:51 | LL | reg.register_static(Box::new(TrivialPass::new(&mut reg.sess_mut))); - | --- --------------- ^^^^^^^^^^^^^^^^^ second mutable borrow occurs here - | | | + | ----------------------------------------------^^^^^^^^^^^^^^^^^--- + | | | | + | | | second mutable borrow occurs here | | first borrow later used by call | first mutable borrow occurs here @@ -32,8 +33,9 @@ error[E0499]: cannot borrow `reg.sess_mut` as mutable more than once at a time --> $DIR/two-phase-surprise-no-conflict.rs:122:54 | LL | reg.register_bound(Box::new(TrivialPass::new_mut(&mut reg.sess_mut))); - | --- -------------- ^^^^^^^^^^^^^^^^^ second mutable borrow occurs here - | | | + | -------------------------------------------------^^^^^^^^^^^^^^^^^--- + | | | | + | | | second mutable borrow occurs here | | first borrow later used by call | first mutable borrow occurs here @@ -41,8 +43,9 @@ error[E0499]: cannot borrow `reg.sess_mut` as mutable more than once at a time --> $DIR/two-phase-surprise-no-conflict.rs:125:53 | LL | reg.register_univ(Box::new(TrivialPass::new_mut(&mut reg.sess_mut))); - | --- ------------- ^^^^^^^^^^^^^^^^^ second mutable borrow occurs here - | | | + | ------------------------------------------------^^^^^^^^^^^^^^^^^--- + | | | | + | | | second mutable borrow occurs here | | first borrow later used by call | first mutable borrow occurs here @@ -50,8 +53,9 @@ error[E0499]: cannot borrow `reg.sess_mut` as mutable more than once at a time --> $DIR/two-phase-surprise-no-conflict.rs:128:44 | LL | reg.register_ref(&TrivialPass::new_mut(&mut reg.sess_mut)); - | --- ------------ ^^^^^^^^^^^^^^^^^ second mutable borrow occurs here - | | | + | ---------------------------------------^^^^^^^^^^^^^^^^^-- + | | | | + | | | second mutable borrow occurs here | | first borrow later used by call | first mutable borrow occurs here @@ -102,8 +106,9 @@ error[E0499]: cannot borrow `reg.sess_mut` as mutable more than once at a time --> $DIR/two-phase-surprise-no-conflict.rs:154:54 | LL | reg.register_bound(Box::new(CapturePass::new_mut(&mut reg.sess_mut))); - | --- -------------- ^^^^^^^^^^^^^^^^^ second mutable borrow occurs here - | | | + | -------------------------------------------------^^^^^^^^^^^^^^^^^--- + | | | | + | | | second mutable borrow occurs here | | first borrow later used by call | first mutable borrow occurs here @@ -124,8 +129,9 @@ error[E0499]: cannot borrow `reg.sess_mut` as mutable more than once at a time --> $DIR/two-phase-surprise-no-conflict.rs:158:53 | LL | reg.register_univ(Box::new(CapturePass::new_mut(&mut reg.sess_mut))); - | --- ------------- ^^^^^^^^^^^^^^^^^ second mutable borrow occurs here - | | | + | ------------------------------------------------^^^^^^^^^^^^^^^^^--- + | | | | + | | | second mutable borrow occurs here | | first borrow later used by call | first mutable borrow occurs here @@ -143,8 +149,9 @@ error[E0499]: cannot borrow `reg.sess_mut` as mutable more than once at a time --> $DIR/two-phase-surprise-no-conflict.rs:162:44 | LL | reg.register_ref(&CapturePass::new_mut(&mut reg.sess_mut)); - | --- ------------ ^^^^^^^^^^^^^^^^^ second mutable borrow occurs here - | | | + | ---------------------------------------^^^^^^^^^^^^^^^^^-- + | | | | + | | | second mutable borrow occurs here | | first borrow later used by call | first mutable borrow occurs here diff --git a/src/test/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.stderr b/src/test/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.stderr index dbba33f018..1663ce81d6 100644 --- a/src/test/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.stderr +++ b/src/test/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.stderr @@ -1,11 +1,15 @@ error[E0507]: cannot move out of `y`, a captured variable in an `Fn` closure --> $DIR/unboxed-closures-move-upvar-from-non-once-ref-closure.rs:11:9 | -LL | let y = vec![format!("World")]; - | - captured outer variable -LL | call(|| { -LL | y.into_iter(); - | ^ move occurs because `y` has type `Vec`, which does not implement the `Copy` trait +LL | let y = vec![format!("World")]; + | - captured outer variable +LL | call(|| { + | __________- +LL | | y.into_iter(); + | | ^ move occurs because `y` has type `Vec`, which does not implement the `Copy` trait +LL | | +LL | | }); + | |_____- captured by this `Fn` closure error: aborting due to previous error diff --git a/src/test/ui/box/into-boxed-slice-fail.stderr b/src/test/ui/box/into-boxed-slice-fail.stderr index 5e3b43a47e..2f1dec9d20 100644 --- a/src/test/ui/box/into-boxed-slice-fail.stderr +++ b/src/test/ui/box/into-boxed-slice-fail.stderr @@ -2,7 +2,9 @@ error[E0277]: the size for values of type `[u8]` cannot be known at compilation --> $DIR/into-boxed-slice-fail.rs:7:35 | LL | let _ = Box::into_boxed_slice(boxed_slice); - | ^^^^^^^^^^^ doesn't have a size known at compile-time + | --------------------- ^^^^^^^^^^^ 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 `[u8]` note: required by `Box::::into_boxed_slice` @@ -24,7 +26,9 @@ error[E0277]: the size for values of type `dyn Debug` cannot be known at compila --> $DIR/into-boxed-slice-fail.rs:11:35 | LL | let _ = Box::into_boxed_slice(boxed_trait); - | ^^^^^^^^^^^ doesn't have a size known at compile-time + | --------------------- ^^^^^^^^^^^ 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 `dyn Debug` note: required by `Box::::into_boxed_slice` diff --git a/src/test/ui/box/leak-alloc.stderr b/src/test/ui/box/leak-alloc.stderr index 09beb18146..e8a6ad0995 100644 --- a/src/test/ui/box/leak-alloc.stderr +++ b/src/test/ui/box/leak-alloc.stderr @@ -2,7 +2,7 @@ error[E0505]: cannot move out of `alloc` because it is borrowed --> $DIR/leak-alloc.rs:26:10 | LL | let boxed = Box::new_in(10, alloc.by_ref()); - | ----- borrow of `alloc` occurs here + | -------------- borrow of `alloc` occurs here LL | let theref = Box::leak(boxed); LL | drop(alloc); | ^^^^^ move out of `alloc` occurs here diff --git a/src/test/ui/c-variadic/issue-86053-1.stderr b/src/test/ui/c-variadic/issue-86053-1.stderr index 793068138a..5d119bb855 100644 --- a/src/test/ui/c-variadic/issue-86053-1.stderr +++ b/src/test/ui/c-variadic/issue-86053-1.stderr @@ -84,12 +84,12 @@ error[E0491]: in type `&'a &'b usize`, reference has a longer lifetime than the LL | self , ... , self , self , ... ) where F : FnOnce ( & 'a & 'b usize ) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: the pointer is valid for the lifetime `'a` as defined on the function body at 10:16 +note: the pointer is valid for the lifetime `'a` as defined here --> $DIR/issue-86053-1.rs:10:16 | LL | fn ordering4 < 'a , 'b > ( a : , self , self , self , | ^^ -note: but the referenced data is only valid for the lifetime `'b` as defined on the function body at 10:21 +note: but the referenced data is only valid for the lifetime `'b` as defined here --> $DIR/issue-86053-1.rs:10:21 | LL | fn ordering4 < 'a , 'b > ( a : , self , self , self , diff --git a/src/test/ui/c-variadic/issue-86053-2.stderr b/src/test/ui/c-variadic/issue-86053-2.stderr index 4fc5e6315e..815b06e770 100644 --- a/src/test/ui/c-variadic/issue-86053-2.stderr +++ b/src/test/ui/c-variadic/issue-86053-2.stderr @@ -5,7 +5,7 @@ LL | unsafe extern "C" fn ordering4<'a, F: H<&'static &'a ()>>(_: (), ...) {} | ^^^^^^^^^^^^^^^^^^ | = note: the pointer is valid for the static lifetime -note: but the referenced data is only valid for the lifetime `'a` as defined on the function body at 8:32 +note: but the referenced data is only valid for the lifetime `'a` as defined here --> $DIR/issue-86053-2.rs:8:32 | LL | unsafe extern "C" fn ordering4<'a, F: H<&'static &'a ()>>(_: (), ...) {} diff --git a/src/test/ui/cancel-clean-via-immediate-rvalue-ref.rs b/src/test/ui/cancel-clean-via-immediate-rvalue-ref.rs index 781d5c14ab..a0a561ab2d 100644 --- a/src/test/ui/cancel-clean-via-immediate-rvalue-ref.rs +++ b/src/test/ui/cancel-clean-via-immediate-rvalue-ref.rs @@ -1,12 +1,10 @@ // run-pass // pretty-expanded FIXME #23616 -#![feature(box_syntax)] - fn foo(x: &mut Box) { - *x = box 5; + *x = Box::new(5); } pub fn main() { - foo(&mut box 4); + foo(&mut Box::new(4)); } diff --git a/src/test/ui/cannot-mutate-captured-non-mut-var.stderr b/src/test/ui/cannot-mutate-captured-non-mut-var.stderr index 2d6e83c9e8..06b5ca407d 100644 --- a/src/test/ui/cannot-mutate-captured-non-mut-var.stderr +++ b/src/test/ui/cannot-mutate-captured-non-mut-var.stderr @@ -12,7 +12,7 @@ error[E0596]: cannot borrow `s` as mutable, as it is not declared as mutable LL | let s = std::io::stdin(); | - help: consider changing this to be mutable: `mut s` LL | to_fn_once(move|| { s.read_to_end(&mut Vec::new()); }); - | ^ cannot borrow as mutable + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot borrow as mutable error: aborting due to 2 previous errors diff --git a/src/test/ui/cast/issue-89497.fixed b/src/test/ui/cast/issue-89497.fixed new file mode 100644 index 0000000000..04c10a5f79 --- /dev/null +++ b/src/test/ui/cast/issue-89497.fixed @@ -0,0 +1,10 @@ +// Regression test for issue #89497. + +// run-rustfix + +fn main() { + let pointer: usize = &1_i32 as *const i32 as usize; + let _reference: &'static i32 = unsafe { &*(pointer as *const i32) }; + //~^ ERROR: non-primitive cast + //~| HELP: consider borrowing the value +} diff --git a/src/test/ui/cast/issue-89497.rs b/src/test/ui/cast/issue-89497.rs new file mode 100644 index 0000000000..76301b704c --- /dev/null +++ b/src/test/ui/cast/issue-89497.rs @@ -0,0 +1,10 @@ +// Regression test for issue #89497. + +// run-rustfix + +fn main() { + let pointer: usize = &1_i32 as *const i32 as usize; + let _reference: &'static i32 = unsafe { pointer as *const i32 as &'static i32 }; + //~^ ERROR: non-primitive cast + //~| HELP: consider borrowing the value +} diff --git a/src/test/ui/cast/issue-89497.stderr b/src/test/ui/cast/issue-89497.stderr new file mode 100644 index 0000000000..3726f8a410 --- /dev/null +++ b/src/test/ui/cast/issue-89497.stderr @@ -0,0 +1,15 @@ +error[E0605]: non-primitive cast: `*const i32` as `&'static i32` + --> $DIR/issue-89497.rs:7:45 + | +LL | let _reference: &'static i32 = unsafe { pointer as *const i32 as &'static i32 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid cast + | +help: consider borrowing the value + | +LL - let _reference: &'static i32 = unsafe { pointer as *const i32 as &'static i32 }; +LL + let _reference: &'static i32 = unsafe { &*(pointer as *const i32) }; + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0605`. diff --git a/src/test/ui/chalkify/type_inference.stderr b/src/test/ui/chalkify/type_inference.stderr index a4a480ac64..14d43c1474 100644 --- a/src/test/ui/chalkify/type_inference.stderr +++ b/src/test/ui/chalkify/type_inference.stderr @@ -2,7 +2,9 @@ error[E0277]: the trait bound `{float}: Bar` is not satisfied --> $DIR/type_inference.rs:27:14 | LL | only_bar(x); - | ^ the trait `Bar` is not implemented for `{float}` + | -------- ^ the trait `Bar` is not implemented for `{float}` + | | + | required by a bound introduced by this call | = help: the following implementations were found: diff --git a/src/test/ui/class-cast-to-trait.rs b/src/test/ui/class-cast-to-trait.rs index bb4c3fac93..345d6efd2d 100644 --- a/src/test/ui/class-cast-to-trait.rs +++ b/src/test/ui/class-cast-to-trait.rs @@ -1,5 +1,3 @@ -#![feature(box_syntax)] - trait Noisy { fn speak(&self); } @@ -48,7 +46,9 @@ fn cat(in_x : usize, in_y : isize, in_name: String) -> Cat { } } + + fn main() { - let nyan: Box = box cat(0, 2, "nyan".to_string()) as Box; + let nyan: Box = Box::new(cat(0, 2, "nyan".to_string())) as Box; nyan.eat(); //~ ERROR no method named `eat` found } diff --git a/src/test/ui/cleanup-arm-conditional.rs b/src/test/ui/cleanup-arm-conditional.rs index 915842f3e8..38c717089c 100644 --- a/src/test/ui/cleanup-arm-conditional.rs +++ b/src/test/ui/cleanup-arm-conditional.rs @@ -7,7 +7,7 @@ // pretty-expanded FIXME #23616 -#![feature(box_syntax, os)] +#![feature(os)] use std::os; @@ -15,7 +15,7 @@ struct Test { x: isize } impl Test { fn get_x(&self) -> Option> { - Some(box self.x) + Some(Box::new(self.x)) } } diff --git a/src/test/ui/cleanup-rvalue-scopes.rs b/src/test/ui/cleanup-rvalue-scopes.rs index c5dd87c0f5..b80f95b79f 100644 --- a/src/test/ui/cleanup-rvalue-scopes.rs +++ b/src/test/ui/cleanup-rvalue-scopes.rs @@ -7,7 +7,6 @@ // lifetime rules. #![feature(box_patterns)] -#![feature(box_syntax)] use std::ops::Drop; @@ -106,8 +105,8 @@ pub fn main() { end_of_block!(AddFlags { bits: ref _x }, AddFlags(1)); end_of_block!(&AddFlags { bits }, &AddFlags(1)); end_of_block!((_, ref _y), (AddFlags(1), 22)); - end_of_block!(box ref _x, box AddFlags(1)); - end_of_block!(box _x, box AddFlags(1)); + end_of_block!(box ref _x, std::boxed::Box::new(AddFlags(1))); + end_of_block!(box _x, std::boxed::Box::new(AddFlags(1))); end_of_block!(_, { { check_flags(0); &AddFlags(1) } }); end_of_block!(_, &((Box { f: AddFlags(1) }).f)); end_of_block!(_, &(([AddFlags(1)])[0])); diff --git a/src/test/ui/cleanup-rvalue-temp-during-incomplete-alloc.rs b/src/test/ui/cleanup-rvalue-temp-during-incomplete-alloc.rs index 62f8b81385..eadbe44a8e 100644 --- a/src/test/ui/cleanup-rvalue-temp-during-incomplete-alloc.rs +++ b/src/test/ui/cleanup-rvalue-temp-during-incomplete-alloc.rs @@ -21,8 +21,6 @@ // ignore-emscripten no threads support -#![feature(box_syntax)] - use std::thread; enum Conzabble { @@ -40,7 +38,7 @@ fn get_bar(x: usize) -> Vec { vec![x * 2] } pub fn fails() { let x = 2; let mut y: Vec> = Vec::new(); - y.push(box Conzabble::Bickwick(do_it(&get_bar(x)))); + y.push(Box::new(Conzabble::Bickwick(do_it(&get_bar(x))))); } pub fn main() { diff --git a/src/test/ui/clone-with-exterior.rs b/src/test/ui/clone-with-exterior.rs index 1ef2971926..9fc661b147 100644 --- a/src/test/ui/clone-with-exterior.rs +++ b/src/test/ui/clone-with-exterior.rs @@ -3,8 +3,6 @@ #![allow(unused_must_use)] // ignore-emscripten no threads support -#![feature(box_syntax)] - use std::thread; struct Pair { @@ -13,7 +11,7 @@ struct Pair { } pub fn main() { - let z: Box<_> = box Pair { a : 10, b : 12}; + let z: Box<_> = Box::new(Pair { a : 10, b : 12}); thread::spawn(move|| { assert_eq!(z.a, 10); diff --git a/src/test/ui/close-over-big-then-small-data.rs b/src/test/ui/close-over-big-then-small-data.rs index 4d6edf4ecb..429b21e8b8 100644 --- a/src/test/ui/close-over-big-then-small-data.rs +++ b/src/test/ui/close-over-big-then-small-data.rs @@ -5,8 +5,6 @@ // storing closure data (as we used to do), the u64 would // overwrite the u16. -#![feature(box_syntax)] - struct Pair { a: A, b: B } @@ -27,10 +25,10 @@ impl Invokable for Invoker { } fn f(a: A, b: u16) -> Box+'static> { - box Invoker { + Box::new(Invoker { a: a, b: b, - } as Box+'static> + }) as Box+'static> } pub fn main() { diff --git a/src/test/ui/closure-expected-type/expect-fn-supply-fn.nll.stderr b/src/test/ui/closure-expected-type/expect-fn-supply-fn.nll.stderr index 768dc8e12d..26f47eb684 100644 --- a/src/test/ui/closure-expected-type/expect-fn-supply-fn.nll.stderr +++ b/src/test/ui/closure-expected-type/expect-fn-supply-fn.nll.stderr @@ -18,8 +18,6 @@ LL | fn expect_free_supply_free_from_fn<'x>(x: &'x u32) { ... LL | with_closure_expecting_fn_with_free_region(|x: fn(&'x u32), y| {}); | ^ requires that `'x` must outlive `'static` - | - = help: consider replacing `'x` with `'static` error[E0308]: mismatched types --> $DIR/expect-fn-supply-fn.rs:32:49 diff --git a/src/test/ui/closure-expected-type/expect-fn-supply-fn.stderr b/src/test/ui/closure-expected-type/expect-fn-supply-fn.stderr index 7a4ff77941..b25a7ab3dc 100644 --- a/src/test/ui/closure-expected-type/expect-fn-supply-fn.stderr +++ b/src/test/ui/closure-expected-type/expect-fn-supply-fn.stderr @@ -6,12 +6,12 @@ LL | with_closure_expecting_fn_with_free_region(|x: fn(&'x u32), y| {}); | = note: expected fn pointer `fn(&u32)` found fn pointer `fn(&'x u32)` -note: the anonymous lifetime #1 defined on the body at 16:48... +note: the anonymous lifetime #1 defined here... --> $DIR/expect-fn-supply-fn.rs:16:48 | LL | with_closure_expecting_fn_with_free_region(|x: fn(&'x u32), y| {}); | ^^^^^^^^^^^^^^^^^^^^^^ -note: ...does not necessarily outlive the lifetime `'x` as defined on the function body at 13:36 +note: ...does not necessarily outlive the lifetime `'x` as defined here --> $DIR/expect-fn-supply-fn.rs:13:36 | LL | fn expect_free_supply_free_from_fn<'x>(x: &'x u32) { @@ -25,12 +25,12 @@ LL | with_closure_expecting_fn_with_free_region(|x: fn(&'x u32), y| {}); | = note: expected fn pointer `fn(&u32)` found fn pointer `fn(&'x u32)` -note: the lifetime `'x` as defined on the function body at 13:36... +note: the lifetime `'x` as defined here... --> $DIR/expect-fn-supply-fn.rs:13:36 | LL | fn expect_free_supply_free_from_fn<'x>(x: &'x u32) { | ^^ -note: ...does not necessarily outlive the anonymous lifetime #1 defined on the body at 16:48 +note: ...does not necessarily outlive the anonymous lifetime #1 defined here --> $DIR/expect-fn-supply-fn.rs:16:48 | LL | with_closure_expecting_fn_with_free_region(|x: fn(&'x u32), y| {}); diff --git a/src/test/ui/closure-expected.stderr b/src/test/ui/closure-expected.stderr index 6c77d08096..d4f2307804 100644 --- a/src/test/ui/closure-expected.stderr +++ b/src/test/ui/closure-expected.stderr @@ -2,7 +2,9 @@ error[E0277]: expected a `FnOnce<()>` closure, found `{integer}` --> $DIR/closure-expected.rs:3:23 | LL | let y = x.or_else(4); - | ^ expected an `FnOnce<()>` closure, found `{integer}` + | ------- ^ 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 */ }` diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-closures-mut-and-imm.rs b/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-closures-mut-and-imm.rs index 6a8c966405..5ff7b1242d 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-closures-mut-and-imm.rs +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-closures-mut-and-imm.rs @@ -1,10 +1,10 @@ // edition:2021 + + // Tests that two closures cannot simultaneously have mutable // and immutable access to the variable. Issue #6801. -#![feature(box_syntax)] - #[derive(Debug)] struct Point { x: i32, diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/liveness.rs b/src/test/ui/closures/2229_closure_analysis/diagnostics/liveness.rs index 1cc22fac35..3399bc0018 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/liveness.rs +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/liveness.rs @@ -3,6 +3,7 @@ // check-pass #![allow(unreachable_code)] #![warn(unused)] +#![allow(dead_code)] #[derive(Debug)] struct Point { diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/liveness.stderr b/src/test/ui/closures/2229_closure_analysis/diagnostics/liveness.stderr index 4eac5a2d28..7410977272 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/liveness.stderr +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/liveness.stderr @@ -1,5 +1,5 @@ warning: value captured by `a` is never read - --> $DIR/liveness.rs:23:9 + --> $DIR/liveness.rs:24:9 | LL | a = 1; | ^ @@ -13,7 +13,7 @@ LL | #![warn(unused)] = help: did you mean to capture by reference instead? warning: unused variable: `a` - --> $DIR/liveness.rs:32:9 + --> $DIR/liveness.rs:33:9 | LL | a += 1; | ^ @@ -27,7 +27,7 @@ LL | #![warn(unused)] = help: did you mean to capture by reference instead? warning: value assigned to `a` is never read - --> $DIR/liveness.rs:52:9 + --> $DIR/liveness.rs:53:9 | LL | a += 1; | ^ @@ -35,7 +35,7 @@ LL | a += 1; = help: maybe it is overwritten before being read? warning: value assigned to `a` is never read - --> $DIR/liveness.rs:76:13 + --> $DIR/liveness.rs:77:13 | LL | a = Some("d1"); | ^ @@ -43,7 +43,7 @@ LL | a = Some("d1"); = help: maybe it is overwritten before being read? warning: value assigned to `b` is never read - --> $DIR/liveness.rs:84:13 + --> $DIR/liveness.rs:85:13 | LL | b = Some("e1"); | ^ @@ -51,7 +51,7 @@ LL | b = Some("e1"); = help: maybe it is overwritten before being read? warning: value assigned to `b` is never read - --> $DIR/liveness.rs:86:13 + --> $DIR/liveness.rs:87:13 | LL | b = Some("e2"); | ^ @@ -59,7 +59,7 @@ LL | b = Some("e2"); = help: maybe it is overwritten before being read? warning: unused variable: `b` - --> $DIR/liveness.rs:84:13 + --> $DIR/liveness.rs:85:13 | LL | b = Some("e1"); | ^ diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/liveness_unintentional_copy.rs b/src/test/ui/closures/2229_closure_analysis/diagnostics/liveness_unintentional_copy.rs index 10a7d07a1d..465c9476ba 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/liveness_unintentional_copy.rs +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/liveness_unintentional_copy.rs @@ -2,6 +2,7 @@ // check-pass #![warn(unused)] +#![allow(dead_code)] #[derive(Debug)] struct MyStruct { diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/liveness_unintentional_copy.stderr b/src/test/ui/closures/2229_closure_analysis/diagnostics/liveness_unintentional_copy.stderr index f74303e3dd..11a440554f 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/liveness_unintentional_copy.stderr +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/liveness_unintentional_copy.stderr @@ -1,5 +1,5 @@ warning: value assigned to `a` is never read - --> $DIR/liveness_unintentional_copy.rs:19:9 + --> $DIR/liveness_unintentional_copy.rs:20:9 | LL | a = s; | ^ @@ -13,7 +13,7 @@ LL | #![warn(unused)] = help: maybe it is overwritten before being read? warning: unused variable: `a` - --> $DIR/liveness_unintentional_copy.rs:19:9 + --> $DIR/liveness_unintentional_copy.rs:20:9 | LL | a = s; | ^ @@ -27,7 +27,7 @@ LL | #![warn(unused)] = help: did you mean to capture by reference instead? warning: unused variable: `a` - --> $DIR/liveness_unintentional_copy.rs:35:9 + --> $DIR/liveness_unintentional_copy.rs:36:9 | LL | a += x; | ^ diff --git a/src/test/ui/closures/2229_closure_analysis/issue-90465.fixed b/src/test/ui/closures/2229_closure_analysis/issue-90465.fixed new file mode 100644 index 0000000000..4e0b18e723 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/issue-90465.fixed @@ -0,0 +1,35 @@ +// run-rustfix + +#![deny(rust_2021_incompatible_closure_captures)] +//~^ NOTE lint level is defined here + +fn main() { + struct Foo(u32); + impl Drop for Foo { + fn drop(&mut self) { + println!("dropped {}", self.0); + } + } + + let f0 = Foo(0); + let f1 = Foo(1); + + let c0 = move || { + let _ = &f0; + //~^ ERROR changes to closure capture in Rust 2021 will affect drop order + //~| NOTE for more information + let _ = f0; + //~^ NOTE in Rust 2018, this causes the closure to capture `f0`, but in Rust 2021, it has no effect + }; + + let c1 = move || { + let _ = &f1; + }; + + println!("dropping 0"); + drop(c0); + println!("dropping 1"); + drop(c1); + println!("dropped all"); +} +//~^ NOTE in Rust 2018, `f0` is dropped here along with the closure, but in Rust 2021 `f0` is not part of the closure diff --git a/src/test/ui/closures/2229_closure_analysis/issue-90465.rs b/src/test/ui/closures/2229_closure_analysis/issue-90465.rs new file mode 100644 index 0000000000..466e6dbabc --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/issue-90465.rs @@ -0,0 +1,34 @@ +// run-rustfix + +#![deny(rust_2021_incompatible_closure_captures)] +//~^ NOTE lint level is defined here + +fn main() { + struct Foo(u32); + impl Drop for Foo { + fn drop(&mut self) { + println!("dropped {}", self.0); + } + } + + let f0 = Foo(0); + let f1 = Foo(1); + + let c0 = move || { + //~^ ERROR changes to closure capture in Rust 2021 will affect drop order + //~| NOTE for more information + let _ = f0; + //~^ NOTE in Rust 2018, this causes the closure to capture `f0`, but in Rust 2021, it has no effect + }; + + let c1 = move || { + let _ = &f1; + }; + + println!("dropping 0"); + drop(c0); + println!("dropping 1"); + drop(c1); + println!("dropped all"); +} +//~^ NOTE in Rust 2018, `f0` is dropped here along with the closure, but in Rust 2021 `f0` is not part of the closure diff --git a/src/test/ui/closures/2229_closure_analysis/issue-90465.stderr b/src/test/ui/closures/2229_closure_analysis/issue-90465.stderr new file mode 100644 index 0000000000..3e921dc0f8 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/issue-90465.stderr @@ -0,0 +1,26 @@ +error: changes to closure capture in Rust 2021 will affect drop order + --> $DIR/issue-90465.rs:17:14 + | +LL | let c0 = move || { + | ^^^^^^^ +... +LL | let _ = f0; + | -- in Rust 2018, this causes the closure to capture `f0`, but in Rust 2021, it has no effect +... +LL | } + | - in Rust 2018, `f0` is dropped here along with the closure, but in Rust 2021 `f0` is not part of the closure + | +note: the lint level is defined here + --> $DIR/issue-90465.rs:3:9 + | +LL | #![deny(rust_2021_incompatible_closure_captures)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: for more information, see +help: add a dummy let to cause `f0` to be fully captured + | +LL ~ let c0 = move || { +LL + let _ = &f0; + | + +error: aborting due to previous error + diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.fixed b/src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.fixed index b0fc5120f0..26703fbf81 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.fixed +++ b/src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.fixed @@ -20,8 +20,8 @@ fn test_send_trait() { let mut f = 10; let fptr = SendPointer(&mut f as *mut i32); thread::spawn(move || { let _ = &fptr; unsafe { - //~^ ERROR: `Send` trait implementation for closure - //~| NOTE: in Rust 2018, this closure implements `Send` as `fptr` implements `Send`, but in Rust 2021, this closure will no longer implement `Send` as `fptr.0` does not implement `Send` + //~^ ERROR: changes to closure capture + //~| NOTE: in Rust 2018, this closure implements `Send` //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `fptr` to be fully captured *fptr.0 = 20; @@ -40,8 +40,9 @@ fn test_sync_trait() { let f = CustomInt(&mut f as *mut i32); let fptr = SyncPointer(f); thread::spawn(move || { let _ = &fptr; unsafe { - //~^ ERROR: `Sync`, `Send` trait implementation for closure - //~| NOTE: in Rust 2018, this closure implements `Sync`, `Send` as `fptr` implements `Sync`, `Send`, but in Rust 2021, this closure will no longer implement `Sync`, `Send` as `fptr.0.0` does not implement `Sync`, `Send` + //~^ ERROR: changes to closure capture + //~| NOTE: in Rust 2018, this closure implements `Sync` + //~| NOTE: in Rust 2018, this closure implements `Send` //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `fptr` to be fully captured *fptr.0.0 = 20; @@ -65,8 +66,8 @@ fn test_clone_trait() { let f = U(S(Foo(0)), T(0)); let c = || { let _ = &f; - //~^ ERROR: `Clone` trait implementation for closure and drop order - //~| NOTE: in Rust 2018, this closure implements `Clone` as `f` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f.1` does not implement `Clone` + //~^ ERROR: changes to closure capture in Rust 2021 will affect drop order and which traits the closure implements + //~| NOTE: in Rust 2018, this closure implements `Clone` //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `f` to be fully captured let f_1 = f.1; diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.rs b/src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.rs index 2bcf9a795e..932db51d43 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.rs +++ b/src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.rs @@ -20,8 +20,8 @@ fn test_send_trait() { let mut f = 10; let fptr = SendPointer(&mut f as *mut i32); thread::spawn(move || unsafe { - //~^ ERROR: `Send` trait implementation for closure - //~| NOTE: in Rust 2018, this closure implements `Send` as `fptr` implements `Send`, but in Rust 2021, this closure will no longer implement `Send` as `fptr.0` does not implement `Send` + //~^ ERROR: changes to closure capture + //~| NOTE: in Rust 2018, this closure implements `Send` //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `fptr` to be fully captured *fptr.0 = 20; @@ -40,8 +40,9 @@ fn test_sync_trait() { let f = CustomInt(&mut f as *mut i32); let fptr = SyncPointer(f); thread::spawn(move || unsafe { - //~^ ERROR: `Sync`, `Send` trait implementation for closure - //~| NOTE: in Rust 2018, this closure implements `Sync`, `Send` as `fptr` implements `Sync`, `Send`, but in Rust 2021, this closure will no longer implement `Sync`, `Send` as `fptr.0.0` does not implement `Sync`, `Send` + //~^ ERROR: changes to closure capture + //~| NOTE: in Rust 2018, this closure implements `Sync` + //~| NOTE: in Rust 2018, this closure implements `Send` //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `fptr` to be fully captured *fptr.0.0 = 20; @@ -64,8 +65,8 @@ impl Clone for U { fn test_clone_trait() { let f = U(S(Foo(0)), T(0)); let c = || { - //~^ ERROR: `Clone` trait implementation for closure and drop order - //~| NOTE: in Rust 2018, this closure implements `Clone` as `f` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f.1` does not implement `Clone` + //~^ ERROR: changes to closure capture in Rust 2021 will affect drop order and which traits the closure implements + //~| NOTE: in Rust 2018, this closure implements `Clone` //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `f` to be fully captured let f_1 = f.1; diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.stderr b/src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.stderr index 8d2d3553d4..ee4907bb75 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.stderr +++ b/src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.stderr @@ -1,8 +1,8 @@ -error: changes to closure capture in Rust 2021 will affect `Send` trait implementation for closure +error: changes to closure capture in Rust 2021 will affect which traits the closure implements --> $DIR/auto_traits.rs:22:19 | LL | thread::spawn(move || unsafe { - | ^^^^^^^^^^^^^^ in Rust 2018, this closure implements `Send` as `fptr` implements `Send`, but in Rust 2021, this closure will no longer implement `Send` as `fptr.0` does not implement `Send` + | ^^^^^^^^^^^^^^ in Rust 2018, this closure implements `Send` as `fptr` implements `Send`, but in Rust 2021, this closure will no longer implement `Send` because `fptr` is not fully captured and `fptr.0` does not implement `Send` ... LL | *fptr.0 = 20; | ------- in Rust 2018, this closure captures all of `fptr`, but in Rust 2021, it will only capture `fptr.0` @@ -23,11 +23,14 @@ LL | LL | *fptr.0 = 20; ... -error: changes to closure capture in Rust 2021 will affect `Sync`, `Send` trait implementation for closure +error: changes to closure capture in Rust 2021 will affect which traits the closure implements --> $DIR/auto_traits.rs:42:19 | LL | thread::spawn(move || unsafe { - | ^^^^^^^^^^^^^^ in Rust 2018, this closure implements `Sync`, `Send` as `fptr` implements `Sync`, `Send`, but in Rust 2021, this closure will no longer implement `Sync`, `Send` as `fptr.0.0` does not implement `Sync`, `Send` + | ^^^^^^^^^^^^^^ + | | + | in Rust 2018, this closure implements `Sync` as `fptr` implements `Sync`, but in Rust 2021, this closure will no longer implement `Sync` because `fptr` is not fully captured and `fptr.0.0` does not implement `Sync` + | in Rust 2018, this closure implements `Send` as `fptr` implements `Send`, but in Rust 2021, this closure will no longer implement `Send` because `fptr` is not fully captured and `fptr.0.0` does not implement `Send` ... LL | *fptr.0.0 = 20; | --------- in Rust 2018, this closure captures all of `fptr`, but in Rust 2021, it will only capture `fptr.0.0` @@ -40,14 +43,14 @@ LL | LL | LL | LL | -LL | *fptr.0.0 = 20; +LL | ... -error: changes to closure capture in Rust 2021 will affect `Clone` trait implementation for closure and drop order - --> $DIR/auto_traits.rs:66:13 +error: changes to closure capture in Rust 2021 will affect drop order and which traits the closure implements + --> $DIR/auto_traits.rs:67:13 | LL | let c = || { - | ^^ in Rust 2018, this closure implements `Clone` as `f` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f.1` does not implement `Clone` + | ^^ in Rust 2018, this closure implements `Clone` as `f` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` because `f` is not fully captured and `f.1` does not implement `Clone` ... LL | let f_1 = f.1; | --- in Rust 2018, this closure captures all of `f`, but in Rust 2021, it will only capture `f.1` diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/closure-body-macro-fragment.stderr b/src/test/ui/closures/2229_closure_analysis/migrations/closure-body-macro-fragment.stderr index a2a9da5f87..675ba0313d 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/closure-body-macro-fragment.stderr +++ b/src/test/ui/closures/2229_closure_analysis/migrations/closure-body-macro-fragment.stderr @@ -17,7 +17,7 @@ LL | | let x = a.0; | | --- in Rust 2018, this closure captures all of `a`, but in Rust 2021, it will only capture `a.0` LL | | println!("{:?}", x); LL | | }); - | |_______- in this macro invocation + | |______- in this macro invocation | note: the lint level is defined here --> $DIR/closure-body-macro-fragment.rs:4:9 diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/issue-90024-adt-correct-subst.rs b/src/test/ui/closures/2229_closure_analysis/migrations/issue-90024-adt-correct-subst.rs new file mode 100644 index 0000000000..ed8cb042b3 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/migrations/issue-90024-adt-correct-subst.rs @@ -0,0 +1,37 @@ +// Test that rustc doesn't ICE as in #90024. +// check-pass +// edition=2018 + +#![warn(rust_2021_incompatible_closure_captures)] + +// Checks there's no double-subst into the generic args, otherwise we get OOB +// MCVE by @lqd +pub struct Graph { + _edges: E, + _nodes: N, + _ix: Vec, +} +fn graph() -> Graph { + todo!() +} +fn first_ice() { + let g = graph::(); + let _ = || g; +} + +// Checks that there is a subst into the fields, otherwise we get normalization error +// MCVE by @cuviper +use std::iter::Empty; +struct Foo { + data: Vec, +} +pub fn second_ice() { + let v = Foo::> { data: vec![] }; + + (|| v.data[0])(); +} + +pub fn main() { + first_ice(); + second_ice(); +} diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.fixed b/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.fixed index a565215468..7df0dd76b4 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.fixed +++ b/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.fixed @@ -19,8 +19,9 @@ where let f = panic::AssertUnwindSafe(f); let result = panic::catch_unwind(move || { let _ = &f; - //~^ ERROR: `UnwindSafe`, `RefUnwindSafe` trait implementation for closure - //~| NOTE: in Rust 2018, this closure implements `UnwindSafe`, `RefUnwindSafe` as `f` implements `UnwindSafe`, `RefUnwindSafe`, but in Rust 2021, this closure will no longer implement `UnwindSafe`, `RefUnwindSafe` as `f.0` does not implement `UnwindSafe`, `RefUnwindSafe` + //~^ ERROR: changes to closure capture in Rust 2021 will affect which traits the closure implements [rust_2021_incompatible_closure_captures] + //~| NOTE: in Rust 2018, this closure implements `UnwindSafe` + //~| NOTE: in Rust 2018, this closure implements `RefUnwindSafe` //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `f` to be fully captured f.0() diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.rs b/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.rs index d9acde073f..d02fac7c66 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.rs +++ b/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.rs @@ -18,8 +18,9 @@ where { let f = panic::AssertUnwindSafe(f); let result = panic::catch_unwind(move || { - //~^ ERROR: `UnwindSafe`, `RefUnwindSafe` trait implementation for closure - //~| NOTE: in Rust 2018, this closure implements `UnwindSafe`, `RefUnwindSafe` as `f` implements `UnwindSafe`, `RefUnwindSafe`, but in Rust 2021, this closure will no longer implement `UnwindSafe`, `RefUnwindSafe` as `f.0` does not implement `UnwindSafe`, `RefUnwindSafe` + //~^ ERROR: changes to closure capture in Rust 2021 will affect which traits the closure implements [rust_2021_incompatible_closure_captures] + //~| NOTE: in Rust 2018, this closure implements `UnwindSafe` + //~| NOTE: in Rust 2018, this closure implements `RefUnwindSafe` //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `f` to be fully captured f.0() diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.stderr b/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.stderr index 10816b7bc3..74f85b6eba 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.stderr +++ b/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.stderr @@ -1,8 +1,11 @@ -error: changes to closure capture in Rust 2021 will affect `UnwindSafe`, `RefUnwindSafe` trait implementation for closure +error: changes to closure capture in Rust 2021 will affect which traits the closure implements --> $DIR/mir_calls_to_shims.rs:20:38 | LL | let result = panic::catch_unwind(move || { - | ^^^^^^^ in Rust 2018, this closure implements `UnwindSafe`, `RefUnwindSafe` as `f` implements `UnwindSafe`, `RefUnwindSafe`, but in Rust 2021, this closure will no longer implement `UnwindSafe`, `RefUnwindSafe` as `f.0` does not implement `UnwindSafe`, `RefUnwindSafe` + | ^^^^^^^ + | | + | in Rust 2018, this closure implements `UnwindSafe` as `f` implements `UnwindSafe`, but in Rust 2021, this closure will no longer implement `UnwindSafe` because `f` is not fully captured and `f.0` does not implement `UnwindSafe` + | in Rust 2018, this closure implements `RefUnwindSafe` as `f` implements `RefUnwindSafe`, but in Rust 2021, this closure will no longer implement `RefUnwindSafe` because `f` is not fully captured and `f.0` does not implement `RefUnwindSafe` ... LL | f.0() | --- in Rust 2018, this closure captures all of `f`, but in Rust 2021, it will only capture `f.0` diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.fixed b/src/test/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.fixed index 11218eff13..2b86b0ddad 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.fixed +++ b/src/test/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.fixed @@ -18,7 +18,6 @@ impl Foo { } } - struct S(Foo); #[derive(Clone)] @@ -37,8 +36,8 @@ fn test_multi_issues() { let f2 = U(S(Foo::from("bar")), T(0)); let c = || { let _ = (&f1, &f2); - //~^ ERROR: `Clone` trait implementation for closure and drop order - //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f1.0` does not implement `Clone` + //~^ ERROR: changes to closure capture in Rust 2021 + //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone` //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `f1`, `f2` to be fully captured let _f_1 = f1.0; @@ -57,8 +56,8 @@ fn test_capturing_all_disjoint_fields_individually() { let f1 = U(S(Foo::from("foo")), T(0)); let c = || { let _ = &f1; - //~^ ERROR: `Clone` trait implementation for closure - //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f1.0` does not implement `Clone` + //~^ ERROR: changes to closure capture in Rust 2021 will affect which traits the closure implements [rust_2021_incompatible_closure_captures] + //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone` //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `f1` to be fully captured let _f_1 = f1.0; @@ -83,9 +82,9 @@ fn test_capturing_several_disjoint_fields_individually_1() { let f1 = U1(S(Foo::from("foo")), T(0), S(Foo::from("bar"))); let c = || { let _ = &f1; - //~^ ERROR: `Clone` trait implementation for closure - //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f1.0` does not implement `Clone` - //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f1.2` does not implement `Clone` + //~^ ERROR: changes to closure capture in Rust 2021 will affect which traits the closure implements [rust_2021_incompatible_closure_captures] + //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone` + //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone` //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `f1` to be fully captured let _f_0 = f1.0; @@ -103,8 +102,8 @@ fn test_capturing_several_disjoint_fields_individually_2() { let f1 = U1(S(Foo::from("foo")), T(0), S(Foo::from("bar"))); let c = || { let _ = &f1; - //~^ ERROR: `Clone` trait implementation for closure and drop order - //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f1.0` does not implement `Clone` + //~^ ERROR: changes to closure capture in Rust 2021 will affect drop order and which traits the closure implements + //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone` //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `f1` to be fully captured let _f_0 = f1.0; @@ -136,9 +135,10 @@ fn test_multi_traits_issues() { let mut f2 = 10; let fptr2 = SendPointer(&mut f2 as *mut i32); thread::spawn(move || { let _ = (&fptr1, &fptr2); unsafe { - //~^ ERROR: `Sync`, `Send` trait implementation for closure - //~| NOTE: in Rust 2018, this closure implements `Sync`, `Send` as `fptr1` implements `Sync`, `Send`, but in Rust 2021, this closure will no longer implement `Sync`, `Send` as `fptr1.0.0` does not implement `Sync`, `Send` - //~| NOTE: in Rust 2018, this closure implements `Send` as `fptr2` implements `Send`, but in Rust 2021, this closure will no longer implement `Send` as `fptr2.0` does not implement `Send` + //~^ ERROR: changes to closure capture in Rust 2021 + //~| NOTE: in Rust 2018, this closure implements `Sync` as `fptr1` implements `Sync` + //~| NOTE: in Rust 2018, this closure implements `Send` as `fptr1` implements `Send` + //~| NOTE: in Rust 2018, this closure implements `Send` as `fptr2` implements `Send` //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `fptr1`, `fptr2` to be fully captured *fptr1.0.0 = 20; diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.rs b/src/test/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.rs index 02f2faa2e8..3cac4abfad 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.rs +++ b/src/test/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.rs @@ -18,7 +18,6 @@ impl Foo { } } - struct S(Foo); #[derive(Clone)] @@ -36,8 +35,8 @@ fn test_multi_issues() { let f1 = U(S(Foo::from("foo")), T(0)); let f2 = U(S(Foo::from("bar")), T(0)); let c = || { - //~^ ERROR: `Clone` trait implementation for closure and drop order - //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f1.0` does not implement `Clone` + //~^ ERROR: changes to closure capture in Rust 2021 + //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone` //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `f1`, `f2` to be fully captured let _f_1 = f1.0; @@ -55,8 +54,8 @@ fn test_multi_issues() { fn test_capturing_all_disjoint_fields_individually() { let f1 = U(S(Foo::from("foo")), T(0)); let c = || { - //~^ ERROR: `Clone` trait implementation for closure - //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f1.0` does not implement `Clone` + //~^ ERROR: changes to closure capture in Rust 2021 will affect which traits the closure implements [rust_2021_incompatible_closure_captures] + //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone` //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `f1` to be fully captured let _f_1 = f1.0; @@ -80,9 +79,9 @@ impl Clone for U1 { fn test_capturing_several_disjoint_fields_individually_1() { let f1 = U1(S(Foo::from("foo")), T(0), S(Foo::from("bar"))); let c = || { - //~^ ERROR: `Clone` trait implementation for closure - //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f1.0` does not implement `Clone` - //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f1.2` does not implement `Clone` + //~^ ERROR: changes to closure capture in Rust 2021 will affect which traits the closure implements [rust_2021_incompatible_closure_captures] + //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone` + //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone` //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `f1` to be fully captured let _f_0 = f1.0; @@ -99,8 +98,8 @@ fn test_capturing_several_disjoint_fields_individually_1() { fn test_capturing_several_disjoint_fields_individually_2() { let f1 = U1(S(Foo::from("foo")), T(0), S(Foo::from("bar"))); let c = || { - //~^ ERROR: `Clone` trait implementation for closure and drop order - //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f1.0` does not implement `Clone` + //~^ ERROR: changes to closure capture in Rust 2021 will affect drop order and which traits the closure implements + //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone` //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `f1` to be fully captured let _f_0 = f1.0; @@ -132,9 +131,10 @@ fn test_multi_traits_issues() { let mut f2 = 10; let fptr2 = SendPointer(&mut f2 as *mut i32); thread::spawn(move || unsafe { - //~^ ERROR: `Sync`, `Send` trait implementation for closure - //~| NOTE: in Rust 2018, this closure implements `Sync`, `Send` as `fptr1` implements `Sync`, `Send`, but in Rust 2021, this closure will no longer implement `Sync`, `Send` as `fptr1.0.0` does not implement `Sync`, `Send` - //~| NOTE: in Rust 2018, this closure implements `Send` as `fptr2` implements `Send`, but in Rust 2021, this closure will no longer implement `Send` as `fptr2.0` does not implement `Send` + //~^ ERROR: changes to closure capture in Rust 2021 + //~| NOTE: in Rust 2018, this closure implements `Sync` as `fptr1` implements `Sync` + //~| NOTE: in Rust 2018, this closure implements `Send` as `fptr1` implements `Send` + //~| NOTE: in Rust 2018, this closure implements `Send` as `fptr2` implements `Send` //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `fptr1`, `fptr2` to be fully captured *fptr1.0.0 = 20; diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.stderr b/src/test/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.stderr index d425db5aa9..0008f1b2c0 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.stderr +++ b/src/test/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.stderr @@ -1,8 +1,8 @@ -error: changes to closure capture in Rust 2021 will affect `Clone` trait implementation for closure and drop order - --> $DIR/multi_diagnostics.rs:38:13 +error: changes to closure capture in Rust 2021 will affect drop order and which traits the closure implements + --> $DIR/multi_diagnostics.rs:37:13 | LL | let c = || { - | ^^ in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f1.0` does not implement `Clone` + | ^^ in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` because `f1` is not fully captured and `f1.0` does not implement `Clone` ... LL | let _f_1 = f1.0; | ---- in Rust 2018, this closure captures all of `f1`, but in Rust 2021, it will only capture `f1.0` @@ -25,11 +25,11 @@ LL ~ let c = || { LL + let _ = (&f1, &f2); | -error: changes to closure capture in Rust 2021 will affect `Clone` trait implementation for closure - --> $DIR/multi_diagnostics.rs:57:13 +error: changes to closure capture in Rust 2021 will affect which traits the closure implements + --> $DIR/multi_diagnostics.rs:56:13 | LL | let c = || { - | ^^ in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f1.0` does not implement `Clone` + | ^^ in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` because `f1` is not fully captured and `f1.0` does not implement `Clone` ... LL | let _f_1 = f1.0; | ---- in Rust 2018, this closure captures all of `f1`, but in Rust 2021, it will only capture `f1.0` @@ -41,14 +41,14 @@ LL ~ let c = || { LL + let _ = &f1; | -error: changes to closure capture in Rust 2021 will affect `Clone` trait implementation for closure - --> $DIR/multi_diagnostics.rs:82:13 +error: changes to closure capture in Rust 2021 will affect which traits the closure implements + --> $DIR/multi_diagnostics.rs:81:13 | LL | let c = || { | ^^ | | - | in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f1.0` does not implement `Clone` - | in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f1.2` does not implement `Clone` + | in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` because `f1` is not fully captured and `f1.0` does not implement `Clone` + | in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` because `f1` is not fully captured and `f1.2` does not implement `Clone` ... LL | let _f_0 = f1.0; | ---- in Rust 2018, this closure captures all of `f1`, but in Rust 2021, it will only capture `f1.0` @@ -63,11 +63,11 @@ LL ~ let c = || { LL + let _ = &f1; | -error: changes to closure capture in Rust 2021 will affect `Clone` trait implementation for closure and drop order - --> $DIR/multi_diagnostics.rs:101:13 +error: changes to closure capture in Rust 2021 will affect drop order and which traits the closure implements + --> $DIR/multi_diagnostics.rs:100:13 | LL | let c = || { - | ^^ in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f1.0` does not implement `Clone` + | ^^ in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` because `f1` is not fully captured and `f1.0` does not implement `Clone` ... LL | let _f_0 = f1.0; | ---- in Rust 2018, this closure captures all of `f1`, but in Rust 2021, it will only capture `f1.0` @@ -88,14 +88,15 @@ LL ~ let c = || { LL + let _ = &f1; | -error: changes to closure capture in Rust 2021 will affect `Sync`, `Send` trait implementation for closure - --> $DIR/multi_diagnostics.rs:134:19 +error: changes to closure capture in Rust 2021 will affect which traits the closure implements + --> $DIR/multi_diagnostics.rs:133:19 | LL | thread::spawn(move || unsafe { | ^^^^^^^^^^^^^^ | | - | in Rust 2018, this closure implements `Sync`, `Send` as `fptr1` implements `Sync`, `Send`, but in Rust 2021, this closure will no longer implement `Sync`, `Send` as `fptr1.0.0` does not implement `Sync`, `Send` - | in Rust 2018, this closure implements `Send` as `fptr2` implements `Send`, but in Rust 2021, this closure will no longer implement `Send` as `fptr2.0` does not implement `Send` + | in Rust 2018, this closure implements `Sync` as `fptr1` implements `Sync`, but in Rust 2021, this closure will no longer implement `Sync` because `fptr1` is not fully captured and `fptr1.0.0` does not implement `Sync` + | in Rust 2018, this closure implements `Send` as `fptr1` implements `Send`, but in Rust 2021, this closure will no longer implement `Send` because `fptr1` is not fully captured and `fptr1.0.0` does not implement `Send` + | in Rust 2018, this closure implements `Send` as `fptr2` implements `Send`, but in Rust 2021, this closure will no longer implement `Send` because `fptr2` is not fully captured and `fptr2.0` does not implement `Send` ... LL | *fptr1.0.0 = 20; | ---------- in Rust 2018, this closure captures all of `fptr1`, but in Rust 2021, it will only capture `fptr1.0.0` diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/struct-pattern-matching-with-methods.rs b/src/test/ui/closures/2229_closure_analysis/run_pass/struct-pattern-matching-with-methods.rs index 045fe78040..ed222b3148 100644 --- a/src/test/ui/closures/2229_closure_analysis/run_pass/struct-pattern-matching-with-methods.rs +++ b/src/test/ui/closures/2229_closure_analysis/run_pass/struct-pattern-matching-with-methods.rs @@ -1,6 +1,7 @@ // edition:2021 //check-pass #![warn(unused)] +#![allow(dead_code)] #![feature(rustc_attrs)] #[derive(Debug, Clone, Copy)] diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/unsafe_ptr.rs b/src/test/ui/closures/2229_closure_analysis/run_pass/unsafe_ptr.rs index 8e4f91c27e..3f7ddf93f0 100644 --- a/src/test/ui/closures/2229_closure_analysis/run_pass/unsafe_ptr.rs +++ b/src/test/ui/closures/2229_closure_analysis/run_pass/unsafe_ptr.rs @@ -3,6 +3,8 @@ // Test that we can use raw ptrs when using `capture_disjoint_fields`. +#![allow(dead_code)] + #[derive(Debug)] struct S { s: String, diff --git a/src/test/ui/closures/closure-bounds-subtype.stderr b/src/test/ui/closures/closure-bounds-subtype.stderr index bfea4979de..1a40326d98 100644 --- a/src/test/ui/closures/closure-bounds-subtype.stderr +++ b/src/test/ui/closures/closure-bounds-subtype.stderr @@ -2,7 +2,9 @@ error[E0277]: `F` cannot be shared between threads safely --> $DIR/closure-bounds-subtype.rs:13:22 | LL | take_const_owned(f); - | ^ `F` cannot be shared between threads safely + | ---------------- ^ `F` cannot be shared between threads safely + | | + | required by a bound introduced by this call | note: required by a bound in `take_const_owned` --> $DIR/closure-bounds-subtype.rs:4:50 diff --git a/src/test/ui/closures/closure-expected-type/expect-region-supply-region-2.nll.stderr b/src/test/ui/closures/closure-expected-type/expect-region-supply-region-2.nll.stderr index 52bca8dd63..9aab51c986 100644 --- a/src/test/ui/closures/closure-expected-type/expect-region-supply-region-2.nll.stderr +++ b/src/test/ui/closures/closure-expected-type/expect-region-supply-region-2.nll.stderr @@ -17,8 +17,6 @@ LL | fn expect_bound_supply_named<'x>() { ... LL | closure_expecting_bound(|x: &'x u32| { | ^ requires that `'x` must outlive `'static` - | - = help: consider replacing `'x` with `'static` error: aborting due to 2 previous errors diff --git a/src/test/ui/closures/closure-expected-type/expect-region-supply-region-2.stderr b/src/test/ui/closures/closure-expected-type/expect-region-supply-region-2.stderr index 07a67a6183..f584b0c838 100644 --- a/src/test/ui/closures/closure-expected-type/expect-region-supply-region-2.stderr +++ b/src/test/ui/closures/closure-expected-type/expect-region-supply-region-2.stderr @@ -6,7 +6,7 @@ LL | closure_expecting_bound(|x: &'x u32| { | = note: expected reference `&u32` found reference `&'x u32` -note: the anonymous lifetime #1 defined on the body at 14:29... +note: the anonymous lifetime #1 defined here... --> $DIR/expect-region-supply-region-2.rs:14:29 | LL | closure_expecting_bound(|x: &'x u32| { @@ -18,7 +18,7 @@ LL | | LL | | f = Some(x); LL | | }); | |_____^ -note: ...does not necessarily outlive the lifetime `'x` as defined on the function body at 9:30 +note: ...does not necessarily outlive the lifetime `'x` as defined here --> $DIR/expect-region-supply-region-2.rs:9:30 | LL | fn expect_bound_supply_named<'x>() { @@ -32,12 +32,12 @@ LL | closure_expecting_bound(|x: &'x u32| { | = note: expected reference `&u32` found reference `&'x u32` -note: the lifetime `'x` as defined on the function body at 9:30... +note: the lifetime `'x` as defined here... --> $DIR/expect-region-supply-region-2.rs:9:30 | LL | fn expect_bound_supply_named<'x>() { | ^^ -note: ...does not necessarily outlive the anonymous lifetime #1 defined on the body at 14:29 +note: ...does not necessarily outlive the anonymous lifetime #1 defined here --> $DIR/expect-region-supply-region-2.rs:14:29 | LL | closure_expecting_bound(|x: &'x u32| { diff --git a/src/test/ui/closures/coerce-unsafe-to-closure.stderr b/src/test/ui/closures/coerce-unsafe-to-closure.stderr index ab035d03b0..4a47e05491 100644 --- a/src/test/ui/closures/coerce-unsafe-to-closure.stderr +++ b/src/test/ui/closures/coerce-unsafe-to-closure.stderr @@ -2,7 +2,9 @@ error[E0277]: expected a `FnOnce<(&str,)>` closure, found `unsafe extern "rust-i --> $DIR/coerce-unsafe-to-closure.rs:2:44 | LL | let x: Option<&[u8]> = Some("foo").map(std::mem::transmute); - | ^^^^^^^^^^^^^^^^^^^ expected an `FnOnce<(&str,)>` closure, found `unsafe extern "rust-intrinsic" fn(_) -> _ {transmute::<_, _>}` + | --- ^^^^^^^^^^^^^^^^^^^ expected an `FnOnce<(&str,)>` closure, found `unsafe extern "rust-intrinsic" fn(_) -> _ {transmute::<_, _>}` + | | + | required by a bound introduced by this call | = help: the trait `FnOnce<(&str,)>` is not implemented for `unsafe extern "rust-intrinsic" fn(_) -> _ {transmute::<_, _>}` diff --git a/src/test/ui/issues/issue-78720.rs b/src/test/ui/closures/issue-78720.rs similarity index 100% rename from src/test/ui/issues/issue-78720.rs rename to src/test/ui/closures/issue-78720.rs diff --git a/src/test/ui/issues/issue-78720.stderr b/src/test/ui/closures/issue-78720.stderr similarity index 100% rename from src/test/ui/issues/issue-78720.stderr rename to src/test/ui/closures/issue-78720.stderr diff --git a/src/test/ui/closures/issue-87814-2.rs b/src/test/ui/closures/issue-87814-2.rs index 7a5facdac5..efe77f90f0 100644 --- a/src/test/ui/closures/issue-87814-2.rs +++ b/src/test/ui/closures/issue-87814-2.rs @@ -1,5 +1,4 @@ // check-pass -#![feature(try_reserve)] fn main() { let mut schema_all: (Vec, Vec) = (vec![], vec![]); diff --git a/src/test/ui/cmse-nonsecure/cmse-nonsecure-call/wrong-abi-location-1.stderr b/src/test/ui/cmse-nonsecure/cmse-nonsecure-call/wrong-abi-location-1.stderr index 3564ab4b6c..08b763b260 100644 --- a/src/test/ui/cmse-nonsecure/cmse-nonsecure-call/wrong-abi-location-1.stderr +++ b/src/test/ui/cmse-nonsecure/cmse-nonsecure-call/wrong-abi-location-1.stderr @@ -1,4 +1,4 @@ -error[E0781]: the `"C-cmse-nonsecure-call"` ABI is only allowed on function pointers. +error[E0781]: the `"C-cmse-nonsecure-call"` ABI is only allowed on function pointers --> $DIR/wrong-abi-location-1.rs:8:1 | LL | pub extern "C-cmse-nonsecure-call" fn test() {} diff --git a/src/test/ui/cmse-nonsecure/cmse-nonsecure-call/wrong-abi-location-2.stderr b/src/test/ui/cmse-nonsecure/cmse-nonsecure-call/wrong-abi-location-2.stderr index 76073f5488..3ade9891e4 100644 --- a/src/test/ui/cmse-nonsecure/cmse-nonsecure-call/wrong-abi-location-2.stderr +++ b/src/test/ui/cmse-nonsecure/cmse-nonsecure-call/wrong-abi-location-2.stderr @@ -1,4 +1,4 @@ -error[E0781]: the `"C-cmse-nonsecure-call"` ABI is only allowed on function pointers. +error[E0781]: the `"C-cmse-nonsecure-call"` ABI is only allowed on function pointers --> $DIR/wrong-abi-location-2.rs:8:1 | LL | / extern "C-cmse-nonsecure-call" { diff --git a/src/test/ui/codemap_tests/bad-format-args.stderr b/src/test/ui/codemap_tests/bad-format-args.stderr index 30013a658f..ba056cccf9 100644 --- a/src/test/ui/codemap_tests/bad-format-args.stderr +++ b/src/test/ui/codemap_tests/bad-format-args.stderr @@ -2,7 +2,7 @@ error: requires at least a format string argument --> $DIR/bad-format-args.rs:2:5 | LL | format!(); - | ^^^^^^^^^^ + | ^^^^^^^^^ | = note: this error originates in the macro `$crate::__export::format_args` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/codemap_tests/issue-11715.stderr b/src/test/ui/codemap_tests/issue-11715.stderr index d0c29c768e..a6b2b2e50a 100644 --- a/src/test/ui/codemap_tests/issue-11715.stderr +++ b/src/test/ui/codemap_tests/issue-11715.stderr @@ -7,7 +7,7 @@ LL | let z = &mut x; | ^^^^^^ second mutable borrow occurs here LL | z.use_mut(); LL | y.use_mut(); - | - first borrow later used here + | ----------- first borrow later used here error: aborting due to previous error diff --git a/src/test/ui/codemap_tests/issue-28308.stderr b/src/test/ui/codemap_tests/issue-28308.stderr index fc902a2b6d..7daa0510cf 100644 --- a/src/test/ui/codemap_tests/issue-28308.stderr +++ b/src/test/ui/codemap_tests/issue-28308.stderr @@ -2,7 +2,7 @@ error[E0600]: cannot apply unary operator `!` to type `&'static str` --> $DIR/issue-28308.rs:2:5 | LL | assert!("foo"); - | ^^^^^^^^^^^^^^^ cannot apply unary operator `!` + | ^^^^^^^^^^^^^^ cannot apply unary operator `!` | = note: this error originates in the macro `assert` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/codemap_tests/one_line.stderr b/src/test/ui/codemap_tests/one_line.stderr index eddbd29c0e..1ee612184d 100644 --- a/src/test/ui/codemap_tests/one_line.stderr +++ b/src/test/ui/codemap_tests/one_line.stderr @@ -2,8 +2,9 @@ error[E0499]: cannot borrow `v` as mutable more than once at a time --> $DIR/one_line.rs:3:12 | LL | v.push(v.pop().unwrap()); - | - ---- ^ second mutable borrow occurs here - | | | + | -------^^^^^^^---------- + | | | | + | | | second mutable borrow occurs here | | first borrow later used by call | first mutable borrow occurs here diff --git a/src/test/ui/coercion/coerce-expect-unsized.rs b/src/test/ui/coercion/coerce-expect-unsized.rs index d486fdf73a..eeb8fe8234 100644 --- a/src/test/ui/coercion/coerce-expect-unsized.rs +++ b/src/test/ui/coercion/coerce-expect-unsized.rs @@ -1,6 +1,5 @@ // run-pass #![allow(unused_braces)] -#![feature(box_syntax)] use std::cell::RefCell; use std::fmt::Debug; diff --git a/src/test/ui/coercion/coerce-issue-49593-box-never.nofallback.stderr b/src/test/ui/coercion/coerce-issue-49593-box-never.nofallback.stderr new file mode 100644 index 0000000000..fbaa874792 --- /dev/null +++ b/src/test/ui/coercion/coerce-issue-49593-box-never.nofallback.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `(): std::error::Error` is not satisfied + --> $DIR/coerce-issue-49593-box-never.rs:17:53 + | +LL | /* *mut $0 is coerced to Box here */ Box::<_ /* ! */>::new(x) + | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::error::Error` is not implemented for `()` + | + = note: required for the cast to the object type `dyn std::error::Error` + +error[E0277]: the trait bound `(): std::error::Error` is not satisfied + --> $DIR/coerce-issue-49593-box-never.rs:22:49 + | +LL | /* *mut $0 is coerced to *mut Error here */ raw_ptr_box::<_ /* ! */>(x) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::error::Error` is not implemented for `()` + | + = note: required for the cast to the object type `(dyn std::error::Error + 'static)` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/coercion/coerce-issue-49593-box-never.rs b/src/test/ui/coercion/coerce-issue-49593-box-never.rs index 0824ce8cd5..7a4324bd5a 100644 --- a/src/test/ui/coercion/coerce-issue-49593-box-never.rs +++ b/src/test/ui/coercion/coerce-issue-49593-box-never.rs @@ -1,5 +1,9 @@ -// check-pass -#![feature(never_type, never_type_fallback)] +// revisions: nofallback fallback +//[fallback] check-pass +//[nofallback] check-fail + +#![feature(never_type)] +#![cfg_attr(fallback, feature(never_type_fallback))] #![allow(unreachable_code)] use std::error::Error; @@ -11,10 +15,12 @@ fn raw_ptr_box(t: T) -> *mut T { fn foo(x: !) -> Box { /* *mut $0 is coerced to Box here */ Box::<_ /* ! */>::new(x) + //[nofallback]~^ ERROR trait bound `(): std::error::Error` is not satisfied } fn foo_raw_ptr(x: !) -> *mut dyn Error { /* *mut $0 is coerced to *mut Error here */ raw_ptr_box::<_ /* ! */>(x) + //[nofallback]~^ ERROR trait bound `(): std::error::Error` is not satisfied } fn no_coercion(d: *mut dyn Error) -> *mut dyn Error { diff --git a/src/test/ui/coercion/issue-88097.rs b/src/test/ui/coercion/issue-88097.rs new file mode 100644 index 0000000000..e543e1bae9 --- /dev/null +++ b/src/test/ui/coercion/issue-88097.rs @@ -0,0 +1,31 @@ +// In #88097, the compiler attempted to coerce a closure type to itself via +// a function pointer, which caused an unnecessary error. Check that this +// behavior has been fixed. + +// check-pass + +fn peculiar() -> impl Fn(u8) -> u8 { + return |x| x + 1 +} + +fn peculiar2() -> impl Fn(u8) -> u8 { + return |x| x + 1; +} + +fn peculiar3() -> impl Fn(u8) -> u8 { + let f = |x| x + 1; + return f +} + +fn peculiar4() -> impl Fn(u8) -> u8 { + let f = |x| x + 1; + f +} + +fn peculiar5() -> impl Fn(u8) -> u8 { + let f = |x| x + 1; + let g = |x| x + 2; + return if true { f } else { g } +} + +fn main() {} diff --git a/src/test/ui/coherence/coherence-impl-trait-for-trait-object-safe.stderr b/src/test/ui/coherence/coherence-impl-trait-for-trait-object-safe.stderr index a2b779e295..e9090c1b6b 100644 --- a/src/test/ui/coherence/coherence-impl-trait-for-trait-object-safe.stderr +++ b/src/test/ui/coherence/coherence-impl-trait-for-trait-object-safe.stderr @@ -4,7 +4,6 @@ error[E0038]: the trait `NotObjectSafe` cannot be made into an object LL | impl NotObjectSafe for dyn NotObjectSafe { } | ^^^^^^^^^^^^^^^^^ `NotObjectSafe` cannot be made into an object | - = help: consider moving `eq` to another trait note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit --> $DIR/coherence-impl-trait-for-trait-object-safe.rs:6:43 | @@ -12,6 +11,7 @@ LL | trait NotObjectSafe { fn eq(&self, other: Self); } | ------------- ^^^^ ...because method `eq` references the `Self` type in this parameter | | | this trait cannot be made into an object... + = help: consider moving `eq` to another trait error: aborting due to previous error diff --git a/src/test/ui/coherence/coherence-unsafe-trait-object-impl.stderr b/src/test/ui/coherence/coherence-unsafe-trait-object-impl.stderr index cf842b1908..2e2dac288a 100644 --- a/src/test/ui/coherence/coherence-unsafe-trait-object-impl.stderr +++ b/src/test/ui/coherence/coherence-unsafe-trait-object-impl.stderr @@ -2,7 +2,9 @@ error[E0277]: the trait bound `&dyn Trait: Trait` is not satisfied --> $DIR/coherence-unsafe-trait-object-impl.rs:15:13 | LL | takes_t(t); - | ^ the trait `Trait` is not implemented for `&dyn Trait` + | ------- ^ the trait `Trait` is not implemented for `&dyn Trait` + | | + | required by a bound introduced by this call | note: required by a bound in `takes_t` --> $DIR/coherence-unsafe-trait-object-impl.rs:10:15 diff --git a/src/test/ui/coherence/coherence_inherent.stderr b/src/test/ui/coherence/coherence_inherent.stderr index 6f36f2a751..46b128c08f 100644 --- a/src/test/ui/coherence/coherence_inherent.stderr +++ b/src/test/ui/coherence/coherence_inherent.stderr @@ -5,8 +5,10 @@ LL | s.the_fn(); | ^^^^^^ method not found in `&TheStruct` | = help: items from traits can only be used if the trait is in scope - = note: the following trait is implemented but not in scope; perhaps add a `use` for it: - `use Lib::TheTrait;` +help: the following trait is implemented but not in scope; perhaps add a `use` for it: + | +LL | use Lib::TheTrait; + | error: aborting due to previous error diff --git a/src/test/ui/coherence/coherence_inherent_cc.stderr b/src/test/ui/coherence/coherence_inherent_cc.stderr index edfe6348d1..af0ef3b693 100644 --- a/src/test/ui/coherence/coherence_inherent_cc.stderr +++ b/src/test/ui/coherence/coherence_inherent_cc.stderr @@ -5,8 +5,10 @@ LL | s.the_fn(); | ^^^^^^ method not found in `&TheStruct` | = help: items from traits can only be used if the trait is in scope - = note: the following trait is implemented but not in scope; perhaps add a `use` for it: - `use coherence_inherent_cc_lib::TheTrait;` +help: the following trait is implemented but not in scope; perhaps add a `use` for it: + | +LL | use coherence_inherent_cc_lib::TheTrait; + | error: aborting due to previous error diff --git a/src/test/ui/command/command-pre-exec.rs b/src/test/ui/command/command-pre-exec.rs index 10a8b19159..61914e2293 100644 --- a/src/test/ui/command/command-pre-exec.rs +++ b/src/test/ui/command/command-pre-exec.rs @@ -8,6 +8,8 @@ // ignore-sgx no processes #![feature(process_exec, rustc_private)] +extern crate libc; + use std::env; use std::io::Error; use std::os::unix::process::CommandExt; @@ -15,23 +17,6 @@ use std::process::Command; use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::Arc; -#[cfg(not(target_os = "linux"))] -fn getpid() -> u32 { - use std::process; - process::id() -} - -/// We need to directly use the getpid syscall instead of using `process::id()` -/// because the libc wrapper might return incorrect values after a process was -/// forked. -#[cfg(target_os = "linux")] -fn getpid() -> u32 { - extern crate libc; - unsafe { - libc::syscall(libc::SYS_getpid) as _ - } -} - fn main() { if let Some(arg) = env::args().nth(1) { match &arg[..] { @@ -83,12 +68,14 @@ fn main() { }; assert_eq!(output.raw_os_error(), Some(102)); - let pid = getpid(); + let pid = unsafe { libc::getpid() }; + assert!(pid >= 0); let output = unsafe { Command::new(&me) .arg("empty") .pre_exec(move || { - let child = getpid(); + let child = libc::getpid(); + assert!(child >= 0); assert!(pid != child); Ok(()) }) diff --git a/src/test/ui/compile_error_macro.stderr b/src/test/ui/compile_error_macro.stderr index 8aa1878c5d..91ebcaa6e9 100644 --- a/src/test/ui/compile_error_macro.stderr +++ b/src/test/ui/compile_error_macro.stderr @@ -2,7 +2,7 @@ error: a very descriptive error message --> $DIR/compile_error_macro.rs:2:5 | LL | compile_error!("a very descriptive error message"); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/conditional-compilation/cfg-attr-syntax-validation.stderr b/src/test/ui/conditional-compilation/cfg-attr-syntax-validation.stderr index bbcab9690a..a057fd19b1 100644 --- a/src/test/ui/conditional-compilation/cfg-attr-syntax-validation.stderr +++ b/src/test/ui/conditional-compilation/cfg-attr-syntax-validation.stderr @@ -59,7 +59,7 @@ LL | #[cfg(feature = $expr)] | ^^^^^ ... LL | generate_s10!(concat!("nonexistent")); - | -------------------------------------- in this macro invocation + | ------------------------------------- in this macro invocation | = note: this error originates in the macro `generate_s10` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -70,7 +70,7 @@ LL | #[cfg(feature = $expr)] | ^^^^^ ... LL | generate_s10!(concat!("nonexistent")); - | -------------------------------------- in this macro invocation + | ------------------------------------- in this macro invocation | = note: this error originates in the macro `generate_s10` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/conditional-compilation/cfg-attr-unknown-attribute-macro-expansion.stderr b/src/test/ui/conditional-compilation/cfg-attr-unknown-attribute-macro-expansion.stderr index a662f68033..fc8df6552c 100644 --- a/src/test/ui/conditional-compilation/cfg-attr-unknown-attribute-macro-expansion.stderr +++ b/src/test/ui/conditional-compilation/cfg-attr-unknown-attribute-macro-expansion.stderr @@ -5,7 +5,7 @@ LL | #[cfg_attr(all(), unknown)] | ^^^^^^^ ... LL | foo!(); - | ------- in this macro invocation + | ------ in this macro invocation | = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/const-generics/broken-mir-2.rs b/src/test/ui/const-generics/broken-mir-2.rs index f9e0315137..9d62281178 100644 --- a/src/test/ui/const-generics/broken-mir-2.rs +++ b/src/test/ui/const-generics/broken-mir-2.rs @@ -1,4 +1,7 @@ // run-pass + +#![allow(dead_code)] + use std::fmt::Debug; #[derive(Debug)] diff --git a/src/test/ui/const-generics/expose-default-substs-param-env.rs b/src/test/ui/const-generics/expose-default-substs-param-env.rs new file mode 100644 index 0000000000..e40c93116a --- /dev/null +++ b/src/test/ui/const-generics/expose-default-substs-param-env.rs @@ -0,0 +1,9 @@ +// build-pass + +#![feature(generic_const_exprs)] +#![allow(unused_braces, incomplete_features)] + +pub trait Foo {} +pub trait Bar: Foo<{ 1 }> { } + +fn main() {} diff --git a/src/test/ui/const-generics/generic_const_exprs/abstract-consts-as-cast-5.rs b/src/test/ui/const-generics/generic_const_exprs/abstract-consts-as-cast-5.rs new file mode 100644 index 0000000000..916d60c0e0 --- /dev/null +++ b/src/test/ui/const-generics/generic_const_exprs/abstract-consts-as-cast-5.rs @@ -0,0 +1,11 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +fn foo(a: [(); N as usize]) { + bar::<{ N as usize as usize }>(); + //~^ error: unconstrained generic constant +} + +fn bar() {} + +fn main() {} diff --git a/src/test/ui/const-generics/generic_const_exprs/abstract-consts-as-cast-5.stderr b/src/test/ui/const-generics/generic_const_exprs/abstract-consts-as-cast-5.stderr new file mode 100644 index 0000000000..d48b639dbd --- /dev/null +++ b/src/test/ui/const-generics/generic_const_exprs/abstract-consts-as-cast-5.stderr @@ -0,0 +1,10 @@ +error: unconstrained generic constant + --> $DIR/abstract-consts-as-cast-5.rs:5:11 + | +LL | bar::<{ N as usize as usize }>(); + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); { N as usize as usize }]:` + +error: aborting due to previous error + diff --git a/src/test/ui/const-generics/generic_const_exprs/array-size-in-generic-struct-param.full.stderr b/src/test/ui/const-generics/generic_const_exprs/array-size-in-generic-struct-param.full.stderr index deb6f3bd12..041232e869 100644 --- a/src/test/ui/const-generics/generic_const_exprs/array-size-in-generic-struct-param.full.stderr +++ b/src/test/ui/const-generics/generic_const_exprs/array-size-in-generic-struct-param.full.stderr @@ -10,9 +10,10 @@ error: overly complex generic constant --> $DIR/array-size-in-generic-struct-param.rs:19:15 | LL | arr: [u8; CFG.arr_size], - | ^^^^^^^^^^^^ unsupported projection + | ^^^^^^^^^^^^ field access is not supported in generic constant | = help: consider moving this anonymous constant into a `const` function + = note: this operation may be supported in the future error: aborting due to 2 previous errors diff --git a/src/test/ui/const-generics/generic_const_exprs/closures.stderr b/src/test/ui/const-generics/generic_const_exprs/closures.stderr index 9f0b7252e8..0dfd804be4 100644 --- a/src/test/ui/const-generics/generic_const_exprs/closures.stderr +++ b/src/test/ui/const-generics/generic_const_exprs/closures.stderr @@ -4,9 +4,10 @@ error: overly complex generic constant LL | fn test() -> [u8; N + (|| 42)()] {} | ^^^^-------^^ | | - | unsupported rvalue + | dereferencing is not supported in generic constants | = help: consider moving this anonymous constant into a `const` function + = note: this operation may be supported in the future error: aborting due to previous error diff --git a/src/test/ui/const-generics/generic_const_exprs/const_eval_resolve_canonical.rs b/src/test/ui/const-generics/generic_const_exprs/const_eval_resolve_canonical.rs new file mode 100644 index 0000000000..b79bc262d2 --- /dev/null +++ b/src/test/ui/const-generics/generic_const_exprs/const_eval_resolve_canonical.rs @@ -0,0 +1,29 @@ +// run-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +trait Foo { + type Assoc: Default; +} + +impl Foo<0> for () { + type Assoc = u32; +} + +impl Foo<3> for () { + type Assoc = i64; +} + +fn foo(_: T) -> <() as Foo<{ N + 1 }>>::Assoc +where + (): Foo<{ N + 1 }>, +{ + Default::default() +} + +fn main() { + // Test that we can correctly infer `T` which requires evaluating + // `{ N + 1 }` which has substs containing an inference var + let mut _q = Default::default(); + _q = foo::<_, 2>(_q); +} diff --git a/src/test/ui/const-generics/generic_const_exprs/let-bindings.stderr b/src/test/ui/const-generics/generic_const_exprs/let-bindings.stderr index 5749defb3e..5ebb4c3999 100644 --- a/src/test/ui/const-generics/generic_const_exprs/let-bindings.stderr +++ b/src/test/ui/const-generics/generic_const_exprs/let-bindings.stderr @@ -2,21 +2,19 @@ error: overly complex generic constant --> $DIR/let-bindings.rs:6:68 | LL | fn test() -> [u8; { let x = N; N + 1 }] where [u8; { let x = N; N + 1 }]: Default { - | ^^^^^^-^^^^^^^^^^^^^ - | | - | unsupported statement + | ^^^^^^^^^^^^^^^^^^^^ blocks are not supported in generic constant | = help: consider moving this anonymous constant into a `const` function + = note: this operation may be supported in the future error: overly complex generic constant --> $DIR/let-bindings.rs:6:35 | LL | fn test() -> [u8; { let x = N; N + 1 }] where [u8; { let x = N; N + 1 }]: Default { - | ^^^^^^-^^^^^^^^^^^^^ - | | - | unsupported statement + | ^^^^^^^^^^^^^^^^^^^^ blocks are not supported in generic constant | = help: consider moving this anonymous constant into a `const` function + = note: this operation may be supported in the future error: aborting due to 2 previous errors diff --git a/src/test/ui/const-generics/generic_const_exprs/object-safety-err-ret.stderr b/src/test/ui/const-generics/generic_const_exprs/object-safety-err-ret.stderr index 319e6c2c03..4e1d71f154 100644 --- a/src/test/ui/const-generics/generic_const_exprs/object-safety-err-ret.stderr +++ b/src/test/ui/const-generics/generic_const_exprs/object-safety-err-ret.stderr @@ -4,7 +4,6 @@ error[E0038]: the trait `Foo` cannot be made into an object LL | fn use_dyn(v: &dyn Foo) { | ^^^^^^^ `Foo` cannot be made into an object | - = help: consider moving `test` to another trait note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit --> $DIR/object-safety-err-ret.rs:8:23 | @@ -12,6 +11,7 @@ LL | trait Foo { | --- this trait cannot be made into an object... LL | fn test(&self) -> [u8; bar::()]; | ^^^^^^^^^^^^^^^^^^^ ...because method `test` references the `Self` type in its return type + = help: consider moving `test` to another trait error: aborting due to previous error diff --git a/src/test/ui/const-generics/generic_const_exprs/unify-op-with-fn-call.rs b/src/test/ui/const-generics/generic_const_exprs/unify-op-with-fn-call.rs new file mode 100644 index 0000000000..c0404d35b0 --- /dev/null +++ b/src/test/ui/const-generics/generic_const_exprs/unify-op-with-fn-call.rs @@ -0,0 +1,35 @@ +#![feature(generic_const_exprs, adt_const_params, const_trait_impl)] +#![allow(incomplete_features)] + +// test `N + N` unifies with explicit function calls for non-builtin-types +#[derive(PartialEq, Eq)] +struct Foo(u8); + +impl const std::ops::Add for Foo { + type Output = Self; + + fn add(self, rhs: Self) -> Self::Output { + self + } +} + +struct Evaluatable; + +fn foo(a: Evaluatable<{ N + N }>) { + bar::<{ std::ops::Add::add(N, N) }>(); +} + +fn bar() {} + +// test that `N + N` unifies with explicit function calls for builin-types +struct Evaluatable2; + +fn foo2(a: Evaluatable2<{ N + N }>) { + bar2::<{ std::ops::Add::add(N, N) }>(); + //~^ error: unconstrained generic constant + // FIXME(generic_const_exprs) make this not an error +} + +fn bar2() {} + +fn main() {} diff --git a/src/test/ui/const-generics/generic_const_exprs/unify-op-with-fn-call.stderr b/src/test/ui/const-generics/generic_const_exprs/unify-op-with-fn-call.stderr new file mode 100644 index 0000000000..d18c7916f5 --- /dev/null +++ b/src/test/ui/const-generics/generic_const_exprs/unify-op-with-fn-call.stderr @@ -0,0 +1,10 @@ +error: unconstrained generic constant + --> $DIR/unify-op-with-fn-call.rs:28:12 + | +LL | bar2::<{ std::ops::Add::add(N, N) }>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); { std::ops::Add::add(N, N) }]:` + +error: aborting due to previous error + diff --git a/src/test/ui/const-generics/generic_const_exprs/unused_expr.stderr b/src/test/ui/const-generics/generic_const_exprs/unused_expr.stderr index 1687dbbcbe..df73acf53d 100644 --- a/src/test/ui/const-generics/generic_const_exprs/unused_expr.stderr +++ b/src/test/ui/const-generics/generic_const_exprs/unused_expr.stderr @@ -2,31 +2,28 @@ error: overly complex generic constant --> $DIR/unused_expr.rs:4:34 | LL | fn add() -> [u8; { N + 1; 5 }] { - | ^^-----^^^^^ - | | - | dead code + | ^^^^^^^^^^^^ blocks are not supported in generic constant | = help: consider moving this anonymous constant into a `const` function + = note: this operation may be supported in the future error: overly complex generic constant --> $DIR/unused_expr.rs:9:34 | LL | fn div() -> [u8; { N / 1; 5 }] { - | ^^-----^^^^^ - | | - | dead code + | ^^^^^^^^^^^^ blocks are not supported in generic constant | = help: consider moving this anonymous constant into a `const` function + = note: this operation may be supported in the future error: overly complex generic constant --> $DIR/unused_expr.rs:16:38 | LL | fn fn_call() -> [u8; { foo(N); 5 }] { - | ^^------^^^^^ - | | - | dead code + | ^^^^^^^^^^^^^ blocks are not supported in generic constant | = help: consider moving this anonymous constant into a `const` function + = note: this operation may be supported in the future error: aborting due to 3 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 5386ef56a2..0f0e339655 100644 --- a/src/test/ui/const-generics/issues/issue-67375.full.stderr +++ b/src/test/ui/const-generics/issues/issue-67375.full.stderr @@ -2,9 +2,9 @@ error: overly complex generic constant --> $DIR/issue-67375.rs:7:17 | LL | inner: [(); { [|_: &T| {}; 0].len() }], - | ^^^----------^^^^^^^^^^^^ - | | - | unsupported rvalue + | ^^---------------------^^ + | | + | pointer casts are not allowed in generic constants | = help: consider moving this anonymous constant into a `const` function diff --git a/src/test/ui/const-generics/issues/issue-67945-2.full.stderr b/src/test/ui/const-generics/issues/issue-67945-2.full.stderr index 118cf447c0..cce85772aa 100644 --- a/src/test/ui/const-generics/issues/issue-67945-2.full.stderr +++ b/src/test/ui/const-generics/issues/issue-67945-2.full.stderr @@ -5,13 +5,13 @@ LL | A: [(); { | _____________^ LL | | LL | | let x: Option> = None; - | | ---- unsupported rvalue LL | | LL | | 0 LL | | }], - | |_____^ + | |_____^ blocks are not supported in generic constant | = help: consider moving this anonymous constant into a `const` function + = note: this operation may be supported in the future error: aborting due to previous error diff --git a/src/test/ui/const-generics/issues/issue-82956.rs b/src/test/ui/const-generics/issues/issue-82956.rs new file mode 100644 index 0000000000..a3a0d8d06e --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-82956.rs @@ -0,0 +1,33 @@ +#![feature(generic_const_exprs, array_map)] +#![allow(incomplete_features)] + +pub struct ConstCheck; + +pub trait True {} +impl True for ConstCheck {} + +pub trait OrdesDec { + type Newlen; + type Output; + + fn pop(self) -> (Self::Newlen, Self::Output); +} + +impl OrdesDec for [T; N] +where + ConstCheck<{N > 1}>: True, + [T; N - 1]: Sized, +{ + type Newlen = [T; N - 1]; + type Output = T; + + fn pop(self) -> (Self::Newlen, Self::Output) { + let mut iter = IntoIter::new(self); + //~^ ERROR: failed to resolve: use of undeclared type `IntoIter` + let end = iter.next_back().unwrap(); + let new = [(); N - 1].map(move |()| iter.next().unwrap()); + (new, end) + } +} + +fn main() {} diff --git a/src/test/ui/const-generics/issues/issue-82956.stderr b/src/test/ui/const-generics/issues/issue-82956.stderr new file mode 100644 index 0000000000..c8b999da98 --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-82956.stderr @@ -0,0 +1,21 @@ +error[E0433]: failed to resolve: use of undeclared type `IntoIter` + --> $DIR/issue-82956.rs:25:24 + | +LL | let mut iter = IntoIter::new(self); + | ^^^^^^^^ not found in this scope + | +help: consider importing one of these items + | +LL | use std::array::IntoIter; + | +LL | use std::collections::binary_heap::IntoIter; + | +LL | use std::collections::btree_map::IntoIter; + | +LL | use std::collections::btree_set::IntoIter; + | + and 8 other candidates + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0433`. diff --git a/src/test/ui/const-generics/issues/issue-84659.rs b/src/test/ui/const-generics/issues/issue-84659.rs new file mode 100644 index 0000000000..440ca740af --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-84659.rs @@ -0,0 +1,12 @@ +#![allow(incomplete_features)] +#![feature(generic_const_exprs)] + +trait Bar {} + +trait Foo<'a> { + const N: usize; + type Baz: Bar<{ Self::N }>; + //~^ ERROR: unconstrained generic constant +} + +fn main() {} diff --git a/src/test/ui/const-generics/issues/issue-84659.stderr b/src/test/ui/const-generics/issues/issue-84659.stderr new file mode 100644 index 0000000000..2dfc48a34e --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-84659.stderr @@ -0,0 +1,10 @@ +error: unconstrained generic constant + --> $DIR/issue-84659.rs:8:15 + | +LL | type Baz: Bar<{ Self::N }>; + | ^^^^^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); { Self::N }]:` + +error: aborting due to previous error + diff --git a/src/test/ui/const-generics/issues/issue-86530.rs b/src/test/ui/const-generics/issues/issue-86530.rs new file mode 100644 index 0000000000..b024decd4e --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-86530.rs @@ -0,0 +1,20 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +pub trait X { + const Y: usize; +} + +fn z(t: T) +where + T: X, + [(); T::Y]: , +{ +} + +fn unit_literals() { + z(" "); + //~^ ERROR: the trait bound `&str: X` is not satisfied +} + +fn main() {} diff --git a/src/test/ui/const-generics/issues/issue-86530.stderr b/src/test/ui/const-generics/issues/issue-86530.stderr new file mode 100644 index 0000000000..c63857b231 --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-86530.stderr @@ -0,0 +1,20 @@ +error[E0277]: the trait bound `&str: X` is not satisfied + --> $DIR/issue-86530.rs:16:7 + | +LL | z(" "); + | - ^^^ the trait `X` is not implemented for `&str` + | | + | required by a bound introduced by this call + | +note: required by a bound in `z` + --> $DIR/issue-86530.rs:10:8 + | +LL | fn z(t: T) + | - required by a bound in this +LL | where +LL | T: X, + | ^ required by this bound in `z` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/const-generics/issues/issue-86535-2.rs b/src/test/ui/const-generics/issues/issue-86535-2.rs new file mode 100644 index 0000000000..0b535fd664 --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-86535-2.rs @@ -0,0 +1,19 @@ +// run-pass +#![feature(adt_const_params, generic_const_exprs)] +#![allow(incomplete_features)] + +pub trait Foo { + const ASSOC_C: usize; + fn foo() where [(); Self::ASSOC_C]:; +} + +struct Bar; +impl Foo for Bar { + const ASSOC_C: usize = 3; + + fn foo() where [u8; Self::ASSOC_C]: { + let _: [u8; Self::ASSOC_C] = loop {}; + } +} + +fn main() {} diff --git a/src/test/ui/const-generics/issues/issue-86535.rs b/src/test/ui/const-generics/issues/issue-86535.rs new file mode 100644 index 0000000000..5289c4e99d --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-86535.rs @@ -0,0 +1,20 @@ +// run-pass +#![feature(adt_const_params, generic_const_exprs)] +#![allow(incomplete_features, unused_variables)] + +struct F; +impl X for F<{ S }> { + const W: usize = 3; + + fn d(r: &[u8; Self::W]) -> F<{ S }> { + let x: [u8; Self::W] = [0; Self::W]; + F + } +} + +pub trait X { + const W: usize; + fn d(r: &[u8; Self::W]) -> Self; +} + +fn main() {} diff --git a/src/test/ui/const-generics/issues/issue-87493.rs b/src/test/ui/const-generics/issues/issue-87493.rs new file mode 100644 index 0000000000..d8599ab22a --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-87493.rs @@ -0,0 +1,14 @@ +pub trait MyTrait { + type Assoc; +} + +pub fn foo(_s: S, _t: T) +where + S: MyTrait, + T: MyTrait, + //~^ ERROR: expected one of `,` or `>`, found `==` + //~| ERROR: this trait takes 0 generic arguments but 1 generic argument was supplied +{ +} + +fn main() {} diff --git a/src/test/ui/const-generics/issues/issue-87493.stderr b/src/test/ui/const-generics/issues/issue-87493.stderr new file mode 100644 index 0000000000..8f92eeaffd --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-87493.stderr @@ -0,0 +1,28 @@ +error: expected one of `,` or `>`, found `==` + --> $DIR/issue-87493.rs:8:22 + | +LL | T: MyTrait, + | ^^ expected one of `,` or `>` + | +help: if you meant to use an associated type binding, replace `==` with `=` + | +LL | T: MyTrait, + | ~ + +error[E0107]: this trait takes 0 generic arguments but 1 generic argument was supplied + --> $DIR/issue-87493.rs:8:8 + | +LL | T: MyTrait, + | ^^^^^^^------------------- help: remove these generics + | | + | expected 0 generic arguments + | +note: trait defined here, with 0 generic parameters + --> $DIR/issue-87493.rs:1:11 + | +LL | pub trait MyTrait { + | ^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0107`. diff --git a/src/test/ui/const-generics/issues/issue-89334.rs b/src/test/ui/const-generics/issues/issue-89334.rs new file mode 100644 index 0000000000..b15b7428cd --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-89334.rs @@ -0,0 +1,16 @@ +// build-pass + +#![feature(generic_const_exprs)] +#![allow(unused_braces, incomplete_features)] + +pub trait AnotherTrait{ + const ARRAY_SIZE: usize; +} +pub trait Shard: + AsMut<[[u8; T::ARRAY_SIZE]]> +where + [(); T::ARRAY_SIZE]: Sized +{ +} + +fn main() {} diff --git a/src/test/ui/const-generics/parser-error-recovery/issue-89013-no-assoc.rs b/src/test/ui/const-generics/parser-error-recovery/issue-89013-no-assoc.rs new file mode 100644 index 0000000000..99d8e9dea9 --- /dev/null +++ b/src/test/ui/const-generics/parser-error-recovery/issue-89013-no-assoc.rs @@ -0,0 +1,16 @@ +trait Foo { + fn do_x(&self) -> [u8; N]; +} + +struct Bar; + +const T: usize = 42; + +impl Foo for Bar { +//~^ERROR expected lifetime, type, or constant, found keyword `const` + fn do_x(&self) -> [u8; 3] { + [0u8; 3] + } +} + +fn main() {} diff --git a/src/test/ui/const-generics/parser-error-recovery/issue-89013-no-assoc.stderr b/src/test/ui/const-generics/parser-error-recovery/issue-89013-no-assoc.stderr new file mode 100644 index 0000000000..ddddd86ab9 --- /dev/null +++ b/src/test/ui/const-generics/parser-error-recovery/issue-89013-no-assoc.stderr @@ -0,0 +1,14 @@ +error: expected lifetime, type, or constant, found keyword `const` + --> $DIR/issue-89013-no-assoc.rs:9:10 + | +LL | impl Foo for Bar { + | ^^^^^ + | +help: the `const` keyword is only needed in the definition of the type + | +LL - impl Foo for Bar { +LL + impl Foo<3> for Bar { + | + +error: aborting due to previous error + diff --git a/src/test/ui/const-generics/parser-error-recovery/issue-89013-no-kw.rs b/src/test/ui/const-generics/parser-error-recovery/issue-89013-no-kw.rs new file mode 100644 index 0000000000..19e0f38d32 --- /dev/null +++ b/src/test/ui/const-generics/parser-error-recovery/issue-89013-no-kw.rs @@ -0,0 +1,17 @@ +trait Foo { + fn do_x(&self) -> [u8; N]; +} + +struct Bar; + +const T: usize = 42; + +impl Foo for Bar { +//~^ ERROR cannot constrain an associated constant to a value +//~| ERROR associated type bindings are not allowed here + fn do_x(&self) -> [u8; 3] { + [0u8; 3] + } +} + +fn main() {} diff --git a/src/test/ui/const-generics/parser-error-recovery/issue-89013-no-kw.stderr b/src/test/ui/const-generics/parser-error-recovery/issue-89013-no-kw.stderr new file mode 100644 index 0000000000..bbca92ad63 --- /dev/null +++ b/src/test/ui/const-generics/parser-error-recovery/issue-89013-no-kw.stderr @@ -0,0 +1,18 @@ +error: cannot constrain an associated constant to a value + --> $DIR/issue-89013-no-kw.rs:9:10 + | +LL | impl Foo for Bar { + | -^^^- + | | | + | | ...cannot be constrained to this value + | this associated constant... + +error[E0229]: associated type bindings are not allowed here + --> $DIR/issue-89013-no-kw.rs:9:10 + | +LL | impl Foo for Bar { + | ^^^^^ associated type not allowed here + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0229`. diff --git a/src/test/ui/const-generics/parser-error-recovery/issue-89013-type.rs b/src/test/ui/const-generics/parser-error-recovery/issue-89013-type.rs new file mode 100644 index 0000000000..0ec6762b6e --- /dev/null +++ b/src/test/ui/const-generics/parser-error-recovery/issue-89013-type.rs @@ -0,0 +1,16 @@ +trait Foo { + fn do_x(&self) -> [u8; N]; +} + +struct Bar; + +const T: usize = 42; + +impl Foo for Bar { +//~^ERROR missing type to the right of `=` + fn do_x(&self) -> [u8; 3] { + [0u8; 3] + } +} + +fn main() {} diff --git a/src/test/ui/const-generics/parser-error-recovery/issue-89013-type.stderr b/src/test/ui/const-generics/parser-error-recovery/issue-89013-type.stderr new file mode 100644 index 0000000000..f0d0d90c77 --- /dev/null +++ b/src/test/ui/const-generics/parser-error-recovery/issue-89013-type.stderr @@ -0,0 +1,8 @@ +error: missing type to the right of `=` + --> $DIR/issue-89013-type.rs:9:13 + | +LL | impl Foo for Bar { + | ^---- expected type, found keyword `type` + +error: aborting due to previous error + diff --git a/src/test/ui/const-generics/parser-error-recovery/issue-89013.rs b/src/test/ui/const-generics/parser-error-recovery/issue-89013.rs new file mode 100644 index 0000000000..ca1158a2f6 --- /dev/null +++ b/src/test/ui/const-generics/parser-error-recovery/issue-89013.rs @@ -0,0 +1,18 @@ +trait Foo { + fn do_x(&self) -> [u8; N]; +} + +struct Bar; + +const T: usize = 42; + +impl Foo for Bar { +//~^ ERROR expected lifetime, type, or constant, found keyword `const` +//~| ERROR cannot constrain an associated constant to a value +//~| ERROR associated type bindings are not allowed here + fn do_x(&self) -> [u8; 3] { + [0u8; 3] + } +} + +fn main() {} diff --git a/src/test/ui/const-generics/parser-error-recovery/issue-89013.stderr b/src/test/ui/const-generics/parser-error-recovery/issue-89013.stderr new file mode 100644 index 0000000000..85379d3f06 --- /dev/null +++ b/src/test/ui/const-generics/parser-error-recovery/issue-89013.stderr @@ -0,0 +1,30 @@ +error: expected lifetime, type, or constant, found keyword `const` + --> $DIR/issue-89013.rs:9:14 + | +LL | impl Foo for Bar { + | ^^^^^ + | +help: the `const` keyword is only needed in the definition of the type + | +LL - impl Foo for Bar { +LL + impl Foo for Bar { + | + +error: cannot constrain an associated constant to a value + --> $DIR/issue-89013.rs:9:10 + | +LL | impl Foo for Bar { + | -^^^^^^^^^- + | | | + | | ...cannot be constrained to this value + | this associated constant... + +error[E0229]: associated type bindings are not allowed here + --> $DIR/issue-89013.rs:9:10 + | +LL | impl Foo for Bar { + | ^^^^^^^^^^^ associated type not allowed here + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0229`. diff --git a/src/test/ui/const-generics/sneaky-array-repeat-expr.rs b/src/test/ui/const-generics/sneaky-array-repeat-expr.rs new file mode 100644 index 0000000000..b147c246bd --- /dev/null +++ b/src/test/ui/const-generics/sneaky-array-repeat-expr.rs @@ -0,0 +1,32 @@ +trait Trait { + const Assoc: usize; +} + +impl Trait for () { + const Assoc: usize = 1; +} + + +pub const fn foo() where (): Trait { + let bar = [(); <()>::Assoc]; + //~^ error: constant expression depends on a generic parameter +} + +trait Trait2 { + const Assoc2: usize; +} + +impl Trait2 for () { + const Assoc2: usize = N - 1; +} + + +pub const fn foo2() where (): Trait2 { + let bar2 = [(); <()>::Assoc2]; + //~^ error: constant expression depends on a generic parameter +} + +fn main() { + foo::<0>(); + foo2::<0>(); +} diff --git a/src/test/ui/const-generics/sneaky-array-repeat-expr.stderr b/src/test/ui/const-generics/sneaky-array-repeat-expr.stderr new file mode 100644 index 0000000000..5c77375d39 --- /dev/null +++ b/src/test/ui/const-generics/sneaky-array-repeat-expr.stderr @@ -0,0 +1,18 @@ +error: constant expression depends on a generic parameter + --> $DIR/sneaky-array-repeat-expr.rs:11:20 + | +LL | let bar = [(); <()>::Assoc]; + | ^^^^^^^^^^^ + | + = note: this may fail depending on what value the parameter takes + +error: constant expression depends on a generic parameter + --> $DIR/sneaky-array-repeat-expr.rs:25:21 + | +LL | let bar2 = [(); <()>::Assoc2]; + | ^^^^^^^^^^^^ + | + = note: this may fail depending on what value the parameter takes + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/const-generics/type-dependent/type-mismatch.full.stderr b/src/test/ui/const-generics/type-dependent/type-mismatch.full.stderr index 02108d8596..70bc640579 100644 --- a/src/test/ui/const-generics/type-dependent/type-mismatch.full.stderr +++ b/src/test/ui/const-generics/type-dependent/type-mismatch.full.stderr @@ -7,7 +7,7 @@ LL | assert_eq!(R.method::<1u16>(), 1); help: change the type of the numeric literal from `u16` to `u8` | LL | assert_eq!(R.method::<1u8>(), 1); - | ~~~ + | ~~ error: aborting due to previous error diff --git a/src/test/ui/const-generics/type-dependent/type-mismatch.min.stderr b/src/test/ui/const-generics/type-dependent/type-mismatch.min.stderr index 02108d8596..70bc640579 100644 --- a/src/test/ui/const-generics/type-dependent/type-mismatch.min.stderr +++ b/src/test/ui/const-generics/type-dependent/type-mismatch.min.stderr @@ -7,7 +7,7 @@ LL | assert_eq!(R.method::<1u16>(), 1); help: change the type of the numeric literal from `u16` to `u8` | LL | assert_eq!(R.method::<1u8>(), 1); - | ~~~ + | ~~ error: aborting due to previous error diff --git a/src/test/ui/const-generics/unused_braces.stderr b/src/test/ui/const-generics/unused_braces.stderr index 5e1bace549..533fcabd41 100644 --- a/src/test/ui/const-generics/unused_braces.stderr +++ b/src/test/ui/const-generics/unused_braces.stderr @@ -2,13 +2,18 @@ warning: unnecessary braces around const expression --> $DIR/unused_braces.rs:9:14 | LL | let _: A<{ 7 }>; - | ^^^^^ help: remove these braces + | ^^ ^^ | note: the lint level is defined here --> $DIR/unused_braces.rs:3:9 | LL | #![warn(unused_braces)] | ^^^^^^^^^^^^^ +help: remove these braces + | +LL - let _: A<{ 7 }>; +LL + let _: A<7>; + | warning: 1 warning emitted diff --git a/src/test/ui/consts/const-eval/const_panic.rs b/src/test/ui/consts/const-eval/const_panic.rs index e4455d86a1..5b9a8f8e2a 100644 --- a/src/test/ui/consts/const-eval/const_panic.rs +++ b/src/test/ui/consts/const-eval/const_panic.rs @@ -1,4 +1,3 @@ -#![feature(const_panic)] #![allow(non_fmt_panics)] #![crate_type = "lib"] @@ -15,10 +14,13 @@ const Y: () = std::unreachable!(); const X: () = std::unimplemented!(); //~^ ERROR evaluation of constant value failed -// + const W: () = std::panic!(MSG); //~^ ERROR evaluation of constant value failed +const W2: () = std::panic!("{}", MSG); +//~^ ERROR evaluation of constant value failed + const Z_CORE: () = core::panic!("cheese"); //~^ ERROR evaluation of constant value failed @@ -33,3 +35,6 @@ const X_CORE: () = core::unimplemented!(); const W_CORE: () = core::panic!(MSG); //~^ ERROR evaluation of constant value failed + +const W2_CORE: () = core::panic!("{}", MSG); +//~^ ERROR evaluation of constant value failed diff --git a/src/test/ui/consts/const-eval/const_panic.stderr b/src/test/ui/consts/const-eval/const_panic.stderr index c0c749ede5..3932c2bc0a 100644 --- a/src/test/ui/consts/const-eval/const_panic.stderr +++ b/src/test/ui/consts/const-eval/const_panic.stderr @@ -1,83 +1,99 @@ error[E0080]: evaluation of constant value failed - --> $DIR/const_panic.rs:7:15 + --> $DIR/const_panic.rs:6:15 | LL | const Z: () = std::panic!("cheese"); - | ^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'cheese', $DIR/const_panic.rs:7:15 + | ^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'cheese', $DIR/const_panic.rs:6:15 | = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0080]: evaluation of constant value failed - --> $DIR/const_panic.rs:10:16 + --> $DIR/const_panic.rs:9:16 | LL | const Z2: () = std::panic!(); - | ^^^^^^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/const_panic.rs:10:16 + | ^^^^^^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/const_panic.rs:9:16 | = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0080]: evaluation of constant value failed - --> $DIR/const_panic.rs:13:15 + --> $DIR/const_panic.rs:12:15 | LL | const Y: () = std::unreachable!(); - | ^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'internal error: entered unreachable code', $DIR/const_panic.rs:13:15 + | ^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'internal error: entered unreachable code', $DIR/const_panic.rs:12:15 | = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0080]: evaluation of constant value failed - --> $DIR/const_panic.rs:16:15 + --> $DIR/const_panic.rs:15:15 | LL | const X: () = std::unimplemented!(); - | ^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'not implemented', $DIR/const_panic.rs:16:15 + | ^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'not implemented', $DIR/const_panic.rs:15:15 | = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0080]: evaluation of constant value failed - --> $DIR/const_panic.rs:19:15 + --> $DIR/const_panic.rs:18:15 | LL | const W: () = std::panic!(MSG); - | ^^^^^^^^^^^^^^^^ the evaluated program panicked at 'hello', $DIR/const_panic.rs:19:15 + | ^^^^^^^^^^^^^^^^ the evaluated program panicked at 'hello', $DIR/const_panic.rs:18:15 | = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0080]: evaluation of constant value failed - --> $DIR/const_panic.rs:22:20 + --> $DIR/const_panic.rs:21:16 + | +LL | const W2: () = std::panic!("{}", MSG); + | ^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'hello', $DIR/const_panic.rs:21:16 + | + = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0080]: evaluation of constant value failed + --> $DIR/const_panic.rs:24:20 | LL | const Z_CORE: () = core::panic!("cheese"); - | ^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'cheese', $DIR/const_panic.rs:22:20 + | ^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'cheese', $DIR/const_panic.rs:24:20 | = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0080]: evaluation of constant value failed - --> $DIR/const_panic.rs:25:21 + --> $DIR/const_panic.rs:27:21 | LL | const Z2_CORE: () = core::panic!(); - | ^^^^^^^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/const_panic.rs:25:21 + | ^^^^^^^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/const_panic.rs:27:21 | = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0080]: evaluation of constant value failed - --> $DIR/const_panic.rs:28:20 + --> $DIR/const_panic.rs:30:20 | LL | const Y_CORE: () = core::unreachable!(); - | ^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'internal error: entered unreachable code', $DIR/const_panic.rs:28:20 + | ^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'internal error: entered unreachable code', $DIR/const_panic.rs:30:20 | = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0080]: evaluation of constant value failed - --> $DIR/const_panic.rs:31:20 + --> $DIR/const_panic.rs:33:20 | LL | const X_CORE: () = core::unimplemented!(); - | ^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'not implemented', $DIR/const_panic.rs:31:20 + | ^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'not implemented', $DIR/const_panic.rs:33:20 | = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0080]: evaluation of constant value failed - --> $DIR/const_panic.rs:34:20 + --> $DIR/const_panic.rs:36:20 | LL | const W_CORE: () = core::panic!(MSG); - | ^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'hello', $DIR/const_panic.rs:34:20 + | ^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'hello', $DIR/const_panic.rs:36:20 | = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 10 previous errors +error[E0080]: evaluation of constant value failed + --> $DIR/const_panic.rs:39:21 + | +LL | const W2_CORE: () = core::panic!("{}", MSG); + | ^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'hello', $DIR/const_panic.rs:39:21 + | + = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 12 previous errors For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/consts/const-eval/const_panic_2021.rs b/src/test/ui/consts/const-eval/const_panic_2021.rs index daef34cd6a..4702aa2f5f 100644 --- a/src/test/ui/consts/const-eval/const_panic_2021.rs +++ b/src/test/ui/consts/const-eval/const_panic_2021.rs @@ -1,7 +1,8 @@ // edition:2021 -#![feature(const_panic)] #![crate_type = "lib"] +const MSG: &str = "hello"; + const A: () = std::panic!("blåhaj"); //~^ ERROR evaluation of constant value failed @@ -14,14 +15,20 @@ const C: () = std::unreachable!(); const D: () = std::unimplemented!(); //~^ ERROR evaluation of constant value failed -const E: () = core::panic!("shark"); +const E: () = std::panic!("{}", MSG); //~^ ERROR evaluation of constant value failed -const F: () = core::panic!(); +const A_CORE: () = core::panic!("shark"); //~^ ERROR evaluation of constant value failed -const G: () = core::unreachable!(); +const B_CORE: () = core::panic!(); //~^ ERROR evaluation of constant value failed -const H: () = core::unimplemented!(); +const C_CORE: () = core::unreachable!(); +//~^ ERROR evaluation of constant value failed + +const D_CORE: () = core::unimplemented!(); +//~^ ERROR evaluation of constant value failed + +const E_CORE: () = core::panic!("{}", MSG); //~^ ERROR evaluation of constant value failed diff --git a/src/test/ui/consts/const-eval/const_panic_2021.stderr b/src/test/ui/consts/const-eval/const_panic_2021.stderr index c1bdab3693..975a07e2b0 100644 --- a/src/test/ui/consts/const-eval/const_panic_2021.stderr +++ b/src/test/ui/consts/const-eval/const_panic_2021.stderr @@ -1,67 +1,83 @@ error[E0080]: evaluation of constant value failed - --> $DIR/const_panic_2021.rs:5:15 + --> $DIR/const_panic_2021.rs:6:15 | LL | const A: () = std::panic!("blåhaj"); - | ^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'blåhaj', $DIR/const_panic_2021.rs:5:15 + | ^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'blåhaj', $DIR/const_panic_2021.rs:6:15 | = note: this error originates in the macro `$crate::panic::panic_2021` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0080]: evaluation of constant value failed - --> $DIR/const_panic_2021.rs:8:15 + --> $DIR/const_panic_2021.rs:9:15 | LL | const B: () = std::panic!(); - | ^^^^^^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/const_panic_2021.rs:8:15 + | ^^^^^^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/const_panic_2021.rs:9:15 | = note: this error originates in the macro `$crate::panic::panic_2021` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0080]: evaluation of constant value failed - --> $DIR/const_panic_2021.rs:11:15 + --> $DIR/const_panic_2021.rs:12:15 | LL | const C: () = std::unreachable!(); - | ^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'internal error: entered unreachable code', $DIR/const_panic_2021.rs:11:15 + | ^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'internal error: entered unreachable code', $DIR/const_panic_2021.rs:12:15 | = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0080]: evaluation of constant value failed - --> $DIR/const_panic_2021.rs:14:15 + --> $DIR/const_panic_2021.rs:15:15 | LL | const D: () = std::unimplemented!(); - | ^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'not implemented', $DIR/const_panic_2021.rs:14:15 + | ^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'not implemented', $DIR/const_panic_2021.rs:15:15 | = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0080]: evaluation of constant value failed - --> $DIR/const_panic_2021.rs:17:15 + --> $DIR/const_panic_2021.rs:18:15 | -LL | const E: () = core::panic!("shark"); - | ^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'shark', $DIR/const_panic_2021.rs:17:15 +LL | const E: () = std::panic!("{}", MSG); + | ^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'hello', $DIR/const_panic_2021.rs:18:15 | = note: this error originates in the macro `$crate::panic::panic_2021` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0080]: evaluation of constant value failed - --> $DIR/const_panic_2021.rs:20:15 + --> $DIR/const_panic_2021.rs:21:20 | -LL | const F: () = core::panic!(); - | ^^^^^^^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/const_panic_2021.rs:20:15 +LL | const A_CORE: () = core::panic!("shark"); + | ^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'shark', $DIR/const_panic_2021.rs:21:20 | = note: this error originates in the macro `$crate::panic::panic_2021` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0080]: evaluation of constant value failed - --> $DIR/const_panic_2021.rs:23:15 + --> $DIR/const_panic_2021.rs:24:20 | -LL | const G: () = core::unreachable!(); - | ^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'internal error: entered unreachable code', $DIR/const_panic_2021.rs:23:15 +LL | const B_CORE: () = core::panic!(); + | ^^^^^^^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/const_panic_2021.rs:24:20 + | + = note: this error originates in the macro `$crate::panic::panic_2021` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0080]: evaluation of constant value failed + --> $DIR/const_panic_2021.rs:27:20 + | +LL | const C_CORE: () = core::unreachable!(); + | ^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'internal error: entered unreachable code', $DIR/const_panic_2021.rs:27:20 | = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0080]: evaluation of constant value failed - --> $DIR/const_panic_2021.rs:26:15 + --> $DIR/const_panic_2021.rs:30:20 | -LL | const H: () = core::unimplemented!(); - | ^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'not implemented', $DIR/const_panic_2021.rs:26:15 +LL | const D_CORE: () = core::unimplemented!(); + | ^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'not implemented', $DIR/const_panic_2021.rs:30:20 | = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 8 previous errors +error[E0080]: evaluation of constant value failed + --> $DIR/const_panic_2021.rs:33:20 + | +LL | const E_CORE: () = core::panic!("{}", MSG); + | ^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'hello', $DIR/const_panic_2021.rs:33:20 + | + = 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 10 previous errors For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/consts/const-eval/const_panic_libcore_bin.rs b/src/test/ui/consts/const-eval/const_panic_libcore_bin.rs index 1ea0845c96..d4dc1a51d7 100644 --- a/src/test/ui/consts/const-eval/const_panic_libcore_bin.rs +++ b/src/test/ui/consts/const-eval/const_panic_libcore_bin.rs @@ -1,6 +1,5 @@ #![crate_type = "bin"] #![feature(lang_items)] -#![feature(const_panic)] #![no_main] #![no_std] diff --git a/src/test/ui/consts/const-eval/const_panic_libcore_bin.stderr b/src/test/ui/consts/const-eval/const_panic_libcore_bin.stderr index 9abf8a20b8..b3fa38241a 100644 --- a/src/test/ui/consts/const-eval/const_panic_libcore_bin.stderr +++ b/src/test/ui/consts/const-eval/const_panic_libcore_bin.stderr @@ -1,24 +1,24 @@ error[E0080]: evaluation of constant value failed - --> $DIR/const_panic_libcore_bin.rs:9:15 + --> $DIR/const_panic_libcore_bin.rs:8:15 | LL | const Z: () = panic!("cheese"); - | ^^^^^^^^^^^^^^^^ the evaluated program panicked at 'cheese', $DIR/const_panic_libcore_bin.rs:9:15 + | ^^^^^^^^^^^^^^^^ the evaluated program panicked at 'cheese', $DIR/const_panic_libcore_bin.rs:8:15 | = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0080]: evaluation of constant value failed - --> $DIR/const_panic_libcore_bin.rs:12:15 + --> $DIR/const_panic_libcore_bin.rs:11:15 | LL | const Y: () = unreachable!(); - | ^^^^^^^^^^^^^^ the evaluated program panicked at 'internal error: entered unreachable code', $DIR/const_panic_libcore_bin.rs:12:15 + | ^^^^^^^^^^^^^^ the evaluated program panicked at 'internal error: entered unreachable code', $DIR/const_panic_libcore_bin.rs:11:15 | = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0080]: evaluation of constant value failed - --> $DIR/const_panic_libcore_bin.rs:15:15 + --> $DIR/const_panic_libcore_bin.rs:14:15 | LL | const X: () = unimplemented!(); - | ^^^^^^^^^^^^^^^^ the evaluated program panicked at 'not implemented', $DIR/const_panic_libcore_bin.rs:15:15 + | ^^^^^^^^^^^^^^^^ the evaluated program panicked at 'not implemented', $DIR/const_panic_libcore_bin.rs:14:15 | = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/consts/const-eval/const_panic_track_caller.rs b/src/test/ui/consts/const-eval/const_panic_track_caller.rs index 7c2532673c..9cf7a3ba7d 100644 --- a/src/test/ui/consts/const-eval/const_panic_track_caller.rs +++ b/src/test/ui/consts/const-eval/const_panic_track_caller.rs @@ -1,4 +1,3 @@ -#![feature(const_panic)] #![allow(non_fmt_panics)] #![crate_type = "lib"] diff --git a/src/test/ui/consts/const-eval/const_panic_track_caller.stderr b/src/test/ui/consts/const-eval/const_panic_track_caller.stderr index 9a458db6ea..5c3b412d37 100644 --- a/src/test/ui/consts/const-eval/const_panic_track_caller.stderr +++ b/src/test/ui/consts/const-eval/const_panic_track_caller.stderr @@ -1,14 +1,14 @@ error[E0080]: evaluation of constant value failed - --> $DIR/const_panic_track_caller.rs:16:5 + --> $DIR/const_panic_track_caller.rs:15:5 | LL | b() | ^^^ | | - | the evaluated program panicked at 'hey', $DIR/const_panic_track_caller.rs:16:5 - | inside `c` at $DIR/const_panic_track_caller.rs:16:5 + | the evaluated program panicked at 'hey', $DIR/const_panic_track_caller.rs:15:5 + | inside `c` at $DIR/const_panic_track_caller.rs:15:5 ... LL | const X: u32 = c(); - | --- inside `X` at $DIR/const_panic_track_caller.rs:22:16 + | --- inside `X` at $DIR/const_panic_track_caller.rs:21:16 error: aborting due to previous error diff --git a/src/test/ui/consts/const-eval/const_raw_ptr_ops.stderr b/src/test/ui/consts/const-eval/const_raw_ptr_ops.stderr index 21d3f5e7e8..1f5bca273d 100644 --- a/src/test/ui/consts/const-eval/const_raw_ptr_ops.stderr +++ b/src/test/ui/consts/const-eval/const_raw_ptr_ops.stderr @@ -1,4 +1,4 @@ -error: pointers cannot be reliably compared during const eval. +error: pointers cannot be reliably compared during const eval --> $DIR/const_raw_ptr_ops.rs:4:26 | LL | const X: bool = unsafe { &1 as *const i32 == &2 as *const i32 }; @@ -6,7 +6,7 @@ LL | const X: bool = unsafe { &1 as *const i32 == &2 as *const i32 }; | = note: see issue #53020 for more information -error: pointers cannot be reliably compared during const eval. +error: pointers cannot be reliably compared during const eval --> $DIR/const_raw_ptr_ops.rs:6:27 | LL | const X2: bool = unsafe { 42 as *const i32 == 43 as *const i32 }; diff --git a/src/test/ui/consts/const-eval/feature-gate-const_panic.rs b/src/test/ui/consts/const-eval/feature-gate-const_panic.rs deleted file mode 100644 index ba5b07239a..0000000000 --- a/src/test/ui/consts/const-eval/feature-gate-const_panic.rs +++ /dev/null @@ -1,10 +0,0 @@ -fn main() {} - -const Z: () = panic!("cheese"); -//~^ ERROR panicking in constants is unstable - -const Y: () = unreachable!(); -//~^ ERROR panicking in constants is unstable - -const X: () = unimplemented!(); -//~^ ERROR panicking in constants is unstable diff --git a/src/test/ui/consts/const-eval/feature-gate-const_panic.stderr b/src/test/ui/consts/const-eval/feature-gate-const_panic.stderr deleted file mode 100644 index 8d8e94cd4f..0000000000 --- a/src/test/ui/consts/const-eval/feature-gate-const_panic.stderr +++ /dev/null @@ -1,33 +0,0 @@ -error[E0658]: panicking in constants is unstable - --> $DIR/feature-gate-const_panic.rs:3:15 - | -LL | const Z: () = panic!("cheese"); - | ^^^^^^^^^^^^^^^^ - | - = note: see issue #51999 for more information - = help: add `#![feature(const_panic)]` to the crate attributes to enable - = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info) - -error[E0658]: panicking in constants is unstable - --> $DIR/feature-gate-const_panic.rs:6:15 - | -LL | const Y: () = unreachable!(); - | ^^^^^^^^^^^^^^ - | - = note: see issue #51999 for more information - = help: add `#![feature(const_panic)]` to the crate attributes to enable - = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info) - -error[E0658]: panicking in constants is unstable - --> $DIR/feature-gate-const_panic.rs:9:15 - | -LL | const X: () = unimplemented!(); - | ^^^^^^^^^^^^^^^^ - | - = note: see issue #51999 for more information - = help: add `#![feature(const_panic)]` to the crate attributes to enable - = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: aborting due to 3 previous errors - -For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/consts/const-eval/match-test-ptr-null.stderr b/src/test/ui/consts/const-eval/match-test-ptr-null.stderr index 4e55b36da7..05c3951c12 100644 --- a/src/test/ui/consts/const-eval/match-test-ptr-null.stderr +++ b/src/test/ui/consts/const-eval/match-test-ptr-null.stderr @@ -1,4 +1,4 @@ -error: pointers cannot be cast to integers during const eval. +error: pointers cannot be cast to integers during const eval --> $DIR/match-test-ptr-null.rs:6:15 | LL | match &1 as *const i32 as usize { diff --git a/src/test/ui/consts/const-eval/panic-assoc-never-type.rs b/src/test/ui/consts/const-eval/panic-assoc-never-type.rs index ab0256a986..2bdf5d5476 100644 --- a/src/test/ui/consts/const-eval/panic-assoc-never-type.rs +++ b/src/test/ui/consts/const-eval/panic-assoc-never-type.rs @@ -2,7 +2,6 @@ // Regression test for #66975 #![warn(const_err)] -#![feature(const_panic)] #![feature(never_type)] struct PrintName; diff --git a/src/test/ui/consts/const-eval/panic-assoc-never-type.stderr b/src/test/ui/consts/const-eval/panic-assoc-never-type.stderr index f1c606a8a2..9631b7748b 100644 --- a/src/test/ui/consts/const-eval/panic-assoc-never-type.stderr +++ b/src/test/ui/consts/const-eval/panic-assoc-never-type.stderr @@ -1,8 +1,8 @@ error[E0080]: evaluation of constant value failed - --> $DIR/panic-assoc-never-type.rs:11:21 + --> $DIR/panic-assoc-never-type.rs:10:21 | LL | const VOID: ! = panic!(); - | ^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/panic-assoc-never-type.rs:11:21 + | ^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/panic-assoc-never-type.rs:10:21 | = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/consts/const-eval/panic-never-type.rs b/src/test/ui/consts/const-eval/panic-never-type.rs index dd875768b1..a74d3ba297 100644 --- a/src/test/ui/consts/const-eval/panic-never-type.rs +++ b/src/test/ui/consts/const-eval/panic-never-type.rs @@ -1,6 +1,5 @@ // Regression test for #66975 #![warn(const_err)] -#![feature(const_panic)] #![feature(never_type)] const VOID: ! = panic!(); diff --git a/src/test/ui/consts/const-eval/panic-never-type.stderr b/src/test/ui/consts/const-eval/panic-never-type.stderr index 9b7f2181c1..8f312d673a 100644 --- a/src/test/ui/consts/const-eval/panic-never-type.stderr +++ b/src/test/ui/consts/const-eval/panic-never-type.stderr @@ -1,8 +1,8 @@ error[E0080]: evaluation of constant value failed - --> $DIR/panic-never-type.rs:6:17 + --> $DIR/panic-never-type.rs:5:17 | LL | const VOID: ! = panic!(); - | ^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/panic-never-type.rs:6:17 + | ^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/panic-never-type.rs:5:17 | = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/consts/const-eval/unwind-abort.rs b/src/test/ui/consts/const-eval/unwind-abort.rs index 89b5135fd3..2b0e58166c 100644 --- a/src/test/ui/consts/const-eval/unwind-abort.rs +++ b/src/test/ui/consts/const-eval/unwind-abort.rs @@ -1,4 +1,4 @@ -#![feature(c_unwind, const_panic, const_extern_fn)] +#![feature(c_unwind, const_extern_fn)] const extern "C" fn foo() { panic!() //~ ERROR evaluation of constant value failed diff --git a/src/test/ui/consts/const-extern-fn/const-extern-fn-min-const-fn.stderr b/src/test/ui/consts/const-extern-fn/const-extern-fn-min-const-fn.stderr index 2e52bae2b6..2b2d23477f 100644 --- a/src/test/ui/consts/const-extern-fn/const-extern-fn-min-const-fn.stderr +++ b/src/test/ui/consts/const-extern-fn/const-extern-fn-min-const-fn.stderr @@ -25,7 +25,7 @@ LL | const unsafe extern "C" fn use_float() { 1.0 + 1.0; } = note: see issue #57241 for more information = help: add `#![feature(const_fn_floating_point_arithmetic)]` to the crate attributes to enable -error: pointers cannot be cast to integers during const eval. +error: pointers cannot be cast to integers during const eval --> $DIR/const-extern-fn-min-const-fn.rs:9:48 | LL | const extern "C" fn ptr_cast(val: *const u8) { val as usize; } diff --git a/src/test/ui/consts/const-external-macro-const-err.stderr b/src/test/ui/consts/const-external-macro-const-err.stderr index 108d976ec6..a66d79a161 100644 --- a/src/test/ui/consts/const-external-macro-const-err.stderr +++ b/src/test/ui/consts/const-external-macro-const-err.stderr @@ -2,7 +2,7 @@ error: any use of this value will cause an error --> $DIR/const-external-macro-const-err.rs:12:5 | LL | static_assert!(2 + 2 == 5); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ index out of bounds: the length is 1 but the index is 1 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ index out of bounds: the length is 1 but the index is 1 | = note: `#[deny(const_err)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! diff --git a/src/test/ui/consts/const-float-bits-conv.rs b/src/test/ui/consts/const-float-bits-conv.rs index 2dfc6de859..c857ad6df2 100644 --- a/src/test/ui/consts/const-float-bits-conv.rs +++ b/src/test/ui/consts/const-float-bits-conv.rs @@ -1,7 +1,6 @@ // compile-flags: -Zmir-opt-level=0 // run-pass -#![feature(const_panic)] #![feature(const_float_bits_conv)] #![feature(const_float_classify)] diff --git a/src/test/ui/consts/const-float-classify.rs b/src/test/ui/consts/const-float-classify.rs index 5d38e032ac..74238d0dd9 100644 --- a/src/test/ui/consts/const-float-classify.rs +++ b/src/test/ui/consts/const-float-classify.rs @@ -1,7 +1,6 @@ // compile-flags: -Zmir-opt-level=0 // run-pass -#![feature(const_panic)] #![feature(const_float_bits_conv)] #![feature(const_float_classify)] #![feature(const_trait_impl)] diff --git a/src/test/ui/consts/const-variant-count.rs b/src/test/ui/consts/const-variant-count.rs index 455419d2c7..50eaeeb468 100644 --- a/src/test/ui/consts/const-variant-count.rs +++ b/src/test/ui/consts/const-variant-count.rs @@ -1,5 +1,5 @@ // run-pass -#![allow(dead_code)] +#![allow(dead_code, enum_intrinsics_non_enums)] #![feature(variant_count)] #![feature(never_type)] diff --git a/src/test/ui/consts/const_fn_trait_bound.rs b/src/test/ui/consts/const_fn_trait_bound.rs index b1ef820d82..19c08b6214 100644 --- a/src/test/ui/consts/const_fn_trait_bound.rs +++ b/src/test/ui/consts/const_fn_trait_bound.rs @@ -8,9 +8,9 @@ const fn test1() {} //[stock]~^ trait bounds const fn test2(_x: &dyn Send) {} -//[stock]~^ trait bounds +//[stock]~^ trait objects in const fn are unstable const fn test3() -> &'static dyn Send { loop {} } -//[stock]~^ trait bounds +//[stock]~^ trait objects in const fn are unstable #[rustc_error] diff --git a/src/test/ui/consts/const_fn_trait_bound.stock.stderr b/src/test/ui/consts/const_fn_trait_bound.stock.stderr index 2ad45f3afd..d652b5268a 100644 --- a/src/test/ui/consts/const_fn_trait_bound.stock.stderr +++ b/src/test/ui/consts/const_fn_trait_bound.stock.stderr @@ -7,7 +7,7 @@ LL | const fn test1() {} = note: see issue #57563 for more information = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable -error[E0658]: trait bounds other than `Sized` on const fn parameters are unstable +error[E0658]: trait objects in const fn are unstable --> $DIR/const_fn_trait_bound.rs:10:16 | LL | const fn test2(_x: &dyn Send) {} @@ -16,7 +16,7 @@ LL | const fn test2(_x: &dyn Send) {} = note: see issue #57563 for more information = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable -error[E0658]: trait bounds other than `Sized` on const fn parameters are unstable +error[E0658]: trait objects in const fn are unstable --> $DIR/const_fn_trait_bound.rs:12:21 | LL | const fn test3() -> &'static dyn Send { loop {} } diff --git a/src/test/ui/consts/const_in_pattern/issue-73431.stderr b/src/test/ui/consts/const_in_pattern/issue-73431.stderr new file mode 100644 index 0000000000..c82dea4aa5 --- /dev/null +++ b/src/test/ui/consts/const_in_pattern/issue-73431.stderr @@ -0,0 +1 @@ +WARN rustc_mir_build::thir::pattern::const_to_pat MIR const-checker found novel structural match violation. See #73448. diff --git a/src/test/ui/consts/const_in_pattern/issue-78057.stderr b/src/test/ui/consts/const_in_pattern/issue-78057.stderr index 0d49d0e96c..35619594f7 100644 --- a/src/test/ui/consts/const_in_pattern/issue-78057.stderr +++ b/src/test/ui/consts/const_in_pattern/issue-78057.stderr @@ -7,8 +7,11 @@ LL | FOO => {}, error: unreachable pattern --> $DIR/issue-78057.rs:14:9 | +LL | FOO => {}, + | --- matches any value +LL | LL | _ => {} - | ^ + | ^ unreachable pattern | note: the lint level is defined here --> $DIR/issue-78057.rs:1:9 diff --git a/src/test/ui/consts/const_let_assign3.stderr b/src/test/ui/consts/const_let_assign3.stderr index 89073f975e..b550ac5457 100644 --- a/src/test/ui/consts/const_let_assign3.stderr +++ b/src/test/ui/consts/const_let_assign3.stderr @@ -11,7 +11,7 @@ error[E0658]: mutable references are not allowed in constants --> $DIR/const_let_assign3.rs:14:5 | LL | s.foo(3); - | ^ + | ^^^^^^^^ | = note: see issue #57349 for more information = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable diff --git a/src/test/ui/consts/const_unsafe_unreachable.rs b/src/test/ui/consts/const_unsafe_unreachable.rs index 1fec491ca9..1c3baec5d8 100644 --- a/src/test/ui/consts/const_unsafe_unreachable.rs +++ b/src/test/ui/consts/const_unsafe_unreachable.rs @@ -1,7 +1,5 @@ // run-pass -#![feature(const_unreachable_unchecked)] - const unsafe fn foo(x: bool) -> bool { match x { true => true, @@ -12,5 +10,5 @@ const unsafe fn foo(x: bool) -> bool { const BAR: bool = unsafe { foo(true) }; fn main() { - assert_eq!(BAR, true); + assert_eq!(BAR, true); } diff --git a/src/test/ui/consts/const_unsafe_unreachable_ub.rs b/src/test/ui/consts/const_unsafe_unreachable_ub.rs index 8cee5b5065..b418fea617 100644 --- a/src/test/ui/consts/const_unsafe_unreachable_ub.rs +++ b/src/test/ui/consts/const_unsafe_unreachable_ub.rs @@ -1,5 +1,4 @@ // error-pattern: evaluation of constant value failed -#![feature(const_unreachable_unchecked)] const unsafe fn foo(x: bool) -> bool { match x { @@ -11,5 +10,5 @@ const unsafe fn foo(x: bool) -> bool { const BAR: bool = unsafe { foo(false) }; fn main() { - assert_eq!(BAR, true); + assert_eq!(BAR, true); } diff --git a/src/test/ui/consts/const_unsafe_unreachable_ub.stderr b/src/test/ui/consts/const_unsafe_unreachable_ub.stderr index 65cb3d74b2..ec6ce1f5d7 100644 --- a/src/test/ui/consts/const_unsafe_unreachable_ub.stderr +++ b/src/test/ui/consts/const_unsafe_unreachable_ub.stderr @@ -7,13 +7,13 @@ LL | unsafe { intrinsics::unreachable() } | entering unreachable code | inside `unreachable_unchecked` at $SRC_DIR/core/src/hint.rs:LL:COL | - ::: $DIR/const_unsafe_unreachable_ub.rs:7:18 + ::: $DIR/const_unsafe_unreachable_ub.rs:6:18 | LL | false => std::hint::unreachable_unchecked(), - | ---------------------------------- inside `foo` at $DIR/const_unsafe_unreachable_ub.rs:7:18 + | ---------------------------------- inside `foo` at $DIR/const_unsafe_unreachable_ub.rs:6:18 ... LL | const BAR: bool = unsafe { foo(false) }; - | ---------- inside `BAR` at $DIR/const_unsafe_unreachable_ub.rs:11:28 + | ---------- inside `BAR` at $DIR/const_unsafe_unreachable_ub.rs:10:28 error: aborting due to previous error diff --git a/src/test/ui/consts/control-flow/assert.rs b/src/test/ui/consts/control-flow/assert.rs index b311cb140c..9d17f65b93 100644 --- a/src/test/ui/consts/control-flow/assert.rs +++ b/src/test/ui/consts/control-flow/assert.rs @@ -1,14 +1,8 @@ -// Test that `assert` works when `const_panic` is enabled. - -// revisions: stock const_panic - -#![cfg_attr(const_panic, feature(const_panic))] +// Test that `assert` works in consts. const _: () = assert!(true); -//[stock]~^ ERROR panicking in constants is unstable const _: () = assert!(false); -//[stock]~^ ERROR panicking in constants is unstable -//[const_panic]~^^ ERROR evaluation of constant value failed +//~^ ERROR evaluation of constant value failed fn main() {} diff --git a/src/test/ui/consts/control-flow/assert.const_panic.stderr b/src/test/ui/consts/control-flow/assert.stderr similarity index 82% rename from src/test/ui/consts/control-flow/assert.const_panic.stderr rename to src/test/ui/consts/control-flow/assert.stderr index 1deaa937ed..8b1ca183de 100644 --- a/src/test/ui/consts/control-flow/assert.const_panic.stderr +++ b/src/test/ui/consts/control-flow/assert.stderr @@ -1,8 +1,8 @@ error[E0080]: evaluation of constant value failed - --> $DIR/assert.rs:10:15 + --> $DIR/assert.rs:5:15 | LL | const _: () = assert!(false); - | ^^^^^^^^^^^^^^ the evaluated program panicked at 'assertion failed: false', $DIR/assert.rs:10:15 + | ^^^^^^^^^^^^^^ the evaluated program panicked at 'assertion failed: false', $DIR/assert.rs:5:15 | = note: this error originates in the macro `assert` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/consts/control-flow/assert.stock.stderr b/src/test/ui/consts/control-flow/assert.stock.stderr deleted file mode 100644 index 0caaeca4ad..0000000000 --- a/src/test/ui/consts/control-flow/assert.stock.stderr +++ /dev/null @@ -1,23 +0,0 @@ -error[E0658]: panicking in constants is unstable - --> $DIR/assert.rs:7:15 - | -LL | const _: () = assert!(true); - | ^^^^^^^^^^^^^ - | - = note: see issue #51999 for more information - = help: add `#![feature(const_panic)]` to the crate attributes to enable - = note: this error originates in the macro `assert` (in Nightly builds, run with -Z macro-backtrace for more info) - -error[E0658]: panicking in constants is unstable - --> $DIR/assert.rs:10:15 - | -LL | const _: () = assert!(false); - | ^^^^^^^^^^^^^^ - | - = note: see issue #51999 for more information - = help: add `#![feature(const_panic)]` to the crate attributes to enable - = note: this error originates in the macro `assert` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/consts/control-flow/basics.rs b/src/test/ui/consts/control-flow/basics.rs index 3a4f24bbcc..02e5501f10 100644 --- a/src/test/ui/consts/control-flow/basics.rs +++ b/src/test/ui/consts/control-flow/basics.rs @@ -2,8 +2,6 @@ // run-pass -#![feature(const_panic)] - const X: u32 = 4; const Y: u32 = 5; diff --git a/src/test/ui/consts/control-flow/short-circuit-let.rs b/src/test/ui/consts/control-flow/short-circuit-let.rs index 4dfa22b8eb..8a58d06ac8 100644 --- a/src/test/ui/consts/control-flow/short-circuit-let.rs +++ b/src/test/ui/consts/control-flow/short-circuit-let.rs @@ -2,8 +2,6 @@ // run-pass -#![feature(const_panic)] - const X: i32 = { let mut x = 0; let _ = true && { x = 1; false }; diff --git a/src/test/ui/consts/control-flow/short-circuit.rs b/src/test/ui/consts/control-flow/short-circuit.rs index f6a0f03a4a..6abe107855 100644 --- a/src/test/ui/consts/control-flow/short-circuit.rs +++ b/src/test/ui/consts/control-flow/short-circuit.rs @@ -3,8 +3,6 @@ // Test that both `&&` and `||` actually short-circuit. // Formerly, both sides were evaluated unconditionally -#![feature(const_panic)] - const TRUE: bool = true || panic!(); const FALSE: bool = false && panic!(); diff --git a/src/test/ui/consts/issue-17458.stderr b/src/test/ui/consts/issue-17458.stderr index aab7d798db..8936c8d84e 100644 --- a/src/test/ui/consts/issue-17458.stderr +++ b/src/test/ui/consts/issue-17458.stderr @@ -1,4 +1,4 @@ -error: pointers cannot be cast to integers during const eval. +error: pointers cannot be cast to integers during const eval --> $DIR/issue-17458.rs:1:28 | LL | static X: usize = unsafe { core::ptr::null::() as usize }; diff --git a/src/test/ui/issues/issue-23833.rs b/src/test/ui/consts/issue-23833.rs similarity index 100% rename from src/test/ui/issues/issue-23833.rs rename to src/test/ui/consts/issue-23833.rs diff --git a/src/test/ui/consts/issue-25826.stderr b/src/test/ui/consts/issue-25826.stderr index 67d1b3ab9b..780edd2149 100644 --- a/src/test/ui/consts/issue-25826.stderr +++ b/src/test/ui/consts/issue-25826.stderr @@ -1,4 +1,4 @@ -error: pointers cannot be reliably compared during const eval. +error: pointers cannot be reliably compared during const eval --> $DIR/issue-25826.rs:3:30 | LL | const A: bool = unsafe { id:: as *const () < id:: as *const () }; diff --git a/src/test/ui/consts/issue-32829.rs b/src/test/ui/consts/issue-32829.rs index adfee7b925..25f323b980 100644 --- a/src/test/ui/consts/issue-32829.rs +++ b/src/test/ui/consts/issue-32829.rs @@ -1,5 +1,5 @@ static S : u64 = { { panic!("foo"); 0 } }; -//~^ ERROR panicking in statics is unstable +//~^ ERROR could not evaluate static initializer fn main() { println!("{:?}", S); diff --git a/src/test/ui/consts/issue-32829.stderr b/src/test/ui/consts/issue-32829.stderr index eba15e3fcc..6155c935a5 100644 --- a/src/test/ui/consts/issue-32829.stderr +++ b/src/test/ui/consts/issue-32829.stderr @@ -1,13 +1,11 @@ -error[E0658]: panicking in statics is unstable +error[E0080]: could not evaluate static initializer --> $DIR/issue-32829.rs:1:22 | LL | static S : u64 = { { panic!("foo"); 0 } }; - | ^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ the evaluated program panicked at 'foo', $DIR/issue-32829.rs:1:22 | - = note: see issue #51999 for more information - = help: add `#![feature(const_panic)]` to the crate attributes to enable = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to previous error -For more information about this error, try `rustc --explain E0658`. +For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/issues/issue-34784.rs b/src/test/ui/consts/issue-34784.rs similarity index 100% rename from src/test/ui/issues/issue-34784.rs rename to src/test/ui/consts/issue-34784.rs diff --git a/src/test/ui/consts/issue-52023-array-size-pointer-cast.stderr b/src/test/ui/consts/issue-52023-array-size-pointer-cast.stderr index 363c7b2c8e..9a3d5716e0 100644 --- a/src/test/ui/consts/issue-52023-array-size-pointer-cast.stderr +++ b/src/test/ui/consts/issue-52023-array-size-pointer-cast.stderr @@ -1,4 +1,4 @@ -error: pointers cannot be cast to integers during const eval. +error: pointers cannot be cast to integers during const eval --> $DIR/issue-52023-array-size-pointer-cast.rs:2:17 | LL | let _ = [0; (&0 as *const i32) as usize]; diff --git a/src/test/ui/consts/issue-66693-panic-in-array-len.rs b/src/test/ui/consts/issue-66693-panic-in-array-len.rs index 718a19067a..fc0dcd7a44 100644 --- a/src/test/ui/consts/issue-66693-panic-in-array-len.rs +++ b/src/test/ui/consts/issue-66693-panic-in-array-len.rs @@ -2,8 +2,6 @@ // in a separate stage before `const`s and `statics` and so the error below is hit and // the compiler exits before generating errors for the others. -#![feature(const_panic)] - fn main() { let _ = [0i32; panic!(2f32)]; //~^ ERROR: argument to `panic!()` in a const context must have type `&str` diff --git a/src/test/ui/consts/issue-66693-panic-in-array-len.stderr b/src/test/ui/consts/issue-66693-panic-in-array-len.stderr index 2dd445b434..4ccbeb73c8 100644 --- a/src/test/ui/consts/issue-66693-panic-in-array-len.stderr +++ b/src/test/ui/consts/issue-66693-panic-in-array-len.stderr @@ -1,5 +1,5 @@ error: argument to `panic!()` in a const context must have type `&str` - --> $DIR/issue-66693-panic-in-array-len.rs:8:20 + --> $DIR/issue-66693-panic-in-array-len.rs:6:20 | LL | let _ = [0i32; panic!(2f32)]; | ^^^^^^^^^^^^ @@ -7,10 +7,10 @@ LL | let _ = [0i32; panic!(2f32)]; = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0080]: evaluation of constant value failed - --> $DIR/issue-66693-panic-in-array-len.rs:12:21 + --> $DIR/issue-66693-panic-in-array-len.rs:10:21 | LL | let _ = [false; panic!()]; - | ^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/issue-66693-panic-in-array-len.rs:12:21 + | ^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/issue-66693-panic-in-array-len.rs:10:21 | = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/consts/issue-66693.rs b/src/test/ui/consts/issue-66693.rs index 77fe4417d5..909bef7aef 100644 --- a/src/test/ui/consts/issue-66693.rs +++ b/src/test/ui/consts/issue-66693.rs @@ -1,8 +1,6 @@ // Tests that the compiler does not ICE when const-evaluating a `panic!()` invocation with a // non-`&str` argument. -#![feature(const_panic)] - const _: () = panic!(1); //~^ ERROR: argument to `panic!()` in a const context must have type `&str` diff --git a/src/test/ui/consts/issue-66693.stderr b/src/test/ui/consts/issue-66693.stderr index 3349e9813a..3530324bda 100644 --- a/src/test/ui/consts/issue-66693.stderr +++ b/src/test/ui/consts/issue-66693.stderr @@ -1,5 +1,5 @@ error: argument to `panic!()` in a const context must have type `&str` - --> $DIR/issue-66693.rs:6:15 + --> $DIR/issue-66693.rs:4:15 | LL | const _: () = panic!(1); | ^^^^^^^^^ @@ -7,7 +7,7 @@ LL | const _: () = panic!(1); = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info) error: argument to `panic!()` in a const context must have type `&str` - --> $DIR/issue-66693.rs:9:19 + --> $DIR/issue-66693.rs:7:19 | LL | static _FOO: () = panic!(true); | ^^^^^^^^^^^^ @@ -15,10 +15,10 @@ LL | static _FOO: () = panic!(true); = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info) error: argument to `panic!()` in a const context must have type `&str` - --> $DIR/issue-66693.rs:13:5 + --> $DIR/issue-66693.rs:11:5 | LL | panic!(&1); - | ^^^^^^^^^^^ + | ^^^^^^^^^^ | = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/consts/issue-76064.rs b/src/test/ui/consts/issue-76064.rs index d511f75df8..3c153ad726 100644 --- a/src/test/ui/consts/issue-76064.rs +++ b/src/test/ui/consts/issue-76064.rs @@ -1,5 +1,3 @@ -// Note: non-`&str` panic arguments gained a separate error in PR #80734 -// which is why this doesn't match the issue -struct Bug([u8; panic!("panic")]); //~ ERROR panicking in constants is unstable +struct Bug([u8; panic!("panic")]); //~ ERROR evaluation of constant value failed fn main() {} diff --git a/src/test/ui/consts/issue-76064.stderr b/src/test/ui/consts/issue-76064.stderr index 875bc5c5cd..ef9d140536 100644 --- a/src/test/ui/consts/issue-76064.stderr +++ b/src/test/ui/consts/issue-76064.stderr @@ -1,13 +1,11 @@ -error[E0658]: panicking in constants is unstable - --> $DIR/issue-76064.rs:3:17 +error[E0080]: evaluation of constant value failed + --> $DIR/issue-76064.rs:1:17 | LL | struct Bug([u8; panic!("panic")]); - | ^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^ the evaluated program panicked at 'panic', $DIR/issue-76064.rs:1:17 | - = note: see issue #51999 for more information - = help: add `#![feature(const_panic)]` to the crate attributes to enable = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to previous error -For more information about this error, try `rustc --explain E0658`. +For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/consts/issue-88071.rs b/src/test/ui/consts/issue-88071.rs new file mode 100644 index 0000000000..a2d4a64212 --- /dev/null +++ b/src/test/ui/consts/issue-88071.rs @@ -0,0 +1,21 @@ +// check-pass +// +// regression test for #88071 + +#![feature(const_btree_new)] +#![feature(const_fn_trait_bound)] + +use std::collections::BTreeMap; + +pub struct CustomMap(BTreeMap); + +impl CustomMap +where + K: Ord, +{ + pub const fn new() -> Self { + CustomMap(BTreeMap::new()) + } +} + +fn main() {} diff --git a/src/test/ui/consts/issue-89088.rs b/src/test/ui/consts/issue-89088.rs new file mode 100644 index 0000000000..40cc665fb6 --- /dev/null +++ b/src/test/ui/consts/issue-89088.rs @@ -0,0 +1,22 @@ +// Regression test for the ICE described in #89088. + +// check-pass + +#![allow(indirect_structural_match)] +use std::borrow::Cow; + +const FOO: &A = &A::Field(Cow::Borrowed("foo")); + +#[derive(PartialEq, Eq)] +enum A { + Field(Cow<'static, str>) +} + +fn main() { + let var = A::Field(Cow::Borrowed("bar")); + + match &var { + FOO => todo!(), + _ => todo!() + } +} diff --git a/src/test/ui/consts/min_const_fn/cmp_fn_pointers.stderr b/src/test/ui/consts/min_const_fn/cmp_fn_pointers.stderr index 04c2febeb9..5d8483cd11 100644 --- a/src/test/ui/consts/min_const_fn/cmp_fn_pointers.stderr +++ b/src/test/ui/consts/min_const_fn/cmp_fn_pointers.stderr @@ -16,7 +16,7 @@ LL | const fn cmp(x: fn(), y: fn()) -> bool { = note: see issue #57563 for more information = help: add `#![feature(const_fn_fn_ptr_basics)]` to the crate attributes to enable -error: pointers cannot be reliably compared during const eval. +error: pointers cannot be reliably compared during const eval --> $DIR/cmp_fn_pointers.rs:4:14 | LL | unsafe { x == y } diff --git a/src/test/ui/consts/min_const_fn/min_const_fn.rs b/src/test/ui/consts/min_const_fn/min_const_fn.rs index bb525d5719..10347a0207 100644 --- a/src/test/ui/consts/min_const_fn/min_const_fn.rs +++ b/src/test/ui/consts/min_const_fn/min_const_fn.rs @@ -130,16 +130,16 @@ const fn no_apit(_x: impl std::fmt::Debug) {} //~^ ERROR trait bounds other than `Sized` //~| ERROR destructor const fn no_dyn_trait(_x: &dyn std::fmt::Debug) {} -//~^ ERROR trait bounds other than `Sized` +//~^ ERROR trait objects in const fn are unstable const fn no_dyn_trait_ret() -> &'static dyn std::fmt::Debug { &() } -//~^ ERROR trait bounds other than `Sized` +//~^ ERROR trait objects in const fn are unstable const fn no_unsafe() { unsafe {} } const fn really_no_traits_i_mean_it() { (&() as &dyn std::fmt::Debug, ()).1 } -//~^ ERROR trait bounds other than `Sized` -//~| ERROR trait bounds other than `Sized` -//~| ERROR trait bounds other than `Sized` +//~^ ERROR trait objects in const fn are unstable +//~| ERROR trait objects in const fn are unstable +//~| ERROR trait objects in const fn are unstable const fn no_fn_ptrs(_x: fn()) {} //~^ ERROR function pointer diff --git a/src/test/ui/consts/min_const_fn/min_const_fn.stderr b/src/test/ui/consts/min_const_fn/min_const_fn.stderr index fcbf39d386..fd1ab6f64b 100644 --- a/src/test/ui/consts/min_const_fn/min_const_fn.stderr +++ b/src/test/ui/consts/min_const_fn/min_const_fn.stderr @@ -164,7 +164,7 @@ LL | const fn foo26() -> &'static u32 { &BAR } | = help: consider extracting the value of the `static` to a `const`, and referring to that -error: pointers cannot be cast to integers during const eval. +error: pointers cannot be cast to integers during const eval --> $DIR/min_const_fn.rs:92:42 | LL | const fn foo30(x: *const u32) -> usize { x as usize } @@ -173,7 +173,7 @@ LL | const fn foo30(x: *const u32) -> usize { x as usize } = note: at compile-time, pointers do not have an integer value = note: avoiding this restriction via `transmute`, `union`, or raw pointers leads to compile-time undefined behavior -error: pointers cannot be cast to integers during const eval. +error: pointers cannot be cast to integers during const eval --> $DIR/min_const_fn.rs:94:63 | LL | const fn foo30_with_unsafe(x: *const u32) -> usize { unsafe { x as usize } } @@ -182,7 +182,7 @@ LL | const fn foo30_with_unsafe(x: *const u32) -> usize { unsafe { x as usize } = note: at compile-time, pointers do not have an integer value = note: avoiding this restriction via `transmute`, `union`, or raw pointers leads to compile-time undefined behavior -error: pointers cannot be cast to integers during const eval. +error: pointers cannot be cast to integers during const eval --> $DIR/min_const_fn.rs:96:42 | LL | const fn foo30_2(x: *mut u32) -> usize { x as usize } @@ -191,7 +191,7 @@ LL | const fn foo30_2(x: *mut u32) -> usize { x as usize } = note: at compile-time, pointers do not have an integer value = note: avoiding this restriction via `transmute`, `union`, or raw pointers leads to compile-time undefined behavior -error: pointers cannot be cast to integers during const eval. +error: pointers cannot be cast to integers during const eval --> $DIR/min_const_fn.rs:98:63 | LL | const fn foo30_2_with_unsafe(x: *mut u32) -> usize { unsafe { x as usize } } @@ -214,6 +214,9 @@ error[E0658]: trait bounds other than `Sized` on const fn parameters are unstabl | LL | impl Foo { | ^ +LL | +LL | const fn foo(&self) {} + | ------------------- function declared as const here | = note: see issue #57563 for more information = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable @@ -223,6 +226,9 @@ error[E0658]: trait bounds other than `Sized` on const fn parameters are unstabl | LL | impl Foo { | ^ +LL | +LL | const fn foo2(&self) {} + | -------------------- function declared as const here | = note: see issue #57563 for more information = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable @@ -232,6 +238,9 @@ error[E0658]: trait bounds other than `Sized` on const fn parameters are unstabl | LL | impl Foo { | ^ +LL | +LL | const fn foo3(&self) {} + | -------------------- function declared as const here | = note: see issue #57563 for more information = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable @@ -270,7 +279,7 @@ LL | const fn no_apit(_x: impl std::fmt::Debug) {} | | | constant functions cannot evaluate destructors -error[E0658]: trait bounds other than `Sized` on const fn parameters are unstable +error[E0658]: trait objects in const fn are unstable --> $DIR/min_const_fn.rs:132:23 | LL | const fn no_dyn_trait(_x: &dyn std::fmt::Debug) {} @@ -279,7 +288,7 @@ LL | const fn no_dyn_trait(_x: &dyn std::fmt::Debug) {} = note: see issue #57563 for more information = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable -error[E0658]: trait bounds other than `Sized` on const fn parameters are unstable +error[E0658]: trait objects in const fn are unstable --> $DIR/min_const_fn.rs:134:32 | LL | const fn no_dyn_trait_ret() -> &'static dyn std::fmt::Debug { &() } @@ -288,29 +297,35 @@ LL | const fn no_dyn_trait_ret() -> &'static dyn std::fmt::Debug { &() } = note: see issue #57563 for more information = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable -error[E0658]: trait bounds other than `Sized` on const fn parameters are unstable +error[E0658]: trait objects in const fn are unstable --> $DIR/min_const_fn.rs:139:41 | LL | const fn really_no_traits_i_mean_it() { (&() as &dyn std::fmt::Debug, ()).1 } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ------------------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | function declared as const here | = note: see issue #57563 for more information = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable -error[E0658]: trait bounds other than `Sized` on const fn parameters are unstable +error[E0658]: trait objects in const fn are unstable --> $DIR/min_const_fn.rs:139:42 | LL | const fn really_no_traits_i_mean_it() { (&() as &dyn std::fmt::Debug, ()).1 } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ------------------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | function declared as const here | = note: see issue #57563 for more information = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable -error[E0658]: trait bounds other than `Sized` on const fn parameters are unstable +error[E0658]: trait objects in const fn are unstable --> $DIR/min_const_fn.rs:139:42 | LL | const fn really_no_traits_i_mean_it() { (&() as &dyn std::fmt::Debug, ()).1 } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ------------------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | function declared as const here | = note: see issue #57563 for more information = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_dyn.rs b/src/test/ui/consts/min_const_fn/min_const_fn_dyn.rs index 6ca1e59b3a..1ab8253b41 100644 --- a/src/test/ui/consts/min_const_fn/min_const_fn_dyn.rs +++ b/src/test/ui/consts/min_const_fn/min_const_fn_dyn.rs @@ -7,9 +7,9 @@ struct Hide(HasDyn); const fn no_inner_dyn_trait(_x: Hide) {} const fn no_inner_dyn_trait2(x: Hide) { x.0.field; -//~^ ERROR trait bounds other than `Sized` +//~^ ERROR trait objects in const fn are unstable } const fn no_inner_dyn_trait_ret() -> Hide { Hide(HasDyn { field: &0 }) } -//~^ ERROR trait bounds other than `Sized` +//~^ ERROR trait objects in const fn are unstable fn main() {} diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_dyn.stderr b/src/test/ui/consts/min_const_fn/min_const_fn_dyn.stderr index ce844a2f07..6eec1df5ae 100644 --- a/src/test/ui/consts/min_const_fn/min_const_fn_dyn.stderr +++ b/src/test/ui/consts/min_const_fn/min_const_fn_dyn.stderr @@ -1,17 +1,21 @@ -error[E0658]: trait bounds other than `Sized` on const fn parameters are unstable +error[E0658]: trait objects in const fn are unstable --> $DIR/min_const_fn_dyn.rs:9:5 | +LL | const fn no_inner_dyn_trait2(x: Hide) { + | ------------------------------------- function declared as const here LL | x.0.field; | ^^^^^^^^^ | = note: see issue #57563 for more information = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable -error[E0658]: trait bounds other than `Sized` on const fn parameters are unstable +error[E0658]: trait objects in const fn are unstable --> $DIR/min_const_fn_dyn.rs:12:66 | LL | const fn no_inner_dyn_trait_ret() -> Hide { Hide(HasDyn { field: &0 }) } - | ^^ + | ----------------------------------------- ^^ + | | + | function declared as const here | = note: see issue #57563 for more information = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_libstd_stability.stderr b/src/test/ui/consts/min_const_fn/min_const_fn_libstd_stability.stderr index d3017c5602..778b0e55f6 100644 --- a/src/test/ui/consts/min_const_fn/min_const_fn_libstd_stability.stderr +++ b/src/test/ui/consts/min_const_fn/min_const_fn_libstd_stability.stderr @@ -4,7 +4,7 @@ error: `foo` is not yet stable as a const fn LL | const fn bar() -> u32 { foo() } | ^^^^^ | - = help: Const-stable functions can only call other const-stable functions + = help: const-stable functions can only call other const-stable functions error: `foo2` is not yet stable as a const fn --> $DIR/min_const_fn_libstd_stability.rs:24:26 @@ -12,7 +12,7 @@ error: `foo2` is not yet stable as a const fn LL | const fn bar2() -> u32 { foo2() } | ^^^^^^ | - = help: Const-stable functions can only call other const-stable functions + = help: const-stable functions can only call other const-stable functions error: const-stable function cannot use `#[feature(const_fn_floating_point_arithmetic)]` --> $DIR/min_const_fn_libstd_stability.rs:29:26 @@ -35,7 +35,7 @@ error: `foo2_gated` is not yet stable as a const fn LL | const fn bar2_gated() -> u32 { foo2_gated() } | ^^^^^^^^^^^^ | - = help: Const-stable functions can only call other const-stable functions + = help: const-stable functions can only call other const-stable functions error: aborting due to 4 previous errors diff --git a/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.stderr b/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.stderr index 53a59467e3..0174cb77f3 100644 --- a/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.stderr +++ b/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.stderr @@ -4,7 +4,7 @@ error: `foo` is not yet stable as a const fn LL | const unsafe fn bar() -> u32 { unsafe { foo() } } | ^^^^^ | - = help: Const-stable functions can only call other const-stable functions + = help: const-stable functions can only call other const-stable functions error: `foo2` is not yet stable as a const fn --> $DIR/min_const_unsafe_fn_libstd_stability.rs:24:42 @@ -12,7 +12,7 @@ error: `foo2` is not yet stable as a const fn LL | const unsafe fn bar2() -> u32 { unsafe { foo2() } } | ^^^^^^ | - = help: Const-stable functions can only call other const-stable functions + = help: const-stable functions can only call other const-stable functions error: const-stable function cannot use `#[feature(const_fn_floating_point_arithmetic)]` --> $DIR/min_const_unsafe_fn_libstd_stability.rs:29:33 @@ -35,7 +35,7 @@ error: `foo2_gated` is not yet stable as a const fn LL | const unsafe fn bar2_gated() -> u32 { unsafe { foo2_gated() } } | ^^^^^^^^^^^^ | - = help: Const-stable functions can only call other const-stable functions + = help: const-stable functions can only call other const-stable functions error: aborting due to 4 previous errors diff --git a/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability2.stderr b/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability2.stderr index 891c34a888..e90ba9b912 100644 --- a/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability2.stderr +++ b/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability2.stderr @@ -4,7 +4,7 @@ error: `foo` is not yet stable as a const fn LL | const unsafe fn bar() -> u32 { foo() } | ^^^^^ | - = help: Const-stable functions can only call other const-stable functions + = help: const-stable functions can only call other const-stable functions error: `foo2` is not yet stable as a const fn --> $DIR/min_const_unsafe_fn_libstd_stability2.rs:24:33 @@ -12,7 +12,7 @@ error: `foo2` is not yet stable as a const fn LL | const unsafe fn bar2() -> u32 { foo2() } | ^^^^^^ | - = help: Const-stable functions can only call other const-stable functions + = help: const-stable functions can only call other const-stable functions error: `foo2_gated` is not yet stable as a const fn --> $DIR/min_const_unsafe_fn_libstd_stability2.rs:33:39 @@ -20,7 +20,7 @@ error: `foo2_gated` is not yet stable as a const fn LL | const unsafe fn bar2_gated() -> u32 { foo2_gated() } | ^^^^^^^^^^^^ | - = help: Const-stable functions can only call other const-stable functions + = help: const-stable functions can only call other const-stable functions error: aborting due to 3 previous errors diff --git a/src/test/ui/consts/miri_unleashed/box.rs b/src/test/ui/consts/miri_unleashed/box.rs index 1f0b7f7e78..32796c6722 100644 --- a/src/test/ui/consts/miri_unleashed/box.rs +++ b/src/test/ui/consts/miri_unleashed/box.rs @@ -9,5 +9,5 @@ fn main() {} static TEST_BAD: &mut i32 = { &mut *(box 0) //~^ ERROR could not evaluate static initializer - //~| NOTE heap allocations + //~| NOTE calling non-const function `alloc::alloc::exchange_malloc` }; diff --git a/src/test/ui/consts/miri_unleashed/box.stderr b/src/test/ui/consts/miri_unleashed/box.stderr index 66ea9d5924..05d9858dc0 100644 --- a/src/test/ui/consts/miri_unleashed/box.stderr +++ b/src/test/ui/consts/miri_unleashed/box.stderr @@ -2,7 +2,7 @@ error[E0080]: could not evaluate static initializer --> $DIR/box.rs:10:11 | LL | &mut *(box 0) - | ^^^^^^^ "heap allocations via `box` keyword" needs an rfc before being allowed inside constants + | ^^^^^^^ calling non-const function `alloc::alloc::exchange_malloc` warning: skipping const checks | diff --git a/src/test/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.32bit.stderr b/src/test/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.32bit.stderr index 64d8540878..186c5b1856 100644 --- a/src/test/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.32bit.stderr +++ b/src/test/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.32bit.stderr @@ -161,17 +161,11 @@ help: skipping check that does not even have a feature gate | LL | unsafe { match static_cross_crate::OPT_ZERO { Some(ref u) => u, None => panic!() } } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -help: skipping check for `const_panic` feature - --> $DIR/const_refers_to_static_cross_crate.rs:32:77 - | -LL | unsafe { match static_cross_crate::OPT_ZERO { Some(ref u) => u, None => panic!() } } - | ^^^^^^^^ help: skipping check that does not even have a feature gate --> $DIR/const_refers_to_static_cross_crate.rs:32:20 | LL | unsafe { match static_cross_crate::OPT_ZERO { Some(ref u) => u, None => panic!() } } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: this warning originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 10 previous errors; 3 warnings emitted diff --git a/src/test/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.64bit.stderr b/src/test/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.64bit.stderr index 8e793ab3f0..7a64abd7b9 100644 --- a/src/test/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.64bit.stderr +++ b/src/test/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.64bit.stderr @@ -161,17 +161,11 @@ help: skipping check that does not even have a feature gate | LL | unsafe { match static_cross_crate::OPT_ZERO { Some(ref u) => u, None => panic!() } } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -help: skipping check for `const_panic` feature - --> $DIR/const_refers_to_static_cross_crate.rs:32:77 - | -LL | unsafe { match static_cross_crate::OPT_ZERO { Some(ref u) => u, None => panic!() } } - | ^^^^^^^^ help: skipping check that does not even have a feature gate --> $DIR/const_refers_to_static_cross_crate.rs:32:20 | LL | unsafe { match static_cross_crate::OPT_ZERO { Some(ref u) => u, None => panic!() } } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: this warning originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 10 previous errors; 3 warnings emitted diff --git a/src/test/ui/consts/miri_unleashed/inline_asm.stderr b/src/test/ui/consts/miri_unleashed/inline_asm.stderr index d06afa8048..ac9191a340 100644 --- a/src/test/ui/consts/miri_unleashed/inline_asm.stderr +++ b/src/test/ui/consts/miri_unleashed/inline_asm.stderr @@ -2,7 +2,7 @@ error[E0080]: could not evaluate static initializer --> $DIR/inline_asm.rs:11:14 | LL | unsafe { llvm_asm!("xor %eax, %eax" ::: "eax"); } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ inline assembly is not supported + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ inline assembly is not supported | = note: this error originates in the macro `llvm_asm` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -10,7 +10,7 @@ error[E0080]: could not evaluate static initializer --> $DIR/inline_asm.rs:20:14 | LL | unsafe { asm!("nop"); } - | ^^^^^^^^^^^^ inline assembly is not supported + | ^^^^^^^^^^^ inline assembly is not supported warning: skipping const checks | @@ -18,12 +18,12 @@ help: skipping check that does not even have a feature gate --> $DIR/inline_asm.rs:11:14 | LL | unsafe { llvm_asm!("xor %eax, %eax" ::: "eax"); } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: skipping check that does not even have a feature gate --> $DIR/inline_asm.rs:20:14 | LL | unsafe { asm!("nop"); } - | ^^^^^^^^^^^^ + | ^^^^^^^^^^^ = note: this warning originates in the macro `llvm_asm` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 2 previous errors; 1 warning emitted diff --git a/src/test/ui/consts/not_const_clusure_in_const.rs b/src/test/ui/consts/not_const_clusure_in_const.rs new file mode 100644 index 0000000000..fd2cfa442d --- /dev/null +++ b/src/test/ui/consts/not_const_clusure_in_const.rs @@ -0,0 +1,9 @@ +// run-pass + +const _FOO: fn() -> String = || "foo".into(); + +pub fn bar() -> fn() -> String { + || "bar".into() +} + +fn main(){} diff --git a/src/test/ui/consts/ptr_comparisons.rs b/src/test/ui/consts/ptr_comparisons.rs index 9b5fd18f81..971b7c3cb1 100644 --- a/src/test/ui/consts/ptr_comparisons.rs +++ b/src/test/ui/consts/ptr_comparisons.rs @@ -5,7 +5,6 @@ // normalize-stderr-64bit: "size 8" -> "size $$WORD" #![feature( - const_panic, core_intrinsics, const_raw_ptr_comparison, const_ptr_offset, diff --git a/src/test/ui/consts/ptr_comparisons.stderr b/src/test/ui/consts/ptr_comparisons.stderr index a28ae521d5..48cd5da213 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::::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL | - ::: $DIR/ptr_comparisons.rs:61:34 + ::: $DIR/ptr_comparisons.rs:60:34 | LL | const _: *const usize = unsafe { (FOO as *const usize).offset(2) }; - | ------------------------------- inside `_` at $DIR/ptr_comparisons.rs:61:34 + | ------------------------------- inside `_` at $DIR/ptr_comparisons.rs:60:34 error[E0080]: evaluation of constant value failed - --> $DIR/ptr_comparisons.rs:64:33 + --> $DIR/ptr_comparisons.rs:63: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:68:27 + --> $DIR/ptr_comparisons.rs:67: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 error: any use of this value will cause an error - --> $DIR/ptr_comparisons.rs:73:27 + --> $DIR/ptr_comparisons.rs:72:27 | LL | const _: usize = unsafe { *std::mem::transmute::<&&usize, &usize>(&FOO) + 4 }; | --------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- diff --git a/src/test/ui/consts/ptr_is_null.rs b/src/test/ui/consts/ptr_is_null.rs index 324f59443f..8babb68585 100644 --- a/src/test/ui/consts/ptr_is_null.rs +++ b/src/test/ui/consts/ptr_is_null.rs @@ -1,7 +1,7 @@ // compile-flags: --crate-type=lib // check-pass -#![feature(const_ptr_is_null, const_panic)] +#![feature(const_ptr_is_null)] const FOO: &usize = &42; diff --git a/src/test/ui/consts/refs_check_const_eq-issue-88384.rs b/src/test/ui/consts/refs_check_const_eq-issue-88384.rs new file mode 100644 index 0000000000..204d18ea25 --- /dev/null +++ b/src/test/ui/consts/refs_check_const_eq-issue-88384.rs @@ -0,0 +1,25 @@ +// check-pass + +#![feature(fn_traits)] +#![feature(adt_const_params)] +//~^ WARNING the feature `adt_const_params` is incomplete + +#[derive(PartialEq, Eq)] +struct CompileTimeSettings{ + hooks: &'static[fn()], +} + +struct Foo; + +impl Foo { + fn call_hooks(){ + } +} + +fn main(){ + const SETTINGS: CompileTimeSettings = CompileTimeSettings{ + hooks: &[], + }; + + Foo::::call_hooks(); +} diff --git a/src/test/ui/consts/refs_check_const_eq-issue-88384.stderr b/src/test/ui/consts/refs_check_const_eq-issue-88384.stderr new file mode 100644 index 0000000000..55928b495b --- /dev/null +++ b/src/test/ui/consts/refs_check_const_eq-issue-88384.stderr @@ -0,0 +1,11 @@ +warning: the feature `adt_const_params` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/refs_check_const_eq-issue-88384.rs:4:12 + | +LL | #![feature(adt_const_params)] + | ^^^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44580 for more information + +warning: 1 warning emitted + diff --git a/src/test/ui/consts/refs_check_const_value_eq-issue-88876.rs b/src/test/ui/consts/refs_check_const_value_eq-issue-88876.rs new file mode 100644 index 0000000000..6ce9da4366 --- /dev/null +++ b/src/test/ui/consts/refs_check_const_value_eq-issue-88876.rs @@ -0,0 +1,12 @@ +// check-pass + +#![allow(incomplete_features)] +#![feature(adt_const_params)] + +struct FooConst {} + +const FOO_ARR: &[&'static str; 2] = &["Hello", "Friend"]; + +fn main() { + let _ = FooConst:: {}; +} diff --git a/src/test/ui/consts/unwind-abort.rs b/src/test/ui/consts/unwind-abort.rs index d9d0b91011..6c94fc7b98 100644 --- a/src/test/ui/consts/unwind-abort.rs +++ b/src/test/ui/consts/unwind-abort.rs @@ -1,6 +1,6 @@ // check-pass -#![feature(c_unwind, const_panic, const_extern_fn)] +#![feature(c_unwind, const_extern_fn)] // We don't unwind in const-eval anyways. const extern "C" fn foo() { diff --git a/src/test/ui/crate-loading/auxiliary/crateresolve2-1.rs b/src/test/ui/crate-loading/auxiliary/crateresolve2-1.rs new file mode 100644 index 0000000000..e9459ed071 --- /dev/null +++ b/src/test/ui/crate-loading/auxiliary/crateresolve2-1.rs @@ -0,0 +1,5 @@ +// compile-flags:-C extra-filename=-1 --emit=metadata +#![crate_name = "crateresolve2"] +#![crate_type = "lib"] + +pub fn f() -> isize { 10 } diff --git a/src/test/ui/crate-loading/auxiliary/crateresolve2-2.rs b/src/test/ui/crate-loading/auxiliary/crateresolve2-2.rs new file mode 100644 index 0000000000..c454168272 --- /dev/null +++ b/src/test/ui/crate-loading/auxiliary/crateresolve2-2.rs @@ -0,0 +1,5 @@ +// compile-flags:-C extra-filename=-2 --emit=metadata +#![crate_name = "crateresolve2"] +#![crate_type = "lib"] + +pub fn f() -> isize { 20 } diff --git a/src/test/ui/crate-loading/auxiliary/crateresolve2-3.rs b/src/test/ui/crate-loading/auxiliary/crateresolve2-3.rs new file mode 100644 index 0000000000..b356db4b6f --- /dev/null +++ b/src/test/ui/crate-loading/auxiliary/crateresolve2-3.rs @@ -0,0 +1,5 @@ +// compile-flags:-C extra-filename=-3 --emit=metadata +#![crate_name = "crateresolve2"] +#![crate_type = "lib"] + +pub fn f() -> isize { 30 } diff --git a/src/test/ui/crate-loading/crateresolve1.rs b/src/test/ui/crate-loading/crateresolve1.rs index 49e47dacc3..f4795e9536 100644 --- a/src/test/ui/crate-loading/crateresolve1.rs +++ b/src/test/ui/crate-loading/crateresolve1.rs @@ -1,10 +1,15 @@ -// dont-check-compiler-stderr // aux-build:crateresolve1-1.rs // aux-build:crateresolve1-2.rs // aux-build:crateresolve1-3.rs -// error-pattern:multiple matching crates for `crateresolve1` + +// normalize-stderr-test: "\.nll/" -> "/" +// normalize-stderr-test: "\\\?\\" -> "" +// normalize-stderr-test: "(lib)?crateresolve1-([123])\.[a-z]+" -> "libcrateresolve1-$2.somelib" + +// NOTE: This test is duplicated at `src/test/ui/error-codes/E0464.rs`. extern crate crateresolve1; +//~^ ERROR multiple matching crates for `crateresolve1` fn main() { } diff --git a/src/test/ui/crate-loading/crateresolve1.stderr b/src/test/ui/crate-loading/crateresolve1.stderr new file mode 100644 index 0000000000..0d7538eafd --- /dev/null +++ b/src/test/ui/crate-loading/crateresolve1.stderr @@ -0,0 +1,14 @@ +error[E0464]: multiple matching crates for `crateresolve1` + --> $DIR/crateresolve1.rs:11:1 + | +LL | extern crate crateresolve1; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: candidates: + crate `crateresolve1`: $TEST_BUILD_DIR/crate-loading/crateresolve1/auxiliary/libcrateresolve1-1.somelib + crate `crateresolve1`: $TEST_BUILD_DIR/crate-loading/crateresolve1/auxiliary/libcrateresolve1-2.somelib + crate `crateresolve1`: $TEST_BUILD_DIR/crate-loading/crateresolve1/auxiliary/libcrateresolve1-3.somelib + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0464`. diff --git a/src/test/ui/crate-loading/crateresolve2.rs b/src/test/ui/crate-loading/crateresolve2.rs new file mode 100644 index 0000000000..5a4fee7ed6 --- /dev/null +++ b/src/test/ui/crate-loading/crateresolve2.rs @@ -0,0 +1,14 @@ +// check-fail + +// aux-build:crateresolve2-1.rs +// aux-build:crateresolve2-2.rs +// aux-build:crateresolve2-3.rs + +// normalize-stderr-test: "\.nll/" -> "/" +// normalize-stderr-test: "\\\?\\" -> "" + +extern crate crateresolve2; +//~^ ERROR multiple matching crates for `crateresolve2` + +fn main() { +} diff --git a/src/test/ui/crate-loading/crateresolve2.stderr b/src/test/ui/crate-loading/crateresolve2.stderr new file mode 100644 index 0000000000..afd3702de7 --- /dev/null +++ b/src/test/ui/crate-loading/crateresolve2.stderr @@ -0,0 +1,14 @@ +error[E0464]: multiple matching crates for `crateresolve2` + --> $DIR/crateresolve2.rs:10:1 + | +LL | extern crate crateresolve2; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: candidates: + crate `crateresolve2`: $TEST_BUILD_DIR/crate-loading/crateresolve2/auxiliary/libcrateresolve2-1.rmeta + crate `crateresolve2`: $TEST_BUILD_DIR/crate-loading/crateresolve2/auxiliary/libcrateresolve2-2.rmeta + crate `crateresolve2`: $TEST_BUILD_DIR/crate-loading/crateresolve2/auxiliary/libcrateresolve2-3.rmeta + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0464`. diff --git a/src/test/ui/crate-method-reexport-grrrrrrr.rs b/src/test/ui/crate-method-reexport-grrrrrrr.rs index eefcf7738a..55e05cfb20 100644 --- a/src/test/ui/crate-method-reexport-grrrrrrr.rs +++ b/src/test/ui/crate-method-reexport-grrrrrrr.rs @@ -1,8 +1,6 @@ // run-pass // pretty-expanded FIXME #23616 -#![feature(box_syntax)] - // This is a regression test that the metadata for the // name_pool::methods impl in the other crate is reachable from this // crate. @@ -14,7 +12,7 @@ extern crate crate_method_reexport_grrrrrrr2; pub fn main() { use crate_method_reexport_grrrrrrr2::rust::add; use crate_method_reexport_grrrrrrr2::rust::cx; - let x: Box<_> = box (); + let x: Box<_> = Box::new(()); x.cx(); let y = (); y.add("hi".to_string()); diff --git a/src/test/ui/cross-crate/auxiliary/cci_nested_lib.rs b/src/test/ui/cross-crate/auxiliary/cci_nested_lib.rs index 379ed07661..23d76ef365 100644 --- a/src/test/ui/cross-crate/auxiliary/cci_nested_lib.rs +++ b/src/test/ui/cross-crate/auxiliary/cci_nested_lib.rs @@ -1,5 +1,3 @@ -#![feature(box_syntax)] - use std::cell::RefCell; pub struct Entry { @@ -37,7 +35,7 @@ pub fn new_int_alist() -> alist { fn eq_int(a: isize, b: isize) -> bool { a == b } return alist { eq_fn: eq_int, - data: box RefCell::new(Vec::new()), + data: Box::new(RefCell::new(Vec::new())), }; } @@ -47,6 +45,6 @@ pub fn new_int_alist_2() -> alist { fn eq_int(a: isize, b: isize) -> bool { a == b } return alist { eq_fn: eq_int, - data: box RefCell::new(Vec::new()), + data: Box::new(RefCell::new(Vec::new())), }; } diff --git a/src/test/ui/cross-crate/cci_borrow.rs b/src/test/ui/cross-crate/cci_borrow.rs index 605a166ffa..fee6b5d03a 100644 --- a/src/test/ui/cross-crate/cci_borrow.rs +++ b/src/test/ui/cross-crate/cci_borrow.rs @@ -1,13 +1,11 @@ // run-pass // aux-build:cci_borrow_lib.rs -#![feature(box_syntax)] - extern crate cci_borrow_lib; use cci_borrow_lib::foo; pub fn main() { - let p: Box<_> = box 22; + let p: Box<_> = Box::new(22); let r = foo(&*p); println!("r={}", r); assert_eq!(r, 22); diff --git a/src/test/ui/cross/cross-borrow-trait.stderr b/src/test/ui/cross/cross-borrow-trait.stderr index f693a3149b..81f309eae0 100644 --- a/src/test/ui/cross/cross-borrow-trait.stderr +++ b/src/test/ui/cross/cross-borrow-trait.stderr @@ -2,10 +2,8 @@ error[E0308]: mismatched types --> $DIR/cross-borrow-trait.rs:10:26 | LL | let _y: &dyn Trait = x; - | ---------- ^ - | | | - | | expected `&dyn Trait`, found struct `Box` - | | help: consider borrowing here: `&x` + | ---------- ^ expected `&dyn Trait`, found struct `Box` + | | | expected due to this | = note: expected reference `&dyn Trait` diff --git a/src/test/ui/cross/cross-crate-macro-backtrace/main.stderr b/src/test/ui/cross/cross-crate-macro-backtrace/main.stderr index 9ebffbfb71..6e2a1d3bbc 100644 --- a/src/test/ui/cross/cross-crate-macro-backtrace/main.stderr +++ b/src/test/ui/cross/cross-crate-macro-backtrace/main.stderr @@ -2,7 +2,7 @@ error: 1 positional argument in format string, but no arguments were given --> $DIR/main.rs:6:5 | LL | myprintln!("{}"); - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ | = note: this error originates in the macro `concat` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/cross/cross-file-errors/main.stderr b/src/test/ui/cross/cross-file-errors/main.stderr index ff9e87250c..829535f921 100644 --- a/src/test/ui/cross/cross-file-errors/main.stderr +++ b/src/test/ui/cross/cross-file-errors/main.stderr @@ -7,7 +7,7 @@ LL | _ ::: $DIR/main.rs:5:5 | LL | underscore!(); - | -------------- in this macro invocation + | ------------- in this macro invocation | = note: see issue #71126 for more information = help: add `#![feature(destructuring_assignment)]` to the crate attributes to enable @@ -22,7 +22,7 @@ LL | _ ::: $DIR/main.rs:5:5 | LL | underscore!(); - | -------------- in this macro invocation + | ------------- in this macro invocation | = note: this error originates in the macro `underscore` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/dep-graph/dep-graph-assoc-type-codegen.rs b/src/test/ui/dep-graph/dep-graph-assoc-type-codegen.rs index a0ee3ad31e..978c199480 100644 --- a/src/test/ui/dep-graph/dep-graph-assoc-type-codegen.rs +++ b/src/test/ui/dep-graph/dep-graph-assoc-type-codegen.rs @@ -1,7 +1,8 @@ // Test that when a trait impl changes, fns whose body uses that trait // must also be recompiled. -// compile-flags: -Z query-dep-graph -C incremental=tmp/dep-graph-assoc-type-codegen +// incremental +// compile-flags: -Z query-dep-graph #![feature(rustc_attrs)] #![allow(warnings)] diff --git a/src/test/ui/dep-graph/dep-graph-assoc-type-codegen.stderr b/src/test/ui/dep-graph/dep-graph-assoc-type-codegen.stderr index 4e659648e9..cdc268cff9 100644 --- a/src/test/ui/dep-graph/dep-graph-assoc-type-codegen.stderr +++ b/src/test/ui/dep-graph/dep-graph-assoc-type-codegen.stderr @@ -1,5 +1,5 @@ error: OK - --> $DIR/dep-graph-assoc-type-codegen.rs:28:5 + --> $DIR/dep-graph-assoc-type-codegen.rs:29:5 | LL | #[rustc_then_this_would_need(typeck)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/dep-graph/dep-graph-caller-callee.rs b/src/test/ui/dep-graph/dep-graph-caller-callee.rs index c95ea53650..4a3a8bb6bf 100644 --- a/src/test/ui/dep-graph/dep-graph-caller-callee.rs +++ b/src/test/ui/dep-graph/dep-graph-caller-callee.rs @@ -1,7 +1,8 @@ // Test that immediate callers have to change when callee changes, but // not callers' callers. -// compile-flags: -Z query-dep-graph -C incremental=tmp/dep-graph-caller-callee +// incremental +// compile-flags: -Z query-dep-graph #![feature(rustc_attrs)] #![allow(dead_code)] diff --git a/src/test/ui/dep-graph/dep-graph-caller-callee.stderr b/src/test/ui/dep-graph/dep-graph-caller-callee.stderr index 3d968aa3ea..4d06dc7f3e 100644 --- a/src/test/ui/dep-graph/dep-graph-caller-callee.stderr +++ b/src/test/ui/dep-graph/dep-graph-caller-callee.stderr @@ -1,11 +1,11 @@ error: OK - --> $DIR/dep-graph-caller-callee.rs:20:5 + --> $DIR/dep-graph-caller-callee.rs:21:5 | LL | #[rustc_then_this_would_need(typeck)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: no path from `x` to `typeck` - --> $DIR/dep-graph-caller-callee.rs:31:5 + --> $DIR/dep-graph-caller-callee.rs:32:5 | LL | #[rustc_then_this_would_need(typeck)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/dep-graph/dep-graph-struct-signature.rs b/src/test/ui/dep-graph/dep-graph-struct-signature.rs index 50a670b877..fcf9f63871 100644 --- a/src/test/ui/dep-graph/dep-graph-struct-signature.rs +++ b/src/test/ui/dep-graph/dep-graph-struct-signature.rs @@ -1,7 +1,8 @@ // Test cases where a changing struct appears in the signature of fns // and methods. -// compile-flags: -Z query-dep-graph -C incremental=tmp/dep-graph-struct-signature +// incremental +// compile-flags: -Z query-dep-graph #![feature(rustc_attrs)] #![allow(dead_code)] diff --git a/src/test/ui/dep-graph/dep-graph-struct-signature.stderr b/src/test/ui/dep-graph/dep-graph-struct-signature.stderr index b81aeabab7..60bfbe94a8 100644 --- a/src/test/ui/dep-graph/dep-graph-struct-signature.stderr +++ b/src/test/ui/dep-graph/dep-graph-struct-signature.stderr @@ -1,131 +1,131 @@ error: no path from `WillChange` to `type_of` - --> $DIR/dep-graph-struct-signature.rs:27:5 + --> $DIR/dep-graph-struct-signature.rs:28:5 | LL | #[rustc_then_this_would_need(type_of)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: no path from `WillChange` to `associated_item` - --> $DIR/dep-graph-struct-signature.rs:28:5 + --> $DIR/dep-graph-struct-signature.rs:29:5 | LL | #[rustc_then_this_would_need(associated_item)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: no path from `WillChange` to `trait_def` - --> $DIR/dep-graph-struct-signature.rs:29:5 + --> $DIR/dep-graph-struct-signature.rs:30:5 | LL | #[rustc_then_this_would_need(trait_def)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: OK - --> $DIR/dep-graph-struct-signature.rs:31:9 + --> $DIR/dep-graph-struct-signature.rs:32:9 | LL | #[rustc_then_this_would_need(fn_sig)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: OK - --> $DIR/dep-graph-struct-signature.rs:35:5 - | -LL | #[rustc_then_this_would_need(fn_sig)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - error: OK --> $DIR/dep-graph-struct-signature.rs:36:5 | -LL | #[rustc_then_this_would_need(typeck)] +LL | #[rustc_then_this_would_need(fn_sig)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: OK - --> $DIR/dep-graph-struct-signature.rs:39:5 + --> $DIR/dep-graph-struct-signature.rs:37:5 | -LL | #[rustc_then_this_would_need(fn_sig)] +LL | #[rustc_then_this_would_need(typeck)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: OK --> $DIR/dep-graph-struct-signature.rs:40:5 | +LL | #[rustc_then_this_would_need(fn_sig)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: OK + --> $DIR/dep-graph-struct-signature.rs:41:5 + | LL | #[rustc_then_this_would_need(typeck)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: OK - --> $DIR/dep-graph-struct-signature.rs:45:5 + --> $DIR/dep-graph-struct-signature.rs:46:5 | LL | #[rustc_then_this_would_need(type_of)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: OK - --> $DIR/dep-graph-struct-signature.rs:47:9 - | -LL | #[rustc_then_this_would_need(fn_sig)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - error: OK --> $DIR/dep-graph-struct-signature.rs:48:9 | +LL | #[rustc_then_this_would_need(fn_sig)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: OK + --> $DIR/dep-graph-struct-signature.rs:49:9 + | LL | #[rustc_then_this_would_need(typeck)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: OK - --> $DIR/dep-graph-struct-signature.rs:52:5 + --> $DIR/dep-graph-struct-signature.rs:53:5 | LL | #[rustc_then_this_would_need(type_of)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: OK - --> $DIR/dep-graph-struct-signature.rs:54:9 - | -LL | #[rustc_then_this_would_need(fn_sig)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - error: OK --> $DIR/dep-graph-struct-signature.rs:55:9 | +LL | #[rustc_then_this_would_need(fn_sig)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: OK + --> $DIR/dep-graph-struct-signature.rs:56:9 + | LL | #[rustc_then_this_would_need(typeck)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: OK - --> $DIR/dep-graph-struct-signature.rs:60:9 + --> $DIR/dep-graph-struct-signature.rs:61:9 | LL | #[rustc_then_this_would_need(type_of)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: OK - --> $DIR/dep-graph-struct-signature.rs:62:9 + --> $DIR/dep-graph-struct-signature.rs:63:9 | LL | #[rustc_then_this_would_need(type_of)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: no path from `WillChange` to `type_of` - --> $DIR/dep-graph-struct-signature.rs:67:5 + --> $DIR/dep-graph-struct-signature.rs:68:5 | LL | #[rustc_then_this_would_need(type_of)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: no path from `WillChange` to `type_of` - --> $DIR/dep-graph-struct-signature.rs:74:5 + --> $DIR/dep-graph-struct-signature.rs:75:5 | LL | #[rustc_then_this_would_need(type_of)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: no path from `WillChange` to `fn_sig` - --> $DIR/dep-graph-struct-signature.rs:76:9 + --> $DIR/dep-graph-struct-signature.rs:77:9 | LL | #[rustc_then_this_would_need(fn_sig)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: no path from `WillChange` to `fn_sig` - --> $DIR/dep-graph-struct-signature.rs:80:5 + --> $DIR/dep-graph-struct-signature.rs:81:5 | LL | #[rustc_then_this_would_need(fn_sig)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: no path from `WillChange` to `fn_sig` - --> $DIR/dep-graph-struct-signature.rs:83:5 + --> $DIR/dep-graph-struct-signature.rs:84:5 | LL | #[rustc_then_this_would_need(fn_sig)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: no path from `WillChange` to `typeck` - --> $DIR/dep-graph-struct-signature.rs:84:5 + --> $DIR/dep-graph-struct-signature.rs:85:5 | LL | #[rustc_then_this_would_need(typeck)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/dep-graph/dep-graph-trait-impl-two-traits-same-method.rs b/src/test/ui/dep-graph/dep-graph-trait-impl-two-traits-same-method.rs index c0a6617316..5da8df5706 100644 --- a/src/test/ui/dep-graph/dep-graph-trait-impl-two-traits-same-method.rs +++ b/src/test/ui/dep-graph/dep-graph-trait-impl-two-traits-same-method.rs @@ -1,7 +1,8 @@ // Test that adding an impl to a trait `Foo` DOES affect functions // that only use `Bar` if they have methods in common. -// compile-flags: -Z query-dep-graph -C incremental=tmp/dep-graph-trait-impl-two-traits-same-method +// incremental +// compile-flags: -Z query-dep-graph #![feature(rustc_attrs)] #![allow(dead_code)] diff --git a/src/test/ui/dep-graph/dep-graph-trait-impl-two-traits-same-method.stderr b/src/test/ui/dep-graph/dep-graph-trait-impl-two-traits-same-method.stderr index ae3d725e1c..6f56cbc8dd 100644 --- a/src/test/ui/dep-graph/dep-graph-trait-impl-two-traits-same-method.stderr +++ b/src/test/ui/dep-graph/dep-graph-trait-impl-two-traits-same-method.stderr @@ -1,11 +1,11 @@ error: OK - --> $DIR/dep-graph-trait-impl-two-traits-same-method.rs:32:5 + --> $DIR/dep-graph-trait-impl-two-traits-same-method.rs:33:5 | LL | #[rustc_then_this_would_need(typeck)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: no path from `x::` to `typeck` - --> $DIR/dep-graph-trait-impl-two-traits-same-method.rs:41:5 + --> $DIR/dep-graph-trait-impl-two-traits-same-method.rs:42:5 | LL | #[rustc_then_this_would_need(typeck)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/dep-graph/dep-graph-trait-impl-two-traits.rs b/src/test/ui/dep-graph/dep-graph-trait-impl-two-traits.rs index 56e9762ddb..0331e75b2f 100644 --- a/src/test/ui/dep-graph/dep-graph-trait-impl-two-traits.rs +++ b/src/test/ui/dep-graph/dep-graph-trait-impl-two-traits.rs @@ -1,7 +1,8 @@ // Test that adding an impl to a trait `Foo` does not affect functions // that only use `Bar`, so long as they do not have methods in common. -// compile-flags: -Z query-dep-graph -C incremental=tmp/dep-graph-trait-impl-two-traits +// incremental +// compile-flags: -Z query-dep-graph #![feature(rustc_attrs)] #![allow(warnings)] diff --git a/src/test/ui/dep-graph/dep-graph-trait-impl-two-traits.stderr b/src/test/ui/dep-graph/dep-graph-trait-impl-two-traits.stderr index 4823927477..08f382cc02 100644 --- a/src/test/ui/dep-graph/dep-graph-trait-impl-two-traits.stderr +++ b/src/test/ui/dep-graph/dep-graph-trait-impl-two-traits.stderr @@ -1,11 +1,11 @@ error: no path from `x::` to `typeck` - --> $DIR/dep-graph-trait-impl-two-traits.rs:31:5 + --> $DIR/dep-graph-trait-impl-two-traits.rs:32:5 | LL | #[rustc_then_this_would_need(typeck)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: no path from `x::` to `typeck` - --> $DIR/dep-graph-trait-impl-two-traits.rs:40:5 + --> $DIR/dep-graph-trait-impl-two-traits.rs:41:5 | LL | #[rustc_then_this_would_need(typeck)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/dep-graph/dep-graph-trait-impl.rs b/src/test/ui/dep-graph/dep-graph-trait-impl.rs index 3bbe3e745c..19002965b9 100644 --- a/src/test/ui/dep-graph/dep-graph-trait-impl.rs +++ b/src/test/ui/dep-graph/dep-graph-trait-impl.rs @@ -1,7 +1,8 @@ // Test that when a trait impl changes, fns whose body uses that trait // must also be recompiled. -// compile-flags: -Z query-dep-graph -C incremental=tmp/dep-graph-trait-impl +// incremental +// compile-flags: -Z query-dep-graph #![feature(rustc_attrs)] #![allow(warnings)] diff --git a/src/test/ui/dep-graph/dep-graph-trait-impl.stderr b/src/test/ui/dep-graph/dep-graph-trait-impl.stderr index f8ead80894..bfee6d5c87 100644 --- a/src/test/ui/dep-graph/dep-graph-trait-impl.stderr +++ b/src/test/ui/dep-graph/dep-graph-trait-impl.stderr @@ -1,29 +1,29 @@ error: OK - --> $DIR/dep-graph-trait-impl.rs:27:5 + --> $DIR/dep-graph-trait-impl.rs:28:5 | LL | #[rustc_then_this_would_need(typeck)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: OK - --> $DIR/dep-graph-trait-impl.rs:32:5 + --> $DIR/dep-graph-trait-impl.rs:33:5 | LL | #[rustc_then_this_would_need(typeck)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: OK - --> $DIR/dep-graph-trait-impl.rs:37:5 + --> $DIR/dep-graph-trait-impl.rs:38:5 | LL | #[rustc_then_this_would_need(typeck)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: OK - --> $DIR/dep-graph-trait-impl.rs:42:5 + --> $DIR/dep-graph-trait-impl.rs:43:5 | LL | #[rustc_then_this_would_need(typeck)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: no path from `x::` to `typeck` - --> $DIR/dep-graph-trait-impl.rs:55:5 + --> $DIR/dep-graph-trait-impl.rs:56:5 | LL | #[rustc_then_this_would_need(typeck)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/dep-graph/dep-graph-type-alias.rs b/src/test/ui/dep-graph/dep-graph-type-alias.rs index 5c5e24693a..0e1b3db192 100644 --- a/src/test/ui/dep-graph/dep-graph-type-alias.rs +++ b/src/test/ui/dep-graph/dep-graph-type-alias.rs @@ -1,6 +1,7 @@ // Test that changing what a `type` points to does not go unnoticed. -// compile-flags: -Z query-dep-graph -C incremental=tmp/dep-graph-type-alias +// incremental +// compile-flags: -Z query-dep-graph #![feature(rustc_attrs)] #![allow(dead_code)] diff --git a/src/test/ui/dep-graph/dep-graph-type-alias.stderr b/src/test/ui/dep-graph/dep-graph-type-alias.stderr index e698ce8f62..c59cf8014c 100644 --- a/src/test/ui/dep-graph/dep-graph-type-alias.stderr +++ b/src/test/ui/dep-graph/dep-graph-type-alias.stderr @@ -1,71 +1,71 @@ error: no path from `TypeAlias` to `type_of` - --> $DIR/dep-graph-type-alias.rs:17:1 + --> $DIR/dep-graph-type-alias.rs:18:1 | LL | #[rustc_then_this_would_need(type_of)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: OK - --> $DIR/dep-graph-type-alias.rs:19:5 + --> $DIR/dep-graph-type-alias.rs:20:5 | LL | #[rustc_then_this_would_need(type_of)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: no path from `TypeAlias` to `type_of` - --> $DIR/dep-graph-type-alias.rs:24:1 + --> $DIR/dep-graph-type-alias.rs:25:1 | LL | #[rustc_then_this_would_need(type_of)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: OK - --> $DIR/dep-graph-type-alias.rs:27:9 + --> $DIR/dep-graph-type-alias.rs:28:9 | LL | #[rustc_then_this_would_need(type_of)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: no path from `TypeAlias` to `type_of` - --> $DIR/dep-graph-type-alias.rs:33:1 + --> $DIR/dep-graph-type-alias.rs:34:1 | LL | #[rustc_then_this_would_need(type_of)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: OK - --> $DIR/dep-graph-type-alias.rs:35:5 + --> $DIR/dep-graph-type-alias.rs:36:5 | LL | #[rustc_then_this_would_need(fn_sig)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: no path from `TypeAlias` to `type_of` - --> $DIR/dep-graph-type-alias.rs:41:1 + --> $DIR/dep-graph-type-alias.rs:42:1 | LL | #[rustc_then_this_would_need(type_of)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: OK - --> $DIR/dep-graph-type-alias.rs:43:5 + --> $DIR/dep-graph-type-alias.rs:44:5 | LL | #[rustc_then_this_would_need(fn_sig)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: OK - --> $DIR/dep-graph-type-alias.rs:44:5 + --> $DIR/dep-graph-type-alias.rs:45:5 | LL | #[rustc_then_this_would_need(typeck)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: OK - --> $DIR/dep-graph-type-alias.rs:48:1 + --> $DIR/dep-graph-type-alias.rs:49:1 | LL | #[rustc_then_this_would_need(type_of)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: OK - --> $DIR/dep-graph-type-alias.rs:51:1 + --> $DIR/dep-graph-type-alias.rs:52:1 | LL | #[rustc_then_this_would_need(fn_sig)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: OK - --> $DIR/dep-graph-type-alias.rs:52:1 + --> $DIR/dep-graph-type-alias.rs:53:1 | LL | #[rustc_then_this_would_need(typeck)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/dep-graph/dep-graph-variance-alias.rs b/src/test/ui/dep-graph/dep-graph-variance-alias.rs index 4f16127595..008434696d 100644 --- a/src/test/ui/dep-graph/dep-graph-variance-alias.rs +++ b/src/test/ui/dep-graph/dep-graph-variance-alias.rs @@ -1,7 +1,8 @@ // Test that changing what a `type` points to does not go unnoticed // by the variance analysis. -// compile-flags: -Z query-dep-graph -C incremental=tmp/dep-graph-variance-alias +// incremental +// compile-flags: -Z query-dep-graph #![feature(rustc_attrs)] #![allow(dead_code)] diff --git a/src/test/ui/dep-graph/dep-graph-variance-alias.stderr b/src/test/ui/dep-graph/dep-graph-variance-alias.stderr index 2422cb9bb2..554ff455a2 100644 --- a/src/test/ui/dep-graph/dep-graph-variance-alias.stderr +++ b/src/test/ui/dep-graph/dep-graph-variance-alias.stderr @@ -1,5 +1,5 @@ error: OK - --> $DIR/dep-graph-variance-alias.rs:18:1 + --> $DIR/dep-graph-variance-alias.rs:19:1 | LL | #[rustc_then_this_would_need(variances_of)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/deprecation/deprecation-lint-2.stderr b/src/test/ui/deprecation/deprecation-lint-2.stderr index 63da838b3c..a73e560527 100644 --- a/src/test/ui/deprecation/deprecation-lint-2.stderr +++ b/src/test/ui/deprecation/deprecation-lint-2.stderr @@ -2,7 +2,7 @@ error: use of deprecated function `deprecation_lint::deprecated`: text --> $DIR/deprecation-lint-2.rs:12:5 | LL | macro_test!(); - | ^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ | note: the lint level is defined here --> $DIR/deprecation-lint-2.rs:4:9 diff --git a/src/test/ui/deref.rs b/src/test/ui/deref.rs index cad4ede06a..0d4e08ad95 100644 --- a/src/test/ui/deref.rs +++ b/src/test/ui/deref.rs @@ -1,9 +1,7 @@ // run-pass // pretty-expanded FIXME #23616 -#![feature(box_syntax)] - pub fn main() { - let x: Box = box 10; + let x: Box = Box::new(10); let _y: isize = *x; } diff --git a/src/test/ui/derives/clone-debug-dead-code.rs b/src/test/ui/derives/clone-debug-dead-code.rs new file mode 100644 index 0000000000..80e9132093 --- /dev/null +++ b/src/test/ui/derives/clone-debug-dead-code.rs @@ -0,0 +1,45 @@ +// Checks that derived implementations of Clone and Debug do not +// contribute to dead code analysis (issue #84647). + +#![forbid(dead_code)] + +struct A { f: () } +//~^ ERROR: field is never read: `f` + +#[derive(Clone)] +struct B { f: () } +//~^ ERROR: field is never read: `f` + +#[derive(Debug)] +struct C { f: () } +//~^ ERROR: field is never read: `f` + +#[derive(Debug,Clone)] +struct D { f: () } +//~^ ERROR: field is never read: `f` + +struct E { f: () } +//~^ ERROR: field is never read: `f` +// Custom impl, still doesn't read f +impl Clone for E { + fn clone(&self) -> Self { + Self { f: () } + } +} + +struct F { f: () } +// Custom impl that actually reads f +impl Clone for F { + fn clone(&self) -> Self { + Self { f: self.f } + } +} + +fn main() { + let _ = A { f: () }; + let _ = B { f: () }; + let _ = C { f: () }; + let _ = D { f: () }; + let _ = E { f: () }; + let _ = F { f: () }; +} diff --git a/src/test/ui/derives/clone-debug-dead-code.stderr b/src/test/ui/derives/clone-debug-dead-code.stderr new file mode 100644 index 0000000000..226007f364 --- /dev/null +++ b/src/test/ui/derives/clone-debug-dead-code.stderr @@ -0,0 +1,38 @@ +error: field is never read: `f` + --> $DIR/clone-debug-dead-code.rs:6:12 + | +LL | struct A { f: () } + | ^^^^^ + | +note: the lint level is defined here + --> $DIR/clone-debug-dead-code.rs:4:11 + | +LL | #![forbid(dead_code)] + | ^^^^^^^^^ + +error: field is never read: `f` + --> $DIR/clone-debug-dead-code.rs:10:12 + | +LL | struct B { f: () } + | ^^^^^ + +error: field is never read: `f` + --> $DIR/clone-debug-dead-code.rs:14:12 + | +LL | struct C { f: () } + | ^^^^^ + +error: field is never read: `f` + --> $DIR/clone-debug-dead-code.rs:18:12 + | +LL | struct D { f: () } + | ^^^^^ + +error: field is never read: `f` + --> $DIR/clone-debug-dead-code.rs:21:12 + | +LL | struct E { f: () } + | ^^^^^ + +error: aborting due to 5 previous errors + 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 fd993d0f9d..1080f94773 100644 --- a/src/test/ui/derives/derive-assoc-type-not-impl.stderr +++ b/src/test/ui/derives/derive-assoc-type-not-impl.stderr @@ -19,6 +19,10 @@ LL | Bar:: { x: 1 }.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` +help: consider annotating `NotClone` with `#[derive(Clone)]` + | +LL | #[derive(Clone)] + | error: aborting due to previous error diff --git a/src/test/ui/derives/derives-span-PartialEq-enum-struct-variant.stderr b/src/test/ui/derives/derives-span-PartialEq-enum-struct-variant.stderr index abcba6da8a..19d2425ff2 100644 --- a/src/test/ui/derives/derives-span-PartialEq-enum-struct-variant.stderr +++ b/src/test/ui/derives/derives-span-PartialEq-enum-struct-variant.stderr @@ -7,8 +7,16 @@ LL | #[derive(PartialEq)] LL | x: Error | ^^^^^^^^ | - = note: an implementation of `std::cmp::PartialEq` might be missing for `Error` +note: an implementation of `PartialEq<_>` might be missing for `Error` + --> $DIR/derives-span-PartialEq-enum-struct-variant.rs:4:1 + | +LL | struct Error; + | ^^^^^^^^^^^^^ must implement `PartialEq<_>` = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `Error` with `#[derive(PartialEq)]` + | +LL | #[derive(PartialEq)] + | error[E0369]: binary operation `!=` cannot be applied to type `Error` --> $DIR/derives-span-PartialEq-enum-struct-variant.rs:9:6 @@ -19,8 +27,16 @@ LL | #[derive(PartialEq)] LL | x: Error | ^^^^^^^^ | - = note: an implementation of `std::cmp::PartialEq` might be missing for `Error` +note: an implementation of `PartialEq<_>` might be missing for `Error` + --> $DIR/derives-span-PartialEq-enum-struct-variant.rs:4:1 + | +LL | struct Error; + | ^^^^^^^^^^^^^ must implement `PartialEq<_>` = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `Error` with `#[derive(PartialEq)]` + | +LL | #[derive(PartialEq)] + | error: aborting due to 2 previous errors diff --git a/src/test/ui/derives/derives-span-PartialEq-enum.stderr b/src/test/ui/derives/derives-span-PartialEq-enum.stderr index cdb40c39f1..419832817c 100644 --- a/src/test/ui/derives/derives-span-PartialEq-enum.stderr +++ b/src/test/ui/derives/derives-span-PartialEq-enum.stderr @@ -7,8 +7,16 @@ LL | #[derive(PartialEq)] LL | Error | ^^^^^ | - = note: an implementation of `std::cmp::PartialEq` might be missing for `Error` +note: an implementation of `PartialEq<_>` might be missing for `Error` + --> $DIR/derives-span-PartialEq-enum.rs:4:1 + | +LL | struct Error; + | ^^^^^^^^^^^^^ must implement `PartialEq<_>` = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `Error` with `#[derive(PartialEq)]` + | +LL | #[derive(PartialEq)] + | error[E0369]: binary operation `!=` cannot be applied to type `Error` --> $DIR/derives-span-PartialEq-enum.rs:9:6 @@ -19,8 +27,16 @@ LL | #[derive(PartialEq)] LL | Error | ^^^^^ | - = note: an implementation of `std::cmp::PartialEq` might be missing for `Error` +note: an implementation of `PartialEq<_>` might be missing for `Error` + --> $DIR/derives-span-PartialEq-enum.rs:4:1 + | +LL | struct Error; + | ^^^^^^^^^^^^^ must implement `PartialEq<_>` = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `Error` with `#[derive(PartialEq)]` + | +LL | #[derive(PartialEq)] + | error: aborting due to 2 previous errors diff --git a/src/test/ui/derives/derives-span-PartialEq-struct.stderr b/src/test/ui/derives/derives-span-PartialEq-struct.stderr index 4cf8851a09..0000f88254 100644 --- a/src/test/ui/derives/derives-span-PartialEq-struct.stderr +++ b/src/test/ui/derives/derives-span-PartialEq-struct.stderr @@ -7,8 +7,16 @@ LL | struct Struct { LL | x: Error | ^^^^^^^^ | - = note: an implementation of `std::cmp::PartialEq` might be missing for `Error` +note: an implementation of `PartialEq<_>` might be missing for `Error` + --> $DIR/derives-span-PartialEq-struct.rs:4:1 + | +LL | struct Error; + | ^^^^^^^^^^^^^ must implement `PartialEq<_>` = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `Error` with `#[derive(PartialEq)]` + | +LL | #[derive(PartialEq)] + | error[E0369]: binary operation `!=` cannot be applied to type `Error` --> $DIR/derives-span-PartialEq-struct.rs:8:5 @@ -19,8 +27,16 @@ LL | struct Struct { LL | x: Error | ^^^^^^^^ | - = note: an implementation of `std::cmp::PartialEq` might be missing for `Error` +note: an implementation of `PartialEq<_>` might be missing for `Error` + --> $DIR/derives-span-PartialEq-struct.rs:4:1 + | +LL | struct Error; + | ^^^^^^^^^^^^^ must implement `PartialEq<_>` = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `Error` with `#[derive(PartialEq)]` + | +LL | #[derive(PartialEq)] + | error: aborting due to 2 previous errors diff --git a/src/test/ui/derives/derives-span-PartialEq-tuple-struct.stderr b/src/test/ui/derives/derives-span-PartialEq-tuple-struct.stderr index 66bc168735..07fa900a8c 100644 --- a/src/test/ui/derives/derives-span-PartialEq-tuple-struct.stderr +++ b/src/test/ui/derives/derives-span-PartialEq-tuple-struct.stderr @@ -7,8 +7,16 @@ LL | struct Struct( LL | Error | ^^^^^ | - = note: an implementation of `std::cmp::PartialEq` might be missing for `Error` +note: an implementation of `PartialEq<_>` might be missing for `Error` + --> $DIR/derives-span-PartialEq-tuple-struct.rs:4:1 + | +LL | struct Error; + | ^^^^^^^^^^^^^ must implement `PartialEq<_>` = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `Error` with `#[derive(PartialEq)]` + | +LL | #[derive(PartialEq)] + | error[E0369]: binary operation `!=` cannot be applied to type `Error` --> $DIR/derives-span-PartialEq-tuple-struct.rs:8:5 @@ -19,8 +27,16 @@ LL | struct Struct( LL | Error | ^^^^^ | - = note: an implementation of `std::cmp::PartialEq` might be missing for `Error` +note: an implementation of `PartialEq<_>` might be missing for `Error` + --> $DIR/derives-span-PartialEq-tuple-struct.rs:4:1 + | +LL | struct Error; + | ^^^^^^^^^^^^^ must implement `PartialEq<_>` = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `Error` with `#[derive(PartialEq)]` + | +LL | #[derive(PartialEq)] + | error: aborting due to 2 previous errors diff --git a/src/test/ui/derives/deriving-copyclone.stderr b/src/test/ui/derives/deriving-copyclone.stderr index ecdbbff4d9..1d0554ad04 100644 --- a/src/test/ui/derives/deriving-copyclone.stderr +++ b/src/test/ui/derives/deriving-copyclone.stderr @@ -2,10 +2,9 @@ error[E0277]: the trait bound `C: Copy` is not satisfied --> $DIR/deriving-copyclone.rs:31:13 | LL | is_copy(B { a: 1, b: C }); - | ^^^^^^^^^^^^^^^^ - | | - | expected an implementor of trait `Copy` - | help: consider borrowing here: `&B { a: 1, b: C }` + | ------- ^^^^^^^^^^^^^^^^ expected an implementor of trait `Copy` + | | + | required by a bound introduced by this call | note: required because of the requirements on the impl of `Copy` for `B` --> $DIR/deriving-copyclone.rs:9:10 @@ -18,15 +17,18 @@ note: required by a bound in `is_copy` LL | fn is_copy(_: T) {} | ^^^^ required by this bound in `is_copy` = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider borrowing here + | +LL | is_copy(&B { a: 1, b: C }); + | + error[E0277]: the trait bound `C: Clone` is not satisfied --> $DIR/deriving-copyclone.rs:32:14 | LL | is_clone(B { a: 1, b: C }); - | ^^^^^^^^^^^^^^^^ - | | - | expected an implementor of trait `Clone` - | help: consider borrowing here: `&B { a: 1, b: C }` + | -------- ^^^^^^^^^^^^^^^^ expected an implementor of trait `Clone` + | | + | required by a bound introduced by this call | note: required because of the requirements on the impl of `Clone` for `B` --> $DIR/deriving-copyclone.rs:9:16 @@ -39,15 +41,18 @@ note: required by a bound in `is_clone` LL | fn is_clone(_: T) {} | ^^^^^ required by this bound in `is_clone` = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider borrowing here + | +LL | is_clone(&B { a: 1, b: C }); + | + error[E0277]: the trait bound `D: Copy` is not satisfied --> $DIR/deriving-copyclone.rs:35:13 | LL | is_copy(B { a: 1, b: D }); - | ^^^^^^^^^^^^^^^^ - | | - | expected an implementor of trait `Copy` - | help: consider borrowing here: `&B { a: 1, b: D }` + | ------- ^^^^^^^^^^^^^^^^ expected an implementor of trait `Copy` + | | + | required by a bound introduced by this call | note: required because of the requirements on the impl of `Copy` for `B` --> $DIR/deriving-copyclone.rs:9:10 @@ -60,6 +65,10 @@ note: required by a bound in `is_copy` LL | fn is_copy(_: T) {} | ^^^^ required by this bound in `is_copy` = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider borrowing here + | +LL | is_copy(&B { a: 1, b: D }); + | + error: aborting due to 3 previous errors 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 b97f87da4b..e322db97fa 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 @@ -7,8 +7,16 @@ LL | struct E { LL | x: NoCloneOrEq | ^^^^^^^^^^^^^^ | - = note: an implementation of `std::cmp::PartialEq` might be missing for `NoCloneOrEq` +note: an implementation of `PartialEq<_>` might be missing for `NoCloneOrEq` + --> $DIR/deriving-no-inner-impl-error-message.rs:1:1 + | +LL | struct NoCloneOrEq; + | ^^^^^^^^^^^^^^^^^^^ must implement `PartialEq<_>` = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `NoCloneOrEq` with `#[derive(PartialEq)]` + | +LL | #[derive(PartialEq)] + | error[E0369]: binary operation `!=` cannot be applied to type `NoCloneOrEq` --> $DIR/deriving-no-inner-impl-error-message.rs:5:5 @@ -19,8 +27,16 @@ LL | struct E { LL | x: NoCloneOrEq | ^^^^^^^^^^^^^^ | - = note: an implementation of `std::cmp::PartialEq` might be missing for `NoCloneOrEq` +note: an implementation of `PartialEq<_>` might be missing for `NoCloneOrEq` + --> $DIR/deriving-no-inner-impl-error-message.rs:1:1 + | +LL | struct NoCloneOrEq; + | ^^^^^^^^^^^^^^^^^^^ must implement `PartialEq<_>` = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `NoCloneOrEq` with `#[derive(PartialEq)]` + | +LL | #[derive(PartialEq)] + | error[E0277]: the trait bound `NoCloneOrEq: Clone` is not satisfied --> $DIR/deriving-no-inner-impl-error-message.rs:10:5 diff --git a/src/test/ui/deriving/deriving-clone-generic-struct.rs b/src/test/ui/deriving/deriving-clone-generic-struct.rs index f6e105555f..4374d1594e 100644 --- a/src/test/ui/deriving/deriving-clone-generic-struct.rs +++ b/src/test/ui/deriving/deriving-clone-generic-struct.rs @@ -1,6 +1,8 @@ // run-pass // pretty-expanded FIXME #23616 +#![allow(dead_code)] + #[derive(Clone)] struct S { foo: (), diff --git a/src/test/ui/deriving/deriving-clone-struct.rs b/src/test/ui/deriving/deriving-clone-struct.rs index 7b0a1d2026..b93cbe5f8b 100644 --- a/src/test/ui/deriving/deriving-clone-struct.rs +++ b/src/test/ui/deriving/deriving-clone-struct.rs @@ -1,6 +1,8 @@ // run-pass // pretty-expanded FIXME #23616 +#![allow(dead_code)] + #[derive(Clone)] struct S { _int: isize, diff --git a/src/test/ui/deriving/deriving-clone-tuple-struct.rs b/src/test/ui/deriving/deriving-clone-tuple-struct.rs index 166f1be55e..7ad3f03471 100644 --- a/src/test/ui/deriving/deriving-clone-tuple-struct.rs +++ b/src/test/ui/deriving/deriving-clone-tuple-struct.rs @@ -1,6 +1,8 @@ // run-pass // pretty-expanded FIXME #23616 +#![allow(dead_code)] + #[derive(Clone)] struct S((), ()); diff --git a/src/test/ui/deriving/deriving-default-box.rs b/src/test/ui/deriving/deriving-default-box.rs index 237dbfaa05..b71e114961 100644 --- a/src/test/ui/deriving/deriving-default-box.rs +++ b/src/test/ui/deriving/deriving-default-box.rs @@ -1,6 +1,4 @@ // run-pass -#![feature(box_syntax)] - use std::default::Default; #[derive(Default)] diff --git a/src/test/ui/deriving/deriving-in-fn.rs b/src/test/ui/deriving/deriving-in-fn.rs index 8931e94a4f..07f91d0597 100644 --- a/src/test/ui/deriving/deriving-in-fn.rs +++ b/src/test/ui/deriving/deriving-in-fn.rs @@ -1,4 +1,7 @@ // run-pass + +#![allow(dead_code)] + pub fn main() { #[derive(Debug)] struct Foo { diff --git a/src/test/ui/issues/issue-3935.rs b/src/test/ui/deriving/issue-3935.rs similarity index 100% rename from src/test/ui/issues/issue-3935.rs rename to src/test/ui/deriving/issue-3935.rs diff --git a/src/test/ui/deriving/issue-89188-gat-hrtb.rs b/src/test/ui/deriving/issue-89188-gat-hrtb.rs new file mode 100644 index 0000000000..abd85a616a --- /dev/null +++ b/src/test/ui/deriving/issue-89188-gat-hrtb.rs @@ -0,0 +1,39 @@ +// check-pass + +#![feature(generic_associated_types)] + +trait CallWithShim: Sized { + type Shim<'s> + where + Self: 's; +} + +#[derive(Clone)] +struct ShimMethod(pub &'static dyn for<'s> Fn(&'s mut T::Shim<'s>)); + +trait CallWithShim2: Sized { + type Shim; +} + +struct S<'s>(&'s ()); + +#[derive(Clone)] +struct ShimMethod2(pub &'static dyn for<'s> Fn(&'s mut T::Shim>)); + +trait Trait<'s, 't, 'u> {} + +#[derive(Clone)] +struct ShimMethod3( + pub &'static dyn for<'s> Fn( + &'s mut T::Shim Fn(&'s mut T::Shim Trait<'s, 't, 'u>>)>, + ), +); + +trait Trait2 { + type As; +} + +#[derive(Clone)] +struct ShimMethod4(pub &'static dyn for<'s> Fn(&'s mut T::As)); + +pub fn main() {} diff --git a/src/test/ui/destructure-trait-ref.rs b/src/test/ui/destructure-trait-ref.rs index fdc9bbab73..50b64aeebf 100644 --- a/src/test/ui/destructure-trait-ref.rs +++ b/src/test/ui/destructure-trait-ref.rs @@ -2,11 +2,11 @@ // reference work properly. #![feature(box_patterns)] -#![feature(box_syntax)] trait T { fn foo(&self) {} } impl T for isize {} + fn main() { // For an expression of the form: // @@ -25,7 +25,7 @@ fn main() { // n == m let &x = &1isize as &dyn T; //~ ERROR type `&dyn T` cannot be dereferenced let &&x = &(&1isize as &dyn T); //~ ERROR type `&dyn T` cannot be dereferenced - let box x = box 1isize as Box; + let box x = Box::new(1isize) as Box; //~^ ERROR type `Box` cannot be dereferenced // n > m @@ -37,7 +37,7 @@ fn main() { //~^ ERROR mismatched types //~| expected trait object `dyn T` //~| found reference `&_` - let box box x = box 1isize as Box; + let box box x = Box::new(1isize) as Box; //~^ ERROR mismatched types //~| expected trait object `dyn T` //~| found struct `Box<_>` diff --git a/src/test/ui/destructure-trait-ref.stderr b/src/test/ui/destructure-trait-ref.stderr index fb43ca760b..302917ca02 100644 --- a/src/test/ui/destructure-trait-ref.stderr +++ b/src/test/ui/destructure-trait-ref.stderr @@ -13,7 +13,7 @@ LL | let &&x = &(&1isize as &dyn T); error[E0033]: type `Box` cannot be dereferenced --> $DIR/destructure-trait-ref.rs:28:9 | -LL | let box x = box 1isize as Box; +LL | let box x = Box::new(1isize) as Box; | ^^^^^ type `Box` cannot be dereferenced error[E0308]: mismatched types @@ -43,8 +43,8 @@ LL | let &&&x = &(&1isize as &dyn T); error[E0308]: mismatched types --> $DIR/destructure-trait-ref.rs:40:13 | -LL | let box box x = box 1isize as Box; - | ^^^^^ ------------------------ this expression has type `Box` +LL | let box box x = Box::new(1isize) as Box; + | ^^^^^ ------------------------------ this expression has type `Box` | | | expected trait object `dyn T`, found struct `Box` | diff --git a/src/test/ui/destructuring-assignment/note-unsupported.stderr b/src/test/ui/destructuring-assignment/note-unsupported.stderr index a81324b99e..7b9788ca0f 100644 --- a/src/test/ui/destructuring-assignment/note-unsupported.stderr +++ b/src/test/ui/destructuring-assignment/note-unsupported.stderr @@ -99,7 +99,22 @@ LL | S { x: a, y: b } += s; | | | cannot use `+=` on type `S` | - = note: an implementation of `std::ops::AddAssign` might be missing for `S` +note: an implementation of `AddAssign<_>` might be missing for `S` + --> $DIR/note-unsupported.rs:1:1 + | +LL | struct S { x: u8, y: u8 } + | ^^^^^^^^ must implement `AddAssign<_>` +note: the following trait must be implemented + --> $SRC_DIR/core/src/ops/arith.rs:LL:COL + | +LL | / pub trait AddAssign { +LL | | /// Performs the `+=` operation. +LL | | /// +LL | | /// # Example +... | +LL | | fn add_assign(&mut self, rhs: Rhs); +LL | | } + | |_^ error[E0067]: invalid left-hand side of assignment --> $DIR/note-unsupported.rs:17:22 diff --git a/src/test/ui/did_you_mean/bad-assoc-expr.stderr b/src/test/ui/did_you_mean/bad-assoc-expr.stderr index fd29f8940b..c295cac9aa 100644 --- a/src/test/ui/did_you_mean/bad-assoc-expr.stderr +++ b/src/test/ui/did_you_mean/bad-assoc-expr.stderr @@ -53,7 +53,7 @@ LL | ($ty: ty) => ($ty::clone(&0)) | ^^^^^^^^^^ help: try: `<$ty>::clone` ... LL | expr!(u8); - | ---------- in this macro invocation + | --------- in this macro invocation | = note: this error originates in the macro `expr` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/did_you_mean/issue-34126.stderr b/src/test/ui/did_you_mean/issue-34126.stderr index 666172197c..0503fac4a6 100644 --- a/src/test/ui/did_you_mean/issue-34126.stderr +++ b/src/test/ui/did_you_mean/issue-34126.stderr @@ -19,8 +19,9 @@ error[E0502]: cannot borrow `self` as mutable because it is also borrowed as imm --> $DIR/issue-34126.rs:6:18 | LL | self.run(&mut self); - | ---- --- ^^^^^^^^^ mutable borrow occurs here - | | | + | ---------^^^^^^^^^- + | | | | + | | | mutable borrow occurs here | | immutable borrow later used by call | immutable borrow occurs here diff --git a/src/test/ui/did_you_mean/issue-35937.stderr b/src/test/ui/did_you_mean/issue-35937.stderr index 1f578d18a1..9562d94509 100644 --- a/src/test/ui/did_you_mean/issue-35937.stderr +++ b/src/test/ui/did_you_mean/issue-35937.stderr @@ -4,7 +4,7 @@ error[E0596]: cannot borrow `f.v` as mutable, as `f` is not declared as mutable LL | let f = Foo { v: Vec::new() }; | - help: consider changing this to be mutable: `mut f` LL | f.v.push("cat".to_string()); - | ^^^ cannot borrow as mutable + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot borrow as mutable error[E0594]: cannot assign to `s.x`, as `s` is not declared as mutable --> $DIR/issue-35937.rs:16:5 diff --git a/src/test/ui/did_you_mean/issue-38147-1.stderr b/src/test/ui/did_you_mean/issue-38147-1.stderr index 6efac371c0..dd193458b3 100644 --- a/src/test/ui/did_you_mean/issue-38147-1.stderr +++ b/src/test/ui/did_you_mean/issue-38147-1.stderr @@ -4,7 +4,7 @@ error[E0596]: cannot borrow `*self.s` as mutable, as it is behind a `&` referenc LL | fn f(&self) { | ----- help: consider changing this to be a mutable reference: `&mut self` LL | self.s.push('x'); - | ^^^^^^ `self` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | ^^^^^^^^^^^^^^^^ `self` is a `&` reference, so the data it refers to cannot be borrowed as mutable error: aborting due to previous error diff --git a/src/test/ui/did_you_mean/issue-38147-2.stderr b/src/test/ui/did_you_mean/issue-38147-2.stderr index cb49810893..8bf5c76977 100644 --- a/src/test/ui/did_you_mean/issue-38147-2.stderr +++ b/src/test/ui/did_you_mean/issue-38147-2.stderr @@ -5,7 +5,7 @@ LL | s: &'a String | ---------- help: consider changing this to be mutable: `&'a mut String` ... LL | self.s.push('x'); - | ^^^^^^ cannot borrow as mutable + | ^^^^^^^^^^^^^^^^ cannot borrow as mutable error: aborting due to previous error diff --git a/src/test/ui/did_you_mean/issue-38147-3.stderr b/src/test/ui/did_you_mean/issue-38147-3.stderr index 67782578a2..0e1e42261c 100644 --- a/src/test/ui/did_you_mean/issue-38147-3.stderr +++ b/src/test/ui/did_you_mean/issue-38147-3.stderr @@ -5,7 +5,7 @@ LL | s: &'a String | ---------- help: consider changing this to be mutable: `&'a mut String` ... LL | self.s.push('x'); - | ^^^^^^ cannot borrow as mutable + | ^^^^^^^^^^^^^^^^ cannot borrow as mutable error: aborting due to previous error diff --git a/src/test/ui/did_you_mean/issue-38147-4.stderr b/src/test/ui/did_you_mean/issue-38147-4.stderr index db3e6b8942..a2d162f08a 100644 --- a/src/test/ui/did_you_mean/issue-38147-4.stderr +++ b/src/test/ui/did_you_mean/issue-38147-4.stderr @@ -4,7 +4,7 @@ error[E0596]: cannot borrow `*f.s` as mutable, as it is behind a `&` reference LL | fn f(x: usize, f: &Foo) { | ---- help: consider changing this to be a mutable reference: `&mut Foo<'_>` LL | f.s.push('x'); - | ^^^ `f` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | ^^^^^^^^^^^^^ `f` is a `&` reference, so the data it refers to cannot be borrowed as mutable error: aborting due to previous error 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 fcb4ea1d59..c7458916c5 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 @@ -2,7 +2,9 @@ error[E0277]: the trait bound `i8: Foo` is not satisfied --> $DIR/issue-39802-show-5-trait-impls.rs:24:21 | LL | Foo::::bar(&1i8); - | ^^^^ the trait `Foo` is not implemented for `i8` + | --------------- ^^^^ the trait `Foo` is not implemented for `i8` + | | + | required by a bound introduced by this call | = help: the following implementations were found: > @@ -20,7 +22,9 @@ error[E0277]: the trait bound `u8: Foo` is not satisfied --> $DIR/issue-39802-show-5-trait-impls.rs:25:21 | LL | Foo::::bar(&1u8); - | ^^^^ the trait `Foo` is not implemented for `u8` + | --------------- ^^^^ the trait `Foo` is not implemented for `u8` + | | + | required by a bound introduced by this call | = help: the following implementations were found: > @@ -37,7 +41,9 @@ error[E0277]: the trait bound `bool: Foo` is not satisfied --> $DIR/issue-39802-show-5-trait-impls.rs:26:21 | LL | Foo::::bar(&true); - | ^^^^^ the trait `Foo` is not implemented for `bool` + | --------------- ^^^^^ the trait `Foo` is not implemented for `bool` + | | + | required by a bound introduced by this call | = help: the following implementations were found: > diff --git a/src/test/ui/did_you_mean/issue-40823.stderr b/src/test/ui/did_you_mean/issue-40823.stderr index 73473406a9..67703a1497 100644 --- a/src/test/ui/did_you_mean/issue-40823.stderr +++ b/src/test/ui/did_you_mean/issue-40823.stderr @@ -4,7 +4,7 @@ error[E0596]: cannot borrow `*buf` as mutable, as it is behind a `&` reference LL | let mut buf = &[1, 2, 3, 4]; | ------------- help: consider changing this to be a mutable reference: `&mut [1, 2, 3, 4]` LL | buf.iter_mut(); - | ^^^ `buf` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | ^^^^^^^^^^^^^^ `buf` is a `&` reference, so the data it refers to cannot be borrowed as mutable error: aborting due to previous error diff --git a/src/test/ui/did_you_mean/issue-87830-try-brackets-for-arrays.rs b/src/test/ui/did_you_mean/issue-87830-try-brackets-for-arrays.rs new file mode 100644 index 0000000000..53dad85900 --- /dev/null +++ b/src/test/ui/did_you_mean/issue-87830-try-brackets-for-arrays.rs @@ -0,0 +1,17 @@ +fn main() {} + +const FOO: [u8; 3] = { //~ ERROR this code is interpreted as a block expression + 1, 2, 3 +}; + +const BAR: [&str; 3] = {"one", "two", "three"}; +//~^ ERROR this code is interpreted as a block expression + +fn foo() { + {1, 2, 3}; + //~^ ERROR this code is interpreted as a block expression +} + +fn bar() { + 1, 2, 3 //~ ERROR expected one of +} diff --git a/src/test/ui/did_you_mean/issue-87830-try-brackets-for-arrays.stderr b/src/test/ui/did_you_mean/issue-87830-try-brackets-for-arrays.stderr new file mode 100644 index 0000000000..9ab491f5c2 --- /dev/null +++ b/src/test/ui/did_you_mean/issue-87830-try-brackets-for-arrays.stderr @@ -0,0 +1,49 @@ +error: this code is interpreted as a block expression, not an array + --> $DIR/issue-87830-try-brackets-for-arrays.rs:3:22 + | +LL | const FOO: [u8; 3] = { + | ______________________^ +LL | | 1, 2, 3 +LL | | }; + | |_^ + | + = note: to define an array, one would use square brackets instead of curly braces +help: try using [] instead of {} + | +LL ~ const FOO: [u8; 3] = [ +LL | 1, 2, 3 +LL ~ ]; + | + +error: this code is interpreted as a block expression, not an array + --> $DIR/issue-87830-try-brackets-for-arrays.rs:7:24 + | +LL | const BAR: [&str; 3] = {"one", "two", "three"}; + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: to define an array, one would use square brackets instead of curly braces +help: try using [] instead of {} + | +LL | const BAR: [&str; 3] = ["one", "two", "three"]; + | ~ ~ + +error: this code is interpreted as a block expression, not an array + --> $DIR/issue-87830-try-brackets-for-arrays.rs:11:5 + | +LL | {1, 2, 3}; + | ^^^^^^^^^ + | + = note: to define an array, one would use square brackets instead of curly braces +help: try using [] instead of {} + | +LL | [1, 2, 3]; + | ~ ~ + +error: expected one of `.`, `;`, `?`, `}`, or an operator, found `,` + --> $DIR/issue-87830-try-brackets-for-arrays.rs:16:6 + | +LL | 1, 2, 3 + | ^ expected one of `.`, `;`, `?`, `}`, or an operator + +error: aborting due to 4 previous errors + diff --git a/src/test/ui/did_you_mean/recursion_limit.stderr b/src/test/ui/did_you_mean/recursion_limit.stderr index fa8bee184a..247fe4b5b0 100644 --- a/src/test/ui/did_you_mean/recursion_limit.stderr +++ b/src/test/ui/did_you_mean/recursion_limit.stderr @@ -4,7 +4,7 @@ error[E0275]: overflow evaluating the requirement `K: Send` LL | is_send::(); | ^^^^^^^^^^^^ | - = help: consider adding a `#![recursion_limit="20"]` attribute to your crate (`recursion_limit`) + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "20"]` attribute to your crate (`recursion_limit`) note: required because it appears within the type `J` --> $DIR/recursion_limit.rs:24:9 | diff --git a/src/test/ui/did_you_mean/recursion_limit_deref.stderr b/src/test/ui/did_you_mean/recursion_limit_deref.stderr index 8339cc291c..658207a47c 100644 --- a/src/test/ui/did_you_mean/recursion_limit_deref.stderr +++ b/src/test/ui/did_you_mean/recursion_limit_deref.stderr @@ -4,7 +4,7 @@ error[E0055]: reached the recursion limit while auto-dereferencing `J` LL | let x: &Bottom = &t; | ^^ deref recursion limit reached | - = help: consider adding a `#![recursion_limit="20"]` attribute to your crate (`recursion_limit_deref`) + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "20"]` attribute to your crate (`recursion_limit_deref`) error[E0308]: mismatched types --> $DIR/recursion_limit_deref.rs:50:22 diff --git a/src/test/ui/did_you_mean/recursion_limit_macro.stderr b/src/test/ui/did_you_mean/recursion_limit_macro.stderr index 0c6fdebd50..71855cf1e2 100644 --- a/src/test/ui/did_you_mean/recursion_limit_macro.stderr +++ b/src/test/ui/did_you_mean/recursion_limit_macro.stderr @@ -5,9 +5,9 @@ LL | ($t:tt $($tail:tt)*) => { recurse!($($tail)*) }; | ^^^^^^^^^^^^^^^^^^^ ... LL | recurse!(0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9); - | -------------------------------------------------- in this macro invocation + | ------------------------------------------------- in this macro invocation | - = help: consider adding a `#![recursion_limit="20"]` attribute to your crate (`recursion_limit_macro`) + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "20"]` attribute to your crate (`recursion_limit_macro`) = note: this error originates in the macro `recurse` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to previous error diff --git a/src/test/ui/directory_ownership/macro-expanded-mod.stderr b/src/test/ui/directory_ownership/macro-expanded-mod.stderr index e1bba8b527..8976341b1a 100644 --- a/src/test/ui/directory_ownership/macro-expanded-mod.stderr +++ b/src/test/ui/directory_ownership/macro-expanded-mod.stderr @@ -5,7 +5,7 @@ LL | mod $i; | ^^^^^^^ ... LL | mod_decl!(foo); - | --------------- in this macro invocation + | -------------- in this macro invocation | = note: this error originates in the macro `mod_decl` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/discrim/discrim-ill-typed.stderr b/src/test/ui/discrim/discrim-ill-typed.stderr index 3d8049cba9..27f516341e 100644 --- a/src/test/ui/discrim/discrim-ill-typed.stderr +++ b/src/test/ui/discrim/discrim-ill-typed.stderr @@ -7,7 +7,7 @@ LL | OhNo = 0_u8, help: change the type of the numeric literal from `u8` to `i8` | LL | OhNo = 0_i8, - | ~~~~ + | ~~ error[E0308]: mismatched types --> $DIR/discrim-ill-typed.rs:28:16 @@ -18,7 +18,7 @@ LL | OhNo = 0_i8, help: change the type of the numeric literal from `i8` to `u8` | LL | OhNo = 0_u8, - | ~~~~ + | ~~ error[E0308]: mismatched types --> $DIR/discrim-ill-typed.rs:41:16 @@ -29,7 +29,7 @@ LL | OhNo = 0_u16, help: change the type of the numeric literal from `u16` to `i16` | LL | OhNo = 0_i16, - | ~~~~~ + | ~~~ error[E0308]: mismatched types --> $DIR/discrim-ill-typed.rs:54:16 @@ -40,7 +40,7 @@ LL | OhNo = 0_i16, help: change the type of the numeric literal from `i16` to `u16` | LL | OhNo = 0_u16, - | ~~~~~ + | ~~~ error[E0308]: mismatched types --> $DIR/discrim-ill-typed.rs:67:16 @@ -51,7 +51,7 @@ LL | OhNo = 0_u32, help: change the type of the numeric literal from `u32` to `i32` | LL | OhNo = 0_i32, - | ~~~~~ + | ~~~ error[E0308]: mismatched types --> $DIR/discrim-ill-typed.rs:80:16 @@ -62,7 +62,7 @@ LL | OhNo = 0_i32, help: change the type of the numeric literal from `i32` to `u32` | LL | OhNo = 0_u32, - | ~~~~~ + | ~~~ error[E0308]: mismatched types --> $DIR/discrim-ill-typed.rs:93:16 @@ -73,7 +73,7 @@ LL | OhNo = 0_u64, help: change the type of the numeric literal from `u64` to `i64` | LL | OhNo = 0_i64, - | ~~~~~ + | ~~~ error[E0308]: mismatched types --> $DIR/discrim-ill-typed.rs:106:16 @@ -84,7 +84,7 @@ LL | OhNo = 0_i64, help: change the type of the numeric literal from `i64` to `u64` | LL | OhNo = 0_u64, - | ~~~~~ + | ~~~ error: aborting due to 8 previous errors diff --git a/src/test/ui/dollar-crate/dollar-crate-is-keyword-2.stderr b/src/test/ui/dollar-crate/dollar-crate-is-keyword-2.stderr index b6df4cacf3..d46029710d 100644 --- a/src/test/ui/dollar-crate/dollar-crate-is-keyword-2.stderr +++ b/src/test/ui/dollar-crate/dollar-crate-is-keyword-2.stderr @@ -5,7 +5,7 @@ LL | use a::$crate::b; | ^^^^^^ `$crate` in paths can only be used in start position ... LL | m!(); - | ----- in this macro invocation + | ---- in this macro invocation | = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -16,7 +16,7 @@ LL | use a::$crate; | ^^^^^^^^^ no `$crate` in `a` ... LL | m!(); - | ----- in this macro invocation + | ---- in this macro invocation | = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -27,7 +27,7 @@ LL | type A = a::$crate; | ^^^^^^ `$crate` in paths can only be used in start position ... LL | m!(); - | ----- in this macro invocation + | ---- in this macro invocation | = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/dollar-crate/dollar-crate-is-keyword.stderr b/src/test/ui/dollar-crate/dollar-crate-is-keyword.stderr index 8e32be8976..b027822307 100644 --- a/src/test/ui/dollar-crate/dollar-crate-is-keyword.stderr +++ b/src/test/ui/dollar-crate/dollar-crate-is-keyword.stderr @@ -5,7 +5,7 @@ LL | struct $crate {} | ^^^^^^ expected identifier, found reserved identifier ... LL | m!(); - | ----- in this macro invocation + | ---- in this macro invocation | = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -16,7 +16,7 @@ LL | use $crate as $crate; | ^^^^^^ expected identifier, found reserved identifier ... LL | m!(); - | ----- in this macro invocation + | ---- in this macro invocation | = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -27,7 +27,7 @@ LL | use $crate; | ^^^^^^^^^^^ ... LL | m!(); - | ----- in this macro invocation + | ---- in this macro invocation | = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -38,7 +38,7 @@ LL | use $crate as $crate; | ^^^^^^^^^^^^^^^^^^^^^ ... LL | m!(); - | ----- in this macro invocation + | ---- in this macro invocation | = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/drop/drop-on-empty-block-exit.rs b/src/test/ui/drop/drop-on-empty-block-exit.rs index 1747bf029a..ef3a90a53a 100644 --- a/src/test/ui/drop/drop-on-empty-block-exit.rs +++ b/src/test/ui/drop/drop-on-empty-block-exit.rs @@ -2,11 +2,9 @@ // pretty-expanded FIXME #23616 #![allow(non_camel_case_types)] -#![feature(box_syntax)] - enum t { foo(Box), } pub fn main() { - let tt = t::foo(box 10); + let tt = t::foo(Box::new(10)); match tt { t::foo(_z) => { } } } diff --git a/src/test/ui/drop/drop-struct-as-object.rs b/src/test/ui/drop/drop-struct-as-object.rs index 1bc3b4c157..377027a4fc 100644 --- a/src/test/ui/drop/drop-struct-as-object.rs +++ b/src/test/ui/drop/drop-struct-as-object.rs @@ -5,8 +5,6 @@ // Test that destructor on a struct runs successfully after the struct // is boxed and converted to an object. -#![feature(box_syntax)] - static mut value: usize = 0; struct Cat { @@ -29,7 +27,7 @@ impl Drop for Cat { pub fn main() { { - let x = box Cat {name: 22}; + let x = Box::new(Cat {name: 22}); let nyan: Box = x as Box; } unsafe { diff --git a/src/test/ui/drop/drop-trait-enum.rs b/src/test/ui/drop/drop-trait-enum.rs index aec46575f9..4ab8f733ad 100644 --- a/src/test/ui/drop/drop-trait-enum.rs +++ b/src/test/ui/drop/drop-trait-enum.rs @@ -4,8 +4,6 @@ #![allow(unused_variables)] // ignore-emscripten no threads support -#![feature(box_syntax)] - use std::thread; use std::sync::mpsc::{channel, Sender}; @@ -57,7 +55,7 @@ pub fn main() { let (sender, receiver) = channel(); { - let v = Foo::NestedVariant(box 42, SendOnDrop { sender: sender.clone() }, sender); + let v = Foo::NestedVariant(Box::new(42), SendOnDrop { sender: sender.clone() }, sender); } assert_eq!(receiver.recv().unwrap(), Message::DestructorRan); assert_eq!(receiver.recv().unwrap(), Message::Dropped); @@ -74,10 +72,10 @@ pub fn main() { let (sender, receiver) = channel(); let t = { thread::spawn(move|| { - let mut v = Foo::NestedVariant(box 42, SendOnDrop { + let mut v = Foo::NestedVariant(Box::new(42), SendOnDrop { sender: sender.clone() }, sender.clone()); - v = Foo::NestedVariant(box 42, + v = Foo::NestedVariant(Box::new(42), SendOnDrop { sender: sender.clone() }, sender.clone()); v = Foo::SimpleVariant(sender.clone()); diff --git a/src/test/ui/dropck/drop-with-active-borrows-1.stderr b/src/test/ui/dropck/drop-with-active-borrows-1.stderr index 7fed27adaf..8d6a7f3721 100644 --- a/src/test/ui/dropck/drop-with-active-borrows-1.stderr +++ b/src/test/ui/dropck/drop-with-active-borrows-1.stderr @@ -2,7 +2,7 @@ error[E0505]: cannot move out of `a` because it is borrowed --> $DIR/drop-with-active-borrows-1.rs:4:10 | LL | let b: Vec<&str> = a.lines().collect(); - | - borrow of `a` occurs here + | --------- borrow of `a` occurs here LL | drop(a); | ^ move out of `a` occurs here LL | for s in &b { diff --git a/src/test/ui/dropck/drop-with-active-borrows-2.stderr b/src/test/ui/dropck/drop-with-active-borrows-2.stderr index ffec9306b7..24650dfac0 100644 --- a/src/test/ui/dropck/drop-with-active-borrows-2.stderr +++ b/src/test/ui/dropck/drop-with-active-borrows-2.stderr @@ -2,7 +2,7 @@ error[E0515]: cannot return value referencing local variable `raw_lines` --> $DIR/drop-with-active-borrows-2.rs:3:5 | LL | raw_lines.iter().map(|l| l.trim()).collect() - | ---------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ----------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | | returns a value referencing data owned by the current function | `raw_lines` is borrowed here diff --git a/src/test/ui/dropck/reject-specialized-drops-8142.stderr b/src/test/ui/dropck/reject-specialized-drops-8142.stderr index cb4d97a8b2..8dbde9d417 100644 --- a/src/test/ui/dropck/reject-specialized-drops-8142.stderr +++ b/src/test/ui/dropck/reject-specialized-drops-8142.stderr @@ -30,7 +30,7 @@ LL | impl Drop for N<'static> { fn drop(&mut self) { } } | = note: expected struct `N<'n>` found struct `N<'static>` -note: the lifetime `'n` as defined on the struct at 7:10... +note: the lifetime `'n` as defined here... --> $DIR/reject-specialized-drops-8142.rs:7:10 | LL | struct N<'n> { x: &'n i8 } @@ -91,12 +91,12 @@ error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'lw` LL | impl<'lw> Drop for W<'lw,'lw> { fn drop(&mut self) { } } // REJECT | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: first, the lifetime cannot outlive the lifetime `'l1` as defined on the struct at 16:10... +note: first, the lifetime cannot outlive the lifetime `'l1` as defined here... --> $DIR/reject-specialized-drops-8142.rs:16:10 | LL | struct W<'l1, 'l2> { x: &'l1 i8, y: &'l2 u8 } | ^^^ -note: ...but the lifetime must also be valid for the lifetime `'l2` as defined on the struct at 16:15... +note: ...but the lifetime must also be valid for the lifetime `'l2` as defined here... --> $DIR/reject-specialized-drops-8142.rs:16:15 | LL | struct W<'l1, 'l2> { x: &'l1 i8, y: &'l2 u8 } diff --git a/src/test/ui/dropck/relate_lt_in_type_outlives_bound.rs b/src/test/ui/dropck/relate_lt_in_type_outlives_bound.rs new file mode 100644 index 0000000000..42530d3173 --- /dev/null +++ b/src/test/ui/dropck/relate_lt_in_type_outlives_bound.rs @@ -0,0 +1,13 @@ +struct Wrapper<'a, T>(&'a T) +where + T: 'a; + +impl<'a, T> Drop for Wrapper<'a, T> +where + T: 'static, + //~^ error: `Drop` impl requires `T: 'static` but the struct it is implemented for does not +{ + fn drop(&mut self) {} +} + +fn main() {} diff --git a/src/test/ui/dropck/relate_lt_in_type_outlives_bound.stderr b/src/test/ui/dropck/relate_lt_in_type_outlives_bound.stderr new file mode 100644 index 0000000000..5176684e15 --- /dev/null +++ b/src/test/ui/dropck/relate_lt_in_type_outlives_bound.stderr @@ -0,0 +1,17 @@ +error[E0367]: `Drop` impl requires `T: 'static` but the struct it is implemented for does not + --> $DIR/relate_lt_in_type_outlives_bound.rs:7:8 + | +LL | T: 'static, + | ^^^^^^^ + | +note: the implementor must specify the same requirement + --> $DIR/relate_lt_in_type_outlives_bound.rs:1:1 + | +LL | / struct Wrapper<'a, T>(&'a T) +LL | | where +LL | | T: 'a; + | |__________^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0367`. diff --git a/src/test/ui/dst/dst-bad-coercions.stderr b/src/test/ui/dst/dst-bad-coercions.stderr index 3e23c5f5c7..01f862ed51 100644 --- a/src/test/ui/dst/dst-bad-coercions.stderr +++ b/src/test/ui/dst/dst-bad-coercions.stderr @@ -13,10 +13,8 @@ error[E0308]: mismatched types --> $DIR/dst-bad-coercions.rs:15:21 | LL | let y: &dyn T = x; - | ------ ^ - | | | - | | expected `&dyn T`, found *-ptr - | | help: consider borrowing here: `&x` + | ------ ^ expected `&dyn T`, found *-ptr + | | | expected due to this | = note: expected reference `&dyn T` @@ -37,10 +35,8 @@ error[E0308]: mismatched types --> $DIR/dst-bad-coercions.rs:20:21 | LL | let y: &dyn T = x; - | ------ ^ - | | | - | | expected `&dyn T`, found *-ptr - | | help: consider borrowing here: `&x` + | ------ ^ expected `&dyn T`, found *-ptr + | | | expected due to this | = note: expected reference `&dyn T` diff --git a/src/test/ui/duplicate_doc_alias.rs b/src/test/ui/duplicate_doc_alias.rs new file mode 100644 index 0000000000..a564ab6453 --- /dev/null +++ b/src/test/ui/duplicate_doc_alias.rs @@ -0,0 +1,9 @@ +#![deny(unused_attributes)] + +#[doc(alias = "A")] +#[doc(alias = "A")] //~ ERROR +#[doc(alias = "B")] +#[doc(alias("B"))] //~ ERROR +pub struct Foo; + +fn main() {} diff --git a/src/test/ui/duplicate_doc_alias.stderr b/src/test/ui/duplicate_doc_alias.stderr new file mode 100644 index 0000000000..4b2dd1f8eb --- /dev/null +++ b/src/test/ui/duplicate_doc_alias.stderr @@ -0,0 +1,24 @@ +error: doc alias is duplicated + --> $DIR/duplicate_doc_alias.rs:4:7 + | +LL | #[doc(alias = "A")] + | ----------- first defined here +LL | #[doc(alias = "A")] + | ^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/duplicate_doc_alias.rs:1:9 + | +LL | #![deny(unused_attributes)] + | ^^^^^^^^^^^^^^^^^ + +error: doc alias is duplicated + --> $DIR/duplicate_doc_alias.rs:6:13 + | +LL | #[doc(alias = "B")] + | ----------- first defined here +LL | #[doc(alias("B"))] + | ^^^ + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/dynamically-sized-types/dst-trait-tuple.rs b/src/test/ui/dynamically-sized-types/dst-trait-tuple.rs index 70bcc3de07..c1e45215ad 100644 --- a/src/test/ui/dynamically-sized-types/dst-trait-tuple.rs +++ b/src/test/ui/dynamically-sized-types/dst-trait-tuple.rs @@ -2,7 +2,6 @@ #![allow(type_alias_bounds)] #![allow(unused_features)] -#![feature(box_syntax)] #![feature(unsized_tuple_coercion)] type Fat = (isize, &'static str, T); diff --git a/src/test/ui/dynamically-sized-types/dst-tuple.rs b/src/test/ui/dynamically-sized-types/dst-tuple.rs index f70a45a1b3..604ac51129 100644 --- a/src/test/ui/dynamically-sized-types/dst-tuple.rs +++ b/src/test/ui/dynamically-sized-types/dst-tuple.rs @@ -1,7 +1,6 @@ // run-pass #![allow(type_alias_bounds)] -#![feature(box_syntax)] #![feature(unsized_tuple_coercion)] type Fat = (isize, &'static str, T); @@ -109,7 +108,7 @@ pub fn main() { assert_eq!((*f2)[1], 2); // Nested Box. - let f1 : Box> = box (5, "some str", [1, 2, 3]); + let f1 : Box> = Box::new((5, "some str", [1, 2, 3])); foo(&*f1); let f2 : Box> = f1; foo(&*f2); diff --git a/src/test/ui/editions/edition-imports-2015.stderr b/src/test/ui/editions/edition-imports-2015.stderr index 2b4eb815b7..3f38e6f8e8 100644 --- a/src/test/ui/editions/edition-imports-2015.stderr +++ b/src/test/ui/editions/edition-imports-2015.stderr @@ -2,7 +2,7 @@ error: cannot glob-import all possible crates --> $DIR/edition-imports-2015.rs:23:5 | LL | gen_glob!(); - | ^^^^^^^^^^^^ + | ^^^^^^^^^^^ | = note: this error originates in the macro `gen_glob` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/editions/edition-imports-2018.stderr b/src/test/ui/editions/edition-imports-2018.stderr index 1a304ebe9a..e7f760e49b 100644 --- a/src/test/ui/editions/edition-imports-2018.stderr +++ b/src/test/ui/editions/edition-imports-2018.stderr @@ -2,7 +2,7 @@ error: cannot glob-import all possible crates --> $DIR/edition-imports-2018.rs:24:5 | LL | gen_glob!(); - | ^^^^^^^^^^^^ + | ^^^^^^^^^^^ | = note: this error originates in the macro `gen_glob` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/editions/edition-imports-virtual-2015-gated.stderr b/src/test/ui/editions/edition-imports-virtual-2015-gated.stderr index 9ca7514d3a..e4bdd28213 100644 --- a/src/test/ui/editions/edition-imports-virtual-2015-gated.stderr +++ b/src/test/ui/editions/edition-imports-virtual-2015-gated.stderr @@ -2,7 +2,7 @@ error[E0432]: unresolved import `E` --> $DIR/edition-imports-virtual-2015-gated.rs:8:5 | LL | gen_gated!(); - | ^^^^^^^^^^^^^ could not find `E` in the list of imported crates + | ^^^^^^^^^^^^ could not find `E` in the list of imported crates | = note: this error originates in the macro `gen_gated` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/empty/empty-comment.stderr b/src/test/ui/empty/empty-comment.stderr index 116cc83fa9..f583dbbdc6 100644 --- a/src/test/ui/empty/empty-comment.stderr +++ b/src/test/ui/empty/empty-comment.stderr @@ -5,7 +5,7 @@ LL | macro_rules! one_arg_macro { | -------------------------- when calling this macro ... LL | one_arg_macro!(/**/); - | ^^^^^^^^^^^^^^^^^^^^^ missing tokens in macro arguments + | ^^^^^^^^^^^^^^^^^^^^ missing tokens in macro arguments error: aborting due to previous error diff --git a/src/test/ui/enum-discriminant/discriminant_value-wrapper.rs b/src/test/ui/enum-discriminant/discriminant_value-wrapper.rs index daef2de87a..65dc916633 100644 --- a/src/test/ui/enum-discriminant/discriminant_value-wrapper.rs +++ b/src/test/ui/enum-discriminant/discriminant_value-wrapper.rs @@ -1,4 +1,7 @@ // run-pass + +#![allow(enum_intrinsics_non_enums)] + use std::mem; enum ADT { diff --git a/src/test/ui/enum-discriminant/issue-90038.rs b/src/test/ui/enum-discriminant/issue-90038.rs new file mode 100644 index 0000000000..5e98eccd9b --- /dev/null +++ b/src/test/ui/enum-discriminant/issue-90038.rs @@ -0,0 +1,21 @@ +// run-pass + +#[repr(u32)] +pub enum Foo { + // Greater than or equal to 2 + A = 2, +} + +pub enum Bar { + A(Foo), + // More than two const variants + B, + C, +} + +fn main() { + match Bar::A(Foo::A) { + Bar::A(_) => (), + _ => unreachable!(), + } +} diff --git a/src/test/ui/enum-discriminant/niche-prefer-zero.rs b/src/test/ui/enum-discriminant/niche-prefer-zero.rs new file mode 100644 index 0000000000..f20607a890 --- /dev/null +++ b/src/test/ui/enum-discriminant/niche-prefer-zero.rs @@ -0,0 +1,14 @@ +// Check that niche selection prefers zero. +// See https://github.com/rust-lang/rust/pull/87794 +// run-pass +#[repr(u8)] +pub enum Size { + One = 1, + Two = 2, + Three = 3, +} + +fn main() { + // check that `None` is zero + assert_eq!(0, unsafe { std::mem::transmute::, u8>(None) }); +} diff --git a/src/test/ui/enum-discriminant/niche.rs b/src/test/ui/enum-discriminant/niche.rs index b3694bb421..8d30610504 100644 --- a/src/test/ui/enum-discriminant/niche.rs +++ b/src/test/ui/enum-discriminant/niche.rs @@ -1,7 +1,5 @@ // run-pass -#![feature(const_panic)] - //! Make sure that we read and write enum discriminants correctly for corner cases caused //! by layout optimizations. diff --git a/src/test/ui/error-codes/E0034.stderr b/src/test/ui/error-codes/E0034.stderr index 83718a1e27..e296217026 100644 --- a/src/test/ui/error-codes/E0034.stderr +++ b/src/test/ui/error-codes/E0034.stderr @@ -16,12 +16,12 @@ LL | fn foo() {} | ^^^^^^^^ help: disambiguate the associated function for candidate #1 | -LL | Trait1::foo() - | ~~~~~~~~ +LL | ::foo() + | ~~~~~~~~~~~~~~~~~~ help: disambiguate the associated function for candidate #2 | -LL | Trait2::foo() - | ~~~~~~~~ +LL | ::foo() + | ~~~~~~~~~~~~~~~~~~ error: aborting due to previous error diff --git a/src/test/ui/error-codes/E0038.stderr b/src/test/ui/error-codes/E0038.stderr index cead9776e4..3773d6f523 100644 --- a/src/test/ui/error-codes/E0038.stderr +++ b/src/test/ui/error-codes/E0038.stderr @@ -4,7 +4,6 @@ error[E0038]: the trait `Trait` cannot be made into an object LL | fn call_foo(x: Box) { | ^^^^^^^^^ `Trait` cannot be made into an object | - = help: consider moving `foo` to another trait note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit --> $DIR/E0038.rs:2:22 | @@ -12,6 +11,7 @@ LL | trait Trait { | ----- this trait cannot be made into an object... LL | fn foo(&self) -> Self; | ^^^^ ...because method `foo` references the `Self` type in its return type + = help: consider moving `foo` to another trait error: aborting due to previous error diff --git a/src/test/ui/error-codes/E0055.stderr b/src/test/ui/error-codes/E0055.stderr index 1b8c5760e6..a52c909623 100644 --- a/src/test/ui/error-codes/E0055.stderr +++ b/src/test/ui/error-codes/E0055.stderr @@ -4,7 +4,7 @@ error[E0055]: reached the recursion limit while auto-dereferencing `Foo` LL | ref_foo.foo(); | ^^^ deref recursion limit reached | - = help: consider adding a `#![recursion_limit="8"]` attribute to your crate (`E0055`) + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "8"]` attribute to your crate (`E0055`) error: aborting due to previous error diff --git a/src/test/ui/error-codes/E0161.edition.stderr b/src/test/ui/error-codes/E0161.edition.stderr index 6beb29c57d..1060675cd4 100644 --- a/src/test/ui/error-codes/E0161.edition.stderr +++ b/src/test/ui/error-codes/E0161.edition.stderr @@ -2,7 +2,7 @@ error[E0161]: cannot move a value of type dyn Bar: the size of dyn Bar cannot be --> $DIR/E0161.rs:29:5 | LL | x.f(); - | ^ + | ^^^^^ error: aborting due to previous error diff --git a/src/test/ui/error-codes/E0161.migrate.stderr b/src/test/ui/error-codes/E0161.migrate.stderr index 6beb29c57d..1060675cd4 100644 --- a/src/test/ui/error-codes/E0161.migrate.stderr +++ b/src/test/ui/error-codes/E0161.migrate.stderr @@ -2,7 +2,7 @@ error[E0161]: cannot move a value of type dyn Bar: the size of dyn Bar cannot be --> $DIR/E0161.rs:29:5 | LL | x.f(); - | ^ + | ^^^^^ error: aborting due to previous error diff --git a/src/test/ui/error-codes/E0161.nll.stderr b/src/test/ui/error-codes/E0161.nll.stderr index 6beb29c57d..1060675cd4 100644 --- a/src/test/ui/error-codes/E0161.nll.stderr +++ b/src/test/ui/error-codes/E0161.nll.stderr @@ -2,7 +2,7 @@ error[E0161]: cannot move a value of type dyn Bar: the size of dyn Bar cannot be --> $DIR/E0161.rs:29:5 | LL | x.f(); - | ^ + | ^^^^^ error: aborting due to previous error diff --git a/src/test/ui/error-codes/E0161.zflags.stderr b/src/test/ui/error-codes/E0161.zflags.stderr index 6beb29c57d..1060675cd4 100644 --- a/src/test/ui/error-codes/E0161.zflags.stderr +++ b/src/test/ui/error-codes/E0161.zflags.stderr @@ -2,7 +2,7 @@ error[E0161]: cannot move a value of type dyn Bar: the size of dyn Bar cannot be --> $DIR/E0161.rs:29:5 | LL | x.f(); - | ^ + | ^^^^^ error: aborting due to previous error diff --git a/src/test/ui/error-codes/E0221.stderr b/src/test/ui/error-codes/E0221.stderr index 86966d520e..f3dbf122de 100644 --- a/src/test/ui/error-codes/E0221.stderr +++ b/src/test/ui/error-codes/E0221.stderr @@ -13,11 +13,11 @@ LL | let _: Self::A; help: use fully qualified syntax to disambiguate | LL | let _: ::A; - | ~~~~~~~~~~~~~~~~ + | ~~~~~~~~~~~~~~~ help: use fully qualified syntax to disambiguate | LL | let _: ::A; - | ~~~~~~~~~~~~~~~~ + | ~~~~~~~~~~~~~~~ error[E0221]: ambiguous associated type `Err` in bounds of `Self` --> $DIR/E0221.rs:21:16 @@ -26,12 +26,13 @@ LL | type Err: T3; | ------------- ambiguous `Err` from `My` LL | fn test() { LL | let _: Self::Err; - | ^^^^^^^^^ - | | - | ambiguous associated type `Err` - | help: use fully qualified syntax to disambiguate: `::Err` + | ^^^^^^^^^ ambiguous associated type `Err` | = note: associated type `Self` could derive from `FromStr` +help: use fully qualified syntax to disambiguate + | +LL | let _: ::Err; + | ~~~~~~~~~~~~~~ error: aborting due to 2 previous errors diff --git a/src/test/ui/error-codes/E0225.stderr b/src/test/ui/error-codes/E0225.stderr index 435a2c9396..a4b33a0b7b 100644 --- a/src/test/ui/error-codes/E0225.stderr +++ b/src/test/ui/error-codes/E0225.stderr @@ -6,7 +6,7 @@ LL | let _: Box; | | | first non-auto trait | - = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: std::io::Read + std::io::Write {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: std::io::Read + std::io::Write {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error[E0225]: only auto traits can be used as additional traits in a trait object @@ -23,7 +23,7 @@ LL | let _: Box; | trait alias used in trait object type (additional use) | trait alias used in trait object type (first use) | - = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: std::io::Read + std::io::Write {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: std::io::Read + std::io::Write {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error: aborting due to 2 previous errors diff --git a/src/test/ui/error-codes/E0275.stderr b/src/test/ui/error-codes/E0275.stderr index 15d851aa93..e13f0961a1 100644 --- a/src/test/ui/error-codes/E0275.stderr +++ b/src/test/ui/error-codes/E0275.stderr @@ -4,7 +4,7 @@ error[E0275]: overflow evaluating the requirement `Bar Foo for T where Bar: Foo {} | ^^^ | - = help: consider adding a `#![recursion_limit="256"]` attribute to your crate (`E0275`) + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`E0275`) note: required because of the requirements on the impl of `Foo` for `Bar>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` --> $DIR/E0275.rs:5:9 | diff --git a/src/test/ui/error-codes/E0277.stderr b/src/test/ui/error-codes/E0277.stderr index c82665aa58..2b4784d7ec 100644 --- a/src/test/ui/error-codes/E0277.stderr +++ b/src/test/ui/error-codes/E0277.stderr @@ -16,7 +16,9 @@ error[E0277]: the trait bound `i32: Foo` is not satisfied --> $DIR/E0277.rs:15:15 | LL | some_func(5i32); - | ^^^^ the trait `Foo` is not implemented for `i32` + | --------- ^^^^ the trait `Foo` is not implemented for `i32` + | | + | required by a bound introduced by this call | note: required by a bound in `some_func` --> $DIR/E0277.rs:7:17 diff --git a/src/test/ui/error-codes/E0308-2.stderr b/src/test/ui/error-codes/E0308-2.stderr index 47fea5a23a..5c1dcb4d4f 100644 --- a/src/test/ui/error-codes/E0308-2.stderr +++ b/src/test/ui/error-codes/E0308-2.stderr @@ -4,9 +4,9 @@ error[E0308]: mismatched types LL | impl Eq for &dyn DynEq {} | ^^ lifetime mismatch | - = note: expected trait `PartialEq` - found trait `PartialEq` -note: the lifetime `'_` as defined on the impl at 9:13... + = note: expected trait `<&dyn DynEq as PartialEq>` + found trait `<&(dyn DynEq + 'static) as PartialEq>` +note: the lifetime `'_` as defined here... --> $DIR/E0308-2.rs:9:13 | LL | impl Eq for &dyn DynEq {} diff --git a/src/test/ui/error-codes/E0395.stderr b/src/test/ui/error-codes/E0395.stderr index 674cc69645..ea17e95a71 100644 --- a/src/test/ui/error-codes/E0395.stderr +++ b/src/test/ui/error-codes/E0395.stderr @@ -1,4 +1,4 @@ -error: pointers cannot be reliably compared during const eval. +error: pointers cannot be reliably compared during const eval --> $DIR/E0395.rs:4:29 | LL | static BAZ: bool = unsafe { (&FOO as *const i32) == (&BAR as *const i32) }; diff --git a/src/test/ui/error-codes/E0407.stderr b/src/test/ui/error-codes/E0407.stderr index 567fc87904..6f6d1ff6a8 100644 --- a/src/test/ui/error-codes/E0407.stderr +++ b/src/test/ui/error-codes/E0407.stderr @@ -2,7 +2,10 @@ error[E0407]: method `b` is not a member of trait `Foo` --> $DIR/E0407.rs:9:5 | LL | fn b() {} - | ^^^^^^^^^ not a member of trait `Foo` + | ^^^-^^^^^ + | | | + | | help: there is an associated function with a similar name: `a` + | not a member of trait `Foo` error: aborting due to previous error diff --git a/src/test/ui/error-codes/E0439.rs b/src/test/ui/error-codes/E0439.rs deleted file mode 100644 index 86e9cb55a9..0000000000 --- a/src/test/ui/error-codes/E0439.rs +++ /dev/null @@ -1,8 +0,0 @@ -#![feature(platform_intrinsics)] - -extern "platform-intrinsic" { - fn simd_shuffle(a: A, b: A, c: [u32; 8]) -> B; //~ ERROR E0439 -} - -fn main () { -} diff --git a/src/test/ui/error-codes/E0439.stderr b/src/test/ui/error-codes/E0439.stderr deleted file mode 100644 index 8021f7d395..0000000000 --- a/src/test/ui/error-codes/E0439.stderr +++ /dev/null @@ -1,9 +0,0 @@ -error[E0439]: invalid `simd_shuffle`, needs length: `simd_shuffle` - --> $DIR/E0439.rs:4:5 - | -LL | fn simd_shuffle(a: A, b: A, c: [u32; 8]) -> B; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0439`. diff --git a/src/test/ui/error-codes/E0464.rs b/src/test/ui/error-codes/E0464.rs new file mode 100644 index 0000000000..969115a7d9 --- /dev/null +++ b/src/test/ui/error-codes/E0464.rs @@ -0,0 +1,15 @@ +// aux-build:crateresolve1-1.rs +// aux-build:crateresolve1-2.rs +// aux-build:crateresolve1-3.rs + +// normalize-stderr-test: "\.nll/" -> "/" +// normalize-stderr-test: "\\\?\\" -> "" +// normalize-stderr-test: "(lib)?crateresolve1-([123])\.[a-z]+" -> "libcrateresolve1-$2.somelib" + +// NOTE: This test is duplicated from `src/test/ui/crate-loading/crateresolve1.rs`. + +extern crate crateresolve1; +//~^ ERROR multiple matching crates for `crateresolve1` + +fn main() { +} diff --git a/src/test/ui/error-codes/E0464.stderr b/src/test/ui/error-codes/E0464.stderr new file mode 100644 index 0000000000..3d950ddd28 --- /dev/null +++ b/src/test/ui/error-codes/E0464.stderr @@ -0,0 +1,14 @@ +error[E0464]: multiple matching crates for `crateresolve1` + --> $DIR/E0464.rs:11:1 + | +LL | extern crate crateresolve1; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: candidates: + crate `crateresolve1`: $TEST_BUILD_DIR/error-codes/E0464/auxiliary/libcrateresolve1-1.somelib + crate `crateresolve1`: $TEST_BUILD_DIR/error-codes/E0464/auxiliary/libcrateresolve1-2.somelib + crate `crateresolve1`: $TEST_BUILD_DIR/error-codes/E0464/auxiliary/libcrateresolve1-3.somelib + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0464`. diff --git a/src/test/ui/error-codes/E0478.stderr b/src/test/ui/error-codes/E0478.stderr index 38736de8d9..ec650085a2 100644 --- a/src/test/ui/error-codes/E0478.stderr +++ b/src/test/ui/error-codes/E0478.stderr @@ -4,12 +4,12 @@ error[E0478]: lifetime bound not satisfied LL | child: Box + 'SnowWhite>, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: lifetime parameter instantiated with the lifetime `'SnowWhite` as defined on the struct at 3:22 +note: lifetime parameter instantiated with the lifetime `'SnowWhite` as defined here --> $DIR/E0478.rs:3:22 | LL | struct Prince<'kiss, 'SnowWhite> { | ^^^^^^^^^^ -note: but lifetime parameter must outlive the lifetime `'kiss` as defined on the struct at 3:15 +note: but lifetime parameter must outlive the lifetime `'kiss` as defined here --> $DIR/E0478.rs:3:15 | LL | struct Prince<'kiss, 'SnowWhite> { diff --git a/src/test/ui/error-codes/E0490.stderr b/src/test/ui/error-codes/E0490.stderr index 9ba5bc330e..96e99bd88a 100644 --- a/src/test/ui/error-codes/E0490.stderr +++ b/src/test/ui/error-codes/E0490.stderr @@ -4,12 +4,12 @@ error[E0490]: a value of type `&'b ()` is borrowed for too long LL | let x: &'a _ = &y; | ^^ | -note: the type is valid for the lifetime `'a` as defined on the function body at 1:6 +note: the type is valid for the lifetime `'a` as defined here --> $DIR/E0490.rs:1:6 | LL | fn f<'a, 'b>(y: &'b ()) { | ^^ -note: but the borrow lasts for the lifetime `'b` as defined on the function body at 1:10 +note: but the borrow lasts for the lifetime `'b` as defined here --> $DIR/E0490.rs:1:10 | LL | fn f<'a, 'b>(y: &'b ()) { @@ -21,7 +21,7 @@ error[E0495]: cannot infer an appropriate lifetime for borrow expression due to LL | let x: &'a _ = &y; | ^^ | -note: first, the lifetime cannot outlive the lifetime `'b` as defined on the function body at 1:10... +note: first, the lifetime cannot outlive the lifetime `'b` as defined here... --> $DIR/E0490.rs:1:10 | LL | fn f<'a, 'b>(y: &'b ()) { @@ -31,7 +31,7 @@ note: ...so that the type `&'b ()` is not borrowed for too long | LL | let x: &'a _ = &y; | ^^ -note: but, the lifetime must be valid for the lifetime `'a` as defined on the function body at 1:6... +note: but, the lifetime must be valid for the lifetime `'a` as defined here... --> $DIR/E0490.rs:1:6 | LL | fn f<'a, 'b>(y: &'b ()) { @@ -48,7 +48,7 @@ error[E0495]: cannot infer an appropriate lifetime due to conflicting requiremen LL | let x: &'a _ = &y; | ^^ | -note: first, the lifetime cannot outlive the lifetime `'b` as defined on the function body at 1:10... +note: first, the lifetime cannot outlive the lifetime `'b` as defined here... --> $DIR/E0490.rs:1:10 | LL | fn f<'a, 'b>(y: &'b ()) { @@ -60,7 +60,7 @@ LL | let x: &'a _ = &y; | ^^ = note: expected `&'a &()` found `&'a &'b ()` -note: but, the lifetime must be valid for the lifetime `'a` as defined on the function body at 1:6... +note: but, the lifetime must be valid for the lifetime `'a` as defined here... --> $DIR/E0490.rs:1:6 | LL | fn f<'a, 'b>(y: &'b ()) { diff --git a/src/test/ui/error-codes/E0499.stderr b/src/test/ui/error-codes/E0499.stderr index d56baf7227..af5a1e1863 100644 --- a/src/test/ui/error-codes/E0499.stderr +++ b/src/test/ui/error-codes/E0499.stderr @@ -7,7 +7,7 @@ LL | let mut a = &mut i; | ^^^^^^ second mutable borrow occurs here LL | a.use_mut(); LL | x.use_mut(); - | - first borrow later used here + | ----------- first borrow later used here error: aborting due to previous error diff --git a/src/test/ui/error-codes/E0502.nll.stderr b/src/test/ui/error-codes/E0502.nll.stderr index e5671ee49e..a3c7ef7618 100644 --- a/src/test/ui/error-codes/E0502.nll.stderr +++ b/src/test/ui/error-codes/E0502.nll.stderr @@ -6,7 +6,7 @@ LL | let ref y = a; LL | bar(a); | ^ mutable borrow occurs here LL | y.use_ref(); - | - immutable borrow later used here + | ----------- immutable borrow later used here error: aborting due to previous error diff --git a/src/test/ui/error-codes/E0502.stderr b/src/test/ui/error-codes/E0502.stderr index cade6d7185..94cc89754d 100644 --- a/src/test/ui/error-codes/E0502.stderr +++ b/src/test/ui/error-codes/E0502.stderr @@ -6,7 +6,7 @@ LL | let ref y = a; LL | bar(a); | ^^^^^^ mutable borrow occurs here LL | y.use_ref(); - | - immutable borrow later used here + | ----------- immutable borrow later used here error: aborting due to previous error diff --git a/src/test/ui/error-codes/E0503.stderr b/src/test/ui/error-codes/E0503.stderr index 106dda2bc2..fafe363eb4 100644 --- a/src/test/ui/error-codes/E0503.stderr +++ b/src/test/ui/error-codes/E0503.stderr @@ -6,7 +6,7 @@ LL | let _borrow = &mut value; LL | let _sum = value + 1; | ^^^^^ use of borrowed `value` LL | _borrow.use_mut(); - | ------- borrow later used here + | ----------------- borrow later used here error: aborting due to previous error diff --git a/src/test/ui/error-codes/E0505.stderr b/src/test/ui/error-codes/E0505.stderr index 4d9d1ef121..bd3f37f54e 100644 --- a/src/test/ui/error-codes/E0505.stderr +++ b/src/test/ui/error-codes/E0505.stderr @@ -6,7 +6,7 @@ LL | let _ref_to_val: &Value = &x; LL | eat(x); | ^ move out of `x` occurs here LL | _ref_to_val.use_ref(); - | ----------- borrow later used here + | --------------------- borrow later used here error: aborting due to previous error diff --git a/src/test/ui/error-codes/E0507.stderr b/src/test/ui/error-codes/E0507.stderr index cd5e467944..3837e20616 100644 --- a/src/test/ui/error-codes/E0507.stderr +++ b/src/test/ui/error-codes/E0507.stderr @@ -2,7 +2,7 @@ error[E0507]: cannot move out of dereference of `Ref<'_, TheDarkKnight>` --> $DIR/E0507.rs:12:5 | LL | x.borrow().nothing_is_true(); - | ^^^^^^^^^^ move occurs because value has type `TheDarkKnight`, which does not implement the `Copy` trait + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ move occurs because value has type `TheDarkKnight`, which does not implement the `Copy` trait error: aborting due to previous error diff --git a/src/test/ui/error-codes/E0605.stderr b/src/test/ui/error-codes/E0605.stderr index e5647ee6d0..d082b6c10c 100644 --- a/src/test/ui/error-codes/E0605.stderr +++ b/src/test/ui/error-codes/E0605.stderr @@ -12,8 +12,9 @@ LL | v as &u8; | help: consider borrowing the value | -LL | &*v as &u8; - | ++ +LL - v as &u8; +LL + &*v; + | error: aborting due to 2 previous errors diff --git a/src/test/ui/error-codes/E0660.stderr b/src/test/ui/error-codes/E0660.stderr index f8d0cb27a3..d9d2f35251 100644 --- a/src/test/ui/error-codes/E0660.stderr +++ b/src/test/ui/error-codes/E0660.stderr @@ -2,13 +2,13 @@ error[E0660]: malformed inline assembly --> $DIR/E0660.rs:6:5 | LL | llvm_asm!("nop" "nop"); - | ^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^ error[E0660]: malformed inline assembly --> $DIR/E0660.rs:8:5 | LL | llvm_asm!("nop" "nop" : "=r"(a)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/error-codes/auxiliary/crateresolve1-1.rs b/src/test/ui/error-codes/auxiliary/crateresolve1-1.rs new file mode 100644 index 0000000000..a00a19e46d --- /dev/null +++ b/src/test/ui/error-codes/auxiliary/crateresolve1-1.rs @@ -0,0 +1,5 @@ +// compile-flags:-C extra-filename=-1 +#![crate_name = "crateresolve1"] +#![crate_type = "lib"] + +pub fn f() -> isize { 10 } diff --git a/src/test/ui/error-codes/auxiliary/crateresolve1-2.rs b/src/test/ui/error-codes/auxiliary/crateresolve1-2.rs new file mode 100644 index 0000000000..71cc0a12ea --- /dev/null +++ b/src/test/ui/error-codes/auxiliary/crateresolve1-2.rs @@ -0,0 +1,5 @@ +// compile-flags:-C extra-filename=-2 +#![crate_name = "crateresolve1"] +#![crate_type = "lib"] + +pub fn f() -> isize { 20 } diff --git a/src/test/ui/error-codes/auxiliary/crateresolve1-3.rs b/src/test/ui/error-codes/auxiliary/crateresolve1-3.rs new file mode 100644 index 0000000000..921687d4c3 --- /dev/null +++ b/src/test/ui/error-codes/auxiliary/crateresolve1-3.rs @@ -0,0 +1,5 @@ +// compile-flags:-C extra-filename=-3 +#![crate_name = "crateresolve1"] +#![crate_type = "lib"] + +pub fn f() -> isize { 30 } diff --git a/src/test/ui/error-codes/e0119/complex-impl.stderr b/src/test/ui/error-codes/e0119/complex-impl.stderr index 04babb0644..6a1a502749 100644 --- a/src/test/ui/error-codes/e0119/complex-impl.stderr +++ b/src/test/ui/error-codes/e0119/complex-impl.stderr @@ -6,7 +6,7 @@ LL | impl 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, V, W>) - where >::Output == V, ::Item == T, 'b: 'a, T: 'a, U: FnOnce<(T,)>, U: 'static, V: Iterator, V: Clone, W: Add, ::Output: Copy; + where >::Output == V, ::Item == T, 'b: 'a, T: 'a, U: 'static, U: FnOnce<(T,)>, V: Iterator, V: Clone, W: Add, ::Output: Copy; error[E0117]: only traits defined in the current crate can be implemented for arbitrary types --> $DIR/complex-impl.rs:9:1 diff --git a/src/test/ui/error-festival.stderr b/src/test/ui/error-festival.stderr index 89a9d965de..b8cd7b7464 100644 --- a/src/test/ui/error-festival.stderr +++ b/src/test/ui/error-festival.stderr @@ -36,7 +36,22 @@ error[E0600]: cannot apply unary operator `!` to type `Question` LL | !Question::Yes; | ^^^^^^^^^^^^^^ cannot apply unary operator `!` | - = note: an implementation of `std::ops::Not` might be missing for `Question` +note: an implementation of `Not` might be missing for `Question` + --> $DIR/error-festival.rs:1:1 + | +LL | enum Question { + | ^^^^^^^^^^^^^ must implement `Not` +note: the following trait must be implemented + --> $SRC_DIR/core/src/ops/bit.rs:LL:COL + | +LL | / pub trait Not { +LL | | /// The resulting type after applying the `!` operator. +LL | | #[stable(feature = "rust1", since = "1.0.0")] +LL | | type Output; +... | +LL | | fn not(self) -> Self::Output; +LL | | } + | |_^ error[E0604]: only `u8` can be cast as `char`, not `u32` --> $DIR/error-festival.rs:25:5 diff --git a/src/test/ui/error-should-say-copy-not-pod.stderr b/src/test/ui/error-should-say-copy-not-pod.stderr index 8c6025e708..637eb27db0 100644 --- a/src/test/ui/error-should-say-copy-not-pod.stderr +++ b/src/test/ui/error-should-say-copy-not-pod.stderr @@ -2,7 +2,9 @@ error[E0277]: the trait bound `String: Copy` is not satisfied --> $DIR/error-should-say-copy-not-pod.rs:6:17 | LL | check_bound("nocopy".to_string()); - | ^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `String` + | ----------- ^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `String` + | | + | required by a bound introduced by this call | note: required by a bound in `check_bound` --> $DIR/error-should-say-copy-not-pod.rs:3:18 diff --git a/src/test/ui/errors/issue-89280-emitter-overflow-splice-lines.rs b/src/test/ui/errors/issue-89280-emitter-overflow-splice-lines.rs new file mode 100644 index 0000000000..a1c7af128d --- /dev/null +++ b/src/test/ui/errors/issue-89280-emitter-overflow-splice-lines.rs @@ -0,0 +1,10 @@ +// check-pass + +trait X { + fn test(x: u32, ( +//~^ WARN anonymous parameters are deprecated and will be removed in the next edition +//~^^ WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! + )) {} +} + +fn main() {} diff --git a/src/test/ui/errors/issue-89280-emitter-overflow-splice-lines.stderr b/src/test/ui/errors/issue-89280-emitter-overflow-splice-lines.stderr new file mode 100644 index 0000000000..4ec78a298f --- /dev/null +++ b/src/test/ui/errors/issue-89280-emitter-overflow-splice-lines.stderr @@ -0,0 +1,23 @@ +warning: anonymous parameters are deprecated and will be removed in the next edition + --> $DIR/issue-89280-emitter-overflow-splice-lines.rs:4:21 + | +LL | fn test(x: u32, ( + | _____________________^ +LL | | +LL | | +LL | | )) {} + | |_____^ + | + = note: `#[warn(anonymous_parameters)]` on by default + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! + = note: for more information, see issue #41686 +help: try naming the parameter or explicitly ignoring it + | +LL ~ fn test(x: u32, _: ( +LL + +LL + +LL ~ )) {} + | + +warning: 1 warning emitted + diff --git a/src/test/ui/explicit/explicit-self-lifetime-mismatch.stderr b/src/test/ui/explicit/explicit-self-lifetime-mismatch.stderr index 5c976098ae..d5ffa8f1b2 100644 --- a/src/test/ui/explicit/explicit-self-lifetime-mismatch.stderr +++ b/src/test/ui/explicit/explicit-self-lifetime-mismatch.stderr @@ -6,12 +6,12 @@ LL | Foo<'b,'a> | = note: expected struct `Foo<'a, 'b>` found struct `Foo<'b, 'a>` -note: the lifetime `'b` as defined on the impl at 6:9... +note: the lifetime `'b` as defined here... --> $DIR/explicit-self-lifetime-mismatch.rs:6:9 | LL | impl<'a,'b> Foo<'a,'b> { | ^^ -note: ...does not necessarily outlive the lifetime `'a` as defined on the impl at 6:6 +note: ...does not necessarily outlive the lifetime `'a` as defined here --> $DIR/explicit-self-lifetime-mismatch.rs:6:6 | LL | impl<'a,'b> Foo<'a,'b> { @@ -25,12 +25,12 @@ LL | Foo<'b,'a> | = note: expected struct `Foo<'a, 'b>` found struct `Foo<'b, 'a>` -note: the lifetime `'a` as defined on the impl at 6:6... +note: the lifetime `'a` as defined here... --> $DIR/explicit-self-lifetime-mismatch.rs:6:6 | LL | impl<'a,'b> Foo<'a,'b> { | ^^ -note: ...does not necessarily outlive the lifetime `'b` as defined on the impl at 6:9 +note: ...does not necessarily outlive the lifetime `'b` as defined here --> $DIR/explicit-self-lifetime-mismatch.rs:6:9 | LL | impl<'a,'b> Foo<'a,'b> { diff --git a/src/test/ui/expr-block-generic-unique1.rs b/src/test/ui/expr-block-generic-unique1.rs index d081cb2be7..14603a2c71 100644 --- a/src/test/ui/expr-block-generic-unique1.rs +++ b/src/test/ui/expr-block-generic-unique1.rs @@ -1,6 +1,5 @@ // run-pass #![allow(unused_braces)] -#![feature(box_syntax)] fn test_generic(expected: Box, eq: F) where T: Clone, F: FnOnce(Box, Box) -> bool { let actual: Box = { expected.clone() }; @@ -13,7 +12,7 @@ fn test_box() { println!("{}", *b2); return *b1 == *b2; } - test_generic::(box true, compare_box); + test_generic::(Box::new(true), compare_box); } pub fn main() { test_box(); } diff --git a/src/test/ui/expr-block-generic-unique2.rs b/src/test/ui/expr-block-generic-unique2.rs index 9362eb86fc..7879c144b1 100644 --- a/src/test/ui/expr-block-generic-unique2.rs +++ b/src/test/ui/expr-block-generic-unique2.rs @@ -1,6 +1,5 @@ // run-pass #![allow(unused_braces)] -#![feature(box_syntax)] fn test_generic(expected: T, eq: F) where T: Clone, F: FnOnce(T, T) -> bool { let actual: T = { expected.clone() }; @@ -9,7 +8,7 @@ fn test_generic(expected: T, eq: F) where T: Clone, F: FnOnce(T, T) -> boo fn test_vec() { fn compare_vec(v1: Box, v2: Box) -> bool { return v1 == v2; } - test_generic::, _>(box 1, compare_vec); + test_generic::, _>(Box::new(1), compare_vec); } pub fn main() { test_vec(); } diff --git a/src/test/ui/expr-block-unique.rs b/src/test/ui/expr-block-unique.rs index eff3fd3a15..5fa11ad128 100644 --- a/src/test/ui/expr-block-unique.rs +++ b/src/test/ui/expr-block-unique.rs @@ -1,5 +1,4 @@ // run-pass #![allow(unused_braces)] -#![feature(box_syntax)] -pub fn main() { let x: Box<_> = { box 100 }; assert_eq!(*x, 100); } +pub fn main() { let x: Box<_> = { Box::new(100) }; assert_eq!(*x, 100); } diff --git a/src/test/ui/expr-if-unique.rs b/src/test/ui/expr-if-unique.rs index 509d069d40..8623268354 100644 --- a/src/test/ui/expr-if-unique.rs +++ b/src/test/ui/expr-if-unique.rs @@ -1,10 +1,8 @@ // run-pass -#![feature(box_syntax)] - // Tests for if as expressions returning boxed types fn test_box() { - let rs: Box<_> = if true { box 100 } else { box 101 }; + let rs: Box<_> = if true { Box::new(100) } else { Box::new(101) }; assert_eq!(*rs, 100); } diff --git a/src/test/ui/expr/if/if-let.stderr b/src/test/ui/expr/if/if-let.stderr index 7975a9dca0..3f3a224583 100644 --- a/src/test/ui/expr/if/if-let.stderr +++ b/src/test/ui/expr/if/if-let.stderr @@ -7,7 +7,7 @@ LL | if let $p = $e $b LL | / foo!(a, 1, { LL | | println!("irrefutable pattern"); LL | | }); - | |_______- in this macro invocation + | |______- in this macro invocation | = note: `#[warn(irrefutable_let_patterns)]` on by default = note: this pattern will always match, so the `if let` is useless @@ -23,7 +23,7 @@ LL | if let $p = $e $b LL | / bar!(a, 1, { LL | | println!("irrefutable pattern"); LL | | }); - | |_______- in this macro invocation + | |______- in this macro invocation | = note: this pattern will always match, so the `if let` is useless = help: consider replacing the `if let` with a `let` diff --git a/src/test/ui/expr/malformed_closure/missing_braces_around_block.fixed b/src/test/ui/expr/malformed_closure/missing_braces_around_block.fixed new file mode 100644 index 0000000000..c50b9a12b6 --- /dev/null +++ b/src/test/ui/expr/malformed_closure/missing_braces_around_block.fixed @@ -0,0 +1,19 @@ +// This snippet ensures that no attempt to recover on a semicolon instead of +// comma is made next to a closure body. +// +// If this recovery happens, then plenty of errors are emitted. Here, we expect +// only one error. +// +// This is part of issue #88065: +// https://github.com/rust-lang/rust/issues/88065 + +// run-rustfix + +fn main() { + let num = 5; + (1..num).reduce(|a, b| { + //~^ ERROR: closure bodies that contain statements must be surrounded by braces + println!("{}", a); + a * b + }).unwrap(); +} diff --git a/src/test/ui/expr/malformed_closure/missing_braces_around_block.rs b/src/test/ui/expr/malformed_closure/missing_braces_around_block.rs new file mode 100644 index 0000000000..58c81f3a6e --- /dev/null +++ b/src/test/ui/expr/malformed_closure/missing_braces_around_block.rs @@ -0,0 +1,19 @@ +// This snippet ensures that no attempt to recover on a semicolon instead of +// comma is made next to a closure body. +// +// If this recovery happens, then plenty of errors are emitted. Here, we expect +// only one error. +// +// This is part of issue #88065: +// https://github.com/rust-lang/rust/issues/88065 + +// run-rustfix + +fn main() { + let num = 5; + (1..num).reduce(|a, b| + //~^ ERROR: closure bodies that contain statements must be surrounded by braces + println!("{}", a); + a * b + ).unwrap(); +} diff --git a/src/test/ui/expr/malformed_closure/missing_braces_around_block.stderr b/src/test/ui/expr/malformed_closure/missing_braces_around_block.stderr new file mode 100644 index 0000000000..dac9a8cfc6 --- /dev/null +++ b/src/test/ui/expr/malformed_closure/missing_braces_around_block.stderr @@ -0,0 +1,38 @@ +error: closure bodies that contain statements must be surrounded by braces + --> $DIR/missing_braces_around_block.rs:14:26 + | +LL | (1..num).reduce(|a, b| + | ^ +... +LL | ).unwrap(); + | ^ + | +note: statement found outside of a block + --> $DIR/missing_braces_around_block.rs:16:26 + | +LL | println!("{}", a); + | -----------------^ this `;` turns the preceding closure into a statement + | | + | this expression is a statement because of the trailing semicolon +note: the closure body may be incorrectly delimited + --> $DIR/missing_braces_around_block.rs:14:21 + | +LL | (1..num).reduce(|a, b| + | _____________________^ +LL | | +LL | | println!("{}", a); + | |_________________________^ this is the parsed closure... +LL | a * b +LL | ).unwrap(); + | - ...but likely you meant the closure to end here +help: try adding braces + | +LL ~ (1..num).reduce(|a, b| { +LL | +LL | println!("{}", a); +LL | a * b +LL ~ }).unwrap(); + | + +error: aborting due to previous error + diff --git a/src/test/ui/expr/malformed_closure/ruby_style_closure.rs b/src/test/ui/expr/malformed_closure/ruby_style_closure.rs new file mode 100644 index 0000000000..e4341e1968 --- /dev/null +++ b/src/test/ui/expr/malformed_closure/ruby_style_closure.rs @@ -0,0 +1,16 @@ +// Part of issue #27300. +// The problem here is that ruby-style closures are parsed as blocks whose +// first statement is a closure. See the issue for more details: +// https://github.com/rust-lang/rust/issues/27300 + +// Note: this test represents what the compiler currently emits. The error +// message will be improved later. + +fn main() { + let p = Some(45).and_then({ + //~^ expected a `FnOnce<({integer},)>` closure, found `Option<_>` + |x| println!("doubling {}", x); + Some(x * 2) + //~^ ERROR: cannot find value `x` in this scope + }); +} diff --git a/src/test/ui/expr/malformed_closure/ruby_style_closure.stderr b/src/test/ui/expr/malformed_closure/ruby_style_closure.stderr new file mode 100644 index 0000000000..14d28b5964 --- /dev/null +++ b/src/test/ui/expr/malformed_closure/ruby_style_closure.stderr @@ -0,0 +1,27 @@ +error[E0425]: cannot find value `x` in this scope + --> $DIR/ruby_style_closure.rs:13:14 + | +LL | Some(x * 2) + | ^ not found in this scope + +error[E0277]: expected a `FnOnce<({integer},)>` closure, found `Option<_>` + --> $DIR/ruby_style_closure.rs:10:31 + | +LL | let p = Some(45).and_then({ + | ______________________--------_^ + | | | + | | required by a bound introduced by this call +LL | | +LL | | |x| println!("doubling {}", x); +LL | | Some(x * 2) + | | ----------- +LL | | +LL | | }); + | |_____^ expected an `FnOnce<({integer},)>` closure, found `Option<_>` + | + = help: the trait `FnOnce<({integer},)>` is not implemented for `Option<_>` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0277, E0425. +For more information about an error, try `rustc --explain E0277`. diff --git a/src/test/ui/extenv/extenv-no-args.stderr b/src/test/ui/extenv/extenv-no-args.stderr index acdde84afa..318ed635be 100644 --- a/src/test/ui/extenv/extenv-no-args.stderr +++ b/src/test/ui/extenv/extenv-no-args.stderr @@ -2,7 +2,7 @@ error: env! takes 1 or 2 arguments --> $DIR/extenv-no-args.rs:1:13 | LL | fn main() { env!(); } - | ^^^^^^^ + | ^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/extenv/extenv-not-defined-custom.stderr b/src/test/ui/extenv/extenv-not-defined-custom.stderr index c81518010b..e7da4e046a 100644 --- a/src/test/ui/extenv/extenv-not-defined-custom.stderr +++ b/src/test/ui/extenv/extenv-not-defined-custom.stderr @@ -2,7 +2,7 @@ error: my error message --> $DIR/extenv-not-defined-custom.rs:1:13 | LL | fn main() { env!("__HOPEFULLY_NOT_DEFINED__", "my error message"); } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: this error originates in the macro `env` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/extenv/extenv-not-defined-default.stderr b/src/test/ui/extenv/extenv-not-defined-default.stderr index 8ecba6dbe9..884875dca5 100644 --- a/src/test/ui/extenv/extenv-not-defined-default.stderr +++ b/src/test/ui/extenv/extenv-not-defined-default.stderr @@ -2,7 +2,7 @@ error: environment variable `__HOPEFULLY_NOT_DEFINED__` not defined --> $DIR/extenv-not-defined-default.rs:2:5 | LL | env!("__HOPEFULLY_NOT_DEFINED__"); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: this error originates in the macro `env` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/extenv/extenv-too-many-args.stderr b/src/test/ui/extenv/extenv-too-many-args.stderr index 3351da0d54..54150a3328 100644 --- a/src/test/ui/extenv/extenv-too-many-args.stderr +++ b/src/test/ui/extenv/extenv-too-many-args.stderr @@ -2,7 +2,7 @@ error: env! takes 1 or 2 arguments --> $DIR/extenv-too-many-args.rs:1:13 | LL | fn main() { env!("one", "two", "three"); } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/extern/extern-wrong-value-type.stderr b/src/test/ui/extern/extern-wrong-value-type.stderr index 74981ebb76..c6f0d5df9b 100644 --- a/src/test/ui/extern/extern-wrong-value-type.stderr +++ b/src/test/ui/extern/extern-wrong-value-type.stderr @@ -2,7 +2,9 @@ error[E0277]: expected a `Fn<()>` closure, found `extern "C" fn() {f}` --> $DIR/extern-wrong-value-type.rs:9:11 | LL | is_fn(f); - | ^ expected an `Fn<()>` closure, found `extern "C" fn() {f}` + | ----- ^ expected an `Fn<()>` closure, found `extern "C" fn() {f}` + | | + | required by a bound introduced by this call | = help: the trait `Fn<()>` is not implemented for `extern "C" fn() {f}` = note: wrap the `extern "C" fn() {f}` in a closure with no arguments: `|| { /* code */ }` diff --git a/src/test/ui/extoption_env-no-args.stderr b/src/test/ui/extoption_env-no-args.stderr index 386d517a44..65067942b8 100644 --- a/src/test/ui/extoption_env-no-args.stderr +++ b/src/test/ui/extoption_env-no-args.stderr @@ -2,7 +2,7 @@ error: option_env! takes 1 argument --> $DIR/extoption_env-no-args.rs:1:13 | LL | fn main() { option_env!(); } - | ^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/extoption_env-too-many-args.stderr b/src/test/ui/extoption_env-too-many-args.stderr index 2ec5594703..a34e60b644 100644 --- a/src/test/ui/extoption_env-too-many-args.stderr +++ b/src/test/ui/extoption_env-too-many-args.stderr @@ -2,7 +2,7 @@ error: option_env! takes 1 argument --> $DIR/extoption_env-too-many-args.rs:1:13 | LL | fn main() { option_env!("one", "two"); } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/feature-gates/feature-gate-allow-internal-unsafe-nested-macro.stderr b/src/test/ui/feature-gates/feature-gate-allow-internal-unsafe-nested-macro.stderr index f1becfb99a..4621bc0b30 100644 --- a/src/test/ui/feature-gates/feature-gate-allow-internal-unsafe-nested-macro.stderr +++ b/src/test/ui/feature-gates/feature-gate-allow-internal-unsafe-nested-macro.stderr @@ -5,7 +5,7 @@ LL | #[allow_internal_unsafe] | ^^^^^^^^^^^^^^^^^^^^^^^^ ... LL | bar!(); - | ------- in this macro invocation + | ------ in this macro invocation | = help: add `#![feature(allow_internal_unsafe)]` to the crate attributes to enable = note: this error originates in the macro `bar` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/feature-gates/feature-gate-allow-internal-unstable-nested-macro.stderr b/src/test/ui/feature-gates/feature-gate-allow-internal-unstable-nested-macro.stderr index 91cf2020a4..1232d13a45 100644 --- a/src/test/ui/feature-gates/feature-gate-allow-internal-unstable-nested-macro.stderr +++ b/src/test/ui/feature-gates/feature-gate-allow-internal-unstable-nested-macro.stderr @@ -5,7 +5,7 @@ LL | #[allow_internal_unstable()] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ... LL | bar!(); - | ------- in this macro invocation + | ------ in this macro invocation | = help: add `#![feature(allow_internal_unstable)]` to the crate attributes to enable = note: this error originates in the macro `bar` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/feature-gates/feature-gate-closure_track_caller.rs b/src/test/ui/feature-gates/feature-gate-closure_track_caller.rs new file mode 100644 index 0000000000..a8d63a8145 --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-closure_track_caller.rs @@ -0,0 +1,7 @@ +#![feature(stmt_expr_attributes)] +#![feature(generators)] + +fn main() { + let _closure = #[track_caller] || {}; //~ `#[track_caller]` on closures + let _generator = #[track_caller] || { yield; }; //~ `#[track_caller]` on closures +} diff --git a/src/test/ui/feature-gates/feature-gate-closure_track_caller.stderr b/src/test/ui/feature-gates/feature-gate-closure_track_caller.stderr new file mode 100644 index 0000000000..ed63d74fe4 --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-closure_track_caller.stderr @@ -0,0 +1,21 @@ +error[E0658]: `#[track_caller]` on closures is currently unstable + --> $DIR/feature-gate-closure_track_caller.rs:5:20 + | +LL | let _closure = #[track_caller] || {}; + | ^^^^^^^^^^^^^^^ + | + = note: see issue #87417 for more information + = help: add `#![feature(closure_track_caller)]` to the crate attributes to enable + +error[E0658]: `#[track_caller]` on closures is currently unstable + --> $DIR/feature-gate-closure_track_caller.rs:6:22 + | +LL | let _generator = #[track_caller] || { yield; }; + | ^^^^^^^^^^^^^^^ + | + = note: see issue #87417 for more information + = help: add `#![feature(closure_track_caller)]` to the crate attributes to enable + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gates/feature-gate-concat_idents2.stderr b/src/test/ui/feature-gates/feature-gate-concat_idents2.stderr index 5e6dcd5447..8663bc7ca7 100644 --- a/src/test/ui/feature-gates/feature-gate-concat_idents2.stderr +++ b/src/test/ui/feature-gates/feature-gate-concat_idents2.stderr @@ -11,7 +11,7 @@ error[E0425]: cannot find value `ab` in this scope --> $DIR/feature-gate-concat_idents2.rs:2:5 | LL | concat_idents!(a, b); - | ^^^^^^^^^^^^^^^^^^^^^ not found in this scope + | ^^^^^^^^^^^^^^^^^^^^ not found in this scope | = note: this error originates in the macro `concat_idents` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/feature-gates/feature-gate-non_exhaustive_omitted_patterns_lint.rs b/src/test/ui/feature-gates/feature-gate-non_exhaustive_omitted_patterns_lint.rs new file mode 100644 index 0000000000..2a34ed4d4f --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-non_exhaustive_omitted_patterns_lint.rs @@ -0,0 +1,31 @@ +#![deny(non_exhaustive_omitted_patterns)] +//~^ ERROR the `non_exhaustive_omitted_patterns` lint is unstable +//~| ERROR the `non_exhaustive_omitted_patterns` lint is unstable +#![allow(non_exhaustive_omitted_patterns)] +//~^ ERROR the `non_exhaustive_omitted_patterns` lint is unstable +//~| ERROR the `non_exhaustive_omitted_patterns` lint is unstable + +fn main() { + enum Foo { + A, B, C, + } + + #[allow(non_exhaustive_omitted_patterns)] + match Foo::A { + Foo::A => {} + Foo::B => {} + } + //~^^^^^ ERROR the `non_exhaustive_omitted_patterns` lint is unstable + //~| ERROR the `non_exhaustive_omitted_patterns` lint is unstable + //~| ERROR the `non_exhaustive_omitted_patterns` lint is unstable + //~| ERROR the `non_exhaustive_omitted_patterns` lint is unstable + + match Foo::A { + Foo::A => {} + Foo::B => {} + #[warn(non_exhaustive_omitted_patterns)] + _ => {} + } + //~^^^ ERROR the `non_exhaustive_omitted_patterns` lint is unstable + //~| ERROR the `non_exhaustive_omitted_patterns` lint is unstable +} diff --git a/src/test/ui/feature-gates/feature-gate-non_exhaustive_omitted_patterns_lint.stderr b/src/test/ui/feature-gates/feature-gate-non_exhaustive_omitted_patterns_lint.stderr new file mode 100644 index 0000000000..691f64cf0a --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-non_exhaustive_omitted_patterns_lint.stderr @@ -0,0 +1,93 @@ +error[E0658]: the `non_exhaustive_omitted_patterns` lint is unstable + --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:1:1 + | +LL | #![deny(non_exhaustive_omitted_patterns)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #89554 for more information + = help: add `#![feature(non_exhaustive_omitted_patterns_lint)]` to the crate attributes to enable + +error[E0658]: the `non_exhaustive_omitted_patterns` lint is unstable + --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:4:1 + | +LL | #![allow(non_exhaustive_omitted_patterns)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #89554 for more information + = help: add `#![feature(non_exhaustive_omitted_patterns_lint)]` to the crate attributes to enable + +error[E0658]: the `non_exhaustive_omitted_patterns` lint is unstable + --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:13:5 + | +LL | #[allow(non_exhaustive_omitted_patterns)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #89554 for more information + = help: add `#![feature(non_exhaustive_omitted_patterns_lint)]` to the crate attributes to enable + +error[E0658]: the `non_exhaustive_omitted_patterns` lint is unstable + --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:13:5 + | +LL | #[allow(non_exhaustive_omitted_patterns)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #89554 for more information + = help: add `#![feature(non_exhaustive_omitted_patterns_lint)]` to the crate attributes to enable + +error[E0658]: the `non_exhaustive_omitted_patterns` lint is unstable + --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:26:9 + | +LL | #[warn(non_exhaustive_omitted_patterns)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #89554 for more information + = help: add `#![feature(non_exhaustive_omitted_patterns_lint)]` to the crate attributes to enable + +error[E0658]: the `non_exhaustive_omitted_patterns` lint is unstable + --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:1:1 + | +LL | #![deny(non_exhaustive_omitted_patterns)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #89554 for more information + = help: add `#![feature(non_exhaustive_omitted_patterns_lint)]` to the crate attributes to enable + +error[E0658]: the `non_exhaustive_omitted_patterns` lint is unstable + --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:4:1 + | +LL | #![allow(non_exhaustive_omitted_patterns)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #89554 for more information + = help: add `#![feature(non_exhaustive_omitted_patterns_lint)]` to the crate attributes to enable + +error[E0658]: the `non_exhaustive_omitted_patterns` lint is unstable + --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:13:5 + | +LL | #[allow(non_exhaustive_omitted_patterns)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #89554 for more information + = help: add `#![feature(non_exhaustive_omitted_patterns_lint)]` to the crate attributes to enable + +error[E0658]: the `non_exhaustive_omitted_patterns` lint is unstable + --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:13:5 + | +LL | #[allow(non_exhaustive_omitted_patterns)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #89554 for more information + = help: add `#![feature(non_exhaustive_omitted_patterns_lint)]` to the crate attributes to enable + +error[E0658]: the `non_exhaustive_omitted_patterns` lint is unstable + --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:26:9 + | +LL | #[warn(non_exhaustive_omitted_patterns)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #89554 for more information + = help: add `#![feature(non_exhaustive_omitted_patterns_lint)]` to the crate attributes to enable + +error: aborting due to 10 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gates/feature-gate-object_safe_for_dispatch.stderr b/src/test/ui/feature-gates/feature-gate-object_safe_for_dispatch.stderr index a3bd65e518..72cb4cc843 100644 --- a/src/test/ui/feature-gates/feature-gate-object_safe_for_dispatch.stderr +++ b/src/test/ui/feature-gates/feature-gate-object_safe_for_dispatch.stderr @@ -40,7 +40,6 @@ error[E0038]: the trait `NonObjectSafe3` cannot be made into an object LL | fn takes_non_object_safe_box(obj: Box) { | ^^^^^^^^^^^^^^^^^^ `NonObjectSafe3` cannot be made into an object | - = help: consider moving `foo` to another trait note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit --> $DIR/feature-gate-object_safe_for_dispatch.rs:11:8 | @@ -48,6 +47,7 @@ LL | trait NonObjectSafe3 { | -------------- this trait cannot be made into an object... LL | fn foo(&self); | ^^^ ...because method `foo` has generic type parameters + = help: consider moving `foo` to another trait error[E0038]: the trait `NonObjectSafe4` cannot be made into an object --> $DIR/feature-gate-object_safe_for_dispatch.rs:31:35 @@ -55,7 +55,6 @@ error[E0038]: the trait `NonObjectSafe4` cannot be made into an object LL | fn return_non_object_safe_rc() -> std::rc::Rc { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `NonObjectSafe4` cannot be made into an object | - = help: consider moving `foo` to another trait note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit --> $DIR/feature-gate-object_safe_for_dispatch.rs:15:22 | @@ -63,6 +62,7 @@ LL | trait NonObjectSafe4 { | -------------- this trait cannot be made into an object... LL | fn foo(&self, s: &Self); | ^^^^^ ...because method `foo` references the `Self` type in this parameter + = help: consider moving `foo` to another trait error[E0038]: the trait `NonObjectSafe1` cannot be made into an object --> $DIR/feature-gate-object_safe_for_dispatch.rs:38:16 diff --git a/src/test/ui/feature-gates/feature-gate-try_reserve.rs b/src/test/ui/feature-gates/feature-gate-try_reserve.rs deleted file mode 100644 index a19dd58da1..0000000000 --- a/src/test/ui/feature-gates/feature-gate-try_reserve.rs +++ /dev/null @@ -1,4 +0,0 @@ -fn main() { - let v = Vec::new(); - v.try_reserve(10); //~ ERROR: use of unstable library feature 'try_reserve' -} diff --git a/src/test/ui/feature-gates/feature-gate-try_reserve.stderr b/src/test/ui/feature-gates/feature-gate-try_reserve.stderr deleted file mode 100644 index 4da9a23a1b..0000000000 --- a/src/test/ui/feature-gates/feature-gate-try_reserve.stderr +++ /dev/null @@ -1,12 +0,0 @@ -error[E0658]: use of unstable library feature 'try_reserve': new API - --> $DIR/feature-gate-try_reserve.rs:3:7 - | -LL | v.try_reserve(10); - | ^^^^^^^^^^^ - | - = note: see issue #48043 for more information - = help: add `#![feature(try_reserve)]` 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-unboxed-closures-manual-impls.stderr b/src/test/ui/feature-gates/feature-gate-unboxed-closures-manual-impls.stderr index 22a1ce3061..e0e0acadb3 100644 --- a/src/test/ui/feature-gates/feature-gate-unboxed-closures-manual-impls.stderr +++ b/src/test/ui/feature-gates/feature-gate-unboxed-closures-manual-impls.stderr @@ -101,5 +101,5 @@ LL | impl FnOnce<()> for Baz { error: aborting due to 12 previous errors -Some errors have detailed explanations: E0229, E0658. -For more information about an error, try `rustc --explain E0229`. +Some errors have detailed explanations: E0183, E0229, E0658. +For more information about an error, try `rustc --explain E0183`. diff --git a/src/test/ui/feature-gates/feature-gate-unboxed-closures.stderr b/src/test/ui/feature-gates/feature-gate-unboxed-closures.stderr index 2c8915d0ac..8c5f879645 100644 --- a/src/test/ui/feature-gates/feature-gate-unboxed-closures.stderr +++ b/src/test/ui/feature-gates/feature-gate-unboxed-closures.stderr @@ -26,4 +26,5 @@ LL | impl FnOnce<(u32, u32)> for Test { error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0658`. +Some errors have detailed explanations: E0183, E0658. +For more information about an error, try `rustc --explain E0183`. diff --git a/src/test/ui/feature-gates/feature-gate-unsized_fn_params.stderr b/src/test/ui/feature-gates/feature-gate-unsized_fn_params.stderr index fbb18c8c49..0f7520ef7f 100644 --- a/src/test/ui/feature-gates/feature-gate-unsized_fn_params.stderr +++ b/src/test/ui/feature-gates/feature-gate-unsized_fn_params.stderr @@ -12,10 +12,10 @@ LL | fn foo(x: &dyn Foo) { | + error[E0277]: the size for values of type `(dyn Foo + 'static)` cannot be known at compilation time - --> $DIR/feature-gate-unsized_fn_params.rs:24:5 + --> $DIR/feature-gate-unsized_fn_params.rs:24:9 | LL | foo(*x); - | ^^^ 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 `(dyn Foo + 'static)` = note: all function arguments must have a statically known size diff --git a/src/test/ui/feature-gates/thread-local-const-init.stderr b/src/test/ui/feature-gates/thread-local-const-init.stderr index eac2100560..f80506831b 100644 --- a/src/test/ui/feature-gates/thread-local-const-init.stderr +++ b/src/test/ui/feature-gates/thread-local-const-init.stderr @@ -2,7 +2,7 @@ error[E0658]: use of unstable library feature 'thread_local_const_init' --> $DIR/thread-local-const-init.rs:1:1 | LL | thread_local!(static X: u32 = const { 0 }); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: see issue #84223 for more information = help: add `#![feature(thread_local_const_init)]` to the crate attributes to enable diff --git a/src/test/ui/feature-gates/trace_macros-gate.stderr b/src/test/ui/feature-gates/trace_macros-gate.stderr index e934bfcccf..1ca10aeece 100644 --- a/src/test/ui/feature-gates/trace_macros-gate.stderr +++ b/src/test/ui/feature-gates/trace_macros-gate.stderr @@ -11,7 +11,7 @@ error: trace_macros! accepts only `true` or `false` --> $DIR/trace_macros-gate.rs:4:5 | LL | trace_macros!(); - | ^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^ error[E0658]: use of unstable library feature 'trace_macros': `trace_macros` is not stable enough for use and is subject to change --> $DIR/trace_macros-gate.rs:6:5 @@ -38,7 +38,7 @@ LL | ($x: ident) => { trace_macros!($x) } | ^^^^^^^^^^^^ ... LL | expando!(true); - | --------------- in this macro invocation + | -------------- in this macro invocation | = note: see issue #29598 for more information = help: add `#![feature(trace_macros)]` to the crate attributes to enable diff --git a/src/test/ui/float-literal-inference-restrictions.stderr b/src/test/ui/float-literal-inference-restrictions.stderr index 263b5e594e..454373c322 100644 --- a/src/test/ui/float-literal-inference-restrictions.stderr +++ b/src/test/ui/float-literal-inference-restrictions.stderr @@ -19,7 +19,7 @@ LL | let y: f32 = 1f64; help: change the type of the numeric literal from `f64` to `f32` | LL | let y: f32 = 1f32; - | ~~~~ + | ~~~ error: aborting due to 2 previous errors diff --git a/src/test/ui/fmt/ifmt-bad-format-args.stderr b/src/test/ui/fmt/ifmt-bad-format-args.stderr index 854abb9063..2db280c5e2 100644 --- a/src/test/ui/fmt/ifmt-bad-format-args.stderr +++ b/src/test/ui/fmt/ifmt-bad-format-args.stderr @@ -2,7 +2,7 @@ error: requires at least a format string argument --> $DIR/ifmt-bad-format-args.rs:2:5 | LL | format_args!(); - | ^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^ | = note: this error originates in the macro `format_args` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/fmt/issue-89173.rs b/src/test/ui/fmt/issue-89173.rs new file mode 100644 index 0000000000..96277d4d0d --- /dev/null +++ b/src/test/ui/fmt/issue-89173.rs @@ -0,0 +1,14 @@ +// Regression test for #89173: Make sure a helpful note is issued for +// printf-style format strings using `*` to specify the width. + +fn main() { + let num = 0x0abcde; + let width = 6; + print!("%0*x", width, num); + //~^ ERROR: multiple unused formatting arguments + //~| NOTE: multiple missing formatting specifiers + //~| NOTE: argument never used + //~| NOTE: argument never used + //~| NOTE: format specifiers use curly braces, and you have to use a positional or named parameter for the width + //~| NOTE: printf formatting not supported +} diff --git a/src/test/ui/fmt/issue-89173.stderr b/src/test/ui/fmt/issue-89173.stderr new file mode 100644 index 0000000000..7b21e0a4fc --- /dev/null +++ b/src/test/ui/fmt/issue-89173.stderr @@ -0,0 +1,18 @@ +error: multiple unused formatting arguments + --> $DIR/issue-89173.rs:7:20 + | +LL | print!("%0*x", width, num); + | ------ ^^^^^ ^^^ argument never used + | | | + | | argument never used + | multiple missing formatting specifiers + | +note: format specifiers use curly braces, and you have to use a positional or named parameter for the width + --> $DIR/issue-89173.rs:7:13 + | +LL | print!("%0*x", width, num); + | ^^^^ + = note: printf formatting not supported; see the documentation for `std::fmt` + +error: aborting due to previous error + diff --git a/src/test/ui/fn/fn-trait-formatting.rs b/src/test/ui/fn/fn-trait-formatting.rs index 0c389e1dc5..636ac7107e 100644 --- a/src/test/ui/fn/fn-trait-formatting.rs +++ b/src/test/ui/fn/fn-trait-formatting.rs @@ -1,17 +1,17 @@ -#![feature(box_syntax)] - fn needs_fn(x: F) where F: Fn(isize) -> isize {} + + fn main() { - let _: () = (box |_: isize| {}) as Box; + let _: () = Box::new(|_: isize| {}) as Box; //~^ ERROR mismatched types //~| expected unit type `()` //~| found struct `Box` - let _: () = (box |_: isize, isize| {}) as Box; + let _: () = Box::new(|_: isize, isize| {}) as Box; //~^ ERROR mismatched types //~| expected unit type `()` //~| found struct `Box` - let _: () = (box || -> isize { unimplemented!() }) as Box isize>; + let _: () = Box::new(|| -> isize { unimplemented!() }) as Box isize>; //~^ ERROR mismatched types //~| expected unit type `()` //~| found struct `Box isize>` diff --git a/src/test/ui/fn/fn-trait-formatting.stderr b/src/test/ui/fn/fn-trait-formatting.stderr index 57a25b8e48..ea88e401be 100644 --- a/src/test/ui/fn/fn-trait-formatting.stderr +++ b/src/test/ui/fn/fn-trait-formatting.stderr @@ -1,8 +1,8 @@ error[E0308]: mismatched types --> $DIR/fn-trait-formatting.rs:6:17 | -LL | let _: () = (box |_: isize| {}) as Box; - | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found struct `Box` +LL | let _: () = Box::new(|_: isize| {}) as Box; + | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found struct `Box` | | | expected due to this | @@ -12,8 +12,8 @@ LL | let _: () = (box |_: isize| {}) as Box; error[E0308]: mismatched types --> $DIR/fn-trait-formatting.rs:10:17 | -LL | let _: () = (box |_: isize, isize| {}) as Box; - | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found struct `Box` +LL | let _: () = Box::new(|_: isize, isize| {}) as Box; + | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found struct `Box` | | | expected due to this | @@ -23,8 +23,8 @@ LL | let _: () = (box |_: isize, isize| {}) as Box; error[E0308]: mismatched types --> $DIR/fn-trait-formatting.rs:14:17 | -LL | let _: () = (box || -> isize { unimplemented!() }) as Box isize>; - | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found struct `Box` +LL | let _: () = Box::new(|| -> isize { unimplemented!() }) as Box isize>; + | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found struct `Box` | | | expected due to this | @@ -35,11 +35,13 @@ error[E0277]: expected a `Fn<(isize,)>` closure, found `{integer}` --> $DIR/fn-trait-formatting.rs:19:14 | LL | needs_fn(1); - | ^ expected an `Fn<(isize,)>` closure, found `{integer}` + | -------- ^ expected an `Fn<(isize,)>` closure, found `{integer}` + | | + | required by a bound introduced by this call | = help: the trait `Fn<(isize,)>` is not implemented for `{integer}` note: required by a bound in `needs_fn` - --> $DIR/fn-trait-formatting.rs:3:31 + --> $DIR/fn-trait-formatting.rs:1:31 | LL | fn needs_fn(x: F) where F: Fn(isize) -> isize {} | ^^^^^^^^^^^^^^^^^^ required by this bound in `needs_fn` diff --git a/src/test/ui/fn/implied-bounds-unnorm-associated-type.nll.stderr b/src/test/ui/fn/implied-bounds-unnorm-associated-type.nll.stderr new file mode 100644 index 0000000000..e37ec7f266 --- /dev/null +++ b/src/test/ui/fn/implied-bounds-unnorm-associated-type.nll.stderr @@ -0,0 +1,14 @@ +error: lifetime may not live long enough + --> $DIR/implied-bounds-unnorm-associated-type.rs:14:5 + | +LL | fn f<'a, 'b>(s: &'b str, _: <&'a &'b () as Trait>::Type) -> &'a str { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | s + | ^ returning this value requires that `'b` must outlive `'a` + | + = help: consider adding the following bound: `'b: 'a` + +error: aborting due to previous error + diff --git a/src/test/ui/fn/implied-bounds-unnorm-associated-type.rs b/src/test/ui/fn/implied-bounds-unnorm-associated-type.rs new file mode 100644 index 0000000000..2e5ac7d739 --- /dev/null +++ b/src/test/ui/fn/implied-bounds-unnorm-associated-type.rs @@ -0,0 +1,22 @@ +// check-fail +// See issue #91068. Types in the substs of an associated type can't be implied +// to be WF, since they don't actually have to be constructed. + +trait Trait { + type Type; +} + +impl Trait for T { + type Type = (); +} + +fn f<'a, 'b>(s: &'b str, _: <&'a &'b () as Trait>::Type) -> &'a str { + s //~ ERROR lifetime mismatch [E0623] +} + +fn main() { + let x = String::from("Hello World!"); + let y = f(&x, ()); + drop(x); + println!("{}", y); +} diff --git a/src/test/ui/fn/implied-bounds-unnorm-associated-type.stderr b/src/test/ui/fn/implied-bounds-unnorm-associated-type.stderr new file mode 100644 index 0000000000..93ab5dceee --- /dev/null +++ b/src/test/ui/fn/implied-bounds-unnorm-associated-type.stderr @@ -0,0 +1,13 @@ +error[E0623]: lifetime mismatch + --> $DIR/implied-bounds-unnorm-associated-type.rs:14:5 + | +LL | fn f<'a, 'b>(s: &'b str, _: <&'a &'b () as Trait>::Type) -> &'a str { + | ------- ---------- + | | + | these two types are declared with different lifetimes... +LL | s + | ^ ...but data from `s` flows here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0623`. diff --git a/src/test/ui/for-loop-while/cleanup-rvalue-during-if-and-while.rs b/src/test/ui/for-loop-while/cleanup-rvalue-during-if-and-while.rs index 6fecb4e76d..afc77355ab 100644 --- a/src/test/ui/for-loop-while/cleanup-rvalue-during-if-and-while.rs +++ b/src/test/ui/for-loop-while/cleanup-rvalue-during-if-and-while.rs @@ -2,8 +2,6 @@ // This test verifies that temporaries created for `while`'s and `if` // conditions are dropped after the condition is evaluated. -#![feature(box_syntax)] - struct Temporary; static mut DROPPED: isize = 0; @@ -18,7 +16,7 @@ impl Temporary { fn do_stuff(&self) -> bool {true} } -fn borrow() -> Box { box Temporary } +fn borrow() -> Box { Box::new(Temporary) } pub fn main() { diff --git a/src/test/ui/future-incompatible-lint-group.stderr b/src/test/ui/future-incompatible-lint-group.stderr index cb9be88c9e..d822847a7a 100644 --- a/src/test/ui/future-incompatible-lint-group.stderr +++ b/src/test/ui/future-incompatible-lint-group.stderr @@ -1,4 +1,4 @@ -warning: anonymous parameters are deprecated and will be removed in the next edition. +warning: anonymous parameters are deprecated and will be removed in the next edition --> $DIR/future-incompatible-lint-group.rs:7:10 | LL | fn f(u8) {} diff --git a/src/test/ui/gated-bad-feature.stderr b/src/test/ui/gated-bad-feature.stderr index 79e59f7631..a8ec939152 100644 --- a/src/test/ui/gated-bad-feature.stderr +++ b/src/test/ui/gated-bad-feature.stderr @@ -20,13 +20,13 @@ error: malformed `feature` attribute input --> $DIR/gated-bad-feature.rs:5:1 | LL | #![feature] - | ^^^^^^^^^^^ help: must be of the form: `#[feature(name1, name1, ...)]` + | ^^^^^^^^^^^ help: must be of the form: `#![feature(name1, name1, ...)]` error: malformed `feature` attribute input --> $DIR/gated-bad-feature.rs:6:1 | LL | #![feature = "foo"] - | ^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[feature(name1, name1, ...)]` + | ^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#![feature(name1, name1, ...)]` error: aborting due to 5 previous errors diff --git a/src/test/ui/generator/dropck-resume.stderr b/src/test/ui/generator/dropck-resume.stderr index ecf92e7e3a..b0756eb558 100644 --- a/src/test/ui/generator/dropck-resume.stderr +++ b/src/test/ui/generator/dropck-resume.stderr @@ -5,7 +5,7 @@ LL | let z = &mut y; | ------ mutable borrow occurs here ... LL | r = y.as_ref().unwrap(); - | ^ immutable borrow occurs here + | ^^^^^^^^^^ immutable borrow occurs here LL | LL | } | - mutable borrow might be used here, when `g` is dropped and runs the destructor for generator diff --git a/src/test/ui/generator/dropck.stderr b/src/test/ui/generator/dropck.stderr index 8bb860f288..7bb188352d 100644 --- a/src/test/ui/generator/dropck.stderr +++ b/src/test/ui/generator/dropck.stderr @@ -2,7 +2,7 @@ error[E0597]: `*cell` does not live long enough --> $DIR/dropck.rs:10:40 | LL | let ref_ = Box::leak(Box::new(Some(cell.borrow_mut()))); - | ^^^^ borrowed value does not live long enough + | ^^^^^^^^^^^^^^^^^ borrowed value does not live long enough ... LL | } | - diff --git a/src/test/ui/generator/issue-88653.rs b/src/test/ui/generator/issue-88653.rs new file mode 100644 index 0000000000..ce9159b53e --- /dev/null +++ b/src/test/ui/generator/issue-88653.rs @@ -0,0 +1,19 @@ +// Regression test for #88653, where a confusing warning about a +// type mismatch in generator arguments was issued. + +#![feature(generators, generator_trait)] + +use std::ops::Generator; + +fn foo(bar: bool) -> impl Generator<(bool,)> { +//~^ ERROR: type mismatch in generator arguments [E0631] +//~| NOTE: expected signature of `fn((bool,)) -> _` + |bar| { + //~^ NOTE: found signature of `fn(bool) -> _` + if bar { + yield bar; + } + } +} + +fn main() {} diff --git a/src/test/ui/generator/issue-88653.stderr b/src/test/ui/generator/issue-88653.stderr new file mode 100644 index 0000000000..5bd8ad129f --- /dev/null +++ b/src/test/ui/generator/issue-88653.stderr @@ -0,0 +1,12 @@ +error[E0631]: type mismatch in generator arguments + --> $DIR/issue-88653.rs:8:22 + | +LL | fn foo(bar: bool) -> impl Generator<(bool,)> { + | ^^^^^^^^^^^^^^^^^^^^^^^ expected signature of `fn((bool,)) -> _` +... +LL | |bar| { + | ----- found signature of `fn(bool) -> _` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0631`. diff --git a/src/test/ui/generator/resume-arg-late-bound.nll.stderr b/src/test/ui/generator/resume-arg-late-bound.nll.stderr index 25bc6afc55..b5144c607a 100644 --- a/src/test/ui/generator/resume-arg-late-bound.nll.stderr +++ b/src/test/ui/generator/resume-arg-late-bound.nll.stderr @@ -6,6 +6,11 @@ LL | test(gen); | = note: expected type `for<'a> Generator<&'a mut bool>` found type `Generator<&mut bool>` +note: the lifetime requirement is introduced here + --> $DIR/resume-arg-late-bound.rs:8:17 + | +LL | fn test(a: impl for<'a> Generator<&'a mut bool>) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/generator/resume-arg-late-bound.stderr b/src/test/ui/generator/resume-arg-late-bound.stderr index 63411b5928..5e60e33584 100644 --- a/src/test/ui/generator/resume-arg-late-bound.stderr +++ b/src/test/ui/generator/resume-arg-late-bound.stderr @@ -6,7 +6,7 @@ LL | test(gen); | = note: expected type `for<'a> Generator<&'a mut bool>` found type `Generator<&mut bool>` -note: the required lifetime does not necessarily outlive the anonymous lifetime #1 defined on the body at 11:15 +note: the required lifetime does not necessarily outlive the anonymous lifetime #1 defined here --> $DIR/resume-arg-late-bound.rs:11:15 | LL | let gen = |arg: &mut bool| { @@ -29,7 +29,7 @@ LL | test(gen); | = note: expected type `for<'a> Generator<&'a mut bool>` found type `Generator<&mut bool>` -note: the anonymous lifetime #1 defined on the body at 11:15 doesn't meet the lifetime requirements +note: the anonymous lifetime #1 defined here doesn't meet the lifetime requirements --> $DIR/resume-arg-late-bound.rs:11:15 | LL | let gen = |arg: &mut bool| { diff --git a/src/test/ui/generator/static-not-unpin.stderr b/src/test/ui/generator/static-not-unpin.stderr index 7ae128d072..4ae745b0ff 100644 --- a/src/test/ui/generator/static-not-unpin.stderr +++ b/src/test/ui/generator/static-not-unpin.stderr @@ -2,7 +2,9 @@ error[E0277]: `[static generator@$DIR/static-not-unpin.rs:11:25: 13:6]` cannot b --> $DIR/static-not-unpin.rs:14:18 | LL | assert_unpin(generator); - | ^^^^^^^^^ the trait `Unpin` is not implemented for `[static generator@$DIR/static-not-unpin.rs:11:25: 13:6]` + | ------------ ^^^^^^^^^ the trait `Unpin` is not implemented for `[static generator@$DIR/static-not-unpin.rs:11:25: 13:6]` + | | + | required by a bound introduced by this call | = note: consider using `Box::pin` note: required by a bound in `assert_unpin` diff --git a/src/test/ui/generator/yield-in-box.rs b/src/test/ui/generator/yield-in-box.rs index 65f368df9c..dd6fa7c151 100644 --- a/src/test/ui/generator/yield-in-box.rs +++ b/src/test/ui/generator/yield-in-box.rs @@ -1,8 +1,10 @@ // run-pass - // Test that box-statements with yields in them work. -#![feature(generators, box_syntax)] +#![feature(generators, box_syntax, generator_trait)] +use std::pin::Pin; +use std::ops::Generator; +use std::ops::GeneratorState; fn main() { let x = 0i32; @@ -15,4 +17,8 @@ fn main() { _t => {} } }; + + let mut g = |_| box yield; + assert_eq!(Pin::new(&mut g).resume(1), GeneratorState::Yielded(())); + assert_eq!(Pin::new(&mut g).resume(2), GeneratorState::Complete(box 2)); } diff --git a/src/test/ui/generator/yield-in-box.stderr b/src/test/ui/generator/yield-in-box.stderr index 24de18edb0..7602e80394 100644 --- a/src/test/ui/generator/yield-in-box.stderr +++ b/src/test/ui/generator/yield-in-box.stderr @@ -1,5 +1,5 @@ warning: unused generator that must be used - --> $DIR/yield-in-box.rs:9:5 + --> $DIR/yield-in-box.rs:11:5 | LL | / || { LL | | let y = 2u32; diff --git a/src/test/ui/generic-associated-types/gat-in-trait-path.stderr b/src/test/ui/generic-associated-types/gat-in-trait-path.stderr index 8651789688..a55642490f 100644 --- a/src/test/ui/generic-associated-types/gat-in-trait-path.stderr +++ b/src/test/ui/generic-associated-types/gat-in-trait-path.stderr @@ -4,7 +4,6 @@ error[E0038]: the trait `Foo` cannot be made into an object LL | fn f(_arg : Box Foo = &'a ()>>) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Foo` cannot be made into an object | - = help: consider moving `A` to another trait note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit --> $DIR/gat-in-trait-path.rs:5:10 | @@ -12,6 +11,7 @@ LL | trait Foo { | --- this trait cannot be made into an object... LL | type A<'a> where Self: 'a; | ^ ...because it contains the generic associated type `A` + = help: consider moving `A` to another trait error: aborting due to previous error diff --git a/src/test/ui/generic-associated-types/impl_bounds.rs b/src/test/ui/generic-associated-types/impl_bounds.rs index 01edad00a8..ff2ffec22c 100644 --- a/src/test/ui/generic-associated-types/impl_bounds.rs +++ b/src/test/ui/generic-associated-types/impl_bounds.rs @@ -13,9 +13,9 @@ struct Fooy(T); impl Foo for Fooy { type A<'a> where Self: 'static = (&'a ()); - //~^ ERROR the parameter type `T` may not live long enough + //~^ ERROR `impl` associated type type B<'a, 'b> where 'b: 'a = (&'a(), &'b ()); - //~^ ERROR lifetime bound not satisfied + //~^ ERROR `impl` associated type //~| ERROR lifetime bound not satisfied type C where Self: Copy = String; //~^ ERROR the trait bound `T: Copy` is not satisfied diff --git a/src/test/ui/generic-associated-types/impl_bounds.stderr b/src/test/ui/generic-associated-types/impl_bounds.stderr index 8cf923ca3a..f47b5f81e2 100644 --- a/src/test/ui/generic-associated-types/impl_bounds.stderr +++ b/src/test/ui/generic-associated-types/impl_bounds.stderr @@ -1,11 +1,20 @@ -error[E0310]: the parameter type `T` may not live long enough +error: `impl` associated type signature for `A` doesn't match `trait` associated type signature --> $DIR/impl_bounds.rs:15:5 | +LL | type A<'a> where Self: 'a; + | -------------------------- expected +... LL | type A<'a> where Self: 'static = (&'a ()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found + +error: `impl` associated type signature for `B` doesn't match `trait` associated type signature + --> $DIR/impl_bounds.rs:17:5 | - = help: consider adding an explicit lifetime bound `T: 'static`... - = note: ...so that the type `Fooy` will meet its required lifetime bounds +LL | type B<'a, 'b> where 'a: 'b; + | ---------------------------- expected +... +LL | type B<'a, 'b> where 'b: 'a = (&'a(), &'b ()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found error[E0478]: lifetime bound not satisfied --> $DIR/impl_bounds.rs:17:5 @@ -13,29 +22,12 @@ error[E0478]: lifetime bound not satisfied LL | type B<'a, 'b> where 'b: 'a = (&'a(), &'b ()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: lifetime parameter instantiated with the lifetime `'b` as defined on the associated item at 17:16 - --> $DIR/impl_bounds.rs:17:16 - | -LL | type B<'a, 'b> where 'b: 'a = (&'a(), &'b ()); - | ^^ -note: but lifetime parameter must outlive the lifetime `'a` as defined on the associated item at 17:12 +note: lifetime parameter instantiated with the lifetime `'a` as defined here --> $DIR/impl_bounds.rs:17:12 | LL | type B<'a, 'b> where 'b: 'a = (&'a(), &'b ()); | ^^ - -error[E0478]: lifetime bound not satisfied - --> $DIR/impl_bounds.rs:17:5 - | -LL | type B<'a, 'b> where 'b: 'a = (&'a(), &'b ()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -note: lifetime parameter instantiated with the lifetime `'a` as defined on the associated item at 17:12 - --> $DIR/impl_bounds.rs:17:12 - | -LL | type B<'a, 'b> where 'b: 'a = (&'a(), &'b ()); - | ^^ -note: but lifetime parameter must outlive the lifetime `'b` as defined on the associated item at 17:16 +note: but lifetime parameter must outlive the lifetime `'b` as defined here --> $DIR/impl_bounds.rs:17:16 | LL | type B<'a, 'b> where 'b: 'a = (&'a(), &'b ()); @@ -93,5 +85,5 @@ LL | impl Foo for Fooy { error: aborting due to 5 previous errors -Some errors have detailed explanations: E0277, E0310, E0478. +Some errors have detailed explanations: E0277, E0478. For more information about an error, try `rustc --explain E0277`. diff --git a/src/test/ui/generic-associated-types/issue-67510-pass.stderr b/src/test/ui/generic-associated-types/issue-67510-pass.stderr index b4b89ab047..7dd1bdf891 100644 --- a/src/test/ui/generic-associated-types/issue-67510-pass.stderr +++ b/src/test/ui/generic-associated-types/issue-67510-pass.stderr @@ -4,7 +4,6 @@ error[E0038]: the trait `X` cannot be made into an object LL | fn _func1<'a>(_x: Box=&'a ()>>) {} | ^^^^^^^^^^^^^^^^^^^ `X` cannot be made into an object | - = help: consider moving `Y` to another trait note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit --> $DIR/issue-67510-pass.rs:4:10 | @@ -12,6 +11,7 @@ LL | trait X { | - this trait cannot be made into an object... LL | type Y<'a>; | ^ ...because it contains the generic associated type `Y` + = help: consider moving `Y` to another trait error: aborting due to previous error diff --git a/src/test/ui/generic-associated-types/issue-76535.stderr b/src/test/ui/generic-associated-types/issue-76535.stderr index 246454f061..0a7eb5dde6 100644 --- a/src/test/ui/generic-associated-types/issue-76535.stderr +++ b/src/test/ui/generic-associated-types/issue-76535.stderr @@ -20,7 +20,6 @@ error[E0038]: the trait `SuperTrait` cannot be made into an object LL | let sub: Box> = Box::new(SuperStruct::new(0)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `SuperTrait` cannot be made into an object | - = help: consider moving `SubType` to another trait note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit --> $DIR/issue-76535.rs:6:10 | @@ -28,6 +27,7 @@ LL | pub trait SuperTrait { | ---------- this trait cannot be made into an object... LL | type SubType<'a>: SubTrait; | ^^^^^^^ ...because it contains the generic associated type `SubType` + = help: consider moving `SubType` to another trait error[E0038]: the trait `SuperTrait` cannot be made into an object --> $DIR/issue-76535.rs:36:57 @@ -35,7 +35,6 @@ error[E0038]: the trait `SuperTrait` cannot be made into an object LL | let sub: Box> = Box::new(SuperStruct::new(0)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `SuperTrait` cannot be made into an object | - = help: consider moving `SubType` to another trait note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit --> $DIR/issue-76535.rs:6:10 | @@ -43,6 +42,7 @@ LL | pub trait SuperTrait { | ---------- this trait cannot be made into an object... LL | type SubType<'a>: SubTrait; | ^^^^^^^ ...because it contains the generic associated type `SubType` + = help: consider moving `SubType` to another trait = note: required because of the requirements on the impl of `CoerceUnsized>>>` for `Box` = note: required by cast to type `Box>>` diff --git a/src/test/ui/generic-associated-types/issue-78113-lifetime-mismatch-dyn-trait-box.stderr b/src/test/ui/generic-associated-types/issue-78113-lifetime-mismatch-dyn-trait-box.stderr index 8ff6cb569b..24be83024b 100644 --- a/src/test/ui/generic-associated-types/issue-78113-lifetime-mismatch-dyn-trait-box.stderr +++ b/src/test/ui/generic-associated-types/issue-78113-lifetime-mismatch-dyn-trait-box.stderr @@ -9,7 +9,7 @@ note: because this has an unmet lifetime requirement | LL | type T<'a>: A; | ^ introduces a `'static` lifetime requirement -note: the lifetime `'a` as defined on the associated item at 17:12... +note: the lifetime `'a` as defined here... --> $DIR/issue-78113-lifetime-mismatch-dyn-trait-box.rs:17:12 | LL | type T<'a> = Box; @@ -36,7 +36,7 @@ note: because this has an unmet lifetime requirement | LL | type T<'a>: C; | ^ introduces a `'static` lifetime requirement -note: the lifetime `'a` as defined on the associated item at 27:12... +note: the lifetime `'a` as defined here... --> $DIR/issue-78113-lifetime-mismatch-dyn-trait-box.rs:27:12 | LL | type T<'a> = Box; @@ -58,7 +58,7 @@ note: because this has an unmet lifetime requirement | LL | type T<'a>: E; | ^ introduces a `'static` lifetime requirement -note: the lifetime `'a` as defined on the associated item at 37:12... +note: the lifetime `'a` as defined here... --> $DIR/issue-78113-lifetime-mismatch-dyn-trait-box.rs:37:12 | LL | type T<'a> = (Box, Box); diff --git a/src/test/ui/generic-associated-types/issue-78671.stderr b/src/test/ui/generic-associated-types/issue-78671.stderr index b927308395..17dd0ff4a0 100644 --- a/src/test/ui/generic-associated-types/issue-78671.stderr +++ b/src/test/ui/generic-associated-types/issue-78671.stderr @@ -20,7 +20,6 @@ error[E0038]: the trait `CollectionFamily` cannot be made into an object LL | Box::new(Family) as &dyn CollectionFamily | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `CollectionFamily` cannot be made into an object | - = help: consider moving `Member` to another trait note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit --> $DIR/issue-78671.rs:4:10 | @@ -28,6 +27,7 @@ LL | trait CollectionFamily { | ---------------- this trait cannot be made into an object... LL | type Member; | ^^^^^^ ...because it contains the generic associated type `Member` + = help: consider moving `Member` to another trait error: aborting due to 2 previous errors diff --git a/src/test/ui/generic-associated-types/issue-79422.stderr b/src/test/ui/generic-associated-types/issue-79422.stderr index 8d8ef6bf83..b6f856a97e 100644 --- a/src/test/ui/generic-associated-types/issue-79422.stderr +++ b/src/test/ui/generic-associated-types/issue-79422.stderr @@ -20,7 +20,6 @@ error[E0038]: the trait `MapLike` cannot be made into an object LL | as Box>>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `MapLike` cannot be made into an object | - = help: consider moving `VRefCont` to another trait note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit --> $DIR/issue-79422.rs:20:10 | @@ -28,6 +27,7 @@ LL | trait MapLike { | ------- this trait cannot be made into an object... LL | type VRefCont<'a>: RefCont<'a, V>; | ^^^^^^^^ ...because it contains the generic associated type `VRefCont` + = help: consider moving `VRefCont` to another trait error[E0038]: the trait `MapLike` cannot be made into an object --> $DIR/issue-79422.rs:41:13 @@ -35,7 +35,6 @@ error[E0038]: the trait `MapLike` cannot be made into an object LL | let m = Box::new(std::collections::BTreeMap::::new()) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `MapLike` cannot be made into an object | - = help: consider moving `VRefCont` to another trait note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit --> $DIR/issue-79422.rs:20:10 | @@ -43,6 +42,7 @@ LL | trait MapLike { | ------- this trait cannot be made into an object... LL | type VRefCont<'a>: RefCont<'a, V>; | ^^^^^^^^ ...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 + 'static)>>>` for `Box>` = note: required by cast to type `Box + 'static)>>` diff --git a/src/test/ui/generic-associated-types/issue-86787.rs b/src/test/ui/generic-associated-types/issue-86787.rs index 57d478a9ef..f1f05ea662 100644 --- a/src/test/ui/generic-associated-types/issue-86787.rs +++ b/src/test/ui/generic-associated-types/issue-86787.rs @@ -21,8 +21,8 @@ where { type T = Either; type TRef<'a> - //~^ the associated type - //~^^ the associated type + //~^ `impl` associated type signature + //~^^ `impl` associated type signature where ::T: 'a, ::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 04cd84b080..648eff77d7 100644 --- a/src/test/ui/generic-associated-types/issue-86787.stderr +++ b/src/test/ui/generic-associated-types/issue-86787.stderr @@ -1,29 +1,32 @@ -error[E0309]: the associated type `::T` may not live long enough +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 | | ::T: 'a, LL | | ::T: 'a - | | - help: consider adding a where clause: `, ::T: 'a` LL | | = Either<&'a Left::T, &'a Right::T>; - | |________________________________________^ ...so that the type `::T` will meet its required lifetime bounds + | |________________________________________^ found -error[E0309]: the associated type `::T` may not live long enough +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 | | ::T: 'a, LL | | ::T: 'a - | | - help: consider adding a where clause: `, ::T: 'a` LL | | = Either<&'a Left::T, &'a Right::T>; - | |________________________________________^ ...so that the type `::T` will meet its required lifetime bounds + | |________________________________________^ found error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0309`. diff --git a/src/test/ui/generic-associated-types/issue-87748.rs b/src/test/ui/generic-associated-types/issue-87748.rs deleted file mode 100644 index 93c3b3937c..0000000000 --- a/src/test/ui/generic-associated-types/issue-87748.rs +++ /dev/null @@ -1,30 +0,0 @@ -// Checks that we properly add implied bounds from unnormalized projections in -// inputs when typechecking functions. - -// check-pass - -#![feature(generic_associated_types)] - -trait MyTrait { - type Assoc<'a, 'b> where 'b: 'a; - fn do_sth(arg: Self::Assoc<'_, '_>); -} - -struct A; -struct B; -struct C; - -impl MyTrait for A { - type Assoc<'a, 'b> where 'b: 'a = u32; - fn do_sth(_: u32) {} -} -impl MyTrait for B { - type Assoc<'a, 'b> where 'b: 'a = u32; - fn do_sth(_: Self::Assoc<'_, '_>) {} -} -impl MyTrait for C { - type Assoc<'a, 'b> where 'b: 'a = u32; - fn do_sth(_: Self::Assoc<'static, 'static>) {} -} - -fn main () {} diff --git a/src/test/ui/generic-associated-types/issue-87750.rs b/src/test/ui/generic-associated-types/issue-87750.rs new file mode 100644 index 0000000000..89bd79ac29 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-87750.rs @@ -0,0 +1,22 @@ +#![feature(generic_associated_types)] + +trait PointerFamily { + type Pointer; +} + +struct Rc(Box); +struct RcFamily; + +impl PointerFamily for RcFamily { + type Pointer = Rc; +} + +#[allow(dead_code)] +enum Node where P::Pointer>: Sized { + Cons(P::Pointer>), +} + +fn main() { + let _list: ::Pointer>; + //~^ ERROR overflow evaluating the requirement `Node: Sized` +} diff --git a/src/test/ui/generic-associated-types/issue-87750.stderr b/src/test/ui/generic-associated-types/issue-87750.stderr new file mode 100644 index 0000000000..854541f3d8 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-87750.stderr @@ -0,0 +1,9 @@ +error[E0275]: overflow evaluating the requirement `Node: Sized` + --> $DIR/issue-87750.rs:20:16 + | +LL | let _list: ::Pointer>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0275`. diff --git a/src/test/ui/generic-associated-types/issue-88287.rs b/src/test/ui/generic-associated-types/issue-88287.rs new file mode 100644 index 0000000000..2e65af594a --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-88287.rs @@ -0,0 +1,39 @@ +// check-pass +// edition:2018 + +#![feature(generic_associated_types)] +#![feature(type_alias_impl_trait)] + +use std::future::Future; + +trait SearchableResource { + type SearchResult; +} + +trait SearchableResourceExt: SearchableResource { + type Future<'f, A: 'f + ?Sized, B: 'f>: Future, ()>> + 'f + where + A: SearchableResource; + + fn search<'c>(&'c self, client: &'c ()) -> Self::Future<'c, Self, Criteria>; +} + +type SearchFutureTy<'f, A, B: 'f> +where + A: SearchableResource + ?Sized + 'f, += impl Future, ()>> + 'f; +impl SearchableResourceExt for T +where + T: SearchableResource, +{ + type Future<'f, A, B: 'f> + where + A: SearchableResource + ?Sized + 'f, + = SearchFutureTy<'f, A, B>; + + fn search<'c>(&'c self, _client: &'c ()) -> Self::Future<'c, Self, Criteria> { + async move { todo!() } + } +} + +fn main() {} diff --git a/src/test/ui/generic-associated-types/issue-88360.rs b/src/test/ui/generic-associated-types/issue-88360.rs new file mode 100644 index 0000000000..06af3f5ec9 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-88360.rs @@ -0,0 +1,19 @@ +#![feature(generic_associated_types)] + +trait GatTrait { + type Gat<'a>; + + fn test(&self) -> Self::Gat<'_>; +} + +trait SuperTrait +where + for<'a> Self: GatTrait = &'a T>, +{ + fn copy(&self) -> Self::Gat<'_> where T: Copy { + *self.test() + //~^ mismatched types + } +} + +fn main() {} diff --git a/src/test/ui/generic-associated-types/issue-88360.stderr b/src/test/ui/generic-associated-types/issue-88360.stderr new file mode 100644 index 0000000000..cfbf3aaa4e --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-88360.stderr @@ -0,0 +1,20 @@ +error[E0308]: mismatched types + --> $DIR/issue-88360.rs:14:9 + | +LL | trait SuperTrait + | - this type parameter +... +LL | fn copy(&self) -> Self::Gat<'_> where T: Copy { + | ------------- expected `&T` because of return type +LL | *self.test() + | ^^^^^^^^^^^^ + | | + | expected `&T`, found type parameter `T` + | help: consider borrowing here: `&*self.test()` + | + = note: expected reference `&T` + found type parameter `T` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/generic-associated-types/issue-88405.rs b/src/test/ui/generic-associated-types/issue-88405.rs new file mode 100644 index 0000000000..4a405bd362 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-88405.rs @@ -0,0 +1,16 @@ +// check-pass + +#![feature(generic_associated_types)] + +trait SomeTrait {} +trait OtherTrait { + type Item; +} + +trait ErrorSimpleExample { + type AssociatedType: SomeTrait; + type GatBounded; + type ErrorMinimal: OtherTrait>; +} + +fn main() {} diff --git a/src/test/ui/generic-associated-types/missing-where-clause-on-trait.rs b/src/test/ui/generic-associated-types/missing-where-clause-on-trait.rs new file mode 100644 index 0000000000..ad9f2e3e4e --- /dev/null +++ b/src/test/ui/generic-associated-types/missing-where-clause-on-trait.rs @@ -0,0 +1,13 @@ +// check-fail + +#![feature(generic_associated_types)] + +trait Foo { + type Assoc<'a, 'b>; +} +impl Foo for () { + type Assoc<'a, 'b> where 'a: 'b = (); + //~^ `impl` associated type +} + +fn main() {} diff --git a/src/test/ui/generic-associated-types/missing-where-clause-on-trait.stderr b/src/test/ui/generic-associated-types/missing-where-clause-on-trait.stderr new file mode 100644 index 0000000000..0e183c8d69 --- /dev/null +++ b/src/test/ui/generic-associated-types/missing-where-clause-on-trait.stderr @@ -0,0 +1,11 @@ +error: `impl` associated type signature for `Assoc` doesn't match `trait` associated type signature + --> $DIR/missing-where-clause-on-trait.rs:9:5 + | +LL | type Assoc<'a, 'b>; + | ------------------- expected +... +LL | type Assoc<'a, 'b> where 'a: 'b = (); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found + +error: aborting due to previous error + diff --git a/src/test/ui/generic-associated-types/trait-objects.stderr b/src/test/ui/generic-associated-types/trait-objects.stderr index 6429bb8159..5ab3791020 100644 --- a/src/test/ui/generic-associated-types/trait-objects.stderr +++ b/src/test/ui/generic-associated-types/trait-objects.stderr @@ -4,7 +4,6 @@ error[E0038]: the trait `StreamingIterator` cannot be made into an object LL | fn min_size(x: &mut dyn for<'a> StreamingIterator = &'a i32>) -> usize { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `StreamingIterator` cannot be made into an object | - = help: consider moving `Item` to another trait note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit --> $DIR/trait-objects.rs:4:10 | @@ -12,6 +11,7 @@ LL | trait StreamingIterator { | ----------------- this trait cannot be made into an object... LL | type Item<'a> where Self: 'a; | ^^^^ ...because it contains the generic associated type `Item` + = help: consider moving `Item` to another trait error: aborting due to previous error diff --git a/src/test/ui/generic-associated-types/unsatified-item-lifetime-bound.stderr b/src/test/ui/generic-associated-types/unsatified-item-lifetime-bound.stderr index 772d027685..4f0a023ee3 100644 --- a/src/test/ui/generic-associated-types/unsatified-item-lifetime-bound.stderr +++ b/src/test/ui/generic-associated-types/unsatified-item-lifetime-bound.stderr @@ -12,7 +12,7 @@ error[E0478]: lifetime bound not satisfied LL | f: ::Y<'a>, | ^^^^^^^^^^^^^^^ | -note: lifetime parameter instantiated with the lifetime `'a` as defined on the struct at 12:10 +note: lifetime parameter instantiated with the lifetime `'a` as defined here --> $DIR/unsatified-item-lifetime-bound.rs:12:10 | LL | struct B<'a, T: for<'r> X = &'r ()>> { @@ -25,7 +25,7 @@ error[E0478]: lifetime bound not satisfied LL | f: ::Y<'a>, | ^^^^^^^^^^^^^^^ | -note: lifetime parameter instantiated with the lifetime `'a` as defined on the struct at 17:10 +note: lifetime parameter instantiated with the lifetime `'a` as defined here --> $DIR/unsatified-item-lifetime-bound.rs:17:10 | LL | struct C<'a, T: X> { @@ -38,7 +38,7 @@ error[E0478]: lifetime bound not satisfied LL | f: <() as X>::Y<'a>, | ^^^^^^^^^^^^^^^^ | -note: lifetime parameter instantiated with the lifetime `'a` as defined on the struct at 22:10 +note: lifetime parameter instantiated with the lifetime `'a` as defined here --> $DIR/unsatified-item-lifetime-bound.rs:22:10 | LL | struct D<'a> { diff --git a/src/test/ui/generic-associated-types/unsatisfied-outlives-bound.stderr b/src/test/ui/generic-associated-types/unsatisfied-outlives-bound.stderr index 8237d3718c..ebb4789345 100644 --- a/src/test/ui/generic-associated-types/unsatisfied-outlives-bound.stderr +++ b/src/test/ui/generic-associated-types/unsatisfied-outlives-bound.stderr @@ -4,7 +4,7 @@ error[E0477]: the type `&'b ()` does not fulfill the required lifetime LL | type Item<'a> = &'b (); | ^^^^^^^^^^^^^^^^^^^^^^^ | -note: type must outlive the lifetime `'a` as defined on the associated item at 8:15 as required by this binding +note: type must outlive the lifetime `'a` as defined here as required by this binding --> $DIR/unsatisfied-outlives-bound.rs:8:15 | LL | type Item<'a> = &'b (); diff --git a/src/test/ui/generics/generic-alias-unique.rs b/src/test/ui/generics/generic-alias-unique.rs index 76a184d8d2..fc13839863 100644 --- a/src/test/ui/generics/generic-alias-unique.rs +++ b/src/test/ui/generics/generic-alias-unique.rs @@ -1,10 +1,9 @@ // run-pass -#![feature(box_syntax)] fn id(t: T) -> T { return t; } pub fn main() { - let expected: Box<_> = box 100; + let expected: Box<_> = Box::new(100); let actual = id::>(expected.clone()); println!("{}", *actual); assert_eq!(*expected, *actual); diff --git a/src/test/ui/generics/generic-exterior-unique.rs b/src/test/ui/generics/generic-exterior-unique.rs index 9b3e1ee02a..10d87f9f43 100644 --- a/src/test/ui/generics/generic-exterior-unique.rs +++ b/src/test/ui/generics/generic-exterior-unique.rs @@ -1,9 +1,8 @@ // run-pass -#![feature(box_syntax)] struct Recbox {x: Box} -fn reclift(t: T) -> Recbox { return Recbox {x: box t}; } +fn reclift(t: T) -> Recbox { return Recbox { x: Box::new(t) }; } pub fn main() { let foo: isize = 17; diff --git a/src/test/ui/generics/generic-fn-unique.rs b/src/test/ui/generics/generic-fn-unique.rs index 6cda1c3dc1..7e246bce9a 100644 --- a/src/test/ui/generics/generic-fn-unique.rs +++ b/src/test/ui/generics/generic-fn-unique.rs @@ -1,6 +1,8 @@ // run-pass -#![feature(box_syntax)] fn f(x: Box) -> Box { return x; } -pub fn main() { let x = f(box 3); println!("{}", *x); } +pub fn main() { + let x = f(Box::new(3)); + println!("{}", *x); +} diff --git a/src/test/ui/generics/generic-object.rs b/src/test/ui/generics/generic-object.rs index 870ff980ec..851424a11b 100644 --- a/src/test/ui/generics/generic-object.rs +++ b/src/test/ui/generics/generic-object.rs @@ -1,5 +1,4 @@ // run-pass -#![feature(box_syntax)] trait Foo { fn get(&self) -> T; @@ -16,7 +15,7 @@ impl Foo for S { } pub fn main() { - let x = box S { x: 1 }; + let x = Box::new(S { x: 1 }); let y = x as Box>; assert_eq!(y.get(), 1); } diff --git a/src/test/ui/generics/generic-recursive-tag.rs b/src/test/ui/generics/generic-recursive-tag.rs index e1875f0abb..74f5b701d9 100644 --- a/src/test/ui/generics/generic-recursive-tag.rs +++ b/src/test/ui/generics/generic-recursive-tag.rs @@ -1,13 +1,12 @@ // run-pass #![allow(non_camel_case_types)] -#![feature(box_syntax)] enum list { cons(Box, Box>), nil, } pub fn main() { let _a: list = - list::cons::(box 10, - box list::cons::(box 12, - box list::cons::(box 13, - box list::nil::))); + list::cons::(Box::new(10), + Box::new(list::cons::(Box::new(12), + Box::new(list::cons::(Box::new(13), + Box::new(list::nil::)))))); } diff --git a/src/test/ui/generics/generic-tag.rs b/src/test/ui/generics/generic-tag.rs index 74ef4eeba8..67f2ccdde3 100644 --- a/src/test/ui/generics/generic-tag.rs +++ b/src/test/ui/generics/generic-tag.rs @@ -5,11 +5,10 @@ // pretty-expanded FIXME #23616 #![allow(unused_variables)] -#![feature(box_syntax)] enum option { some(Box), none, } pub fn main() { - let mut a: option = option::some::(box 10); + let mut a: option = option::some::(Box::new(10)); a = option::none::; } diff --git a/src/test/ui/generics/generic-unique.rs b/src/test/ui/generics/generic-unique.rs index d36504c75d..2f34712ecf 100644 --- a/src/test/ui/generics/generic-unique.rs +++ b/src/test/ui/generics/generic-unique.rs @@ -1,10 +1,9 @@ // run-pass #![allow(dead_code)] -#![feature(box_syntax)] struct Triple { x: T, y: T, z: T } -fn box_it(x: Triple) -> Box> { return box x; } +fn box_it(x: Triple) -> Box> { return Box::new(x); } pub fn main() { let x: Box> = box_it::(Triple{x: 1, y: 2, z: 3}); diff --git a/src/test/ui/mid-path-type-params.rs b/src/test/ui/generics/mid-path-type-params.rs similarity index 100% rename from src/test/ui/mid-path-type-params.rs rename to src/test/ui/generics/mid-path-type-params.rs diff --git a/src/test/ui/generics/wrong-number-of-args.stderr b/src/test/ui/generics/wrong-number-of-args.stderr index 98e5cd6bab..22da0dffbf 100644 --- a/src/test/ui/generics/wrong-number-of-args.stderr +++ b/src/test/ui/generics/wrong-number-of-args.stderr @@ -440,17 +440,6 @@ note: trait defined here, with 1 lifetime parameter: `'a` LL | trait GenericLifetimeAT<'a> { | ^^^^^^^^^^^^^^^^^ -- -error[E0106]: missing lifetime specifier - --> $DIR/wrong-number-of-args.rs:169:44 - | -LL | type C = Box>; - | ^ expected named lifetime parameter - | -help: consider introducing a named lifetime parameter - | -LL | type C<'a> = Box>; - | ++++ +++ - error[E0107]: this trait takes 0 generic arguments but 1 generic argument was supplied --> $DIR/wrong-number-of-args.rs:169:26 | @@ -465,6 +454,17 @@ note: trait defined here, with 0 generic parameters LL | trait GenericLifetimeAT<'a> { | ^^^^^^^^^^^^^^^^^ +error[E0106]: missing lifetime specifier + --> $DIR/wrong-number-of-args.rs:169:44 + | +LL | type C = Box>; + | ^ expected named lifetime parameter + | +help: consider introducing a named lifetime parameter + | +LL | type C<'a> = Box>; + | ++++ +++ + error[E0107]: this trait takes 1 generic argument but 0 generic arguments were supplied --> $DIR/wrong-number-of-args.rs:181:26 | @@ -525,17 +525,6 @@ help: add missing generic argument LL | type C = Box>; | +++ -error[E0106]: missing lifetime specifier - --> $DIR/wrong-number-of-args.rs:201:48 - | -LL | type A = Box>; - | ^ expected named lifetime parameter - | -help: consider introducing a named lifetime parameter - | -LL | type A<'a> = Box>; - | ++++ +++ - error[E0107]: this trait takes 1 generic argument but 0 generic arguments were supplied --> $DIR/wrong-number-of-args.rs:201:26 | @@ -552,6 +541,17 @@ help: add missing generic argument LL | type A = Box>; | ++ +error[E0106]: missing lifetime specifier + --> $DIR/wrong-number-of-args.rs:201:48 + | +LL | type A = Box>; + | ^ expected named lifetime parameter + | +help: consider introducing a named lifetime parameter + | +LL | type A<'a> = Box>; + | ++++ +++ + error[E0107]: this trait takes 1 generic argument but 0 generic arguments were supplied --> $DIR/wrong-number-of-args.rs:207:26 | @@ -609,17 +609,6 @@ help: consider introducing a named lifetime parameter LL | type D<'a> = Box>; | ++++ +++ -error[E0106]: missing lifetime specifier - --> $DIR/wrong-number-of-args.rs:221:48 - | -LL | type E = Box>; - | ^ expected named lifetime parameter - | -help: consider introducing a named lifetime parameter - | -LL | type E<'a> = Box>; - | ++++ +++ - error[E0107]: this trait takes 1 generic argument but 2 generic arguments were supplied --> $DIR/wrong-number-of-args.rs:221:26 | @@ -634,6 +623,17 @@ note: trait defined here, with 1 generic parameter: `A` LL | trait GenericLifetimeTypeAT<'a, A> { | ^^^^^^^^^^^^^^^^^^^^^ - +error[E0106]: missing lifetime specifier + --> $DIR/wrong-number-of-args.rs:221:48 + | +LL | type E = Box>; + | ^ expected named lifetime parameter + | +help: consider introducing a named lifetime parameter + | +LL | type E<'a> = Box>; + | ++++ +++ + error[E0107]: this trait takes 1 lifetime argument but 2 lifetime arguments were supplied --> $DIR/wrong-number-of-args.rs:227:26 | @@ -767,17 +767,6 @@ help: add missing lifetime argument LL | type B = Box>; | ++++ -error[E0106]: missing lifetime specifiers - --> $DIR/wrong-number-of-args.rs:279:56 - | -LL | type A = Box>; - | ^ expected 2 lifetime parameters - | -help: consider introducing a named lifetime parameter - | -LL | type A<'a> = Box>; - | ++++ +++++++ - error[E0107]: this trait takes 1 generic argument but 0 generic arguments were supplied --> $DIR/wrong-number-of-args.rs:279:26 | @@ -794,6 +783,17 @@ help: add missing generic argument LL | type A = Box>; | ++ +error[E0106]: missing lifetime specifiers + --> $DIR/wrong-number-of-args.rs:279:56 + | +LL | type A = Box>; + | ^ expected 2 lifetime parameters + | +help: consider introducing a named lifetime parameter + | +LL | type A<'a> = Box>; + | ++++ +++++++ + error[E0107]: this trait takes 2 lifetime arguments but 1 lifetime argument was supplied --> $DIR/wrong-number-of-args.rs:285:26 | diff --git a/src/test/ui/half-open-range-patterns/half-open-range-pats-inclusive-dotdotdot-bad-syntax.stderr b/src/test/ui/half-open-range-patterns/half-open-range-pats-inclusive-dotdotdot-bad-syntax.stderr index 8584b650ae..da37ff3016 100644 --- a/src/test/ui/half-open-range-patterns/half-open-range-pats-inclusive-dotdotdot-bad-syntax.stderr +++ b/src/test/ui/half-open-range-patterns/half-open-range-pats-inclusive-dotdotdot-bad-syntax.stderr @@ -29,7 +29,7 @@ LL | let ...$e; | ^^^ help: use `..=` instead ... LL | mac!(0); - | -------- in this macro invocation + | ------- in this macro invocation | = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/half-open-range-patterns/half-open-range-pats-inclusive-no-end.stderr b/src/test/ui/half-open-range-patterns/half-open-range-pats-inclusive-no-end.stderr index 42c55de28e..5a504a90b5 100644 --- a/src/test/ui/half-open-range-patterns/half-open-range-pats-inclusive-no-end.stderr +++ b/src/test/ui/half-open-range-patterns/half-open-range-pats-inclusive-no-end.stderr @@ -37,7 +37,7 @@ LL | let $e...; | ^^^ help: use `..` instead ... LL | mac!(0); - | -------- in this macro invocation + | ------- in this macro invocation | = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -49,7 +49,7 @@ LL | let $e..=; | ^^^ help: use `..` instead ... LL | mac!(0); - | -------- in this macro invocation + | ------- in this macro invocation | = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/hashmap/hashmap-iter-value-lifetime.nll.stderr b/src/test/ui/hashmap/hashmap-iter-value-lifetime.nll.stderr deleted file mode 100644 index 312a91adca..0000000000 --- a/src/test/ui/hashmap/hashmap-iter-value-lifetime.nll.stderr +++ /dev/null @@ -1,15 +0,0 @@ -error[E0502]: cannot borrow `my_stuff` as mutable because it is also borrowed as immutable - --> $DIR/hashmap-iter-value-lifetime.rs:7:5 - | -LL | let (_, thing) = my_stuff.iter().next().unwrap(); - | -------- immutable borrow occurs here -LL | -LL | my_stuff.clear(); - | ^^^^^^^^ mutable borrow occurs here -LL | -LL | println!("{}", *thing); - | ------ immutable borrow later used here - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0502`. diff --git a/src/test/ui/hashmap/hashmap-iter-value-lifetime.stderr b/src/test/ui/hashmap/hashmap-iter-value-lifetime.stderr index f7626b13ba..0724fec905 100644 --- a/src/test/ui/hashmap/hashmap-iter-value-lifetime.stderr +++ b/src/test/ui/hashmap/hashmap-iter-value-lifetime.stderr @@ -2,7 +2,7 @@ error[E0502]: cannot borrow `my_stuff` as mutable because it is also borrowed as --> $DIR/hashmap-iter-value-lifetime.rs:7:5 | LL | let (_, thing) = my_stuff.iter().next().unwrap(); - | -------- immutable borrow occurs here + | --------------- immutable borrow occurs here LL | LL | my_stuff.clear(); | ^^^^^^^^^^^^^^^^ mutable borrow occurs here diff --git a/src/test/ui/hashmap/hashmap-lifetimes.nll.stderr b/src/test/ui/hashmap/hashmap-lifetimes.nll.stderr deleted file mode 100644 index aa8e890c16..0000000000 --- a/src/test/ui/hashmap/hashmap-lifetimes.nll.stderr +++ /dev/null @@ -1,13 +0,0 @@ -error[E0502]: cannot borrow `my_stuff` as mutable because it is also borrowed as immutable - --> $DIR/hashmap-lifetimes.rs:6:5 - | -LL | let mut it = my_stuff.iter(); - | -------- immutable borrow occurs here -LL | my_stuff.insert(1, 43); - | ^^^^^^^^ mutable borrow occurs here -LL | it; - | -- immutable borrow later used here - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0502`. diff --git a/src/test/ui/hashmap/hashmap-lifetimes.stderr b/src/test/ui/hashmap/hashmap-lifetimes.stderr index 497c7d1216..d1bcd53ae3 100644 --- a/src/test/ui/hashmap/hashmap-lifetimes.stderr +++ b/src/test/ui/hashmap/hashmap-lifetimes.stderr @@ -2,7 +2,7 @@ error[E0502]: cannot borrow `my_stuff` as mutable because it is also borrowed as --> $DIR/hashmap-lifetimes.rs:6:5 | LL | let mut it = my_stuff.iter(); - | -------- immutable borrow occurs here + | --------------- immutable borrow occurs here LL | my_stuff.insert(1, 43); | ^^^^^^^^^^^^^^^^^^^^^^ mutable borrow occurs here LL | it; 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 8311c147ee..b13226fef6 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,11 +1,19 @@ error[E0631]: type mismatch in closure arguments --> $DIR/issue-62529-1.rs:80:10 | -LL | task(annotate( - | ^^^^^^^^ expected signature of `for<'r> fn( as FamilyLt<'r>>::Out) -> _` -... -LL | |value: &mut usize| { - | ------------------- found signature of `for<'r> fn(&'r mut usize) -> _` +LL | task(annotate( + | _____----_^ + | | | + | | required by a bound introduced by this call +LL | | +LL | | +LL | | Annotate::>::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( as FamilyLt<'r>>::Out) -> _` | note: required by a bound in `annotate` --> $DIR/issue-62529-1.rs:44:8 @@ -20,7 +28,9 @@ error[E0277]: the size for values of type `impl Execute` cannot be known at comp --> $DIR/issue-62529-1.rs:80:10 | LL | task(annotate( - | __________^ + | _____----_^ + | | | + | | required by a bound introduced by this call LL | | LL | | LL | | Annotate::>::new(), @@ -44,7 +54,9 @@ error[E0277]: the trait bound `impl Execute: Execute` is not satisfied --> $DIR/issue-62529-1.rs:80:10 | LL | task(annotate( - | __________^ + | _____----_^ + | | | + | | required by a bound introduced by this call LL | | LL | | LL | | Annotate::>::new(), diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-80706.rs b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-80706.rs new file mode 100644 index 0000000000..112227c85c --- /dev/null +++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-80706.rs @@ -0,0 +1,70 @@ +// check-pass +// edition:2018 + +type BoxFuture = std::pin::Pin>>; + +fn main() { + f(); +} + +async fn f() { + run("dependency").await; +} + +struct InMemoryStorage; + +struct User<'dep> { + dep: &'dep str, +} + +impl<'a> StorageRequest for SaveUser<'a> { + fn execute(&self) -> BoxFuture> { + todo!() + } +} + +trait Storage { + type Error; +} + +impl Storage for InMemoryStorage { + type Error = String; +} + +trait StorageRequestReturnType { + type Output; +} + +trait StorageRequest: StorageRequestReturnType { + fn execute( + &self, + ) -> BoxFuture::Output, ::Error>>; +} + +struct SaveUser<'a> { + name: &'a str, +} + +impl<'a> StorageRequestReturnType for SaveUser<'a> { + type Output = (); +} + +impl<'dep> User<'dep> { + async fn save(self) + where + S: Storage, + for<'a> SaveUser<'a>: StorageRequest, + { + SaveUser { name: "Joe" } + .execute() + .await; + } +} + +async fn run(dep: &str) +where + S: Storage, + for<'a> SaveUser<'a>: StorageRequest, +{ + User { dep }.save().await; +} diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-80956.rs b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-80956.rs new file mode 100644 index 0000000000..6316ceea15 --- /dev/null +++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-80956.rs @@ -0,0 +1,21 @@ +// check-pass + +trait Bar { + type Type; +} +struct Foo<'a>(&'a ()); +impl<'a> Bar for Foo<'a> { + type Type = (); +} + +fn func<'a>(_: as Bar>::Type) {} +fn assert_is_func(_: fn(A)) {} + +fn test() +where + for<'a> as Bar>::Type: Sized, +{ + assert_is_func(func); +} + +fn main() {} diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-81809.rs b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-81809.rs new file mode 100644 index 0000000000..f6ab9c203b --- /dev/null +++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-81809.rs @@ -0,0 +1,21 @@ +// check-pass + +pub trait Indexable { + type Idx; +} +impl Indexable for u8 { + type Idx = u8; +} +impl Indexable for u16 { + type Idx = u16; +} + +pub trait Indexer: std::ops::Index {} + +trait StoreIndex: Indexer + Indexer {} + +fn foo(st: &impl StoreIndex) -> &dyn StoreIndex { + st as &dyn StoreIndex +} + +fn main() {} diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-85455.rs b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-85455.rs new file mode 100644 index 0000000000..3a4d6c02a1 --- /dev/null +++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-85455.rs @@ -0,0 +1,18 @@ +#![feature(unboxed_closures)] + +trait SomeTrait<'a> { + type Associated; +} + +fn give_me_ice() { + callee:: >::Associated>(); + //~^ ERROR: the trait bound `T: SomeTrait<'_>` is not satisfied +} + +fn callee>() { + println!("{}", std::any::type_name::<>::Output>()); +} + +fn main() { + give_me_ice::<()>(); +} diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-85455.stderr b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-85455.stderr new file mode 100644 index 0000000000..aaf45dc7ad --- /dev/null +++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-85455.stderr @@ -0,0 +1,14 @@ +error[E0277]: the trait bound `T: SomeTrait<'_>` is not satisfied + --> $DIR/issue-85455.rs:8:5 + | +LL | callee:: >::Associated>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `SomeTrait<'_>` is not implemented for `T` + | +help: consider restricting type parameter `T` + | +LL | fn give_me_ice>() { + | +++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-89118.rs b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-89118.rs new file mode 100644 index 0000000000..fffb54f86c --- /dev/null +++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-89118.rs @@ -0,0 +1,32 @@ +trait BufferMut {} +struct Ctx(D); + +trait BufferUdpStateContext {} +impl BufferUdpStateContext for C {} + +trait StackContext +where + Ctx<()>: for<'a> BufferUdpStateContext<&'a ()>, +{ + type Dispatcher; +} + +trait TimerContext { + type Handler; +} +impl TimerContext for C +where + C: StackContext, + //~^ ERROR: is not satisfied [E0277] +{ + type Handler = Ctx; + //~^ ERROR: is not satisfied [E0277] +} + +struct EthernetWorker(C) +where + Ctx<()>: for<'a> BufferUdpStateContext<&'a ()>; +impl EthernetWorker {} +//~^ ERROR: is not satisfied [E0277] + +fn main() {} diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-89118.stderr b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-89118.stderr new file mode 100644 index 0000000000..7f45fb83ce --- /dev/null +++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-89118.stderr @@ -0,0 +1,63 @@ +error[E0277]: the trait bound `for<'a> &'a (): BufferMut` is not satisfied + --> $DIR/issue-89118.rs:19:8 + | +LL | C: StackContext, + | ^^^^^^^^^^^^ the trait `for<'a> BufferMut` is not implemented for `&'a ()` + | +note: required because of the requirements on the impl of `for<'a> BufferUdpStateContext<&'a ()>` for `Ctx<()>` + --> $DIR/issue-89118.rs:5:23 + | +LL | impl BufferUdpStateContext for C {} + | ^^^^^^^^^^^^^^^^^^^^^^^^ ^ +note: required by a bound in `StackContext` + --> $DIR/issue-89118.rs:9:14 + | +LL | trait StackContext + | ------------ required by a bound in this +LL | where +LL | Ctx<()>: for<'a> BufferUdpStateContext<&'a ()>, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `StackContext` + +error[E0277]: the trait bound `for<'a> &'a (): BufferMut` is not satisfied + --> $DIR/issue-89118.rs:22:20 + | +LL | type Handler = Ctx; + | ^^^^^^^^^^^^^^^^^^ the trait `for<'a> BufferMut` is not implemented for `&'a ()` + | +note: required because of the requirements on the impl of `for<'a> BufferUdpStateContext<&'a ()>` for `Ctx<()>` + --> $DIR/issue-89118.rs:5:23 + | +LL | impl BufferUdpStateContext for C {} + | ^^^^^^^^^^^^^^^^^^^^^^^^ ^ +note: required by a bound in `StackContext` + --> $DIR/issue-89118.rs:9:14 + | +LL | trait StackContext + | ------------ required by a bound in this +LL | where +LL | Ctx<()>: for<'a> BufferUdpStateContext<&'a ()>, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `StackContext` + +error[E0277]: the trait bound `for<'a> &'a (): BufferMut` is not satisfied + --> $DIR/issue-89118.rs:29:9 + | +LL | impl EthernetWorker {} + | ^^^^^^^^^^^^^^^^^ the trait `for<'a> BufferMut` is not implemented for `&'a ()` + | +note: required because of the requirements on the impl of `for<'a> BufferUdpStateContext<&'a ()>` for `Ctx<()>` + --> $DIR/issue-89118.rs:5:23 + | +LL | impl BufferUdpStateContext for C {} + | ^^^^^^^^^^^^^^^^^^^^^^^^ ^ +note: required by a bound in `EthernetWorker` + --> $DIR/issue-89118.rs:28:14 + | +LL | struct EthernetWorker(C) + | -------------- required by a bound in this +LL | where +LL | Ctx<()>: for<'a> BufferUdpStateContext<&'a ()>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `EthernetWorker` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_a_b_ret_a_vs_bound_a_ret_a.nll.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_a_b_ret_a_vs_bound_a_ret_a.nll.stderr index 439a113ef3..87d826021b 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_a_b_ret_a_vs_bound_a_ret_a.nll.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_a_b_ret_a_vs_bound_a_ret_a.nll.stderr @@ -8,8 +8,8 @@ LL | / check! { bound_a_b_ret_a_vs_bound_a_ret_a: (for<'a,'b> fn(&'a u32, &'b u3 LL | | for<'a> fn(&'a u32, &'a u32) -> &'a u32) } | |_____________________________________________- in this macro invocation | - = note: expected enum `Option fn(&'r u32, &'s u32) -> &'r u32>` - found enum `Option fn(&'r u32, &'r u32) -> &'r u32>` + = note: expected enum `Option fn(&'a u32, &'b u32) -> &'a u32>` + found enum `Option fn(&'a u32, &'a u32) -> &'a u32>` = note: this error originates in the macro `check` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to previous error diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_free_x.nll.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_free_x.nll.stderr index 61b3f0ca28..bd97f6f090 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_free_x.nll.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_free_x.nll.stderr @@ -8,7 +8,7 @@ LL | / check! { bound_a_vs_free_x: (for<'a> fn(&'a u32), LL | | fn(&'x u32)) } | |______________- in this macro invocation | - = note: expected enum `Option fn(&'r u32)>` + = note: expected enum `Option fn(&'a u32)>` found enum `Option` = note: this error originates in the macro `check` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_b_vs_bound_inv_a.nll.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_b_vs_bound_inv_a.nll.stderr index 75e2ba58f3..874909bf48 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_b_vs_bound_inv_a.nll.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_b_vs_bound_inv_a.nll.stderr @@ -8,8 +8,8 @@ LL | / check! { bound_inv_a_b_vs_bound_inv_a: (for<'a,'b> fn(Inv<'a>, Inv<'b>), LL | | for<'a> fn(Inv<'a>, Inv<'a>)) } | |__________________________________- in this macro invocation | - = note: expected enum `Option fn(Inv<'r>, Inv<'s>)>` - found enum `Option fn(Inv<'r>, Inv<'r>)>` + = note: expected enum `Option fn(Inv<'a>, Inv<'b>)>` + found enum `Option fn(Inv<'a>, Inv<'a>)>` = note: this error originates in the macro `check` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0308]: mismatched types @@ -22,8 +22,8 @@ LL | / check! { bound_inv_a_b_vs_bound_inv_a: (for<'a,'b> fn(Inv<'a>, Inv<'b>), LL | | for<'a> fn(Inv<'a>, Inv<'a>)) } | |__________________________________- in this macro invocation | - = note: expected enum `Option fn(Inv<'r>, Inv<'s>)>` - found enum `Option fn(Inv<'r>, Inv<'r>)>` + = note: expected enum `Option fn(Inv<'a>, Inv<'b>)>` + found enum `Option fn(Inv<'a>, Inv<'a>)>` = note: this error originates in the macro `check` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 2 previous errors diff --git a/src/test/ui/hr-subtype/hr-subtype.free_inv_x_vs_free_inv_y.stderr b/src/test/ui/hr-subtype/hr-subtype.free_inv_x_vs_free_inv_y.stderr index 8b0e36ab5f..9f20035722 100644 --- a/src/test/ui/hr-subtype/hr-subtype.free_inv_x_vs_free_inv_y.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.free_inv_x_vs_free_inv_y.stderr @@ -10,7 +10,7 @@ LL | | fn(Inv<'y>)) } | = note: expected enum `Option)>` found enum `Option)>` -note: the lifetime `'x` as defined on the function body at 38:20... +note: the lifetime `'x` as defined here... --> $DIR/hr-subtype.rs:38:20 | LL | fn subtype<'x, 'y: 'x, 'z: 'y>() { @@ -19,7 +19,7 @@ LL | fn subtype<'x, 'y: 'x, 'z: 'y>() { LL | / check! { free_inv_x_vs_free_inv_y: (fn(Inv<'x>), LL | | fn(Inv<'y>)) } | |______________- in this macro invocation -note: ...does not necessarily outlive the lifetime `'y` as defined on the function body at 38:24 +note: ...does not necessarily outlive the lifetime `'y` as defined here --> $DIR/hr-subtype.rs:38:24 | LL | fn subtype<'x, 'y: 'x, 'z: 'y>() { @@ -42,7 +42,7 @@ LL | | fn(Inv<'y>)) } | = note: expected enum `Option)>` found enum `Option)>` -note: the lifetime `'x` as defined on the function body at 44:22... +note: the lifetime `'x` as defined here... --> $DIR/hr-subtype.rs:44:22 | LL | fn supertype<'x, 'y: 'x, 'z: 'y>() { @@ -51,7 +51,7 @@ LL | fn supertype<'x, 'y: 'x, 'z: 'y>() { LL | / check! { free_inv_x_vs_free_inv_y: (fn(Inv<'x>), LL | | fn(Inv<'y>)) } | |______________- in this macro invocation -note: ...does not necessarily outlive the lifetime `'y` as defined on the function body at 44:26 +note: ...does not necessarily outlive the lifetime `'y` as defined here --> $DIR/hr-subtype.rs:44:26 | LL | fn supertype<'x, 'y: 'x, 'z: 'y>() { diff --git a/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_y.stderr b/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_y.stderr index fb1127f7f4..07add3d91a 100644 --- a/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_y.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_y.stderr @@ -10,7 +10,7 @@ LL | | fn(&'y u32)) } | = note: expected enum `Option` found enum `Option` -note: the lifetime `'x` as defined on the function body at 44:22... +note: the lifetime `'x` as defined here... --> $DIR/hr-subtype.rs:44:22 | LL | fn supertype<'x, 'y: 'x, 'z: 'y>() { @@ -19,7 +19,7 @@ LL | fn supertype<'x, 'y: 'x, 'z: 'y>() { LL | / check! { free_x_vs_free_y: (fn(&'x u32), LL | | fn(&'y u32)) } | |______________- in this macro invocation -note: ...does not necessarily outlive the lifetime `'y` as defined on the function body at 44:26 +note: ...does not necessarily outlive the lifetime `'y` as defined here --> $DIR/hr-subtype.rs:44:26 | LL | fn supertype<'x, 'y: 'x, 'z: 'y>() { diff --git a/src/test/ui/hrtb/hrtb-debruijn-in-receiver.stderr b/src/test/ui/hrtb/hrtb-debruijn-in-receiver.stderr index 70d5b3c2ec..fa391ecba8 100644 --- a/src/test/ui/hrtb/hrtb-debruijn-in-receiver.stderr +++ b/src/test/ui/hrtb/hrtb-debruijn-in-receiver.stderr @@ -2,9 +2,9 @@ error[E0499]: cannot borrow `foo` as mutable more than once at a time --> $DIR/hrtb-debruijn-in-receiver.rs:17:5 | LL | foo.insert(); - | --- first mutable borrow occurs here + | ------------ first mutable borrow occurs here LL | foo.insert(); - | ^^^ + | ^^^^^^^^^^^^ | | | second mutable borrow occurs here | first borrow later used here diff --git a/src/test/ui/hrtb/hrtb-higher-ranker-supertraits-transitive.stderr b/src/test/ui/hrtb/hrtb-higher-ranker-supertraits-transitive.stderr index d8267712c2..8cda76b949 100644 --- a/src/test/ui/hrtb/hrtb-higher-ranker-supertraits-transitive.stderr +++ b/src/test/ui/hrtb/hrtb-higher-ranker-supertraits-transitive.stderr @@ -2,7 +2,9 @@ error[E0277]: the trait bound `for<'ccx> B: Bar<'ccx>` is not satisfied --> $DIR/hrtb-higher-ranker-supertraits-transitive.rs:47:26 | LL | want_bar_for_any_ccx(b); - | ^ the trait `for<'ccx> Bar<'ccx>` is not implemented for `B` + | -------------------- ^ the trait `for<'ccx> Bar<'ccx>` is not implemented for `B` + | | + | required by a bound introduced by this call | note: required by a bound in `want_bar_for_any_ccx` --> $DIR/hrtb-higher-ranker-supertraits-transitive.rs:32:15 diff --git a/src/test/ui/hrtb/hrtb-higher-ranker-supertraits.stderr b/src/test/ui/hrtb/hrtb-higher-ranker-supertraits.stderr index a510c05055..88793a1525 100644 --- a/src/test/ui/hrtb/hrtb-higher-ranker-supertraits.stderr +++ b/src/test/ui/hrtb/hrtb-higher-ranker-supertraits.stderr @@ -2,7 +2,9 @@ error[E0277]: the trait bound `for<'tcx> F: Foo<'tcx>` is not satisfied --> $DIR/hrtb-higher-ranker-supertraits.rs:18:26 | LL | want_foo_for_any_tcx(f); - | ^ the trait `for<'tcx> Foo<'tcx>` is not implemented for `F` + | -------------------- ^ the trait `for<'tcx> Foo<'tcx>` is not implemented for `F` + | | + | required by a bound introduced by this call | note: required by a bound in `want_foo_for_any_tcx` --> $DIR/hrtb-higher-ranker-supertraits.rs:22:15 @@ -20,7 +22,9 @@ error[E0277]: the trait bound `for<'ccx> B: Bar<'ccx>` is not satisfied --> $DIR/hrtb-higher-ranker-supertraits.rs:35:26 | LL | want_bar_for_any_ccx(b); - | ^ the trait `for<'ccx> Bar<'ccx>` is not implemented for `B` + | -------------------- ^ the trait `for<'ccx> Bar<'ccx>` is not implemented for `B` + | | + | required by a bound introduced by this call | note: required by a bound in `want_bar_for_any_ccx` --> $DIR/hrtb-higher-ranker-supertraits.rs:39:15 diff --git a/src/test/ui/hrtb/hrtb-just-for-static.nll.stderr b/src/test/ui/hrtb/hrtb-just-for-static.nll.stderr index 17d59bb321..a5770431ea 100644 --- a/src/test/ui/hrtb/hrtb-just-for-static.nll.stderr +++ b/src/test/ui/hrtb/hrtb-just-for-static.nll.stderr @@ -14,8 +14,6 @@ LL | fn give_some<'a>() { | -- lifetime `'a` defined here LL | want_hrtb::<&'a u32>() | ^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` - | - = help: consider replacing `'a` with `'static` error: implementation of `Foo` is not general enough --> $DIR/hrtb-just-for-static.rs:30:5 diff --git a/src/test/ui/hrtb/hrtb-perfect-forwarding.nll.stderr b/src/test/ui/hrtb/hrtb-perfect-forwarding.nll.stderr index aefe3cdfd6..68da46d46b 100644 --- a/src/test/ui/hrtb/hrtb-perfect-forwarding.nll.stderr +++ b/src/test/ui/hrtb/hrtb-perfect-forwarding.nll.stderr @@ -54,8 +54,6 @@ LL | fn foo_hrtb_bar_not<'b, T>(mut t: T) ... LL | foo_hrtb_bar_not(&mut t); | ^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'b` must outlive `'static` - | - = help: consider replacing `'b` with `'static` error: implementation of `Bar` is not general enough --> $DIR/hrtb-perfect-forwarding.rs:43:5 diff --git a/src/test/ui/hrtb/issue-88446.rs b/src/test/ui/hrtb/issue-88446.rs new file mode 100644 index 0000000000..571b853175 --- /dev/null +++ b/src/test/ui/hrtb/issue-88446.rs @@ -0,0 +1,35 @@ +// check-pass + +trait Yokeable<'a> { + type Output: 'a; +} +impl<'a> Yokeable<'a> for () { + type Output = (); +} + +trait DataMarker<'data> { + type Yokeable: for<'a> Yokeable<'a>; +} +impl<'data> DataMarker<'data> for () { + type Yokeable = (); +} + +struct DataPayload<'data, M>(&'data M); + +impl DataPayload<'static, ()> { + pub fn map_project_with_capture( + _: for<'a> fn( + capture: T, + std::marker::PhantomData<&'a ()>, + ) -> >::Output, + ) -> DataPayload<'static, M2> + where + M2: DataMarker<'static>, + { + todo!() + } +} + +fn main() { + let _: DataPayload<()> = DataPayload::<()>::map_project_with_capture::<_, &()>(|_, _| todo!()); +} diff --git a/src/test/ui/hygiene/assoc_item_ctxt.stderr b/src/test/ui/hygiene/assoc_item_ctxt.stderr index 6e4fecf0ce..d65716ec2c 100644 --- a/src/test/ui/hygiene/assoc_item_ctxt.stderr +++ b/src/test/ui/hygiene/assoc_item_ctxt.stderr @@ -2,10 +2,13 @@ error[E0407]: method `method` is not a member of trait `Tr` --> $DIR/assoc_item_ctxt.rs:35:13 | LL | fn method() {} - | ^^^^^^^^^^^^^^ not a member of trait `Tr` + | ^^^------^^^^^ + | | | + | | help: there is an associated function with a similar name: `method` + | not a member of trait `Tr` ... LL | mac_trait_impl!(); - | ------------------ in this macro invocation + | ----------------- in this macro invocation | = note: this error originates in the macro `mac_trait_impl` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -19,7 +22,7 @@ LL | impl Tr for u8 { | ^^^^^^^^^^^^^^ missing `method` in implementation ... LL | mac_trait_impl!(); - | ------------------ in this macro invocation + | ----------------- in this macro invocation | = note: this error originates in the macro `mac_trait_impl` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/hygiene/duplicate_lifetimes.stderr b/src/test/ui/hygiene/duplicate_lifetimes.stderr index b699142c67..4d41ebaa43 100644 --- a/src/test/ui/hygiene/duplicate_lifetimes.stderr +++ b/src/test/ui/hygiene/duplicate_lifetimes.stderr @@ -5,7 +5,7 @@ LL | fn g<$a, 'a>() {} | ^^ declared twice ... LL | m!('a); - | ------- + | ------ | | | | | previous declaration here | in this macro invocation @@ -19,7 +19,7 @@ LL | fn h<$a, 'a>() {} | ^^ declared twice ... LL | n!('a); - | ------- + | ------ | | | | | previous declaration here | in this macro invocation diff --git a/src/test/ui/hygiene/extern-prelude-from-opaque-fail.stderr b/src/test/ui/hygiene/extern-prelude-from-opaque-fail.stderr index 98e15c9aad..e89c19b588 100644 --- a/src/test/ui/hygiene/extern-prelude-from-opaque-fail.stderr +++ b/src/test/ui/hygiene/extern-prelude-from-opaque-fail.stderr @@ -14,7 +14,7 @@ LL | use my_core; | ^^^^^^^ no `my_core` in the root ... LL | a!(); - | ----- in this macro invocation + | ---- in this macro invocation | = note: this error originates in the macro `a` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -25,7 +25,7 @@ LL | fn f() { my_core::mem::drop(0); } | ^^^^^^^ use of undeclared crate or module `my_core` ... LL | a!(); - | ----- in this macro invocation + | ---- in this macro invocation | = note: this error originates in the macro `a` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/hygiene/fields-definition.stderr b/src/test/ui/hygiene/fields-definition.stderr index 0c62c00aab..9d091cedd2 100644 --- a/src/test/ui/hygiene/fields-definition.stderr +++ b/src/test/ui/hygiene/fields-definition.stderr @@ -7,7 +7,7 @@ LL | $a: u8, | ^^^^^^ field already declared ... LL | legacy!(a); - | ----------- in this macro invocation + | ---------- in this macro invocation | = note: this error originates in the macro `legacy` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/hygiene/fields-numeric-borrowck.stderr b/src/test/ui/hygiene/fields-numeric-borrowck.stderr index fb90825c0d..bc13aa62f4 100644 --- a/src/test/ui/hygiene/fields-numeric-borrowck.stderr +++ b/src/test/ui/hygiene/fields-numeric-borrowck.stderr @@ -7,7 +7,7 @@ LL | let S { 0: ref mut borrow2 } = s; | ^^^^^^^^^^^^^^^ second mutable borrow occurs here ... LL | borrow1.use_mut(); - | ------- first borrow later used here + | ----------------- first borrow later used here error: aborting due to previous error diff --git a/src/test/ui/hygiene/generate-mod.stderr b/src/test/ui/hygiene/generate-mod.stderr index d96f8329fb..32a2e145ca 100644 --- a/src/test/ui/hygiene/generate-mod.stderr +++ b/src/test/ui/hygiene/generate-mod.stderr @@ -17,7 +17,7 @@ LL | type A = FromOutside; | ^^^^^^^^^^^ not found in this scope ... LL | genmod_transparent!(); - | ---------------------- in this macro invocation + | --------------------- in this macro invocation | = note: this error originates in the macro `genmod_transparent` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -28,7 +28,7 @@ LL | type Inner = Outer; | ^^^^^ not found in this scope ... LL | genmod_transparent!(); - | ---------------------- in this macro invocation + | --------------------- in this macro invocation | = note: this error originates in the macro `genmod_transparent` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -39,7 +39,7 @@ LL | type A = FromOutside; | ^^^^^^^^^^^ not found in this scope ... LL | genmod_legacy!(); - | ----------------- in this macro invocation + | ---------------- in this macro invocation | = note: this error originates in the macro `genmod_legacy` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -50,7 +50,7 @@ LL | type Inner = Outer; | ^^^^^ not found in this scope ... LL | genmod_legacy!(); - | ----------------- in this macro invocation + | ---------------- in this macro invocation | = note: this error originates in the macro `genmod_legacy` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/hygiene/globs.stderr b/src/test/ui/hygiene/globs.stderr index c2497f8ff7..bcfcc28adf 100644 --- a/src/test/ui/hygiene/globs.stderr +++ b/src/test/ui/hygiene/globs.stderr @@ -4,7 +4,7 @@ error[E0425]: cannot find function `f` in this scope LL | f(); | ^ not found in this scope | -help: consider importing one of these items +help: consider importing this function | LL | use foo::f; | @@ -32,12 +32,12 @@ error[E0425]: cannot find function `f` in this scope --> $DIR/globs.rs:61:12 | LL | n!(f); - | ------ in this macro invocation + | ----- in this macro invocation ... LL | n!(f); | ^ not found in this scope | - = note: consider importing one of these items: + = note: consider importing this function: foo::f = note: this error originates in the macro `n` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -45,12 +45,12 @@ error[E0425]: cannot find function `f` in this scope --> $DIR/globs.rs:65:17 | LL | n!(f); - | ------ in this macro invocation + | ----- in this macro invocation ... LL | f | ^ not found in this scope | - = note: consider importing one of these items: + = note: consider importing this function: foo::f = note: this error originates in the macro `n` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/hygiene/hygienic-label-1.stderr b/src/test/ui/hygiene/hygienic-label-1.stderr index c1ed861836..deb6a20599 100644 --- a/src/test/ui/hygiene/hygienic-label-1.stderr +++ b/src/test/ui/hygiene/hygienic-label-1.stderr @@ -5,7 +5,7 @@ LL | () => { break 'x; } | ^^ undeclared label `'x` ... LL | 'x: loop { foo!(); } - | ------- in this macro invocation + | ------ in this macro invocation | = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/hygiene/hygienic-label-3.stderr b/src/test/ui/hygiene/hygienic-label-3.stderr index 29d1b67e09..cf7f78a99e 100644 --- a/src/test/ui/hygiene/hygienic-label-3.stderr +++ b/src/test/ui/hygiene/hygienic-label-3.stderr @@ -5,7 +5,7 @@ LL | () => { break 'x; } | ^^ undeclared label `'x` ... LL | foo!(); - | ------- in this macro invocation + | ------ in this macro invocation | = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/hygiene/hygienic-labels-in-let.stderr b/src/test/ui/hygiene/hygienic-labels-in-let.stderr index afca48fe84..519e3c0880 100644 --- a/src/test/ui/hygiene/hygienic-labels-in-let.stderr +++ b/src/test/ui/hygiene/hygienic-labels-in-let.stderr @@ -8,7 +8,7 @@ LL | 'x: loop { | -- first declared here LL | // this 'x should refer to the outer loop, lexically LL | loop_x!(break 'x); - | ------------------ in this macro invocation + | ----------------- in this macro invocation | = note: this warning originates in the macro `loop_x` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -40,7 +40,7 @@ LL | 'x: loop { | -- first declared here ... LL | loop_x!(break 'x); - | ------------------ in this macro invocation + | ----------------- in this macro invocation | = note: this warning originates in the macro `loop_x` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -54,7 +54,7 @@ LL | 'x: loop { $e } | label `'x` already in scope ... LL | loop_x!(break 'x); - | ------------------ in this macro invocation + | ----------------- in this macro invocation | = note: this warning originates in the macro `loop_x` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -68,7 +68,7 @@ LL | 'x: for _ in 0..1 { | -- first declared here ... LL | loop_x!(break 'x); - | ------------------ in this macro invocation + | ----------------- in this macro invocation | = note: this warning originates in the macro `loop_x` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -118,7 +118,7 @@ LL | 'x: loop { | -- first declared here ... LL | while_true!(break 'x); - | ---------------------- in this macro invocation + | --------------------- in this macro invocation | = note: this warning originates in the macro `while_true` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -132,7 +132,7 @@ LL | 'x: while 1 + 1 == 2 { $e } | ^^ label `'x` already in scope ... LL | while_true!(break 'x); - | ---------------------- in this macro invocation + | --------------------- in this macro invocation | = note: this warning originates in the macro `while_true` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -146,7 +146,7 @@ LL | 'x: for _ in 0..1 { | -- first declared here ... LL | while_true!(break 'x); - | ---------------------- in this macro invocation + | --------------------- in this macro invocation | = note: this warning originates in the macro `while_true` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -160,7 +160,7 @@ LL | 'x: while 1 + 1 == 2 { $e } | ^^ label `'x` already in scope ... LL | while_true!(break 'x); - | ---------------------- in this macro invocation + | --------------------- in this macro invocation | = note: this warning originates in the macro `while_true` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -174,7 +174,7 @@ LL | 'x: for _ in 0..1 { | -- first declared here ... LL | while_true!(break 'x); - | ---------------------- in this macro invocation + | --------------------- in this macro invocation | = note: this warning originates in the macro `while_true` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -242,7 +242,7 @@ LL | 'x: loop { | -- first declared here ... LL | run_once!(continue 'x); - | ----------------------- in this macro invocation + | ---------------------- in this macro invocation | = note: this warning originates in the macro `run_once` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -256,7 +256,7 @@ LL | 'x: for _ in 0..1 { $e } | ^^ label `'x` already in scope ... LL | run_once!(continue 'x); - | ----------------------- in this macro invocation + | ---------------------- in this macro invocation | = note: this warning originates in the macro `run_once` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -270,7 +270,7 @@ LL | 'x: for _ in 0..1 { | -- first declared here ... LL | run_once!(continue 'x); - | ----------------------- in this macro invocation + | ---------------------- in this macro invocation | = note: this warning originates in the macro `run_once` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -284,7 +284,7 @@ LL | 'x: for _ in 0..1 { $e } | ^^ label `'x` already in scope ... LL | run_once!(continue 'x); - | ----------------------- in this macro invocation + | ---------------------- in this macro invocation | = note: this warning originates in the macro `run_once` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -298,7 +298,7 @@ LL | 'x: for _ in 0..1 { | -- first declared here ... LL | run_once!(continue 'x); - | ----------------------- in this macro invocation + | ---------------------- in this macro invocation | = note: this warning originates in the macro `run_once` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -312,7 +312,7 @@ LL | 'x: for _ in 0..1 { $e } | ^^ label `'x` already in scope ... LL | run_once!(continue 'x); - | ----------------------- in this macro invocation + | ---------------------- in this macro invocation | = note: this warning originates in the macro `run_once` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -326,7 +326,7 @@ LL | 'x: for _ in 0..1 { | -- first declared here ... LL | run_once!(continue 'x); - | ----------------------- in this macro invocation + | ---------------------- in this macro invocation | = note: this warning originates in the macro `run_once` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/hygiene/hygienic-labels.stderr b/src/test/ui/hygiene/hygienic-labels.stderr index 8c14e4f8a4..f0b891fe34 100644 --- a/src/test/ui/hygiene/hygienic-labels.stderr +++ b/src/test/ui/hygiene/hygienic-labels.stderr @@ -8,7 +8,7 @@ LL | 'x: for _ in 0..1 { | -- first declared here LL | // this 'x should refer to the outer loop, lexically LL | loop_x!(break 'x); - | ------------------ in this macro invocation + | ----------------- in this macro invocation | = note: this warning originates in the macro `loop_x` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -40,7 +40,7 @@ LL | 'x: for _ in 0..1 { | -- first declared here ... LL | loop_x!(break 'x); - | ------------------ in this macro invocation + | ----------------- in this macro invocation | = note: this warning originates in the macro `loop_x` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -54,7 +54,7 @@ LL | 'x: loop { $e } | label `'x` already in scope ... LL | loop_x!(break 'x); - | ------------------ in this macro invocation + | ----------------- in this macro invocation | = note: this warning originates in the macro `loop_x` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -68,7 +68,7 @@ LL | 'x: loop { | -- first declared here ... LL | loop_x!(break 'x); - | ------------------ in this macro invocation + | ----------------- in this macro invocation | = note: this warning originates in the macro `loop_x` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -118,7 +118,7 @@ LL | 'x: for _ in 0..1 { | -- first declared here ... LL | while_x!(break 'x); - | ------------------- in this macro invocation + | ------------------ in this macro invocation | = note: this warning originates in the macro `while_x` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -132,7 +132,7 @@ LL | 'x: while 1 + 1 == 2 { $e } | ^^ label `'x` already in scope ... LL | while_x!(break 'x); - | ------------------- in this macro invocation + | ------------------ in this macro invocation | = note: this warning originates in the macro `while_x` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -146,7 +146,7 @@ LL | 'x: loop { | -- first declared here ... LL | while_x!(break 'x); - | ------------------- in this macro invocation + | ------------------ in this macro invocation | = note: this warning originates in the macro `while_x` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -160,7 +160,7 @@ LL | 'x: while 1 + 1 == 2 { $e } | ^^ label `'x` already in scope ... LL | while_x!(break 'x); - | ------------------- in this macro invocation + | ------------------ in this macro invocation | = note: this warning originates in the macro `while_x` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -174,7 +174,7 @@ LL | 'x: while 1 + 1 == 2 { | -- first declared here ... LL | while_x!(break 'x); - | ------------------- in this macro invocation + | ------------------ in this macro invocation | = note: this warning originates in the macro `while_x` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -242,7 +242,7 @@ LL | 'x: for _ in 0..1 { | -- first declared here ... LL | run_once!(continue 'x); - | ----------------------- in this macro invocation + | ---------------------- in this macro invocation | = note: this warning originates in the macro `run_once` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -256,7 +256,7 @@ LL | 'x: for _ in 0..1 { $e } | ^^ label `'x` already in scope ... LL | run_once!(continue 'x); - | ----------------------- in this macro invocation + | ---------------------- in this macro invocation | = note: this warning originates in the macro `run_once` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -270,7 +270,7 @@ LL | 'x: loop { | -- first declared here ... LL | run_once!(continue 'x); - | ----------------------- in this macro invocation + | ---------------------- in this macro invocation | = note: this warning originates in the macro `run_once` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -284,7 +284,7 @@ LL | 'x: for _ in 0..1 { $e } | ^^ label `'x` already in scope ... LL | run_once!(continue 'x); - | ----------------------- in this macro invocation + | ---------------------- in this macro invocation | = note: this warning originates in the macro `run_once` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -298,7 +298,7 @@ LL | 'x: while 1 + 1 == 2 { | -- first declared here ... LL | run_once!(continue 'x); - | ----------------------- in this macro invocation + | ---------------------- in this macro invocation | = note: this warning originates in the macro `run_once` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -312,7 +312,7 @@ LL | 'x: while 1 + 1 == 2 { $e } | -- first declared here ... LL | run_once!(continue 'x); - | ----------------------- in this macro invocation + | ---------------------- in this macro invocation | = note: this warning originates in the macro `run_once` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -326,7 +326,7 @@ LL | 'x: for _ in 0..1 { | -- first declared here ... LL | run_once!(continue 'x); - | ----------------------- in this macro invocation + | ---------------------- in this macro invocation | = note: this warning originates in the macro `run_once` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/hygiene/impl_items.stderr b/src/test/ui/hygiene/impl_items.stderr index 9fefa29c4d..523309f432 100644 --- a/src/test/ui/hygiene/impl_items.stderr +++ b/src/test/ui/hygiene/impl_items.stderr @@ -5,7 +5,7 @@ LL | let _: () = S.f(); | ^ private type ... LL | foo::m!(); - | ---------- in this macro invocation + | --------- in this macro invocation | = note: this error originates in the macro `foo::m` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/hygiene/missing-self-diag.stderr b/src/test/ui/hygiene/missing-self-diag.stderr index b5370209f9..690bcd0322 100644 --- a/src/test/ui/hygiene/missing-self-diag.stderr +++ b/src/test/ui/hygiene/missing-self-diag.stderr @@ -6,7 +6,7 @@ LL | self.bar(); ... LL | / pub fn foo(&self) { LL | | call_bar!(); - | | ------------ in this macro invocation + | | ----------- in this macro invocation LL | | } | |_____- this function has a `self` parameter, but a macro invocation can only access identifiers it receives from parameters | diff --git a/src/test/ui/hygiene/no_implicit_prelude.stderr b/src/test/ui/hygiene/no_implicit_prelude.stderr index 4f49b3106e..0f2ff96b5e 100644 --- a/src/test/ui/hygiene/no_implicit_prelude.stderr +++ b/src/test/ui/hygiene/no_implicit_prelude.stderr @@ -2,7 +2,7 @@ error[E0433]: failed to resolve: use of undeclared type `Vec` --> $DIR/no_implicit_prelude.rs:11:9 | LL | fn f() { ::bar::m!(); } - | ------------ in this macro invocation + | ----------- in this macro invocation ... LL | Vec::new(); | ^^^ not found in this scope @@ -17,15 +17,17 @@ error[E0599]: no method named `clone` found for unit type `()` in the current sc --> $DIR/no_implicit_prelude.rs:12:12 | LL | fn f() { ::bar::m!(); } - | ------------ in this macro invocation + | ----------- in this macro invocation ... LL | ().clone() | ^^^^^ method not found in `()` | = help: items from traits can only be used if the trait is in scope - = note: the following trait is implemented but not in scope; perhaps add a `use` for it: - `use std::clone::Clone;` = note: this error originates in the macro `::bar::m` (in Nightly builds, run with -Z macro-backtrace for more info) +help: the following trait is implemented but not in scope; perhaps add a `use` for it: + | +LL | use std::clone::Clone; + | error: aborting due to 2 previous errors diff --git a/src/test/ui/hygiene/privacy-early.stderr b/src/test/ui/hygiene/privacy-early.stderr index 42aee62e09..0375ed56d9 100644 --- a/src/test/ui/hygiene/privacy-early.stderr +++ b/src/test/ui/hygiene/privacy-early.stderr @@ -5,7 +5,7 @@ LL | use f as g; | ^^^^^^ ... LL | foo::m!(); - | ---------- in this macro invocation + | --------- in this macro invocation | note: consider marking `f` as `pub` in the imported module --> $DIR/privacy-early.rs:10:13 @@ -14,7 +14,7 @@ LL | use f as g; | ^^^^^^ ... LL | foo::m!(); - | ---------- in this macro invocation + | --------- in this macro invocation = note: this error originates in the macro `foo::m` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to previous error diff --git a/src/test/ui/hygiene/trait_items.stderr b/src/test/ui/hygiene/trait_items.stderr index f16bb80dbb..80bdbe0e21 100644 --- a/src/test/ui/hygiene/trait_items.stderr +++ b/src/test/ui/hygiene/trait_items.stderr @@ -5,15 +5,17 @@ LL | fn f(&self) {} | - the method is available for `()` here ... LL | fn f() { ::baz::m!(); } - | ------------ in this macro invocation + | ----------- in this macro invocation ... LL | pub macro m() { ().f() } | ^ method not found in `()` | = help: items from traits can only be used if the trait is in scope - = note: the following trait is implemented but not in scope; perhaps add a `use` for it: - `use foo::T;` = note: this error originates in the macro `::baz::m` (in Nightly builds, run with -Z macro-backtrace for more info) +help: the following trait is implemented but not in scope; perhaps add a `use` for it: + | +LL | use foo::T; + | error: aborting due to previous error diff --git a/src/test/ui/impl-header-lifetime-elision/dyn-trait.nll.stderr b/src/test/ui/impl-header-lifetime-elision/dyn-trait.nll.stderr index d72435bc63..88c260b18c 100644 --- a/src/test/ui/impl-header-lifetime-elision/dyn-trait.nll.stderr +++ b/src/test/ui/impl-header-lifetime-elision/dyn-trait.nll.stderr @@ -2,11 +2,14 @@ error[E0521]: borrowed data escapes outside of function --> $DIR/dyn-trait.rs:20:5 | LL | fn with_dyn_debug_static<'a>(x: Box) { - | - `x` is a reference that is only valid in the function body + | -- - `x` is a reference that is only valid in the function body + | | + | lifetime `'a` defined here LL | static_val(x); - | ^^^^^^^^^^^^^ `x` escapes the function body here - | - = help: consider replacing `'a` with `'static` + | ^^^^^^^^^^^^^ + | | + | `x` escapes the function body here + | argument requires that `'a` must outlive `'static` error: aborting due to previous error diff --git a/src/test/ui/impl-trait/auto-trait-leak.stderr b/src/test/ui/impl-trait/auto-trait-leak.stderr index a31c104d8f..634ff14869 100644 --- a/src/test/ui/impl-trait/auto-trait-leak.stderr +++ b/src/test/ui/impl-trait/auto-trait-leak.stderr @@ -34,7 +34,7 @@ note: ...which requires type-checking `cycle1`... | LL | send(cycle2().clone()); | ^^^^ - = note: ...which requires evaluating trait selection obligation `impl std::clone::Clone: std::marker::Send`... + = note: ...which requires evaluating trait selection obligation `impl core::clone::Clone: core::marker::Send`... note: ...which requires computing type of `cycle2::{opaque#0}`... --> $DIR/auto-trait-leak.rs:19:16 | @@ -70,7 +70,7 @@ note: ...which requires type-checking `cycle2`... | LL | send(cycle1().clone()); | ^^^^ - = note: ...which requires evaluating trait selection obligation `impl std::clone::Clone: std::marker::Send`... + = note: ...which requires evaluating trait selection obligation `impl core::clone::Clone: core::marker::Send`... = note: ...which again requires computing type of `cycle1::{opaque#0}`, completing the cycle note: cycle used when checking item types in top-level module --> $DIR/auto-trait-leak.rs:1:1 diff --git a/src/test/ui/impl-trait/hidden-lifetimes.stderr b/src/test/ui/impl-trait/hidden-lifetimes.stderr index 7cea4fb93d..60d3409a8a 100644 --- a/src/test/ui/impl-trait/hidden-lifetimes.stderr +++ b/src/test/ui/impl-trait/hidden-lifetimes.stderr @@ -2,25 +2,27 @@ error[E0700]: hidden type for `impl Trait` captures lifetime that does not appea --> $DIR/hidden-lifetimes.rs:28:54 | LL | fn hide_ref<'a, 'b, T: 'static>(x: &'a mut &'b T) -> impl Swap + 'a { - | ^^^^^^^^^^^^^^ + | -- ^^^^^^^^^^^^^^ + | | + | hidden type `&'a mut &'b T` captures the lifetime `'b` as defined here | -note: hidden type `&'a mut &'b T` captures the lifetime `'b` as defined on the function body at 28:17 - --> $DIR/hidden-lifetimes.rs:28:17 +help: to declare that the `impl Trait` captures 'b, you can add an explicit `'b` lifetime bound | -LL | fn hide_ref<'a, 'b, T: 'static>(x: &'a mut &'b T) -> impl Swap + 'a { - | ^^ +LL | fn hide_ref<'a, 'b, T: 'static>(x: &'a mut &'b T) -> impl Swap + 'a + 'b { + | ++++ error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds --> $DIR/hidden-lifetimes.rs:45:70 | LL | fn hide_rc_refcell<'a, 'b: 'a, T: 'static>(x: Rc>) -> impl Swap + 'a { - | ^^^^^^^^^^^^^^ + | -- ^^^^^^^^^^^^^^ + | | + | hidden type `Rc>` captures the lifetime `'b` as defined here | -note: hidden type `Rc>` captures the lifetime `'b` as defined on the function body at 45:24 - --> $DIR/hidden-lifetimes.rs:45:24 +help: to declare that the `impl Trait` captures 'b, you can add an explicit `'b` lifetime bound | -LL | fn hide_rc_refcell<'a, 'b: 'a, T: 'static>(x: Rc>) -> impl Swap + 'a { - | ^^ +LL | fn hide_rc_refcell<'a, 'b: 'a, T: 'static>(x: Rc>) -> impl Swap + 'a + 'b { + | ++++ error: aborting due to 2 previous errors diff --git a/src/test/ui/impl-trait/multiple-lifetimes/error-handling-2.rs b/src/test/ui/impl-trait/multiple-lifetimes/error-handling-2.rs index 96d891b2cf..72e9d96da3 100644 --- a/src/test/ui/impl-trait/multiple-lifetimes/error-handling-2.rs +++ b/src/test/ui/impl-trait/multiple-lifetimes/error-handling-2.rs @@ -1,6 +1,3 @@ -// compile-flags:-Zborrowck=mir - -#![feature(member_constraints)] #![feature(type_alias_impl_trait)] #[derive(Clone)] diff --git a/src/test/ui/impl-trait/multiple-lifetimes/error-handling-2.stderr b/src/test/ui/impl-trait/multiple-lifetimes/error-handling-2.stderr index 59105f1180..40bec0da27 100644 --- a/src/test/ui/impl-trait/multiple-lifetimes/error-handling-2.stderr +++ b/src/test/ui/impl-trait/multiple-lifetimes/error-handling-2.stderr @@ -1,14 +1,10 @@ error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds - --> $DIR/error-handling-2.rs:13:60 + --> $DIR/error-handling-2.rs:10:60 | LL | fn foo<'a: 'b, 'b, 'c>(x: &'static i32, mut y: &'a i32) -> E<'b, 'c> { - | ^^^^^^^^^ - | -note: hidden type `*mut &'a i32` captures the lifetime `'a` as defined on the function body at 13:8 - --> $DIR/error-handling-2.rs:13:8 - | -LL | fn foo<'a: 'b, 'b, 'c>(x: &'static i32, mut y: &'a i32) -> E<'b, 'c> { - | ^^ + | -- ^^^^^^^^^ + | | + | hidden type `*mut &'a i32` captures the lifetime `'a` as defined here error: aborting due to previous error diff --git a/src/test/ui/impl-trait/multiple-lifetimes/error-handling.rs b/src/test/ui/impl-trait/multiple-lifetimes/error-handling.rs index 6d88f16ea8..367e7f4e6e 100644 --- a/src/test/ui/impl-trait/multiple-lifetimes/error-handling.rs +++ b/src/test/ui/impl-trait/multiple-lifetimes/error-handling.rs @@ -1,5 +1,3 @@ -// compile-flags:-Zborrowck=mir - #![feature(type_alias_impl_trait)] #[derive(Clone)] diff --git a/src/test/ui/impl-trait/multiple-lifetimes/error-handling.stderr b/src/test/ui/impl-trait/multiple-lifetimes/error-handling.stderr index ccd0040030..01d9f506a0 100644 --- a/src/test/ui/impl-trait/multiple-lifetimes/error-handling.stderr +++ b/src/test/ui/impl-trait/multiple-lifetimes/error-handling.stderr @@ -1,5 +1,5 @@ error: lifetime may not live long enough - --> $DIR/error-handling.rs:22:16 + --> $DIR/error-handling.rs:20:16 | LL | fn foo<'a, 'b, 'c>(x: &'static i32, mut y: &'a i32) -> E<'b, 'c> { | -- -- lifetime `'b` defined here 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 index 8cf89f164b..bfe656c7e2 100644 --- 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 @@ -2,9 +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 '_#9r +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 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 index 1bcb28120e..75c2dd8e9d 100644 --- 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 @@ -2,9 +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 '_#6r +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 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 3b75939ff0..812093e6e7 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 @@ -19,7 +19,6 @@ LL | fn explicit<'a>(x: &'a i32) -> impl Copy { x } | | | lifetime `'a` defined here | - = help: consider replacing `'a` with `'static` help: to allow this `impl Trait` to capture borrowed data with lifetime `'a`, add `'a` as a bound | LL | fn explicit<'a>(x: &'a i32) -> impl Copy + 'a { x } @@ -42,7 +41,6 @@ LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'static { x } | -- lifetime `'a` defined here ^ returning this value requires that `'a` must outlive `'static` | = help: consider replacing `'a` with `'static` - = 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 @@ -67,7 +65,6 @@ 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` - = help: consider replacing `'a` with `'static` error: lifetime may not live long enough --> $DIR/must_outlive_least_region_or_bound.rs:32:61 diff --git a/src/test/ui/impl-trait/region-escape-via-bound.stderr b/src/test/ui/impl-trait/region-escape-via-bound.stderr index 969ddc57af..9dc2ea5bc8 100644 --- a/src/test/ui/impl-trait/region-escape-via-bound.stderr +++ b/src/test/ui/impl-trait/region-escape-via-bound.stderr @@ -3,12 +3,14 @@ error[E0700]: hidden type for `impl Trait` captures lifetime that does not appea | LL | fn foo(x: Cell<&'x u32>) -> impl Trait<'y> | ^^^^^^^^^^^^^^ - | -note: hidden type `Cell<&'x u32>` captures the lifetime `'x` as defined on the function body at 17:7 - --> $DIR/region-escape-via-bound.rs:17:7 - | +LL | LL | where 'x: 'y - | ^^ + | -- hidden type `Cell<&'x u32>` captures the lifetime `'x` as defined here + | +help: to declare that the `impl Trait` captures 'x, you can add an explicit `'x` lifetime bound + | +LL | fn foo(x: Cell<&'x u32>) -> impl Trait<'y> + 'x + | ++++ error: aborting due to previous error 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 index 05a9ed1d4e..a3aeff50ee 100644 --- a/src/test/ui/impl-trait/static-return-lifetime-infered.nll.stderr +++ b/src/test/ui/impl-trait/static-return-lifetime-infered.nll.stderr @@ -19,7 +19,6 @@ LL | fn iter_values<'a>(&'a self) -> impl Iterator { | | | lifetime `'a` defined here | - = help: consider replacing `'a` with `'static` 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 + 'a { diff --git a/src/test/ui/issues/type-arg-mismatch-due-to-impl-trait.rs b/src/test/ui/impl-trait/type-arg-mismatch-due-to-impl-trait.rs similarity index 100% rename from src/test/ui/issues/type-arg-mismatch-due-to-impl-trait.rs rename to src/test/ui/impl-trait/type-arg-mismatch-due-to-impl-trait.rs diff --git a/src/test/ui/issues/type-arg-mismatch-due-to-impl-trait.stderr b/src/test/ui/impl-trait/type-arg-mismatch-due-to-impl-trait.stderr similarity index 100% rename from src/test/ui/issues/type-arg-mismatch-due-to-impl-trait.stderr rename to src/test/ui/impl-trait/type-arg-mismatch-due-to-impl-trait.stderr diff --git a/src/test/ui/imports/extern-prelude-extern-crate-fail.stderr b/src/test/ui/imports/extern-prelude-extern-crate-fail.stderr index ade7571277..f7e37449ee 100644 --- a/src/test/ui/imports/extern-prelude-extern-crate-fail.stderr +++ b/src/test/ui/imports/extern-prelude-extern-crate-fail.stderr @@ -5,7 +5,7 @@ LL | extern crate std as non_existent; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ... LL | define_std_as_non_existent!(); - | ------------------------------ in this macro invocation + | ----------------------------- in this macro invocation | = note: this error originates in the macro `define_std_as_non_existent` (in Nightly builds, run with -Z macro-backtrace for more info) 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 089a897f1c..472824b84f 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 @@ -5,7 +5,7 @@ LL | extern crate std as core; | ^^^^^^^^^^^^^^^^^^^^^^^^^ ... LL | define_other_core!(); - | --------------------- in this macro invocation + | -------------------- in this macro invocation | = note: this error originates in the macro `define_other_core` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -22,7 +22,7 @@ LL | extern crate std as Vec; | ^^^^^^^^^^^^^^^^^^^^^^^^ ... LL | define_vec!(); - | -------------- in this macro invocation + | ------------- in this macro invocation note: `Vec` could also refer to the struct defined here --> $SRC_DIR/std/src/prelude/mod.rs:LL:COL | diff --git a/src/test/ui/imports/glob-resolve1.stderr b/src/test/ui/imports/glob-resolve1.stderr index 2c7a8ad5c1..3b66a5e315 100644 --- a/src/test/ui/imports/glob-resolve1.stderr +++ b/src/test/ui/imports/glob-resolve1.stderr @@ -4,10 +4,11 @@ error[E0425]: cannot find function `fpriv` in this scope LL | fpriv(); | ^^^^^ not found in this scope | -help: consider importing this function - | -LL | use bar::fpriv; +note: function `bar::fpriv` exists but is inaccessible + --> $DIR/glob-resolve1.rs:7:5 | +LL | fn fpriv() {} + | ^^^^^^^^^^ not accessible error[E0425]: cannot find function `epriv` in this scope --> $DIR/glob-resolve1.rs:27:5 @@ -15,10 +16,11 @@ error[E0425]: cannot find function `epriv` in this scope LL | epriv(); | ^^^^^ not found in this scope | -help: consider importing this function - | -LL | use bar::epriv; +note: function `bar::epriv` exists but is inaccessible + --> $DIR/glob-resolve1.rs:9:9 | +LL | fn epriv(); + | ^^^^^^^^^^^ not accessible error[E0423]: expected value, found enum `B` --> $DIR/glob-resolve1.rs:28:5 @@ -44,10 +46,11 @@ error[E0425]: cannot find value `C` in this scope LL | C; | ^ not found in this scope | -help: consider importing this unit struct - | -LL | use bar::C; +note: unit struct `bar::C` exists but is inaccessible + --> $DIR/glob-resolve1.rs:18:5 | +LL | struct C; + | ^^^^^^^^^ not accessible error[E0425]: cannot find function `import` in this scope --> $DIR/glob-resolve1.rs:30:5 @@ -67,16 +70,13 @@ LL | pub enum B { | ---------- similarly named enum `B` defined here ... LL | foo::(); - | ^ + | ^ help: an enum with a similar name exists: `B` | -help: an enum with a similar name exists - | -LL | foo::(); - | ~ -help: consider importing this enum - | -LL | use bar::A; +note: enum `bar::A` exists but is inaccessible + --> $DIR/glob-resolve1.rs:11:5 | +LL | enum A { + | ^^^^^^ not accessible error[E0412]: cannot find type `C` in this scope --> $DIR/glob-resolve1.rs:33:11 @@ -85,16 +85,13 @@ LL | pub enum B { | ---------- similarly named enum `B` defined here ... LL | foo::(); - | ^ + | ^ help: an enum with a similar name exists: `B` | -help: an enum with a similar name exists - | -LL | foo::(); - | ~ -help: consider importing this struct - | -LL | use bar::C; +note: struct `bar::C` exists but is inaccessible + --> $DIR/glob-resolve1.rs:18:5 | +LL | struct C; + | ^^^^^^^^^ not accessible error[E0412]: cannot find type `D` in this scope --> $DIR/glob-resolve1.rs:34:11 @@ -103,16 +100,13 @@ LL | pub enum B { | ---------- similarly named enum `B` defined here ... LL | foo::(); - | ^ + | ^ help: an enum with a similar name exists: `B` | -help: an enum with a similar name exists - | -LL | foo::(); - | ~ -help: consider importing this type alias - | -LL | use bar::D; +note: type alias `bar::D` exists but is inaccessible + --> $DIR/glob-resolve1.rs:20:5 | +LL | type D = isize; + | ^^^^^^^^^^^^^^^ not accessible error: aborting due to 8 previous errors diff --git a/src/test/ui/imports/import-crate-var.stderr b/src/test/ui/imports/import-crate-var.stderr index fd4c76c1fa..f1f1dfbdbd 100644 --- a/src/test/ui/imports/import-crate-var.stderr +++ b/src/test/ui/imports/import-crate-var.stderr @@ -2,7 +2,7 @@ error: `$crate` may not be imported --> $DIR/import-crate-var.rs:6:5 | LL | m!(); - | ^^^^^ + | ^^^^ | = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/imports/issue-30560.stderr b/src/test/ui/imports/issue-30560.stderr index b74134aacc..69cfd4c06a 100644 --- a/src/test/ui/imports/issue-30560.stderr +++ b/src/test/ui/imports/issue-30560.stderr @@ -1,4 +1,4 @@ -error: items in traits are not importable. +error: items in traits are not importable --> $DIR/issue-30560.rs:7:5 | LL | use T::*; diff --git a/src/test/ui/imports/issue-4366-2.stderr b/src/test/ui/imports/issue-4366-2.stderr index a86ec7fabe..4c94634ee6 100644 --- a/src/test/ui/imports/issue-4366-2.stderr +++ b/src/test/ui/imports/issue-4366-2.stderr @@ -4,10 +4,11 @@ error[E0412]: cannot find type `Bar` in this scope LL | fn sub() -> Bar { 1 } | ^^^ not found in this scope | -help: consider importing this type alias - | -LL | use a::b::Bar; +note: type alias `a::b::Bar` exists but is inaccessible + --> $DIR/issue-4366-2.rs:11:9 | +LL | type Bar = isize; + | ^^^^^^^^^^^^^^^^^ not accessible error[E0423]: expected function, found module `foo` --> $DIR/issue-4366-2.rs:25:5 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 9983073ece..f809698fe1 100644 --- a/src/test/ui/imports/local-modularized-tricky-fail-1.stderr +++ b/src/test/ui/imports/local-modularized-tricky-fail-1.stderr @@ -13,7 +13,7 @@ LL | | } | |_____^ ... LL | define_exported!(); - | ------------------- in this macro invocation + | ------------------ in this macro invocation note: `exported` could also refer to the macro imported here --> $DIR/local-modularized-tricky-fail-1.rs:22:5 | @@ -37,7 +37,7 @@ LL | | } | |_____^ ... LL | define_exported!(); - | ------------------- in this macro invocation + | ------------------ in this macro invocation note: `exported` could also refer to the macro imported here --> $DIR/local-modularized-tricky-fail-1.rs:22:5 | @@ -62,7 +62,7 @@ LL | | } | |_____^ ... LL | define_panic!(); - | ---------------- in this macro invocation + | --------------- in this macro invocation = 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) @@ -82,7 +82,7 @@ LL | | } | |_____^ ... LL | define_include!(); - | ------------------ in this macro invocation + | ----------------- in this macro invocation = help: use `crate::include` to refer to this macro unambiguously = note: this error originates in the macro `define_include` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/imports/local-modularized-tricky-fail-2.stderr b/src/test/ui/imports/local-modularized-tricky-fail-2.stderr index ab9f1eca23..3c20f552fd 100644 --- a/src/test/ui/imports/local-modularized-tricky-fail-2.stderr +++ b/src/test/ui/imports/local-modularized-tricky-fail-2.stderr @@ -16,7 +16,7 @@ LL | | } | |_____^ ... LL | define_exported!(); - | ------------------- in this macro invocation + | ------------------ in this macro invocation = note: this error originates in the macro `define_exported` (in Nightly builds, run with -Z macro-backtrace for more info) error: macro-expanded `macro_export` macros from the current crate cannot be referred to by absolute paths @@ -36,7 +36,7 @@ LL | | } | |_____^ ... LL | define_exported!(); - | ------------------- in this macro invocation + | ------------------ in this macro invocation = note: this error originates in the macro `define_exported` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 2 previous errors diff --git a/src/test/ui/imports/shadow_builtin_macros.stderr b/src/test/ui/imports/shadow_builtin_macros.stderr index 82d8078856..2fcbb2a045 100644 --- a/src/test/ui/imports/shadow_builtin_macros.stderr +++ b/src/test/ui/imports/shadow_builtin_macros.stderr @@ -27,7 +27,7 @@ LL | macro_rules! panic { () => {} } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ LL | } } LL | m!(); - | ----- in this macro invocation + | ---- 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) diff --git a/src/test/ui/in-band-lifetimes/elided-lifetimes.stderr b/src/test/ui/in-band-lifetimes/elided-lifetimes.stderr index 7094f427aa..037ce401b3 100644 --- a/src/test/ui/in-band-lifetimes/elided-lifetimes.stderr +++ b/src/test/ui/in-band-lifetimes/elided-lifetimes.stderr @@ -35,7 +35,7 @@ LL | fn $fn_name(gift: &str) -> $type_name { | ^^^^^^^^^^- help: indicate the anonymous lifetime: `<'_>` ... LL | autowrapper!(Autowrapped, autowrap_gift, 'a); - | --------------------------------------------- in this macro invocation + | -------------------------------------------- in this macro invocation | = note: this error originates in the macro `autowrapper` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/indexing-requires-a-uint.stderr b/src/test/ui/indexing-requires-a-uint.stderr index 1bcb89de2b..24f42f22f3 100644 --- a/src/test/ui/indexing-requires-a-uint.stderr +++ b/src/test/ui/indexing-requires-a-uint.stderr @@ -16,7 +16,7 @@ LL | bar::(i); // i should not be re-coerced back to an isize help: you can convert a `usize` to an `isize` and panic if the converted value doesn't fit | LL | bar::(i.try_into().unwrap()); // i should not be re-coerced back to an isize - | ~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error: aborting due to 2 previous errors diff --git a/src/test/ui/inference/deref-suggestion.stderr b/src/test/ui/inference/deref-suggestion.stderr index c5c8b88429..da11ba204c 100644 --- a/src/test/ui/inference/deref-suggestion.stderr +++ b/src/test/ui/inference/deref-suggestion.stderr @@ -56,7 +56,7 @@ error[E0308]: mismatched types --> $DIR/deref-suggestion.rs:36:5 | LL | assert_eq!(3i32, &3i32); - | ^^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found `&i32` + | ^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found `&i32` | = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/inference/issue-71309.rs b/src/test/ui/inference/issue-71309.rs new file mode 100644 index 0000000000..c31107d8fe --- /dev/null +++ b/src/test/ui/inference/issue-71309.rs @@ -0,0 +1,7 @@ +fn foo(x: Result) -> Result<(), ()> { + let y: u32 = x?; + //~^ ERROR: `?` operator has incompatible types + Ok(()) +} + +fn main() {} diff --git a/src/test/ui/inference/issue-71309.stderr b/src/test/ui/inference/issue-71309.stderr new file mode 100644 index 0000000000..af8714f1c8 --- /dev/null +++ b/src/test/ui/inference/issue-71309.stderr @@ -0,0 +1,15 @@ +error[E0308]: `?` operator has incompatible types + --> $DIR/issue-71309.rs:2:18 + | +LL | let y: u32 = x?; + | ^^ expected `u32`, found `i32` + | + = note: `?` operator cannot convert from `i32` to `u32` +help: you can convert an `i32` to a `u32` and panic if the converted value doesn't fit + | +LL | let y: u32 = x?.try_into().unwrap(); + | ++++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/infinite/infinite-autoderef.rs b/src/test/ui/infinite/infinite-autoderef.rs index 6d6908ef7f..ca26252832 100644 --- a/src/test/ui/infinite/infinite-autoderef.rs +++ b/src/test/ui/infinite/infinite-autoderef.rs @@ -1,6 +1,6 @@ // error-pattern: reached the recursion limit while auto-dereferencing -#![feature(box_syntax)] + use std::ops::Deref; @@ -17,7 +17,7 @@ impl Deref for Foo { pub fn main() { let mut x; loop { - x = box x; + x = Box::new(x); x.foo; x.bar(); } diff --git a/src/test/ui/infinite/infinite-autoderef.stderr b/src/test/ui/infinite/infinite-autoderef.stderr index cbefbf83be..03e4718f5d 100644 --- a/src/test/ui/infinite/infinite-autoderef.stderr +++ b/src/test/ui/infinite/infinite-autoderef.stderr @@ -1,13 +1,10 @@ error[E0308]: mismatched types --> $DIR/infinite-autoderef.rs:20:13 | -LL | x = box x; - | ^^^^^ cyclic type of infinite size - | -help: try using a conversion method - | -LL | x = (box x).to_string(); - | + +++++++++++++ +LL | x = Box::new(x); + | ^^^^^^^^^^^- help: try using a conversion method: `.to_string()` + | | + | cyclic type of infinite size error[E0055]: reached the recursion limit while auto-dereferencing `Foo` --> $DIR/infinite-autoderef.rs:25:5 @@ -15,7 +12,7 @@ error[E0055]: reached the recursion limit while auto-dereferencing `Foo` LL | Foo.foo; | ^^^^^^^ deref recursion limit reached | - = help: consider adding a `#![recursion_limit="256"]` attribute to your crate (`infinite_autoderef`) + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`infinite_autoderef`) error[E0055]: reached the recursion limit while auto-dereferencing `Foo` --> $DIR/infinite-autoderef.rs:25:9 @@ -23,7 +20,7 @@ error[E0055]: reached the recursion limit while auto-dereferencing `Foo` LL | Foo.foo; | ^^^ deref recursion limit reached | - = help: consider adding a `#![recursion_limit="256"]` attribute to your crate (`infinite_autoderef`) + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`infinite_autoderef`) error[E0609]: no field `foo` on type `Foo` --> $DIR/infinite-autoderef.rs:25:9 @@ -37,7 +34,7 @@ error[E0055]: reached the recursion limit while auto-dereferencing `Foo` LL | Foo.bar(); | ^^^ deref recursion limit reached | - = help: consider adding a `#![recursion_limit="256"]` attribute to your crate (`infinite_autoderef`) + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`infinite_autoderef`) error[E0599]: no method named `bar` found for struct `Foo` in the current scope --> $DIR/infinite-autoderef.rs:26:9 diff --git a/src/test/ui/infinite/infinite-macro-expansion.stderr b/src/test/ui/infinite/infinite-macro-expansion.stderr index c7d9118d3f..15654dfaf8 100644 --- a/src/test/ui/infinite/infinite-macro-expansion.stderr +++ b/src/test/ui/infinite/infinite-macro-expansion.stderr @@ -7,7 +7,7 @@ LL | () => (recursive!()) LL | recursive!() | ------------ in this macro invocation | - = help: consider adding a `#![recursion_limit="256"]` attribute to your crate (`infinite_macro_expansion`) + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`infinite_macro_expansion`) = note: this error originates in the macro `recursive` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to previous error diff --git a/src/test/ui/inherent-impls-overlap-check/no-overlap.rs b/src/test/ui/inherent-impls-overlap-check/no-overlap.rs index 341bfc7b60..450e6d4202 100644 --- a/src/test/ui/inherent-impls-overlap-check/no-overlap.rs +++ b/src/test/ui/inherent-impls-overlap-check/no-overlap.rs @@ -31,4 +31,23 @@ repeat::repeat_with_idents!(impl Bar { fn IDENT() {} }); impl Bar { fn foo() {} } impl Bar { fn foo() {} } +// Regression test for issue #89820: + +impl Bar { + pub fn a() {} + pub fn aa() {} +} + +impl Bar { + pub fn b() {} + pub fn bb() {} +} + +impl Bar { + pub fn a() {} + pub fn aa() {} + pub fn bb() {} + pub fn b() {} +} + fn main() {} diff --git a/src/test/ui/init-res-into-things.rs b/src/test/ui/init-res-into-things.rs index ed0c600c1d..7f416262dc 100644 --- a/src/test/ui/init-res-into-things.rs +++ b/src/test/ui/init-res-into-things.rs @@ -2,7 +2,6 @@ #![allow(non_camel_case_types)] #![allow(dead_code)] -#![feature(box_syntax)] use std::cell::Cell; @@ -58,7 +57,7 @@ fn test_tup() { fn test_unique() { let i = &Cell::new(0); { - let _a: Box<_> = box r(i); + let _a: Box<_> = Box::new(r(i)); } assert_eq!(i.get(), 1); } @@ -66,9 +65,9 @@ fn test_unique() { fn test_unique_rec() { let i = &Cell::new(0); { - let _a: Box<_> = box BoxR { + let _a: Box<_> = Box::new(BoxR { x: r(i) - }; + }); } assert_eq!(i.get(), 1); } diff --git a/src/test/ui/integer-literal-suffix-inference.stderr b/src/test/ui/integer-literal-suffix-inference.stderr index c9cfbc506b..4c29c4a1cb 100644 --- a/src/test/ui/integer-literal-suffix-inference.stderr +++ b/src/test/ui/integer-literal-suffix-inference.stderr @@ -7,7 +7,7 @@ LL | id_i8(a16); help: you can convert an `i16` to an `i8` and panic if the converted value doesn't fit | LL | id_i8(a16.try_into().unwrap()); - | ~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/integer-literal-suffix-inference.rs:41:11 @@ -18,7 +18,7 @@ LL | id_i8(a32); help: you can convert an `i32` to an `i8` and panic if the converted value doesn't fit | LL | id_i8(a32.try_into().unwrap()); - | ~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/integer-literal-suffix-inference.rs:44:11 @@ -29,7 +29,7 @@ LL | id_i8(a64); help: you can convert an `i64` to an `i8` and panic if the converted value doesn't fit | LL | id_i8(a64.try_into().unwrap()); - | ~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/integer-literal-suffix-inference.rs:47:11 @@ -40,16 +40,18 @@ LL | id_i8(asize); help: you can convert an `isize` to an `i8` and panic if the converted value doesn't fit | LL | id_i8(asize.try_into().unwrap()); - | ~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/integer-literal-suffix-inference.rs:51:12 | LL | id_i16(a8); - | ^^ - | | - | expected `i16`, found `i8` - | help: you can convert an `i8` to an `i16`: `a8.into()` + | ^^ expected `i16`, found `i8` + | +help: you can convert an `i8` to an `i16` + | +LL | id_i16(a8.into()); + | +++++++ error[E0308]: mismatched types --> $DIR/integer-literal-suffix-inference.rs:55:12 @@ -60,7 +62,7 @@ LL | id_i16(a32); help: you can convert an `i32` to an `i16` and panic if the converted value doesn't fit | LL | id_i16(a32.try_into().unwrap()); - | ~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/integer-literal-suffix-inference.rs:58:12 @@ -71,7 +73,7 @@ LL | id_i16(a64); help: you can convert an `i64` to an `i16` and panic if the converted value doesn't fit | LL | id_i16(a64.try_into().unwrap()); - | ~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/integer-literal-suffix-inference.rs:61:12 @@ -82,25 +84,29 @@ LL | id_i16(asize); help: you can convert an `isize` to an `i16` and panic if the converted value doesn't fit | LL | id_i16(asize.try_into().unwrap()); - | ~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/integer-literal-suffix-inference.rs:65:12 | LL | id_i32(a8); - | ^^ - | | - | expected `i32`, found `i8` - | help: you can convert an `i8` to an `i32`: `a8.into()` + | ^^ expected `i32`, found `i8` + | +help: you can convert an `i8` to an `i32` + | +LL | id_i32(a8.into()); + | +++++++ error[E0308]: mismatched types --> $DIR/integer-literal-suffix-inference.rs:68:12 | LL | id_i32(a16); - | ^^^ - | | - | expected `i32`, found `i16` - | help: you can convert an `i16` to an `i32`: `a16.into()` + | ^^^ expected `i32`, found `i16` + | +help: you can convert an `i16` to an `i32` + | +LL | id_i32(a16.into()); + | +++++++ error[E0308]: mismatched types --> $DIR/integer-literal-suffix-inference.rs:72:12 @@ -111,7 +117,7 @@ LL | id_i32(a64); help: you can convert an `i64` to an `i32` and panic if the converted value doesn't fit | LL | id_i32(a64.try_into().unwrap()); - | ~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/integer-literal-suffix-inference.rs:75:12 @@ -122,34 +128,40 @@ LL | id_i32(asize); help: you can convert an `isize` to an `i32` and panic if the converted value doesn't fit | LL | id_i32(asize.try_into().unwrap()); - | ~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/integer-literal-suffix-inference.rs:79:12 | LL | id_i64(a8); - | ^^ - | | - | expected `i64`, found `i8` - | help: you can convert an `i8` to an `i64`: `a8.into()` + | ^^ expected `i64`, found `i8` + | +help: you can convert an `i8` to an `i64` + | +LL | id_i64(a8.into()); + | +++++++ error[E0308]: mismatched types --> $DIR/integer-literal-suffix-inference.rs:82:12 | LL | id_i64(a16); - | ^^^ - | | - | expected `i64`, found `i16` - | help: you can convert an `i16` to an `i64`: `a16.into()` + | ^^^ expected `i64`, found `i16` + | +help: you can convert an `i16` to an `i64` + | +LL | id_i64(a16.into()); + | +++++++ error[E0308]: mismatched types --> $DIR/integer-literal-suffix-inference.rs:85:12 | LL | id_i64(a32); - | ^^^ - | | - | expected `i64`, found `i32` - | help: you can convert an `i32` to an `i64`: `a32.into()` + | ^^^ expected `i64`, found `i32` + | +help: you can convert an `i32` to an `i64` + | +LL | id_i64(a32.into()); + | +++++++ error[E0308]: mismatched types --> $DIR/integer-literal-suffix-inference.rs:89:12 @@ -160,25 +172,29 @@ LL | id_i64(asize); help: you can convert an `isize` to an `i64` and panic if the converted value doesn't fit | LL | id_i64(asize.try_into().unwrap()); - | ~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/integer-literal-suffix-inference.rs:93:14 | LL | id_isize(a8); - | ^^ - | | - | expected `isize`, found `i8` - | help: you can convert an `i8` to an `isize`: `a8.into()` + | ^^ expected `isize`, found `i8` + | +help: you can convert an `i8` to an `isize` + | +LL | id_isize(a8.into()); + | +++++++ error[E0308]: mismatched types --> $DIR/integer-literal-suffix-inference.rs:96:14 | LL | id_isize(a16); - | ^^^ - | | - | expected `isize`, found `i16` - | help: you can convert an `i16` to an `isize`: `a16.into()` + | ^^^ expected `isize`, found `i16` + | +help: you can convert an `i16` to an `isize` + | +LL | id_isize(a16.into()); + | +++++++ error[E0308]: mismatched types --> $DIR/integer-literal-suffix-inference.rs:99:14 @@ -189,7 +205,7 @@ LL | id_isize(a32); help: you can convert an `i32` to an `isize` and panic if the converted value doesn't fit | LL | id_isize(a32.try_into().unwrap()); - | ~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/integer-literal-suffix-inference.rs:102:14 @@ -200,7 +216,7 @@ LL | id_isize(a64); help: you can convert an `i64` to an `isize` and panic if the converted value doesn't fit | LL | id_isize(a64.try_into().unwrap()); - | ~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/integer-literal-suffix-inference.rs:108:11 @@ -211,7 +227,7 @@ LL | id_i8(c16); help: you can convert an `i16` to an `i8` and panic if the converted value doesn't fit | LL | id_i8(c16.try_into().unwrap()); - | ~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/integer-literal-suffix-inference.rs:111:11 @@ -222,7 +238,7 @@ LL | id_i8(c32); help: you can convert an `i32` to an `i8` and panic if the converted value doesn't fit | LL | id_i8(c32.try_into().unwrap()); - | ~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/integer-literal-suffix-inference.rs:114:11 @@ -233,16 +249,18 @@ LL | id_i8(c64); help: you can convert an `i64` to an `i8` and panic if the converted value doesn't fit | LL | id_i8(c64.try_into().unwrap()); - | ~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/integer-literal-suffix-inference.rs:118:12 | LL | id_i16(c8); - | ^^ - | | - | expected `i16`, found `i8` - | help: you can convert an `i8` to an `i16`: `c8.into()` + | ^^ expected `i16`, found `i8` + | +help: you can convert an `i8` to an `i16` + | +LL | id_i16(c8.into()); + | +++++++ error[E0308]: mismatched types --> $DIR/integer-literal-suffix-inference.rs:122:12 @@ -253,7 +271,7 @@ LL | id_i16(c32); help: you can convert an `i32` to an `i16` and panic if the converted value doesn't fit | LL | id_i16(c32.try_into().unwrap()); - | ~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/integer-literal-suffix-inference.rs:125:12 @@ -264,25 +282,29 @@ LL | id_i16(c64); help: you can convert an `i64` to an `i16` and panic if the converted value doesn't fit | LL | id_i16(c64.try_into().unwrap()); - | ~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/integer-literal-suffix-inference.rs:129:12 | LL | id_i32(c8); - | ^^ - | | - | expected `i32`, found `i8` - | help: you can convert an `i8` to an `i32`: `c8.into()` + | ^^ expected `i32`, found `i8` + | +help: you can convert an `i8` to an `i32` + | +LL | id_i32(c8.into()); + | +++++++ error[E0308]: mismatched types --> $DIR/integer-literal-suffix-inference.rs:132:12 | LL | id_i32(c16); - | ^^^ - | | - | expected `i32`, found `i16` - | help: you can convert an `i16` to an `i32`: `c16.into()` + | ^^^ expected `i32`, found `i16` + | +help: you can convert an `i16` to an `i32` + | +LL | id_i32(c16.into()); + | +++++++ error[E0308]: mismatched types --> $DIR/integer-literal-suffix-inference.rs:136:12 @@ -293,34 +315,40 @@ LL | id_i32(c64); help: you can convert an `i64` to an `i32` and panic if the converted value doesn't fit | LL | id_i32(c64.try_into().unwrap()); - | ~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/integer-literal-suffix-inference.rs:140:12 | LL | id_i64(a8); - | ^^ - | | - | expected `i64`, found `i8` - | help: you can convert an `i8` to an `i64`: `a8.into()` + | ^^ expected `i64`, found `i8` + | +help: you can convert an `i8` to an `i64` + | +LL | id_i64(a8.into()); + | +++++++ error[E0308]: mismatched types --> $DIR/integer-literal-suffix-inference.rs:143:12 | LL | id_i64(a16); - | ^^^ - | | - | expected `i64`, found `i16` - | help: you can convert an `i16` to an `i64`: `a16.into()` + | ^^^ expected `i64`, found `i16` + | +help: you can convert an `i16` to an `i64` + | +LL | id_i64(a16.into()); + | +++++++ error[E0308]: mismatched types --> $DIR/integer-literal-suffix-inference.rs:146:12 | LL | id_i64(a32); - | ^^^ - | | - | expected `i64`, found `i32` - | help: you can convert an `i32` to an `i64`: `a32.into()` + | ^^^ expected `i64`, found `i32` + | +help: you can convert an `i32` to an `i64` + | +LL | id_i64(a32.into()); + | +++++++ error[E0308]: mismatched types --> $DIR/integer-literal-suffix-inference.rs:152:11 @@ -331,7 +359,7 @@ LL | id_u8(b16); help: you can convert a `u16` to a `u8` and panic if the converted value doesn't fit | LL | id_u8(b16.try_into().unwrap()); - | ~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/integer-literal-suffix-inference.rs:155:11 @@ -342,7 +370,7 @@ LL | id_u8(b32); help: you can convert a `u32` to a `u8` and panic if the converted value doesn't fit | LL | id_u8(b32.try_into().unwrap()); - | ~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/integer-literal-suffix-inference.rs:158:11 @@ -353,7 +381,7 @@ LL | id_u8(b64); help: you can convert a `u64` to a `u8` and panic if the converted value doesn't fit | LL | id_u8(b64.try_into().unwrap()); - | ~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/integer-literal-suffix-inference.rs:161:11 @@ -364,16 +392,18 @@ LL | id_u8(bsize); help: you can convert a `usize` to a `u8` and panic if the converted value doesn't fit | LL | id_u8(bsize.try_into().unwrap()); - | ~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/integer-literal-suffix-inference.rs:165:12 | LL | id_u16(b8); - | ^^ - | | - | expected `u16`, found `u8` - | help: you can convert a `u8` to a `u16`: `b8.into()` + | ^^ expected `u16`, found `u8` + | +help: you can convert a `u8` to a `u16` + | +LL | id_u16(b8.into()); + | +++++++ error[E0308]: mismatched types --> $DIR/integer-literal-suffix-inference.rs:169:12 @@ -384,7 +414,7 @@ LL | id_u16(b32); help: you can convert a `u32` to a `u16` and panic if the converted value doesn't fit | LL | id_u16(b32.try_into().unwrap()); - | ~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/integer-literal-suffix-inference.rs:172:12 @@ -395,7 +425,7 @@ LL | id_u16(b64); help: you can convert a `u64` to a `u16` and panic if the converted value doesn't fit | LL | id_u16(b64.try_into().unwrap()); - | ~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/integer-literal-suffix-inference.rs:175:12 @@ -406,25 +436,29 @@ LL | id_u16(bsize); help: you can convert a `usize` to a `u16` and panic if the converted value doesn't fit | LL | id_u16(bsize.try_into().unwrap()); - | ~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/integer-literal-suffix-inference.rs:179:12 | LL | id_u32(b8); - | ^^ - | | - | expected `u32`, found `u8` - | help: you can convert a `u8` to a `u32`: `b8.into()` + | ^^ expected `u32`, found `u8` + | +help: you can convert a `u8` to a `u32` + | +LL | id_u32(b8.into()); + | +++++++ error[E0308]: mismatched types --> $DIR/integer-literal-suffix-inference.rs:182:12 | LL | id_u32(b16); - | ^^^ - | | - | expected `u32`, found `u16` - | help: you can convert a `u16` to a `u32`: `b16.into()` + | ^^^ expected `u32`, found `u16` + | +help: you can convert a `u16` to a `u32` + | +LL | id_u32(b16.into()); + | +++++++ error[E0308]: mismatched types --> $DIR/integer-literal-suffix-inference.rs:186:12 @@ -435,7 +469,7 @@ LL | id_u32(b64); help: you can convert a `u64` to a `u32` and panic if the converted value doesn't fit | LL | id_u32(b64.try_into().unwrap()); - | ~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/integer-literal-suffix-inference.rs:189:12 @@ -446,34 +480,40 @@ LL | id_u32(bsize); help: you can convert a `usize` to a `u32` and panic if the converted value doesn't fit | LL | id_u32(bsize.try_into().unwrap()); - | ~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/integer-literal-suffix-inference.rs:193:12 | LL | id_u64(b8); - | ^^ - | | - | expected `u64`, found `u8` - | help: you can convert a `u8` to a `u64`: `b8.into()` + | ^^ expected `u64`, found `u8` + | +help: you can convert a `u8` to a `u64` + | +LL | id_u64(b8.into()); + | +++++++ error[E0308]: mismatched types --> $DIR/integer-literal-suffix-inference.rs:196:12 | LL | id_u64(b16); - | ^^^ - | | - | expected `u64`, found `u16` - | help: you can convert a `u16` to a `u64`: `b16.into()` + | ^^^ expected `u64`, found `u16` + | +help: you can convert a `u16` to a `u64` + | +LL | id_u64(b16.into()); + | +++++++ error[E0308]: mismatched types --> $DIR/integer-literal-suffix-inference.rs:199:12 | LL | id_u64(b32); - | ^^^ - | | - | expected `u64`, found `u32` - | help: you can convert a `u32` to a `u64`: `b32.into()` + | ^^^ expected `u64`, found `u32` + | +help: you can convert a `u32` to a `u64` + | +LL | id_u64(b32.into()); + | +++++++ error[E0308]: mismatched types --> $DIR/integer-literal-suffix-inference.rs:203:12 @@ -484,25 +524,29 @@ LL | id_u64(bsize); help: you can convert a `usize` to a `u64` and panic if the converted value doesn't fit | LL | id_u64(bsize.try_into().unwrap()); - | ~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/integer-literal-suffix-inference.rs:207:14 | LL | id_usize(b8); - | ^^ - | | - | expected `usize`, found `u8` - | help: you can convert a `u8` to a `usize`: `b8.into()` + | ^^ expected `usize`, found `u8` + | +help: you can convert a `u8` to a `usize` + | +LL | id_usize(b8.into()); + | +++++++ error[E0308]: mismatched types --> $DIR/integer-literal-suffix-inference.rs:210:14 | LL | id_usize(b16); - | ^^^ - | | - | expected `usize`, found `u16` - | help: you can convert a `u16` to a `usize`: `b16.into()` + | ^^^ expected `usize`, found `u16` + | +help: you can convert a `u16` to a `usize` + | +LL | id_usize(b16.into()); + | +++++++ error[E0308]: mismatched types --> $DIR/integer-literal-suffix-inference.rs:213:14 @@ -513,7 +557,7 @@ LL | id_usize(b32); help: you can convert a `u32` to a `usize` and panic if the converted value doesn't fit | LL | id_usize(b32.try_into().unwrap()); - | ~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/integer-literal-suffix-inference.rs:216:14 @@ -524,7 +568,7 @@ LL | id_usize(b64); help: you can convert a `u64` to a `usize` and panic if the converted value doesn't fit | LL | id_usize(b64.try_into().unwrap()); - | ~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error: aborting due to 52 previous errors diff --git a/src/test/ui/internal/internal-unstable-noallow.stderr b/src/test/ui/internal/internal-unstable-noallow.stderr index 29680c0a63..b0ceae62ab 100644 --- a/src/test/ui/internal/internal-unstable-noallow.stderr +++ b/src/test/ui/internal/internal-unstable-noallow.stderr @@ -2,7 +2,7 @@ error[E0658]: use of unstable library feature 'function' --> $DIR/internal-unstable-noallow.rs:16:5 | LL | call_unstable_noallow!(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^ | = help: add `#![feature(function)]` to the crate attributes to enable = note: this error originates in the macro `call_unstable_noallow` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -11,7 +11,7 @@ error[E0658]: use of unstable library feature 'struct_field' --> $DIR/internal-unstable-noallow.rs:18:5 | LL | construct_unstable_noallow!(0); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: add `#![feature(struct_field)]` to the crate attributes to enable = note: this error originates in the macro `construct_unstable_noallow` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/internal/internal-unstable.stderr b/src/test/ui/internal/internal-unstable.stderr index 5261a79dfa..b973ea67bf 100644 --- a/src/test/ui/internal/internal-unstable.stderr +++ b/src/test/ui/internal/internal-unstable.stderr @@ -37,7 +37,7 @@ LL | internal_unstable::unstable(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ ... LL | bar!(internal_unstable::unstable()); - | ------------------------------------ in this macro invocation + | ----------------------------------- in this macro invocation | = help: add `#![feature(function)]` to the crate attributes to enable = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/intrinsics/const-eval-select-bad.rs b/src/test/ui/intrinsics/const-eval-select-bad.rs new file mode 100644 index 0000000000..8fbdc0c39c --- /dev/null +++ b/src/test/ui/intrinsics/const-eval-select-bad.rs @@ -0,0 +1,36 @@ +#![feature(const_eval_select)] + +use std::intrinsics::const_eval_select; + +const fn not_fn_items() { + const_eval_select((), || {}, || {}); + //~^ ERROR expected a `FnOnce<()>` closure + const_eval_select((), 42, 0xDEADBEEF); + //~^ ERROR expected a `FnOnce<()>` closure +} + +const fn foo(n: i32) -> i32 { + n +} + +fn bar(n: i32) -> bool { + assert_eq!(n, 0, "{} must be equal to {}", n, 0); + n == 0 +} + +fn baz(n: bool) -> i32 { + assert!(n, "{} must be true", n); + n as i32 +} + +const fn return_ty_mismatch() { + const_eval_select((1,), foo, bar); + //~^ ERROR type mismatch +} + +const fn args_ty_mismatch() { + const_eval_select((true,), foo, baz); + //~^ ERROR type mismatch +} + +fn main() {} diff --git a/src/test/ui/intrinsics/const-eval-select-bad.stderr b/src/test/ui/intrinsics/const-eval-select-bad.stderr new file mode 100644 index 0000000000..78647e9213 --- /dev/null +++ b/src/test/ui/intrinsics/const-eval-select-bad.stderr @@ -0,0 +1,65 @@ +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 + | +LL | const_eval_select((), || {}, || {}); + | ----------------- ^^^^^ expected an `FnOnce<()>` closure, found `[closure@$DIR/const-eval-select-bad.rs:6:27: 6:32]` + | | + | required by a bound introduced by this call + | + = help: the trait `FnOnce<()>` is not implemented for `[closure@$DIR/const-eval-select-bad.rs:6:27: 6:32]` + = note: wrap the `[closure@$DIR/const-eval-select-bad.rs:6:27: 6:32]` 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 | F: ~const FnOnce, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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 | F: ~const FnOnce, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `const_eval_select` + +error[E0271]: type mismatch resolving ` bool {bar} as FnOnce<(i32,)>>::Output == i32` + --> $DIR/const-eval-select-bad.rs:27:5 + | +LL | const_eval_select((1,), foo, bar); + | ^^^^^^^^^^^^^^^^^ expected `i32`, found `bool` + | +note: required by a bound in `const_eval_select` + --> $SRC_DIR/core/src/intrinsics.rs:LL:COL + | +LL | G: FnOnce + ~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 + | +LL | const fn foo(n: i32) -> i32 { + | --------------------------- found signature of `fn(i32) -> _` +... +LL | const_eval_select((true,), foo, baz); + | ----------------- ^^^ expected signature of `fn(bool) -> _` + | | + | required by a bound introduced by this call + | +note: required by a bound in `const_eval_select` + --> $SRC_DIR/core/src/intrinsics.rs:LL:COL + | +LL | F: ~const FnOnce, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `const_eval_select` + +error: aborting due to 4 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/const-eval-select-stability.rs b/src/test/ui/intrinsics/const-eval-select-stability.rs new file mode 100644 index 0000000000..db2462aee5 --- /dev/null +++ b/src/test/ui/intrinsics/const-eval-select-stability.rs @@ -0,0 +1,20 @@ +#![feature(staged_api)] +#![feature(const_eval_select)] +#![stable(since = "1.0", feature = "ui_test")] + +use std::intrinsics::const_eval_select; + +fn log() { + println!("HEY HEY HEY") +} + +const fn nothing(){} + +#[stable(since = "1.0", feature = "hey")] +#[rustc_const_stable(since = "1.0", feature = "const_hey")] +pub const unsafe fn hey() { + const_eval_select((), nothing, log); + //~^ ERROR `const_eval_select` is not yet stable as a const fn +} + +fn main() {} diff --git a/src/test/ui/intrinsics/const-eval-select-stability.stderr b/src/test/ui/intrinsics/const-eval-select-stability.stderr new file mode 100644 index 0000000000..79641bbb46 --- /dev/null +++ b/src/test/ui/intrinsics/const-eval-select-stability.stderr @@ -0,0 +1,10 @@ +error: `const_eval_select` is not yet stable as a const fn + --> $DIR/const-eval-select-stability.rs:16:5 + | +LL | const_eval_select((), nothing, log); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: const-stable functions can only call other const-stable functions + +error: aborting due to previous error + diff --git a/src/test/ui/intrinsics/const-eval-select-x86_64.rs b/src/test/ui/intrinsics/const-eval-select-x86_64.rs new file mode 100644 index 0000000000..afec8e054b --- /dev/null +++ b/src/test/ui/intrinsics/const-eval-select-x86_64.rs @@ -0,0 +1,39 @@ +// run-pass +// only-x86_64 + +#![feature(const_eval_select)] +use std::intrinsics::const_eval_select; +use std::arch::x86_64::*; +use std::mem::transmute; + +const fn eq_ct(x: [i32; 4], y: [i32; 4]) -> bool { + x[0] == y[0] && x[1] == y[1] && x[2] == y[2] && x[3] == y[3] +} + +fn eq_rt(x: [i32; 4], y: [i32; 4]) -> bool { + unsafe { + let x = _mm_loadu_si128(&x as *const _ as *const _); + let y = _mm_loadu_si128(&y as *const _ as *const _); + let r = _mm_cmpeq_epi32(x, y); + let r = _mm_movemask_ps(transmute(r) ); + r == 0b1111 + } +} + +const fn eq(x: [i32; 4], y: [i32; 4]) -> bool { + unsafe { + const_eval_select((x, y), eq_ct, eq_rt) + } +} + +fn main() { + const X: bool = eq([0, 1, 2, 3], [0, 1, 2, 3]); + assert_eq!(X, true); + let x = eq([0, 1, 2, 3], [0, 1, 2, 3]); + assert_eq!(x, true); + + const Y: bool = eq([0, 1, 2, 3], [0, 1, 3, 2]); + assert_eq!(Y, false); + let y = eq([0, 1, 2, 3], [0, 1, 3, 2]); + assert_eq!(y, false); +} diff --git a/src/test/ui/intrinsics/const-eval-select.rs b/src/test/ui/intrinsics/const-eval-select.rs new file mode 100644 index 0000000000..744db2f15b --- /dev/null +++ b/src/test/ui/intrinsics/const-eval-select.rs @@ -0,0 +1,26 @@ +// run-pass + +#![feature(const_eval_select)] + +use std::intrinsics::const_eval_select; + +const fn yes() -> bool { + true +} + +fn no() -> bool { + false +} + +// not a sound use case; testing only +const fn is_const_eval() -> bool { + unsafe { const_eval_select((), yes, no) } +} + +fn main() { + const YES: bool = is_const_eval(); + let no = is_const_eval(); + + assert_eq!(true, YES); + assert_eq!(false, no); +} diff --git a/src/test/ui/intrinsics/intrinsic-atomics.rs b/src/test/ui/intrinsics/intrinsic-atomics.rs index 608cf3dee5..c6e48e8b5a 100644 --- a/src/test/ui/intrinsics/intrinsic-atomics.rs +++ b/src/test/ui/intrinsics/intrinsic-atomics.rs @@ -1,5 +1,4 @@ // run-pass -#![feature(box_syntax)] #![feature(intrinsics)] mod rusti { @@ -34,7 +33,7 @@ mod rusti { pub fn main() { unsafe { - let mut x: Box<_> = box 1; + let mut x: Box<_> = Box::new(1); assert_eq!(rusti::atomic_load(&*x), 1); *x = 5; diff --git a/src/test/ui/intrinsics/panic-uninitialized-zeroed.rs b/src/test/ui/intrinsics/panic-uninitialized-zeroed.rs index 72c0d7913e..324bba15e4 100644 --- a/src/test/ui/intrinsics/panic-uninitialized-zeroed.rs +++ b/src/test/ui/intrinsics/panic-uninitialized-zeroed.rs @@ -2,6 +2,7 @@ // ignore-wasm32-bare compiled with panic=abort by default // revisions: mir thir // [thir]compile-flags: -Zthir-unsafeck +// ignore-tidy-linelength // This test checks panic emitted from `mem::{uninitialized,zeroed}`. @@ -114,11 +115,11 @@ fn main() { test_panic_msg( || mem::uninitialized::<*const dyn Send>(), - "attempted to leave type `*const dyn std::marker::Send` uninitialized, which is invalid" + "attempted to leave type `*const dyn core::marker::Send` uninitialized, which is invalid" ); test_panic_msg( || mem::zeroed::<*const dyn Send>(), - "attempted to zero-initialize type `*const dyn std::marker::Send`, which is invalid" + "attempted to zero-initialize type `*const dyn core::marker::Send`, which is invalid" ); /* FIXME(#66151) we conservatively do not error here yet. @@ -145,12 +146,12 @@ fn main() { test_panic_msg( || mem::uninitialized::<(NonNull, u32, u32)>(), - "attempted to leave type `(std::ptr::NonNull, u32, u32)` uninitialized, \ + "attempted to leave type `(core::ptr::non_null::NonNull, u32, u32)` uninitialized, \ which is invalid" ); test_panic_msg( || mem::zeroed::<(NonNull, u32, u32)>(), - "attempted to zero-initialize type `(std::ptr::NonNull, u32, u32)`, \ + "attempted to zero-initialize type `(core::ptr::non_null::NonNull, u32, u32)`, \ which is invalid" ); @@ -187,7 +188,7 @@ fn main() { ); test_panic_msg( || mem::uninitialized::>(), - "attempted to leave type `std::mem::ManuallyDrop` uninitialized, which is invalid" + "attempted to leave type `core::mem::manually_drop::ManuallyDrop` uninitialized, which is invalid" ); // Some things that should work. diff --git a/src/test/ui/invalid/invalid-crate-type-macro.rs b/src/test/ui/invalid/invalid-crate-type-macro.rs new file mode 100644 index 0000000000..9ba5e79ba9 --- /dev/null +++ b/src/test/ui/invalid/invalid-crate-type-macro.rs @@ -0,0 +1,7 @@ +#![crate_type = foo!()] //~ ERROR malformed `crate_type` attribute + +macro_rules! foo { + () => {"rlib"}; +} + +fn main() {} diff --git a/src/test/ui/invalid/invalid-crate-type-macro.stderr b/src/test/ui/invalid/invalid-crate-type-macro.stderr new file mode 100644 index 0000000000..c196d4278a --- /dev/null +++ b/src/test/ui/invalid/invalid-crate-type-macro.stderr @@ -0,0 +1,8 @@ +error: malformed `crate_type` attribute input + --> $DIR/invalid-crate-type-macro.rs:1:1 + | +LL | #![crate_type = foo!()] + | ^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#![crate_type = "bin|lib|..."]` + +error: aborting due to previous error + diff --git a/src/test/ui/invalid_crate_type_syntax.stderr b/src/test/ui/invalid_crate_type_syntax.stderr index 92bed23158..4072a2fa16 100644 --- a/src/test/ui/invalid_crate_type_syntax.stderr +++ b/src/test/ui/invalid_crate_type_syntax.stderr @@ -2,7 +2,7 @@ error: malformed `crate_type` attribute input --> $DIR/invalid_crate_type_syntax.rs:2:1 | LL | #![crate_type(lib)] - | ^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[crate_type = "bin|lib|..."]` + | ^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#![crate_type = "bin|lib|..."]` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-10291.nll.stderr b/src/test/ui/issues/issue-10291.nll.stderr index 1ebb0c6cf1..a7b827d27a 100644 --- a/src/test/ui/issues/issue-10291.nll.stderr +++ b/src/test/ui/issues/issue-10291.nll.stderr @@ -6,8 +6,6 @@ LL | fn test<'x>(x: &'x isize) { LL | drop:: FnMut(&'z isize) -> &'z isize>>(Box::new(|z| { LL | x | ^ returning this value requires that `'x` must outlive `'static` - | - = help: consider replacing `'x` with `'static` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-10291.stderr b/src/test/ui/issues/issue-10291.stderr index ff51aa3acf..a80b0ba5e9 100644 --- a/src/test/ui/issues/issue-10291.stderr +++ b/src/test/ui/issues/issue-10291.stderr @@ -4,7 +4,7 @@ error[E0312]: lifetime of reference outlives lifetime of borrowed content... LL | x | ^ | -note: ...the reference is valid for the anonymous lifetime #1 defined on the body at 2:69... +note: ...the reference is valid for the anonymous lifetime #1 defined here... --> $DIR/issue-10291.rs:2:69 | LL | drop:: FnMut(&'z isize) -> &'z isize>>(Box::new(|z| { @@ -12,7 +12,7 @@ LL | drop:: FnMut(&'z isize) -> &'z isize>>(Box::new(|z| { LL | | x LL | | })); | |_____^ -note: ...but the borrowed content is only valid for the lifetime `'x` as defined on the function body at 1:9 +note: ...but the borrowed content is only valid for the lifetime `'x` as defined here --> $DIR/issue-10291.rs:1:9 | LL | fn test<'x>(x: &'x isize) { diff --git a/src/test/ui/issues/issue-10465.stderr b/src/test/ui/issues/issue-10465.stderr index eb32c8db3f..0ccf69dc06 100644 --- a/src/test/ui/issues/issue-10465.stderr +++ b/src/test/ui/issues/issue-10465.stderr @@ -5,8 +5,10 @@ LL | b.foo(); | ^^^ method not found in `&B` | = help: items from traits can only be used if the trait is in scope - = note: the following trait is implemented but not in scope; perhaps add a `use` for it: - `use a::A;` +help: the following trait is implemented but not in scope; perhaps add a `use` for it: + | +LL | use a::A; + | error: aborting due to previous error diff --git a/src/test/ui/issues/issue-13359.stderr b/src/test/ui/issues/issue-13359.stderr index 0796ede52a..075c92e65d 100644 --- a/src/test/ui/issues/issue-13359.stderr +++ b/src/test/ui/issues/issue-13359.stderr @@ -7,7 +7,7 @@ LL | foo(1*(1 as isize)); help: you can convert an `isize` to an `i16` and panic if the converted value doesn't fit | LL | foo((1*(1 as isize)).try_into().unwrap()); - | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + | + +++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/issue-13359.rs:10:9 @@ -18,7 +18,7 @@ LL | bar(1*(1 as usize)); help: you can convert a `usize` to a `u32` and panic if the converted value doesn't fit | LL | bar((1*(1 as usize)).try_into().unwrap()); - | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + | + +++++++++++++++++++++ error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-13497-2.stderr b/src/test/ui/issues/issue-13497-2.stderr index 8ad921027e..6f72b79f2a 100644 --- a/src/test/ui/issues/issue-13497-2.stderr +++ b/src/test/ui/issues/issue-13497-2.stderr @@ -1,13 +1,14 @@ error[E0515]: cannot return value referencing local variable `rawLines` --> $DIR/issue-13497-2.rs:3:5 | -LL | rawLines - | ^------- - | | - | _____`rawLines` is borrowed here - | | -LL | | .iter().map(|l| l.trim()).collect() - | |___________________________________________^ returns a value referencing data owned by the current function +LL | rawLines + | _____^ + | |_____| + | || +LL | || .iter().map(|l| l.trim()).collect() + | ||_______________-___________________________^ returns a value referencing data owned by the current function + | |________________| + | `rawLines` is borrowed here error: aborting due to previous error diff --git a/src/test/ui/issues/issue-1362.stderr b/src/test/ui/issues/issue-1362.stderr index a925fc29c8..babbb6e519 100644 --- a/src/test/ui/issues/issue-1362.stderr +++ b/src/test/ui/issues/issue-1362.stderr @@ -9,7 +9,7 @@ LL | let x: u32 = 20i32; help: change the type of the numeric literal from `i32` to `u32` | LL | let x: u32 = 20u32; - | ~~~~~ + | ~~~ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-14091-2.stderr b/src/test/ui/issues/issue-14091-2.stderr index acf837d0f7..fbfa6e1abb 100644 --- a/src/test/ui/issues/issue-14091-2.stderr +++ b/src/test/ui/issues/issue-14091-2.stderr @@ -2,9 +2,24 @@ error[E0600]: cannot apply unary operator `!` to type `BytePos` --> $DIR/issue-14091-2.rs:15:5 | LL | assert!(x, x); - | ^^^^^^^^^^^^^^ cannot apply unary operator `!` + | ^^^^^^^^^^^^^ cannot apply unary operator `!` | - = note: an implementation of `std::ops::Not` might be missing for `BytePos` +note: an implementation of `Not` might be missing for `BytePos` + --> $DIR/issue-14091-2.rs:6:1 + | +LL | pub struct BytePos(pub u32); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ must implement `Not` +note: the following trait must be implemented + --> $SRC_DIR/core/src/ops/bit.rs:LL:COL + | +LL | / pub trait Not { +LL | | /// The resulting type after applying the `!` operator. +LL | | #[stable(feature = "rust1", since = "1.0.0")] +LL | | type Output; +... | +LL | | fn not(self) -> Self::Output; +LL | | } + | |_^ = note: this error originates in the macro `assert` (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-14091.stderr b/src/test/ui/issues/issue-14091.stderr index 7db4734780..0a9640a9e3 100644 --- a/src/test/ui/issues/issue-14091.stderr +++ b/src/test/ui/issues/issue-14091.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/issue-14091.rs:2:5 | LL | assert!(1,1); - | ^^^^^^^^^^^^^ expected `bool`, found integer + | ^^^^^^^^^^^^ expected `bool`, found integer error: aborting due to previous error diff --git a/src/test/ui/issues/issue-1448-2.stderr b/src/test/ui/issues/issue-1448-2.stderr index 6bf76c4904..da44566d07 100644 --- a/src/test/ui/issues/issue-1448-2.stderr +++ b/src/test/ui/issues/issue-1448-2.stderr @@ -7,7 +7,7 @@ LL | println!("{}", foo(10i32)); help: change the type of the numeric literal from `i32` to `u32` | LL | println!("{}", foo(10u32)); - | ~~~~~ + | ~~~ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-16098.stderr b/src/test/ui/issues/issue-16098.stderr index a63bcd9ba5..64280219d7 100644 --- a/src/test/ui/issues/issue-16098.stderr +++ b/src/test/ui/issues/issue-16098.stderr @@ -7,7 +7,7 @@ LL | $n + prob1!($n - 1); LL | println!("Problem 1: {}", prob1!(1000)); | ------------ in this macro invocation | - = help: consider adding a `#![recursion_limit="256"]` attribute to your crate (`issue_16098`) + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_16098`) = note: this error originates in the macro `prob1` (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-16683.nll.stderr b/src/test/ui/issues/issue-16683.nll.stderr index 51d86eaf9e..0e8f520353 100644 --- a/src/test/ui/issues/issue-16683.nll.stderr +++ b/src/test/ui/issues/issue-16683.nll.stderr @@ -1,10 +1,19 @@ error[E0521]: borrowed data escapes outside of associated function --> $DIR/issue-16683.rs:4:9 | +LL | trait T<'a> { + | -- lifetime `'a` defined here +LL | fn a(&'a self) -> &'a bool; LL | fn b(&self) { - | ----- `self` is a reference that is only valid in the associated function body + | ----- + | | + | `self` is a reference that is only valid in the associated function body + | let's call the lifetime of this reference `'1` LL | self.a(); - | ^^^^^^^^ `self` escapes the associated function body here + | ^^^^^^^^ + | | + | `self` escapes the associated function body here + | argument requires that `'1` must outlive `'a` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-16683.stderr b/src/test/ui/issues/issue-16683.stderr index 35bcf286c4..d4e18df8de 100644 --- a/src/test/ui/issues/issue-16683.stderr +++ b/src/test/ui/issues/issue-16683.stderr @@ -4,7 +4,7 @@ error[E0495]: cannot infer an appropriate lifetime for autoref due to conflictin LL | self.a(); | ^ | -note: first, the lifetime cannot outlive the anonymous lifetime defined on the method body at 3:10... +note: first, the lifetime cannot outlive the anonymous lifetime defined here... --> $DIR/issue-16683.rs:3:10 | LL | fn b(&self) { @@ -14,7 +14,7 @@ note: ...so that reference does not outlive borrowed content | LL | self.a(); | ^^^^ -note: but, the lifetime must be valid for the lifetime `'a` as defined on the trait at 1:9... +note: but, the lifetime must be valid for the lifetime `'a` as defined here... --> $DIR/issue-16683.rs:1:9 | LL | trait T<'a> { diff --git a/src/test/ui/issues/issue-16966.stderr b/src/test/ui/issues/issue-16966.stderr index f9467af9e3..09e20c0c77 100644 --- a/src/test/ui/issues/issue-16966.stderr +++ b/src/test/ui/issues/issue-16966.stderr @@ -2,7 +2,7 @@ error[E0282]: type annotations needed --> $DIR/issue-16966.rs:2:5 | LL | panic!(std::default::Default::default()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type for type parameter `M` declared on the function `begin_panic` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type for type parameter `M` declared on the function `begin_panic` | = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/issues/issue-17651.rs b/src/test/ui/issues/issue-17651.rs index 08f352c11f..7629a5a3be 100644 --- a/src/test/ui/issues/issue-17651.rs +++ b/src/test/ui/issues/issue-17651.rs @@ -4,5 +4,4 @@ fn main() { (|| Box::new(*(&[0][..])))(); //~^ ERROR the size for values of type - //~| ERROR the size for values of type } diff --git a/src/test/ui/issues/issue-17651.stderr b/src/test/ui/issues/issue-17651.stderr index ee1464fd84..214477f6c6 100644 --- a/src/test/ui/issues/issue-17651.stderr +++ b/src/test/ui/issues/issue-17651.stderr @@ -2,7 +2,9 @@ error[E0277]: the size for values of type `[{integer}]` cannot be known at compi --> $DIR/issue-17651.rs:5:18 | LL | (|| Box::new(*(&[0][..])))(); - | ^^^^^^^^^^^ doesn't have a size known at compile-time + | -------- ^^^^^^^^^^^ 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 `[{integer}]` note: required by `Box::::new` @@ -11,16 +13,6 @@ note: required by `Box::::new` LL | pub fn new(x: T) -> Self { | ^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0277]: the size for values of type `[{integer}]` cannot be known at compilation time - --> $DIR/issue-17651.rs:5:9 - | -LL | (|| Box::new(*(&[0][..])))(); - | ^^^^^^^^ doesn't have a size known at compile-time - | - = help: the trait `Sized` is not implemented for `[{integer}]` - = note: all function arguments must have a statically known size - = help: unsized fn params are gated as an unstable feature - -error: aborting due to 2 previous errors +error: aborting due to previous error For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/issues/issue-17740.stderr b/src/test/ui/issues/issue-17740.stderr index 995f5f1fc3..d177380415 100644 --- a/src/test/ui/issues/issue-17740.stderr +++ b/src/test/ui/issues/issue-17740.stderr @@ -6,12 +6,12 @@ LL | fn bar(self: &mut Foo) { | = note: expected struct `Foo<'a>` found struct `Foo<'_>` -note: the anonymous lifetime defined on the method body at 6:23... +note: the anonymous lifetime defined here... --> $DIR/issue-17740.rs:6:23 | LL | fn bar(self: &mut Foo) { | ^^^ -note: ...does not necessarily outlive the lifetime `'a` as defined on the impl at 5:7 +note: ...does not necessarily outlive the lifetime `'a` as defined here --> $DIR/issue-17740.rs:5:7 | LL | impl <'a> Foo<'a>{ @@ -25,12 +25,12 @@ LL | fn bar(self: &mut Foo) { | = note: expected struct `Foo<'a>` found struct `Foo<'_>` -note: the lifetime `'a` as defined on the impl at 5:7... +note: the lifetime `'a` as defined here... --> $DIR/issue-17740.rs:5:7 | LL | impl <'a> Foo<'a>{ | ^^ -note: ...does not necessarily outlive the anonymous lifetime defined on the method body at 6:23 +note: ...does not necessarily outlive the anonymous lifetime defined here --> $DIR/issue-17740.rs:6:23 | LL | fn bar(self: &mut Foo) { diff --git a/src/test/ui/issues/issue-17758.nll.stderr b/src/test/ui/issues/issue-17758.nll.stderr index 075c141ed7..b929fdbf36 100644 --- a/src/test/ui/issues/issue-17758.nll.stderr +++ b/src/test/ui/issues/issue-17758.nll.stderr @@ -1,10 +1,19 @@ error[E0521]: borrowed data escapes outside of associated function --> $DIR/issue-17758.rs:7:9 | +LL | trait Foo<'a> { + | -- lifetime `'a` defined here +LL | fn foo(&'a self); LL | fn bar(&self) { - | ----- `self` is a reference that is only valid in the associated function body + | ----- + | | + | `self` is a reference that is only valid in the associated function body + | let's call the lifetime of this reference `'1` LL | self.foo(); - | ^^^^^^^^^^ `self` escapes the associated function body here + | ^^^^^^^^^^ + | | + | `self` escapes the associated function body here + | argument requires that `'1` must outlive `'a` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-17758.stderr b/src/test/ui/issues/issue-17758.stderr index 846e8939b5..711217033a 100644 --- a/src/test/ui/issues/issue-17758.stderr +++ b/src/test/ui/issues/issue-17758.stderr @@ -4,7 +4,7 @@ error[E0495]: cannot infer an appropriate lifetime for autoref due to conflictin LL | self.foo(); | ^^^ | -note: first, the lifetime cannot outlive the anonymous lifetime defined on the method body at 6:12... +note: first, the lifetime cannot outlive the anonymous lifetime defined here... --> $DIR/issue-17758.rs:6:12 | LL | fn bar(&self) { @@ -14,7 +14,7 @@ note: ...so that reference does not outlive borrowed content | LL | self.foo(); | ^^^^ -note: but, the lifetime must be valid for the lifetime `'a` as defined on the trait at 4:11... +note: but, the lifetime must be valid for the lifetime `'a` as defined here... --> $DIR/issue-17758.rs:4:11 | LL | trait Foo<'a> { diff --git a/src/test/ui/issues/issue-17905-2.stderr b/src/test/ui/issues/issue-17905-2.stderr index 3c27f70585..c68265f71f 100644 --- a/src/test/ui/issues/issue-17905-2.stderr +++ b/src/test/ui/issues/issue-17905-2.stderr @@ -6,12 +6,12 @@ LL | fn say(self: &Pair<&str, isize>) { | = note: expected struct `Pair<&str, _>` found struct `Pair<&str, _>` -note: the anonymous lifetime defined on the method body at 8:24... +note: the anonymous lifetime defined here... --> $DIR/issue-17905-2.rs:8:24 | LL | fn say(self: &Pair<&str, isize>) { | ^^^^ -note: ...does not necessarily outlive the lifetime `'_` as defined on the impl at 5:5 +note: ...does not necessarily outlive the lifetime `'_` as defined here --> $DIR/issue-17905-2.rs:5:5 | LL | &str, @@ -25,12 +25,12 @@ LL | fn say(self: &Pair<&str, isize>) { | = note: expected struct `Pair<&str, _>` found struct `Pair<&str, _>` -note: the lifetime `'_` as defined on the impl at 5:5... +note: the lifetime `'_` as defined here... --> $DIR/issue-17905-2.rs:5:5 | LL | &str, | ^ -note: ...does not necessarily outlive the anonymous lifetime defined on the method body at 8:24 +note: ...does not necessarily outlive the anonymous lifetime defined here --> $DIR/issue-17905-2.rs:8:24 | LL | fn say(self: &Pair<&str, isize>) { diff --git a/src/test/ui/issues/issue-18294.stderr b/src/test/ui/issues/issue-18294.stderr index 432e9a6518..e0cbd2a216 100644 --- a/src/test/ui/issues/issue-18294.stderr +++ b/src/test/ui/issues/issue-18294.stderr @@ -1,4 +1,4 @@ -error: pointers cannot be cast to integers during const eval. +error: pointers cannot be cast to integers during const eval --> $DIR/issue-18294.rs:3:31 | LL | const Y: usize = unsafe { &X as *const u32 as usize }; diff --git a/src/test/ui/issues/issue-18400.stderr b/src/test/ui/issues/issue-18400.stderr index 92d5308844..92e0f60079 100644 --- a/src/test/ui/issues/issue-18400.stderr +++ b/src/test/ui/issues/issue-18400.stderr @@ -4,7 +4,7 @@ error[E0275]: overflow evaluating the requirement `_: Sized` LL | 0.contains(bits); | ^^^^^^^^ | - = help: consider adding a `#![recursion_limit="256"]` attribute to your crate (`issue_18400`) + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_18400`) note: required because of the requirements on the impl of `Set<&[_]>` for `{integer}` --> $DIR/issue-18400.rs:6:16 | diff --git a/src/test/ui/issues/issue-18959.stderr b/src/test/ui/issues/issue-18959.stderr index 2a5416ce85..b9e2787363 100644 --- a/src/test/ui/issues/issue-18959.stderr +++ b/src/test/ui/issues/issue-18959.stderr @@ -4,7 +4,6 @@ error[E0038]: the trait `Bar` cannot be made into an object LL | fn foo(b: &dyn Bar) { | ^^^^^^^ `Bar` cannot be made into an object | - = help: consider moving `foo` to another trait note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit --> $DIR/issue-18959.rs:1:20 | @@ -12,6 +11,7 @@ LL | pub trait Foo { fn foo(&self, ext_thing: &T); } | ^^^ ...because method `foo` has generic type parameters LL | pub trait Bar: Foo { } | --- this trait cannot be made into an object... + = help: consider moving `foo` to another trait error: aborting due to previous error diff --git a/src/test/ui/issues/issue-19163.stderr b/src/test/ui/issues/issue-19163.stderr index af509aa59d..ae1ae14266 100644 --- a/src/test/ui/issues/issue-19163.stderr +++ b/src/test/ui/issues/issue-19163.stderr @@ -1,8 +1,10 @@ error[E0596]: cannot borrow data in a `&` reference as mutable - --> $DIR/issue-19163.rs:9:14 + --> $DIR/issue-19163.rs:9:5 | LL | mywrite!(&v, "Hello world"); - | ^^ cannot borrow as mutable + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot borrow as mutable + | + = note: this error originates in the macro `mywrite` (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-19358.rs b/src/test/ui/issues/issue-19358.rs index f66e0a1c07..3970a4155e 100644 --- a/src/test/ui/issues/issue-19358.rs +++ b/src/test/ui/issues/issue-19358.rs @@ -1,4 +1,7 @@ // run-pass + +#![allow(dead_code)] + trait Trait { fn dummy(&self) { } } #[derive(Debug)] diff --git a/src/test/ui/issues/issue-19538.stderr b/src/test/ui/issues/issue-19538.stderr index 555d0ff0dc..7b37e1f95d 100644 --- a/src/test/ui/issues/issue-19538.stderr +++ b/src/test/ui/issues/issue-19538.stderr @@ -4,7 +4,6 @@ error[E0038]: the trait `Bar` cannot be made into an object LL | let test: &mut dyn Bar = &mut thing; | ^^^^^^^^^^^^ `Bar` cannot be made into an object | - = help: consider moving `foo` to another trait note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit --> $DIR/issue-19538.rs:2:8 | @@ -13,6 +12,7 @@ LL | fn foo(&self, val: T); ... LL | trait Bar: Foo { } | --- this trait cannot be made into an object... + = help: consider moving `foo` to another trait error[E0038]: the trait `Bar` cannot be made into an object --> $DIR/issue-19538.rs:17:30 @@ -20,7 +20,6 @@ error[E0038]: the trait `Bar` cannot be made into an object LL | let test: &mut dyn Bar = &mut thing; | ^^^^^^^^^^ `Bar` cannot be made into an object | - = help: consider moving `foo` to another trait note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit --> $DIR/issue-19538.rs:2:8 | @@ -29,6 +28,7 @@ LL | fn foo(&self, val: T); ... LL | trait Bar: Foo { } | --- this trait cannot be made into an object... + = help: consider moving `foo` to another trait = note: required because of the requirements on the impl of `CoerceUnsized<&mut dyn Bar>` for `&mut Thing` = note: required by cast to type `&mut dyn Bar` diff --git a/src/test/ui/issues/issue-20413.stderr b/src/test/ui/issues/issue-20413.stderr index 572c8ee33c..9135c5ac36 100644 --- a/src/test/ui/issues/issue-20413.stderr +++ b/src/test/ui/issues/issue-20413.stderr @@ -13,7 +13,7 @@ error[E0275]: overflow evaluating the requirement `NoData Foo for T where NoData: Foo { | ^^^ | - = help: consider adding a `#![recursion_limit="256"]` attribute to your crate (`issue_20413`) + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_20413`) note: required because of the requirements on the impl of `Foo` for `NoData>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` --> $DIR/issue-20413.rs:8:9 | @@ -33,7 +33,7 @@ error[E0275]: overflow evaluating the requirement `NoData Foo for T where NoData: Foo { | ^^^ | - = help: consider adding a `#![recursion_limit="256"]` attribute to your crate (`issue_20413`) + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_20413`) note: required because of the requirements on the impl of `Foo` for `NoData>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` --> $DIR/issue-20413.rs:8:9 | @@ -53,7 +53,7 @@ error[E0275]: overflow evaluating the requirement `EvenLessData Bar for T where EvenLessData: Baz { | ^^^ | - = help: consider adding a `#![recursion_limit="256"]` attribute to your crate (`issue_20413`) + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_20413`) note: required because of the requirements on the impl of `Bar` for `AlmostNoData>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` --> $DIR/issue-20413.rs:28:9 | @@ -78,7 +78,7 @@ error[E0275]: overflow evaluating the requirement `EvenLessData Bar for T where EvenLessData: Baz { | ^^^ | - = help: consider adding a `#![recursion_limit="256"]` attribute to your crate (`issue_20413`) + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_20413`) note: required because of the requirements on the impl of `Bar` for `AlmostNoData>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` --> $DIR/issue-20413.rs:28:9 | @@ -103,7 +103,7 @@ error[E0275]: overflow evaluating the requirement `AlmostNoData Baz for T where AlmostNoData: Bar { | ^^^ | - = help: consider adding a `#![recursion_limit="256"]` attribute to your crate (`issue_20413`) + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_20413`) note: required because of the requirements on the impl of `Baz` for `EvenLessData>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` --> $DIR/issue-20413.rs:36:9 | @@ -128,7 +128,7 @@ error[E0275]: overflow evaluating the requirement `AlmostNoData Baz for T where AlmostNoData: Bar { | ^^^ | - = help: consider adding a `#![recursion_limit="256"]` attribute to your crate (`issue_20413`) + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_20413`) note: required because of the requirements on the impl of `Baz` for `EvenLessData>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` --> $DIR/issue-20413.rs:36:9 | diff --git a/src/test/ui/issues/issue-20605.stderr b/src/test/ui/issues/issue-20605.stderr index 25a90df456..5a67aead75 100644 --- a/src/test/ui/issues/issue-20605.stderr +++ b/src/test/ui/issues/issue-20605.stderr @@ -2,15 +2,19 @@ error[E0277]: the size for values of type `dyn Iterator` cann --> $DIR/issue-20605.rs:2:17 | LL | for item in *things { *item = 0 } - | ^^^^^^^ doesn't have a size known at compile-time + | ^^^^^^^ expected an implementor of trait `IntoIterator` | - = help: the trait `Sized` is not implemented for `dyn Iterator` + = note: the trait bound `dyn Iterator: IntoIterator` is not satisfied = note: required because of the requirements on the impl of `IntoIterator` for `dyn Iterator` 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 } + | ++++ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-20831-debruijn.stderr b/src/test/ui/issues/issue-20831-debruijn.stderr index 03e3311e0f..57f9575bdb 100644 --- a/src/test/ui/issues/issue-20831-debruijn.stderr +++ b/src/test/ui/issues/issue-20831-debruijn.stderr @@ -4,12 +4,12 @@ error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` d LL | fn subscribe(&mut self, t : Box::Output> + 'a>) { | ^^^^^^^^^ | -note: first, the lifetime cannot outlive the anonymous lifetime defined on the method body at 28:58... +note: first, the lifetime cannot outlive the anonymous lifetime defined here... --> $DIR/issue-20831-debruijn.rs:28:58 | LL | fn subscribe(&mut self, t : Box::Output> + 'a>) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: ...but the lifetime must also be valid for the lifetime `'a` as defined on the impl at 26:6... +note: ...but the lifetime must also be valid for the lifetime `'a` as defined here... --> $DIR/issue-20831-debruijn.rs:26:6 | LL | impl<'a> Publisher<'a> for MyStruct<'a> { @@ -19,8 +19,8 @@ note: ...so that the types are compatible | LL | fn subscribe(&mut self, t : Box::Output> + 'a>) { | ^^^^^^^^^ - = note: expected `Publisher<'_>` - found `Publisher<'_>` + = note: expected ` as Publisher<'_>>` + found ` as Publisher<'_>>` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-2150.stderr b/src/test/ui/issues/issue-2150.stderr index f1cb3890a7..26874faa2b 100644 --- a/src/test/ui/issues/issue-2150.stderr +++ b/src/test/ui/issues/issue-2150.stderr @@ -2,7 +2,7 @@ error: unreachable statement --> $DIR/issue-2150.rs:8:5 | LL | panic!(); - | --------- any code following this expression is unreachable + | -------- any code following this expression is unreachable LL | for x in &v { i += 1; } | ^^^^^^^^^^^^^^^^^^^^^^^ unreachable statement | diff --git a/src/test/ui/issues/issue-21600.stderr b/src/test/ui/issues/issue-21600.stderr index 84c7106e89..dab3c3d179 100644 --- a/src/test/ui/issues/issue-21600.stderr +++ b/src/test/ui/issues/issue-21600.stderr @@ -5,7 +5,7 @@ LL | fn call_it(f: F) where F: Fn() { f(); } | - change this to accept `FnMut` instead of `Fn` ... LL | call_it(|| x.gen_mut()); - | ------- ^ cannot borrow as mutable + | ------- ^^^^^^^^^^^ cannot borrow as mutable | | | expects `Fn` instead of `FnMut` diff --git a/src/test/ui/issues/issue-23122-2.stderr b/src/test/ui/issues/issue-23122-2.stderr index 68a95dc265..b345e90178 100644 --- a/src/test/ui/issues/issue-23122-2.stderr +++ b/src/test/ui/issues/issue-23122-2.stderr @@ -4,7 +4,7 @@ error[E0275]: overflow evaluating the requirement `<<<<<<<<<<<<<<<<<<<<<<<<<<<<< LL | type Next = as Next>::Next; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: consider adding a `#![recursion_limit="256"]` attribute to your crate (`issue_23122_2`) + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_23122_2`) note: required because of the requirements on the impl of `Next` for `GetNext<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next>` --> $DIR/issue-23122-2.rs:8:15 | diff --git a/src/test/ui/issues/issue-23966.stderr b/src/test/ui/issues/issue-23966.stderr index fff9b3c303..9c87ee6104 100644 --- a/src/test/ui/issues/issue-23966.stderr +++ b/src/test/ui/issues/issue-23966.stderr @@ -2,7 +2,9 @@ error[E0277]: expected a `FnMut<(_, char)>` closure, found `()` --> $DIR/issue-23966.rs:2:32 | LL | "".chars().fold(|_, _| (), ()); - | ^^ expected an `FnMut<(_, char)>` closure, found `()` + | ---- ^^ expected an `FnMut<(_, char)>` closure, found `()` + | | + | required by a bound introduced by this call | = help: the trait `FnMut<(_, char)>` is not implemented for `()` diff --git a/src/test/ui/issues/issue-25076.stderr b/src/test/ui/issues/issue-25076.stderr index ece99596e5..159cc484c5 100644 --- a/src/test/ui/issues/issue-25076.stderr +++ b/src/test/ui/issues/issue-25076.stderr @@ -2,7 +2,9 @@ error[E0277]: the trait bound `(): InOut<_>` is not satisfied --> $DIR/issue-25076.rs:10:20 | LL | do_fold(bot(), ()); - | ^^ the trait `InOut<_>` is not implemented for `()` + | ------- ^^ the trait `InOut<_>` is not implemented for `()` + | | + | required by a bound introduced by this call | note: required by a bound in `do_fold` --> $DIR/issue-25076.rs:5:18 diff --git a/src/test/ui/issues/issue-25385.stderr b/src/test/ui/issues/issue-25385.stderr index 5b8bd94186..39dbdd753a 100644 --- a/src/test/ui/issues/issue-25385.stderr +++ b/src/test/ui/issues/issue-25385.stderr @@ -5,7 +5,7 @@ LL | ($e:expr) => { $e.foo() } | ^^^ method not found in `i32` ... LL | foo!(a); - | -------- in this macro invocation + | ------- in this macro invocation | = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/issues/issue-26093.stderr b/src/test/ui/issues/issue-26093.stderr index 33526721b1..1a08d0fef4 100644 --- a/src/test/ui/issues/issue-26093.stderr +++ b/src/test/ui/issues/issue-26093.stderr @@ -5,7 +5,7 @@ LL | $thing = 42; | ^ ... LL | not_a_place!(99); - | ----------------- + | ---------------- | | | | | cannot assign to this expression | in this macro invocation @@ -19,7 +19,7 @@ LL | $thing += 42; | ^^ ... LL | not_a_place!(99); - | ----------------- + | ---------------- | | | | | cannot assign to this expression | in this macro invocation diff --git a/src/test/ui/issues/issue-26217.nll.stderr b/src/test/ui/issues/issue-26217.nll.stderr index 83f10c67d4..c7601caacd 100644 --- a/src/test/ui/issues/issue-26217.nll.stderr +++ b/src/test/ui/issues/issue-26217.nll.stderr @@ -5,8 +5,6 @@ LL | fn bar<'a>() { | -- lifetime `'a` defined here LL | foo::<&'a i32>(); | ^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` - | - = help: consider replacing `'a` with `'static` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-27942.stderr b/src/test/ui/issues/issue-27942.stderr index 80eecb42d1..a0126b68fd 100644 --- a/src/test/ui/issues/issue-27942.stderr +++ b/src/test/ui/issues/issue-27942.stderr @@ -6,12 +6,12 @@ LL | fn select(&self) -> BufferViewHandle; | = note: expected type `Resources<'_>` found type `Resources<'a>` -note: the anonymous lifetime defined on the method body at 5:15... +note: the anonymous lifetime defined here... --> $DIR/issue-27942.rs:5:15 | LL | fn select(&self) -> BufferViewHandle; | ^^^^^ -note: ...does not necessarily outlive the lifetime `'a` as defined on the trait at 3:18 +note: ...does not necessarily outlive the lifetime `'a` as defined here --> $DIR/issue-27942.rs:3:18 | LL | pub trait Buffer<'a, R: Resources<'a>> { @@ -25,12 +25,12 @@ LL | fn select(&self) -> BufferViewHandle; | = note: expected type `Resources<'_>` found type `Resources<'a>` -note: the lifetime `'a` as defined on the trait at 3:18... +note: the lifetime `'a` as defined here... --> $DIR/issue-27942.rs:3:18 | LL | pub trait Buffer<'a, R: Resources<'a>> { | ^^ -note: ...does not necessarily outlive the anonymous lifetime defined on the method body at 5:15 +note: ...does not necessarily outlive the anonymous lifetime defined here --> $DIR/issue-27942.rs:5:15 | LL | fn select(&self) -> BufferViewHandle; diff --git a/src/test/ui/issues/issue-28098.stderr b/src/test/ui/issues/issue-28098.stderr index 70caeb0ea3..6a74f4ed48 100644 --- a/src/test/ui/issues/issue-28098.stderr +++ b/src/test/ui/issues/issue-28098.stderr @@ -2,7 +2,9 @@ error[E0277]: `()` is not an iterator --> $DIR/issue-28098.rs:2:28 | LL | let _ = Iterator::next(&mut ()); - | ^^^^^^^ `()` is not an iterator + | -------------- ^^^^^^^ `()` is not an iterator + | | + | required by a bound introduced by this call | = help: the trait `Iterator` is not implemented for `()` note: required by `std::iter::Iterator::next` @@ -29,7 +31,9 @@ error[E0277]: `()` is not an iterator --> $DIR/issue-28098.rs:9:28 | LL | let _ = Iterator::next(&mut ()); - | ^^^^^^^ `()` is not an iterator + | -------------- ^^^^^^^ `()` is not an iterator + | | + | required by a bound introduced by this call | = help: the trait `Iterator` is not implemented for `()` note: required by `std::iter::Iterator::next` @@ -50,7 +54,9 @@ error[E0277]: `()` is not an iterator --> $DIR/issue-28098.rs:18:28 | LL | let _ = Iterator::next(&mut ()); - | ^^^^^^^ `()` is not an iterator + | -------------- ^^^^^^^ `()` is not an iterator + | | + | required by a bound introduced by this call | = help: the trait `Iterator` is not implemented for `()` note: required by `std::iter::Iterator::next` @@ -63,7 +69,9 @@ error[E0277]: `()` is not an iterator --> $DIR/issue-28098.rs:22:28 | LL | let _ = Iterator::next(&mut ()); - | ^^^^^^^ `()` is not an iterator + | -------------- ^^^^^^^ `()` is not an iterator + | | + | required by a bound introduced by this call | = help: the trait `Iterator` is not implemented for `()` note: required by `std::iter::Iterator::next` diff --git a/src/test/ui/issues/issue-29084.stderr b/src/test/ui/issues/issue-29084.stderr index fec1c55f89..a973e23e29 100644 --- a/src/test/ui/issues/issue-29084.stderr +++ b/src/test/ui/issues/issue-29084.stderr @@ -5,7 +5,7 @@ LL | bar(&mut $d); | ^^^^^^^ expected `u8`, found `&mut u8` ... LL | foo!(0u8); - | ---------- in this macro invocation + | --------- in this macro invocation | = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/issues/issue-2995.stderr b/src/test/ui/issues/issue-2995.stderr index 455d32e233..7616f987d7 100644 --- a/src/test/ui/issues/issue-2995.stderr +++ b/src/test/ui/issues/issue-2995.stderr @@ -6,8 +6,9 @@ LL | let _q: &isize = p as &isize; | help: consider borrowing the value | -LL | let _q: &isize = &*p as &isize; - | ++ +LL - let _q: &isize = p as &isize; +LL + let _q: &isize = &*p; + | error: aborting due to previous error diff --git a/src/test/ui/issues/issue-30355.stderr b/src/test/ui/issues/issue-30355.stderr index 79f5db650d..71bbdf5dec 100644 --- a/src/test/ui/issues/issue-30355.stderr +++ b/src/test/ui/issues/issue-30355.stderr @@ -1,8 +1,8 @@ error[E0277]: the size for values of type `[u8]` cannot be known at compilation time - --> $DIR/issue-30355.rs:5:6 + --> $DIR/issue-30355.rs:5:8 | LL | &X(*Y) - | ^ 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 `[u8]` = note: all function arguments must have a statically known size diff --git a/src/test/ui/issues/issue-31011.stderr b/src/test/ui/issues/issue-31011.stderr index ab04159486..58c170409f 100644 --- a/src/test/ui/issues/issue-31011.stderr +++ b/src/test/ui/issues/issue-31011.stderr @@ -8,7 +8,7 @@ LL | fn wrap(context: &T) -> () | - type parameter 'T' declared here LL | { LL | log!(context, "entered wrapper"); - | --------------------------------- in this macro invocation + | -------------------------------- in this macro invocation | = note: this error originates in the macro `log` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/issues/issue-31076.rs b/src/test/ui/issues/issue-31076.rs index f9c35526ec..cdb196d4ff 100644 --- a/src/test/ui/issues/issue-31076.rs +++ b/src/test/ui/issues/issue-31076.rs @@ -11,7 +11,7 @@ impl Add for i32 {} fn main() { let x = 5 + 6; - //~^ ERROR cannot add `{integer}` to `{integer}` + //~^ ERROR cannot add `i32` to `{integer}` let y = 5i32 + 6i32; //~^ ERROR cannot add `i32` to `i32` } diff --git a/src/test/ui/issues/issue-31076.stderr b/src/test/ui/issues/issue-31076.stderr index 4c0e1cf7eb..ac0d9dc752 100644 --- a/src/test/ui/issues/issue-31076.stderr +++ b/src/test/ui/issues/issue-31076.stderr @@ -1,8 +1,8 @@ -error[E0369]: cannot add `{integer}` to `{integer}` +error[E0369]: cannot add `i32` to `{integer}` --> $DIR/issue-31076.rs:13:15 | LL | let x = 5 + 6; - | - ^ - {integer} + | - ^ - i32 | | | {integer} diff --git a/src/test/ui/issues/issue-32655.stderr b/src/test/ui/issues/issue-32655.stderr index c0d9899eb8..2d9ce430a4 100644 --- a/src/test/ui/issues/issue-32655.stderr +++ b/src/test/ui/issues/issue-32655.stderr @@ -5,7 +5,7 @@ LL | #[derive_Clone] | ^^^^^^^^^^^^ ... LL | foo!(); - | ------- in this macro invocation + | ------ in this macro invocation | = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/issues/issue-32782.stderr b/src/test/ui/issues/issue-32782.stderr index ed43fa73a0..a6c55ba03f 100644 --- a/src/test/ui/issues/issue-32782.stderr +++ b/src/test/ui/issues/issue-32782.stderr @@ -5,7 +5,7 @@ LL | #[allow_internal_unstable] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ... LL | foo!(); - | ------- in this macro invocation + | ------ in this macro invocation | = help: add `#![feature(allow_internal_unstable)]` to the crate attributes to enable = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/issues/issue-32963.stderr b/src/test/ui/issues/issue-32963.stderr index b5aa7b1b94..5e7762b322 100644 --- a/src/test/ui/issues/issue-32963.stderr +++ b/src/test/ui/issues/issue-32963.stderr @@ -6,7 +6,7 @@ LL | size_of_copy::(); | | | first non-auto trait | - = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Misc + Copy {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Misc + Copy {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error[E0225]: only auto traits can be used as additional traits in a trait object @@ -17,7 +17,7 @@ LL | size_of_copy::(); | | | first non-auto trait | - = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Misc + Copy {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Misc + Copy {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error[E0277]: the trait bound `dyn Misc: Copy` is not satisfied diff --git a/src/test/ui/issues/issue-34255-1.rs b/src/test/ui/issues/issue-34255-1.rs index b1071934bb..c70cd8b507 100644 --- a/src/test/ui/issues/issue-34255-1.rs +++ b/src/test/ui/issues/issue-34255-1.rs @@ -6,5 +6,5 @@ enum Test { fn main() { Test::Drill(field: 42); - //~^ ERROR expected type, found + //~^ ERROR invalid `struct` delimiters or `fn` call arguments } diff --git a/src/test/ui/issues/issue-34255-1.stderr b/src/test/ui/issues/issue-34255-1.stderr index c8bad3b3bb..fbff75e37d 100644 --- a/src/test/ui/issues/issue-34255-1.stderr +++ b/src/test/ui/issues/issue-34255-1.stderr @@ -1,13 +1,18 @@ -error: expected type, found `42` - --> $DIR/issue-34255-1.rs:8:24 +error: invalid `struct` delimiters or `fn` call arguments + --> $DIR/issue-34255-1.rs:8:5 | LL | Test::Drill(field: 42); - | - ^^ expected type - | | - | tried to parse a type due to this type ascription + | ^^^^^^^^^^^^^^^^^^^^^^ | - = note: `#![feature(type_ascription)]` lets you annotate an expression with a type: `: ` - = note: see issue #23416 for more information +help: if `Test::Drill` is a struct, use braces as delimiters + | +LL | Test::Drill { field: 42 }; + | ~ ~ +help: if `Test::Drill` is a function, use the arguments directly + | +LL - Test::Drill(field: 42); +LL + Test::Drill(42); + | error: aborting due to previous error diff --git a/src/test/ui/issues/issue-37884.stderr b/src/test/ui/issues/issue-37884.stderr index d741d42685..cd84b6ef48 100644 --- a/src/test/ui/issues/issue-37884.stderr +++ b/src/test/ui/issues/issue-37884.stderr @@ -11,12 +11,12 @@ LL | | } | = note: expected fn pointer `fn(&mut RepeatMut<'a, T>) -> Option<_>` found fn pointer `fn(&'a mut RepeatMut<'a, T>) -> Option<_>` -note: the anonymous lifetime #1 defined on the method body at 6:5... +note: the anonymous lifetime #1 defined here... --> $DIR/issue-37884.rs:6:5 | LL | fn next(&'a mut self) -> Option | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: ...does not necessarily outlive the lifetime `'a` as defined on the impl at 3:6 +note: ...does not necessarily outlive the lifetime `'a` as defined here --> $DIR/issue-37884.rs:3:6 | LL | impl<'a, T: 'a> Iterator for RepeatMut<'a, T> { diff --git a/src/test/ui/issues/issue-3794.rs b/src/test/ui/issues/issue-3794.rs index 408d8d866d..1809e822c5 100644 --- a/src/test/ui/issues/issue-3794.rs +++ b/src/test/ui/issues/issue-3794.rs @@ -1,5 +1,6 @@ // run-pass #![feature(box_syntax)] +#![allow(dead_code)] trait T { fn print(&self); diff --git a/src/test/ui/issues/issue-3820.stderr b/src/test/ui/issues/issue-3820.stderr index 84f8f9bd14..d5c24e1bb6 100644 --- a/src/test/ui/issues/issue-3820.stderr +++ b/src/test/ui/issues/issue-3820.stderr @@ -6,7 +6,22 @@ LL | let w = u * 3; | | | Thing | - = note: an implementation of `std::ops::Mul` might be missing for `Thing` +note: an implementation of `Mul<_>` might be missing for `Thing` + --> $DIR/issue-3820.rs:1:1 + | +LL | struct Thing { + | ^^^^^^^^^^^^ must implement `Mul<_>` +note: the following trait must be implemented + --> $SRC_DIR/core/src/ops/arith.rs:LL:COL + | +LL | / pub trait Mul { +LL | | /// The resulting type after applying the `*` operator. +LL | | #[stable(feature = "rust1", since = "1.0.0")] +LL | | type Output; +... | +LL | | fn mul(self, rhs: Rhs) -> Self::Output; +LL | | } + | |_^ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-39848.stderr b/src/test/ui/issues/issue-39848.stderr index 02c6cd0ca4..08faed24bc 100644 --- a/src/test/ui/issues/issue-39848.stderr +++ b/src/test/ui/issues/issue-39848.stderr @@ -9,7 +9,7 @@ LL | if $tgt.has_$field() {} | this `if` expression has a condition, but no block ... LL | get_opt!(bar, foo); - | ------------------- in this macro invocation + | ------------------ in this macro invocation | = note: this error originates in the macro `get_opt` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/issues/issue-41726.stderr b/src/test/ui/issues/issue-41726.stderr index b00a420bc3..22631e7c2a 100644 --- a/src/test/ui/issues/issue-41726.stderr +++ b/src/test/ui/issues/issue-41726.stderr @@ -2,7 +2,7 @@ error[E0596]: cannot borrow data in an index of `HashMap>` a --> $DIR/issue-41726.rs:5:9 | LL | things[src.as_str()].sort(); - | ^^^^^^^^^^^^^^^^^^^^ cannot borrow as mutable + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot borrow as mutable | = help: trait `IndexMut` is required to modify indexed content, but it is not implemented for `HashMap>` diff --git a/src/test/ui/issues/issue-42106.stderr b/src/test/ui/issues/issue-42106.stderr index d5a9d233bc..73cf8652f6 100644 --- a/src/test/ui/issues/issue-42106.stderr +++ b/src/test/ui/issues/issue-42106.stderr @@ -4,9 +4,9 @@ error[E0502]: cannot borrow `*collection` as mutable because it is also borrowed LL | let _a = &collection; | ----------- immutable borrow occurs here LL | collection.swap(1, 2); - | ^^^^^^^^^^ mutable borrow occurs here + | ^^^^^^^^^^^^^^^^^^^^^ mutable borrow occurs here LL | _a.use_ref(); - | -- immutable borrow later used here + | ------------ immutable borrow later used here error: aborting due to previous error diff --git a/src/test/ui/issues/issue-42954.stderr b/src/test/ui/issues/issue-42954.stderr index d00fd4aad7..396a91994e 100644 --- a/src/test/ui/issues/issue-42954.stderr +++ b/src/test/ui/issues/issue-42954.stderr @@ -7,7 +7,7 @@ LL | $i as u32 < 0 | not interpreted as comparison ... LL | is_plainly_printable!(c); - | ------------------------- in this macro invocation + | ------------------------ in this macro invocation | = note: this error originates in the macro `is_plainly_printable` (in Nightly builds, run with -Z macro-backtrace for more info) help: try comparing the cast value diff --git a/src/test/ui/issues/issue-4335.stderr b/src/test/ui/issues/issue-4335.stderr index f187969ff4..fa3b58e127 100644 --- a/src/test/ui/issues/issue-4335.stderr +++ b/src/test/ui/issues/issue-4335.stderr @@ -4,7 +4,10 @@ error[E0507]: cannot move out of `*v`, as `v` is a captured variable in an `FnMu LL | fn f<'r, T>(v: &'r T) -> Box T + 'r> { | - captured outer variable LL | id(Box::new(|| *v)) - | ^^ move occurs because `*v` has type `T`, which does not implement the `Copy` trait + | ---^^ + | | | + | | move occurs because `*v` has type `T`, which does not implement the `Copy` trait + | captured by this `FnMut` closure error: aborting due to previous error diff --git a/src/test/ui/issues/issue-44405.stderr b/src/test/ui/issues/issue-44405.stderr index 1fd69f6e77..626cb2999e 100644 --- a/src/test/ui/issues/issue-44405.stderr +++ b/src/test/ui/issues/issue-44405.stderr @@ -2,7 +2,7 @@ error[E0596]: cannot borrow data in an index of `Container` as mutable --> $DIR/issue-44405.rs:21:5 | LL | container[&mut val].test(); - | ^^^^^^^^^^^^^^^^^^^ cannot borrow as mutable + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot borrow as mutable | = help: trait `IndexMut` is required to modify indexed content, but it is not implemented for `Container` diff --git a/src/test/ui/issues/issue-4736.stderr b/src/test/ui/issues/issue-4736.stderr index 9be4eb1c7f..2a1f1819c3 100644 --- a/src/test/ui/issues/issue-4736.stderr +++ b/src/test/ui/issues/issue-4736.stderr @@ -5,9 +5,12 @@ LL | struct NonCopyable(()); | ----------- `NonCopyable` defined here ... LL | let z = NonCopyable{ p: () }; - | ----------- ^ field does not exist - | | - | help: `NonCopyable` is a tuple struct, use the appropriate syntax: `NonCopyable(/* fields */)` + | ^ field does not exist + | +help: `NonCopyable` is a tuple struct, use the appropriate syntax + | +LL | let z = NonCopyable(/* fields */); + | ~~~~~~~~~~~~~~~~~~~~~~~~~ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-47646.stderr b/src/test/ui/issues/issue-47646.stderr index b46c277d04..eff1de3e01 100644 --- a/src/test/ui/issues/issue-47646.stderr +++ b/src/test/ui/issues/issue-47646.stderr @@ -2,7 +2,7 @@ error[E0502]: cannot borrow `heap` as immutable because it is also borrowed as m --> $DIR/issue-47646.rs:9:30 | LL | let borrow = heap.peek_mut(); - | ---- mutable borrow occurs here + | --------------- mutable borrow occurs here LL | LL | match (borrow, ()) { | ------------ a temporary with access to the mutable borrow is created here ... diff --git a/src/test/ui/issues/issue-47706-trait.stderr b/src/test/ui/issues/issue-47706-trait.stderr index 8a6a199148..2e542644b7 100644 --- a/src/test/ui/issues/issue-47706-trait.stderr +++ b/src/test/ui/issues/issue-47706-trait.stderr @@ -4,7 +4,9 @@ error[E0593]: function is expected to take a single 0-tuple as argument, but it LL | fn f(&self, _: ()) { | ------------------ takes 2 distinct arguments LL | None::<()>.map(Self::f); - | ^^^^^^^ expected function that takes a single 0-tuple as argument + | --- ^^^^^^^ expected function that takes a single 0-tuple as argument + | | + | required by a bound introduced by this call 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 d9680a26e0..acf7626c63 100644 --- a/src/test/ui/issues/issue-47706.stderr +++ b/src/test/ui/issues/issue-47706.stderr @@ -5,7 +5,9 @@ LL | pub fn new(foo: Option, _: ()) -> Foo { | ------------------------------------------ takes 2 arguments ... LL | self.foo.map(Foo::new) - | ^^^^^^^^ expected function that takes 1 argument + | --- ^^^^^^^^ expected function that takes 1 argument + | | + | required by a bound introduced by this call error[E0593]: function is expected to take 0 arguments, but it takes 1 argument --> $DIR/issue-47706.rs:27:9 @@ -14,7 +16,9 @@ LL | Bar(i32), | -------- takes 1 argument ... LL | foo(Qux::Bar); - | ^^^^^^^^ expected function that takes 0 arguments + | --- ^^^^^^^^ expected function that takes 0 arguments + | | + | required by a bound introduced by this call | note: required by a bound in `foo` --> $DIR/issue-47706.rs:22:8 diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.stderr index 21fc3b2bdd..ce8173169b 100644 --- a/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.stderr +++ b/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.stderr @@ -6,7 +6,6 @@ LL | let _result = &Some(42).as_deref(); | = note: the following trait bounds were not satisfied: `{integer}: Deref` - `<{integer} as Deref>::Target = _` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.stderr index c86b024de2..e4e9705b07 100644 --- a/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.stderr +++ b/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.stderr @@ -6,7 +6,7 @@ LL | let _result = &mut Some(42).as_deref_mut(); | = note: the following trait bounds were not satisfied: `{integer}: DerefMut` - `<{integer} as Deref>::Target = _` + `{integer}: Deref` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref.stderr index 9711e27d8a..a3b9ac6775 100644 --- a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref.stderr +++ b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref.stderr @@ -6,7 +6,6 @@ LL | let _result = &Ok(42).as_deref(); | = note: the following trait bounds were not satisfied: `{integer}: Deref` - `<{integer} as Deref>::Target = _` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.stderr index ee7ea1e6a0..98a7091dd0 100644 --- a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.stderr +++ b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.stderr @@ -6,7 +6,7 @@ LL | let _result = &mut Ok(42).as_deref_mut(); | = note: the following trait bounds were not satisfied: `{integer}: DerefMut` - `<{integer} as Deref>::Target = _` + `{integer}: Deref` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-50403.stderr b/src/test/ui/issues/issue-50403.stderr index d20a98ecc6..a3a2ed044d 100644 --- a/src/test/ui/issues/issue-50403.stderr +++ b/src/test/ui/issues/issue-50403.stderr @@ -1,4 +1,4 @@ -error: concat_idents! takes 1 or more arguments. +error: concat_idents! takes 1 or more arguments --> $DIR/issue-50403.rs:4:13 | LL | let x = concat_idents!(); diff --git a/src/test/ui/issues/issue-51102.stderr b/src/test/ui/issues/issue-51102.stderr index eb9eb68020..09c52292dc 100644 --- a/src/test/ui/issues/issue-51102.stderr +++ b/src/test/ui/issues/issue-51102.stderr @@ -2,7 +2,10 @@ error[E0026]: struct `SimpleStruct` does not have a field named `state` --> $DIR/issue-51102.rs:13:17 | LL | state: 0, - | ^^^^^ struct `SimpleStruct` does not have this field + | ^^^^^ + | | + | struct `SimpleStruct` does not have this field + | help: `SimpleStruct` has a field named `no_state_here` error[E0025]: field `no_state_here` bound multiple times in the pattern --> $DIR/issue-51102.rs:24:17 diff --git a/src/test/ui/issues/issue-51632-try-desugar-incompatible-types.rs b/src/test/ui/issues/issue-51632-try-desugar-incompatible-types.rs index bb74f0e0dc..35402dff67 100644 --- a/src/test/ui/issues/issue-51632-try-desugar-incompatible-types.rs +++ b/src/test/ui/issues/issue-51632-try-desugar-incompatible-types.rs @@ -6,7 +6,7 @@ fn missing_discourses() -> Result { fn forbidden_narratives() -> Result { missing_discourses()? - //~^ ERROR try expression alternatives have incompatible types + //~^ ERROR: `?` operator has incompatible types } fn main() {} 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 2c821aa230..0f61e03c3b 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 @@ -1,9 +1,10 @@ -error[E0308]: try expression alternatives have incompatible types +error[E0308]: `?` operator has incompatible types --> $DIR/issue-51632-try-desugar-incompatible-types.rs:8:5 | LL | missing_discourses()? | ^^^^^^^^^^^^^^^^^^^^^ expected enum `Result`, found `isize` | + = note: `?` operator cannot convert from `isize` to `Result` = note: expected enum `Result` found type `isize` help: try removing this `?` diff --git a/src/test/ui/issues/issue-51848.stderr b/src/test/ui/issues/issue-51848.stderr index bb32b7f9a1..c25bedf37b 100644 --- a/src/test/ui/issues/issue-51848.stderr +++ b/src/test/ui/issues/issue-51848.stderr @@ -7,7 +7,7 @@ LL | println!("{"); | because of this opening brace ... LL | macro_with_error!(); - | -------------------- in this macro invocation + | ------------------- in this macro invocation | = note: if you intended to print `{`, you can escape it using `{{` = note: this error originates in the macro `macro_with_error` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/issues/issue-52126-assign-op-invariance.stderr b/src/test/ui/issues/issue-52126-assign-op-invariance.stderr index d231f621e5..d450675776 100644 --- a/src/test/ui/issues/issue-52126-assign-op-invariance.stderr +++ b/src/test/ui/issues/issue-52126-assign-op-invariance.stderr @@ -2,7 +2,7 @@ error[E0597]: `line` does not live long enough --> $DIR/issue-52126-assign-op-invariance.rs:34:28 | LL | let v: Vec<&str> = line.split_whitespace().collect(); - | ^^^^ borrowed value does not live long enough + | ^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough ... LL | acc += cnt2; | --- borrow later used here diff --git a/src/test/ui/issues/issue-52213.stderr b/src/test/ui/issues/issue-52213.stderr index 7463af9332..aef5e258a1 100644 --- a/src/test/ui/issues/issue-52213.stderr +++ b/src/test/ui/issues/issue-52213.stderr @@ -4,7 +4,7 @@ error[E0495]: cannot infer an appropriate lifetime due to conflicting requiremen LL | match (&t,) { | ^^^^^ | -note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 1:23... +note: first, the lifetime cannot outlive the lifetime `'a` as defined here... --> $DIR/issue-52213.rs:1:23 | LL | fn transmute_lifetime<'a, 'b, T>(t: &'a (T,)) -> &'b T { @@ -16,7 +16,7 @@ LL | match (&t,) { | ^^^^^ = note: expected `(&&(T,),)` found `(&&'a (T,),)` -note: but, the lifetime must be valid for the lifetime `'b` as defined on the function body at 1:27... +note: but, the lifetime must be valid for the lifetime `'b` as defined here... --> $DIR/issue-52213.rs:1:27 | LL | fn transmute_lifetime<'a, 'b, T>(t: &'a (T,)) -> &'b T { diff --git a/src/test/ui/issues/issue-52533-1.stderr b/src/test/ui/issues/issue-52533-1.stderr index 4247d55156..475c7d0b48 100644 --- a/src/test/ui/issues/issue-52533-1.stderr +++ b/src/test/ui/issues/issue-52533-1.stderr @@ -6,12 +6,12 @@ LL | gimme(|x, y| y) | = note: expected reference `&Foo<'_, '_, u32>` found reference `&Foo<'_, '_, u32>` -note: the anonymous lifetime #3 defined on the body at 9:11... +note: the anonymous lifetime #3 defined here... --> $DIR/issue-52533-1.rs:9:11 | LL | gimme(|x, y| y) | ^^^^^^^^ -note: ...does not necessarily outlive the anonymous lifetime #2 defined on the body at 9:11 +note: ...does not necessarily outlive the anonymous lifetime #2 defined here --> $DIR/issue-52533-1.rs:9:11 | LL | gimme(|x, y| y) diff --git a/src/test/ui/issues/issue-52533.stderr b/src/test/ui/issues/issue-52533.stderr index 4e41620eec..ccedbcfec7 100644 --- a/src/test/ui/issues/issue-52533.stderr +++ b/src/test/ui/issues/issue-52533.stderr @@ -4,12 +4,12 @@ error[E0312]: lifetime of reference outlives lifetime of borrowed content... LL | foo(|a, b| b) | ^ | -note: ...the reference is valid for the anonymous lifetime #1 defined on the body at 5:9... +note: ...the reference is valid for the anonymous lifetime #1 defined here... --> $DIR/issue-52533.rs:5:9 | LL | foo(|a, b| b) | ^^^^^^^^ -note: ...but the borrowed content is only valid for the anonymous lifetime #2 defined on the body at 5:9 +note: ...but the borrowed content is only valid for the anonymous lifetime #2 defined here --> $DIR/issue-52533.rs:5:9 | LL | foo(|a, b| b) diff --git a/src/test/ui/issues/issue-53251.stderr b/src/test/ui/issues/issue-53251.stderr index fd2522dfbe..cee9a5deb0 100644 --- a/src/test/ui/issues/issue-53251.stderr +++ b/src/test/ui/issues/issue-53251.stderr @@ -7,7 +7,7 @@ LL | S::f::(); | expected 0 generic arguments ... LL | impl_add!(a b); - | --------------- in this macro invocation + | -------------- in this macro invocation | note: associated function defined here, with 0 generic parameters --> $DIR/issue-53251.rs:4:8 @@ -25,7 +25,7 @@ LL | S::f::(); | expected 0 generic arguments ... LL | impl_add!(a b); - | --------------- in this macro invocation + | -------------- in this macro invocation | note: associated function defined here, with 0 generic parameters --> $DIR/issue-53251.rs:4:8 diff --git a/src/test/ui/issues/issue-54943.nll.stderr b/src/test/ui/issues/issue-54943.nll.stderr index 5bf6d3382d..59be0f983b 100644 --- a/src/test/ui/issues/issue-54943.nll.stderr +++ b/src/test/ui/issues/issue-54943.nll.stderr @@ -6,8 +6,6 @@ LL | fn boo<'a>() { ... LL | let x = foo::<&'a u32>(); | ^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` - | - = help: consider replacing `'a` with `'static` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-55796.nll.stderr b/src/test/ui/issues/issue-55796.nll.stderr index 61d4070d48..c1a3084f30 100644 --- a/src/test/ui/issues/issue-55796.nll.stderr +++ b/src/test/ui/issues/issue-55796.nll.stderr @@ -6,8 +6,6 @@ LL | pub trait Graph<'a> { ... LL | Box::new(self.out_edges(u).map(|e| e.target())) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static` - | - = help: consider replacing `'a` with `'static` error: lifetime may not live long enough --> $DIR/issue-55796.rs:23:9 @@ -17,8 +15,6 @@ LL | pub trait Graph<'a> { ... LL | Box::new(self.in_edges(u).map(|e| e.target())) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static` - | - = help: consider replacing `'a` with `'static` error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-55796.stderr b/src/test/ui/issues/issue-55796.stderr index ffe3bb737a..304339657f 100644 --- a/src/test/ui/issues/issue-55796.stderr +++ b/src/test/ui/issues/issue-55796.stderr @@ -4,7 +4,7 @@ error[E0495]: cannot infer an appropriate lifetime due to conflicting requiremen LL | Box::new(self.out_edges(u).map(|e| e.target())) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: first, the lifetime cannot outlive the lifetime `'a` as defined on the trait at 7:17... +note: first, the lifetime cannot outlive the lifetime `'a` as defined here... --> $DIR/issue-55796.rs:7:17 | LL | pub trait Graph<'a> { @@ -15,7 +15,7 @@ note: ...so that the type `Map<>::EdgesIter, [closure@$DIR/iss LL | Box::new(self.out_edges(u).map(|e| e.target())) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: but, the lifetime must be valid for the static lifetime... -note: ...so that the expression is assignable +note: ...so that the types are compatible --> $DIR/issue-55796.rs:18:9 | LL | Box::new(self.out_edges(u).map(|e| e.target())) @@ -29,7 +29,7 @@ error[E0495]: cannot infer an appropriate lifetime due to conflicting requiremen LL | Box::new(self.in_edges(u).map(|e| e.target())) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: first, the lifetime cannot outlive the lifetime `'a` as defined on the trait at 7:17... +note: first, the lifetime cannot outlive the lifetime `'a` as defined here... --> $DIR/issue-55796.rs:7:17 | LL | pub trait Graph<'a> { @@ -40,7 +40,7 @@ note: ...so that the type `Map<>::EdgesIter, [closure@$DIR/iss LL | Box::new(self.in_edges(u).map(|e| e.target())) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: but, the lifetime must be valid for the static lifetime... -note: ...so that the expression is assignable +note: ...so that the types are compatible --> $DIR/issue-55796.rs:23:9 | LL | Box::new(self.in_edges(u).map(|e| e.target())) diff --git a/src/test/ui/issues/issue-56031.stderr b/src/test/ui/issues/issue-56031.stderr index 3d7acee0a5..7ee5bc6ec6 100644 --- a/src/test/ui/issues/issue-56031.stderr +++ b/src/test/ui/issues/issue-56031.stderr @@ -3,6 +3,16 @@ error: missing trait in a trait impl | LL | impl for T {} | ^ + | +help: add a trait here + | +LL | impl Trait for T {} + | +++++ +help: for an inherent impl, drop this `for` + | +LL - impl for T {} +LL + impl T {} + | error: aborting due to previous error diff --git a/src/test/ui/issues/issue-5791.rs b/src/test/ui/issues/issue-5791.rs deleted file mode 100644 index 3544160f09..0000000000 --- a/src/test/ui/issues/issue-5791.rs +++ /dev/null @@ -1,14 +0,0 @@ -// run-pass -#![allow(dead_code)] -#![warn(clashing_extern_declarations)] -// pretty-expanded FIXME #23616 - -extern "C" { - #[link_name = "malloc"] - fn malloc1(len: i32) -> *const u8; - #[link_name = "malloc"] - //~^ WARN `malloc2` redeclares `malloc` with a different signature - fn malloc2(len: i32, foo: i32) -> *const u8; -} - -pub fn main() {} diff --git a/src/test/ui/issues/issue-5791.stderr b/src/test/ui/issues/issue-5791.stderr deleted file mode 100644 index cf60e609de..0000000000 --- a/src/test/ui/issues/issue-5791.stderr +++ /dev/null @@ -1,21 +0,0 @@ -warning: `malloc2` redeclares `malloc` with a different signature - --> $DIR/issue-5791.rs:9:5 - | -LL | / #[link_name = "malloc"] -LL | | fn malloc1(len: i32) -> *const u8; - | |______________________________________- `malloc` previously declared here -LL | / #[link_name = "malloc"] -LL | | -LL | | fn malloc2(len: i32, foo: i32) -> *const u8; - | |________________________________________________^ this signature doesn't match the previous declaration - | -note: the lint level is defined here - --> $DIR/issue-5791.rs:3:9 - | -LL | #![warn(clashing_extern_declarations)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: expected `unsafe extern "C" fn(i32) -> *const u8` - found `unsafe extern "C" fn(i32, i32) -> *const u8` - -warning: 1 warning emitted - diff --git a/src/test/ui/issues/issue-59488.stderr b/src/test/ui/issues/issue-59488.stderr index 7789ee342a..f739557e00 100644 --- a/src/test/ui/issues/issue-59488.stderr +++ b/src/test/ui/issues/issue-59488.stderr @@ -72,7 +72,7 @@ error[E0369]: binary operation `==` cannot be applied to type `fn(usize) -> Foo --> $DIR/issue-59488.rs:30:5 | LL | assert_eq!(Foo::Bar, i); - | ^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^ | | | fn(usize) -> Foo {Foo::Bar} | fn(usize) -> Foo {Foo::Bar} @@ -83,7 +83,7 @@ error[E0277]: `fn(usize) -> Foo {Foo::Bar}` doesn't implement `Debug` --> $DIR/issue-59488.rs:30:5 | LL | assert_eq!(Foo::Bar, i); - | ^^^^^^^^^^^^^^^^^^^^^^^^ `fn(usize) -> Foo {Foo::Bar}` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | ^^^^^^^^^^^^^^^^^^^^^^^ `fn(usize) -> Foo {Foo::Bar}` cannot be formatted using `{:?}` because it doesn't implement `Debug` | = help: the trait `Debug` is not implemented for `fn(usize) -> Foo {Foo::Bar}` = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/issues/issue-59494.stderr b/src/test/ui/issues/issue-59494.stderr index 90af47dfa7..9b7fe1ef78 100644 --- a/src/test/ui/issues/issue-59494.stderr +++ b/src/test/ui/issues/issue-59494.stderr @@ -2,7 +2,9 @@ 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<(((_, _), _),)>` note: required by a bound in `t8n` diff --git a/src/test/ui/issues/issue-60218.stderr b/src/test/ui/issues/issue-60218.stderr index ac33cfd040..870b250144 100644 --- a/src/test/ui/issues/issue-60218.stderr +++ b/src/test/ui/issues/issue-60218.stderr @@ -1,8 +1,10 @@ error[E0277]: the trait bound `&u32: Foo` is not satisfied - --> $DIR/issue-60218.rs:18:5 + --> $DIR/issue-60218.rs:18:27 | LL | trigger_error(vec![], |x: &u32| x) - | ^^^^^^^^^^^^^ the trait `Foo` is not implemented for `&u32` + | ------------- ^^^^^^^^^^^ the trait `Foo` is not implemented for `&u32` + | | + | required by a bound introduced by this call | note: required by a bound in `trigger_error` --> $DIR/issue-60218.rs:13:72 diff --git a/src/test/ui/issues/issue-60283.stderr b/src/test/ui/issues/issue-60283.stderr index 2ee5510521..34893cd8f1 100644 --- a/src/test/ui/issues/issue-60283.stderr +++ b/src/test/ui/issues/issue-60283.stderr @@ -2,10 +2,11 @@ error[E0631]: type mismatch in function arguments --> $DIR/issue-60283.rs:17:13 | LL | foo((), drop) - | ^^^^ - | | - | expected signature of `for<'a> fn(<() as Trait<'a>>::Item) -> _` - | found signature of `fn(()) -> _` + | --- ^^^^ + | | | + | | expected signature of `for<'a> fn(<() as Trait<'a>>::Item) -> _` + | | found signature of `fn(()) -> _` + | required by a bound introduced by this call | note: required by a bound in `foo` --> $DIR/issue-60283.rs:12:16 @@ -20,7 +21,9 @@ error[E0277]: the size for values of type `<() as Trait<'_>>::Item` cannot be kn --> $DIR/issue-60283.rs:17:13 | LL | foo((), drop) - | ^^^^ doesn't have a size known at compile-time + | --- ^^^^ 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 `<() as Trait<'_>>::Item` note: required by a bound in `std::mem::drop` diff --git a/src/test/ui/issues/issue-61108.stderr b/src/test/ui/issues/issue-61108.stderr index fb242f738c..6f345f56d1 100644 --- a/src/test/ui/issues/issue-61108.stderr +++ b/src/test/ui/issues/issue-61108.stderr @@ -10,7 +10,7 @@ LL | for l in bad_letters { | help: consider borrowing to avoid moving into the for loop: `&bad_letters` ... LL | bad_letters.push('s'); - | ^^^^^^^^^^^ value borrowed here after move + | ^^^^^^^^^^^^^^^^^^^^^ value borrowed here after move | note: this function takes ownership of the receiver `self`, which moves `bad_letters` --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL diff --git a/src/test/ui/issues/issue-61882-2.stderr b/src/test/ui/issues/issue-61882-2.stderr index 03a65540ce..0b8e134c96 100644 --- a/src/test/ui/issues/issue-61882-2.stderr +++ b/src/test/ui/issues/issue-61882-2.stderr @@ -5,7 +5,7 @@ LL | Self(&x); | ^^ | | | borrowed value does not live long enough - | requires that `x` is borrowed for `'static` + | this usage requires that `x` is borrowed for `'static` LL | LL | } | - `x` dropped here while still borrowed diff --git a/src/test/ui/issues/issue-62375.stderr b/src/test/ui/issues/issue-62375.stderr index 6db45630b9..478e025bed 100644 --- a/src/test/ui/issues/issue-62375.stderr +++ b/src/test/ui/issues/issue-62375.stderr @@ -6,7 +6,15 @@ LL | a == A::Value; | | | A | - = note: an implementation of `std::cmp::PartialEq` might be missing for `A` +note: an implementation of `PartialEq<_>` might be missing for `A` + --> $DIR/issue-62375.rs:1:1 + | +LL | enum A { + | ^^^^^^ must implement `PartialEq<_>` +help: consider annotating `A` with `#[derive(PartialEq)]` + | +LL | #[derive(PartialEq)] + | error: aborting due to previous error diff --git a/src/test/ui/issues/issue-65230.rs b/src/test/ui/issues/issue-65230.rs new file mode 100644 index 0000000000..54141d2214 --- /dev/null +++ b/src/test/ui/issues/issue-65230.rs @@ -0,0 +1,11 @@ +trait T0 {} +trait T1: T0 {} + +trait T2 {} + +impl<'a> T0 for &'a (dyn T2 + 'static) {} + +impl T1 for &dyn T2 {} +//~^ ERROR mismatched types + +fn main() {} diff --git a/src/test/ui/issues/issue-65230.stderr b/src/test/ui/issues/issue-65230.stderr new file mode 100644 index 0000000000..bfeb38d647 --- /dev/null +++ b/src/test/ui/issues/issue-65230.stderr @@ -0,0 +1,18 @@ +error[E0308]: mismatched types + --> $DIR/issue-65230.rs:8:6 + | +LL | impl T1 for &dyn T2 {} + | ^^ lifetime mismatch + | + = note: expected trait `<&dyn T2 as T0>` + found trait `<&(dyn T2 + 'static) as T0>` +note: the lifetime `'_` as defined here... + --> $DIR/issue-65230.rs:8:13 + | +LL | impl T1 for &dyn T2 {} + | ^ + = note: ...does not necessarily outlive the static lifetime + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/issues/issue-6596-1.stderr b/src/test/ui/issues/issue-6596-1.stderr index c01205223d..7ab3685c5c 100644 --- a/src/test/ui/issues/issue-6596-1.stderr +++ b/src/test/ui/issues/issue-6596-1.stderr @@ -5,7 +5,7 @@ LL | $nonexistent | ^^^^^^^^^^^^ expected expression ... LL | e!(foo); - | -------- in this macro invocation + | ------- in this macro invocation | = note: this error originates in the macro `e` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/issues/issue-6596-2.stderr b/src/test/ui/issues/issue-6596-2.stderr index 90627d3bbd..3fe3d4d9d6 100644 --- a/src/test/ui/issues/issue-6596-2.stderr +++ b/src/test/ui/issues/issue-6596-2.stderr @@ -5,7 +5,7 @@ LL | { $inp $nonexistent } | ^^^^^^^^^^^^ expected one of 8 possible tokens ... LL | g!(foo); - | -------- in this macro invocation + | ------- in this macro invocation | = note: this error originates in the macro `g` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/issues/issue-66353.stderr b/src/test/ui/issues/issue-66353.stderr index 59a521c736..282e236d3d 100644 --- a/src/test/ui/issues/issue-66353.stderr +++ b/src/test/ui/issues/issue-66353.stderr @@ -8,7 +8,9 @@ error[E0277]: the trait bound `(): _Func<_>` is not satisfied --> $DIR/issue-66353.rs:12:41 | LL | _Func::< <() as _A>::AssocT >::func(()); - | ^^ the trait `_Func<_>` is not implemented for `()` + | ----------------------------------- ^^ 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 diff --git a/src/test/ui/issues/issue-68091-unicode-ident-after-if.stderr b/src/test/ui/issues/issue-68091-unicode-ident-after-if.stderr index 43fda800cf..cdd4c67050 100644 --- a/src/test/ui/issues/issue-68091-unicode-ident-after-if.stderr +++ b/src/test/ui/issues/issue-68091-unicode-ident-after-if.stderr @@ -11,7 +11,7 @@ LL | $($c)ö* {} | ^^ expected `bool`, found `()` ... LL | x!(if); - | ------- in this macro invocation + | ------ in this macro invocation | = note: this error originates in the macro `x` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/issues/issue-70724-add_type_neq_err_label-unwrap.stderr b/src/test/ui/issues/issue-70724-add_type_neq_err_label-unwrap.stderr index f074a99e5e..cd4cc96920 100644 --- a/src/test/ui/issues/issue-70724-add_type_neq_err_label-unwrap.stderr +++ b/src/test/ui/issues/issue-70724-add_type_neq_err_label-unwrap.stderr @@ -2,7 +2,7 @@ error[E0369]: binary operation `==` cannot be applied to type `fn() -> i32 {a}` --> $DIR/issue-70724-add_type_neq_err_label-unwrap.rs:6:5 | LL | assert_eq!(a, 0); - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ | | | fn() -> i32 {a} | {integer} @@ -14,7 +14,7 @@ error[E0308]: mismatched types --> $DIR/issue-70724-add_type_neq_err_label-unwrap.rs:6:5 | LL | assert_eq!(a, 0); - | ^^^^^^^^^^^^^^^^^ expected fn item, found integer + | ^^^^^^^^^^^^^^^^ expected fn item, found integer | = note: expected fn item `fn() -> i32 {a}` found type `i32` @@ -27,7 +27,7 @@ LL | fn a() -> i32 { | - consider calling this function ... LL | assert_eq!(a, 0); - | ^^^^^^^^^^^^^^^^^ `fn() -> i32 {a}` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | ^^^^^^^^^^^^^^^^ `fn() -> i32 {a}` cannot be formatted using `{:?}` because it doesn't implement `Debug` | = help: the trait `Debug` is not implemented for `fn() -> i32 {a}` = help: use parentheses to call the function: `a()` diff --git a/src/test/ui/issues/issue-75777.nll.stderr b/src/test/ui/issues/issue-75777.nll.stderr index 98aacb1711..d779753687 100644 --- a/src/test/ui/issues/issue-75777.nll.stderr +++ b/src/test/ui/issues/issue-75777.nll.stderr @@ -6,8 +6,6 @@ LL | fn inject<'a, Env: 'a, A: 'a + Send>(v: A) -> Box Bo LL | let fut: BoxFuture<'a, A> = Box::pin(future::ready(v)); LL | Box::new(move |_| fut) | ^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static` - | - = help: consider replacing `'a` with `'static` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-75777.stderr b/src/test/ui/issues/issue-75777.stderr index 16249a33c2..bf271ab78f 100644 --- a/src/test/ui/issues/issue-75777.stderr +++ b/src/test/ui/issues/issue-75777.stderr @@ -4,7 +4,7 @@ error[E0495]: cannot infer an appropriate lifetime due to conflicting requiremen LL | Box::new(move |_| fut) | ^^^^^^^^^^^^ | -note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 11:11... +note: first, the lifetime cannot outlive the lifetime `'a` as defined here... --> $DIR/issue-75777.rs:11:11 | LL | fn inject<'a, Env: 'a, A: 'a + Send>(v: A) -> Box BoxFuture<'a, A>> { @@ -17,7 +17,7 @@ LL | Box::new(move |_| fut) = note: expected `(Pin + Send>>,)` found `(Pin + Send + 'a)>>,)` = note: but, the lifetime must be valid for the static lifetime... -note: ...so that the expression is assignable +note: ...so that the types are compatible --> $DIR/issue-75777.rs:13:5 | LL | Box::new(move |_| fut) diff --git a/src/test/ui/issues/issue-7970a.stderr b/src/test/ui/issues/issue-7970a.stderr index 5cfb62f3d0..ea400d7e19 100644 --- a/src/test/ui/issues/issue-7970a.stderr +++ b/src/test/ui/issues/issue-7970a.stderr @@ -5,7 +5,7 @@ LL | macro_rules! one_arg_macro { | -------------------------- when calling this macro ... LL | one_arg_macro!(); - | ^^^^^^^^^^^^^^^^^ missing tokens in macro arguments + | ^^^^^^^^^^^^^^^^ missing tokens in macro arguments error: aborting due to previous error diff --git a/src/test/ui/issues/issue-80607.stderr b/src/test/ui/issues/issue-80607.stderr index 22a660b416..38e46683b0 100644 --- a/src/test/ui/issues/issue-80607.stderr +++ b/src/test/ui/issues/issue-80607.stderr @@ -5,9 +5,12 @@ LL | V1(i32), | -- `Enum::V1` defined here ... LL | Enum::V1 { x } - | -------- ^ field does not exist - | | - | help: `Enum::V1` is a tuple variant, use the appropriate syntax: `Enum::V1(/* fields */)` + | ^ field does not exist + | +help: `Enum::V1` is a tuple variant, use the appropriate syntax + | +LL | Enum::V1(/* fields */) + | ~~~~~~~~~~~~~~~~~~~~~~ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-81584.stderr b/src/test/ui/issues/issue-81584.stderr index d57f1b778d..54973cfa34 100644 --- a/src/test/ui/issues/issue-81584.stderr +++ b/src/test/ui/issues/issue-81584.stderr @@ -2,7 +2,7 @@ error[E0515]: cannot return value referencing function parameter `y` --> $DIR/issue-81584.rs:5:22 | LL | .map(|y| y.iter().map(|x| x + 1)) - | -^^^^^^^^^^^^^^^^^^^^^^ + | --------^^^^^^^^^^^^^^^ | | | returns a value referencing data owned by the current function | `y` is borrowed here diff --git a/src/test/ui/issues/issue-86865.rs b/src/test/ui/issues/issue-86865.rs new file mode 100644 index 0000000000..01e0a20a51 --- /dev/null +++ b/src/test/ui/issues/issue-86865.rs @@ -0,0 +1,11 @@ +use std::fmt::Write; + +fn main() { + println!(b"foo"); + //~^ ERROR format argument must be a string literal + //~| HELP consider removing the leading `b` + let mut s = String::new(); + write!(s, b"foo{}", "bar"); + //~^ ERROR format argument must be a string literal + //~| HELP consider removing the leading `b` +} diff --git a/src/test/ui/issues/issue-86865.stderr b/src/test/ui/issues/issue-86865.stderr new file mode 100644 index 0000000000..eed7553663 --- /dev/null +++ b/src/test/ui/issues/issue-86865.stderr @@ -0,0 +1,18 @@ +error: format argument must be a string literal + --> $DIR/issue-86865.rs:4:14 + | +LL | println!(b"foo"); + | -^^^^^ + | | + | help: consider removing the leading `b` + +error: format argument must be a string literal + --> $DIR/issue-86865.rs:8:15 + | +LL | write!(s, b"foo{}", "bar"); + | -^^^^^^^ + | | + | help: consider removing the leading `b` + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/issues/issue-87199.stderr b/src/test/ui/issues/issue-87199.stderr index fc9418b36b..0ec5e73f39 100644 --- a/src/test/ui/issues/issue-87199.stderr +++ b/src/test/ui/issues/issue-87199.stderr @@ -20,7 +20,9 @@ error[E0277]: the size for values of type `[i32]` cannot be known at compilation --> $DIR/issue-87199.rs:18:22 | LL | ref_arg::<[i32]>(&[5]); - | ^^^^ doesn't have a size known at compile-time + | ---------------- ^^^^ 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 `[i32]` note: required by a bound in `ref_arg` diff --git a/src/test/ui/issues/issue-8761.stderr b/src/test/ui/issues/issue-8761.stderr index 4c67dbf679..c70093bafb 100644 --- a/src/test/ui/issues/issue-8761.stderr +++ b/src/test/ui/issues/issue-8761.stderr @@ -7,7 +7,7 @@ LL | A = 1i64, help: change the type of the numeric literal from `i64` to `isize` | LL | A = 1isize, - | ~~~~~~ + | ~~~~~ error[E0308]: mismatched types --> $DIR/issue-8761.rs:5:9 @@ -18,7 +18,7 @@ LL | B = 2u8 help: change the type of the numeric literal from `u8` to `isize` | LL | B = 2isize - | ~~~~~~ + | ~~~~~ error: aborting due to 2 previous errors diff --git a/src/test/ui/iterators/into-iter-on-arrays-2018.stderr b/src/test/ui/iterators/into-iter-on-arrays-2018.stderr index bc08fdcafa..e994d69110 100644 --- a/src/test/ui/iterators/into-iter-on-arrays-2018.stderr +++ b/src/test/ui/iterators/into-iter-on-arrays-2018.stderr @@ -1,4 +1,4 @@ -warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021. +warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021 --> $DIR/into-iter-on-arrays-2018.rs:14:34 | LL | let _: Iter<'_, i32> = array.into_iter(); @@ -16,7 +16,7 @@ help: or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicit LL | let _: Iter<'_, i32> = IntoIterator::into_iter(array); | ++++++++++++++++++++++++ ~ -warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021. +warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021 --> $DIR/into-iter-on-arrays-2018.rs:18:44 | LL | let _: Iter<'_, i32> = Box::new(array).into_iter(); @@ -25,7 +25,7 @@ LL | let _: Iter<'_, i32> = Box::new(array).into_iter(); = warning: this changes meaning in Rust 2021 = note: for more information, see -warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021. +warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021 --> $DIR/into-iter-on-arrays-2018.rs:22:43 | LL | let _: Iter<'_, i32> = Rc::new(array).into_iter(); @@ -34,7 +34,7 @@ LL | let _: Iter<'_, i32> = Rc::new(array).into_iter(); = warning: this changes meaning in Rust 2021 = note: for more information, see -warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021. +warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021 --> $DIR/into-iter-on-arrays-2018.rs:25:41 | LL | let _: Iter<'_, i32> = Array(array).into_iter(); @@ -43,7 +43,7 @@ LL | let _: Iter<'_, i32> = Array(array).into_iter(); = warning: this changes meaning in Rust 2021 = note: for more information, see -warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021. +warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021 --> $DIR/into-iter-on-arrays-2018.rs:32:24 | LL | for _ in [1, 2, 3].into_iter() {} diff --git a/src/test/ui/iterators/into-iter-on-arrays-lint.stderr b/src/test/ui/iterators/into-iter-on-arrays-lint.stderr index 2df1a06df2..634728096e 100644 --- a/src/test/ui/iterators/into-iter-on-arrays-lint.stderr +++ b/src/test/ui/iterators/into-iter-on-arrays-lint.stderr @@ -1,4 +1,4 @@ -warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021. +warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021 --> $DIR/into-iter-on-arrays-lint.rs:10:11 | LL | small.into_iter(); @@ -16,7 +16,7 @@ help: or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicit LL | IntoIterator::into_iter(small); | ++++++++++++++++++++++++ ~ -warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021. +warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021 --> $DIR/into-iter-on-arrays-lint.rs:13:12 | LL | [1, 2].into_iter(); @@ -33,7 +33,7 @@ help: or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicit LL | IntoIterator::into_iter([1, 2]); | ++++++++++++++++++++++++ ~ -warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021. +warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021 --> $DIR/into-iter-on-arrays-lint.rs:16:9 | LL | big.into_iter(); @@ -50,7 +50,7 @@ help: or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicit LL | IntoIterator::into_iter(big); | ++++++++++++++++++++++++ ~ -warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021. +warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021 --> $DIR/into-iter-on-arrays-lint.rs:19:15 | LL | [0u8; 33].into_iter(); @@ -67,7 +67,7 @@ help: or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicit LL | IntoIterator::into_iter([0u8; 33]); | ++++++++++++++++++++++++ ~ -warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021. +warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021 --> $DIR/into-iter-on-arrays-lint.rs:23:21 | LL | Box::new(small).into_iter(); @@ -76,7 +76,7 @@ LL | Box::new(small).into_iter(); = warning: this changes meaning in Rust 2021 = note: for more information, see -warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021. +warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021 --> $DIR/into-iter-on-arrays-lint.rs:26:22 | LL | Box::new([1, 2]).into_iter(); @@ -85,7 +85,7 @@ LL | Box::new([1, 2]).into_iter(); = warning: this changes meaning in Rust 2021 = note: for more information, see -warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021. +warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021 --> $DIR/into-iter-on-arrays-lint.rs:29:19 | LL | Box::new(big).into_iter(); @@ -94,7 +94,7 @@ LL | Box::new(big).into_iter(); = warning: this changes meaning in Rust 2021 = note: for more information, see -warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021. +warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021 --> $DIR/into-iter-on-arrays-lint.rs:32:25 | LL | Box::new([0u8; 33]).into_iter(); @@ -103,7 +103,7 @@ LL | Box::new([0u8; 33]).into_iter(); = warning: this changes meaning in Rust 2021 = note: for more information, see -warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021. +warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021 --> $DIR/into-iter-on-arrays-lint.rs:36:31 | LL | Box::new(Box::new(small)).into_iter(); @@ -112,7 +112,7 @@ LL | Box::new(Box::new(small)).into_iter(); = warning: this changes meaning in Rust 2021 = note: for more information, see -warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021. +warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021 --> $DIR/into-iter-on-arrays-lint.rs:39:32 | LL | Box::new(Box::new([1, 2])).into_iter(); @@ -121,7 +121,7 @@ LL | Box::new(Box::new([1, 2])).into_iter(); = warning: this changes meaning in Rust 2021 = note: for more information, see -warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021. +warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021 --> $DIR/into-iter-on-arrays-lint.rs:42:29 | LL | Box::new(Box::new(big)).into_iter(); @@ -130,7 +130,7 @@ LL | Box::new(Box::new(big)).into_iter(); = warning: this changes meaning in Rust 2021 = note: for more information, see -warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021. +warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021 --> $DIR/into-iter-on-arrays-lint.rs:45:35 | LL | Box::new(Box::new([0u8; 33])).into_iter(); diff --git a/src/test/ui/kindck/kindck-impl-type-params-2.rs b/src/test/ui/kindck/kindck-impl-type-params-2.rs index c08f776dbf..8b0771985d 100644 --- a/src/test/ui/kindck/kindck-impl-type-params-2.rs +++ b/src/test/ui/kindck/kindck-impl-type-params-2.rs @@ -1,15 +1,15 @@ -#![feature(box_syntax)] - trait Foo { } + + impl Foo for T { } fn take_param(foo: &T) { } fn main() { - let x: Box<_> = box 3; + let x: Box<_> = Box::new(3); take_param(&x); //~^ ERROR the trait bound `Box<{integer}>: Foo` is not satisfied } diff --git a/src/test/ui/kindck/kindck-impl-type-params-2.stderr b/src/test/ui/kindck/kindck-impl-type-params-2.stderr index 60ad68cec4..89975e9683 100644 --- a/src/test/ui/kindck/kindck-impl-type-params-2.stderr +++ b/src/test/ui/kindck/kindck-impl-type-params-2.stderr @@ -2,7 +2,9 @@ error[E0277]: the trait bound `Box<{integer}>: Foo` is not satisfied --> $DIR/kindck-impl-type-params-2.rs:13:16 | LL | take_param(&x); - | ^^ the trait `Copy` is not implemented for `Box<{integer}>` + | ---------- ^^ the trait `Copy` is not implemented for `Box<{integer}>` + | | + | required by a bound introduced by this call | note: required because of the requirements on the impl of `Foo` for `Box<{integer}>` --> $DIR/kindck-impl-type-params-2.rs:6:14 diff --git a/src/test/ui/kindck/kindck-impl-type-params.rs b/src/test/ui/kindck/kindck-impl-type-params.rs index 4d4d191b6a..5622d65cb1 100644 --- a/src/test/ui/kindck/kindck-impl-type-params.rs +++ b/src/test/ui/kindck/kindck-impl-type-params.rs @@ -1,7 +1,7 @@ // Issue #14061: tests the interaction between generic implementation // parameter bounds and trait objects. -#![feature(box_syntax)] + use std::marker; @@ -34,7 +34,7 @@ fn foo<'a>() { } fn foo2<'a>() { - let t: Box> = box S(marker::PhantomData); + let t: Box> = Box::new(S(marker::PhantomData)); let a = t as Box>; //~^ ERROR : Copy` is not satisfied } @@ -42,7 +42,7 @@ fn foo2<'a>() { fn foo3<'a>() { struct Foo; // does not impl Copy - let t: Box> = box S(marker::PhantomData); + let t: Box> = Box::new(S(marker::PhantomData)); let a: Box> = t; //~^ ERROR : Copy` is not satisfied } diff --git a/src/test/ui/kindck/kindck-inherited-copy-bound.curr.stderr b/src/test/ui/kindck/kindck-inherited-copy-bound.curr.stderr index ac43c549d8..016cd393c8 100644 --- a/src/test/ui/kindck/kindck-inherited-copy-bound.curr.stderr +++ b/src/test/ui/kindck/kindck-inherited-copy-bound.curr.stderr @@ -2,7 +2,9 @@ error[E0277]: the trait bound `Box<{integer}>: Foo` is not satisfied --> $DIR/kindck-inherited-copy-bound.rs:21:16 | LL | take_param(&x); - | ^^ the trait `Copy` is not implemented for `Box<{integer}>` + | ---------- ^^ the trait `Copy` is not implemented for `Box<{integer}>` + | | + | required by a bound introduced by this call | note: required because of the requirements on the impl of `Foo` for `Box<{integer}>` --> $DIR/kindck-inherited-copy-bound.rs:14:14 diff --git a/src/test/ui/kindck/kindck-inherited-copy-bound.object_safe_for_dispatch.stderr b/src/test/ui/kindck/kindck-inherited-copy-bound.object_safe_for_dispatch.stderr index a486ab17c8..eaf34dff41 100644 --- a/src/test/ui/kindck/kindck-inherited-copy-bound.object_safe_for_dispatch.stderr +++ b/src/test/ui/kindck/kindck-inherited-copy-bound.object_safe_for_dispatch.stderr @@ -2,7 +2,9 @@ error[E0277]: the trait bound `Box<{integer}>: Foo` is not satisfied --> $DIR/kindck-inherited-copy-bound.rs:21:16 | LL | take_param(&x); - | ^^ the trait `Copy` is not implemented for `Box<{integer}>` + | ---------- ^^ the trait `Copy` is not implemented for `Box<{integer}>` + | | + | required by a bound introduced by this call | note: required because of the requirements on the impl of `Foo` for `Box<{integer}>` --> $DIR/kindck-inherited-copy-bound.rs:14:14 diff --git a/src/test/ui/kindck/kindck-inherited-copy-bound.rs b/src/test/ui/kindck/kindck-inherited-copy-bound.rs index aad693e5b1..87d47556bd 100644 --- a/src/test/ui/kindck/kindck-inherited-copy-bound.rs +++ b/src/test/ui/kindck/kindck-inherited-copy-bound.rs @@ -3,7 +3,7 @@ // revisions: curr object_safe_for_dispatch #![cfg_attr(object_safe_for_dispatch, feature(object_safe_for_dispatch))] -#![feature(box_syntax)] + use std::any::Any; @@ -17,13 +17,13 @@ impl Foo for T { fn take_param(foo: &T) { } fn a() { - let x: Box<_> = box 3; + let x: Box<_> = Box::new(3); take_param(&x); //[curr]~ ERROR E0277 //[object_safe_for_dispatch]~^ ERROR E0277 } fn b() { - let x: Box<_> = box 3; + let x: Box<_> = Box::new(3); let y = &x; let z = &x as &dyn Foo; //[curr]~^ ERROR E0038 diff --git a/src/test/ui/lang-items/fn-fn_mut-call-ill-formed.rs b/src/test/ui/lang-items/fn-fn_mut-call-ill-formed.rs new file mode 100644 index 0000000000..52bd8136d9 --- /dev/null +++ b/src/test/ui/lang-items/fn-fn_mut-call-ill-formed.rs @@ -0,0 +1,27 @@ +// Make sure that an error is reported if the `call` function of the +// `fn`/`fn_mut` lang item is grossly ill-formed. + +#![feature(lang_items)] +#![feature(no_core)] +#![no_core] + +#[lang = "fn"] +trait MyFn { + const call: i32 = 42; + //~^ ERROR: `call` trait item in `fn` lang item must be a function +} + +#[lang = "fn_mut"] +trait MyFnMut { + fn call(i: i32, j: i32) -> i32 { i + j } + //~^ ERROR: first argument of `call` in `fn_mut` lang item must be a reference +} + +fn main() { + let a = || 42; + a(); + + let mut i = 0; + let mut b = || { i += 1; }; + b(); +} diff --git a/src/test/ui/lang-items/fn-fn_mut-call-ill-formed.stderr b/src/test/ui/lang-items/fn-fn_mut-call-ill-formed.stderr new file mode 100644 index 0000000000..82bdae270c --- /dev/null +++ b/src/test/ui/lang-items/fn-fn_mut-call-ill-formed.stderr @@ -0,0 +1,14 @@ +error: `call` trait item in `fn` lang item must be a function + --> $DIR/fn-fn_mut-call-ill-formed.rs:10:5 + | +LL | const call: i32 = 42; + | ^^^^^^^^^^^^^^^^^^^^^ + +error: first argument of `call` in `fn_mut` lang item must be a reference + --> $DIR/fn-fn_mut-call-ill-formed.rs:16:16 + | +LL | fn call(i: i32, j: i32) -> i32 { i + j } + | ^^^ + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/lang-items/issue-83471.rs b/src/test/ui/lang-items/issue-83471.rs new file mode 100644 index 0000000000..b32aa03415 --- /dev/null +++ b/src/test/ui/lang-items/issue-83471.rs @@ -0,0 +1,23 @@ +// Regression test for the ICE reported in issue #83471. + +#![crate_type="lib"] +#![feature(no_core)] +#![no_core] + +#[lang = "sized"] +//~^ ERROR: language items are subject to change [E0658] +trait Sized {} + +#[lang = "fn"] +//~^ ERROR: language items are subject to change [E0658] +//~| ERROR: `fn` language item must be applied to a trait with 1 generic argument +trait Fn { + fn call(export_name); + //~^ ERROR: expected type + //~| WARNING: anonymous parameters are deprecated + //~| WARNING: this is accepted in the current edition +} +fn call_through_fn_trait() { + a() + //~^ ERROR: cannot find function +} diff --git a/src/test/ui/lang-items/issue-83471.stderr b/src/test/ui/lang-items/issue-83471.stderr new file mode 100644 index 0000000000..6d796fe7f5 --- /dev/null +++ b/src/test/ui/lang-items/issue-83471.stderr @@ -0,0 +1,51 @@ +error[E0573]: expected type, found built-in attribute `export_name` + --> $DIR/issue-83471.rs:15:13 + | +LL | fn call(export_name); + | ^^^^^^^^^^^ not a type + +error[E0425]: cannot find function `a` in this scope + --> $DIR/issue-83471.rs:21:5 + | +LL | a() + | ^ not found in this scope + +error[E0658]: language items are subject to change + --> $DIR/issue-83471.rs:7:1 + | +LL | #[lang = "sized"] + | ^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(lang_items)]` to the crate attributes to enable + +error[E0658]: language items are subject to change + --> $DIR/issue-83471.rs:11:1 + | +LL | #[lang = "fn"] + | ^^^^^^^^^^^^^^ + | + = help: add `#![feature(lang_items)]` to the crate attributes to enable + +warning: anonymous parameters are deprecated and will be removed in the next edition + --> $DIR/issue-83471.rs:15:13 + | +LL | fn call(export_name); + | ^^^^^^^^^^^ help: try naming the parameter or explicitly ignoring it: `_: export_name` + | + = note: `#[warn(anonymous_parameters)]` on by default + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! + = note: for more information, see issue #41686 + +error[E0718]: `fn` language item must be applied to a trait with 1 generic argument + --> $DIR/issue-83471.rs:11:1 + | +LL | #[lang = "fn"] + | ^^^^^^^^^^^^^^ +... +LL | trait Fn { + | - this trait has 0 generic arguments + +error: aborting due to 5 previous errors; 1 warning emitted + +Some errors have detailed explanations: E0425, E0573, E0658, E0718. +For more information about an error, try `rustc --explain E0425`. diff --git a/src/test/ui/lang-items/lang-item-generic-requirements.rs b/src/test/ui/lang-items/lang-item-generic-requirements.rs index d785749afc..c0b958f2bf 100644 --- a/src/test/ui/lang-items/lang-item-generic-requirements.rs +++ b/src/test/ui/lang-items/lang-item-generic-requirements.rs @@ -1,9 +1,8 @@ -// Checks whether declaring a lang item with the wrong number -// of generic arguments crashes the compiler (issue #83893, #87573, and part of #9307). +// Checks that declaring a lang item with the wrong number +// of generic arguments errors rather than crashing (issue #83893, #87573, part of #9307, #79559). #![feature(lang_items, no_core)] #![no_core] -#![crate_type = "lib"] #[lang = "sized"] trait MySized {} @@ -26,6 +25,14 @@ struct MyPhantomData; //~^ ERROR parameter `T` is never used //~| ERROR parameter `U` is never used +// When the `start` lang item is missing generics very odd things can happen, especially when +// it comes to cross-crate monomorphization +#[lang = "start"] +//~^ ERROR `start` language item must be applied to a function with 1 generic argument [E0718] +fn start(_: *const u8, _: isize, _: *const *const u8) -> isize { + 0 +} + fn ice() { // Use add let r = 5; @@ -42,3 +49,6 @@ fn ice() { // Use phantomdata let _ = MyPhantomData::<(), i32>; } + +// use `start` +fn main() {} diff --git a/src/test/ui/lang-items/lang-item-generic-requirements.stderr b/src/test/ui/lang-items/lang-item-generic-requirements.stderr index add5938811..df5a77850f 100644 --- a/src/test/ui/lang-items/lang-item-generic-requirements.stderr +++ b/src/test/ui/lang-items/lang-item-generic-requirements.stderr @@ -1,5 +1,5 @@ error[E0718]: `add` language item must be applied to a trait with 1 generic argument - --> $DIR/lang-item-generic-requirements.rs:11:1 + --> $DIR/lang-item-generic-requirements.rs:10:1 | LL | #[lang = "add"] | ^^^^^^^^^^^^^^^ @@ -7,7 +7,7 @@ LL | trait MyAdd<'a, T> {} | ------- this trait has 2 generic arguments error[E0718]: `drop_in_place` language item must be applied to a function with at least 1 generic argument - --> $DIR/lang-item-generic-requirements.rs:15:1 + --> $DIR/lang-item-generic-requirements.rs:14:1 | LL | #[lang = "drop_in_place"] | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -16,7 +16,7 @@ LL | fn my_ptr_drop() {} | - this function has 0 generic arguments error[E0718]: `index` language item must be applied to a trait with 1 generic argument - --> $DIR/lang-item-generic-requirements.rs:19:1 + --> $DIR/lang-item-generic-requirements.rs:18:1 | LL | #[lang = "index"] | ^^^^^^^^^^^^^^^^^ @@ -24,7 +24,7 @@ LL | trait MyIndex<'a, T> {} | ------- this trait has 2 generic arguments error[E0718]: `phantom_data` language item must be applied to a struct with 1 generic argument - --> $DIR/lang-item-generic-requirements.rs:23:1 + --> $DIR/lang-item-generic-requirements.rs:22:1 | LL | #[lang = "phantom_data"] | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -32,8 +32,17 @@ LL | LL | struct MyPhantomData; | ------ this struct has 2 generic arguments +error[E0718]: `start` language item must be applied to a function with 1 generic argument + --> $DIR/lang-item-generic-requirements.rs:30:1 + | +LL | #[lang = "start"] + | ^^^^^^^^^^^^^^^^^ +LL | +LL | fn start(_: *const u8, _: isize, _: *const *const u8) -> isize { + | - this function has 0 generic arguments + error[E0392]: parameter `T` is never used - --> $DIR/lang-item-generic-requirements.rs:25:22 + --> $DIR/lang-item-generic-requirements.rs:24:22 | LL | struct MyPhantomData; | ^ unused parameter @@ -42,7 +51,7 @@ LL | struct MyPhantomData; = help: if you intended `T` to be a const parameter, use `const T: usize` instead error[E0392]: parameter `U` is never used - --> $DIR/lang-item-generic-requirements.rs:25:25 + --> $DIR/lang-item-generic-requirements.rs:24:25 | LL | struct MyPhantomData; | ^ unused parameter @@ -50,7 +59,7 @@ LL | struct MyPhantomData; = help: consider removing `U` or referring to it in a field = help: if you intended `U` to be a const parameter, use `const U: usize` instead -error: aborting due to 6 previous errors +error: aborting due to 7 previous errors Some errors have detailed explanations: E0392, E0718. For more information about an error, try `rustc --explain E0392`. diff --git a/src/test/ui/last-use-is-capture.rs b/src/test/ui/last-use-is-capture.rs index af23087779..1055fe7995 100644 --- a/src/test/ui/last-use-is-capture.rs +++ b/src/test/ui/last-use-is-capture.rs @@ -3,13 +3,11 @@ #![allow(dead_code)] // Make sure #1399 stays fixed -#![feature(box_syntax)] - struct A { a: Box } pub fn main() { fn invoke(f: F) where F: FnOnce() { f(); } - let k: Box<_> = box 22; + let k: Box<_> = 22.into(); let _u = A {a: k.clone()}; invoke(|| println!("{}", k.clone()) ) } diff --git a/src/test/ui/leak-unique-as-tydesc.rs b/src/test/ui/leak-unique-as-tydesc.rs index 752081b78f..322f726156 100644 --- a/src/test/ui/leak-unique-as-tydesc.rs +++ b/src/test/ui/leak-unique-as-tydesc.rs @@ -1,8 +1,9 @@ // run-pass // pretty-expanded FIXME #23616 -#![feature(box_syntax)] - fn leaky(_t: T) { } -pub fn main() { let x = box 10; leaky::>(x); } +pub fn main() { + let x = Box::new(10); + leaky::>(x); +} diff --git a/src/test/ui/lifetimes/borrowck-let-suggestion.stderr b/src/test/ui/lifetimes/borrowck-let-suggestion.stderr index 4a605cfb86..bbf04c9843 100644 --- a/src/test/ui/lifetimes/borrowck-let-suggestion.stderr +++ b/src/test/ui/lifetimes/borrowck-let-suggestion.stderr @@ -7,7 +7,7 @@ LL | let mut x = vec![1].iter(); | creates a temporary which is freed while still in use LL | LL | x.use_mut(); - | - borrow later used here + | ----------- borrow later used here | = note: consider using a `let` binding to create a longer lived value = note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/lifetimes/issue-77175.rs b/src/test/ui/lifetimes/issue-77175.rs new file mode 100644 index 0000000000..2282752b6c --- /dev/null +++ b/src/test/ui/lifetimes/issue-77175.rs @@ -0,0 +1,19 @@ +#[deny(single_use_lifetimes)] +// edition:2018 +// check-pass + +// Prior to the fix, the compiler complained that the 'a lifetime was only used +// once. This was obviously wrong since the lifetime is used twice: For the s3 +// parameter and the return type. The issue was caused by the compiler +// desugaring the async function into a generator that uses only a single +// lifetime, which then the validator complained about becauase of the +// single_use_lifetimes constraints. +async fn bar<'a>(s1: String, s2: &'_ str, s3: &'a str) -> &'a str { + s3 +} + +fn foo<'a>(s1: String, s2: &'_ str, s3: &'a str) -> &'a str { + s3 +} + +fn main() {} diff --git a/src/test/ui/lifetimes/issue-79187-2.nll.stderr b/src/test/ui/lifetimes/issue-79187-2.nll.stderr index 907b43d676..04d9b64d64 100644 --- a/src/test/ui/lifetimes/issue-79187-2.nll.stderr +++ b/src/test/ui/lifetimes/issue-79187-2.nll.stderr @@ -38,6 +38,11 @@ note: this closure does not fulfill the lifetime requirements | LL | take_foo(|a| a); | ^^^^^ +note: the lifetime requirement is introduced here + --> $DIR/issue-79187-2.rs:5:21 + | +LL | fn take_foo(_: impl Foo) {} + | ^^^ error[E0308]: mismatched types --> $DIR/issue-79187-2.rs:9:5 @@ -47,6 +52,11 @@ LL | take_foo(|a: &i32| a); | = note: expected reference `&i32` found reference `&i32` +note: the lifetime requirement is introduced here + --> $DIR/issue-79187-2.rs:5:21 + | +LL | fn take_foo(_: impl Foo) {} + | ^^^ error[E0308]: mismatched types --> $DIR/issue-79187-2.rs:10:5 @@ -56,6 +66,11 @@ LL | take_foo(|a: &i32| -> &i32 { a }); | = note: expected reference `&i32` found reference `&i32` +note: the lifetime requirement is introduced here + --> $DIR/issue-79187-2.rs:5:21 + | +LL | fn take_foo(_: impl Foo) {} + | ^^^ error: aborting due to 6 previous errors diff --git a/src/test/ui/lifetimes/issue-79187-2.stderr b/src/test/ui/lifetimes/issue-79187-2.stderr index a156c74fb3..2aca8faff9 100644 --- a/src/test/ui/lifetimes/issue-79187-2.stderr +++ b/src/test/ui/lifetimes/issue-79187-2.stderr @@ -25,7 +25,7 @@ LL | take_foo(|a: &i32| a); | = note: expected reference `&i32` found reference `&i32` -note: the anonymous lifetime #1 defined on the body at 9:14 doesn't meet the lifetime requirements +note: the anonymous lifetime #1 defined here doesn't meet the lifetime requirements --> $DIR/issue-79187-2.rs:9:14 | LL | take_foo(|a: &i32| a); @@ -44,7 +44,7 @@ LL | take_foo(|a: &i32| -> &i32 { a }); | = note: expected reference `&i32` found reference `&i32` -note: the anonymous lifetime #1 defined on the body at 10:14 doesn't meet the lifetime requirements +note: the anonymous lifetime #1 defined here doesn't meet the lifetime requirements --> $DIR/issue-79187-2.rs:10:14 | LL | take_foo(|a: &i32| -> &i32 { a }); diff --git a/src/test/ui/lifetimes/issue-79187.nll.stderr b/src/test/ui/lifetimes/issue-79187.nll.stderr index 725b132e83..3a993e88d8 100644 --- a/src/test/ui/lifetimes/issue-79187.nll.stderr +++ b/src/test/ui/lifetimes/issue-79187.nll.stderr @@ -11,6 +11,11 @@ note: this closure does not fulfill the lifetime requirements | LL | let f = |_| (); | ^^^^^^ +note: the lifetime requirement is introduced here + --> $DIR/issue-79187.rs:1:18 + | +LL | fn thing(x: impl FnOnce(&u32)) {} + | ^^^^^^^^^^^^ error: implementation of `FnOnce` is not general enough --> $DIR/issue-79187.rs:5:5 diff --git a/src/test/ui/lifetimes/lifetime-bound-will-change-warning.nll.stderr b/src/test/ui/lifetimes/lifetime-bound-will-change-warning.nll.stderr index 57dab46df6..6f3f84096e 100644 --- a/src/test/ui/lifetimes/lifetime-bound-will-change-warning.nll.stderr +++ b/src/test/ui/lifetimes/lifetime-bound-will-change-warning.nll.stderr @@ -2,23 +2,29 @@ error[E0521]: borrowed data escapes outside of function --> $DIR/lifetime-bound-will-change-warning.rs:34:5 | LL | fn test2<'a>(x: &'a Box) { - | - `x` is a reference that is only valid in the function body + | -- - `x` is a reference that is only valid in the function body + | | + | lifetime `'a` defined here LL | // but ref_obj will not, so warn. LL | ref_obj(x) - | ^^^^^^^^^^ `x` escapes the function body here - | - = help: consider replacing `'a` with `'static` + | ^^^^^^^^^^ + | | + | `x` escapes the function body here + | argument requires that `'a` must outlive `'static` error[E0521]: borrowed data escapes outside of function --> $DIR/lifetime-bound-will-change-warning.rs:39:5 | LL | fn test2cc<'a>(x: &'a Box) { - | - `x` is a reference that is only valid in the function body + | -- - `x` is a reference that is only valid in the function body + | | + | lifetime `'a` defined here LL | // same as test2, but cross crate LL | lib::ref_obj(x) - | ^^^^^^^^^^^^^^^ `x` escapes the function body here - | - = help: consider replacing `'a` with `'static` + | ^^^^^^^^^^^^^^^ + | | + | `x` escapes the function body here + | argument requires that `'a` must outlive `'static` error: aborting due to 2 previous errors diff --git a/src/test/ui/lifetimes/lifetime-bound-will-change-warning.stderr b/src/test/ui/lifetimes/lifetime-bound-will-change-warning.stderr index 91cdc0205d..bb691fc072 100644 --- a/src/test/ui/lifetimes/lifetime-bound-will-change-warning.stderr +++ b/src/test/ui/lifetimes/lifetime-bound-will-change-warning.stderr @@ -6,7 +6,7 @@ LL | ref_obj(x) | = note: expected reference `&Box<(dyn Fn() + 'static)>` found reference `&Box<(dyn Fn() + 'a)>` -note: the lifetime `'a` as defined on the function body at 32:10... +note: the lifetime `'a` as defined here... --> $DIR/lifetime-bound-will-change-warning.rs:32:10 | LL | fn test2<'a>(x: &'a Box) { @@ -21,7 +21,7 @@ LL | lib::ref_obj(x) | = note: expected reference `&Box<(dyn Fn() + 'static)>` found reference `&Box<(dyn Fn() + 'a)>` -note: the lifetime `'a` as defined on the function body at 37:12... +note: the lifetime `'a` as defined here... --> $DIR/lifetime-bound-will-change-warning.rs:37:12 | LL | fn test2cc<'a>(x: &'a Box) { diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-fn-items.nll.stderr b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-fn-items.nll.stderr index 33be98c649..825c45b243 100644 --- a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-fn-items.nll.stderr +++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-fn-items.nll.stderr @@ -1,11 +1,3 @@ -error[E0596]: cannot borrow `y` as mutable, as it is not declared as mutable - --> $DIR/ex3-both-anon-regions-using-fn-items.rs:2:3 - | -LL | fn foo(x:fn(&u8, &u8), y: Vec<&u8>, z: &u8) { - | - help: consider changing this to be mutable: `mut y` -LL | y.push(z); - | ^ cannot borrow as mutable - error: lifetime may not live long enough --> $DIR/ex3-both-anon-regions-using-fn-items.rs:2:3 | @@ -16,6 +8,14 @@ LL | fn foo(x:fn(&u8, &u8), y: Vec<&u8>, z: &u8) { LL | y.push(z); | ^^^^^^^^^ argument requires that `'1` must outlive `'2` +error[E0596]: cannot borrow `y` as mutable, as it is not declared as mutable + --> $DIR/ex3-both-anon-regions-using-fn-items.rs:2:3 + | +LL | fn foo(x:fn(&u8, &u8), y: Vec<&u8>, z: &u8) { + | - help: consider changing this to be mutable: `mut y` +LL | y.push(z); + | ^^^^^^^^^ cannot borrow as mutable + error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0596`. diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-trait-objects.nll.stderr b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-trait-objects.nll.stderr index 3c95be95db..78a828dde8 100644 --- a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-trait-objects.nll.stderr +++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-trait-objects.nll.stderr @@ -1,11 +1,3 @@ -error[E0596]: cannot borrow `y` as mutable, as it is not declared as mutable - --> $DIR/ex3-both-anon-regions-using-trait-objects.rs:2:3 - | -LL | fn foo(x:Box , y: Vec<&u8>, z: &u8) { - | - help: consider changing this to be mutable: `mut y` -LL | y.push(z); - | ^ cannot borrow as mutable - error: lifetime may not live long enough --> $DIR/ex3-both-anon-regions-using-trait-objects.rs:2:3 | @@ -16,6 +8,14 @@ LL | fn foo(x:Box , y: Vec<&u8>, z: &u8) { LL | y.push(z); | ^^^^^^^^^ argument requires that `'1` must outlive `'2` +error[E0596]: cannot borrow `y` as mutable, as it is not declared as mutable + --> $DIR/ex3-both-anon-regions-using-trait-objects.rs:2:3 + | +LL | fn foo(x:Box , y: Vec<&u8>, z: &u8) { + | - help: consider changing this to be mutable: `mut y` +LL | y.push(z); + | ^^^^^^^^^ cannot borrow as mutable + error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0596`. diff --git a/src/test/ui/lifetimes/lifetime-errors/issue_74400.nll.stderr b/src/test/ui/lifetimes/lifetime-errors/issue_74400.nll.stderr new file mode 100644 index 0000000000..5509226cb1 --- /dev/null +++ b/src/test/ui/lifetimes/lifetime-errors/issue_74400.nll.stderr @@ -0,0 +1,35 @@ +error[E0310]: the parameter type `T` may not live long enough + --> $DIR/issue_74400.rs:12:5 + | +LL | f(data, identity) + | ^^^^^^^^^^^^^^^^^ + | + = help: consider adding an explicit lifetime bound `T: 'static`... + +error[E0308]: mismatched types + --> $DIR/issue_74400.rs:12:5 + | +LL | f(data, identity) + | ^^^^^^^^^^^^^^^^^ one type is more general than the other + | + = note: expected type `for<'r> Fn<(&'r T,)>` + found type `Fn<(&T,)>` +note: the lifetime requirement is introduced here + --> $DIR/issue_74400.rs:8:34 + | +LL | fn f(data: &[T], key: impl Fn(&T) -> S) { + | ^^^^^^^^^^^ + +error: implementation of `FnOnce` is not general enough + --> $DIR/issue_74400.rs:12:5 + | +LL | f(data, identity) + | ^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough + | + = note: `fn(&'2 T) -> &'2 T {identity::<&'2 T>}` must implement `FnOnce<(&'1 T,)>`, for any lifetime `'1`... + = note: ...but it actually implements `FnOnce<(&'2 T,)>`, for some specific lifetime `'2` + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0308, E0310. +For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/lifetimes/lifetime-errors/issue_74400.rs b/src/test/ui/lifetimes/lifetime-errors/issue_74400.rs new file mode 100644 index 0000000000..f83384524f --- /dev/null +++ b/src/test/ui/lifetimes/lifetime-errors/issue_74400.rs @@ -0,0 +1,13 @@ +//! Regression test for #74400: Type mismatch in function arguments E0631, E0271 are falsely +//! recognized as E0308 mismatched types. + +use std::convert::identity; + +fn main() {} + +fn f(data: &[T], key: impl Fn(&T) -> S) { +} + +fn g(data: &[T]) { + f(data, identity) //~ ERROR implementation of `FnOnce` is not general +} diff --git a/src/test/ui/lifetimes/lifetime-errors/issue_74400.stderr b/src/test/ui/lifetimes/lifetime-errors/issue_74400.stderr new file mode 100644 index 0000000000..d972861a2b --- /dev/null +++ b/src/test/ui/lifetimes/lifetime-errors/issue_74400.stderr @@ -0,0 +1,11 @@ +error: implementation of `FnOnce` is not general enough + --> $DIR/issue_74400.rs:12:5 + | +LL | f(data, identity) + | ^ implementation of `FnOnce` is not general enough + | + = note: `fn(&'2 T) -> &'2 T {identity::<&'2 T>}` must implement `FnOnce<(&'1 T,)>`, for any lifetime `'1`... + = note: ...but it actually implements `FnOnce<(&'2 T,)>`, for some specific lifetime `'2` + +error: aborting due to previous error + diff --git a/src/test/ui/lifetimes/undeclared-lifetime-used-in-debug-macro-issue-70152.stderr b/src/test/ui/lifetimes/undeclared-lifetime-used-in-debug-macro-issue-70152.stderr index 8c87f6da8d..e18d725fae 100644 --- a/src/test/ui/lifetimes/undeclared-lifetime-used-in-debug-macro-issue-70152.stderr +++ b/src/test/ui/lifetimes/undeclared-lifetime-used-in-debug-macro-issue-70152.stderr @@ -8,6 +8,17 @@ LL | a: &'b str, | = help: if you want to experiment with in-band lifetime bindings, add `#![feature(in_band_lifetimes)]` to the crate attributes +error[E0261]: use of undeclared lifetime name `'b` + --> $DIR/undeclared-lifetime-used-in-debug-macro-issue-70152.rs:3:9 + | +LL | #[derive(Eq, PartialEq)] + | -- lifetime `'b` is missing in item created through this procedural macro +LL | struct Test { +LL | a: &'b str, + | ^^ undeclared lifetime + | + = help: if you want to experiment with in-band lifetime bindings, add `#![feature(in_band_lifetimes)]` to the crate attributes + error[E0261]: use of undeclared lifetime name `'b` --> $DIR/undeclared-lifetime-used-in-debug-macro-issue-70152.rs:13:13 | @@ -24,17 +35,6 @@ help: consider introducing lifetime `'b` here LL | fn foo<'b>(&'b self) {} | ++++ -error[E0261]: use of undeclared lifetime name `'b` - --> $DIR/undeclared-lifetime-used-in-debug-macro-issue-70152.rs:3:9 - | -LL | #[derive(Eq, PartialEq)] - | -- lifetime `'b` is missing in item created through this procedural macro -LL | struct Test { -LL | a: &'b str, - | ^^ undeclared lifetime - | - = help: if you want to experiment with in-band lifetime bindings, add `#![feature(in_band_lifetimes)]` to the crate attributes - error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0261`. diff --git a/src/test/ui/enable-unstable-lib-feature.rs b/src/test/ui/lint/enable-unstable-lib-feature.rs similarity index 100% rename from src/test/ui/enable-unstable-lib-feature.rs rename to src/test/ui/lint/enable-unstable-lib-feature.rs diff --git a/src/test/ui/enable-unstable-lib-feature.stderr b/src/test/ui/lint/enable-unstable-lib-feature.stderr similarity index 100% rename from src/test/ui/enable-unstable-lib-feature.stderr rename to src/test/ui/lint/enable-unstable-lib-feature.stderr diff --git a/src/test/ui/issues/issue-57410.rs b/src/test/ui/lint/issue-57410.rs similarity index 100% rename from src/test/ui/issues/issue-57410.rs rename to src/test/ui/lint/issue-57410.rs diff --git a/src/test/ui/lint/issue-70819-dont-override-forbid-in-same-scope.rs b/src/test/ui/lint/issue-70819-dont-override-forbid-in-same-scope.rs index 05d7d924c8..c66037e9a7 100644 --- a/src/test/ui/lint/issue-70819-dont-override-forbid-in-same-scope.rs +++ b/src/test/ui/lint/issue-70819-dont-override-forbid-in-same-scope.rs @@ -21,8 +21,6 @@ fn forbid_first(num: i32) -> i32 { #![deny(unused)] //~^ ERROR: deny(unused) incompatible with previous forbid //~| WARNING being phased out - //~| ERROR: deny(unused) incompatible with previous forbid - //~| WARNING being phased out #![warn(unused)] #![allow(unused)] diff --git a/src/test/ui/lint/issue-70819-dont-override-forbid-in-same-scope.stderr b/src/test/ui/lint/issue-70819-dont-override-forbid-in-same-scope.stderr index 475410cecf..5093715dec 100644 --- a/src/test/ui/lint/issue-70819-dont-override-forbid-in-same-scope.stderr +++ b/src/test/ui/lint/issue-70819-dont-override-forbid-in-same-scope.stderr @@ -14,16 +14,5 @@ LL | #![forbid(forbidden_lint_groups)] = warning: this was previously accepted 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 -error: deny(unused) incompatible with previous forbid - --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:21:13 - | -LL | #![forbid(unused)] - | ------ `forbid` level set here -LL | #![deny(unused)] - | ^^^^^^ 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 - -error: aborting due to 2 previous errors +error: aborting due to previous error diff --git a/src/test/ui/lint/issue-79546-fuel-ice.rs b/src/test/ui/lint/issue-79546-fuel-ice.rs new file mode 100644 index 0000000000..0e9f54088b --- /dev/null +++ b/src/test/ui/lint/issue-79546-fuel-ice.rs @@ -0,0 +1,8 @@ +// Regression test for the ICE described in #79546. + +// compile-flags: --cap-lints=allow -Zfuel=issue79546=0 +// check-pass +#![crate_name="issue79546"] + +struct S; +fn main() {} diff --git a/src/test/ui/issues/issue-79744.rs b/src/test/ui/lint/issue-79744.rs similarity index 100% rename from src/test/ui/issues/issue-79744.rs rename to src/test/ui/lint/issue-79744.rs diff --git a/src/test/ui/issues/issue-79744.stderr b/src/test/ui/lint/issue-79744.stderr similarity index 100% rename from src/test/ui/issues/issue-79744.stderr rename to src/test/ui/lint/issue-79744.stderr diff --git a/src/test/ui/lint/issue-87308.rs b/src/test/ui/lint/issue-87308.rs new file mode 100644 index 0000000000..48fbb2a013 --- /dev/null +++ b/src/test/ui/lint/issue-87308.rs @@ -0,0 +1,12 @@ +// Regression test for issue #87308. + +// compile-flags: -Zunpretty=everybody_loops +// check-pass + +macro_rules! foo { + () => { break 'x; } +} + +pub fn main() { + 'x: loop { foo!() } +} diff --git a/src/test/ui/lint/issue-87308.stdout b/src/test/ui/lint/issue-87308.stdout new file mode 100644 index 0000000000..68a076c93b --- /dev/null +++ b/src/test/ui/lint/issue-87308.stdout @@ -0,0 +1,14 @@ +#![feature(prelude_import)] +#![no_std] +#[prelude_import] +use ::std::prelude::rust_2015::*; +#[macro_use] +extern crate std; +// Regression test for issue #87308. + +// compile-flags: -Zunpretty=everybody_loops +// check-pass + +macro_rules! foo { () => { break 'x ; } } + +pub fn main() { loop { } } diff --git a/src/test/ui/lint/issue-89469.rs b/src/test/ui/lint/issue-89469.rs new file mode 100644 index 0000000000..3a6ab45284 --- /dev/null +++ b/src/test/ui/lint/issue-89469.rs @@ -0,0 +1,20 @@ +// Regression test for #89469, where an extra non_snake_case warning was +// reported for a shorthand field binding. + +// check-pass +#![deny(non_snake_case)] + +#[allow(non_snake_case)] +struct Entry { + A: u16, + a: u16 +} + +fn foo() -> Entry {todo!()} + +pub fn f() { + let Entry { A, a } = foo(); + let _ = (A, a); +} + +fn main() {} diff --git a/src/test/ui/lint/issue-90614-accept-allow-text-direction-codepoint-in-comment-lint.rs b/src/test/ui/lint/issue-90614-accept-allow-text-direction-codepoint-in-comment-lint.rs new file mode 100644 index 0000000000..425e2703c9 --- /dev/null +++ b/src/test/ui/lint/issue-90614-accept-allow-text-direction-codepoint-in-comment-lint.rs @@ -0,0 +1,9 @@ +// check-pass +// Allowing the code lint should work without warning and +// the text flow char in the comment should be ignored. + +#![allow(text_direction_codepoint_in_comment)] + +fn main() { + // U+2066 LEFT-TO-RIGHT ISOLATE follows:⁦⁦ +} diff --git a/src/test/ui/lint/known-tool-in-submodule/root.rs b/src/test/ui/lint/known-tool-in-submodule/root.rs new file mode 100644 index 0000000000..80806dcbd2 --- /dev/null +++ b/src/test/ui/lint/known-tool-in-submodule/root.rs @@ -0,0 +1,10 @@ +// check-pass + +#![feature(register_tool)] +#![register_tool(tool)] + +mod submodule; + +fn main() { + submodule::foo(); +} diff --git a/src/test/ui/lint/known-tool-in-submodule/submodule.rs b/src/test/ui/lint/known-tool-in-submodule/submodule.rs new file mode 100644 index 0000000000..bb25e10056 --- /dev/null +++ b/src/test/ui/lint/known-tool-in-submodule/submodule.rs @@ -0,0 +1,4 @@ +// ignore-test: not a test + +#[allow(tool::lint)] +pub fn foo() {} diff --git a/src/test/ui/lint/lint-ctypes-fn.rs b/src/test/ui/lint/lint-ctypes-fn.rs index c18cb88103..d3b36a9d59 100644 --- a/src/test/ui/lint/lint-ctypes-fn.rs +++ b/src/test/ui/lint/lint-ctypes-fn.rs @@ -66,6 +66,10 @@ pub extern "C" fn ptr_type1(size: *const Foo) { } pub extern "C" fn ptr_type2(size: *const Foo) { } +pub extern "C" fn ptr_unit(p: *const ()) { } + +pub extern "C" fn ptr_tuple(p: *const ((),)) { } + pub extern "C" fn slice_type(p: &[u32]) { } //~^ ERROR: uses type `[u32]` diff --git a/src/test/ui/lint/lint-ctypes-fn.stderr b/src/test/ui/lint/lint-ctypes-fn.stderr index d591d4ad29..740075ca7d 100644 --- a/src/test/ui/lint/lint-ctypes-fn.stderr +++ b/src/test/ui/lint/lint-ctypes-fn.stderr @@ -1,5 +1,5 @@ error: `extern` fn uses type `[u32]`, which is not FFI-safe - --> $DIR/lint-ctypes-fn.rs:69:33 + --> $DIR/lint-ctypes-fn.rs:73:33 | LL | pub extern "C" fn slice_type(p: &[u32]) { } | ^^^^^^ not FFI-safe @@ -13,7 +13,7 @@ LL | #![deny(improper_ctypes_definitions)] = note: slices have no C equivalent error: `extern` fn uses type `str`, which is not FFI-safe - --> $DIR/lint-ctypes-fn.rs:72:31 + --> $DIR/lint-ctypes-fn.rs:76:31 | LL | pub extern "C" fn str_type(p: &str) { } | ^^^^ not FFI-safe @@ -22,7 +22,7 @@ LL | pub extern "C" fn str_type(p: &str) { } = note: string slices have no C equivalent error: `extern` fn uses type `Box<[u8]>`, which is not FFI-safe - --> $DIR/lint-ctypes-fn.rs:79:34 + --> $DIR/lint-ctypes-fn.rs:83:34 | LL | pub extern "C" fn boxed_slice(p: Box<[u8]>) { } | ^^^^^^^^^ not FFI-safe @@ -30,7 +30,7 @@ LL | pub extern "C" fn boxed_slice(p: Box<[u8]>) { } = note: box cannot be represented as a single pointer error: `extern` fn uses type `Box`, which is not FFI-safe - --> $DIR/lint-ctypes-fn.rs:82:35 + --> $DIR/lint-ctypes-fn.rs:86:35 | LL | pub extern "C" fn boxed_string(p: Box) { } | ^^^^^^^^ not FFI-safe @@ -38,7 +38,7 @@ LL | pub extern "C" fn boxed_string(p: Box) { } = note: box cannot be represented as a single pointer error: `extern` fn uses type `Box`, which is not FFI-safe - --> $DIR/lint-ctypes-fn.rs:85:34 + --> $DIR/lint-ctypes-fn.rs:89:34 | LL | pub extern "C" fn boxed_trait(p: Box) { } | ^^^^^^^^^^^^^^ not FFI-safe @@ -46,7 +46,7 @@ LL | pub extern "C" fn boxed_trait(p: Box) { } = note: box cannot be represented as a single pointer error: `extern` fn uses type `char`, which is not FFI-safe - --> $DIR/lint-ctypes-fn.rs:88:32 + --> $DIR/lint-ctypes-fn.rs:92:32 | LL | pub extern "C" fn char_type(p: char) { } | ^^^^ not FFI-safe @@ -55,7 +55,7 @@ LL | pub extern "C" fn char_type(p: char) { } = note: the `char` type has no C equivalent error: `extern` fn uses type `i128`, which is not FFI-safe - --> $DIR/lint-ctypes-fn.rs:91:32 + --> $DIR/lint-ctypes-fn.rs:95:32 | LL | pub extern "C" fn i128_type(p: i128) { } | ^^^^ not FFI-safe @@ -63,7 +63,7 @@ LL | pub extern "C" fn i128_type(p: i128) { } = note: 128-bit integers don't currently have a known stable ABI error: `extern` fn uses type `u128`, which is not FFI-safe - --> $DIR/lint-ctypes-fn.rs:94:32 + --> $DIR/lint-ctypes-fn.rs:98:32 | LL | pub extern "C" fn u128_type(p: u128) { } | ^^^^ not FFI-safe @@ -71,7 +71,7 @@ LL | pub extern "C" fn u128_type(p: u128) { } = note: 128-bit integers don't currently have a known stable ABI error: `extern` fn uses type `(i32, i32)`, which is not FFI-safe - --> $DIR/lint-ctypes-fn.rs:97:33 + --> $DIR/lint-ctypes-fn.rs:101:33 | LL | pub extern "C" fn tuple_type(p: (i32, i32)) { } | ^^^^^^^^^^ not FFI-safe @@ -80,7 +80,7 @@ LL | pub extern "C" fn tuple_type(p: (i32, i32)) { } = note: tuples have unspecified layout error: `extern` fn uses type `(i32, i32)`, which is not FFI-safe - --> $DIR/lint-ctypes-fn.rs:100:34 + --> $DIR/lint-ctypes-fn.rs:104:34 | LL | pub extern "C" fn tuple_type2(p: I32Pair) { } | ^^^^^^^ not FFI-safe @@ -89,7 +89,7 @@ LL | pub extern "C" fn tuple_type2(p: I32Pair) { } = note: tuples have unspecified layout error: `extern` fn uses type `ZeroSize`, which is not FFI-safe - --> $DIR/lint-ctypes-fn.rs:103:32 + --> $DIR/lint-ctypes-fn.rs:107:32 | LL | pub extern "C" fn zero_size(p: ZeroSize) { } | ^^^^^^^^ not FFI-safe @@ -103,7 +103,7 @@ LL | pub struct ZeroSize; | ^^^^^^^^^^^^^^^^^^^^ error: `extern` fn uses type `ZeroSizeWithPhantomData`, which is not FFI-safe - --> $DIR/lint-ctypes-fn.rs:106:40 + --> $DIR/lint-ctypes-fn.rs:110:40 | LL | pub extern "C" fn zero_size_phantom(p: ZeroSizeWithPhantomData) { } | ^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -116,7 +116,7 @@ LL | pub struct ZeroSizeWithPhantomData(PhantomData); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `extern` fn uses type `PhantomData`, which is not FFI-safe - --> $DIR/lint-ctypes-fn.rs:109:51 + --> $DIR/lint-ctypes-fn.rs:113:51 | LL | pub extern "C" fn zero_size_phantom_toplevel() -> PhantomData { | ^^^^^^^^^^^^^^^^^ not FFI-safe @@ -124,7 +124,7 @@ LL | pub extern "C" fn zero_size_phantom_toplevel() -> PhantomData { = note: composed only of `PhantomData` error: `extern` fn uses type `fn()`, which is not FFI-safe - --> $DIR/lint-ctypes-fn.rs:114:30 + --> $DIR/lint-ctypes-fn.rs:118:30 | LL | pub extern "C" fn fn_type(p: RustFn) { } | ^^^^^^ not FFI-safe @@ -133,7 +133,7 @@ LL | pub extern "C" fn fn_type(p: RustFn) { } = note: this function pointer has Rust-specific calling convention error: `extern` fn uses type `fn()`, which is not FFI-safe - --> $DIR/lint-ctypes-fn.rs:117:31 + --> $DIR/lint-ctypes-fn.rs:121:31 | LL | pub extern "C" fn fn_type2(p: fn()) { } | ^^^^ not FFI-safe @@ -142,7 +142,7 @@ LL | pub extern "C" fn fn_type2(p: fn()) { } = note: this function pointer has Rust-specific calling convention error: `extern` fn uses type `i128`, which is not FFI-safe - --> $DIR/lint-ctypes-fn.rs:122:39 + --> $DIR/lint-ctypes-fn.rs:126:39 | LL | pub extern "C" fn transparent_i128(p: TransparentI128) { } | ^^^^^^^^^^^^^^^ not FFI-safe @@ -150,7 +150,7 @@ LL | pub extern "C" fn transparent_i128(p: TransparentI128) { } = note: 128-bit integers don't currently have a known stable ABI error: `extern` fn uses type `str`, which is not FFI-safe - --> $DIR/lint-ctypes-fn.rs:125:38 + --> $DIR/lint-ctypes-fn.rs:129:38 | LL | pub extern "C" fn transparent_str(p: TransparentStr) { } | ^^^^^^^^^^^^^^ not FFI-safe @@ -159,7 +159,7 @@ LL | pub extern "C" fn transparent_str(p: TransparentStr) { } = note: string slices have no C equivalent error: `extern` fn uses type `PhantomData`, which is not FFI-safe - --> $DIR/lint-ctypes-fn.rs:171:43 + --> $DIR/lint-ctypes-fn.rs:175:43 | LL | pub extern "C" fn unused_generic2() -> PhantomData { | ^^^^^^^^^^^^^^^^^ not FFI-safe @@ -167,7 +167,7 @@ LL | pub extern "C" fn unused_generic2() -> PhantomData { = note: composed only of `PhantomData` error: `extern` fn uses type `Vec`, which is not FFI-safe - --> $DIR/lint-ctypes-fn.rs:184:39 + --> $DIR/lint-ctypes-fn.rs:188:39 | LL | pub extern "C" fn used_generic4(x: Vec) { } | ^^^^^^ not FFI-safe @@ -176,7 +176,7 @@ LL | pub extern "C" fn used_generic4(x: Vec) { } = note: this struct has unspecified layout error: `extern` fn uses type `Vec`, which is not FFI-safe - --> $DIR/lint-ctypes-fn.rs:187:41 + --> $DIR/lint-ctypes-fn.rs:191:41 | LL | pub extern "C" fn used_generic5() -> Vec { | ^^^^^^ not FFI-safe diff --git a/src/test/ui/lint/lint-ctypes.rs b/src/test/ui/lint/lint-ctypes.rs index a291471f56..9165e14b7f 100644 --- a/src/test/ui/lint/lint-ctypes.rs +++ b/src/test/ui/lint/lint-ctypes.rs @@ -47,6 +47,8 @@ pub struct ZeroSizeWithPhantomData(::std::marker::PhantomData); extern "C" { pub fn ptr_type1(size: *const Foo); //~ ERROR: uses type `Foo` pub fn ptr_type2(size: *const Foo); //~ ERROR: uses type `Foo` + pub fn ptr_unit(p: *const ()); + pub fn ptr_tuple(p: *const ((),)); //~ ERROR: uses type `((),)` pub fn slice_type(p: &[u32]); //~ ERROR: uses type `[u32]` pub fn str_type(p: &str); //~ ERROR: uses type `str` pub fn box_type(p: Box); //~ ERROR uses type `Box` diff --git a/src/test/ui/lint/lint-ctypes.stderr b/src/test/ui/lint/lint-ctypes.stderr index 7f21e412c3..342b6bfc6f 100644 --- a/src/test/ui/lint/lint-ctypes.stderr +++ b/src/test/ui/lint/lint-ctypes.stderr @@ -31,8 +31,17 @@ note: the type is defined here LL | pub struct Foo; | ^^^^^^^^^^^^^^^ +error: `extern` block uses type `((),)`, which is not FFI-safe + --> $DIR/lint-ctypes.rs:51:25 + | +LL | pub fn ptr_tuple(p: *const ((),)); + | ^^^^^^^^^^^^ not FFI-safe + | + = help: consider using a struct instead + = note: tuples have unspecified layout + error: `extern` block uses type `[u32]`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:50:26 + --> $DIR/lint-ctypes.rs:52:26 | LL | pub fn slice_type(p: &[u32]); | ^^^^^^ not FFI-safe @@ -41,7 +50,7 @@ LL | pub fn slice_type(p: &[u32]); = note: slices have no C equivalent error: `extern` block uses type `str`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:51:24 + --> $DIR/lint-ctypes.rs:53:24 | LL | pub fn str_type(p: &str); | ^^^^ not FFI-safe @@ -50,7 +59,7 @@ LL | pub fn str_type(p: &str); = note: string slices have no C equivalent error: `extern` block uses type `Box`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:52:24 + --> $DIR/lint-ctypes.rs:54:24 | LL | pub fn box_type(p: Box); | ^^^^^^^^ not FFI-safe @@ -59,7 +68,7 @@ LL | pub fn box_type(p: Box); = note: this struct has unspecified layout error: `extern` block uses type `Option>`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:53:28 + --> $DIR/lint-ctypes.rs:55:28 | LL | pub fn opt_box_type(p: Option>); | ^^^^^^^^^^^^^^^^ not FFI-safe @@ -68,7 +77,7 @@ LL | pub fn opt_box_type(p: Option>); = note: enum has no representation hint error: `extern` block uses type `char`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:55:25 + --> $DIR/lint-ctypes.rs:57:25 | LL | pub fn char_type(p: char); | ^^^^ not FFI-safe @@ -77,7 +86,7 @@ LL | pub fn char_type(p: char); = note: the `char` type has no C equivalent error: `extern` block uses type `i128`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:56:25 + --> $DIR/lint-ctypes.rs:58:25 | LL | pub fn i128_type(p: i128); | ^^^^ not FFI-safe @@ -85,7 +94,7 @@ LL | pub fn i128_type(p: i128); = note: 128-bit integers don't currently have a known stable ABI error: `extern` block uses type `u128`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:57:25 + --> $DIR/lint-ctypes.rs:59:25 | LL | pub fn u128_type(p: u128); | ^^^^ not FFI-safe @@ -93,7 +102,7 @@ LL | pub fn u128_type(p: u128); = note: 128-bit integers don't currently have a known stable ABI error: `extern` block uses type `dyn Bar`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:58:26 + --> $DIR/lint-ctypes.rs:60:26 | LL | pub fn trait_type(p: &dyn Bar); | ^^^^^^^^ not FFI-safe @@ -101,7 +110,7 @@ LL | pub fn trait_type(p: &dyn Bar); = note: trait objects have no C equivalent error: `extern` block uses type `(i32, i32)`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:59:26 + --> $DIR/lint-ctypes.rs:61:26 | LL | pub fn tuple_type(p: (i32, i32)); | ^^^^^^^^^^ not FFI-safe @@ -110,7 +119,7 @@ LL | pub fn tuple_type(p: (i32, i32)); = note: tuples have unspecified layout error: `extern` block uses type `(i32, i32)`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:60:27 + --> $DIR/lint-ctypes.rs:62:27 | LL | pub fn tuple_type2(p: I32Pair); | ^^^^^^^ not FFI-safe @@ -119,7 +128,7 @@ LL | pub fn tuple_type2(p: I32Pair); = note: tuples have unspecified layout error: `extern` block uses type `ZeroSize`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:61:25 + --> $DIR/lint-ctypes.rs:63:25 | LL | pub fn zero_size(p: ZeroSize); | ^^^^^^^^ not FFI-safe @@ -133,7 +142,7 @@ LL | pub struct ZeroSize; | ^^^^^^^^^^^^^^^^^^^^ error: `extern` block uses type `ZeroSizeWithPhantomData`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:62:33 + --> $DIR/lint-ctypes.rs:64:33 | LL | pub fn zero_size_phantom(p: ZeroSizeWithPhantomData); | ^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -146,7 +155,7 @@ LL | pub struct ZeroSizeWithPhantomData(::std::marker::PhantomData); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `extern` block uses type `PhantomData`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:65:12 + --> $DIR/lint-ctypes.rs:67:12 | LL | -> ::std::marker::PhantomData; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -154,7 +163,7 @@ LL | -> ::std::marker::PhantomData; = note: composed only of `PhantomData` error: `extern` block uses type `fn()`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:66:23 + --> $DIR/lint-ctypes.rs:68:23 | LL | pub fn fn_type(p: RustFn); | ^^^^^^ not FFI-safe @@ -163,7 +172,7 @@ LL | pub fn fn_type(p: RustFn); = note: this function pointer has Rust-specific calling convention error: `extern` block uses type `fn()`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:67:24 + --> $DIR/lint-ctypes.rs:69:24 | LL | pub fn fn_type2(p: fn()); | ^^^^ not FFI-safe @@ -172,7 +181,7 @@ LL | pub fn fn_type2(p: fn()); = note: this function pointer has Rust-specific calling convention error: `extern` block uses type `Box`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:68:28 + --> $DIR/lint-ctypes.rs:70:28 | LL | pub fn fn_contained(p: RustBadRet); | ^^^^^^^^^^ not FFI-safe @@ -181,7 +190,7 @@ LL | pub fn fn_contained(p: RustBadRet); = note: this struct has unspecified layout error: `extern` block uses type `i128`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:69:32 + --> $DIR/lint-ctypes.rs:71:32 | LL | pub fn transparent_i128(p: TransparentI128); | ^^^^^^^^^^^^^^^ not FFI-safe @@ -189,7 +198,7 @@ LL | pub fn transparent_i128(p: TransparentI128); = note: 128-bit integers don't currently have a known stable ABI error: `extern` block uses type `str`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:70:31 + --> $DIR/lint-ctypes.rs:72:31 | LL | pub fn transparent_str(p: TransparentStr); | ^^^^^^^^^^^^^^ not FFI-safe @@ -198,7 +207,7 @@ LL | pub fn transparent_str(p: TransparentStr); = note: string slices have no C equivalent error: `extern` block uses type `Box`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:71:30 + --> $DIR/lint-ctypes.rs:73:30 | LL | pub fn transparent_fn(p: TransparentBadFn); | ^^^^^^^^^^^^^^^^ not FFI-safe @@ -207,7 +216,7 @@ LL | pub fn transparent_fn(p: TransparentBadFn); = note: this struct has unspecified layout error: `extern` block uses type `[u8; 8]`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:72:27 + --> $DIR/lint-ctypes.rs:74:27 | LL | pub fn raw_array(arr: [u8; 8]); | ^^^^^^^ not FFI-safe @@ -216,7 +225,7 @@ LL | pub fn raw_array(arr: [u8; 8]); = note: passing raw arrays by value is not FFI-safe error: `extern` block uses type `Option>`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:74:26 + --> $DIR/lint-ctypes.rs:76:26 | LL | pub fn no_niche_a(a: Option>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -225,7 +234,7 @@ LL | pub fn no_niche_a(a: Option>); = note: enum has no representation hint error: `extern` block uses type `Option>`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:76:26 + --> $DIR/lint-ctypes.rs:78:26 | LL | pub fn no_niche_b(b: Option>); | ^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -234,7 +243,7 @@ LL | pub fn no_niche_b(b: Option>); = note: enum has no representation hint error: `extern` block uses type `u128`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:79:34 + --> $DIR/lint-ctypes.rs:81:34 | LL | pub static static_u128_type: u128; | ^^^^ not FFI-safe @@ -242,12 +251,12 @@ LL | pub static static_u128_type: u128; = note: 128-bit integers don't currently have a known stable ABI error: `extern` block uses type `u128`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:80:40 + --> $DIR/lint-ctypes.rs:82:40 | LL | pub static static_u128_array_type: [u128; 16]; | ^^^^^^^^^^ not FFI-safe | = note: 128-bit integers don't currently have a known stable ABI -error: aborting due to 26 previous errors +error: aborting due to 27 previous errors diff --git a/src/test/ui/lint/lint-enum-intrinsics-non-enums.rs b/src/test/ui/lint/lint-enum-intrinsics-non-enums.rs new file mode 100644 index 0000000000..8ad337064e --- /dev/null +++ b/src/test/ui/lint/lint-enum-intrinsics-non-enums.rs @@ -0,0 +1,67 @@ +// Test the enum_intrinsics_non_enums lint. + +#![feature(variant_count)] + +use std::mem::{discriminant, variant_count}; + +enum SomeEnum { + A, + B, +} + +struct SomeStruct; + +fn generic_discriminant(v: &T) { + discriminant::(v); +} + +fn generic_variant_count() -> usize { + variant_count::() +} + +fn test_discriminant() { + discriminant(&SomeEnum::A); + generic_discriminant(&SomeEnum::B); + + discriminant(&()); + //~^ error: the return value of `mem::discriminant` is unspecified when called with a non-enum type + + discriminant(&&SomeEnum::B); + //~^ error: the return value of `mem::discriminant` is unspecified when called with a non-enum type + + discriminant(&SomeStruct); + //~^ error: the return value of `mem::discriminant` is unspecified when called with a non-enum type + + discriminant(&123u32); + //~^ error: the return value of `mem::discriminant` is unspecified when called with a non-enum type + + discriminant(&&123i8); + //~^ error: the return value of `mem::discriminant` is unspecified when called with a non-enum type +} + +fn test_variant_count() { + variant_count::(); + generic_variant_count::(); + + variant_count::<&str>(); + //~^ error: the return value of `mem::variant_count` is unspecified when called with a non-enum type + + variant_count::<*const u8>(); + //~^ error: the return value of `mem::variant_count` is unspecified when called with a non-enum type + + variant_count::<()>(); + //~^ error: the return value of `mem::variant_count` is unspecified when called with a non-enum type + + variant_count::<&SomeEnum>(); + //~^ error: the return value of `mem::variant_count` is unspecified when called with a non-enum type +} + +fn main() { + test_discriminant(); + test_variant_count(); + + // The lint ignores cases where the type is generic, so these should be + // allowed even though their return values are unspecified + generic_variant_count::(); + generic_discriminant::(&SomeStruct); +} diff --git a/src/test/ui/lint/lint-enum-intrinsics-non-enums.stderr b/src/test/ui/lint/lint-enum-intrinsics-non-enums.stderr new file mode 100644 index 0000000000..bec9fb62ef --- /dev/null +++ b/src/test/ui/lint/lint-enum-intrinsics-non-enums.stderr @@ -0,0 +1,95 @@ +error: the return value of `mem::discriminant` is unspecified when called with a non-enum type + --> $DIR/lint-enum-intrinsics-non-enums.rs:26:5 + | +LL | discriminant(&()); + | ^^^^^^^^^^^^^^^^^ + | + = note: `#[deny(enum_intrinsics_non_enums)]` on by default +note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `()`, which is not an enum. + --> $DIR/lint-enum-intrinsics-non-enums.rs:26:18 + | +LL | discriminant(&()); + | ^^^ + +error: the return value of `mem::discriminant` is unspecified when called with a non-enum type + --> $DIR/lint-enum-intrinsics-non-enums.rs:29:5 + | +LL | discriminant(&&SomeEnum::B); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `&SomeEnum`, which is not an enum. + --> $DIR/lint-enum-intrinsics-non-enums.rs:29:18 + | +LL | discriminant(&&SomeEnum::B); + | ^^^^^^^^^^^^^ + +error: the return value of `mem::discriminant` is unspecified when called with a non-enum type + --> $DIR/lint-enum-intrinsics-non-enums.rs:32:5 + | +LL | discriminant(&SomeStruct); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `SomeStruct`, which is not an enum. + --> $DIR/lint-enum-intrinsics-non-enums.rs:32:18 + | +LL | discriminant(&SomeStruct); + | ^^^^^^^^^^^ + +error: the return value of `mem::discriminant` is unspecified when called with a non-enum type + --> $DIR/lint-enum-intrinsics-non-enums.rs:35:5 + | +LL | discriminant(&123u32); + | ^^^^^^^^^^^^^^^^^^^^^ + | +note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `u32`, which is not an enum. + --> $DIR/lint-enum-intrinsics-non-enums.rs:35:18 + | +LL | discriminant(&123u32); + | ^^^^^^^ + +error: the return value of `mem::discriminant` is unspecified when called with a non-enum type + --> $DIR/lint-enum-intrinsics-non-enums.rs:38:5 + | +LL | discriminant(&&123i8); + | ^^^^^^^^^^^^^^^^^^^^^ + | +note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `&i8`, which is not an enum. + --> $DIR/lint-enum-intrinsics-non-enums.rs:38:18 + | +LL | discriminant(&&123i8); + | ^^^^^^^ + +error: the return value of `mem::variant_count` is unspecified when called with a non-enum type + --> $DIR/lint-enum-intrinsics-non-enums.rs:46:5 + | +LL | variant_count::<&str>(); + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the type parameter of `variant_count` should be an enum, but it was instantiated with the type `&str`, which is not an enum. + +error: the return value of `mem::variant_count` is unspecified when called with a non-enum type + --> $DIR/lint-enum-intrinsics-non-enums.rs:49:5 + | +LL | variant_count::<*const u8>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the type parameter of `variant_count` should be an enum, but it was instantiated with the type `*const u8`, which is not an enum. + +error: the return value of `mem::variant_count` is unspecified when called with a non-enum type + --> $DIR/lint-enum-intrinsics-non-enums.rs:52:5 + | +LL | variant_count::<()>(); + | ^^^^^^^^^^^^^^^^^^^^^ + | + = note: the type parameter of `variant_count` should be an enum, but it was instantiated with the type `()`, which is not an enum. + +error: the return value of `mem::variant_count` is unspecified when called with a non-enum type + --> $DIR/lint-enum-intrinsics-non-enums.rs:55:5 + | +LL | variant_count::<&SomeEnum>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the type parameter of `variant_count` should be an enum, but it was instantiated with the type `&SomeEnum`, which is not an enum. + +error: aborting due to 9 previous errors + diff --git a/src/test/ui/lint/lint-malformed.stderr b/src/test/ui/lint/lint-malformed.stderr index b3a41a786c..91b4e509b2 100644 --- a/src/test/ui/lint/lint-malformed.stderr +++ b/src/test/ui/lint/lint-malformed.stderr @@ -14,7 +14,7 @@ error: malformed `deny` attribute input --> $DIR/lint-malformed.rs:1:1 | LL | #![deny = "foo"] - | ^^^^^^^^^^^^^^^^ help: must be of the form: `#[deny(lint1, lint2, ..., /*opt*/ reason = "...")]` + | ^^^^^^^^^^^^^^^^ help: must be of the form: `#![deny(lint1, lint2, ..., /*opt*/ reason = "...")]` error[E0452]: malformed lint attribute input --> $DIR/lint-malformed.rs:2:10 diff --git a/src/test/ui/lint/lint-owned-heap-memory.rs b/src/test/ui/lint/lint-owned-heap-memory.rs index 7ef18c28c1..af47d5c072 100644 --- a/src/test/ui/lint/lint-owned-heap-memory.rs +++ b/src/test/ui/lint/lint-owned-heap-memory.rs @@ -1,12 +1,12 @@ #![allow(dead_code)] #![forbid(box_pointers)] -#![feature(box_syntax)] + struct Foo { x: Box //~ ERROR type uses owned } fn main() { - let _x : Foo = Foo {x : box 10}; + let _x: Foo = Foo { x : Box::new(10) }; //~^ ERROR type uses owned } diff --git a/src/test/ui/lint/lint-owned-heap-memory.stderr b/src/test/ui/lint/lint-owned-heap-memory.stderr index 40310f9387..5ba3969707 100644 --- a/src/test/ui/lint/lint-owned-heap-memory.stderr +++ b/src/test/ui/lint/lint-owned-heap-memory.stderr @@ -13,8 +13,8 @@ LL | #![forbid(box_pointers)] error: type uses owned (Box type) pointers: Box --> $DIR/lint-owned-heap-memory.rs:10:29 | -LL | let _x : Foo = Foo {x : box 10}; - | ^^^^^^ +LL | let _x: Foo = Foo { x : Box::new(10) }; + | ^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/lint/lint-stability2.stderr b/src/test/ui/lint/lint-stability2.stderr index 52f6c69cfc..51bdf84a32 100644 --- a/src/test/ui/lint/lint-stability2.stderr +++ b/src/test/ui/lint/lint-stability2.stderr @@ -2,7 +2,7 @@ error: use of deprecated function `lint_stability::deprecated`: text --> $DIR/lint-stability2.rs:12:5 | LL | macro_test!(); - | ^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ | note: the lint level is defined here --> $DIR/lint-stability2.rs:4:9 diff --git a/src/test/ui/lint/lint-unnecessary-parens.stderr b/src/test/ui/lint/lint-unnecessary-parens.stderr index 9eae7da900..1d5f9ebb5e 100644 --- a/src/test/ui/lint/lint-unnecessary-parens.stderr +++ b/src/test/ui/lint/lint-unnecessary-parens.stderr @@ -2,109 +2,210 @@ error: unnecessary parentheses around `return` value --> $DIR/lint-unnecessary-parens.rs:13:12 | LL | return (1); - | ^^^ help: remove these parentheses + | ^ ^ | note: the lint level is defined here --> $DIR/lint-unnecessary-parens.rs:3:9 | LL | #![deny(unused_parens)] | ^^^^^^^^^^^^^ +help: remove these parentheses + | +LL - return (1); +LL + return 1; + | error: unnecessary parentheses around `return` value --> $DIR/lint-unnecessary-parens.rs:16:12 | LL | return (X { y }); - | ^^^^^^^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - return (X { y }); +LL + return X { y }; + | error: unnecessary parentheses around type --> $DIR/lint-unnecessary-parens.rs:19:46 | LL | pub fn unused_parens_around_return_type() -> (u32) { - | ^^^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - pub fn unused_parens_around_return_type() -> (u32) { +LL + pub fn unused_parens_around_return_type() -> u32 { + | error: unnecessary parentheses around block return value --> $DIR/lint-unnecessary-parens.rs:25:9 | LL | (5) - | ^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - (5) +LL + 5 + | error: unnecessary parentheses around block return value --> $DIR/lint-unnecessary-parens.rs:27:5 | LL | (5) - | ^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - (5) +LL + 5 + | error: unnecessary parentheses around assigned value --> $DIR/lint-unnecessary-parens.rs:44:31 | LL | pub const CONST_ITEM: usize = (10); - | ^^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - pub const CONST_ITEM: usize = (10); +LL + pub const CONST_ITEM: usize = 10; + | error: unnecessary parentheses around assigned value --> $DIR/lint-unnecessary-parens.rs:45:33 | LL | pub static STATIC_ITEM: usize = (10); - | ^^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - pub static STATIC_ITEM: usize = (10); +LL + pub static STATIC_ITEM: usize = 10; + | error: unnecessary parentheses around function argument --> $DIR/lint-unnecessary-parens.rs:49:9 | LL | bar((true)); - | ^^^^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - bar((true)); +LL + bar(true); + | error: unnecessary parentheses around `if` condition --> $DIR/lint-unnecessary-parens.rs:51:8 | LL | if (true) {} - | ^^^^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - if (true) {} +LL + if true {} + | error: unnecessary parentheses around `while` condition --> $DIR/lint-unnecessary-parens.rs:52:11 | LL | while (true) {} - | ^^^^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - while (true) {} +LL + while true {} + | error: unnecessary parentheses around `match` scrutinee expression --> $DIR/lint-unnecessary-parens.rs:53:11 | LL | match (true) { - | ^^^^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - match (true) { +LL + match true { + | error: unnecessary parentheses around `let` scrutinee expression --> $DIR/lint-unnecessary-parens.rs:56:16 | LL | if let 1 = (1) {} - | ^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - if let 1 = (1) {} +LL + if let 1 = 1 {} + | error: unnecessary parentheses around `let` scrutinee expression --> $DIR/lint-unnecessary-parens.rs:57:19 | LL | while let 1 = (2) {} - | ^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - while let 1 = (2) {} +LL + while let 1 = 2 {} + | error: unnecessary parentheses around method argument --> $DIR/lint-unnecessary-parens.rs:73:24 | LL | X { y: false }.foo((true)); - | ^^^^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - X { y: false }.foo((true)); +LL + X { y: false }.foo(true); + | error: unnecessary parentheses around assigned value --> $DIR/lint-unnecessary-parens.rs:75:18 | LL | let mut _a = (0); - | ^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - let mut _a = (0); +LL + let mut _a = 0; + | error: unnecessary parentheses around assigned value --> $DIR/lint-unnecessary-parens.rs:76:10 | LL | _a = (0); - | ^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - _a = (0); +LL + _a = 0; + | error: unnecessary parentheses around assigned value --> $DIR/lint-unnecessary-parens.rs:77:11 | LL | _a += (1); - | ^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - _a += (1); +LL + _a += 1; + | error: aborting due to 17 previous errors diff --git a/src/test/ui/lint/lints-in-foreign-macros.stderr b/src/test/ui/lint/lints-in-foreign-macros.stderr index 55fea4e363..f20e16287a 100644 --- a/src/test/ui/lint/lints-in-foreign-macros.stderr +++ b/src/test/ui/lint/lints-in-foreign-macros.stderr @@ -5,7 +5,7 @@ LL | () => {use std::string::ToString;} | ^^^^^^^^^^^^^^^^^^^^^ ... LL | mod a { foo!(); } - | ------- in this macro invocation + | ------ in this macro invocation | note: the lint level is defined here --> $DIR/lints-in-foreign-macros.rs:4:9 diff --git a/src/test/ui/lint/must_not_suspend/boxed.rs b/src/test/ui/lint/must_not_suspend/boxed.rs new file mode 100644 index 0000000000..1f823fc559 --- /dev/null +++ b/src/test/ui/lint/must_not_suspend/boxed.rs @@ -0,0 +1,25 @@ +// edition:2018 +#![feature(must_not_suspend)] +#![deny(must_not_suspend)] + +#[must_not_suspend = "You gotta use Umm's, ya know?"] +struct Umm { + i: i64 +} + + +fn bar() -> Box { + Box::new(Umm { + i: 1 + }) +} + +async fn other() {} + +pub async fn uhoh() { + let _guard = bar(); //~ ERROR boxed `Umm` held across + other().await; +} + +fn main() { +} diff --git a/src/test/ui/lint/must_not_suspend/boxed.stderr b/src/test/ui/lint/must_not_suspend/boxed.stderr new file mode 100644 index 0000000000..edc62b6d68 --- /dev/null +++ b/src/test/ui/lint/must_not_suspend/boxed.stderr @@ -0,0 +1,26 @@ +error: boxed `Umm` held across a suspend point, but should not be + --> $DIR/boxed.rs:20:9 + | +LL | let _guard = bar(); + | ^^^^^^ +LL | other().await; + | ------------- the value is held across this suspend point + | +note: the lint level is defined here + --> $DIR/boxed.rs:3:9 + | +LL | #![deny(must_not_suspend)] + | ^^^^^^^^^^^^^^^^ +note: You gotta use Umm's, ya know? + --> $DIR/boxed.rs:20:9 + | +LL | let _guard = bar(); + | ^^^^^^ +help: consider using a block (`{ ... }`) to shrink the value's scope, ending before the suspend point + --> $DIR/boxed.rs:20:9 + | +LL | let _guard = bar(); + | ^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/lint/must_not_suspend/dedup.rs b/src/test/ui/lint/must_not_suspend/dedup.rs new file mode 100644 index 0000000000..040fff5a5a --- /dev/null +++ b/src/test/ui/lint/must_not_suspend/dedup.rs @@ -0,0 +1,20 @@ +// edition:2018 +#![feature(must_not_suspend)] +#![deny(must_not_suspend)] + +#[must_not_suspend] +struct No {} + +async fn shushspend() {} + +async fn wheeee(t: T) { + shushspend().await; + drop(t); +} + +async fn yes() { + wheeee(No {}).await; //~ ERROR `No` held across +} + +fn main() { +} diff --git a/src/test/ui/lint/must_not_suspend/dedup.stderr b/src/test/ui/lint/must_not_suspend/dedup.stderr new file mode 100644 index 0000000000..542b7a3bc7 --- /dev/null +++ b/src/test/ui/lint/must_not_suspend/dedup.stderr @@ -0,0 +1,19 @@ +error: `No` held across a suspend point, but should not be + --> $DIR/dedup.rs:16:12 + | +LL | wheeee(No {}).await; + | -------^^^^^------- the value is held across this suspend point + | +note: the lint level is defined here + --> $DIR/dedup.rs:3:9 + | +LL | #![deny(must_not_suspend)] + | ^^^^^^^^^^^^^^^^ +help: consider using a block (`{ ... }`) to shrink the value's scope, ending before the suspend point + --> $DIR/dedup.rs:16:12 + | +LL | wheeee(No {}).await; + | ^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/lint/must_not_suspend/feature-gate-must_not_suspend.rs b/src/test/ui/lint/must_not_suspend/feature-gate-must_not_suspend.rs new file mode 100644 index 0000000000..1554408c17 --- /dev/null +++ b/src/test/ui/lint/must_not_suspend/feature-gate-must_not_suspend.rs @@ -0,0 +1,9 @@ +// edition:2018 + +#[must_not_suspend = "You gotta use Umm's, ya know?"] //~ ERROR the `#[must_not_suspend]` +struct Umm { + _i: i64 +} + +fn main() { +} diff --git a/src/test/ui/lint/must_not_suspend/feature-gate-must_not_suspend.stderr b/src/test/ui/lint/must_not_suspend/feature-gate-must_not_suspend.stderr new file mode 100644 index 0000000000..ab20a8be87 --- /dev/null +++ b/src/test/ui/lint/must_not_suspend/feature-gate-must_not_suspend.stderr @@ -0,0 +1,12 @@ +error[E0658]: the `#[must_not_suspend]` attribute is an experimental feature + --> $DIR/feature-gate-must_not_suspend.rs:3:1 + | +LL | #[must_not_suspend = "You gotta use Umm's, ya know?"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #83310 for more information + = help: add `#![feature(must_not_suspend)]` 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/lint/must_not_suspend/gated.rs b/src/test/ui/lint/must_not_suspend/gated.rs new file mode 100644 index 0000000000..acb81b0bf9 --- /dev/null +++ b/src/test/ui/lint/must_not_suspend/gated.rs @@ -0,0 +1,14 @@ +// edition:2018 +#![deny(must_not_suspend)] //~ ERROR the `must_not_suspend` +//~| ERROR the `must_not_suspend` +//~| ERROR the `must_not_suspend` + +async fn other() {} + +pub async fn uhoh(m: std::sync::Mutex<()>) { + let _guard = m.lock().unwrap(); //~ ERROR `MutexGuard` held across + other().await; +} + +fn main() { +} diff --git a/src/test/ui/lint/must_not_suspend/gated.stderr b/src/test/ui/lint/must_not_suspend/gated.stderr new file mode 100644 index 0000000000..be077deb3f --- /dev/null +++ b/src/test/ui/lint/must_not_suspend/gated.stderr @@ -0,0 +1,54 @@ +error[E0658]: the `must_not_suspend` lint is unstable + --> $DIR/gated.rs:2:1 + | +LL | #![deny(must_not_suspend)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #83310 for more information + = help: add `#![feature(must_not_suspend)]` to the crate attributes to enable + +error[E0658]: the `must_not_suspend` lint is unstable + --> $DIR/gated.rs:2:1 + | +LL | #![deny(must_not_suspend)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #83310 for more information + = help: add `#![feature(must_not_suspend)]` to the crate attributes to enable + +error[E0658]: the `must_not_suspend` lint is unstable + --> $DIR/gated.rs:2:1 + | +LL | #![deny(must_not_suspend)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #83310 for more information + = help: add `#![feature(must_not_suspend)]` to the crate attributes to enable + +error: `MutexGuard` held across a suspend point, but should not be + --> $DIR/gated.rs:9:9 + | +LL | let _guard = m.lock().unwrap(); + | ^^^^^^ +LL | other().await; + | ------------- the value is held across this suspend point + | +note: the lint level is defined here + --> $DIR/gated.rs:2:9 + | +LL | #![deny(must_not_suspend)] + | ^^^^^^^^^^^^^^^^ +note: holding a MutexGuard across suspend points can cause deadlocks, delays, and cause Futures to not implement `Send` + --> $DIR/gated.rs:9:9 + | +LL | let _guard = m.lock().unwrap(); + | ^^^^^^ +help: consider using a block (`{ ... }`) to shrink the value's scope, ending before the suspend point + --> $DIR/gated.rs:9:9 + | +LL | let _guard = m.lock().unwrap(); + | ^^^^^^ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/lint/must_not_suspend/generic.rs b/src/test/ui/lint/must_not_suspend/generic.rs new file mode 100644 index 0000000000..b3effa020c --- /dev/null +++ b/src/test/ui/lint/must_not_suspend/generic.rs @@ -0,0 +1,20 @@ +// edition:2018 +// run-pass +// +// this test shows a case where the lint doesn't fire in generic code +#![feature(must_not_suspend)] +#![deny(must_not_suspend)] + +#[must_not_suspend] +struct No {} + +async fn shushspend() {} + +async fn wheeee(t: T) { + shushspend().await; + drop(t); +} + +fn main() { + let _fut = wheeee(No {}); +} diff --git a/src/test/ui/lint/must_not_suspend/handled.rs b/src/test/ui/lint/must_not_suspend/handled.rs new file mode 100644 index 0000000000..8714be6449 --- /dev/null +++ b/src/test/ui/lint/must_not_suspend/handled.rs @@ -0,0 +1,28 @@ +// edition:2018 +// run-pass +#![feature(must_not_suspend)] +#![deny(must_not_suspend)] + +#[must_not_suspend = "You gotta use Umm's, ya know?"] +struct Umm { + _i: i64 +} + + +fn bar() -> Umm { + Umm { + _i: 1 + } +} + +async fn other() {} + +pub async fn uhoh() { + { + let _guard = bar(); + } + other().await; +} + +fn main() { +} diff --git a/src/test/ui/lint/must_not_suspend/issue-89562.rs b/src/test/ui/lint/must_not_suspend/issue-89562.rs new file mode 100644 index 0000000000..acdb36fcda --- /dev/null +++ b/src/test/ui/lint/must_not_suspend/issue-89562.rs @@ -0,0 +1,19 @@ +// edition:2018 +// run-pass + +use std::sync::Mutex; + +// Copied from the issue. Allow-by-default for now, so run-pass +pub async fn foo() { + let foo = Mutex::new(1); + let lock = foo.lock().unwrap(); + + // Prevent mutex lock being held across `.await` point. + drop(lock); + + bar().await; +} + +async fn bar() {} + +fn main() {} diff --git a/src/test/ui/lint/must_not_suspend/mutex.rs b/src/test/ui/lint/must_not_suspend/mutex.rs new file mode 100644 index 0000000000..7bb895e7d3 --- /dev/null +++ b/src/test/ui/lint/must_not_suspend/mutex.rs @@ -0,0 +1,13 @@ +// edition:2018 +#![feature(must_not_suspend)] +#![deny(must_not_suspend)] + +async fn other() {} + +pub async fn uhoh(m: std::sync::Mutex<()>) { + let _guard = m.lock().unwrap(); //~ ERROR `MutexGuard` held across + other().await; +} + +fn main() { +} diff --git a/src/test/ui/lint/must_not_suspend/mutex.stderr b/src/test/ui/lint/must_not_suspend/mutex.stderr new file mode 100644 index 0000000000..dde506c19e --- /dev/null +++ b/src/test/ui/lint/must_not_suspend/mutex.stderr @@ -0,0 +1,26 @@ +error: `MutexGuard` held across a suspend point, but should not be + --> $DIR/mutex.rs:8:9 + | +LL | let _guard = m.lock().unwrap(); + | ^^^^^^ +LL | other().await; + | ------------- the value is held across this suspend point + | +note: the lint level is defined here + --> $DIR/mutex.rs:3:9 + | +LL | #![deny(must_not_suspend)] + | ^^^^^^^^^^^^^^^^ +note: holding a MutexGuard across suspend points can cause deadlocks, delays, and cause Futures to not implement `Send` + --> $DIR/mutex.rs:8:9 + | +LL | let _guard = m.lock().unwrap(); + | ^^^^^^ +help: consider using a block (`{ ... }`) to shrink the value's scope, ending before the suspend point + --> $DIR/mutex.rs:8:9 + | +LL | let _guard = m.lock().unwrap(); + | ^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/lint/must_not_suspend/other_items.rs b/src/test/ui/lint/must_not_suspend/other_items.rs new file mode 100644 index 0000000000..5aa1abb14d --- /dev/null +++ b/src/test/ui/lint/must_not_suspend/other_items.rs @@ -0,0 +1,8 @@ +// edition:2018 +#![feature(must_not_suspend)] +#![deny(must_not_suspend)] + +#[must_not_suspend] //~ ERROR attribute should be +mod inner {} + +fn main() {} diff --git a/src/test/ui/lint/must_not_suspend/other_items.stderr b/src/test/ui/lint/must_not_suspend/other_items.stderr new file mode 100644 index 0000000000..41c8896921 --- /dev/null +++ b/src/test/ui/lint/must_not_suspend/other_items.stderr @@ -0,0 +1,10 @@ +error: `must_not_suspend` attribute should be applied to a struct, enum, or trait + --> $DIR/other_items.rs:5:1 + | +LL | #[must_not_suspend] + | ^^^^^^^^^^^^^^^^^^^ +LL | mod inner {} + | ------------ is not a struct, enum, or trait + +error: aborting due to previous error + diff --git a/src/test/ui/lint/must_not_suspend/ref.rs b/src/test/ui/lint/must_not_suspend/ref.rs new file mode 100644 index 0000000000..738dd9e046 --- /dev/null +++ b/src/test/ui/lint/must_not_suspend/ref.rs @@ -0,0 +1,29 @@ +// edition:2018 +#![feature(must_not_suspend)] +#![deny(must_not_suspend)] + +#[must_not_suspend = "You gotta use Umm's, ya know?"] +struct Umm { + i: i64 +} + +struct Bar { + u: Umm, +} + +async fn other() {} + +impl Bar { + async fn uhoh(&mut self) { + let guard = &mut self.u; //~ ERROR `Umm` held across + + other().await; + + *guard = Umm { + i: 2 + } + } +} + +fn main() { +} diff --git a/src/test/ui/lint/must_not_suspend/ref.stderr b/src/test/ui/lint/must_not_suspend/ref.stderr new file mode 100644 index 0000000000..78b44b0062 --- /dev/null +++ b/src/test/ui/lint/must_not_suspend/ref.stderr @@ -0,0 +1,27 @@ +error: `Umm` held across a suspend point, but should not be + --> $DIR/ref.rs:18:26 + | +LL | let guard = &mut self.u; + | ^^^^^^ +LL | +LL | other().await; + | ------------- the value is held across this suspend point + | +note: the lint level is defined here + --> $DIR/ref.rs:3:9 + | +LL | #![deny(must_not_suspend)] + | ^^^^^^^^^^^^^^^^ +note: You gotta use Umm's, ya know? + --> $DIR/ref.rs:18:26 + | +LL | let guard = &mut self.u; + | ^^^^^^ +help: consider using a block (`{ ... }`) to shrink the value's scope, ending before the suspend point + --> $DIR/ref.rs:18:26 + | +LL | let guard = &mut self.u; + | ^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/lint/must_not_suspend/return.rs b/src/test/ui/lint/must_not_suspend/return.rs new file mode 100644 index 0000000000..5b1fa5e272 --- /dev/null +++ b/src/test/ui/lint/must_not_suspend/return.rs @@ -0,0 +1,9 @@ +// edition:2018 +#![feature(must_not_suspend)] +#![deny(must_not_suspend)] + +#[must_not_suspend] //~ ERROR attribute should be +fn foo() -> i32 { + 0 +} +fn main() {} diff --git a/src/test/ui/lint/must_not_suspend/return.stderr b/src/test/ui/lint/must_not_suspend/return.stderr new file mode 100644 index 0000000000..fdada85eb4 --- /dev/null +++ b/src/test/ui/lint/must_not_suspend/return.stderr @@ -0,0 +1,12 @@ +error: `must_not_suspend` attribute should be applied to a struct, enum, or trait + --> $DIR/return.rs:5:1 + | +LL | #[must_not_suspend] + | ^^^^^^^^^^^^^^^^^^^ +LL | / fn foo() -> i32 { +LL | | 0 +LL | | } + | |_- is not a struct, enum, or trait + +error: aborting due to previous error + diff --git a/src/test/ui/lint/must_not_suspend/trait.rs b/src/test/ui/lint/must_not_suspend/trait.rs new file mode 100644 index 0000000000..6c911cb4b0 --- /dev/null +++ b/src/test/ui/lint/must_not_suspend/trait.rs @@ -0,0 +1,28 @@ +// edition:2018 +#![feature(must_not_suspend)] +#![deny(must_not_suspend)] + +#[must_not_suspend] +trait Wow {} + +impl Wow for i32 {} + +fn r#impl() -> impl Wow { + 1 +} + +fn r#dyn() -> Box { + Box::new(1) +} + +async fn other() {} + +pub async fn uhoh() { + let _guard1 = r#impl(); //~ ERROR implementer of `Wow` held across + let _guard2 = r#dyn(); //~ ERROR boxed `Wow` trait object held across + + other().await; +} + +fn main() { +} diff --git a/src/test/ui/lint/must_not_suspend/trait.stderr b/src/test/ui/lint/must_not_suspend/trait.stderr new file mode 100644 index 0000000000..d19ffddd48 --- /dev/null +++ b/src/test/ui/lint/must_not_suspend/trait.stderr @@ -0,0 +1,37 @@ +error: implementer of `Wow` held across a suspend point, but should not be + --> $DIR/trait.rs:21:9 + | +LL | let _guard1 = r#impl(); + | ^^^^^^^ +... +LL | other().await; + | ------------- the value is held across this suspend point + | +note: the lint level is defined here + --> $DIR/trait.rs:3:9 + | +LL | #![deny(must_not_suspend)] + | ^^^^^^^^^^^^^^^^ +help: consider using a block (`{ ... }`) to shrink the value's scope, ending before the suspend point + --> $DIR/trait.rs:21:9 + | +LL | let _guard1 = r#impl(); + | ^^^^^^^ + +error: boxed `Wow` trait object held across a suspend point, but should not be + --> $DIR/trait.rs:22:9 + | +LL | let _guard2 = r#dyn(); + | ^^^^^^^ +LL | +LL | other().await; + | ------------- the value is held across this suspend point + | +help: consider using a block (`{ ... }`) to shrink the value's scope, ending before the suspend point + --> $DIR/trait.rs:22:9 + | +LL | let _guard2 = r#dyn(); + | ^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/lint/must_not_suspend/unit.rs b/src/test/ui/lint/must_not_suspend/unit.rs new file mode 100644 index 0000000000..d3a19f7043 --- /dev/null +++ b/src/test/ui/lint/must_not_suspend/unit.rs @@ -0,0 +1,25 @@ +// edition:2018 +#![feature(must_not_suspend)] +#![deny(must_not_suspend)] + +#[must_not_suspend = "You gotta use Umm's, ya know?"] +struct Umm { + i: i64 +} + + +fn bar() -> Umm { + Umm { + i: 1 + } +} + +async fn other() {} + +pub async fn uhoh() { + let _guard = bar(); //~ ERROR `Umm` held across + other().await; +} + +fn main() { +} diff --git a/src/test/ui/lint/must_not_suspend/unit.stderr b/src/test/ui/lint/must_not_suspend/unit.stderr new file mode 100644 index 0000000000..425c076823 --- /dev/null +++ b/src/test/ui/lint/must_not_suspend/unit.stderr @@ -0,0 +1,26 @@ +error: `Umm` held across a suspend point, but should not be + --> $DIR/unit.rs:20:9 + | +LL | let _guard = bar(); + | ^^^^^^ +LL | other().await; + | ------------- the value is held across this suspend point + | +note: the lint level is defined here + --> $DIR/unit.rs:3:9 + | +LL | #![deny(must_not_suspend)] + | ^^^^^^^^^^^^^^^^ +note: You gotta use Umm's, ya know? + --> $DIR/unit.rs:20:9 + | +LL | let _guard = bar(); + | ^^^^^^ +help: consider using a block (`{ ... }`) to shrink the value's scope, ending before the suspend point + --> $DIR/unit.rs:20:9 + | +LL | let _guard = bar(); + | ^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/lint/must_not_suspend/warn.rs b/src/test/ui/lint/must_not_suspend/warn.rs new file mode 100644 index 0000000000..7fdea66a23 --- /dev/null +++ b/src/test/ui/lint/must_not_suspend/warn.rs @@ -0,0 +1,26 @@ +// edition:2018 +// run-pass +#![feature(must_not_suspend)] +#![warn(must_not_suspend)] + +#[must_not_suspend = "You gotta use Umm's, ya know?"] +struct Umm { + _i: i64 +} + + +fn bar() -> Umm { + Umm { + _i: 1 + } +} + +async fn other() {} + +pub async fn uhoh() { + let _guard = bar(); //~ WARNING `Umm` held across + other().await; +} + +fn main() { +} diff --git a/src/test/ui/lint/must_not_suspend/warn.stderr b/src/test/ui/lint/must_not_suspend/warn.stderr new file mode 100644 index 0000000000..42374d4aca --- /dev/null +++ b/src/test/ui/lint/must_not_suspend/warn.stderr @@ -0,0 +1,26 @@ +warning: `Umm` held across a suspend point, but should not be + --> $DIR/warn.rs:21:9 + | +LL | let _guard = bar(); + | ^^^^^^ +LL | other().await; + | ------------- the value is held across this suspend point + | +note: the lint level is defined here + --> $DIR/warn.rs:4:9 + | +LL | #![warn(must_not_suspend)] + | ^^^^^^^^^^^^^^^^ +note: You gotta use Umm's, ya know? + --> $DIR/warn.rs:21:9 + | +LL | let _guard = bar(); + | ^^^^^^ +help: consider using a block (`{ ... }`) to shrink the value's scope, ending before the suspend point + --> $DIR/warn.rs:21:9 + | +LL | let _guard = bar(); + | ^^^^^^ + +warning: 1 warning emitted + diff --git a/src/test/ui/lint/outer-forbid.rs b/src/test/ui/lint/outer-forbid.rs index 486ec3c468..ba330258d1 100644 --- a/src/test/ui/lint/outer-forbid.rs +++ b/src/test/ui/lint/outer-forbid.rs @@ -17,10 +17,9 @@ #![forbid(unused, non_snake_case)] #![forbid(forbidden_lint_groups)] -#[allow(unused_variables)] //~ ERROR incompatible with previous +#[allow(unused_variables)] //~^ ERROR incompatible with previous //~| WARNING this was previously accepted by the compiler -//~| WARNING this was previously accepted by the compiler fn foo() {} #[allow(unused)] //~ ERROR incompatible with previous diff --git a/src/test/ui/lint/outer-forbid.stderr b/src/test/ui/lint/outer-forbid.stderr index d69157a8bb..7814573210 100644 --- a/src/test/ui/lint/outer-forbid.stderr +++ b/src/test/ui/lint/outer-forbid.stderr @@ -16,7 +16,7 @@ LL | #![forbid(forbidden_lint_groups)] = note: for more information, see issue #81670 error: allow(unused) incompatible with previous forbid - --> $DIR/outer-forbid.rs:26:9 + --> $DIR/outer-forbid.rs:25:9 | LL | #![forbid(unused, non_snake_case)] | ------ `forbid` level set here @@ -28,7 +28,7 @@ LL | #[allow(unused)] = note: for more information, see issue #81670 error[E0453]: allow(nonstandard_style) incompatible with previous forbid - --> $DIR/outer-forbid.rs:30:9 + --> $DIR/outer-forbid.rs:29:9 | LL | #![forbid(unused, non_snake_case)] | -------------- `forbid` level set here @@ -36,18 +36,6 @@ LL | #![forbid(unused, non_snake_case)] LL | #[allow(nonstandard_style)] | ^^^^^^^^^^^^^^^^^ overruled by previous forbid -error: allow(unused_variables) incompatible with previous forbid - --> $DIR/outer-forbid.rs:20:9 - | -LL | #![forbid(unused, non_snake_case)] - | ------ `forbid` level set here -... -LL | #[allow(unused_variables)] - | ^^^^^^^^^^^^^^^^ 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 - -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0453`. diff --git a/src/test/ui/lint/rfc-2457-non-ascii-idents/lint-mixed-script-confusables.rs b/src/test/ui/lint/rfc-2457-non-ascii-idents/lint-mixed-script-confusables.rs index 7ee9c41f6a..9d837d41f1 100644 --- a/src/test/ui/lint/rfc-2457-non-ascii-idents/lint-mixed-script-confusables.rs +++ b/src/test/ui/lint/rfc-2457-non-ascii-idents/lint-mixed-script-confusables.rs @@ -1,14 +1,14 @@ #![deny(mixed_script_confusables)] struct ΑctuallyNotLatin; -//~^ ERROR The usage of Script Group `Greek` in this crate consists solely of +//~^ ERROR the usage of Script Group `Greek` in this crate consists solely of fn main() { let v = ΑctuallyNotLatin; } mod роре { -//~^ ERROR The usage of Script Group `Cyrillic` in this crate consists solely of +//~^ ERROR the usage of Script Group `Cyrillic` in this crate consists solely of const エ: &'static str = "アイウ"; - //~^ ERROR The usage of Script Group `Japanese, Katakana` in this crate consists solely of + //~^ ERROR the usage of Script Group `Japanese, Katakana` in this crate consists solely of } diff --git a/src/test/ui/lint/rfc-2457-non-ascii-idents/lint-mixed-script-confusables.stderr b/src/test/ui/lint/rfc-2457-non-ascii-idents/lint-mixed-script-confusables.stderr index 4018b381fb..9ca034b71b 100644 --- a/src/test/ui/lint/rfc-2457-non-ascii-idents/lint-mixed-script-confusables.stderr +++ b/src/test/ui/lint/rfc-2457-non-ascii-idents/lint-mixed-script-confusables.stderr @@ -1,4 +1,4 @@ -error: The usage of Script Group `Greek` in this crate consists solely of mixed script confusables +error: the usage of Script Group `Greek` in this crate consists solely of mixed script confusables --> $DIR/lint-mixed-script-confusables.rs:3:8 | LL | struct ΑctuallyNotLatin; @@ -9,26 +9,26 @@ note: the lint level is defined here | LL | #![deny(mixed_script_confusables)] | ^^^^^^^^^^^^^^^^^^^^^^^^ - = note: The usage includes 'Α' (U+0391). - = note: Please recheck to make sure their usages are indeed what you want. + = note: the usage includes 'Α' (U+0391) + = note: please recheck to make sure their usages are indeed what you want -error: The usage of Script Group `Cyrillic` in this crate consists solely of mixed script confusables +error: the usage of Script Group `Cyrillic` in this crate consists solely of mixed script confusables --> $DIR/lint-mixed-script-confusables.rs:10:5 | LL | mod роре { | ^^^^ | - = note: The usage includes 'е' (U+0435), 'о' (U+043E), 'р' (U+0440). - = note: Please recheck to make sure their usages are indeed what you want. + = note: the usage includes 'е' (U+0435), 'о' (U+043E), 'р' (U+0440) + = note: please recheck to make sure their usages are indeed what you want -error: The usage of Script Group `Japanese, Katakana` in this crate consists solely of mixed script confusables +error: the usage of Script Group `Japanese, Katakana` in this crate consists solely of mixed script confusables --> $DIR/lint-mixed-script-confusables.rs:12:11 | LL | const エ: &'static str = "アイウ"; | ^^ | - = note: The usage includes 'エ' (U+30A8). - = note: Please recheck to make sure their usages are indeed what you want. + = note: the usage includes 'エ' (U+30A8) + = note: please recheck to make sure their usages are indeed what you want error: aborting due to 3 previous errors diff --git a/src/test/ui/lint/suggestions.stderr b/src/test/ui/lint/suggestions.stderr index cad2514625..255772ff40 100644 --- a/src/test/ui/lint/suggestions.stderr +++ b/src/test/ui/lint/suggestions.stderr @@ -10,13 +10,18 @@ warning: unnecessary parentheses around assigned value --> $DIR/suggestions.rs:48:31 | LL | let mut registry_no = (format!("NX-{}", 74205)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove these parentheses + | ^ ^ | note: the lint level is defined here --> $DIR/suggestions.rs:4:21 | LL | #![warn(unused_mut, unused_parens)] // UI tests pass `-A unused`—see Issue #43896 | ^^^^^^^^^^^^^ +help: remove these parentheses + | +LL - let mut registry_no = (format!("NX-{}", 74205)); +LL + let mut registry_no = format!("NX-{}", 74205); + | warning: variable does not need to be mutable --> $DIR/suggestions.rs:48:13 diff --git a/src/test/ui/lint/unaligned_references.stderr b/src/test/ui/lint/unaligned_references.stderr index b4cce3cfea..6a5cc91963 100644 --- a/src/test/ui/lint/unaligned_references.stderr +++ b/src/test/ui/lint/unaligned_references.stderr @@ -47,7 +47,7 @@ error: reference to packed field is unaligned --> $DIR/unaligned_references.rs:32:17 | LL | let _ = good.data.clone(); - | ^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #82523 diff --git a/src/test/ui/lint/unreachable_pub-pub_crate.stderr b/src/test/ui/lint/unreachable_pub-pub_crate.stderr index 27444e0553..f284db80ff 100644 --- a/src/test/ui/lint/unreachable_pub-pub_crate.stderr +++ b/src/test/ui/lint/unreachable_pub-pub_crate.stderr @@ -126,7 +126,7 @@ LL | ($visibility: vis, $name: ident) => { $visibility struct $name {} } | ^^^^^^^^^^^^^^^^^^^^^^^^ ... LL | define_empty_struct_with_visibility!(pub, Fluorine); - | ---------------------------------------------------- + | --------------------------------------------------- | | | | | help: consider restricting its visibility: `pub(crate)` | in this macro invocation diff --git a/src/test/ui/lint/unreachable_pub.stderr b/src/test/ui/lint/unreachable_pub.stderr index 5d79292e3e..61c9582287 100644 --- a/src/test/ui/lint/unreachable_pub.stderr +++ b/src/test/ui/lint/unreachable_pub.stderr @@ -126,7 +126,7 @@ LL | ($visibility: vis, $name: ident) => { $visibility struct $name {} } | ^^^^^^^^^^^^^^^^^^^^^^^^ ... LL | define_empty_struct_with_visibility!(pub, Fluorine); - | ---------------------------------------------------- + | --------------------------------------------------- | | | | | help: consider restricting its visibility: `crate` | in this macro invocation diff --git a/src/test/ui/lint/unsafe_code/auxiliary/forge_unsafe_block.rs b/src/test/ui/lint/unsafe_code/auxiliary/forge_unsafe_block.rs new file mode 100644 index 0000000000..26871c98db --- /dev/null +++ b/src/test/ui/lint/unsafe_code/auxiliary/forge_unsafe_block.rs @@ -0,0 +1,16 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::{Delimiter, Group, Ident, Span, TokenStream, TokenTree}; + +#[proc_macro] +pub fn forge_unsafe_block(input: TokenStream) -> TokenStream { + let mut output = TokenStream::new(); + output.extend(Some(TokenTree::from(Ident::new("unsafe", Span::call_site())))); + output.extend(Some(TokenTree::from(Group::new(Delimiter::Brace, input)))); + output +} diff --git a/src/test/ui/lint/unsafe_code/forge_unsafe_block.rs b/src/test/ui/lint/unsafe_code/forge_unsafe_block.rs new file mode 100644 index 0000000000..a1bd7b4131 --- /dev/null +++ b/src/test/ui/lint/unsafe_code/forge_unsafe_block.rs @@ -0,0 +1,16 @@ +// check-pass +// aux-build:forge_unsafe_block.rs + +#[macro_use] +extern crate forge_unsafe_block; + +unsafe fn foo() {} + +#[forbid(unsafe_code)] +fn main() { + // `forbid` doesn't work for non-user-provided unsafe blocks. + // see `UnsafeCode::check_expr`. + forge_unsafe_block! { + foo(); + } +} diff --git a/src/test/ui/lint/unused/issue-47390-unused-variable-in-struct-pattern.rs b/src/test/ui/lint/unused/issue-47390-unused-variable-in-struct-pattern.rs index 0ad014e336..4822a9b2c7 100644 --- a/src/test/ui/lint/unused/issue-47390-unused-variable-in-struct-pattern.rs +++ b/src/test/ui/lint/unused/issue-47390-unused-variable-in-struct-pattern.rs @@ -1,7 +1,7 @@ // check-pass -#![feature(box_syntax)] #![feature(box_patterns)] + #![warn(unused)] // UI tests pass `-A unused` (#43896) struct SoulHistory { @@ -67,7 +67,7 @@ fn main() { }; // Boxed struct - match box bag { + match Box::new(bag) { box Large::Suit { case } => {} //~ WARNING unused variable: `case` }; diff --git a/src/test/ui/lint/unused/issue-54538-unused-parens-lint.stderr b/src/test/ui/lint/unused/issue-54538-unused-parens-lint.stderr index e6d0a359c5..677b96d3f3 100644 --- a/src/test/ui/lint/unused/issue-54538-unused-parens-lint.stderr +++ b/src/test/ui/lint/unused/issue-54538-unused-parens-lint.stderr @@ -2,151 +2,294 @@ error: unnecessary parentheses around pattern --> $DIR/issue-54538-unused-parens-lint.rs:16:9 | LL | let (a) = 0; - | ^^^ help: remove these parentheses + | ^ ^ | note: the lint level is defined here --> $DIR/issue-54538-unused-parens-lint.rs:13:9 | LL | #![deny(unused_parens)] | ^^^^^^^^^^^^^ +help: remove these parentheses + | +LL - let (a) = 0; +LL + let a = 0; + | error: unnecessary parentheses around pattern --> $DIR/issue-54538-unused-parens-lint.rs:17:9 | LL | for (a) in 0..1 {} - | ^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - for (a) in 0..1 {} +LL + for a in 0..1 {} + | error: unnecessary parentheses around pattern --> $DIR/issue-54538-unused-parens-lint.rs:18:12 | LL | if let (a) = 0 {} - | ^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - if let (a) = 0 {} +LL + if let a = 0 {} + | error: unnecessary parentheses around pattern --> $DIR/issue-54538-unused-parens-lint.rs:19:15 | LL | while let (a) = 0 {} - | ^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - while let (a) = 0 {} +LL + while let a = 0 {} + | error: unnecessary parentheses around pattern --> $DIR/issue-54538-unused-parens-lint.rs:20:12 | LL | fn foo((a): u8) {} - | ^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - fn foo((a): u8) {} +LL + fn foo(a: u8) {} + | error: unnecessary parentheses around pattern --> $DIR/issue-54538-unused-parens-lint.rs:21:14 | LL | let _ = |(a): u8| 0; - | ^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - let _ = |(a): u8| 0; +LL + let _ = |a: u8| 0; + | error: unnecessary parentheses around pattern --> $DIR/issue-54538-unused-parens-lint.rs:49:12 | LL | if let (0 | 1) = 0 {} - | ^^^^^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - if let (0 | 1) = 0 {} +LL + if let 0 | 1 = 0 {} + | error: unnecessary parentheses around pattern --> $DIR/issue-54538-unused-parens-lint.rs:50:13 | LL | if let ((0 | 1),) = (0,) {} - | ^^^^^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - if let ((0 | 1),) = (0,) {} +LL + if let (0 | 1,) = (0,) {} + | error: unnecessary parentheses around pattern --> $DIR/issue-54538-unused-parens-lint.rs:51:13 | LL | if let [(0 | 1)] = [0] {} - | ^^^^^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - if let [(0 | 1)] = [0] {} +LL + if let [0 | 1] = [0] {} + | error: unnecessary parentheses around pattern --> $DIR/issue-54538-unused-parens-lint.rs:52:16 | LL | if let 0 | (1 | 2) = 0 {} - | ^^^^^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - if let 0 | (1 | 2) = 0 {} +LL + if let 0 | 1 | 2 = 0 {} + | error: unnecessary parentheses around pattern --> $DIR/issue-54538-unused-parens-lint.rs:54:15 | LL | if let TS((0 | 1)) = TS(0) {} - | ^^^^^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - if let TS((0 | 1)) = TS(0) {} +LL + if let TS(0 | 1) = TS(0) {} + | error: unnecessary parentheses around pattern --> $DIR/issue-54538-unused-parens-lint.rs:56:20 | LL | if let NS { f: (0 | 1) } = (NS { f: 0 }) {} - | ^^^^^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - if let NS { f: (0 | 1) } = (NS { f: 0 }) {} +LL + if let NS { f: 0 | 1 } = (NS { f: 0 }) {} + | error: unnecessary parentheses around pattern --> $DIR/issue-54538-unused-parens-lint.rs:66:9 | LL | (_) => {} - | ^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - (_) => {} +LL + _ => {} + | error: unnecessary parentheses around pattern --> $DIR/issue-54538-unused-parens-lint.rs:67:9 | LL | (y) => {} - | ^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - (y) => {} +LL + y => {} + | error: unnecessary parentheses around pattern --> $DIR/issue-54538-unused-parens-lint.rs:68:9 | LL | (ref r) => {} - | ^^^^^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - (ref r) => {} +LL + ref r => {} + | error: unnecessary parentheses around pattern --> $DIR/issue-54538-unused-parens-lint.rs:69:9 | LL | (e @ 1...2) => {} - | ^^^^^^^^^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - (e @ 1...2) => {} +LL + e @ 1...2 => {} + | error: unnecessary parentheses around pattern --> $DIR/issue-54538-unused-parens-lint.rs:75:9 | LL | (e @ &(1...2)) => {} - | ^^^^^^^^^^^^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - (e @ &(1...2)) => {} +LL + e @ &(1...2) => {} + | error: unnecessary parentheses around pattern --> $DIR/issue-54538-unused-parens-lint.rs:76:10 | LL | &(_) => {} - | ^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - &(_) => {} +LL + &_ => {} + | error: unnecessary parentheses around pattern --> $DIR/issue-54538-unused-parens-lint.rs:87:9 | LL | (_) => {} - | ^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - (_) => {} +LL + _ => {} + | error: unnecessary parentheses around pattern --> $DIR/issue-54538-unused-parens-lint.rs:88:9 | LL | (y) => {} - | ^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - (y) => {} +LL + y => {} + | error: unnecessary parentheses around pattern --> $DIR/issue-54538-unused-parens-lint.rs:89:9 | LL | (ref r) => {} - | ^^^^^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - (ref r) => {} +LL + ref r => {} + | error: unnecessary parentheses around pattern --> $DIR/issue-54538-unused-parens-lint.rs:90:9 | LL | (e @ 1..=2) => {} - | ^^^^^^^^^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - (e @ 1..=2) => {} +LL + e @ 1..=2 => {} + | error: unnecessary parentheses around pattern --> $DIR/issue-54538-unused-parens-lint.rs:96:9 | LL | (e @ &(1..=2)) => {} - | ^^^^^^^^^^^^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - (e @ &(1..=2)) => {} +LL + e @ &(1..=2) => {} + | error: unnecessary parentheses around pattern --> $DIR/issue-54538-unused-parens-lint.rs:97:10 | LL | &(_) => {} - | ^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - &(_) => {} +LL + &_ => {} + | error: aborting due to 24 previous errors diff --git a/src/test/ui/lint/unused/issue-74883-unused-paren-baren-yield.stderr b/src/test/ui/lint/unused/issue-74883-unused-paren-baren-yield.stderr index 3f6260dc6e..a715093df4 100644 --- a/src/test/ui/lint/unused/issue-74883-unused-paren-baren-yield.stderr +++ b/src/test/ui/lint/unused/issue-74883-unused-paren-baren-yield.stderr @@ -2,49 +2,83 @@ error: unnecessary parentheses around `let` scrutinee expression --> $DIR/issue-74883-unused-paren-baren-yield.rs:14:29 | LL | while let Some(_) = ({yield}) {} - | ^^^^^^^^^ help: remove these parentheses + | ^ ^ | note: the lint level is defined here --> $DIR/issue-74883-unused-paren-baren-yield.rs:3:24 | LL | #![deny(unused_braces, unused_parens)] | ^^^^^^^^^^^^^ +help: remove these parentheses + | +LL - while let Some(_) = ({yield}) {} +LL + while let Some(_) = {yield} {} + | error: unnecessary parentheses around `let` scrutinee expression --> $DIR/issue-74883-unused-paren-baren-yield.rs:15:29 | LL | while let Some(_) = ((yield)) {} - | ^^^^^^^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - while let Some(_) = ((yield)) {} +LL + while let Some(_) = (yield) {} + | error: unnecessary braces around block return value --> $DIR/issue-74883-unused-paren-baren-yield.rs:16:10 | LL | {{yield}}; - | ^^^^^^^ help: remove these braces + | ^ ^ | note: the lint level is defined here --> $DIR/issue-74883-unused-paren-baren-yield.rs:3:9 | LL | #![deny(unused_braces, unused_parens)] | ^^^^^^^^^^^^^ +help: remove these braces + | +LL - {{yield}}; +LL + {yield}; + | error: unnecessary parentheses around block return value --> $DIR/issue-74883-unused-paren-baren-yield.rs:17:10 | LL | {( yield )}; - | ^^^^^^^^^ help: remove these parentheses + | ^^ ^^ + | +help: remove these parentheses + | +LL - {( yield )}; +LL + {yield}; + | error: unnecessary parentheses around block return value --> $DIR/issue-74883-unused-paren-baren-yield.rs:18:30 | LL | while let Some(_) = {(yield)} {} - | ^^^^^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - while let Some(_) = {(yield)} {} +LL + while let Some(_) = {yield} {} + | error: unnecessary braces around block return value --> $DIR/issue-74883-unused-paren-baren-yield.rs:19:30 | LL | while let Some(_) = {{yield}} {} - | ^^^^^^^ help: remove these braces + | ^ ^ + | +help: remove these braces + | +LL - while let Some(_) = {{yield}} {} +LL + while let Some(_) = {yield} {} + | error: aborting due to 6 previous errors diff --git a/src/test/ui/lint/unused/issue-88519-unused-paren.rs b/src/test/ui/lint/unused/issue-88519-unused-paren.rs new file mode 100644 index 0000000000..be02fcd3f0 --- /dev/null +++ b/src/test/ui/lint/unused/issue-88519-unused-paren.rs @@ -0,0 +1,94 @@ +// check-pass +// Make sure unused parens lint doesn't emit a false positive. +// See https://github.com/rust-lang/rust/issues/88519 +#![deny(unused_parens)] +#![feature(type_ascription)] + +// binary ops are tested in issue-71290-unused-paren-binop.rs + +mod call { + fn noop() -> u8 { 0 } + fn outside() -> u8 { + ({ noop })() + } + fn inside() -> u8 { + ({ noop }()) + } + fn outside_match() -> u8 { + (match noop { x => x })() + } + fn inside_match() -> u8 { + (match noop { x => x }()) + } + fn outside_if() -> u8 { + (if false { noop } else { noop })() + } + fn inside_if() -> u8 { + (if false { noop } else { noop }()) + } +} + +mod casts { + fn outside() -> u8 { + ({ 0 }) as u8 + } + fn inside() -> u8 { + ({ 0 } as u8) + } + fn outside_match() -> u8 { + (match 0 { x => x }) as u8 + } + fn inside_match() -> u8 { + (match 0 { x => x } as u8) + } + fn outside_if() -> u8 { + (if false { 0 } else { 0 }) as u8 + } + fn inside_if() -> u8 { + (if false { 0 } else { 0 } as u8) + } +} + +mod typeascription { + fn outside() -> u8 { + ({ 0 }): u8 + } + fn inside() -> u8 { + ({ 0 }: u8) + } + fn outside_match() -> u8 { + (match 0 { x => x }): u8 + } + fn inside_match() -> u8 { + (match 0 { x => x }: u8) + } + fn outside_if() -> u8 { + (if false { 0 } else { 0 }): u8 + } + fn inside_if() -> u8 { + (if false { 0 } else { 0 }: u8) + } +} + +mod index { + fn outside(x: &[u8]) -> u8 { + ({ x })[0] + } + fn inside(x: &[u8]) -> u8 { + ({ x }[0]) + } + fn outside_match(x: &[u8]) -> u8 { + (match x { x => x })[0] + } + fn inside_match(x: &[u8]) -> u8 { + (match x { x => x }[0]) + } + fn outside_if(x: &[u8]) -> u8 { + (if false { x } else { x })[0] + } + fn inside_if(x: &[u8]) -> u8 { + (if false { x } else { x }[0]) + } +} + +fn main() {} diff --git a/src/test/ui/lint/unused/unused-macro-rules.stderr b/src/test/ui/lint/unused/unused-macro-rules.stderr index 55072bd81b..6812a1d8f6 100644 --- a/src/test/ui/lint/unused/unused-macro-rules.stderr +++ b/src/test/ui/lint/unused/unused-macro-rules.stderr @@ -21,7 +21,7 @@ LL | | } | |_________^ ... LL | create_macro!(); - | ---------------- in this macro invocation + | --------------- in this macro invocation | = note: this error originates in the macro `create_macro` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/lint/unused_braces.stderr b/src/test/ui/lint/unused_braces.stderr index 8fa5dfde61..7d6fef00ac 100644 --- a/src/test/ui/lint/unused_braces.stderr +++ b/src/test/ui/lint/unused_braces.stderr @@ -2,43 +2,71 @@ warning: unnecessary parentheses around assigned value --> $DIR/unused_braces.rs:10:13 | LL | let _ = (7); - | ^^^ help: remove these parentheses + | ^ ^ | note: the lint level is defined here --> $DIR/unused_braces.rs:4:24 | LL | #![warn(unused_braces, unused_parens)] | ^^^^^^^^^^^^^ +help: remove these parentheses + | +LL - let _ = (7); +LL + let _ = 7; + | warning: unnecessary braces around `if` condition --> $DIR/unused_braces.rs:26:8 | LL | if { true } { - | ^^^^^^^^ help: remove these braces + | ^^ ^^ | note: the lint level is defined here --> $DIR/unused_braces.rs:4:9 | LL | #![warn(unused_braces, unused_parens)] | ^^^^^^^^^^^^^ +help: remove these braces + | +LL - if { true } { +LL + if true { + | warning: unnecessary braces around `while` condition --> $DIR/unused_braces.rs:30:11 | LL | while { false } { - | ^^^^^^^^^ help: remove these braces + | ^^ ^^ + | +help: remove these braces + | +LL - while { false } { +LL + while false { + | warning: unnecessary braces around const expression --> $DIR/unused_braces.rs:34:17 | LL | let _: [u8; { 3 }]; - | ^^^^^ help: remove these braces + | ^^ ^^ + | +help: remove these braces + | +LL - let _: [u8; { 3 }]; +LL + let _: [u8; 3]; + | warning: unnecessary braces around function argument --> $DIR/unused_braces.rs:37:13 | LL | consume({ 7 }); - | ^^^^^ help: remove these braces + | ^^ ^^ + | +help: remove these braces + | +LL - consume({ 7 }); +LL + consume(7); + | warning: 5 warnings emitted diff --git a/src/test/ui/lint/unused_braces_borrow.stderr b/src/test/ui/lint/unused_braces_borrow.stderr index f018c46fcd..5a5326cab3 100644 --- a/src/test/ui/lint/unused_braces_borrow.stderr +++ b/src/test/ui/lint/unused_braces_borrow.stderr @@ -2,13 +2,18 @@ warning: unnecessary braces around function argument --> $DIR/unused_braces_borrow.rs:24:13 | LL | consume({ a.b }); - | ^^^^^^^ help: remove these braces + | ^^ ^^ | note: the lint level is defined here --> $DIR/unused_braces_borrow.rs:4:9 | LL | #![warn(unused_braces)] | ^^^^^^^^^^^^^ +help: remove these braces + | +LL - consume({ a.b }); +LL + consume(a.b); + | warning: 1 warning emitted diff --git a/src/test/ui/lint/unused_parens_json_suggestion.stderr b/src/test/ui/lint/unused_parens_json_suggestion.stderr index 09f0fc9003..498c25d2e1 100644 --- a/src/test/ui/lint/unused_parens_json_suggestion.stderr +++ b/src/test/ui/lint/unused_parens_json_suggestion.stderr @@ -1,14 +1,19 @@ -{"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":609,"line_start":16,"line_end":16,"column_start":14,"column_end":27,"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":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)); --> $DIR/unused_parens_json_suggestion.rs:16:14 | LL | let _a = (1 / (2 + 3)); - | ^^^^^^^^^^^^^ help: remove these parentheses + | ^ ^ | note: the lint level is defined here --> $DIR/unused_parens_json_suggestion.rs:10:9 | LL | #![deny(unused_parens)] | ^^^^^^^^^^^^^ +help: remove these parentheses + | +LL - let _a = (1 / (2 + 3)); +LL + let _a = 1 / (2 + 3); + | "} {"message":"aborting due to previous error","code":null,"level":"error","spans":[],"children":[],"rendered":"error: aborting due to previous error 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 5fb67fd7c9..08291b10fc 100644 --- a/src/test/ui/lint/unused_parens_remove_json_suggestion.stderr +++ b/src/test/ui/lint/unused_parens_remove_json_suggestion.stderr @@ -1,70 +1,123 @@ -{"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":504,"line_start":17,"line_end":17,"column_start":8,"column_end":12,"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":500,"byte_end":501,"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) { - | ^^^^ help: remove these parentheses + | ^ ^ | note: the lint level is defined here --> $DIR/unused_parens_remove_json_suggestion.rs:10:9 | LL | #![deny(unused_parens)] | ^^^^^^^^^^^^^ +help: remove these parentheses + | +LL - if (_b) { +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":634,"line_start":28,"line_end":28,"column_start":7,"column_end":10,"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":631,"byte_end":632,"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) { - | ^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - if(c) { +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":714,"line_start":32,"line_end":32,"column_start":8,"column_end":11,"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":711,"byte_end":712,"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){ - | ^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - if (c){ +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":808,"line_start":36,"line_end":36,"column_start":11,"column_end":26,"is_primary":true,"text":[{"text":" while (false && true){","highlight_start":11,"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":808,"line_start":36,"line_end":36,"column_start":11,"column_end":26,"is_primary":true,"text":[{"text":" while (false && true){","highlight_start":11,"highlight_end":26}],"label":null,"suggested_replacement":"false && true ","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":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 --> $DIR/unused_parens_remove_json_suggestion.rs:36:11 | LL | while (false && true){ - | ^^^^^^^^^^^^^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - while (false && true){ +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":824,"line_start":37,"line_end":37,"column_start":12,"column_end":15,"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":821,"byte_end":822,"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) { - | ^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - if (c) { +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":933,"line_start":43,"line_end":43,"column_start":10,"column_end":25,"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":918,"byte_end":919,"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) { - | ^^^^^^^^^^^^^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - while(true && false) { +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":995,"line_start":44,"line_end":44,"column_start":18,"column_end":26,"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":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){ --> $DIR/unused_parens_remove_json_suggestion.rs:44:18 | LL | for _ in (0 .. 3){ - | ^^^^^^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - for _ in (0 .. 3){ +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":1096,"line_start":49,"line_end":49,"column_start":14,"column_end":22,"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":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) { --> $DIR/unused_parens_remove_json_suggestion.rs:49:14 | LL | for _ in (0 .. 3) { - | ^^^^^^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - for _ in (0 .. 3) { +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":1162,"line_start":50,"line_end":50,"column_start":15,"column_end":30,"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":1147,"byte_end":1148,"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) { - | ^^^^^^^^^^^^^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - while (true && false) { +LL + while true && false { + | "} {"message":"aborting due to 9 previous errors","code":null,"level":"error","spans":[],"children":[],"rendered":"error: aborting due to 9 previous errors diff --git a/src/test/ui/list.rs b/src/test/ui/list.rs index 2ac5733b41..cb83d4103d 100644 --- a/src/test/ui/list.rs +++ b/src/test/ui/list.rs @@ -3,8 +3,8 @@ #![allow(non_camel_case_types)] // pretty-expanded FIXME #23616 -#![feature(box_syntax)] - enum list { cons(isize, Box), nil, } -pub fn main() { list::cons(10, box list::cons(11, box list::cons(12, box list::nil))); } +pub fn main() { + list::cons(10, Box::new(list::cons(11, Box::new(list::cons(12, Box::new(list::nil)))))); +} diff --git a/src/test/ui/liveness/liveness-move-call-arg.rs b/src/test/ui/liveness/liveness-move-call-arg.rs index 98d12f5747..1bc2ea6b9f 100644 --- a/src/test/ui/liveness/liveness-move-call-arg.rs +++ b/src/test/ui/liveness/liveness-move-call-arg.rs @@ -1,10 +1,10 @@ -#![feature(box_syntax)] - fn take(_x: Box) {} + fn main() { - let x: Box = box 25; + let x: Box = Box::new(25); + loop { take(x); //~ ERROR use of moved value: `x` } diff --git a/src/test/ui/liveness/liveness-move-call-arg.stderr b/src/test/ui/liveness/liveness-move-call-arg.stderr index 5ea5c40f2a..7c0e916edd 100644 --- a/src/test/ui/liveness/liveness-move-call-arg.stderr +++ b/src/test/ui/liveness/liveness-move-call-arg.stderr @@ -1,9 +1,9 @@ error[E0382]: use of moved value: `x` --> $DIR/liveness-move-call-arg.rs:9:14 | -LL | let x: Box = box 25; +LL | let x: Box = Box::new(25); | - move occurs because `x` has type `Box`, which does not implement the `Copy` trait -LL | loop { +... LL | take(x); | ^ value moved here, in previous iteration of loop diff --git a/src/test/ui/liveness/liveness-move-in-loop.rs b/src/test/ui/liveness/liveness-move-in-loop.rs index eb3288a28e..064be14d6d 100644 --- a/src/test/ui/liveness/liveness-move-in-loop.rs +++ b/src/test/ui/liveness/liveness-move-in-loop.rs @@ -1,8 +1,8 @@ -#![feature(box_syntax)] - fn main() { - let y: Box = box 42; + + let y: Box = 42.into(); let mut x: Box; + loop { println!("{}", y); loop { diff --git a/src/test/ui/liveness/liveness-move-in-loop.stderr b/src/test/ui/liveness/liveness-move-in-loop.stderr index 66b6373e45..832d4f8fa0 100644 --- a/src/test/ui/liveness/liveness-move-in-loop.stderr +++ b/src/test/ui/liveness/liveness-move-in-loop.stderr @@ -1,7 +1,7 @@ error[E0382]: use of moved value: `y` --> $DIR/liveness-move-in-loop.rs:11:25 | -LL | let y: Box = box 42; +LL | let y: Box = 42.into(); | - move occurs because `y` has type `Box`, which does not implement the `Copy` trait ... LL | x = y; diff --git a/src/test/ui/liveness/liveness-move-in-while.rs b/src/test/ui/liveness/liveness-move-in-while.rs index 9f3ebf1362..7c0cd282c9 100644 --- a/src/test/ui/liveness/liveness-move-in-while.rs +++ b/src/test/ui/liveness/liveness-move-in-while.rs @@ -1,8 +1,8 @@ -#![feature(box_syntax)] - fn main() { - let y: Box = box 42; + + let y: Box = 42.into(); let mut x: Box; + loop { println!("{}", y); //~ ERROR borrow of moved value: `y` while true { while true { while true { x = y; x.clone(); } } } diff --git a/src/test/ui/liveness/liveness-move-in-while.stderr b/src/test/ui/liveness/liveness-move-in-while.stderr index 92e0f37252..6a8f239bd0 100644 --- a/src/test/ui/liveness/liveness-move-in-while.stderr +++ b/src/test/ui/liveness/liveness-move-in-while.stderr @@ -21,7 +21,7 @@ LL | while true { while true { while true { x = y; x.clone(); } } } error[E0382]: borrow of moved value: `y` --> $DIR/liveness-move-in-while.rs:7:24 | -LL | let y: Box = box 42; +LL | let y: Box = 42.into(); | - move occurs because `y` has type `Box`, which does not implement the `Copy` trait ... LL | println!("{}", y); diff --git a/src/test/ui/liveness/liveness-return-last-stmt-semi.stderr b/src/test/ui/liveness/liveness-return-last-stmt-semi.stderr index d9dac5de62..0b33d8d0a2 100644 --- a/src/test/ui/liveness/liveness-return-last-stmt-semi.stderr +++ b/src/test/ui/liveness/liveness-return-last-stmt-semi.stderr @@ -28,13 +28,12 @@ error[E0308]: mismatched types --> $DIR/liveness-return-last-stmt-semi.rs:4:41 | LL | macro_rules! test { () => { fn foo() -> i32 { 1; } } } - | --- ^^^ - help: consider removing this semicolon - | | | - | | expected `i32`, found `()` + | --- ^^^ expected `i32`, found `()` + | | | implicitly returns `()` as its body has no tail or `return` expression ... LL | test!(); - | -------- in this macro invocation + | ------- in this macro invocation | = note: this error originates in the macro `test` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/liveness/liveness-use-after-move.rs b/src/test/ui/liveness/liveness-use-after-move.rs index 5263e29360..46102ca1eb 100644 --- a/src/test/ui/liveness/liveness-use-after-move.rs +++ b/src/test/ui/liveness/liveness-use-after-move.rs @@ -1,8 +1,8 @@ -#![feature(box_syntax)] - fn main() { - let x: Box<_> = box 5; + + let x: Box<_> = 5.into(); let y = x; + println!("{}", *x); //~ ERROR borrow of moved value: `x` y.clone(); } diff --git a/src/test/ui/liveness/liveness-use-after-move.stderr b/src/test/ui/liveness/liveness-use-after-move.stderr index 3977a3f413..292ce013dc 100644 --- a/src/test/ui/liveness/liveness-use-after-move.stderr +++ b/src/test/ui/liveness/liveness-use-after-move.stderr @@ -1,10 +1,11 @@ error[E0382]: borrow of moved value: `x` --> $DIR/liveness-use-after-move.rs:6:20 | -LL | let x: Box<_> = box 5; +LL | let x: Box<_> = 5.into(); | - move occurs because `x` has type `Box`, which does not implement the `Copy` trait LL | let y = x; | - value moved here +LL | LL | println!("{}", *x); | ^^ value borrowed here after move diff --git a/src/test/ui/llvm-asm/inline-asm-bad-constraint.stderr b/src/test/ui/llvm-asm/inline-asm-bad-constraint.stderr index 5efc38522b..a624829f14 100644 --- a/src/test/ui/llvm-asm/inline-asm-bad-constraint.stderr +++ b/src/test/ui/llvm-asm/inline-asm-bad-constraint.stderr @@ -18,7 +18,7 @@ error[E0668]: malformed inline assembly --> $DIR/inline-asm-bad-constraint.rs:38:9 | LL | llvm_asm!("addb $1, $0" : "={rax}"((0i32, rax))); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: this error originates in the macro `llvm_asm` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/issues/issue-37433.rs b/src/test/ui/llvm-asm/issue-37433.rs similarity index 100% rename from src/test/ui/issues/issue-37433.rs rename to src/test/ui/llvm-asm/issue-37433.rs diff --git a/src/test/ui/issues/issue-37433.stderr b/src/test/ui/llvm-asm/issue-37433.stderr similarity index 100% rename from src/test/ui/issues/issue-37433.stderr rename to src/test/ui/llvm-asm/issue-37433.stderr diff --git a/src/test/ui/llvm-asm/issue-62046.stderr b/src/test/ui/llvm-asm/issue-62046.stderr index 73842a4b9e..ae271afe26 100644 --- a/src/test/ui/llvm-asm/issue-62046.stderr +++ b/src/test/ui/llvm-asm/issue-62046.stderr @@ -2,7 +2,7 @@ error[E0668]: malformed inline assembly --> $DIR/issue-62046.rs:9:9 | LL | llvm_asm!("nop" : "+r"("r15")); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: this error originates in the macro `llvm_asm` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/llvm-asm/llvm-asm-parse-errors.stderr b/src/test/ui/llvm-asm/llvm-asm-parse-errors.stderr index 10cb4fcfe4..715d05beaa 100644 --- a/src/test/ui/llvm-asm/llvm-asm-parse-errors.stderr +++ b/src/test/ui/llvm-asm/llvm-asm-parse-errors.stderr @@ -2,7 +2,7 @@ error: macro requires a string literal as an argument --> $DIR/llvm-asm-parse-errors.rs:5:5 | LL | llvm_asm!(); - | ^^^^^^^^^^^^ string literal required + | ^^^^^^^^^^^ string literal required error: expected string literal --> $DIR/llvm-asm-parse-errors.rs:6:23 diff --git a/src/test/ui/loops/loops-reject-duplicate-labels-2.rs b/src/test/ui/loops/loops-reject-duplicate-labels-2.rs index 3a860f508f..68a19a8f6f 100644 --- a/src/test/ui/loops/loops-reject-duplicate-labels-2.rs +++ b/src/test/ui/loops/loops-reject-duplicate-labels-2.rs @@ -1,7 +1,7 @@ // check-pass +#![feature(label_break_value)] - -// Issue #21633: reject duplicate loop labels in function bodies. +// Issue #21633: reject duplicate loop labels and block labels in function bodies. // // This is testing the generalization (to the whole function body) // discussed here: @@ -26,6 +26,8 @@ pub fn foo() { { 'lt: loop { break; } } { 'lt: while let Some(_) = None:: { break; } } //~^ WARN label name `'lt` shadows a label name that is already in scope + { 'bl: {} } + { 'bl: {} } //~ WARN label name `'bl` shadows a label name that is already in scope } diff --git a/src/test/ui/loops/loops-reject-duplicate-labels-2.stderr b/src/test/ui/loops/loops-reject-duplicate-labels-2.stderr index 6c53d04e10..2c372fcff7 100644 --- a/src/test/ui/loops/loops-reject-duplicate-labels-2.stderr +++ b/src/test/ui/loops/loops-reject-duplicate-labels-2.stderr @@ -62,5 +62,13 @@ LL | { 'lt: loop { break; } } LL | { 'lt: while let Some(_) = None:: { break; } } | ^^^ label `'lt` already in scope -warning: 8 warnings emitted +warning: label name `'bl` shadows a label name that is already in scope + --> $DIR/loops-reject-duplicate-labels-2.rs:30:7 + | +LL | { 'bl: {} } + | --- first declared here +LL | { 'bl: {} } + | ^^^ label `'bl` already in scope + +warning: 9 warnings emitted diff --git a/src/test/ui/loops/loops-reject-duplicate-labels.rs b/src/test/ui/loops/loops-reject-duplicate-labels.rs index d9334ce385..c34bcf3df1 100644 --- a/src/test/ui/loops/loops-reject-duplicate-labels.rs +++ b/src/test/ui/loops/loops-reject-duplicate-labels.rs @@ -1,8 +1,7 @@ // check-pass +#![feature(label_break_value)] - -// Issue #21633: reject duplicate loop labels in function bodies. -// This is testing the exact cases that are in the issue description. +// Issue #21633: reject duplicate loop labels and block labels in function bodies. #[allow(unused_labels)] fn foo() { @@ -24,6 +23,8 @@ fn foo() { 'lt: loop { break; } 'lt: while let Some(_) = None:: { break; } //~^ WARN label name `'lt` shadows a label name that is already in scope + 'bl: {} + 'bl: {} //~ WARN label name `'bl` shadows a label name that is already in scope } // Note however that it is okay for the same label to be reused in @@ -33,6 +34,8 @@ struct S; impl S { fn m1(&self) { 'okay: loop { break 'okay; } } fn m2(&self) { 'okay: loop { break 'okay; } } + fn m3(&self) { 'okay: { break 'okay; } } + fn m4(&self) { 'okay: { break 'okay; } } } @@ -40,5 +43,7 @@ pub fn main() { let s = S; s.m1(); s.m2(); + s.m3(); + s.m4(); foo(); } diff --git a/src/test/ui/loops/loops-reject-duplicate-labels.stderr b/src/test/ui/loops/loops-reject-duplicate-labels.stderr index 5bdf64849f..3bf3af763e 100644 --- a/src/test/ui/loops/loops-reject-duplicate-labels.stderr +++ b/src/test/ui/loops/loops-reject-duplicate-labels.stderr @@ -1,5 +1,5 @@ warning: label name `'fl` shadows a label name that is already in scope - --> $DIR/loops-reject-duplicate-labels.rs:10:5 + --> $DIR/loops-reject-duplicate-labels.rs:9:5 | LL | 'fl: for _ in 0..10 { break; } | --- first declared here @@ -7,7 +7,7 @@ LL | 'fl: loop { break; } | ^^^ label `'fl` already in scope warning: label name `'lf` shadows a label name that is already in scope - --> $DIR/loops-reject-duplicate-labels.rs:13:5 + --> $DIR/loops-reject-duplicate-labels.rs:12:5 | LL | 'lf: loop { break; } | --- first declared here @@ -15,7 +15,7 @@ LL | 'lf: for _ in 0..10 { break; } | ^^^ label `'lf` already in scope warning: label name `'wl` shadows a label name that is already in scope - --> $DIR/loops-reject-duplicate-labels.rs:15:5 + --> $DIR/loops-reject-duplicate-labels.rs:14:5 | LL | 'wl: while 2 > 1 { break; } | --- first declared here @@ -23,7 +23,7 @@ LL | 'wl: loop { break; } | ^^^ label `'wl` already in scope warning: label name `'lw` shadows a label name that is already in scope - --> $DIR/loops-reject-duplicate-labels.rs:17:5 + --> $DIR/loops-reject-duplicate-labels.rs:16:5 | LL | 'lw: loop { break; } | --- first declared here @@ -31,7 +31,7 @@ LL | 'lw: while 2 > 1 { break; } | ^^^ label `'lw` already in scope warning: label name `'fw` shadows a label name that is already in scope - --> $DIR/loops-reject-duplicate-labels.rs:19:5 + --> $DIR/loops-reject-duplicate-labels.rs:18:5 | LL | 'fw: for _ in 0..10 { break; } | --- first declared here @@ -39,7 +39,7 @@ LL | 'fw: while 2 > 1 { break; } | ^^^ label `'fw` already in scope warning: label name `'wf` shadows a label name that is already in scope - --> $DIR/loops-reject-duplicate-labels.rs:21:5 + --> $DIR/loops-reject-duplicate-labels.rs:20:5 | LL | 'wf: while 2 > 1 { break; } | --- first declared here @@ -47,7 +47,7 @@ LL | 'wf: for _ in 0..10 { break; } | ^^^ label `'wf` already in scope warning: label name `'tl` shadows a label name that is already in scope - --> $DIR/loops-reject-duplicate-labels.rs:23:5 + --> $DIR/loops-reject-duplicate-labels.rs:22:5 | LL | 'tl: while let Some(_) = None:: { break; } | --- first declared here @@ -55,12 +55,20 @@ LL | 'tl: loop { break; } | ^^^ label `'tl` already in scope warning: label name `'lt` shadows a label name that is already in scope - --> $DIR/loops-reject-duplicate-labels.rs:25:5 + --> $DIR/loops-reject-duplicate-labels.rs:24:5 | LL | 'lt: loop { break; } | --- first declared here LL | 'lt: while let Some(_) = None:: { break; } | ^^^ label `'lt` already in scope -warning: 8 warnings emitted +warning: label name `'bl` shadows a label name that is already in scope + --> $DIR/loops-reject-duplicate-labels.rs:27:5 + | +LL | 'bl: {} + | --- first declared here +LL | 'bl: {} + | ^^^ label `'bl` already in scope + +warning: 9 warnings emitted diff --git a/src/test/ui/loops/loops-reject-lifetime-shadowing-label.rs b/src/test/ui/loops/loops-reject-lifetime-shadowing-label.rs index 3212b78b08..ce2d07eb06 100644 --- a/src/test/ui/loops/loops-reject-lifetime-shadowing-label.rs +++ b/src/test/ui/loops/loops-reject-lifetime-shadowing-label.rs @@ -1,10 +1,10 @@ // check-pass - +#![feature(label_break_value)] #![allow(dead_code, unused_variables)] -// Issue #21633: reject duplicate loop labels in function bodies. +// Issue #21633: reject duplicate loop labels and block labels in function bodies. // -// Test rejection of lifetimes in *expressions* that shadow loop labels. +// Test rejection of lifetimes in *expressions* that shadow labels. fn foo() { // Reusing lifetime `'a` in function item is okay. @@ -23,8 +23,13 @@ fn foo() { assert_eq!((*b)(&z), z); break 'a; } -} + 'b: { + let b = Box::new(|x: &()| ()) as Box Fn(&'b ())>; + //~^ WARN lifetime name `'b` shadows a label name that is already in scope + break 'b; + } +} pub fn main() { foo(); diff --git a/src/test/ui/loops/loops-reject-lifetime-shadowing-label.stderr b/src/test/ui/loops/loops-reject-lifetime-shadowing-label.stderr index dcee1a8009..9702b71600 100644 --- a/src/test/ui/loops/loops-reject-lifetime-shadowing-label.stderr +++ b/src/test/ui/loops/loops-reject-lifetime-shadowing-label.stderr @@ -6,5 +6,13 @@ LL | 'a: loop { LL | let b = Box::new(|x: &i8| *x) as Box Fn(&'a i8) -> i8>; | ^^ label `'a` already in scope -warning: 1 warning emitted +warning: lifetime name `'b` shadows a label name that is already in scope + --> $DIR/loops-reject-lifetime-shadowing-label.rs:28:55 + | +LL | 'b: { + | -- first declared here +LL | let b = Box::new(|x: &()| ()) as Box Fn(&'b ())>; + | ^^ label `'b` already in scope + +warning: 2 warnings emitted diff --git a/src/test/ui/lub-glb/old-lub-glb-hr-noteq1.nll.stderr b/src/test/ui/lub-glb/old-lub-glb-hr-noteq1.nll.stderr index 3fdc2da9f1..5ac392914e 100644 --- a/src/test/ui/lub-glb/old-lub-glb-hr-noteq1.nll.stderr +++ b/src/test/ui/lub-glb/old-lub-glb-hr-noteq1.nll.stderr @@ -4,8 +4,8 @@ error[E0308]: mismatched types LL | _ => y, | ^ one type is more general than the other | - = note: expected fn pointer `for<'r, 's> fn(&'r u8, &'s u8) -> &'r u8` - found fn pointer `for<'r> fn(&'r u8, &'r u8) -> &'r u8` + = note: expected fn pointer `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8` + found fn pointer `for<'a> fn(&'a u8, &'a u8) -> &'a u8` error: aborting due to previous error diff --git a/src/test/ui/lub-glb/old-lub-glb-object.nll.stderr b/src/test/ui/lub-glb/old-lub-glb-object.nll.stderr index ad14d6b752..355f0754ab 100644 --- a/src/test/ui/lub-glb/old-lub-glb-object.nll.stderr +++ b/src/test/ui/lub-glb/old-lub-glb-object.nll.stderr @@ -4,8 +4,8 @@ error[E0308]: mismatched types LL | _ => y, | ^ one type is more general than the other | - = note: expected trait object `dyn for<'r, 's> Foo<&'r u8, &'s u8>` - found trait object `dyn for<'r> Foo<&'r u8, &'r u8>` + = note: expected trait object `dyn for<'a, 'b> Foo<&'a u8, &'b u8>` + found trait object `dyn for<'a> Foo<&'a u8, &'a u8>` error[E0308]: mismatched types --> $DIR/old-lub-glb-object.rs:10:14 @@ -13,8 +13,8 @@ error[E0308]: mismatched types LL | _ => y, | ^ one type is more general than the other | - = note: expected trait object `dyn for<'r, 's> Foo<&'r u8, &'s u8>` - found trait object `dyn for<'r> Foo<&'r u8, &'r u8>` + = note: expected trait object `dyn for<'a, 'b> Foo<&'a u8, &'b u8>` + found trait object `dyn for<'a> Foo<&'a u8, &'a u8>` error: aborting due to 2 previous errors diff --git a/src/test/ui/lub-if.nll.stderr b/src/test/ui/lub-if.nll.stderr index 1ef479fcd4..832688f516 100644 --- a/src/test/ui/lub-if.nll.stderr +++ b/src/test/ui/lub-if.nll.stderr @@ -6,8 +6,6 @@ LL | pub fn opt_str2<'a>(maybestr: &'a Option) -> &'static str { ... LL | s | ^ returning this value requires that `'a` must outlive `'static` - | - = help: consider replacing `'a` with `'static` error: lifetime may not live long enough --> $DIR/lub-if.rs:35:9 @@ -17,8 +15,6 @@ LL | pub fn opt_str3<'a>(maybestr: &'a Option) -> &'static str { ... LL | s | ^ returning this value requires that `'a` must outlive `'static` - | - = help: consider replacing `'a` with `'static` error: aborting due to 2 previous errors diff --git a/src/test/ui/lub-if.stderr b/src/test/ui/lub-if.stderr index 0a4744013a..a12c48582c 100644 --- a/src/test/ui/lub-if.stderr +++ b/src/test/ui/lub-if.stderr @@ -5,7 +5,7 @@ LL | s | ^ | = note: ...the reference is valid for the static lifetime... -note: ...but the borrowed content is only valid for the lifetime `'a` as defined on the function body at 23:17 +note: ...but the borrowed content is only valid for the lifetime `'a` as defined here --> $DIR/lub-if.rs:23:17 | LL | pub fn opt_str2<'a>(maybestr: &'a Option) -> &'static str { @@ -18,7 +18,7 @@ LL | s | ^ | = note: ...the reference is valid for the static lifetime... -note: ...but the borrowed content is only valid for the lifetime `'a` as defined on the function body at 32:17 +note: ...but the borrowed content is only valid for the lifetime `'a` as defined here --> $DIR/lub-if.rs:32:17 | LL | pub fn opt_str3<'a>(maybestr: &'a Option) -> &'static str { diff --git a/src/test/ui/lub-match.nll.stderr b/src/test/ui/lub-match.nll.stderr index ed551da54f..3a344a77d2 100644 --- a/src/test/ui/lub-match.nll.stderr +++ b/src/test/ui/lub-match.nll.stderr @@ -6,8 +6,6 @@ LL | pub fn opt_str2<'a>(maybestr: &'a Option) -> &'static str { ... LL | s | ^ returning this value requires that `'a` must outlive `'static` - | - = help: consider replacing `'a` with `'static` error: lifetime may not live long enough --> $DIR/lub-match.rs:39:13 @@ -17,8 +15,6 @@ LL | pub fn opt_str3<'a>(maybestr: &'a Option) -> &'static str { ... LL | s | ^ returning this value requires that `'a` must outlive `'static` - | - = help: consider replacing `'a` with `'static` error: aborting due to 2 previous errors diff --git a/src/test/ui/lub-match.stderr b/src/test/ui/lub-match.stderr index 168a389446..04d50f5ebf 100644 --- a/src/test/ui/lub-match.stderr +++ b/src/test/ui/lub-match.stderr @@ -5,7 +5,7 @@ LL | s | ^ | = note: ...the reference is valid for the static lifetime... -note: ...but the borrowed content is only valid for the lifetime `'a` as defined on the function body at 25:17 +note: ...but the borrowed content is only valid for the lifetime `'a` as defined here --> $DIR/lub-match.rs:25:17 | LL | pub fn opt_str2<'a>(maybestr: &'a Option) -> &'static str { @@ -18,7 +18,7 @@ LL | s | ^ | = note: ...the reference is valid for the static lifetime... -note: ...but the borrowed content is only valid for the lifetime `'a` as defined on the function body at 35:17 +note: ...but the borrowed content is only valid for the lifetime `'a` as defined here --> $DIR/lub-match.rs:35:17 | LL | pub fn opt_str3<'a>(maybestr: &'a Option) -> &'static str { diff --git a/src/test/ui/macro_backtrace/main.-Zmacro-backtrace.stderr b/src/test/ui/macro_backtrace/main.-Zmacro-backtrace.stderr index 4383759514..1d57b32d47 100644 --- a/src/test/ui/macro_backtrace/main.-Zmacro-backtrace.stderr +++ b/src/test/ui/macro_backtrace/main.-Zmacro-backtrace.stderr @@ -8,7 +8,7 @@ LL | | } | |_- in this expansion of `pong!` ... LL | pong!(); - | -------- in this macro invocation + | ------- in this macro invocation error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `error` --> $DIR/main.rs:10:20 @@ -20,14 +20,14 @@ LL | | } | |__- in this expansion of `pong!` (#2) ... LL | ping!(); - | -------- in this macro invocation (#1) + | ------- in this macro invocation (#1) | ::: $DIR/auxiliary/ping.rs:5:1 | LL | / macro_rules! ping { LL | | () => { LL | | pong!(); - | | -------- in this macro invocation (#2) + | | ------- in this macro invocation (#2) LL | | } LL | | } | |_- in this expansion of `ping!` (#1) @@ -42,14 +42,14 @@ LL | | } | |__- in this expansion of `pong!` (#5) ... LL | deep!(); - | -------- in this macro invocation (#1) + | ------- in this macro invocation (#1) | ::: $DIR/auxiliary/ping.rs:5:1 | LL | / macro_rules! ping { LL | | () => { LL | | pong!(); - | | -------- in this macro invocation (#5) + | | ------- in this macro invocation (#5) LL | | } LL | | } | |_- in this expansion of `ping!` (#4) @@ -57,7 +57,7 @@ LL | | } LL | / macro_rules! deep { LL | | () => { LL | | foo!(); - | | ------- in this macro invocation (#2) + | | ------ in this macro invocation (#2) LL | | } LL | | } | |__- in this expansion of `deep!` (#1) @@ -65,7 +65,7 @@ LL | | } LL | / macro_rules! foo { LL | | () => { LL | | bar!(); - | | ------- in this macro invocation (#3) + | | ------ in this macro invocation (#3) LL | | } LL | | } | |__- in this expansion of `foo!` (#2) @@ -73,7 +73,7 @@ LL | | } LL | / macro_rules! bar { LL | | () => { LL | | ping!(); - | | -------- in this macro invocation (#4) + | | ------- in this macro invocation (#4) LL | | } LL | | } | |__- in this expansion of `bar!` (#3) diff --git a/src/test/ui/macro_backtrace/main.default.stderr b/src/test/ui/macro_backtrace/main.default.stderr index f03637abb6..fa9b4090dd 100644 --- a/src/test/ui/macro_backtrace/main.default.stderr +++ b/src/test/ui/macro_backtrace/main.default.stderr @@ -5,7 +5,7 @@ LL | () => { syntax error }; | ^^^^^ expected one of 8 possible tokens ... LL | pong!(); - | -------- in this macro invocation + | ------- in this macro invocation | = note: this error originates in the macro `pong` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -16,7 +16,7 @@ LL | () => { syntax error }; | ^^^^^ expected one of 8 possible tokens ... LL | ping!(); - | -------- in this macro invocation + | ------- in this macro invocation | = note: this error originates in the macro `pong` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -27,7 +27,7 @@ LL | () => { syntax error }; | ^^^^^ expected one of 8 possible tokens ... LL | deep!(); - | -------- in this macro invocation + | ------- in this macro invocation | = note: this error originates in the macro `pong` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/macros/assert-trailing-junk.stderr b/src/test/ui/macros/assert-trailing-junk.stderr index 84a6768b3f..eb001429c5 100644 --- a/src/test/ui/macros/assert-trailing-junk.stderr +++ b/src/test/ui/macros/assert-trailing-junk.stderr @@ -38,7 +38,7 @@ error: macro requires an expression as an argument --> $DIR/assert-trailing-junk.rs:19:5 | LL | assert!(true;); - | ^^^^^^^^^^^^-^^ + | ^^^^^^^^^^^^-^ | | | help: try removing semicolon diff --git a/src/test/ui/macros/assert.stderr b/src/test/ui/macros/assert.stderr index c7566d8931..57e5c77a56 100644 --- a/src/test/ui/macros/assert.stderr +++ b/src/test/ui/macros/assert.stderr @@ -2,7 +2,7 @@ error: macro requires a boolean expression as an argument --> $DIR/assert.rs:2:5 | LL | assert!(); - | ^^^^^^^^^^ boolean expression required + | ^^^^^^^^^ boolean expression required error: expected expression, found keyword `struct` --> $DIR/assert.rs:3:13 @@ -14,7 +14,7 @@ error: macro requires a boolean expression as an argument --> $DIR/assert.rs:4:5 | LL | debug_assert!(); - | ^^^^^^^^^^^^^^^^ boolean expression required + | ^^^^^^^^^^^^^^^ boolean expression required | = note: this error originates in the macro `debug_assert` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/auxiliary/define-macro.rs b/src/test/ui/macros/auxiliary/define-macro.rs similarity index 100% rename from src/test/ui/auxiliary/define-macro.rs rename to src/test/ui/macros/auxiliary/define-macro.rs diff --git a/src/test/ui/macros/auxiliary/macro-def-site-super.rs b/src/test/ui/macros/auxiliary/macro-def-site-super.rs new file mode 100644 index 0000000000..cab747c2c0 --- /dev/null +++ b/src/test/ui/macros/auxiliary/macro-def-site-super.rs @@ -0,0 +1,13 @@ +#![feature(decl_macro)] + +mod inner1 { + pub struct Struct {} + + pub mod inner2 { + pub macro mac() { + super::Struct + } + } +} + +pub use inner1::inner2 as public; diff --git a/src/test/ui/macros/bang-after-name.fixed b/src/test/ui/macros/bang-after-name.fixed new file mode 100644 index 0000000000..c107ddd5d0 --- /dev/null +++ b/src/test/ui/macros/bang-after-name.fixed @@ -0,0 +1,8 @@ +// run-rustfix +#[allow(unused_macros)] + +macro_rules! foo { //~ ERROR macro names aren't followed by a `!` + () => {}; +} + +fn main() {} diff --git a/src/test/ui/macros/bang-after-name.rs b/src/test/ui/macros/bang-after-name.rs new file mode 100644 index 0000000000..7654d8c440 --- /dev/null +++ b/src/test/ui/macros/bang-after-name.rs @@ -0,0 +1,8 @@ +// run-rustfix +#[allow(unused_macros)] + +macro_rules! foo! { //~ ERROR macro names aren't followed by a `!` + () => {}; +} + +fn main() {} diff --git a/src/test/ui/macros/bang-after-name.stderr b/src/test/ui/macros/bang-after-name.stderr new file mode 100644 index 0000000000..f609c4943e --- /dev/null +++ b/src/test/ui/macros/bang-after-name.stderr @@ -0,0 +1,8 @@ +error: macro names aren't followed by a `!` + --> $DIR/bang-after-name.rs:4:17 + | +LL | macro_rules! foo! { + | ^ help: remove the `!` + +error: aborting due to previous error + diff --git a/src/test/ui/macros/cfg.stderr b/src/test/ui/macros/cfg.stderr index a8e96c0137..4785ef9aae 100644 --- a/src/test/ui/macros/cfg.stderr +++ b/src/test/ui/macros/cfg.stderr @@ -2,7 +2,7 @@ error: macro requires a cfg-pattern as an argument --> $DIR/cfg.rs:2:5 | LL | cfg!(); - | ^^^^^^^ cfg-pattern required + | ^^^^^^ cfg-pattern required | = note: this error originates in the macro `cfg` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/macros/format-parse-errors.stderr b/src/test/ui/macros/format-parse-errors.stderr index ef914cc1c6..c0e766681f 100644 --- a/src/test/ui/macros/format-parse-errors.stderr +++ b/src/test/ui/macros/format-parse-errors.stderr @@ -2,7 +2,7 @@ error: requires at least a format string argument --> $DIR/format-parse-errors.rs:4:5 | LL | format!(); - | ^^^^^^^^^^ + | ^^^^^^^^^ | = note: this error originates in the macro `$crate::__export::format_args` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/macros/global-asm.stderr b/src/test/ui/macros/global-asm.stderr index a8621a0c51..3c26ec65aa 100644 --- a/src/test/ui/macros/global-asm.stderr +++ b/src/test/ui/macros/global-asm.stderr @@ -2,7 +2,7 @@ error: requires at least a template string argument --> $DIR/global-asm.rs:4:5 | LL | global_asm!(); - | ^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ error: expected expression, found keyword `struct` --> $DIR/global-asm.rs:5:17 diff --git a/src/test/ui/macros/issue-54441.stderr b/src/test/ui/macros/issue-54441.stderr index 752916e665..bbbca211b8 100644 --- a/src/test/ui/macros/issue-54441.stderr +++ b/src/test/ui/macros/issue-54441.stderr @@ -5,7 +5,7 @@ LL | let | ^^^ ... LL | m!(); - | ----- caused by the macro expansion here + | ---- caused by the macro expansion here | = note: the usage of `m!` is likely invalid in foreign item context diff --git a/src/test/ui/macros/issue-78325-inconsistent-resolution.stderr b/src/test/ui/macros/issue-78325-inconsistent-resolution.stderr index 2934281cdd..53a0a0793b 100644 --- a/src/test/ui/macros/issue-78325-inconsistent-resolution.stderr +++ b/src/test/ui/macros/issue-78325-inconsistent-resolution.stderr @@ -5,7 +5,7 @@ LL | extern crate std as core; | ^^^^^^^^^^^^^^^^^^^^^^^^^ ... LL | define_other_core!(); - | --------------------- in this macro invocation + | -------------------- in this macro invocation | = note: this error originates in the macro `define_other_core` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/macros/issue-84632-eager-expansion-recursion-limit.rs b/src/test/ui/macros/issue-84632-eager-expansion-recursion-limit.rs index 9139775c80..7a1e62d49d 100644 --- a/src/test/ui/macros/issue-84632-eager-expansion-recursion-limit.rs +++ b/src/test/ui/macros/issue-84632-eager-expansion-recursion-limit.rs @@ -7,7 +7,7 @@ macro_rules! a { (A) => (concat!("", a!())); (A, $($A:ident),*) => (concat!("", a!($($A),*))) //~^ ERROR recursion limit reached - //~| HELP consider adding + //~| HELP consider increasing the recursion limit } fn main() { diff --git a/src/test/ui/macros/issue-84632-eager-expansion-recursion-limit.stderr b/src/test/ui/macros/issue-84632-eager-expansion-recursion-limit.stderr index e6067e3334..e266617bd2 100644 --- a/src/test/ui/macros/issue-84632-eager-expansion-recursion-limit.stderr +++ b/src/test/ui/macros/issue-84632-eager-expansion-recursion-limit.stderr @@ -5,9 +5,9 @@ LL | (A, $($A:ident),*) => (concat!("", a!($($A),*))) | ^^^^^^^^^^^^^^^^^^^^^^^^ ... LL | a!(A, A, A, A, A, A, A, A, A, A, A); - | ------------------------------------ in this macro invocation + | ----------------------------------- in this macro invocation | - = help: consider adding a `#![recursion_limit="30"]` attribute to your crate (`issue_84632_eager_expansion_recursion_limit`) + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "30"]` attribute to your crate (`issue_84632_eager_expansion_recursion_limit`) = note: this error originates in the macro `a` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to previous error diff --git a/src/test/ui/macros/macro-at-most-once-rep-2015.stderr b/src/test/ui/macros/macro-at-most-once-rep-2015.stderr index f9871ab8ff..9a3df858e5 100644 --- a/src/test/ui/macros/macro-at-most-once-rep-2015.stderr +++ b/src/test/ui/macros/macro-at-most-once-rep-2015.stderr @@ -38,7 +38,7 @@ LL | macro_rules! barplus { | -------------------- when calling this macro ... LL | barplus!(); - | ^^^^^^^^^^^ missing tokens in macro arguments + | ^^^^^^^^^^ missing tokens in macro arguments error: unexpected end of macro invocation --> $DIR/macro-at-most-once-rep-2015.rs:30:15 @@ -74,7 +74,7 @@ LL | macro_rules! barstar { | -------------------- when calling this macro ... LL | barstar!(); - | ^^^^^^^^^^^ missing tokens in macro arguments + | ^^^^^^^^^^ missing tokens in macro arguments error: unexpected end of macro invocation --> $DIR/macro-at-most-once-rep-2015.rs:37:15 diff --git a/src/test/ui/macros/macro-at-most-once-rep-2018.stderr b/src/test/ui/macros/macro-at-most-once-rep-2018.stderr index bfe5883b03..013fabe13e 100644 --- a/src/test/ui/macros/macro-at-most-once-rep-2018.stderr +++ b/src/test/ui/macros/macro-at-most-once-rep-2018.stderr @@ -38,7 +38,7 @@ LL | macro_rules! barplus { | -------------------- when calling this macro ... LL | barplus!(); - | ^^^^^^^^^^^ missing tokens in macro arguments + | ^^^^^^^^^^ missing tokens in macro arguments error: unexpected end of macro invocation --> $DIR/macro-at-most-once-rep-2018.rs:30:15 @@ -74,7 +74,7 @@ LL | macro_rules! barstar { | -------------------- when calling this macro ... LL | barstar!(); - | ^^^^^^^^^^^ missing tokens in macro arguments + | ^^^^^^^^^^ missing tokens in macro arguments error: unexpected end of macro invocation --> $DIR/macro-at-most-once-rep-2018.rs:37:15 diff --git a/src/test/ui/macros/macro-backtrace-invalid-internals.stderr b/src/test/ui/macros/macro-backtrace-invalid-internals.stderr index 5c86460082..aa8f06a0df 100644 --- a/src/test/ui/macros/macro-backtrace-invalid-internals.stderr +++ b/src/test/ui/macros/macro-backtrace-invalid-internals.stderr @@ -5,7 +5,7 @@ LL | 1.fake() | ^^^^ method not found in `{integer}` ... LL | fake_method_stmt!(); - | -------------------- in this macro invocation + | ------------------- in this macro invocation | = note: this error originates in the macro `fake_method_stmt` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -16,7 +16,7 @@ LL | 1.fake | ^^^^ ... LL | fake_field_stmt!(); - | ------------------- in this macro invocation + | ------------------ in this macro invocation | = note: this error originates in the macro `fake_field_stmt` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -27,7 +27,7 @@ LL | (1).0 | ^ ... LL | fake_anon_field_stmt!(); - | ------------------------ in this macro invocation + | ----------------------- in this macro invocation | = note: this error originates in the macro `fake_anon_field_stmt` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -38,7 +38,7 @@ LL | 2.0.neg() | ^^^ ... LL | real_method_stmt!(); - | -------------------- in this macro invocation + | ------------------- in this macro invocation | = note: this error originates in the macro `real_method_stmt` (in Nightly builds, run with -Z macro-backtrace for more info) help: you must specify a concrete type for this numeric value, like `f32` diff --git a/src/test/ui/macros/macro-backtrace-nested.stderr b/src/test/ui/macros/macro-backtrace-nested.stderr index d61434e5f2..38b52e1a12 100644 --- a/src/test/ui/macros/macro-backtrace-nested.stderr +++ b/src/test/ui/macros/macro-backtrace-nested.stderr @@ -16,7 +16,7 @@ LL | () => (fake) | ^^^^ not found in this scope ... LL | call_nested_expr_sum!(); - | ------------------------ in this macro invocation + | ----------------------- in this macro invocation | = note: this error originates in the macro `nested_expr` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/macros/macro-backtrace-println.stderr b/src/test/ui/macros/macro-backtrace-println.stderr index 0703868e9b..bc00e0db83 100644 --- a/src/test/ui/macros/macro-backtrace-println.stderr +++ b/src/test/ui/macros/macro-backtrace-println.stderr @@ -5,7 +5,7 @@ LL | ($fmt:expr) => (myprint!(concat!($fmt, "\n"))); | ^^^^^^^^^^^^^^^^^^^ ... LL | myprintln!("{}"); - | ----------------- in this macro invocation + | ---------------- in this macro invocation | = note: this error originates in the macro `concat` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/macros/macro-comma-support.stderr b/src/test/ui/macros/macro-comma-support.stderr index 28d064f7f5..874efccd32 100644 --- a/src/test/ui/macros/macro-comma-support.stderr +++ b/src/test/ui/macros/macro-comma-support.stderr @@ -2,13 +2,13 @@ error: lel --> $DIR/macro-comma-support.rs:6:5 | LL | compile_error!("lel"); - | ^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^ error: lel --> $DIR/macro-comma-support.rs:7:5 | LL | compile_error!("lel",); - | ^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/macros/macro-context.stderr b/src/test/ui/macros/macro-context.stderr index 3b8a6f1749..5dc1780703 100644 --- a/src/test/ui/macros/macro-context.stderr +++ b/src/test/ui/macros/macro-context.stderr @@ -38,7 +38,7 @@ LL | () => ( i ; typeof ); | ^^^^^^ expected expression ... LL | m!(); - | ----- in this macro invocation + | ---- in this macro invocation | = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/macros/macro-def-site-super.rs b/src/test/ui/macros/macro-def-site-super.rs new file mode 100644 index 0000000000..716a8ced5b --- /dev/null +++ b/src/test/ui/macros/macro-def-site-super.rs @@ -0,0 +1,10 @@ +// `super` in a `macro` refers to the parent module of the macro itself and not its reexport. + +// check-pass +// aux-build:macro-def-site-super.rs + +extern crate macro_def_site_super; + +type A = macro_def_site_super::public::mac!(); + +fn main() {} diff --git a/src/test/ui/macros/macro-inner-attributes.stderr b/src/test/ui/macros/macro-inner-attributes.stderr index 8223220d9a..77b6486155 100644 --- a/src/test/ui/macros/macro-inner-attributes.stderr +++ b/src/test/ui/macros/macro-inner-attributes.stderr @@ -3,6 +3,11 @@ error[E0433]: failed to resolve: use of undeclared crate or module `a` | LL | a::bar(); | ^ use of undeclared crate or module `a` + | +help: there is a crate or module with a similar name + | +LL | b::bar(); + | ~ error: aborting due to previous error diff --git a/src/test/ui/macros/macro-lifetime-used-with-labels.stderr b/src/test/ui/macros/macro-lifetime-used-with-labels.stderr index f6fc803441..69334e2119 100644 --- a/src/test/ui/macros/macro-lifetime-used-with-labels.stderr +++ b/src/test/ui/macros/macro-lifetime-used-with-labels.stderr @@ -7,7 +7,7 @@ LL | 'b: loop { LL | 'b: loop { | -- first declared here LL | br2!('b); - | --------- in this macro invocation + | -------- in this macro invocation | = note: this warning originates in the macro `br2` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/macros/macro-local-data-key-priv.stderr b/src/test/ui/macros/macro-local-data-key-priv.stderr index 89ff753b37..b449e34736 100644 --- a/src/test/ui/macros/macro-local-data-key-priv.stderr +++ b/src/test/ui/macros/macro-local-data-key-priv.stderr @@ -8,7 +8,7 @@ note: the constant `baz` is defined here --> $DIR/macro-local-data-key-priv.rs:4:5 | LL | thread_local!(static baz: f64 = 0.0); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the macro `$crate::__thread_local_inner` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to previous error diff --git a/src/test/ui/macros/macro-shadowing.stderr b/src/test/ui/macros/macro-shadowing.stderr index 0105208453..58224b7073 100644 --- a/src/test/ui/macros/macro-shadowing.stderr +++ b/src/test/ui/macros/macro-shadowing.stderr @@ -5,7 +5,7 @@ LL | #[macro_use] | ^^^^^^^^^^^^ ... LL | m1!(); - | ------ in this macro invocation + | ----- in this macro invocation | = 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) @@ -23,7 +23,7 @@ LL | macro_rules! foo { () => {} } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ... LL | m1!(); - | ------ in this macro invocation + | ----- in this macro invocation note: `foo` could also refer to the macro defined here --> $DIR/macro-shadowing.rs:5:1 | diff --git a/src/test/ui/macros/macros-nonfatal-errors.stderr b/src/test/ui/macros/macros-nonfatal-errors.stderr index 00c23d501a..64065cd272 100644 --- a/src/test/ui/macros/macros-nonfatal-errors.stderr +++ b/src/test/ui/macros/macros-nonfatal-errors.stderr @@ -138,11 +138,11 @@ error: inline assembly must be a string literal LL | llvm_asm!(invalid); | ^^^^^^^ -error: concat_idents! requires ident args. +error: concat_idents! requires ident args --> $DIR/macros-nonfatal-errors.rs:102:5 | LL | concat_idents!("not", "idents"); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: argument must be a string literal --> $DIR/macros-nonfatal-errors.rs:104:17 @@ -166,7 +166,7 @@ error: environment variable `RUST_HOPEFULLY_THIS_DOESNT_EXIST` not defined --> $DIR/macros-nonfatal-errors.rs:107:5 | LL | env!("RUST_HOPEFULLY_THIS_DOESNT_EXIST"); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: this error originates in the macro `env` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -197,7 +197,7 @@ error: couldn't read $DIR/i'd be quite surprised if a file with this name existe --> $DIR/macros-nonfatal-errors.rs:114:5 | LL | include_str!("i'd be quite surprised if a file with this name existed"); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: this error originates in the macro `include_str` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -211,7 +211,7 @@ error: couldn't read $DIR/i'd be quite surprised if a file with this name existe --> $DIR/macros-nonfatal-errors.rs:116:5 | LL | include_bytes!("i'd be quite surprised if a file with this name existed"); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: this error originates in the macro `include_bytes` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -219,7 +219,7 @@ error: trace_macros! accepts only `true` or `false` --> $DIR/macros-nonfatal-errors.rs:118:5 | LL | trace_macros!(invalid); - | ^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 27 previous errors diff --git a/src/test/ui/macros/must-use-in-macro-55516.stderr b/src/test/ui/macros/must-use-in-macro-55516.stderr index 46fa43ac96..b56b00cc7d 100644 --- a/src/test/ui/macros/must-use-in-macro-55516.stderr +++ b/src/test/ui/macros/must-use-in-macro-55516.stderr @@ -2,7 +2,7 @@ warning: unused `Result` that must be used --> $DIR/must-use-in-macro-55516.rs:9:5 | LL | write!(&mut example, "{}", 42); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-W unused-must-use` implied by `-W unused` = note: this `Result` may be an `Err` variant, which should be handled diff --git a/src/test/ui/macros/nonterminal-matching.stderr b/src/test/ui/macros/nonterminal-matching.stderr index 38df53fb69..155a942513 100644 --- a/src/test/ui/macros/nonterminal-matching.stderr +++ b/src/test/ui/macros/nonterminal-matching.stderr @@ -8,7 +8,7 @@ LL | n!(a $nt_item b); | ^^^^^^^^ no rules expected this token in macro call ... LL | complex_nonterminal!(enum E {}); - | -------------------------------- in this macro invocation + | ------------------------------- in this macro invocation | = note: this error originates in the macro `complex_nonterminal` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/out-of-order-shadowing.rs b/src/test/ui/macros/out-of-order-shadowing.rs similarity index 100% rename from src/test/ui/out-of-order-shadowing.rs rename to src/test/ui/macros/out-of-order-shadowing.rs diff --git a/src/test/ui/out-of-order-shadowing.stderr b/src/test/ui/macros/out-of-order-shadowing.stderr similarity index 96% rename from src/test/ui/out-of-order-shadowing.stderr rename to src/test/ui/macros/out-of-order-shadowing.stderr index 1db31e0272..6b11916707 100644 --- a/src/test/ui/out-of-order-shadowing.stderr +++ b/src/test/ui/macros/out-of-order-shadowing.stderr @@ -8,7 +8,7 @@ note: `bar` could refer to the macro defined here --> $DIR/out-of-order-shadowing.rs:4:1 | LL | define_macro!(bar); - | ^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^ note: `bar` could also refer to the macro defined here --> $DIR/out-of-order-shadowing.rs:3:1 | diff --git a/src/test/ui/macros/restricted-shadowing-legacy.stderr b/src/test/ui/macros/restricted-shadowing-legacy.stderr index cf4203525e..4912166883 100644 --- a/src/test/ui/macros/restricted-shadowing-legacy.stderr +++ b/src/test/ui/macros/restricted-shadowing-legacy.stderr @@ -5,7 +5,7 @@ LL | m!(); | ^ ambiguous name ... LL | include!(); - | ----------- in this macro invocation + | ---------- in this macro invocation | note: `m` could refer to the macro defined here --> $DIR/restricted-shadowing-legacy.rs:88:9 @@ -14,7 +14,7 @@ LL | macro_rules! m { () => { Right } } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ... LL | include!(); - | ----------- in this macro invocation + | ---------- in this macro invocation note: `m` could also refer to the macro defined here --> $DIR/restricted-shadowing-legacy.rs:97:9 | @@ -22,7 +22,7 @@ LL | macro_rules! m { () => {} } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ ... LL | include!(); - | ----------- in this macro invocation + | ---------- 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) @@ -32,7 +32,7 @@ LL | macro_rules! gen_invoc { () => { m!() } } | ^ ambiguous name ... LL | include!(); - | ----------- in this macro invocation + | ---------- in this macro invocation | note: `m` could refer to the macro defined here --> $DIR/restricted-shadowing-legacy.rs:88:9 @@ -41,7 +41,7 @@ LL | macro_rules! m { () => { Right } } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ... LL | include!(); - | ----------- in this macro invocation + | ---------- in this macro invocation note: `m` could also refer to the macro defined here --> $DIR/restricted-shadowing-legacy.rs:135:9 | @@ -49,7 +49,7 @@ LL | macro_rules! m { () => {} } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ ... LL | include!(); - | ----------- in this macro invocation + | ---------- 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) @@ -59,7 +59,7 @@ LL | m!(); | ^ ambiguous name ... LL | include!(); - | ----------- in this macro invocation + | ---------- in this macro invocation | note: `m` could refer to the macro defined here --> $DIR/restricted-shadowing-legacy.rs:88:9 @@ -68,7 +68,7 @@ LL | macro_rules! m { () => { Right } } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ... LL | include!(); - | ----------- in this macro invocation + | ---------- in this macro invocation note: `m` could also refer to the macro defined here --> $DIR/restricted-shadowing-legacy.rs:144:9 | @@ -76,7 +76,7 @@ LL | macro_rules! m { () => {} } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ ... LL | include!(); - | ----------- in this macro invocation + | ---------- 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) @@ -86,7 +86,7 @@ LL | m!(); | ^ ambiguous name ... LL | include!(); - | ----------- in this macro invocation + | ---------- in this macro invocation | note: `m` could refer to the macro defined here --> $DIR/restricted-shadowing-legacy.rs:88:9 @@ -95,7 +95,7 @@ LL | macro_rules! m { () => { Right } } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ... LL | include!(); - | ----------- in this macro invocation + | ---------- in this macro invocation note: `m` could also refer to the macro defined here --> $DIR/restricted-shadowing-legacy.rs:85:9 | @@ -103,7 +103,7 @@ LL | macro_rules! m { () => { Wrong } } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ... LL | include!(); - | ----------- in this macro invocation + | ---------- 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) @@ -113,7 +113,7 @@ LL | m!(); | ^ ambiguous name ... LL | include!(); - | ----------- in this macro invocation + | ---------- in this macro invocation | note: `m` could refer to the macro defined here --> $DIR/restricted-shadowing-legacy.rs:88:9 @@ -122,7 +122,7 @@ LL | macro_rules! m { () => { Right } } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ... LL | include!(); - | ----------- in this macro invocation + | ---------- in this macro invocation note: `m` could also refer to the macro defined here --> $DIR/restricted-shadowing-legacy.rs:85:9 | @@ -130,7 +130,7 @@ LL | macro_rules! m { () => { Wrong } } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ... LL | include!(); - | ----------- in this macro invocation + | ---------- 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) @@ -140,7 +140,7 @@ LL | macro_rules! gen_invoc { () => { m!() } } | ^ ambiguous name ... LL | include!(); - | ----------- in this macro invocation + | ---------- in this macro invocation | note: `m` could refer to the macro defined here --> $DIR/restricted-shadowing-legacy.rs:88:9 @@ -149,7 +149,7 @@ LL | macro_rules! m { () => { Right } } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ... LL | include!(); - | ----------- in this macro invocation + | ---------- in this macro invocation note: `m` could also refer to the macro defined here --> $DIR/restricted-shadowing-legacy.rs:85:9 | @@ -157,7 +157,7 @@ LL | macro_rules! m { () => { Wrong } } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ... LL | include!(); - | ----------- in this macro invocation + | ---------- 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) @@ -167,7 +167,7 @@ LL | m!(); | ^ ambiguous name ... LL | include!(); - | ----------- in this macro invocation + | ---------- in this macro invocation | note: `m` could refer to the macro defined here --> $DIR/restricted-shadowing-legacy.rs:88:9 @@ -176,7 +176,7 @@ LL | macro_rules! m { () => { Right } } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ... LL | include!(); - | ----------- in this macro invocation + | ---------- in this macro invocation note: `m` could also refer to the macro defined here --> $DIR/restricted-shadowing-legacy.rs:227:13 | @@ -184,7 +184,7 @@ LL | macro_rules! m { () => {} } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ ... LL | include!(); - | ----------- in this macro invocation + | ---------- 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) @@ -194,7 +194,7 @@ LL | macro_rules! gen_invoc { () => { m!() } } | ^ ambiguous name ... LL | include!(); - | ----------- in this macro invocation + | ---------- in this macro invocation | note: `m` could refer to the macro defined here --> $DIR/restricted-shadowing-legacy.rs:88:9 @@ -203,7 +203,7 @@ LL | macro_rules! m { () => { Right } } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ... LL | include!(); - | ----------- in this macro invocation + | ---------- in this macro invocation note: `m` could also refer to the macro defined here --> $DIR/restricted-shadowing-legacy.rs:257:13 | @@ -211,7 +211,7 @@ LL | macro_rules! m { () => {} } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ ... LL | include!(); - | ----------- in this macro invocation + | ---------- 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: aborting due to 8 previous errors diff --git a/src/test/ui/macros/restricted-shadowing-modern.stderr b/src/test/ui/macros/restricted-shadowing-modern.stderr index 6161e46e48..62639eeb11 100644 --- a/src/test/ui/macros/restricted-shadowing-modern.stderr +++ b/src/test/ui/macros/restricted-shadowing-modern.stderr @@ -5,7 +5,7 @@ LL | m!(); | ^ ambiguous name ... LL | include!(); - | ----------- in this macro invocation + | ---------- in this macro invocation | note: `m` could refer to the macro defined here --> $DIR/restricted-shadowing-modern.rs:91:9 @@ -14,7 +14,7 @@ LL | macro m() { Right } | ^^^^^^^^^^^^^^^^^^^ ... LL | include!(); - | ----------- in this macro invocation + | ---------- in this macro invocation note: `m` could also refer to the macro defined here --> $DIR/restricted-shadowing-modern.rs:99:9 | @@ -22,7 +22,7 @@ LL | macro m() {} | ^^^^^^^^^^^^ ... LL | include!(); - | ----------- in this macro invocation + | ---------- 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) @@ -32,7 +32,7 @@ LL | macro gen_invoc() { m!() } | ^ ambiguous name ... LL | include!(); - | ----------- in this macro invocation + | ---------- in this macro invocation | note: `m` could refer to the macro defined here --> $DIR/restricted-shadowing-modern.rs:91:9 @@ -41,7 +41,7 @@ LL | macro m() { Right } | ^^^^^^^^^^^^^^^^^^^ ... LL | include!(); - | ----------- in this macro invocation + | ---------- in this macro invocation note: `m` could also refer to the macro defined here --> $DIR/restricted-shadowing-modern.rs:143:9 | @@ -49,7 +49,7 @@ LL | macro m() {} | ^^^^^^^^^^^^ ... LL | include!(); - | ----------- in this macro invocation + | ---------- 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) @@ -59,7 +59,7 @@ LL | m!(); | ^ ambiguous name ... LL | include!(); - | ----------- in this macro invocation + | ---------- in this macro invocation | note: `m` could refer to the macro defined here --> $DIR/restricted-shadowing-modern.rs:91:9 @@ -68,7 +68,7 @@ LL | macro m() { Right } | ^^^^^^^^^^^^^^^^^^^ ... LL | include!(); - | ----------- in this macro invocation + | ---------- in this macro invocation note: `m` could also refer to the macro defined here --> $DIR/restricted-shadowing-modern.rs:153:9 | @@ -76,7 +76,7 @@ LL | macro m() {} | ^^^^^^^^^^^^ ... LL | include!(); - | ----------- in this macro invocation + | ---------- 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) @@ -86,7 +86,7 @@ LL | m!(); | ^ ambiguous name ... LL | include!(); - | ----------- in this macro invocation + | ---------- in this macro invocation | note: `m` could refer to the macro defined here --> $DIR/restricted-shadowing-modern.rs:91:9 @@ -95,7 +95,7 @@ LL | macro m() { Right } | ^^^^^^^^^^^^^^^^^^^ ... LL | include!(); - | ----------- in this macro invocation + | ---------- in this macro invocation note: `m` could also refer to the macro defined here --> $DIR/restricted-shadowing-modern.rs:87:9 | @@ -103,7 +103,7 @@ LL | macro m() { Wrong } | ^^^^^^^^^^^^^^^^^^^ ... LL | include!(); - | ----------- in this macro invocation + | ---------- 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) @@ -113,7 +113,7 @@ LL | m!(); | ^ ambiguous name ... LL | include!(); - | ----------- in this macro invocation + | ---------- in this macro invocation | note: `m` could refer to the macro defined here --> $DIR/restricted-shadowing-modern.rs:91:9 @@ -122,7 +122,7 @@ LL | macro m() { Right } | ^^^^^^^^^^^^^^^^^^^ ... LL | include!(); - | ----------- in this macro invocation + | ---------- in this macro invocation note: `m` could also refer to the macro defined here --> $DIR/restricted-shadowing-modern.rs:87:9 | @@ -130,7 +130,7 @@ LL | macro m() { Wrong } | ^^^^^^^^^^^^^^^^^^^ ... LL | include!(); - | ----------- in this macro invocation + | ---------- 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) @@ -140,7 +140,7 @@ LL | macro gen_invoc() { m!() } | ^ ambiguous name ... LL | include!(); - | ----------- in this macro invocation + | ---------- in this macro invocation | note: `m` could refer to the macro defined here --> $DIR/restricted-shadowing-modern.rs:91:9 @@ -149,7 +149,7 @@ LL | macro m() { Right } | ^^^^^^^^^^^^^^^^^^^ ... LL | include!(); - | ----------- in this macro invocation + | ---------- in this macro invocation note: `m` could also refer to the macro defined here --> $DIR/restricted-shadowing-modern.rs:87:9 | @@ -157,7 +157,7 @@ LL | macro m() { Wrong } | ^^^^^^^^^^^^^^^^^^^ ... LL | include!(); - | ----------- in this macro invocation + | ---------- 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: aborting due to 6 previous errors diff --git a/src/test/ui/macros/same-sequence-span.stderr b/src/test/ui/macros/same-sequence-span.stderr index 4581d58318..bdd191e8ed 100644 --- a/src/test/ui/macros/same-sequence-span.stderr +++ b/src/test/ui/macros/same-sequence-span.stderr @@ -18,7 +18,7 @@ error: `$x:expr` may be followed by `$y:tt`, which is not allowed for `expr` fra --> $DIR/same-sequence-span.rs:19:1 | LL | proc_macro_sequence::make_foo!(); - | ^-------------------------------- + | ^------------------------------- | | | _in this macro invocation | | @@ -34,7 +34,7 @@ error: `$x:expr` may be followed by `=`, which is not allowed for `expr` fragmen --> $DIR/same-sequence-span.rs:19:1 | LL | proc_macro_sequence::make_foo!(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not allowed after `expr` fragments + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not allowed after `expr` fragments | = note: allowed there are: `=>`, `,` or `;` = note: this error originates in the macro `proc_macro_sequence::make_foo` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/macros/span-covering-argument-1.stderr b/src/test/ui/macros/span-covering-argument-1.stderr index f563b0dc12..ce3424a8b1 100644 --- a/src/test/ui/macros/span-covering-argument-1.stderr +++ b/src/test/ui/macros/span-covering-argument-1.stderr @@ -7,7 +7,7 @@ LL | *&mut $s = 0; | ^^^^^^^ cannot borrow as mutable ... LL | bad!(foo whatever); - | ------------------- in this macro invocation + | ------------------ in this macro invocation | = note: this error originates in the macro `bad` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/macros/trace-macro.stderr b/src/test/ui/macros/trace-macro.stderr index bf48e80eff..43272248c2 100644 --- a/src/test/ui/macros/trace-macro.stderr +++ b/src/test/ui/macros/trace-macro.stderr @@ -2,7 +2,7 @@ note: trace_macro --> $DIR/trace-macro.rs:5:5 | LL | println!("Hello, World!"); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: expanding `println! { "Hello, World!" }` = note: to `{ $crate :: io :: _print($crate :: format_args_nl! ("Hello, World!")) ; }` diff --git a/src/test/ui/macros/trace_faulty_macros.stderr b/src/test/ui/macros/trace_faulty_macros.stderr index 38affde5f6..d6fc694021 100644 --- a/src/test/ui/macros/trace_faulty_macros.stderr +++ b/src/test/ui/macros/trace_faulty_macros.stderr @@ -8,7 +8,7 @@ LL | my_faulty_macro!(bcd); | ^^^ no rules expected this token in macro call ... LL | my_faulty_macro!(); - | ------------------- in this macro invocation + | ------------------ in this macro invocation | = note: this error originates in the macro `my_faulty_macro` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -16,7 +16,7 @@ note: trace_macro --> $DIR/trace_faulty_macros.rs:31:5 | LL | my_faulty_macro!(); - | ^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^ | = note: expanding `my_faulty_macro! { }` = note: to `my_faulty_macro! (bcd) ;` @@ -26,19 +26,19 @@ error: recursion limit reached while expanding `my_recursive_macro!` --> $DIR/trace_faulty_macros.rs:22:9 | LL | my_recursive_macro!(); - | ^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^ ... LL | my_recursive_macro!(); - | ---------------------- in this macro invocation + | --------------------- in this macro invocation | - = help: consider adding a `#![recursion_limit="8"]` attribute to your crate (`trace_faulty_macros`) + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "8"]` attribute to your crate (`trace_faulty_macros`) = note: this error originates in the macro `my_recursive_macro` (in Nightly builds, run with -Z macro-backtrace for more info) note: trace_macro --> $DIR/trace_faulty_macros.rs:32:5 | LL | my_recursive_macro!(); - | ^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^ | = note: expanding `my_recursive_macro! { }` = note: to `my_recursive_macro! () ;` diff --git a/src/test/ui/malformed/malformed-plugin-1.stderr b/src/test/ui/malformed/malformed-plugin-1.stderr index 98744434d4..505f6b6f14 100644 --- a/src/test/ui/malformed/malformed-plugin-1.stderr +++ b/src/test/ui/malformed/malformed-plugin-1.stderr @@ -2,7 +2,7 @@ error: malformed `plugin` attribute input --> $DIR/malformed-plugin-1.rs:2:1 | LL | #![plugin] - | ^^^^^^^^^^ help: must be of the form: `#[plugin(name)]` + | ^^^^^^^^^^ help: must be of the form: `#![plugin(name)]` warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675 --> $DIR/malformed-plugin-1.rs:2:1 diff --git a/src/test/ui/malformed/malformed-plugin-2.stderr b/src/test/ui/malformed/malformed-plugin-2.stderr index 9bf0bf9345..52bbd82a38 100644 --- a/src/test/ui/malformed/malformed-plugin-2.stderr +++ b/src/test/ui/malformed/malformed-plugin-2.stderr @@ -2,7 +2,7 @@ error: malformed `plugin` attribute input --> $DIR/malformed-plugin-2.rs:2:1 | LL | #![plugin="bleh"] - | ^^^^^^^^^^^^^^^^^ help: must be of the form: `#[plugin(name)]` + | ^^^^^^^^^^^^^^^^^ help: must be of the form: `#![plugin(name)]` warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675 --> $DIR/malformed-plugin-2.rs:2:1 diff --git a/src/test/ui/map-types.rs b/src/test/ui/map-types.rs index 89b5708750..dc33b96180 100644 --- a/src/test/ui/map-types.rs +++ b/src/test/ui/map-types.rs @@ -1,7 +1,7 @@ -#![feature(box_syntax)] - use std::collections::HashMap; + + trait Map { fn get(&self, k: K) -> V { panic!() } @@ -12,7 +12,7 @@ impl Map for HashMap {} // Test that trait types printed in error msgs include the type arguments. fn main() { - let x: Box> = box HashMap::new(); + let x: Box> = HashMap::new().into(); let x: Box> = x; let y: Box> = Box::new(x); //~^ ERROR `Box>: Map` is not satisfied diff --git a/src/test/ui/guards.rs b/src/test/ui/match/guards.rs similarity index 100% rename from src/test/ui/guards.rs rename to src/test/ui/match/guards.rs diff --git a/src/test/ui/issues/issue-33498.rs b/src/test/ui/match/issue-33498.rs similarity index 100% rename from src/test/ui/issues/issue-33498.rs rename to src/test/ui/match/issue-33498.rs diff --git a/src/test/ui/issues/issue-41255.rs b/src/test/ui/match/issue-41255.rs similarity index 100% rename from src/test/ui/issues/issue-41255.rs rename to src/test/ui/match/issue-41255.rs diff --git a/src/test/ui/issues/issue-41255.stderr b/src/test/ui/match/issue-41255.stderr similarity index 100% rename from src/test/ui/issues/issue-41255.stderr rename to src/test/ui/match/issue-41255.stderr diff --git a/src/test/ui/issues/issue-56685.rs b/src/test/ui/match/issue-56685.rs similarity index 100% rename from src/test/ui/issues/issue-56685.rs rename to src/test/ui/match/issue-56685.rs diff --git a/src/test/ui/issues/issue-56685.stderr b/src/test/ui/match/issue-56685.stderr similarity index 100% rename from src/test/ui/issues/issue-56685.stderr rename to src/test/ui/match/issue-56685.stderr diff --git a/src/test/ui/match/issue-74050-end-span.stderr b/src/test/ui/match/issue-74050-end-span.stderr index d636a11a91..59c091e44e 100644 --- a/src/test/ui/match/issue-74050-end-span.stderr +++ b/src/test/ui/match/issue-74050-end-span.stderr @@ -5,7 +5,7 @@ LL | let _arg = match args.next() { | ---- borrow later stored here LL | Some(arg) => { LL | match arg.to_str() { - | ^^^ borrowed value does not live long enough + | ^^^^^^^^^^^^ borrowed value does not live long enough ... LL | } | - `arg` dropped here while still borrowed diff --git a/src/test/ui/match/match-ref-mut-invariance.stderr b/src/test/ui/match/match-ref-mut-invariance.stderr index 3e9f729dc0..f9271cb3d0 100644 --- a/src/test/ui/match/match-ref-mut-invariance.stderr +++ b/src/test/ui/match/match-ref-mut-invariance.stderr @@ -6,12 +6,12 @@ LL | match self.0 { ref mut x => x } | = note: expected mutable reference `&'a mut &'a i32` found mutable reference `&'a mut &'b i32` -note: the lifetime `'a` as defined on the method body at 9:12... +note: the lifetime `'a` as defined here... --> $DIR/match-ref-mut-invariance.rs:9:12 | LL | fn bar<'a>(&'a mut self) -> &'a mut &'a i32 { | ^^ -note: ...does not necessarily outlive the lifetime `'b` as defined on the impl at 8:6 +note: ...does not necessarily outlive the lifetime `'b` as defined here --> $DIR/match-ref-mut-invariance.rs:8:6 | LL | impl<'b> S<'b> { diff --git a/src/test/ui/match/match-ref-mut-let-invariance.stderr b/src/test/ui/match/match-ref-mut-let-invariance.stderr index 303aba3422..c021a5a91f 100644 --- a/src/test/ui/match/match-ref-mut-let-invariance.stderr +++ b/src/test/ui/match/match-ref-mut-let-invariance.stderr @@ -6,12 +6,12 @@ LL | x | = note: expected mutable reference `&'a mut &'a i32` found mutable reference `&'a mut &'b i32` -note: the lifetime `'a` as defined on the method body at 9:12... +note: the lifetime `'a` as defined here... --> $DIR/match-ref-mut-let-invariance.rs:9:12 | LL | fn bar<'a>(&'a mut self) -> &'a mut &'a i32 { | ^^ -note: ...does not necessarily outlive the lifetime `'b` as defined on the impl at 8:6 +note: ...does not necessarily outlive the lifetime `'b` as defined here --> $DIR/match-ref-mut-let-invariance.rs:8:6 | LL | impl<'b> S<'b> { diff --git a/src/test/ui/maybe-bounds-where.rs b/src/test/ui/maybe-bounds-where.rs index cf011653c2..d7af0c4248 100644 --- a/src/test/ui/maybe-bounds-where.rs +++ b/src/test/ui/maybe-bounds-where.rs @@ -11,6 +11,7 @@ trait Trait<'a> {} struct S4(T) where for<'a> T: ?Trait<'a>; //~^ ERROR `?Trait` bounds are only permitted at the point where a type parameter is declared +//~| WARN default bound relaxed for a type parameter struct S5(*const T) where T: ?Trait<'static> + ?Sized; //~^ ERROR type parameter has more than one relaxed default bound diff --git a/src/test/ui/maybe-bounds-where.stderr b/src/test/ui/maybe-bounds-where.stderr index 0ef8e9e9c7..39bc1b88e5 100644 --- a/src/test/ui/maybe-bounds-where.stderr +++ b/src/test/ui/maybe-bounds-where.stderr @@ -1,45 +1,51 @@ error: `?Trait` bounds are only permitted at the point where a type parameter is declared - --> $DIR/maybe-bounds-where.rs:1:23 + --> $DIR/maybe-bounds-where.rs:1:28 | LL | struct S1(T) where (T): ?Sized; - | ^^^ + | ^^^^^^ error: `?Trait` bounds are only permitted at the point where a type parameter is declared - --> $DIR/maybe-bounds-where.rs:4:23 + --> $DIR/maybe-bounds-where.rs:4:27 | LL | struct S2(T) where u8: ?Sized; - | ^^ + | ^^^^^^ error: `?Trait` bounds are only permitted at the point where a type parameter is declared - --> $DIR/maybe-bounds-where.rs:7:23 + --> $DIR/maybe-bounds-where.rs:7:35 | LL | struct S3(T) where &'static T: ?Sized; - | ^^^^^^^^^^ + | ^^^^^^ error: `?Trait` bounds are only permitted at the point where a type parameter is declared - --> $DIR/maybe-bounds-where.rs:12:31 + --> $DIR/maybe-bounds-where.rs:12:34 | LL | struct S4(T) where for<'a> T: ?Trait<'a>; - | ^ + | ^^^^^^^^^^ error: `?Trait` bounds are only permitted at the point where a type parameter is declared - --> $DIR/maybe-bounds-where.rs:20:18 + --> $DIR/maybe-bounds-where.rs:21:21 | LL | fn f() where T: ?Sized {} - | ^ + | ^^^^^^ + +warning: default bound relaxed for a type parameter, but this does nothing because the given bound is not a default; only `?Sized` is supported + --> $DIR/maybe-bounds-where.rs:12:11 + | +LL | struct S4(T) where for<'a> T: ?Trait<'a>; + | ^ error[E0203]: type parameter has more than one relaxed default bound, only one is supported - --> $DIR/maybe-bounds-where.rs:15:11 + --> $DIR/maybe-bounds-where.rs:16:11 | LL | struct S5(*const T) where T: ?Trait<'static> + ?Sized; | ^ warning: default bound relaxed for a type parameter, but this does nothing because the given bound is not a default; only `?Sized` is supported - --> $DIR/maybe-bounds-where.rs:15:11 + --> $DIR/maybe-bounds-where.rs:16:11 | LL | struct S5(*const T) where T: ?Trait<'static> + ?Sized; | ^ -error: aborting due to 6 previous errors; 1 warning emitted +error: aborting due to 6 previous errors; 2 warnings emitted For more information about this error, try `rustc --explain E0203`. diff --git a/src/test/ui/meta/expected-error-correct-rev.a.stderr b/src/test/ui/meta/expected-error-correct-rev.a.stderr index 75c1f695d7..4adeebe2a5 100644 --- a/src/test/ui/meta/expected-error-correct-rev.a.stderr +++ b/src/test/ui/meta/expected-error-correct-rev.a.stderr @@ -9,7 +9,7 @@ LL | let x: u32 = 22_usize; help: change the type of the numeric literal from `usize` to `u32` | LL | let x: u32 = 22_u32; - | ~~~~~~ + | ~~~ error: aborting due to previous error diff --git a/src/test/ui/meta/meta-expected-error-wrong-rev.a.stderr b/src/test/ui/meta/meta-expected-error-wrong-rev.a.stderr index 7985357d0a..012071df2b 100644 --- a/src/test/ui/meta/meta-expected-error-wrong-rev.a.stderr +++ b/src/test/ui/meta/meta-expected-error-wrong-rev.a.stderr @@ -9,7 +9,7 @@ LL | let x: u32 = 22_usize; help: change the type of the numeric literal from `usize` to `u32` | LL | let x: u32 = 22_u32; - | ~~~~~~ + | ~~~ error: aborting due to previous error diff --git a/src/test/ui/methods/auxiliary/method_self_arg1.rs b/src/test/ui/methods/auxiliary/method_self_arg1.rs index 8258fdd9ab..f89019fe58 100644 --- a/src/test/ui/methods/auxiliary/method_self_arg1.rs +++ b/src/test/ui/methods/auxiliary/method_self_arg1.rs @@ -1,7 +1,5 @@ #![crate_type = "lib"] -#![feature(box_syntax)] - static mut COUNT: u64 = 1; pub fn get_count() -> u64 { unsafe { COUNT } } @@ -19,8 +17,8 @@ impl Foo { Foo::baz(self); Foo::baz(*x); - Foo::qux(box self); - Foo::qux(box *x); + Foo::qux(Box::new(self)); + Foo::qux(Box::new(*x)); } pub fn bar(&self) { diff --git a/src/test/ui/methods/auxiliary/method_self_arg2.rs b/src/test/ui/methods/auxiliary/method_self_arg2.rs index 94a4a016c3..9672545629 100644 --- a/src/test/ui/methods/auxiliary/method_self_arg2.rs +++ b/src/test/ui/methods/auxiliary/method_self_arg2.rs @@ -1,7 +1,5 @@ #![crate_type = "lib"] -#![feature(box_syntax)] - static mut COUNT: u64 = 1; pub fn get_count() -> u64 { unsafe { COUNT } } @@ -15,11 +13,11 @@ impl Foo { // Test internal call. Bar::foo1(&self); Bar::foo2(self); - Bar::foo3(box self); + Bar::foo3(Box::new(self)); Bar::bar1(&self); Bar::bar2(self); - Bar::bar3(box self); + Bar::bar3(Box::new(self)); } } 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 e725e74efc..4b494c9611 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 @@ -17,7 +17,7 @@ LL | let y: usize = x.foo(); help: you can convert an `isize` to a `usize` and panic if the converted value doesn't fit | LL | let y: usize = x.foo().try_into().unwrap(); - | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error: aborting due to 2 previous errors diff --git a/src/test/ui/methods/method-ambig-two-traits-from-impls2.stderr b/src/test/ui/methods/method-ambig-two-traits-from-impls2.stderr index e0a58aed8f..4ba778e0ef 100644 --- a/src/test/ui/methods/method-ambig-two-traits-from-impls2.stderr +++ b/src/test/ui/methods/method-ambig-two-traits-from-impls2.stderr @@ -16,12 +16,12 @@ LL | fn foo() {} | ^^^^^^^^ help: disambiguate the associated function for candidate #1 | -LL | A::foo(); - | ~~~ +LL | ::foo(); + | ~~~~~~~~~~~ help: disambiguate the associated function for candidate #2 | -LL | B::foo(); - | ~~~ +LL | ::foo(); + | ~~~~~~~~~~~ error: aborting due to previous error diff --git a/src/test/ui/methods/method-call-err-msg.stderr b/src/test/ui/methods/method-call-err-msg.stderr index ffeacfe15d..c1183e053e 100644 --- a/src/test/ui/methods/method-call-err-msg.stderr +++ b/src/test/ui/methods/method-call-err-msg.stderr @@ -55,6 +55,17 @@ LL | .take() = note: the following trait bounds were not satisfied: `Foo: Iterator` which is required by `&mut Foo: Iterator` +note: the following trait must be implemented + --> $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 | | } + | |_^ = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `take`, perhaps you need to implement it: candidate #1: `Iterator` diff --git a/src/test/ui/methods/method-self-arg-2.stderr b/src/test/ui/methods/method-self-arg-2.stderr index 946e71ee5b..b98f7a7866 100644 --- a/src/test/ui/methods/method-self-arg-2.stderr +++ b/src/test/ui/methods/method-self-arg-2.stderr @@ -6,7 +6,7 @@ LL | let y = &mut x; LL | Foo::bar(&x); | ^^ immutable borrow occurs here LL | y.use_mut(); - | - mutable borrow later used here + | ----------- mutable borrow later used here error[E0499]: cannot borrow `x` as mutable more than once at a time --> $DIR/method-self-arg-2.rs:20:14 @@ -16,7 +16,7 @@ LL | let y = &mut x; LL | Foo::baz(&mut x); | ^^^^^^ second mutable borrow occurs here LL | y.use_mut(); - | - first borrow later used here + | ----------- first borrow later used here error: aborting due to 2 previous errors diff --git a/src/test/ui/methods/method-self-arg-aux1.rs b/src/test/ui/methods/method-self-arg-aux1.rs index 9e38ff7de3..79b70a17ca 100644 --- a/src/test/ui/methods/method-self-arg-aux1.rs +++ b/src/test/ui/methods/method-self-arg-aux1.rs @@ -1,8 +1,6 @@ // run-pass // Test method calls with self as an argument (cross-crate) -#![feature(box_syntax)] - // aux-build:method_self_arg1.rs extern crate method_self_arg1; use method_self_arg1::Foo; @@ -12,7 +10,7 @@ fn main() { // Test external call. Foo::bar(&x); Foo::baz(x); - Foo::qux(box x); + Foo::qux(Box::new(x)); x.foo(&x); diff --git a/src/test/ui/methods/method-self-arg-aux2.rs b/src/test/ui/methods/method-self-arg-aux2.rs index 8e70399d04..16487b54f1 100644 --- a/src/test/ui/methods/method-self-arg-aux2.rs +++ b/src/test/ui/methods/method-self-arg-aux2.rs @@ -1,8 +1,6 @@ // run-pass // Test method calls with self as an argument (cross-crate) -#![feature(box_syntax)] - // aux-build:method_self_arg2.rs extern crate method_self_arg2; use method_self_arg2::{Foo, Bar}; @@ -12,11 +10,11 @@ fn main() { // Test external call. Bar::foo1(&x); Bar::foo2(x); - Bar::foo3(box x); + Bar::foo3(Box::new(x)); Bar::bar1(&x); Bar::bar2(x); - Bar::bar3(box x); + Bar::bar3(Box::new(x)); x.run_trait(); diff --git a/src/test/ui/methods/method-self-arg-trait.rs b/src/test/ui/methods/method-self-arg-trait.rs index 227b1eab25..ffa7a552b2 100644 --- a/src/test/ui/methods/method-self-arg-trait.rs +++ b/src/test/ui/methods/method-self-arg-trait.rs @@ -1,8 +1,6 @@ // run-pass // Test method calls with self as an argument -#![feature(box_syntax)] - static mut COUNT: u64 = 1; #[derive(Copy, Clone)] @@ -44,11 +42,11 @@ impl Foo { // Test internal call. Bar::foo1(&self); Bar::foo2(self); - Bar::foo3(box self); + Bar::foo3(Box::new(self)); Bar::bar1(&self); Bar::bar2(self); - Bar::bar3(box self); + Bar::bar3(Box::new(self)); } } @@ -57,11 +55,11 @@ fn main() { // Test external call. Bar::foo1(&x); Bar::foo2(x); - Bar::foo3(box x); + Bar::foo3(Box::new(x)); Bar::bar1(&x); Bar::bar2(x); - Bar::bar3(box x); + Bar::bar3(Box::new(x)); x.baz(); diff --git a/src/test/ui/methods/method-self-arg.rs b/src/test/ui/methods/method-self-arg.rs index 2d25b0dbad..f738fa19c8 100644 --- a/src/test/ui/methods/method-self-arg.rs +++ b/src/test/ui/methods/method-self-arg.rs @@ -1,8 +1,6 @@ // run-pass // Test method calls with self as an argument -#![feature(box_syntax)] - static mut COUNT: usize = 1; #[derive(Copy, Clone)] @@ -18,8 +16,8 @@ impl Foo { Foo::baz(self); Foo::baz(*x); - Foo::qux(box self); - Foo::qux(box *x); + Foo::qux(Box::new(self)); + Foo::qux(Box::new(*x)); } fn bar(&self) { @@ -40,7 +38,7 @@ fn main() { // Test external call. Foo::bar(&x); Foo::baz(x); - Foo::qux(box x); + Foo::qux(Box::new(x)); x.foo(&x); diff --git a/src/test/ui/methods/method-two-trait-defer-resolution-2.rs b/src/test/ui/methods/method-two-trait-defer-resolution-2.rs index 8af3dcf5c3..fc5766da97 100644 --- a/src/test/ui/methods/method-two-trait-defer-resolution-2.rs +++ b/src/test/ui/methods/method-two-trait-defer-resolution-2.rs @@ -10,8 +10,6 @@ // codegen the call as `Foo::foo(&x)` and let the specific impl get // chosen later. -#![feature(box_syntax)] - trait Foo { fn foo(&self) -> isize; } @@ -37,7 +35,7 @@ fn call_foo_copy() -> isize { fn call_foo_other() -> isize { let mut x: Vec<_> = Vec::new(); let y = x.foo(); - let z: Box = box 0; + let z: Box = Box::new(0); x.push(z); y } diff --git a/src/test/ui/mir-dataflow/liveness-enum.rs b/src/test/ui/mir-dataflow/liveness-enum.rs new file mode 100644 index 0000000000..5eb04ae8c8 --- /dev/null +++ b/src/test/ui/mir-dataflow/liveness-enum.rs @@ -0,0 +1,22 @@ +#![feature(core_intrinsics, rustc_attrs)] + +use std::intrinsics::rustc_peek; + +#[rustc_mir(rustc_peek_liveness, stop_after_dataflow)] +fn foo() -> Option { + let mut x = None; + + // `x` is live here since it is used in the next statement... + rustc_peek(x); + + dbg!(x); + + // But not here, since it is overwritten below + rustc_peek(x); //~ ERROR rustc_peek: bit not set + + x = Some(4); + + x +} + +fn main() {} diff --git a/src/test/ui/mir-dataflow/liveness-enum.stderr b/src/test/ui/mir-dataflow/liveness-enum.stderr new file mode 100644 index 0000000000..483944d731 --- /dev/null +++ b/src/test/ui/mir-dataflow/liveness-enum.stderr @@ -0,0 +1,10 @@ +error: rustc_peek: bit not set + --> $DIR/liveness-enum.rs:15:5 + | +LL | rustc_peek(x); + | ^^^^^^^^^^^^^ + +error: stop_after_dataflow ended compilation + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/mismatched_types/E0631.stderr b/src/test/ui/mismatched_types/E0631.stderr index c8e81c93e2..1f2e169c68 100644 --- a/src/test/ui/mismatched_types/E0631.stderr +++ b/src/test/ui/mismatched_types/E0631.stderr @@ -33,7 +33,9 @@ LL | fn f(_: u64) {} | ------------ found signature of `fn(u64) -> _` ... LL | foo(f); - | ^ expected signature of `fn(usize) -> _` + | --- ^ expected signature of `fn(usize) -> _` + | | + | required by a bound introduced by this call | note: required by a bound in `foo` --> $DIR/E0631.rs:3:11 @@ -48,7 +50,9 @@ LL | fn f(_: u64) {} | ------------ found signature of `fn(u64) -> _` ... LL | bar(f); - | ^ expected signature of `fn(usize) -> _` + | --- ^ expected signature of `fn(usize) -> _` + | | + | required by a bound introduced by this call | note: required by a bound in `bar` --> $DIR/E0631.rs:4:11 diff --git a/src/test/ui/mismatched_types/cast-rfc0401.stderr b/src/test/ui/mismatched_types/cast-rfc0401.stderr index a47eb87cff..7f91d5ed42 100644 --- a/src/test/ui/mismatched_types/cast-rfc0401.stderr +++ b/src/test/ui/mismatched_types/cast-rfc0401.stderr @@ -28,8 +28,9 @@ LL | let _ = v as &u8; | help: consider borrowing the value | -LL | let _ = &*v as &u8; - | ++ +LL - let _ = v as &u8; +LL + let _ = &*v; + | error[E0605]: non-primitive cast: `*const u8` as `E` --> $DIR/cast-rfc0401.rs:30:13 diff --git a/src/test/ui/mismatched_types/closure-arg-count.stderr b/src/test/ui/mismatched_types/closure-arg-count.stderr index 6790017246..e8fcf80e94 100644 --- a/src/test/ui/mismatched_types/closure-arg-count.stderr +++ b/src/test/ui/mismatched_types/closure-arg-count.stderr @@ -119,7 +119,9 @@ error[E0593]: function is expected to take a single 2-tuple as argument, but it --> $DIR/closure-arg-count.rs:24:57 | LL | let _it = vec![1, 2, 3].into_iter().enumerate().map(foo); - | ^^^ expected function that takes a single 2-tuple as argument + | --- ^^^ expected function that takes a single 2-tuple as argument + | | + | required by a bound introduced by this call ... LL | fn foo() {} | -------- takes 0 arguments @@ -130,13 +132,17 @@ error[E0593]: closure is expected to take a single 2-tuple as argument, but it t LL | let bar = |i, x, y| i; | --------- takes 3 distinct arguments LL | let _it = vec![1, 2, 3].into_iter().enumerate().map(bar); - | ^^^ expected closure that takes a single 2-tuple as argument + | --- ^^^ expected closure that takes a single 2-tuple as argument + | | + | required by a bound introduced by this call 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 | LL | let _it = vec![1, 2, 3].into_iter().enumerate().map(qux); - | ^^^ expected function that takes a single 2-tuple as argument + | --- ^^^ expected function that takes a single 2-tuple as argument + | | + | required by a bound introduced by this call ... LL | fn qux(x: usize, y: usize) {} | -------------------------- takes 2 distinct arguments @@ -145,13 +151,17 @@ error[E0593]: function is expected to take 1 argument, but it takes 2 arguments --> $DIR/closure-arg-count.rs:32:45 | LL | let _it = vec![1, 2, 3].into_iter().map(usize::checked_add); - | ^^^^^^^^^^^^^^^^^^ expected function that takes 1 argument + | --- ^^^^^^^^^^^^^^^^^^ expected function that takes 1 argument + | | + | required by a bound introduced by this call error[E0593]: function is expected to take 0 arguments, but it takes 1 argument --> $DIR/closure-arg-count.rs:35:10 | LL | call(Foo); - | ^^^ expected function that takes 0 arguments + | ---- ^^^ expected function that takes 0 arguments + | | + | required by a bound introduced by this call ... LL | struct Foo(u8); | --------------- takes 1 argument 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 521de3742b..0ec282dac4 100644 --- a/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr +++ b/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr @@ -30,7 +30,7 @@ LL | baz(f); | = note: expected type `for<'r> Fn<(*mut &'r u32,)>` found type `Fn<(*mut &'a u32,)>` -note: the required lifetime does not necessarily outlive the lifetime `'a` as defined on the function body at 9:10 +note: the required lifetime does not necessarily outlive the lifetime `'a` as defined here --> $DIR/closure-arg-type-mismatch.rs:9:10 | LL | fn _test<'a>(f: fn(*mut &'a u32)) { @@ -58,7 +58,7 @@ LL | baz(f); | = note: expected type `for<'r> Fn<(*mut &'r u32,)>` found type `Fn<(*mut &'a u32,)>` -note: the lifetime `'a` as defined on the function body at 9:10 doesn't meet the lifetime requirements +note: the lifetime `'a` as defined here doesn't meet the lifetime requirements --> $DIR/closure-arg-type-mismatch.rs:9:10 | LL | fn _test<'a>(f: fn(*mut &'a u32)) { diff --git a/src/test/ui/mismatched_types/closure-mismatch.nll.stderr b/src/test/ui/mismatched_types/closure-mismatch.nll.stderr index f29126e6af..bd36fab928 100644 --- a/src/test/ui/mismatched_types/closure-mismatch.nll.stderr +++ b/src/test/ui/mismatched_types/closure-mismatch.nll.stderr @@ -20,6 +20,11 @@ note: this closure does not fulfill the lifetime requirements | LL | baz(|_| ()); | ^^^^^^ +note: the lifetime requirement is introduced here + --> $DIR/closure-mismatch.rs:5:11 + | +LL | fn baz(_: T) {} + | ^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/mismatched_types/fn-variance-1.stderr b/src/test/ui/mismatched_types/fn-variance-1.stderr index afde894b30..ce1dde94b5 100644 --- a/src/test/ui/mismatched_types/fn-variance-1.stderr +++ b/src/test/ui/mismatched_types/fn-variance-1.stderr @@ -5,7 +5,9 @@ LL | fn takes_mut(x: &mut isize) { } | --------------------------- found signature of `for<'r> fn(&'r mut isize) -> _` ... LL | apply(&3, takes_mut); - | ^^^^^^^^^ expected signature of `fn(&{integer}) -> _` + | ----- ^^^^^^^^^ expected signature of `fn(&{integer}) -> _` + | | + | required by a bound introduced by this call | note: required by a bound in `apply` --> $DIR/fn-variance-1.rs:5:37 @@ -20,7 +22,9 @@ LL | fn takes_imm(x: &isize) { } | ----------------------- found signature of `for<'r> fn(&'r isize) -> _` ... LL | apply(&mut 3, takes_imm); - | ^^^^^^^^^ expected signature of `fn(&mut {integer}) -> _` + | ----- ^^^^^^^^^ expected signature of `fn(&mut {integer}) -> _` + | | + | required by a bound introduced by this call | note: required by a bound in `apply` --> $DIR/fn-variance-1.rs:5:37 diff --git a/src/test/ui/mismatched_types/issue-26480.stderr b/src/test/ui/mismatched_types/issue-26480.stderr index e480bb250b..da8a976daa 100644 --- a/src/test/ui/mismatched_types/issue-26480.stderr +++ b/src/test/ui/mismatched_types/issue-26480.stderr @@ -5,13 +5,13 @@ LL | $arr.len() * size_of($arr[0])); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `u64`, found `usize` ... LL | write!(hello); - | -------------- in this macro invocation + | ------------- in this macro invocation | = note: this error originates in the macro `write` (in Nightly builds, run with -Z macro-backtrace for more info) help: you can convert a `usize` to a `u64` and panic if the converted value doesn't fit | LL | ($arr.len() * size_of($arr[0])).try_into().unwrap()); - | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + | + +++++++++++++++++++++ error[E0605]: non-primitive cast: `{integer}` as `()` --> $DIR/issue-26480.rs:22:19 @@ -20,7 +20,7 @@ LL | ($x:expr) => ($x as ()) | ^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object ... LL | cast!(2); - | --------- in this macro invocation + | -------- in this macro invocation | = note: this error originates in the macro `cast` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr b/src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr index 1030061b2d..596b7bfe79 100644 --- a/src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr +++ b/src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr @@ -9,6 +9,10 @@ LL | a.unwrap(); | = note: the following trait bounds were not satisfied: `Foo: Debug` +help: consider annotating `Foo` with `#[derive(Debug)]` + | +LL | #[derive(Debug)] + | error: aborting due to previous error diff --git a/src/test/ui/mismatched_types/numeric-literal-cast.stderr b/src/test/ui/mismatched_types/numeric-literal-cast.stderr index 7ab5224979..55e45a8f16 100644 --- a/src/test/ui/mismatched_types/numeric-literal-cast.stderr +++ b/src/test/ui/mismatched_types/numeric-literal-cast.stderr @@ -7,7 +7,7 @@ LL | foo(1u8); help: change the type of the numeric literal from `u8` to `u16` | LL | foo(1u16); - | ~~~~ + | ~~~ error[E0308]: mismatched types --> $DIR/numeric-literal-cast.rs:8:10 @@ -18,7 +18,7 @@ LL | foo1(2f32); help: change the type of the numeric literal from `f32` to `f64` | LL | foo1(2f64); - | ~~~~ + | ~~~ error[E0308]: mismatched types --> $DIR/numeric-literal-cast.rs:10:10 @@ -29,7 +29,7 @@ LL | foo2(3i16); help: change the type of the numeric literal from `i16` to `i32` | LL | foo2(3i32); - | ~~~~ + | ~~~ error: aborting due to 3 previous errors diff --git a/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.rs b/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.rs index ad59462e9b..44ec28f53c 100644 --- a/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.rs +++ b/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.rs @@ -16,5 +16,6 @@ pub fn main() { let z = call_it(3, f); //~^ ERROR type mismatch //~| NOTE expected signature of `fn(isize, isize) -> _` + //~| NOTE required by a bound introduced by this call println!("{}", z); } diff --git a/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.stderr b/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.stderr index 4406f8a9e5..f9ef5bc4e3 100644 --- a/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.stderr +++ b/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.stderr @@ -5,7 +5,9 @@ LL | let f = to_fn_mut(|x: usize, y: isize| -> isize { (x as isize) + y }); | ----------------------------- found signature of `fn(usize, isize) -> _` LL | LL | let z = call_it(3, f); - | ^ expected signature of `fn(isize, isize) -> _` + | ------- ^ expected signature of `fn(isize, isize) -> _` + | | + | required by a bound introduced by this call | note: required by a bound in `call_it` --> $DIR/unboxed-closures-vtable-mismatch.rs:7:14 diff --git a/src/test/ui/missing/missing-alloc_error_handler.stderr b/src/test/ui/missing/missing-alloc_error_handler.stderr index 511d0788b4..ed84493deb 100644 --- a/src/test/ui/missing/missing-alloc_error_handler.stderr +++ b/src/test/ui/missing/missing-alloc_error_handler.stderr @@ -1,6 +1,6 @@ -error: `#[alloc_error_handler]` function required, but not found. +error: `#[alloc_error_handler]` function required, but not found -note: Use `#![feature(default_alloc_error_handler)]` for a default error handler. +note: Use `#![feature(default_alloc_error_handler)]` for a default error handler error: aborting due to previous error diff --git a/src/test/ui/missing/missing-allocator.stderr b/src/test/ui/missing/missing-allocator.stderr index 59648c42a5..0da5651c18 100644 --- a/src/test/ui/missing/missing-allocator.stderr +++ b/src/test/ui/missing/missing-allocator.stderr @@ -1,4 +1,4 @@ -error: no global memory allocator found but one is required; link to std or add `#[global_allocator]` to a static item that implements the GlobalAlloc trait. +error: no global memory allocator found but one is required; link to std or add `#[global_allocator]` to a static item that implements the GlobalAlloc trait error: aborting due to previous error diff --git a/src/test/ui/modules/issue-56411.stderr b/src/test/ui/modules/issue-56411.stderr index cbeaafd926..5ab4542b04 100644 --- a/src/test/ui/modules/issue-56411.stderr +++ b/src/test/ui/modules/issue-56411.stderr @@ -10,7 +10,7 @@ LL | pub use self::$name; | you can use `as` to change the binding name of the import ... LL | import!(("issue-56411-aux.rs", issue_56411_aux)); - | ------------------------------------------------- in this macro invocation + | ------------------------------------------------ in this macro invocation | = 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) @@ -22,7 +22,7 @@ LL | pub use self::$name; | ^^^^^^^^^^^ re-export of private `issue_56411_aux` ... LL | import!(("issue-56411-aux.rs", issue_56411_aux)); - | ------------------------------------------------- in this macro invocation + | ------------------------------------------------ in this macro invocation | = note: consider declaring type or module `issue_56411_aux` with `pub` = note: this error originates in the macro `import` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/modules/path-invalid-form.rs b/src/test/ui/modules/path-invalid-form.rs new file mode 100644 index 0000000000..713ef4a795 --- /dev/null +++ b/src/test/ui/modules/path-invalid-form.rs @@ -0,0 +1,4 @@ +#[path = 123] //~ ERROR malformed `path` attribute +mod foo; + +fn main() {} diff --git a/src/test/ui/modules/path-invalid-form.stderr b/src/test/ui/modules/path-invalid-form.stderr new file mode 100644 index 0000000000..7e8aa44ef8 --- /dev/null +++ b/src/test/ui/modules/path-invalid-form.stderr @@ -0,0 +1,8 @@ +error: malformed `path` attribute input + --> $DIR/path-invalid-form.rs:1:1 + | +LL | #[path = 123] + | ^^^^^^^^^^^^^ help: must be of the form: `#[path = "file"]` + +error: aborting due to previous error + diff --git a/src/test/ui/modules/path-macro.rs b/src/test/ui/modules/path-macro.rs new file mode 100644 index 0000000000..ce2d1e2da2 --- /dev/null +++ b/src/test/ui/modules/path-macro.rs @@ -0,0 +1,8 @@ +macro_rules! foo { + () => {"bar.rs"}; +} + +#[path = foo!()] //~ ERROR malformed `path` attribute +mod abc; + +fn main() {} diff --git a/src/test/ui/modules/path-macro.stderr b/src/test/ui/modules/path-macro.stderr new file mode 100644 index 0000000000..9a2e01ea26 --- /dev/null +++ b/src/test/ui/modules/path-macro.stderr @@ -0,0 +1,8 @@ +error: malformed `path` attribute input + --> $DIR/path-macro.rs:5:1 + | +LL | #[path = foo!()] + | ^^^^^^^^^^^^^^^^ help: must be of the form: `#[path = "file"]` + +error: aborting due to previous error + diff --git a/src/test/ui/monomorphize-abi-alignment.rs b/src/test/ui/monomorphize-abi-alignment.rs index 637b09fc04..a8d8bd1d5f 100644 --- a/src/test/ui/monomorphize-abi-alignment.rs +++ b/src/test/ui/monomorphize-abi-alignment.rs @@ -1,6 +1,7 @@ // run-pass #![allow(non_upper_case_globals)] +#![allow(dead_code)] /*! * On x86_64-linux-gnu and possibly other platforms, structs get 8-byte "preferred" alignment, * but their "ABI" alignment (i.e., what actually matters for data layout) is the largest alignment diff --git a/src/test/ui/moves/issue-72649-uninit-in-loop.rs b/src/test/ui/moves/issue-72649-uninit-in-loop.rs new file mode 100644 index 0000000000..e6bc4e22ec --- /dev/null +++ b/src/test/ui/moves/issue-72649-uninit-in-loop.rs @@ -0,0 +1,74 @@ +// Regression test for issue #72649 +// Tests that we don't emit spurious +// 'value moved in previous iteration of loop' message + +struct NonCopy; + +fn good() { + loop { + let value = NonCopy{}; + let _used = value; + } +} + +fn moved_here_1() { + loop { + let value = NonCopy{}; + //~^ NOTE move occurs because `value` has type `NonCopy`, which does not implement the `Copy` trait + let _used = value; + //~^ NOTE value moved here + let _used2 = value; //~ ERROR use of moved value: `value` + //~^ NOTE value used here after move + } +} + +fn moved_here_2() { + let value = NonCopy{}; + //~^ NOTE move occurs because `value` has type `NonCopy`, which does not implement the `Copy` trait + loop { + let _used = value; + //~^ NOTE value moved here + loop { + let _used2 = value; //~ ERROR use of moved value: `value` + //~^ NOTE value used here after move + } + } +} + +fn moved_loop_1() { + let value = NonCopy{}; + //~^ NOTE move occurs because `value` has type `NonCopy`, which does not implement the `Copy` trait + loop { + let _used = value; //~ ERROR use of moved value: `value` + //~^ NOTE value moved here, in previous iteration of loop + } +} + +fn moved_loop_2() { + let mut value = NonCopy{}; + //~^ NOTE move occurs because `value` has type `NonCopy`, which does not implement the `Copy` trait + let _used = value; + value = NonCopy{}; + loop { + let _used2 = value; //~ ERROR use of moved value: `value` + //~^ NOTE value moved here, in previous iteration of loop + } +} + +fn uninit_1() { + loop { + let value: NonCopy; + let _used = value; //~ ERROR use of possibly-uninitialized variable: `value` + //~^ NOTE use of possibly-uninitialized `value` + } +} + +fn uninit_2() { + let mut value: NonCopy; + loop { + let _used = value; //~ ERROR use of possibly-uninitialized variable: `value` + //~^ NOTE use of possibly-uninitialized `value` + } +} + +fn main() {} diff --git a/src/test/ui/moves/issue-72649-uninit-in-loop.stderr b/src/test/ui/moves/issue-72649-uninit-in-loop.stderr new file mode 100644 index 0000000000..076d3dff14 --- /dev/null +++ b/src/test/ui/moves/issue-72649-uninit-in-loop.stderr @@ -0,0 +1,58 @@ +error[E0382]: use of moved value: `value` + --> $DIR/issue-72649-uninit-in-loop.rs:20:22 + | +LL | let value = NonCopy{}; + | ----- move occurs because `value` has type `NonCopy`, which does not implement the `Copy` trait +LL | +LL | let _used = value; + | ----- value moved here +LL | +LL | let _used2 = value; + | ^^^^^ value used here after move + +error[E0382]: use of moved value: `value` + --> $DIR/issue-72649-uninit-in-loop.rs:32:26 + | +LL | let value = NonCopy{}; + | ----- move occurs because `value` has type `NonCopy`, which does not implement the `Copy` trait +... +LL | let _used = value; + | ----- value moved here +... +LL | let _used2 = value; + | ^^^^^ value used here after move + +error[E0382]: use of moved value: `value` + --> $DIR/issue-72649-uninit-in-loop.rs:42:21 + | +LL | let value = NonCopy{}; + | ----- move occurs because `value` has type `NonCopy`, which does not implement the `Copy` trait +... +LL | let _used = value; + | ^^^^^ value moved here, in previous iteration of loop + +error[E0382]: use of moved value: `value` + --> $DIR/issue-72649-uninit-in-loop.rs:53:22 + | +LL | let mut value = NonCopy{}; + | --------- move occurs because `value` has type `NonCopy`, which does not implement the `Copy` trait +... +LL | let _used2 = value; + | ^^^^^ value moved here, in previous iteration of loop + +error[E0381]: use of possibly-uninitialized variable: `value` + --> $DIR/issue-72649-uninit-in-loop.rs:61:21 + | +LL | let _used = value; + | ^^^^^ use of possibly-uninitialized `value` + +error[E0381]: use of possibly-uninitialized variable: `value` + --> $DIR/issue-72649-uninit-in-loop.rs:69:21 + | +LL | let _used = value; + | ^^^^^ use of possibly-uninitialized `value` + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0381, E0382. +For more information about an error, try `rustc --explain E0381`. diff --git a/src/test/ui/moves/move-1-unique.rs b/src/test/ui/moves/move-1-unique.rs index 48baead074..f98d075d18 100644 --- a/src/test/ui/moves/move-1-unique.rs +++ b/src/test/ui/moves/move-1-unique.rs @@ -1,6 +1,6 @@ // run-pass #![allow(unused_mut)] -#![feature(box_syntax)] +#![allow(dead_code)] #[derive(Clone)] struct Triple { @@ -12,12 +12,12 @@ struct Triple { fn test(x: bool, foo: Box) -> isize { let bar = foo; let mut y: Box; - if x { y = bar; } else { y = box Triple{x: 4, y: 5, z: 6}; } + if x { y = bar; } else { y = Box::new(Triple{x: 4, y: 5, z: 6}); } return y.y; } pub fn main() { - let x: Box<_> = box Triple{x: 1, y: 2, z: 3}; + let x: Box<_> = Box::new(Triple{x: 1, y: 2, z: 3}); assert_eq!(test(true, x.clone()), 2); assert_eq!(test(true, x.clone()), 2); assert_eq!(test(true, x.clone()), 2); diff --git a/src/test/ui/moves/move-2-unique.rs b/src/test/ui/moves/move-2-unique.rs index 910a88c102..8fda3c1c86 100644 --- a/src/test/ui/moves/move-2-unique.rs +++ b/src/test/ui/moves/move-2-unique.rs @@ -1,11 +1,10 @@ // run-pass #![allow(dead_code)] -#![feature(box_syntax)] struct X { x: isize, y: isize, z: isize } pub fn main() { - let x: Box<_> = box X{x: 1, y: 2, z: 3}; + let x: Box<_> = Box::new(X {x: 1, y: 2, z: 3}); let y = x; assert_eq!(y.y, 2); } diff --git a/src/test/ui/moves/move-2.rs b/src/test/ui/moves/move-2.rs index 4ad53e96e5..5e01008746 100644 --- a/src/test/ui/moves/move-2.rs +++ b/src/test/ui/moves/move-2.rs @@ -1,7 +1,6 @@ // run-pass #![allow(dead_code)] -#![feature(box_syntax)] struct X { x: isize, y: isize, z: isize } -pub fn main() { let x: Box<_> = box X {x: 1, y: 2, z: 3}; let y = x; assert_eq!(y.y, 2); } +pub fn main() { let x: Box<_> = Box::new(X {x: 1, y: 2, z: 3}); let y = x; assert_eq!(y.y, 2); } diff --git a/src/test/ui/moves/move-3-unique.rs b/src/test/ui/moves/move-3-unique.rs index 55b10e057d..8e5df2c3ff 100644 --- a/src/test/ui/moves/move-3-unique.rs +++ b/src/test/ui/moves/move-3-unique.rs @@ -1,6 +1,6 @@ // run-pass #![allow(unused_mut)] -#![feature(box_syntax)] +#![allow(dead_code)] #[derive(Clone)] struct Triple { @@ -12,12 +12,12 @@ struct Triple { fn test(x: bool, foo: Box) -> isize { let bar = foo; let mut y: Box; - if x { y = bar; } else { y = box Triple {x: 4, y: 5, z: 6}; } + if x { y = bar; } else { y = Box::new(Triple {x: 4, y: 5, z: 6}); } return y.y; } pub fn main() { - let x: Box<_> = box Triple{x: 1, y: 2, z: 3}; + let x: Box<_> = Box::new(Triple{x: 1, y: 2, z: 3}); for _ in 0_usize..10000_usize { assert_eq!(test(true, x.clone()), 2); } diff --git a/src/test/ui/moves/move-4-unique.rs b/src/test/ui/moves/move-4-unique.rs index 1787caadb7..24aec7ea62 100644 --- a/src/test/ui/moves/move-4-unique.rs +++ b/src/test/ui/moves/move-4-unique.rs @@ -1,6 +1,5 @@ // run-pass #![allow(dead_code)] -#![feature(box_syntax)] struct Triple {a: isize, b: isize, c: isize} @@ -13,7 +12,7 @@ fn test(foo: Box) -> Box { } pub fn main() { - let x = box Triple{a: 1, b: 2, c: 3}; + let x = Box::new(Triple{a: 1, b: 2, c: 3}); let y = test(x); assert_eq!(y.c, 3); } diff --git a/src/test/ui/moves/move-4.rs b/src/test/ui/moves/move-4.rs index c87c605df7..63aa031a66 100644 --- a/src/test/ui/moves/move-4.rs +++ b/src/test/ui/moves/move-4.rs @@ -1,6 +1,5 @@ // run-pass #![allow(dead_code)] -#![feature(box_syntax)] struct Triple { a: isize, b: isize, c: isize } @@ -13,7 +12,7 @@ fn test(foo: Box) -> Box { } pub fn main() { - let x = box Triple{a: 1, b: 2, c: 3}; + let x = Box::new(Triple{ a: 1, b: 2, c: 3 }); let y = test(x); assert_eq!(y.c, 3); } diff --git a/src/test/ui/moves/move-arg-2-unique.rs b/src/test/ui/moves/move-arg-2-unique.rs index fcfd5e1476..9622c83750 100644 --- a/src/test/ui/moves/move-arg-2-unique.rs +++ b/src/test/ui/moves/move-arg-2-unique.rs @@ -1,13 +1,12 @@ // run-pass -#![feature(box_syntax)] fn test(foo: Box> ) { assert_eq!((*foo)[0], 10); } pub fn main() { - let x = box vec![10]; + let x = Box::new(vec![10]); // Test forgetting a local by move-in test(x); // Test forgetting a temporary by move-in. - test(box vec![10]); + test(Box::new(vec![10])); } diff --git a/src/test/ui/moves/move-arg-2.rs b/src/test/ui/moves/move-arg-2.rs index 4cd1f6fe81..77ee06e192 100644 --- a/src/test/ui/moves/move-arg-2.rs +++ b/src/test/ui/moves/move-arg-2.rs @@ -1,13 +1,12 @@ // run-pass -#![feature(box_syntax)] fn test(foo: Box>) { assert_eq!((*foo)[0], 10); } pub fn main() { - let x = box vec![10]; + let x = Box::new(vec![10]); // Test forgetting a local by move-in test(x); // Test forgetting a temporary by move-in. - test(box vec![10]); + test(Box::new(vec![10])); } diff --git a/src/test/ui/moves/move-fn-self-receiver.stderr b/src/test/ui/moves/move-fn-self-receiver.stderr index eca6bb9296..57be5fb4d8 100644 --- a/src/test/ui/moves/move-fn-self-receiver.stderr +++ b/src/test/ui/moves/move-fn-self-receiver.stderr @@ -75,7 +75,7 @@ error[E0505]: cannot move out of `mut_foo` because it is borrowed --> $DIR/move-fn-self-receiver.rs:50:5 | LL | let ret = mut_foo.use_mut_self(); - | ------- borrow of `mut_foo` occurs here + | ---------------------- borrow of `mut_foo` occurs here LL | mut_foo; | ^^^^^^^ move out of `mut_foo` occurs here LL | ret; diff --git a/src/test/ui/moves/move-guard-same-consts.rs b/src/test/ui/moves/move-guard-same-consts.rs index a2beb368b6..b96ef8e19e 100644 --- a/src/test/ui/moves/move-guard-same-consts.rs +++ b/src/test/ui/moves/move-guard-same-consts.rs @@ -2,16 +2,16 @@ // arms whose patterns were composed solely of constants to not have // them linked in the cfg. // -// THis was broken for various reasons. In particular, that hack was +// This was broken for various reasons. In particular, that hack was // originally authored under the assunption that other checks // elsewhere would ensure that the two patterns did not overlap. But // that assumption did not hold, at least not in the long run (namely, // overlapping patterns were turned into warnings rather than errors). -#![feature(box_syntax)] + fn main() { - let x: Box<_> = box 1; + let x: Box<_> = Box::new(1); let v = (1, 2); diff --git a/src/test/ui/moves/move-guard-same-consts.stderr b/src/test/ui/moves/move-guard-same-consts.stderr index 5fc8a54993..2048fefefa 100644 --- a/src/test/ui/moves/move-guard-same-consts.stderr +++ b/src/test/ui/moves/move-guard-same-consts.stderr @@ -1,7 +1,7 @@ error[E0382]: use of moved value: `x` --> $DIR/move-guard-same-consts.rs:20:24 | -LL | let x: Box<_> = box 1; +LL | let x: Box<_> = Box::new(1); | - move occurs because `x` has type `Box`, which does not implement the `Copy` trait ... LL | (1, 2) if take(x) => (), diff --git a/src/test/ui/moves/move-in-guard-1.rs b/src/test/ui/moves/move-in-guard-1.rs index 9c50782e64..36e39fea6a 100644 --- a/src/test/ui/moves/move-in-guard-1.rs +++ b/src/test/ui/moves/move-in-guard-1.rs @@ -1,7 +1,7 @@ -#![feature(box_syntax)] - pub fn main() { - let x: Box<_> = box 1; + + + let x: Box<_> = Box::new(1); let v = (1, 2); diff --git a/src/test/ui/moves/move-in-guard-1.stderr b/src/test/ui/moves/move-in-guard-1.stderr index d894209f51..5e9aa66b90 100644 --- a/src/test/ui/moves/move-in-guard-1.stderr +++ b/src/test/ui/moves/move-in-guard-1.stderr @@ -1,7 +1,7 @@ error[E0382]: use of moved value: `x` --> $DIR/move-in-guard-1.rs:10:24 | -LL | let x: Box<_> = box 1; +LL | let x: Box<_> = Box::new(1); | - move occurs because `x` has type `Box`, which does not implement the `Copy` trait ... LL | (1, _) if take(x) => (), diff --git a/src/test/ui/moves/move-in-guard-2.rs b/src/test/ui/moves/move-in-guard-2.rs index f478625a83..085b7ec6e0 100644 --- a/src/test/ui/moves/move-in-guard-2.rs +++ b/src/test/ui/moves/move-in-guard-2.rs @@ -1,7 +1,5 @@ -#![feature(box_syntax)] - pub fn main() { - let x: Box<_> = box 1; + let x: Box<_> = Box::new(1); let v = (1, 2); diff --git a/src/test/ui/moves/move-in-guard-2.stderr b/src/test/ui/moves/move-in-guard-2.stderr index a067d43389..ea350926b1 100644 --- a/src/test/ui/moves/move-in-guard-2.stderr +++ b/src/test/ui/moves/move-in-guard-2.stderr @@ -1,7 +1,7 @@ error[E0382]: use of moved value: `x` - --> $DIR/move-in-guard-2.rs:10:24 + --> $DIR/move-in-guard-2.rs:8:24 | -LL | let x: Box<_> = box 1; +LL | let x: Box<_> = Box::new(1); | - move occurs because `x` has type `Box`, which does not implement the `Copy` trait ... LL | (_, 2) if take(x) => (), diff --git a/src/test/ui/moves/move-out-of-tuple-field.rs b/src/test/ui/moves/move-out-of-tuple-field.rs index e5a505bb88..66912fa4d0 100644 --- a/src/test/ui/moves/move-out-of-tuple-field.rs +++ b/src/test/ui/moves/move-out-of-tuple-field.rs @@ -1,13 +1,13 @@ -#![feature(box_syntax)] - struct Foo(Box); + + fn main() { - let x: (Box<_>,) = (box 1,); + let x: (Box<_>,) = (Box::new(1),); let y = x.0; let z = x.0; //~ ERROR use of moved value: `x.0` - let x = Foo(box 1); + let x = Foo(Box::new(1)); let y = x.0; let z = x.0; //~ ERROR use of moved value: `x.0` } diff --git a/src/test/ui/moves/moves-based-on-type-block-bad.rs b/src/test/ui/moves/moves-based-on-type-block-bad.rs index 085e249c0f..eca33167f4 100644 --- a/src/test/ui/moves/moves-based-on-type-block-bad.rs +++ b/src/test/ui/moves/moves-based-on-type-block-bad.rs @@ -1,5 +1,5 @@ #![feature(box_patterns)] -#![feature(box_syntax)] + struct S { x: Box @@ -16,7 +16,7 @@ fn f(s: &S, g: G) where G: FnOnce(&S) { } fn main() { - let s = S { x: box E::Bar(box 42) }; + let s = S { x: Box::new(E::Bar(Box::new(42))) }; loop { f(&s, |hellothere| { match hellothere.x { //~ ERROR cannot move out diff --git a/src/test/ui/moves/moves-based-on-type-move-out-of-closure-env-issue-1965.rs b/src/test/ui/moves/moves-based-on-type-move-out-of-closure-env-issue-1965.rs index 52a5103865..76b7aab542 100644 --- a/src/test/ui/moves/moves-based-on-type-move-out-of-closure-env-issue-1965.rs +++ b/src/test/ui/moves/moves-based-on-type-move-out-of-closure-env-issue-1965.rs @@ -1,10 +1,10 @@ -#![feature(box_syntax, unboxed_closures)] +#![feature(unboxed_closures)] fn to_fn>(f: F) -> F { f } fn test(_x: Box) {} fn main() { - let i = box 3; + let i = Box::new(3); let _f = to_fn(|| test(i)); //~ ERROR cannot move out } diff --git a/src/test/ui/moves/moves-based-on-type-move-out-of-closure-env-issue-1965.stderr b/src/test/ui/moves/moves-based-on-type-move-out-of-closure-env-issue-1965.stderr index 9427ba546a..ce930eee2e 100644 --- a/src/test/ui/moves/moves-based-on-type-move-out-of-closure-env-issue-1965.stderr +++ b/src/test/ui/moves/moves-based-on-type-move-out-of-closure-env-issue-1965.stderr @@ -1,10 +1,13 @@ error[E0507]: cannot move out of `i`, a captured variable in an `Fn` closure --> $DIR/moves-based-on-type-move-out-of-closure-env-issue-1965.rs:9:28 | -LL | let i = box 3; +LL | let i = Box::new(3); | - captured outer variable LL | let _f = to_fn(|| test(i)); - | ^ move occurs because `i` has type `Box`, which does not implement the `Copy` trait + | --------^- + | | | + | | move occurs because `i` has type `Box`, which does not implement the `Copy` trait + | captured by this `Fn` closure error: aborting due to previous error diff --git a/src/test/ui/moves/moves-based-on-type-tuple.rs b/src/test/ui/moves/moves-based-on-type-tuple.rs index 828d90cd7a..2e67d8f8a6 100644 --- a/src/test/ui/moves/moves-based-on-type-tuple.rs +++ b/src/test/ui/moves/moves-based-on-type-tuple.rs @@ -1,10 +1,10 @@ -#![feature(box_syntax)] - fn dup(x: Box) -> Box<(Box,Box)> { - box (x, x) + + + Box::new((x, x)) //~^ use of moved value: `x` [E0382] } fn main() { - dup(box 3); + dup(Box::new(3)); } diff --git a/src/test/ui/moves/moves-based-on-type-tuple.stderr b/src/test/ui/moves/moves-based-on-type-tuple.stderr index a52c023e20..eef8ce61fa 100644 --- a/src/test/ui/moves/moves-based-on-type-tuple.stderr +++ b/src/test/ui/moves/moves-based-on-type-tuple.stderr @@ -1,12 +1,13 @@ error[E0382]: use of moved value: `x` - --> $DIR/moves-based-on-type-tuple.rs:4:13 + --> $DIR/moves-based-on-type-tuple.rs:4:18 | LL | fn dup(x: Box) -> Box<(Box,Box)> { | - move occurs because `x` has type `Box`, which does not implement the `Copy` trait -LL | box (x, x) - | - ^ value used here after move - | | - | value moved here +... +LL | Box::new((x, x)) + | - ^ value used here after move + | | + | value moved here error: aborting due to previous error diff --git a/src/test/ui/moves/moves-sru-moved-field.rs b/src/test/ui/moves/moves-sru-moved-field.rs index e620e5de92..72957c49fc 100644 --- a/src/test/ui/moves/moves-sru-moved-field.rs +++ b/src/test/ui/moves/moves-sru-moved-field.rs @@ -1,7 +1,7 @@ -#![feature(box_syntax)] - type Noncopyable = Box; + + struct Foo { copied: isize, moved: Box, @@ -10,8 +10,8 @@ struct Foo { fn test0(f: Foo, g: Noncopyable, h: Noncopyable) { // just copy implicitly copyable fields from `f`, no moves: - let _b = Foo {moved: box 1, noncopyable: g, ..f}; - let _c = Foo {moved: box 2, noncopyable: h, ..f}; + let _b = Foo {moved: Box::new(1), noncopyable: g, ..f}; + let _c = Foo {moved: Box::new(2), noncopyable: h, ..f}; } fn test1(f: Foo, g: Noncopyable, h: Noncopyable) { diff --git a/src/test/ui/mut-function-arguments.rs b/src/test/ui/mut-function-arguments.rs index 620d00edbb..1e682fc4b6 100644 --- a/src/test/ui/mut-function-arguments.rs +++ b/src/test/ui/mut-function-arguments.rs @@ -1,7 +1,5 @@ // run-pass -#![feature(box_syntax)] - fn f(mut y: Box) { *y = 5; assert_eq!(*y, 5); @@ -9,13 +7,13 @@ fn f(mut y: Box) { fn g() { let frob = |mut q: Box| { *q = 2; assert_eq!(*q, 2); }; - let w = box 37; + let w = Box::new(37); frob(w); } pub fn main() { - let z = box 17; + let z = Box::new(17); f(z); g(); } diff --git a/src/test/ui/mut/mut-cant-alias.stderr b/src/test/ui/mut/mut-cant-alias.stderr index d56e45db13..6046c076f2 100644 --- a/src/test/ui/mut/mut-cant-alias.stderr +++ b/src/test/ui/mut/mut-cant-alias.stderr @@ -6,7 +6,7 @@ LL | let b1 = &mut *b; LL | let b2 = &mut *b; | ^ second mutable borrow occurs here LL | b1.use_mut(); - | -- first borrow later used here + | ------------ first borrow later used here error: aborting due to previous error diff --git a/src/test/ui/mut/mut-cross-borrowing.rs b/src/test/ui/mut/mut-cross-borrowing.rs index 63e49c292e..080faab732 100644 --- a/src/test/ui/mut/mut-cross-borrowing.rs +++ b/src/test/ui/mut/mut-cross-borrowing.rs @@ -1,8 +1,8 @@ -#![feature(box_syntax)] - fn f(_: &mut isize) {} fn main() { - let mut x: Box<_> = box 3; + + let mut x: Box<_> = Box::new(3); + f(x) //~ ERROR mismatched types } diff --git a/src/test/ui/mut/mut-suggestion.stderr b/src/test/ui/mut/mut-suggestion.stderr index 245eaff4bb..cba284550b 100644 --- a/src/test/ui/mut/mut-suggestion.stderr +++ b/src/test/ui/mut/mut-suggestion.stderr @@ -5,7 +5,7 @@ LL | fn func(arg: S) { | --- help: consider changing this to be mutable: `mut arg` ... LL | arg.mutate(); - | ^^^ cannot borrow as mutable + | ^^^^^^^^^^^^ cannot borrow as mutable error[E0596]: cannot borrow `local` as mutable, as it is not declared as mutable --> $DIR/mut-suggestion.rs:20:5 @@ -14,7 +14,7 @@ LL | let local = S; | ----- help: consider changing this to be mutable: `mut local` ... LL | local.mutate(); - | ^^^^^ cannot borrow as mutable + | ^^^^^^^^^^^^^^ cannot borrow as mutable error: aborting due to 2 previous errors diff --git a/src/test/ui/mutexguard-sync.stderr b/src/test/ui/mutexguard-sync.stderr index 172e257ebf..b3c77b13ea 100644 --- a/src/test/ui/mutexguard-sync.stderr +++ b/src/test/ui/mutexguard-sync.stderr @@ -2,7 +2,9 @@ error[E0277]: `Cell` cannot be shared between threads safely --> $DIR/mutexguard-sync.rs:11:15 | LL | test_sync(guard); - | ^^^^^ `Cell` cannot be shared between threads safely + | --------- ^^^^^ `Cell` cannot be shared between threads safely + | | + | required by a bound introduced by this call | = help: the trait `Sync` is not implemented for `Cell` = note: required because of the requirements on the impl of `Sync` for `MutexGuard<'_, Cell>` diff --git a/src/test/ui/namespace/namespace-mix.stderr b/src/test/ui/namespace/namespace-mix.stderr index e4e1071638..b610857229 100644 --- a/src/test/ui/namespace/namespace-mix.stderr +++ b/src/test/ui/namespace/namespace-mix.stderr @@ -100,7 +100,9 @@ error[E0277]: the trait bound `c::Item: Impossible` is not satisfied --> $DIR/namespace-mix.rs:33:11 | LL | check(m1::S{}); - | ^^^^^^^ the trait `Impossible` is not implemented for `c::Item` + | ----- ^^^^^^^ the trait `Impossible` is not implemented for `c::Item` + | | + | required by a bound introduced by this call | note: required by a bound in `check` --> $DIR/namespace-mix.rs:21:13 @@ -112,7 +114,9 @@ error[E0277]: the trait bound `c::S: Impossible` is not satisfied --> $DIR/namespace-mix.rs:35:11 | LL | check(m2::S{}); - | ^^^^^^^ the trait `Impossible` is not implemented for `c::S` + | ----- ^^^^^^^ the trait `Impossible` is not implemented for `c::S` + | | + | required by a bound introduced by this call | note: required by a bound in `check` --> $DIR/namespace-mix.rs:21:13 @@ -124,7 +128,9 @@ error[E0277]: the trait bound `c::Item: Impossible` is not satisfied --> $DIR/namespace-mix.rs:36:11 | LL | check(m2::S); - | ^^^^^ the trait `Impossible` is not implemented for `c::Item` + | ----- ^^^^^ the trait `Impossible` is not implemented for `c::Item` + | | + | required by a bound introduced by this call | note: required by a bound in `check` --> $DIR/namespace-mix.rs:21:13 @@ -136,7 +142,9 @@ error[E0277]: the trait bound `namespace_mix::c::Item: Impossible` is not satisf --> $DIR/namespace-mix.rs:39:11 | LL | check(xm1::S{}); - | ^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item` + | ----- ^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item` + | | + | required by a bound introduced by this call | note: required by a bound in `check` --> $DIR/namespace-mix.rs:21:13 @@ -148,7 +156,9 @@ error[E0277]: the trait bound `namespace_mix::c::S: Impossible` is not satisfied --> $DIR/namespace-mix.rs:41:11 | LL | check(xm2::S{}); - | ^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::S` + | ----- ^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::S` + | | + | required by a bound introduced by this call | note: required by a bound in `check` --> $DIR/namespace-mix.rs:21:13 @@ -160,7 +170,9 @@ error[E0277]: the trait bound `namespace_mix::c::Item: Impossible` is not satisf --> $DIR/namespace-mix.rs:42:11 | LL | check(xm2::S); - | ^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item` + | ----- ^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item` + | | + | required by a bound introduced by this call | note: required by a bound in `check` --> $DIR/namespace-mix.rs:21:13 @@ -172,7 +184,9 @@ error[E0277]: the trait bound `c::Item: Impossible` is not satisfied --> $DIR/namespace-mix.rs:55:11 | LL | check(m3::TS{}); - | ^^^^^^^^ the trait `Impossible` is not implemented for `c::Item` + | ----- ^^^^^^^^ the trait `Impossible` is not implemented for `c::Item` + | | + | required by a bound introduced by this call | note: required by a bound in `check` --> $DIR/namespace-mix.rs:21:13 @@ -184,7 +198,9 @@ error[E0277]: the trait bound `fn() -> c::TS {c::TS}: Impossible` is not satisfi --> $DIR/namespace-mix.rs:56:11 | LL | check(m3::TS); - | ^^^^^^ the trait `Impossible` is not implemented for `fn() -> c::TS {c::TS}` + | ----- ^^^^^^ the trait `Impossible` is not implemented for `fn() -> c::TS {c::TS}` + | | + | required by a bound introduced by this call | note: required by a bound in `check` --> $DIR/namespace-mix.rs:21:13 @@ -196,7 +212,9 @@ error[E0277]: the trait bound `c::TS: Impossible` is not satisfied --> $DIR/namespace-mix.rs:57:11 | LL | check(m4::TS{}); - | ^^^^^^^^ the trait `Impossible` is not implemented for `c::TS` + | ----- ^^^^^^^^ the trait `Impossible` is not implemented for `c::TS` + | | + | required by a bound introduced by this call | note: required by a bound in `check` --> $DIR/namespace-mix.rs:21:13 @@ -208,7 +226,9 @@ error[E0277]: the trait bound `c::Item: Impossible` is not satisfied --> $DIR/namespace-mix.rs:58:11 | LL | check(m4::TS); - | ^^^^^^ the trait `Impossible` is not implemented for `c::Item` + | ----- ^^^^^^ the trait `Impossible` is not implemented for `c::Item` + | | + | required by a bound introduced by this call | note: required by a bound in `check` --> $DIR/namespace-mix.rs:21:13 @@ -220,7 +240,9 @@ error[E0277]: the trait bound `namespace_mix::c::Item: Impossible` is not satisf --> $DIR/namespace-mix.rs:61:11 | LL | check(xm3::TS{}); - | ^^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item` + | ----- ^^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item` + | | + | required by a bound introduced by this call | note: required by a bound in `check` --> $DIR/namespace-mix.rs:21:13 @@ -232,7 +254,9 @@ error[E0277]: the trait bound `fn() -> namespace_mix::c::TS {namespace_mix::c::T --> $DIR/namespace-mix.rs:62:11 | LL | check(xm3::TS); - | ^^^^^^^ the trait `Impossible` is not implemented for `fn() -> namespace_mix::c::TS {namespace_mix::c::TS}` + | ----- ^^^^^^^ the trait `Impossible` is not implemented for `fn() -> namespace_mix::c::TS {namespace_mix::c::TS}` + | | + | required by a bound introduced by this call | note: required by a bound in `check` --> $DIR/namespace-mix.rs:21:13 @@ -244,7 +268,9 @@ error[E0277]: the trait bound `namespace_mix::c::TS: Impossible` is not satisfie --> $DIR/namespace-mix.rs:63:11 | LL | check(xm4::TS{}); - | ^^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::TS` + | ----- ^^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::TS` + | | + | required by a bound introduced by this call | note: required by a bound in `check` --> $DIR/namespace-mix.rs:21:13 @@ -256,7 +282,9 @@ error[E0277]: the trait bound `namespace_mix::c::Item: Impossible` is not satisf --> $DIR/namespace-mix.rs:64:11 | LL | check(xm4::TS); - | ^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item` + | ----- ^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item` + | | + | required by a bound introduced by this call | note: required by a bound in `check` --> $DIR/namespace-mix.rs:21:13 @@ -268,7 +296,9 @@ error[E0277]: the trait bound `c::Item: Impossible` is not satisfied --> $DIR/namespace-mix.rs:77:11 | LL | check(m5::US{}); - | ^^^^^^^^ the trait `Impossible` is not implemented for `c::Item` + | ----- ^^^^^^^^ the trait `Impossible` is not implemented for `c::Item` + | | + | required by a bound introduced by this call | note: required by a bound in `check` --> $DIR/namespace-mix.rs:21:13 @@ -280,7 +310,9 @@ error[E0277]: the trait bound `c::US: Impossible` is not satisfied --> $DIR/namespace-mix.rs:78:11 | LL | check(m5::US); - | ^^^^^^ the trait `Impossible` is not implemented for `c::US` + | ----- ^^^^^^ the trait `Impossible` is not implemented for `c::US` + | | + | required by a bound introduced by this call | note: required by a bound in `check` --> $DIR/namespace-mix.rs:21:13 @@ -292,7 +324,9 @@ error[E0277]: the trait bound `c::US: Impossible` is not satisfied --> $DIR/namespace-mix.rs:79:11 | LL | check(m6::US{}); - | ^^^^^^^^ the trait `Impossible` is not implemented for `c::US` + | ----- ^^^^^^^^ the trait `Impossible` is not implemented for `c::US` + | | + | required by a bound introduced by this call | note: required by a bound in `check` --> $DIR/namespace-mix.rs:21:13 @@ -304,7 +338,9 @@ error[E0277]: the trait bound `c::Item: Impossible` is not satisfied --> $DIR/namespace-mix.rs:80:11 | LL | check(m6::US); - | ^^^^^^ the trait `Impossible` is not implemented for `c::Item` + | ----- ^^^^^^ the trait `Impossible` is not implemented for `c::Item` + | | + | required by a bound introduced by this call | note: required by a bound in `check` --> $DIR/namespace-mix.rs:21:13 @@ -316,7 +352,9 @@ error[E0277]: the trait bound `namespace_mix::c::Item: Impossible` is not satisf --> $DIR/namespace-mix.rs:83:11 | LL | check(xm5::US{}); - | ^^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item` + | ----- ^^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item` + | | + | required by a bound introduced by this call | note: required by a bound in `check` --> $DIR/namespace-mix.rs:21:13 @@ -328,7 +366,9 @@ error[E0277]: the trait bound `namespace_mix::c::US: Impossible` is not satisfie --> $DIR/namespace-mix.rs:84:11 | LL | check(xm5::US); - | ^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::US` + | ----- ^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::US` + | | + | required by a bound introduced by this call | note: required by a bound in `check` --> $DIR/namespace-mix.rs:21:13 @@ -340,7 +380,9 @@ error[E0277]: the trait bound `namespace_mix::c::US: Impossible` is not satisfie --> $DIR/namespace-mix.rs:85:11 | LL | check(xm6::US{}); - | ^^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::US` + | ----- ^^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::US` + | | + | required by a bound introduced by this call | note: required by a bound in `check` --> $DIR/namespace-mix.rs:21:13 @@ -352,7 +394,9 @@ error[E0277]: the trait bound `namespace_mix::c::Item: Impossible` is not satisf --> $DIR/namespace-mix.rs:86:11 | LL | check(xm6::US); - | ^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item` + | ----- ^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item` + | | + | required by a bound introduced by this call | note: required by a bound in `check` --> $DIR/namespace-mix.rs:21:13 @@ -364,7 +408,9 @@ error[E0277]: the trait bound `c::Item: Impossible` is not satisfied --> $DIR/namespace-mix.rs:99:11 | LL | check(m7::V{}); - | ^^^^^^^ the trait `Impossible` is not implemented for `c::Item` + | ----- ^^^^^^^ the trait `Impossible` is not implemented for `c::Item` + | | + | required by a bound introduced by this call | note: required by a bound in `check` --> $DIR/namespace-mix.rs:21:13 @@ -376,7 +422,9 @@ error[E0277]: the trait bound `c::E: Impossible` is not satisfied --> $DIR/namespace-mix.rs:101:11 | LL | check(m8::V{}); - | ^^^^^^^ the trait `Impossible` is not implemented for `c::E` + | ----- ^^^^^^^ the trait `Impossible` is not implemented for `c::E` + | | + | required by a bound introduced by this call | note: required by a bound in `check` --> $DIR/namespace-mix.rs:21:13 @@ -388,7 +436,9 @@ error[E0277]: the trait bound `c::Item: Impossible` is not satisfied --> $DIR/namespace-mix.rs:102:11 | LL | check(m8::V); - | ^^^^^ the trait `Impossible` is not implemented for `c::Item` + | ----- ^^^^^ the trait `Impossible` is not implemented for `c::Item` + | | + | required by a bound introduced by this call | note: required by a bound in `check` --> $DIR/namespace-mix.rs:21:13 @@ -400,7 +450,9 @@ error[E0277]: the trait bound `namespace_mix::c::Item: Impossible` is not satisf --> $DIR/namespace-mix.rs:105:11 | LL | check(xm7::V{}); - | ^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item` + | ----- ^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item` + | | + | required by a bound introduced by this call | note: required by a bound in `check` --> $DIR/namespace-mix.rs:21:13 @@ -412,7 +464,9 @@ error[E0277]: the trait bound `namespace_mix::c::E: Impossible` is not satisfied --> $DIR/namespace-mix.rs:107:11 | LL | check(xm8::V{}); - | ^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::E` + | ----- ^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::E` + | | + | required by a bound introduced by this call | note: required by a bound in `check` --> $DIR/namespace-mix.rs:21:13 @@ -424,7 +478,9 @@ error[E0277]: the trait bound `namespace_mix::c::Item: Impossible` is not satisf --> $DIR/namespace-mix.rs:108:11 | LL | check(xm8::V); - | ^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item` + | ----- ^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item` + | | + | required by a bound introduced by this call | note: required by a bound in `check` --> $DIR/namespace-mix.rs:21:13 @@ -436,7 +492,9 @@ error[E0277]: the trait bound `c::Item: Impossible` is not satisfied --> $DIR/namespace-mix.rs:121:11 | LL | check(m9::TV{}); - | ^^^^^^^^ the trait `Impossible` is not implemented for `c::Item` + | ----- ^^^^^^^^ the trait `Impossible` is not implemented for `c::Item` + | | + | required by a bound introduced by this call | note: required by a bound in `check` --> $DIR/namespace-mix.rs:21:13 @@ -448,7 +506,9 @@ error[E0277]: the trait bound `fn() -> c::E {c::E::TV}: Impossible` is not satis --> $DIR/namespace-mix.rs:122:11 | LL | check(m9::TV); - | ^^^^^^ the trait `Impossible` is not implemented for `fn() -> c::E {c::E::TV}` + | ----- ^^^^^^ the trait `Impossible` is not implemented for `fn() -> c::E {c::E::TV}` + | | + | required by a bound introduced by this call | note: required by a bound in `check` --> $DIR/namespace-mix.rs:21:13 @@ -460,7 +520,9 @@ error[E0277]: the trait bound `c::E: Impossible` is not satisfied --> $DIR/namespace-mix.rs:123:11 | LL | check(mA::TV{}); - | ^^^^^^^^ the trait `Impossible` is not implemented for `c::E` + | ----- ^^^^^^^^ the trait `Impossible` is not implemented for `c::E` + | | + | required by a bound introduced by this call | note: required by a bound in `check` --> $DIR/namespace-mix.rs:21:13 @@ -472,7 +534,9 @@ error[E0277]: the trait bound `c::Item: Impossible` is not satisfied --> $DIR/namespace-mix.rs:124:11 | LL | check(mA::TV); - | ^^^^^^ the trait `Impossible` is not implemented for `c::Item` + | ----- ^^^^^^ the trait `Impossible` is not implemented for `c::Item` + | | + | required by a bound introduced by this call | note: required by a bound in `check` --> $DIR/namespace-mix.rs:21:13 @@ -484,7 +548,9 @@ error[E0277]: the trait bound `namespace_mix::c::Item: Impossible` is not satisf --> $DIR/namespace-mix.rs:127:11 | LL | check(xm9::TV{}); - | ^^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item` + | ----- ^^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item` + | | + | required by a bound introduced by this call | note: required by a bound in `check` --> $DIR/namespace-mix.rs:21:13 @@ -496,7 +562,9 @@ error[E0277]: the trait bound `fn() -> namespace_mix::c::E {namespace_mix::xm7:: --> $DIR/namespace-mix.rs:128:11 | LL | check(xm9::TV); - | ^^^^^^^ the trait `Impossible` is not implemented for `fn() -> namespace_mix::c::E {namespace_mix::xm7::TV}` + | ----- ^^^^^^^ the trait `Impossible` is not implemented for `fn() -> namespace_mix::c::E {namespace_mix::xm7::TV}` + | | + | required by a bound introduced by this call | note: required by a bound in `check` --> $DIR/namespace-mix.rs:21:13 @@ -508,7 +576,9 @@ error[E0277]: the trait bound `namespace_mix::c::E: Impossible` is not satisfied --> $DIR/namespace-mix.rs:129:11 | LL | check(xmA::TV{}); - | ^^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::E` + | ----- ^^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::E` + | | + | required by a bound introduced by this call | note: required by a bound in `check` --> $DIR/namespace-mix.rs:21:13 @@ -520,7 +590,9 @@ error[E0277]: the trait bound `namespace_mix::c::Item: Impossible` is not satisf --> $DIR/namespace-mix.rs:130:11 | LL | check(xmA::TV); - | ^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item` + | ----- ^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item` + | | + | required by a bound introduced by this call | note: required by a bound in `check` --> $DIR/namespace-mix.rs:21:13 @@ -532,7 +604,9 @@ error[E0277]: the trait bound `c::Item: Impossible` is not satisfied --> $DIR/namespace-mix.rs:143:11 | LL | check(mB::UV{}); - | ^^^^^^^^ the trait `Impossible` is not implemented for `c::Item` + | ----- ^^^^^^^^ the trait `Impossible` is not implemented for `c::Item` + | | + | required by a bound introduced by this call | note: required by a bound in `check` --> $DIR/namespace-mix.rs:21:13 @@ -544,7 +618,9 @@ error[E0277]: the trait bound `c::E: Impossible` is not satisfied --> $DIR/namespace-mix.rs:144:11 | LL | check(mB::UV); - | ^^^^^^ the trait `Impossible` is not implemented for `c::E` + | ----- ^^^^^^ the trait `Impossible` is not implemented for `c::E` + | | + | required by a bound introduced by this call | note: required by a bound in `check` --> $DIR/namespace-mix.rs:21:13 @@ -556,7 +632,9 @@ error[E0277]: the trait bound `c::E: Impossible` is not satisfied --> $DIR/namespace-mix.rs:145:11 | LL | check(mC::UV{}); - | ^^^^^^^^ the trait `Impossible` is not implemented for `c::E` + | ----- ^^^^^^^^ the trait `Impossible` is not implemented for `c::E` + | | + | required by a bound introduced by this call | note: required by a bound in `check` --> $DIR/namespace-mix.rs:21:13 @@ -568,7 +646,9 @@ error[E0277]: the trait bound `c::Item: Impossible` is not satisfied --> $DIR/namespace-mix.rs:146:11 | LL | check(mC::UV); - | ^^^^^^ the trait `Impossible` is not implemented for `c::Item` + | ----- ^^^^^^ the trait `Impossible` is not implemented for `c::Item` + | | + | required by a bound introduced by this call | note: required by a bound in `check` --> $DIR/namespace-mix.rs:21:13 @@ -580,7 +660,9 @@ error[E0277]: the trait bound `namespace_mix::c::Item: Impossible` is not satisf --> $DIR/namespace-mix.rs:149:11 | LL | check(xmB::UV{}); - | ^^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item` + | ----- ^^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item` + | | + | required by a bound introduced by this call | note: required by a bound in `check` --> $DIR/namespace-mix.rs:21:13 @@ -592,7 +674,9 @@ error[E0277]: the trait bound `namespace_mix::c::E: Impossible` is not satisfied --> $DIR/namespace-mix.rs:150:11 | LL | check(xmB::UV); - | ^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::E` + | ----- ^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::E` + | | + | required by a bound introduced by this call | note: required by a bound in `check` --> $DIR/namespace-mix.rs:21:13 @@ -604,7 +688,9 @@ error[E0277]: the trait bound `namespace_mix::c::E: Impossible` is not satisfied --> $DIR/namespace-mix.rs:151:11 | LL | check(xmC::UV{}); - | ^^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::E` + | ----- ^^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::E` + | | + | required by a bound introduced by this call | note: required by a bound in `check` --> $DIR/namespace-mix.rs:21:13 @@ -616,7 +702,9 @@ error[E0277]: the trait bound `namespace_mix::c::Item: Impossible` is not satisf --> $DIR/namespace-mix.rs:152:11 | LL | check(xmC::UV); - | ^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item` + | ----- ^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item` + | | + | required by a bound introduced by this call | note: required by a bound in `check` --> $DIR/namespace-mix.rs:21:13 diff --git a/src/test/ui/native-library-link-flags/mix-bundle-and-whole-archive-link-attr.rs b/src/test/ui/native-library-link-flags/mix-bundle-and-whole-archive-link-attr.rs new file mode 100644 index 0000000000..c3714a3845 --- /dev/null +++ b/src/test/ui/native-library-link-flags/mix-bundle-and-whole-archive-link-attr.rs @@ -0,0 +1,12 @@ +// compile-flags: -Zunstable-options --crate-type rlib +// build-fail +// error-pattern: the linking modifiers `+bundle` and `+whole-archive` are not compatible with each other when generating rlibs + +#![feature(native_link_modifiers)] +#![feature(native_link_modifiers_bundle)] +#![feature(native_link_modifiers_whole_archive)] + +#[link(name = "mylib", kind = "static", modifiers = "+bundle,+whole-archive")] +extern "C" { } + +fn main() { } diff --git a/src/test/ui/native-library-link-flags/mix-bundle-and-whole-archive-link-attr.stderr b/src/test/ui/native-library-link-flags/mix-bundle-and-whole-archive-link-attr.stderr new file mode 100644 index 0000000000..246efb8d62 --- /dev/null +++ b/src/test/ui/native-library-link-flags/mix-bundle-and-whole-archive-link-attr.stderr @@ -0,0 +1,6 @@ +error: the linking modifiers `+bundle` and `+whole-archive` are not compatible with each other when generating rlibs + +error: could not find native static library `mylib`, perhaps an -L flag is missing? + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/native-library-link-flags/mix-bundle-and-whole-archive.rs b/src/test/ui/native-library-link-flags/mix-bundle-and-whole-archive.rs new file mode 100644 index 0000000000..1d0768d99c --- /dev/null +++ b/src/test/ui/native-library-link-flags/mix-bundle-and-whole-archive.rs @@ -0,0 +1,7 @@ +// Mixing +bundle and +whole-archive is not allowed + +// compile-flags: -l static:+bundle,+whole-archive=mylib -Zunstable-options --crate-type rlib +// build-fail +// error-pattern: the linking modifiers `+bundle` and `+whole-archive` are not compatible with each other when generating rlibs + +fn main() { } diff --git a/src/test/ui/native-library-link-flags/mix-bundle-and-whole-archive.stderr b/src/test/ui/native-library-link-flags/mix-bundle-and-whole-archive.stderr new file mode 100644 index 0000000000..246efb8d62 --- /dev/null +++ b/src/test/ui/native-library-link-flags/mix-bundle-and-whole-archive.stderr @@ -0,0 +1,6 @@ +error: the linking modifiers `+bundle` and `+whole-archive` are not compatible with each other when generating rlibs + +error: could not find native static library `mylib`, perhaps an -L flag is missing? + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/never_type/defaulted-never-note.stderr b/src/test/ui/never_type/defaulted-never-note.fallback.stderr similarity index 78% rename from src/test/ui/never_type/defaulted-never-note.stderr rename to src/test/ui/never_type/defaulted-never-note.fallback.stderr index 109a81a5ca..b105f03f81 100644 --- a/src/test/ui/never_type/defaulted-never-note.stderr +++ b/src/test/ui/never_type/defaulted-never-note.fallback.stderr @@ -1,14 +1,14 @@ error[E0277]: the trait bound `!: ImplementedForUnitButNotNever` is not satisfied - --> $DIR/defaulted-never-note.rs:26:5 + --> $DIR/defaulted-never-note.rs:30:5 | LL | foo(_x); | ^^^ the trait `ImplementedForUnitButNotNever` is not implemented for `!` | - = note: this trait is implemented for `()`. - = note: this error might have been caused by changes to Rust's type-inference algorithm (see issue #48950 for more information). + = note: this trait is implemented for `()` + = note: this error might have been caused by changes to Rust's type-inference algorithm (see issue #48950 for more information) = help: did you intend to use the type `()` here instead? note: required by a bound in `foo` - --> $DIR/defaulted-never-note.rs:21:11 + --> $DIR/defaulted-never-note.rs:25:11 | LL | fn foo(_t: T) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `foo` diff --git a/src/test/ui/never_type/defaulted-never-note.rs b/src/test/ui/never_type/defaulted-never-note.rs index 70333c5f32..54f551759c 100644 --- a/src/test/ui/never_type/defaulted-never-note.rs +++ b/src/test/ui/never_type/defaulted-never-note.rs @@ -1,6 +1,10 @@ +// revisions: nofallback fallback +//[nofallback] run-pass +//[fallback] check-fail + // We need to opt into the `never_type_fallback` feature // to trigger the requirement that this is testing. -#![feature(never_type, never_type_fallback)] +#![cfg_attr(fallback, feature(never_type, never_type_fallback))] #![allow(unused)] @@ -19,16 +23,16 @@ trait ImplementedForUnitButNotNever {} impl ImplementedForUnitButNotNever for () {} fn foo(_t: T) {} -//~^ NOTE required by this bound in `foo` -//~| NOTE required by a bound in `foo` +//[fallback]~^ NOTE required by this bound in `foo` +//[fallback]~| NOTE required by a bound in `foo` fn smeg() { let _x = return; foo(_x); - //~^ ERROR the trait bound - //~| NOTE the trait `ImplementedForUnitButNotNever` is not implemented - //~| NOTE this trait is implemented for `()` - //~| NOTE this error might have been caused - //~| HELP did you intend + //[fallback]~^ ERROR the trait bound + //[fallback]~| NOTE the trait `ImplementedForUnitButNotNever` is not implemented + //[fallback]~| NOTE this trait is implemented for `()` + //[fallback]~| NOTE this error might have been caused + //[fallback]~| HELP did you intend } fn main() { diff --git a/src/test/ui/never_type/diverging-fallback-control-flow.rs b/src/test/ui/never_type/diverging-fallback-control-flow.rs index ea4881049d..45a3362fa6 100644 --- a/src/test/ui/never_type/diverging-fallback-control-flow.rs +++ b/src/test/ui/never_type/diverging-fallback-control-flow.rs @@ -1,30 +1,28 @@ +// revisions: nofallback fallback // run-pass #![allow(dead_code)] #![allow(unused_assignments)] #![allow(unused_variables)] #![allow(unreachable_code)] - // Test various cases where we permit an unconstrained variable -// to fallback based on control-flow. -// -// These represent current behavior, but are pretty dubious. I would -// like to revisit these and potentially change them. --nmatsakis +// to fallback based on control-flow. In all of these cases, +// the type variable winds up being the target of both a `!` coercion +// and a coercion from a non-`!` variable, and hence falls back to `()`. +#![cfg_attr(fallback, feature(never_type, never_type_fallback))] -#![feature(never_type, never_type_fallback)] - -trait BadDefault { +trait UnitDefault { fn default() -> Self; } -impl BadDefault for u32 { +impl UnitDefault for u32 { fn default() -> Self { 0 } } -impl BadDefault for ! { - fn default() -> ! { +impl UnitDefault for () { + fn default() -> () { panic!() } } @@ -33,7 +31,7 @@ fn assignment() { let x; if true { - x = BadDefault::default(); + x = UnitDefault::default(); } else { x = return; } @@ -45,13 +43,13 @@ fn assignment_rev() { if true { x = return; } else { - x = BadDefault::default(); + x = UnitDefault::default(); } } fn if_then_else() { let _x = if true { - BadDefault::default() + UnitDefault::default() } else { return; }; @@ -61,19 +59,19 @@ fn if_then_else_rev() { let _x = if true { return; } else { - BadDefault::default() + UnitDefault::default() }; } fn match_arm() { - let _x = match Ok(BadDefault::default()) { + let _x = match Ok(UnitDefault::default()) { Ok(v) => v, Err(()) => return, }; } fn match_arm_rev() { - let _x = match Ok(BadDefault::default()) { + let _x = match Ok(UnitDefault::default()) { Err(()) => return, Ok(v) => v, }; @@ -84,7 +82,7 @@ fn loop_break() { if false { break return; } else { - break BadDefault::default(); + break UnitDefault::default(); } }; } @@ -94,9 +92,9 @@ fn loop_break_rev() { if false { break return; } else { - break BadDefault::default(); + break UnitDefault::default(); } }; } -fn main() { } +fn main() {} diff --git a/src/test/ui/never_type/diverging-fallback-no-leak.fallback.stderr b/src/test/ui/never_type/diverging-fallback-no-leak.fallback.stderr new file mode 100644 index 0000000000..72cd693805 --- /dev/null +++ b/src/test/ui/never_type/diverging-fallback-no-leak.fallback.stderr @@ -0,0 +1,18 @@ +error[E0277]: the trait bound `!: Test` is not satisfied + --> $DIR/diverging-fallback-no-leak.rs:17:5 + | +LL | unconstrained_arg(return); + | ^^^^^^^^^^^^^^^^^ the trait `Test` is not implemented for `!` + | + = note: this trait is implemented for `()` + = note: this error might have been caused by changes to Rust's type-inference algorithm (see issue #48950 for more information) + = help: did you intend to use the type `()` here instead? +note: required by a bound in `unconstrained_arg` + --> $DIR/diverging-fallback-no-leak.rs:12:25 + | +LL | fn unconstrained_arg(_: T) {} + | ^^^^ required by this bound in `unconstrained_arg` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/never_type/diverging-fallback-no-leak.rs b/src/test/ui/never_type/diverging-fallback-no-leak.rs new file mode 100644 index 0000000000..03478e19dd --- /dev/null +++ b/src/test/ui/never_type/diverging-fallback-no-leak.rs @@ -0,0 +1,19 @@ +// revisions: nofallback fallback +//[nofallback] check-pass + +#![cfg_attr(fallback, feature(never_type, never_type_fallback))] + +fn make_unit() {} + +trait Test {} +impl Test for i32 {} +impl Test for () {} + +fn unconstrained_arg(_: T) {} + +fn main() { + // Here the type variable falls back to `!`, + // and hence we get a type error. + unconstrained_arg(return); + //[fallback]~^ ERROR trait bound `!: Test` is not satisfied +} diff --git a/src/test/ui/never_type/diverging-fallback-unconstrained-return.rs b/src/test/ui/never_type/diverging-fallback-unconstrained-return.rs new file mode 100644 index 0000000000..7ea97126f8 --- /dev/null +++ b/src/test/ui/never_type/diverging-fallback-unconstrained-return.rs @@ -0,0 +1,37 @@ +// Variant of diverging-falllback-control-flow that tests +// the specific case of a free function with an unconstrained +// return type. This captures the pattern we saw in the wild +// in the objc crate, where changing the fallback from `!` to `()` +// resulted in unsoundness. +// +// check-pass + +// revisions: nofallback fallback + +#![cfg_attr(fallback, feature(never_type, never_type_fallback))] + + +fn make_unit() {} + +trait UnitReturn {} +impl UnitReturn for i32 {} +impl UnitReturn for () {} + +fn unconstrained_return() -> T { + unsafe { + let make_unit_fn: fn() = make_unit; + let ffi: fn() -> T = std::mem::transmute(make_unit_fn); + ffi() + } +} + +fn main() { + // In Ye Olde Days, the `T` parameter of `unconstrained_return` + // winds up "entangled" with the `!` type that results from + // `panic!`, and hence falls back to `()`. This is kind of unfortunate + // and unexpected. When we introduced the `!` type, the original + // idea was to change that fallback to `!`, but that would have resulted + // in this code no longer compiling (or worse, in some cases it injected + // unsound results). + let _ = if true { unconstrained_return() } else { panic!() }; +} diff --git a/src/test/ui/expr-empty-ret.rs b/src/test/ui/never_type/expr-empty-ret.rs similarity index 100% rename from src/test/ui/expr-empty-ret.rs rename to src/test/ui/never_type/expr-empty-ret.rs diff --git a/src/test/ui/never_type/fallback-closure-ret.rs b/src/test/ui/never_type/fallback-closure-ret.rs new file mode 100644 index 0000000000..5c8ce48cbb --- /dev/null +++ b/src/test/ui/never_type/fallback-closure-ret.rs @@ -0,0 +1,23 @@ +// This test verifies that never type fallback preserves the following code in a +// compiling state. This pattern is fairly common in the wild, notably seen in +// wasmtime v0.16. Typically this is some closure wrapper that expects a +// collection of 'known' signatures, and -> ! is not included in that set. +// +// This test is specifically targeted by the unit type fallback when +// encountering a set of obligations like `?T: Foo` and `Trait::Projection = +// ?T`. In the code below, these are `R: Bar` and `Fn::Output = R`. +// +// revisions: nofallback fallback +// check-pass + +#![cfg_attr(fallback, feature(never_type_fallback))] + +trait Bar { } +impl Bar for () { } +impl Bar for u32 { } + +fn foo(_: impl Fn() -> R) {} + +fn main() { + foo(|| panic!()); +} diff --git a/src/test/ui/never_type/fallback-closure-wrap.fallback.stderr b/src/test/ui/never_type/fallback-closure-wrap.fallback.stderr new file mode 100644 index 0000000000..78d1a3caf4 --- /dev/null +++ b/src/test/ui/never_type/fallback-closure-wrap.fallback.stderr @@ -0,0 +1,17 @@ +error[E0271]: type mismatch resolving `<[closure@$DIR/fallback-closure-wrap.rs:18:40: 21:6] as FnOnce<()>>::Output == ()` + --> $DIR/fallback-closure-wrap.rs:18:31 + | +LL | let error = Closure::wrap(Box::new(move || { + | _______________________________^ +LL | | +LL | | panic!("Can't connect to server."); +LL | | }) as Box); + | |______^ expected `()`, found `!` + | + = note: expected unit type `()` + found type `!` + = note: required for the cast to the object type `dyn FnMut()` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0271`. diff --git a/src/test/ui/never_type/fallback-closure-wrap.rs b/src/test/ui/never_type/fallback-closure-wrap.rs new file mode 100644 index 0000000000..af0577ac06 --- /dev/null +++ b/src/test/ui/never_type/fallback-closure-wrap.rs @@ -0,0 +1,30 @@ +// This is a minified example from Crater breakage observed when attempting to +// stabilize never type, nstoddard/webgl-gui @ 22f0169f. +// +// This particular test case currently fails as the inference to `()` rather +// than `!` happens as a result of an `as` cast, which is not currently tracked. +// Crater did not find many cases of this occuring, but it is included for +// awareness. +// +// revisions: nofallback fallback +//[nofallback] check-pass +//[fallback] check-fail + +#![cfg_attr(fallback, feature(never_type_fallback))] + +use std::marker::PhantomData; + +fn main() { + let error = Closure::wrap(Box::new(move || { + //[fallback]~^ ERROR type mismatch resolving + panic!("Can't connect to server."); + }) as Box); +} + +struct Closure(PhantomData); + +impl Closure { + fn wrap(data: Box) -> Closure { + todo!() + } +} 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 new file mode 100644 index 0000000000..614cdff1f8 --- /dev/null +++ b/src/test/ui/never_type/never-value-fallback-issue-66757.nofallback.stderr @@ -0,0 +1,17 @@ +error[E0277]: the trait bound `E: From<()>` is not satisfied + --> $DIR/never-value-fallback-issue-66757.rs:28:5 + | +LL | >::from(never); + | ^^^^^^^^^^^^^^^^^^^^ the trait `From<()>` is not implemented for `E` + | + = help: the following implementations were found: + > +note: required by `from` + --> $SRC_DIR/core/src/convert/mod.rs:LL:COL + | +LL | fn from(_: T) -> Self; + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/never_type/never-value-fallback-issue-66757.rs b/src/test/ui/never_type/never-value-fallback-issue-66757.rs index f2e9e08730..fc6fe6eb5c 100644 --- a/src/test/ui/never_type/never-value-fallback-issue-66757.rs +++ b/src/test/ui/never_type/never-value-fallback-issue-66757.rs @@ -4,12 +4,13 @@ // never) and an uninferred variable (here the argument to `From`) it // doesn't fallback to `()` but rather `!`. // -// run-pass +// revisions: nofallback fallback +//[fallback] run-pass +//[nofallback] check-fail #![feature(never_type)] -// FIXME(#67225) -- this should be true even without the fallback gate. -#![feature(never_type_fallback)] +#![cfg_attr(fallback, feature(never_type_fallback))] struct E; @@ -21,9 +22,10 @@ impl From for E { #[allow(unreachable_code)] #[allow(dead_code)] +#[allow(unused_must_use)] fn foo(never: !) { >::from(never); // Ok - >::from(never); // Inference fails here + >::from(never); //[nofallback]~ ERROR trait bound `E: From<()>` is not satisfied } fn main() { } diff --git a/src/test/ui/new-box-syntax.rs b/src/test/ui/new-box-syntax.rs index 418cf554b4..c56e1dd462 100644 --- a/src/test/ui/new-box-syntax.rs +++ b/src/test/ui/new-box-syntax.rs @@ -5,7 +5,6 @@ * http://creativecommons.org/publicdomain/zero/1.0/ */ #![allow(dead_code, unused_variables)] -#![feature(box_syntax)] // Tests that the new `box` syntax works with unique pointers. @@ -17,12 +16,12 @@ struct Structure { } pub fn main() { - let y: Box = box 2; - let b: Box = box (1 + 2); - let c = box (3 + 4); + let y: Box = Box::new(2); + let b: Box = Box::new(1 + 2); + let c = Box::new(3 + 4); - let s: Box = box Structure { + let s: Box = Box::new(Structure { x: 3, y: 4, - }; + }); } diff --git a/src/test/ui/new-box.rs b/src/test/ui/new-box.rs index d11f0d045a..96a3b197f4 100644 --- a/src/test/ui/new-box.rs +++ b/src/test/ui/new-box.rs @@ -1,7 +1,5 @@ // run-pass -#![feature(box_syntax)] - fn f(x: Box) { let y: &isize = &*x; println!("{}", *x); @@ -27,6 +25,6 @@ fn g(x: Box) { } fn main() { - f(box 1234); - g(box Struct as Box); + f(Box::new(1234)); + g(Box::new(Struct) as Box); } diff --git a/src/test/ui/nll/closure-access-spans.stderr b/src/test/ui/nll/closure-access-spans.stderr index 8eded8f285..e9d7ca953d 100644 --- a/src/test/ui/nll/closure-access-spans.stderr +++ b/src/test/ui/nll/closure-access-spans.stderr @@ -8,7 +8,7 @@ LL | || x; | | | immutable borrow occurs here LL | r.use_mut(); - | - mutable borrow later used here + | ----------- mutable borrow later used here error[E0499]: cannot borrow `x` as mutable more than once at a time --> $DIR/closure-access-spans.rs:11:5 @@ -20,7 +20,7 @@ LL | || x = 2; | | | second mutable borrow occurs here LL | r.use_mut(); - | - first borrow later used here + | ----------- first borrow later used here error[E0500]: closure requires unique access to `x` but it is already borrowed --> $DIR/closure-access-spans.rs:17:5 @@ -32,7 +32,7 @@ LL | || *x = 2; | | | closure construction occurs here LL | r.use_mut(); - | - first borrow later used here + | ----------- first borrow later used here error[E0503]: cannot use `x` because it was mutably borrowed --> $DIR/closure-access-spans.rs:23:13 @@ -42,7 +42,7 @@ LL | let r = &mut x; LL | move || x; | ^ use of borrowed `x` LL | r.use_ref(); - | - borrow later used here + | ----------- borrow later used here error[E0505]: cannot move out of `x` because it is borrowed --> $DIR/closure-access-spans.rs:29:5 @@ -54,7 +54,7 @@ LL | || x; | | | move out of `x` occurs here LL | r.use_ref(); - | - borrow later used here + | ----------- borrow later used here error[E0382]: borrow of moved value: `x` --> $DIR/closure-access-spans.rs:35:5 diff --git a/src/test/ui/nll/closure-borrow-spans.stderr b/src/test/ui/nll/closure-borrow-spans.stderr index fffbee4d4a..bada4e1b84 100644 --- a/src/test/ui/nll/closure-borrow-spans.stderr +++ b/src/test/ui/nll/closure-borrow-spans.stderr @@ -8,7 +8,7 @@ LL | let f = || x.len(); LL | let y = x; | ^ move out of `x` occurs here LL | f.use_ref(); - | - borrow later used here + | ----------- borrow later used here error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable --> $DIR/closure-borrow-spans.rs:11:13 @@ -20,7 +20,7 @@ LL | let f = || x; LL | let y = &mut x; | ^^^^^^ mutable borrow occurs here LL | f.use_ref(); - | - immutable borrow later used here + | ----------- immutable borrow later used here error[E0597]: `x` does not live long enough --> $DIR/closure-borrow-spans.rs:19:16 @@ -32,7 +32,7 @@ LL | f = || x; LL | } | - `x` dropped here while still borrowed LL | f.use_ref(); - | - borrow later used here + | ----------- borrow later used here error[E0506]: cannot assign to `x` because it is borrowed --> $DIR/closure-borrow-spans.rs:26:5 @@ -44,7 +44,7 @@ LL | let f = || x; LL | x = 1; | ^^^^^ assignment to borrowed `x` occurs here LL | f.use_ref(); - | - borrow later used here + | ----------- borrow later used here error[E0503]: cannot use `x` because it was mutably borrowed --> $DIR/closure-borrow-spans.rs:32:13 @@ -56,7 +56,7 @@ LL | let f = || x = 0; LL | let y = x; | ^ use of borrowed `x` LL | f.use_ref(); - | - borrow later used here + | ----------- borrow later used here error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable --> $DIR/closure-borrow-spans.rs:38:13 @@ -68,7 +68,7 @@ LL | let f = || x = 0; LL | let y = &x; | ^^ immutable borrow occurs here LL | f.use_ref(); - | - mutable borrow later used here + | ----------- mutable borrow later used here error[E0499]: cannot borrow `x` as mutable more than once at a time --> $DIR/closure-borrow-spans.rs:44:13 @@ -80,7 +80,7 @@ LL | let f = || x = 0; LL | let y = &mut x; | ^^^^^^ second mutable borrow occurs here LL | f.use_ref(); - | - first borrow later used here + | ----------- first borrow later used here error[E0597]: `x` does not live long enough --> $DIR/closure-borrow-spans.rs:52:16 @@ -92,7 +92,7 @@ LL | f = || x = 0; LL | } | - `x` dropped here while still borrowed LL | f.use_ref(); - | - borrow later used here + | ----------- borrow later used here error[E0506]: cannot assign to `x` because it is borrowed --> $DIR/closure-borrow-spans.rs:59:5 @@ -104,7 +104,7 @@ LL | let f = || x = 0; LL | x = 1; | ^^^^^ assignment to borrowed `x` occurs here LL | f.use_ref(); - | - borrow later used here + | ----------- borrow later used here error[E0505]: cannot move out of `x` because it is borrowed --> $DIR/closure-borrow-spans.rs:65:13 @@ -116,7 +116,7 @@ LL | let f = || *x = 0; LL | let y = x; | ^ move out of `x` occurs here LL | f.use_ref(); - | - borrow later used here + | ----------- borrow later used here error[E0501]: cannot borrow `x` as immutable because previous closure requires unique access --> $DIR/closure-borrow-spans.rs:71:13 @@ -128,7 +128,7 @@ LL | let f = || *x = 0; LL | let y = &x; | ^^ second borrow occurs here LL | f.use_ref(); - | - first borrow later used here + | ----------- first borrow later used here error[E0501]: cannot borrow `x` as mutable because previous closure requires unique access --> $DIR/closure-borrow-spans.rs:77:13 @@ -140,7 +140,7 @@ LL | let f = || *x = 0; LL | let y = &mut x; | ^^^^^^ second borrow occurs here LL | f.use_ref(); - | - first borrow later used here + | ----------- first borrow later used here error[E0597]: `x` does not live long enough --> $DIR/closure-borrow-spans.rs:86:16 @@ -152,7 +152,7 @@ LL | f = || *x = 0; LL | } | - `x` dropped here while still borrowed LL | f.use_ref(); - | - borrow later used here + | ----------- borrow later used here error[E0506]: cannot assign to `*x` because it is borrowed --> $DIR/closure-borrow-spans.rs:93:5 @@ -164,7 +164,7 @@ LL | let f = || *x = 0; LL | *x = 1; | ^^^^^^ assignment to borrowed `*x` occurs here LL | f.use_ref(); - | - borrow later used here + | ----------- borrow later used here error: aborting due to 14 previous errors diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr index 29993b129c..d77793291c 100644 --- a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr @@ -38,16 +38,19 @@ error[E0521]: borrowed data escapes outside of function --> $DIR/propagate-approximated-shorter-to-static-no-bound.rs:32:5 | LL | fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) { - | ------ `cell_a` is a reference that is only valid in the function body + | -- ------ `cell_a` is a reference that is only valid in the function body + | | + | lifetime `'a` defined here LL | / establish_relationships(&cell_a, &cell_b, |_outlives, x, y| { LL | | LL | | LL | | // Only works if 'x: 'y: LL | | demand_y(x, y, x.get()) LL | | }); - | |______^ `cell_a` escapes the function body here - | - = help: consider replacing `'a` with `'static` + | | ^ + | | | + | |______`cell_a` escapes the function body here + | argument requires that `'a` must outlive `'static` error: aborting due to previous error diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr index cb505d8b1e..cc67270ad2 100644 --- a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr @@ -38,16 +38,19 @@ error[E0521]: borrowed data escapes outside of function --> $DIR/propagate-approximated-shorter-to-static-wrong-bound.rs:35:5 | LL | fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) { - | ------ `cell_a` is a reference that is only valid in the function body + | -- ------ `cell_a` is a reference that is only valid in the function body + | | + | lifetime `'a` defined here LL | / establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| { LL | | LL | | LL | | // Only works if 'x: 'y: LL | | demand_y(x, y, x.get()) LL | | }); - | |______^ `cell_a` escapes the function body here - | - = help: consider replacing `'a` with `'static` + | | ^ + | | | + | |______`cell_a` escapes the function body here + | argument requires that `'a` must outlive `'static` error: aborting due to previous error diff --git a/src/test/ui/nll/closure-requirements/region-lbr-named-does-not-outlive-static.stderr b/src/test/ui/nll/closure-requirements/region-lbr-named-does-not-outlive-static.stderr index 1fa3d01017..d0a24a267f 100644 --- a/src/test/ui/nll/closure-requirements/region-lbr-named-does-not-outlive-static.stderr +++ b/src/test/ui/nll/closure-requirements/region-lbr-named-does-not-outlive-static.stderr @@ -5,8 +5,6 @@ LL | fn foo<'a>(x: &'a u32) -> &'static u32 { | -- lifetime `'a` defined here LL | &*x | ^^^ returning this value requires that `'a` must outlive `'static` - | - = help: consider replacing `'a` with `'static` error: aborting due to previous error diff --git a/src/test/ui/nll/get_default.nll.stderr b/src/test/ui/nll/get_default.nll.stderr deleted file mode 100644 index 2791230698..0000000000 --- a/src/test/ui/nll/get_default.nll.stderr +++ /dev/null @@ -1,48 +0,0 @@ -error[E0502]: cannot borrow `*map` as mutable because it is also borrowed as immutable - --> $DIR/get_default.rs:21:17 - | -LL | fn ok(map: &mut Map) -> &String { - | - let's call the lifetime of this reference `'1` -LL | loop { -LL | match map.get() { - | --- immutable borrow occurs here -LL | Some(v) => { -LL | return v; - | - returning this value requires that `*map` is borrowed for `'1` -... -LL | map.set(String::new()); // Ideally, this would not error. - | ^^^ mutable borrow occurs here - -error[E0502]: cannot borrow `*map` as mutable because it is also borrowed as immutable - --> $DIR/get_default.rs:32:17 - | -LL | fn err(map: &mut Map) -> &String { - | - let's call the lifetime of this reference `'1` -LL | loop { -LL | match map.get() { - | --- immutable borrow occurs here -LL | Some(v) => { -LL | map.set(String::new()); // Both AST and MIR error here - | ^^^ mutable borrow occurs here -LL | -LL | return v; - | - returning this value requires that `*map` is borrowed for `'1` - -error[E0502]: cannot borrow `*map` as mutable because it is also borrowed as immutable - --> $DIR/get_default.rs:37:17 - | -LL | fn err(map: &mut Map) -> &String { - | - let's call the lifetime of this reference `'1` -LL | loop { -LL | match map.get() { - | --- immutable borrow occurs here -... -LL | return v; - | - returning this value requires that `*map` is borrowed for `'1` -... -LL | map.set(String::new()); // Ideally, just AST would error here - | ^^^ mutable borrow occurs here - -error: aborting due to 3 previous errors - -For more information about this error, try `rustc --explain E0502`. diff --git a/src/test/ui/nll/get_default.stderr b/src/test/ui/nll/get_default.stderr index af79771e7e..6998c04336 100644 --- a/src/test/ui/nll/get_default.stderr +++ b/src/test/ui/nll/get_default.stderr @@ -5,7 +5,7 @@ LL | fn ok(map: &mut Map) -> &String { | - let's call the lifetime of this reference `'1` LL | loop { LL | match map.get() { - | --- immutable borrow occurs here + | --------- immutable borrow occurs here LL | Some(v) => { LL | return v; | - returning this value requires that `*map` is borrowed for `'1` @@ -20,7 +20,7 @@ LL | fn err(map: &mut Map) -> &String { | - let's call the lifetime of this reference `'1` LL | loop { LL | match map.get() { - | --- immutable borrow occurs here + | --------- immutable borrow occurs here LL | Some(v) => { LL | map.set(String::new()); // Both AST and MIR error here | ^^^^^^^^^^^^^^^^^^^^^^ mutable borrow occurs here @@ -35,7 +35,7 @@ LL | fn err(map: &mut Map) -> &String { | - let's call the lifetime of this reference `'1` LL | loop { LL | match map.get() { - | --- immutable borrow occurs here + | --------- immutable borrow occurs here ... LL | return v; | - returning this value requires that `*map` is borrowed for `'1` diff --git a/src/test/ui/nll/issue-46036.stderr b/src/test/ui/nll/issue-46036.stderr index 49dd0e267b..e6e95ee613 100644 --- a/src/test/ui/nll/issue-46036.stderr +++ b/src/test/ui/nll/issue-46036.stderr @@ -5,7 +5,7 @@ LL | let foo = Foo { x: &a }; | ^^ | | | borrowed value does not live long enough - | requires that `a` is borrowed for `'static` + | this usage requires that `a` is borrowed for `'static` LL | loop { } LL | } | - `a` dropped here while still borrowed diff --git a/src/test/ui/nll/issue-46589.stderr b/src/test/ui/nll/issue-46589.stderr index 82cd364eef..60ef3f7b85 100644 --- a/src/test/ui/nll/issue-46589.stderr +++ b/src/test/ui/nll/issue-46589.stderr @@ -2,10 +2,10 @@ error[E0499]: cannot borrow `**other` as mutable more than once at a time --> $DIR/issue-46589.rs:23:21 | LL | *other = match (*other).get_self() { - | -------- first mutable borrow occurs here + | ------------------- first mutable borrow occurs here LL | Some(s) => s, LL | None => (*other).new_self() - | ^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^ | | | second mutable borrow occurs here | first borrow later used here diff --git a/src/test/ui/nll/issue-50716.nll.stderr b/src/test/ui/nll/issue-50716.nll.stderr index 7b83e4beaf..38dd1b5f6f 100644 --- a/src/test/ui/nll/issue-50716.nll.stderr +++ b/src/test/ui/nll/issue-50716.nll.stderr @@ -6,8 +6,6 @@ LL | fn foo<'a, T: 'static>(s: Box<<&'a T as A>::X>) ... LL | let _x = *s; | ^^ proving this value is `Sized` requires that `'a` must outlive `'static` - | - = help: consider replacing `'a` with `'static` error: aborting due to previous error diff --git a/src/test/ui/nll/issue-50716.stderr b/src/test/ui/nll/issue-50716.stderr index 3dee3345db..be68d252f3 100644 --- a/src/test/ui/nll/issue-50716.stderr +++ b/src/test/ui/nll/issue-50716.stderr @@ -4,9 +4,9 @@ error[E0308]: mismatched types LL | let _x = *s; | ^^ lifetime mismatch | - = note: expected type `Sized` - found type `Sized` -note: the lifetime `'a` as defined on the function body at 9:8... + = note: expected type `<<&'a T as A>::X as Sized>` + found type `<<&'static T as A>::X as Sized>` +note: the lifetime `'a` as defined here... --> $DIR/issue-50716.rs:9:8 | LL | fn foo<'a, T: 'static>(s: Box<<&'a T as A>::X>) diff --git a/src/test/ui/nll/issue-51191.stderr b/src/test/ui/nll/issue-51191.stderr index 18696f57c4..9f4e971f90 100644 --- a/src/test/ui/nll/issue-51191.stderr +++ b/src/test/ui/nll/issue-51191.stderr @@ -45,7 +45,7 @@ error[E0596]: cannot borrow data in a `&` reference as mutable --> $DIR/issue-51191.rs:22:9 | LL | (&mut self).bar(); - | ^^^^^^^^^^^ cannot borrow as mutable + | ^^^^^^^^^^^^^^^^^ cannot borrow as mutable error[E0596]: cannot borrow `self` as mutable, as it is not declared as mutable --> $DIR/issue-51191.rs:28:9 diff --git a/src/test/ui/nll/issue-52663-span-decl-captured-variable.stderr b/src/test/ui/nll/issue-52663-span-decl-captured-variable.stderr index 67115a5ccd..c9324f0422 100644 --- a/src/test/ui/nll/issue-52663-span-decl-captured-variable.stderr +++ b/src/test/ui/nll/issue-52663-span-decl-captured-variable.stderr @@ -4,7 +4,10 @@ error[E0507]: cannot move out of `x.0`, as `x` is a captured variable in an `Fn` LL | let x = (vec![22], vec![44]); | - captured outer variable LL | expect_fn(|| drop(x.0)); - | ^^^ move occurs because `x.0` has type `Vec`, which does not implement the `Copy` trait + | --------^^^- + | | | + | | move occurs because `x.0` has type `Vec`, which does not implement the `Copy` trait + | captured by this `Fn` closure error: aborting due to previous error diff --git a/src/test/ui/nll/issue-52663-trait-object.rs b/src/test/ui/nll/issue-52663-trait-object.rs index a7be365bde..f6bbb2d14b 100644 --- a/src/test/ui/nll/issue-52663-trait-object.rs +++ b/src/test/ui/nll/issue-52663-trait-object.rs @@ -1,16 +1,16 @@ -#![feature(box_syntax)] - trait Foo { fn get(&self); } impl Foo for A { fn get(&self) { } } + + fn main() { let _ = { let tmp0 = 3; let tmp1 = &tmp0; - box tmp1 as Box + Box::new(tmp1) as Box }; //~^^^ ERROR `tmp0` does not live long enough } diff --git a/src/test/ui/nll/issue-52663-trait-object.stderr b/src/test/ui/nll/issue-52663-trait-object.stderr index b71893de7f..5cedea6e66 100644 --- a/src/test/ui/nll/issue-52663-trait-object.stderr +++ b/src/test/ui/nll/issue-52663-trait-object.stderr @@ -3,8 +3,8 @@ error[E0597]: `tmp0` does not live long enough | LL | let tmp1 = &tmp0; | ^^^^^ borrowed value does not live long enough -LL | box tmp1 as Box - | ----------------------------- borrow later captured here by trait object +LL | Box::new(tmp1) as Box + | ----------------------------------- borrow later captured here by trait object LL | }; | - `tmp0` dropped here while still borrowed diff --git a/src/test/ui/nll/issue-52669.stderr b/src/test/ui/nll/issue-52669.stderr index db53e444b9..807b95f7e1 100644 --- a/src/test/ui/nll/issue-52669.stderr +++ b/src/test/ui/nll/issue-52669.stderr @@ -7,7 +7,7 @@ LL | a.b = B; LL | foo(a); | - value moved here LL | a.b.clone() - | ^^^ value borrowed here after move + | ^^^^^^^^^^^ value borrowed here after move error: aborting due to previous error diff --git a/src/test/ui/nll/issue-52742.stderr b/src/test/ui/nll/issue-52742.stderr index 23bb12f942..3f8481219a 100644 --- a/src/test/ui/nll/issue-52742.stderr +++ b/src/test/ui/nll/issue-52742.stderr @@ -4,12 +4,12 @@ error[E0312]: lifetime of reference outlives lifetime of borrowed content... LL | self.y = b.z | ^^^ | -note: ...the reference is valid for the lifetime `'_` as defined on the impl at 12:10... +note: ...the reference is valid for the lifetime `'_` as defined here... --> $DIR/issue-52742.rs:12:10 | LL | impl Foo<'_, '_> { | ^^ -note: ...but the borrowed content is only valid for the anonymous lifetime defined on the method body at 13:31 +note: ...but the borrowed content is only valid for the anonymous lifetime defined here --> $DIR/issue-52742.rs:13:31 | LL | fn take_bar(&mut self, b: Bar<'_>) { diff --git a/src/test/ui/nll/issue-53773.stderr b/src/test/ui/nll/issue-53773.stderr index 45831460e5..11cd423295 100644 --- a/src/test/ui/nll/issue-53773.stderr +++ b/src/test/ui/nll/issue-53773.stderr @@ -7,7 +7,7 @@ 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 + | ------------- borrow later used here | = note: consider using a `let` binding to create a longer lived value diff --git a/src/test/ui/nll/issue-54556-niconii.stderr b/src/test/ui/nll/issue-54556-niconii.stderr index 70f063ca0e..a8e1edc549 100644 --- a/src/test/ui/nll/issue-54556-niconii.stderr +++ b/src/test/ui/nll/issue-54556-niconii.stderr @@ -2,7 +2,7 @@ error[E0597]: `counter` does not live long enough --> $DIR/issue-54556-niconii.rs:22:20 | LL | if let Ok(_) = counter.lock() { } - | ^^^^^^^------- + | ^^^^^^^^^^^^^^ | | | borrowed value does not live long enough | a temporary with access to the borrow is created here ... diff --git a/src/test/ui/nll/issue-55394.stderr b/src/test/ui/nll/issue-55394.stderr index 36721f923f..197f8dfa2a 100644 --- a/src/test/ui/nll/issue-55394.stderr +++ b/src/test/ui/nll/issue-55394.stderr @@ -4,7 +4,7 @@ error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'s` d LL | Foo { bar } | ^^^ | -note: first, the lifetime cannot outlive the anonymous lifetime defined on the method body at 8:17... +note: first, the lifetime cannot outlive the anonymous lifetime defined here... --> $DIR/issue-55394.rs:8:17 | LL | fn new(bar: &mut Bar) -> Self { @@ -14,12 +14,12 @@ note: ...so that reference does not outlive borrowed content | LL | Foo { bar } | ^^^ -note: but, the lifetime must be valid for the lifetime `'_` as defined on the impl at 7:10... +note: but, the lifetime must be valid for the lifetime `'_` as defined here... --> $DIR/issue-55394.rs:7:10 | LL | impl Foo<'_> { | ^^ -note: ...so that the expression is assignable +note: ...so that the types are compatible --> $DIR/issue-55394.rs:9:9 | LL | Foo { bar } diff --git a/src/test/ui/nll/issue-55401.nll.stderr b/src/test/ui/nll/issue-55401.nll.stderr index df320aa084..4f797f26a1 100644 --- a/src/test/ui/nll/issue-55401.nll.stderr +++ b/src/test/ui/nll/issue-55401.nll.stderr @@ -6,8 +6,6 @@ LL | fn static_to_a_to_static_through_ref_in_tuple<'a>(x: &'a u32) -> &'static u LL | let (ref y, _z): (&'a u32, u32) = (&22, 44); LL | *y | ^^ returning this value requires that `'a` must outlive `'static` - | - = help: consider replacing `'a` with `'static` error: aborting due to previous error diff --git a/src/test/ui/nll/issue-55401.stderr b/src/test/ui/nll/issue-55401.stderr index 2dc7236cbc..55c51d532e 100644 --- a/src/test/ui/nll/issue-55401.stderr +++ b/src/test/ui/nll/issue-55401.stderr @@ -5,7 +5,7 @@ LL | *y | ^^ | = note: ...the reference is valid for the static lifetime... -note: ...but the borrowed content is only valid for the lifetime `'a` as defined on the function body at 1:47 +note: ...but the borrowed content is only valid for the lifetime `'a` as defined here --> $DIR/issue-55401.rs:1:47 | LL | fn static_to_a_to_static_through_ref_in_tuple<'a>(x: &'a u32) -> &'static u32 { diff --git a/src/test/ui/nll/issue-55825-const-fn.rs b/src/test/ui/nll/issue-55825-const-fn.rs new file mode 100644 index 0000000000..c9efccd15b --- /dev/null +++ b/src/test/ui/nll/issue-55825-const-fn.rs @@ -0,0 +1,8 @@ +// Regression test for issue #55825 +// Tests that we don't emit a spurious warning in NLL mode + +#![feature(nll)] + +const fn no_dyn_trait_ret() -> &'static dyn std::fmt::Debug { &() } //~ ERROR const + +fn main() { } diff --git a/src/test/ui/nll/issue-55825-const-fn.stderr b/src/test/ui/nll/issue-55825-const-fn.stderr new file mode 100644 index 0000000000..9af5180343 --- /dev/null +++ b/src/test/ui/nll/issue-55825-const-fn.stderr @@ -0,0 +1,12 @@ +error[E0658]: trait objects in const fn are unstable + --> $DIR/issue-55825-const-fn.rs:6:32 + | +LL | const fn no_dyn_trait_ret() -> &'static dyn std::fmt::Debug { &() } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #57563 for more information + = help: add `#![feature(const_fn_trait_bound)]` 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/nll/issue-58299.stderr b/src/test/ui/nll/issue-58299.stderr index 5be4e56171..aba07542d0 100644 --- a/src/test/ui/nll/issue-58299.stderr +++ b/src/test/ui/nll/issue-58299.stderr @@ -6,8 +6,6 @@ LL | fn foo<'a>(x: i32) { ... LL | A::<'a>::X..=A::<'static>::X => (), | ^^^^^^^^^^ requires that `'a` must outlive `'static` - | - = help: consider replacing `'a` with `'static` error: lifetime may not live long enough --> $DIR/issue-58299.rs:24:27 @@ -17,8 +15,6 @@ LL | fn bar<'a>(x: i32) { ... LL | A::<'static>::X..=A::<'a>::X => (), | ^^^^^^^^^^ requires that `'a` must outlive `'static` - | - = help: consider replacing `'a` with `'static` error: aborting due to 2 previous errors diff --git a/src/test/ui/nll/issue-62007-assign-const-index.stderr b/src/test/ui/nll/issue-62007-assign-const-index.stderr index 0db9fe62c3..12e28aa3fb 100644 --- a/src/test/ui/nll/issue-62007-assign-const-index.stderr +++ b/src/test/ui/nll/issue-62007-assign-const-index.stderr @@ -17,7 +17,7 @@ LL | fn to_refs(mut list: [&mut List; 2]) -> Vec<&mut T> { | - let's call the lifetime of this reference `'1` ... LL | if let Some(n) = list[0].next.as_mut() { - | ^^^^^^^^^^^^--------- + | ^^^^^^^^^^^^^^^^^^^^^ | | | `list[_].next` was mutably borrowed here in the previous iteration of the loop | argument requires that `list[_].next` is borrowed for `'1` diff --git a/src/test/ui/nll/issue-62007-assign-differing-fields.stderr b/src/test/ui/nll/issue-62007-assign-differing-fields.stderr index f1af2e855a..4488431fc5 100644 --- a/src/test/ui/nll/issue-62007-assign-differing-fields.stderr +++ b/src/test/ui/nll/issue-62007-assign-differing-fields.stderr @@ -17,7 +17,7 @@ LL | fn to_refs<'a, T>(mut list: (&'a mut List, &'a mut List)) -> Vec<&'a | -- lifetime `'a` defined here ... LL | if let Some(n) = (list.0).next.as_mut() { - | ^^^^^^^^^^^^^--------- + | ^^^^^^^^^^^^^^^^^^^^^^ | | | `list.0.next` was mutably borrowed here in the previous iteration of the loop | argument requires that `list.0.next` is borrowed for `'a` diff --git a/src/test/ui/nll/issue-67007-escaping-data.rs b/src/test/ui/nll/issue-67007-escaping-data.rs new file mode 100644 index 0000000000..8c21737e05 --- /dev/null +++ b/src/test/ui/nll/issue-67007-escaping-data.rs @@ -0,0 +1,26 @@ +// Regression test for issue #67007 +// Ensures that we show information about the specific regions involved + +#![feature(nll)] + +// Covariant over 'a, invariant over 'tcx +struct FnCtxt<'a, 'tcx: 'a>(&'a (), *mut &'tcx ()); + +impl<'a, 'tcx> FnCtxt<'a, 'tcx> { + fn use_it(&self, _: &'tcx ()) {} +} + +struct Consumer<'tcx>(&'tcx ()); + +impl<'tcx> Consumer<'tcx> { + fn bad_method<'a>(&self, fcx: &FnCtxt<'a, 'tcx>) { + let other = self.use_fcx(fcx); //~ ERROR borrowed data + fcx.use_it(other); + } + + fn use_fcx<'a>(&self, _: &FnCtxt<'a, 'tcx>) -> &'a () { + &() + } +} + +fn main() {} diff --git a/src/test/ui/nll/issue-67007-escaping-data.stderr b/src/test/ui/nll/issue-67007-escaping-data.stderr new file mode 100644 index 0000000000..2834d6fb0d --- /dev/null +++ b/src/test/ui/nll/issue-67007-escaping-data.stderr @@ -0,0 +1,21 @@ +error[E0521]: borrowed data escapes outside of associated function + --> $DIR/issue-67007-escaping-data.rs:17:21 + | +LL | impl<'tcx> Consumer<'tcx> { + | ---- lifetime `'tcx` defined here +LL | fn bad_method<'a>(&self, fcx: &FnCtxt<'a, 'tcx>) { + | -- ----- --- `fcx` is a reference that is only valid in the associated function body + | | | + | | `self` declared here, outside of the associated function body + | lifetime `'a` defined here +LL | let other = self.use_fcx(fcx); + | ^^^^^^^^^^^^^^^^^ + | | + | `fcx` escapes the associated function body here + | argument requires that `'a` must outlive `'tcx` + | + = help: consider adding the following bound: `'a: 'tcx` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0521`. diff --git a/src/test/ui/nll/issue-73159-rpit-static.rs b/src/test/ui/nll/issue-73159-rpit-static.rs new file mode 100644 index 0000000000..a5455a3f9e --- /dev/null +++ b/src/test/ui/nll/issue-73159-rpit-static.rs @@ -0,0 +1,14 @@ +// Regression test for issue #73159 +// Tests thar we don't suggest replacing 'a with 'static' + +#![feature(nll)] + +struct Foo<'a>(&'a [u8]); + +impl<'a> Foo<'a> { + fn make_it(&self) -> impl Iterator { //~ ERROR lifetime may not live + self.0.iter().copied() + } +} + +fn main() {} diff --git a/src/test/ui/nll/issue-73159-rpit-static.stderr b/src/test/ui/nll/issue-73159-rpit-static.stderr new file mode 100644 index 0000000000..60b1552701 --- /dev/null +++ b/src/test/ui/nll/issue-73159-rpit-static.stderr @@ -0,0 +1,10 @@ +error: lifetime may not live long enough + --> $DIR/issue-73159-rpit-static.rs:9:26 + | +LL | impl<'a> Foo<'a> { + | -- lifetime `'a` defined here +LL | fn make_it(&self) -> impl Iterator { + | ^^^^^^^^^^^^^^^^^^^^^^^^ opaque type requires that `'a` must outlive `'static` + +error: aborting due to previous error + diff --git a/src/test/ui/nll/loan_ends_mid_block_vec.stderr b/src/test/ui/nll/loan_ends_mid_block_vec.stderr index c0b97bea34..22c72af61d 100644 --- a/src/test/ui/nll/loan_ends_mid_block_vec.stderr +++ b/src/test/ui/nll/loan_ends_mid_block_vec.stderr @@ -5,7 +5,7 @@ LL | let slice = &mut data; | --------- first mutable borrow occurs here LL | capitalize(slice); LL | data.push('d'); - | ^^^^ second mutable borrow occurs here + | ^^^^^^^^^^^^^^ second mutable borrow occurs here ... LL | capitalize(slice); | ----- first borrow later used here @@ -17,7 +17,7 @@ LL | let slice = &mut data; | --------- first mutable borrow occurs here ... LL | data.push('e'); - | ^^^^ second mutable borrow occurs here + | ^^^^^^^^^^^^^^ second mutable borrow occurs here ... LL | capitalize(slice); | ----- first borrow later used here @@ -29,7 +29,7 @@ LL | let slice = &mut data; | --------- first mutable borrow occurs here ... LL | data.push('f'); - | ^^^^ second mutable borrow occurs here + | ^^^^^^^^^^^^^^ second mutable borrow occurs here LL | LL | capitalize(slice); | ----- first borrow later used here diff --git a/src/test/ui/nll/mir_check_cast_reify.stderr b/src/test/ui/nll/mir_check_cast_reify.stderr index 1722da8f34..4e8eec330a 100644 --- a/src/test/ui/nll/mir_check_cast_reify.stderr +++ b/src/test/ui/nll/mir_check_cast_reify.stderr @@ -6,8 +6,6 @@ LL | fn bar<'a>(x: &'a u32) -> &'static u32 { ... LL | f(x) | ^^^^ returning this value requires that `'a` must outlive `'static` - | - = help: consider replacing `'a` with `'static` error: aborting due to previous error diff --git a/src/test/ui/nll/mir_check_cast_unsafe_fn.stderr b/src/test/ui/nll/mir_check_cast_unsafe_fn.stderr index c87425ecfc..52959850a3 100644 --- a/src/test/ui/nll/mir_check_cast_unsafe_fn.stderr +++ b/src/test/ui/nll/mir_check_cast_unsafe_fn.stderr @@ -6,8 +6,6 @@ LL | fn bar<'a>(input: &'a u32, f: fn(&'a u32) -> &'a u32) -> &'static u32 { ... LL | unsafe { g(input) } | ^^^^^^^^ returning this value requires that `'a` must outlive `'static` - | - = help: consider replacing `'a` with `'static` error: aborting due to previous error diff --git a/src/test/ui/nll/mir_check_cast_unsize.stderr b/src/test/ui/nll/mir_check_cast_unsize.stderr index cb7328d117..364d6c17ea 100644 --- a/src/test/ui/nll/mir_check_cast_unsize.stderr +++ b/src/test/ui/nll/mir_check_cast_unsize.stderr @@ -5,8 +5,6 @@ LL | fn bar<'a>(x: &'a u32) -> &'static dyn Debug { | -- lifetime `'a` defined here LL | x | ^ returning this value requires that `'a` must outlive `'static` - | - = help: consider replacing `'a` with `'static` error: aborting due to previous error diff --git a/src/test/ui/nll/normalization-bounds-error.stderr b/src/test/ui/nll/normalization-bounds-error.stderr index 8c7c8918f3..6da3d5d969 100644 --- a/src/test/ui/nll/normalization-bounds-error.stderr +++ b/src/test/ui/nll/normalization-bounds-error.stderr @@ -4,12 +4,12 @@ error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'d` d LL | fn visit_seq<'d, 'a: 'd>() -> <&'a () as Visitor<'d>>::Value {} | ^^^^^^^^^ | -note: first, the lifetime cannot outlive the lifetime `'d` as defined on the function body at 12:14... +note: first, the lifetime cannot outlive the lifetime `'d` as defined here... --> $DIR/normalization-bounds-error.rs:12:14 | LL | fn visit_seq<'d, 'a: 'd>() -> <&'a () as Visitor<'d>>::Value {} | ^^ -note: ...but the lifetime must also be valid for the lifetime `'a` as defined on the function body at 12:18... +note: ...but the lifetime must also be valid for the lifetime `'a` as defined here... --> $DIR/normalization-bounds-error.rs:12:18 | LL | fn visit_seq<'d, 'a: 'd>() -> <&'a () as Visitor<'d>>::Value {} diff --git a/src/test/ui/nll/outlives-suggestion-more.stderr b/src/test/ui/nll/outlives-suggestion-more.stderr index 2ebcbf5cba..a80e59d482 100644 --- a/src/test/ui/nll/outlives-suggestion-more.stderr +++ b/src/test/ui/nll/outlives-suggestion-more.stderr @@ -46,8 +46,6 @@ LL | fn foo2<'a, 'b, 'c>(x: &'a usize, y: &'b usize) -> (&'c usize, &'static usi | -- lifetime `'b` defined here LL | (x, y) | ^^^^^^ returning this value requires that `'b` must outlive `'static` - | - = help: consider replacing `'b` with `'static` help: the following changes may resolve your lifetime errors | @@ -88,8 +86,6 @@ LL | fn foo3<'a, 'b, 'c, 'd, 'e>( ... LL | (x, y, z) | ^^^^^^^^^ returning this value requires that `'c` must outlive `'static` - | - = help: consider replacing `'c` with `'static` help: the following changes may resolve your lifetime errors | diff --git a/src/test/ui/nll/outlives-suggestion-simple.stderr b/src/test/ui/nll/outlives-suggestion-simple.stderr index bfe98a71a9..3b2017d2d0 100644 --- a/src/test/ui/nll/outlives-suggestion-simple.stderr +++ b/src/test/ui/nll/outlives-suggestion-simple.stderr @@ -17,8 +17,6 @@ LL | fn foo2<'a>(x: &'a usize) -> &'static usize { | -- lifetime `'a` defined here LL | x | ^ returning this value requires that `'a` must outlive `'static` - | - = help: consider replacing `'a` with `'static` error: lifetime may not live long enough --> $DIR/outlives-suggestion-simple.rs:14:5 @@ -66,8 +64,6 @@ LL | pub fn foo<'a>(x: &'a usize) -> Self { | -- lifetime `'a` defined here LL | Foo { x } | ^^^^^^^^^ returning this value requires that `'a` must outlive `'static` - | - = help: consider replacing `'a` with `'static` error: lifetime may not live long enough --> $DIR/outlives-suggestion-simple.rs:41:9 @@ -96,13 +92,20 @@ LL | self.x error[E0521]: borrowed data escapes outside of associated function --> $DIR/outlives-suggestion-simple.rs:73:9 | +LL | impl<'a> Foo2<'a> { + | -- lifetime `'a` defined here +LL | // should not produce outlives suggestions to name 'self LL | fn get_bar(&self) -> Bar2 { | ----- | | | `self` declared here, outside of the associated function body | `self` is a reference that is only valid in the associated function body + | let's call the lifetime of this reference `'1` LL | Bar2::new(&self) - | ^^^^^^^^^^^^^^^^ `self` escapes the associated function body here + | ^^^^^^^^^^^^^^^^ + | | + | `self` escapes the associated function body here + | argument requires that `'1` must outlive `'a` error: aborting due to 9 previous errors diff --git a/src/test/ui/nll/polonius/assignment-to-differing-field.stderr b/src/test/ui/nll/polonius/assignment-to-differing-field.stderr index 2fe6a53a49..fd5e4531b2 100644 --- a/src/test/ui/nll/polonius/assignment-to-differing-field.stderr +++ b/src/test/ui/nll/polonius/assignment-to-differing-field.stderr @@ -17,7 +17,7 @@ LL | fn assignment_to_field_projection<'a, T>( | -- lifetime `'a` defined here ... LL | if let Some(n) = (list.0).next.as_mut() { - | ^^^^^^^^^^^^^--------- + | ^^^^^^^^^^^^^^^^^^^^^^ | | | `list.0.next` was mutably borrowed here in the previous iteration of the loop | argument requires that `list.0.next` is borrowed for `'a` @@ -41,7 +41,7 @@ LL | fn assignment_through_projection_chain<'a, T>( | -- lifetime `'a` defined here ... LL | if let Some(n) = ((((list.0).0).0).0).0.next.as_mut() { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^--------- + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | | `list.0.0.0.0.0.next` was mutably borrowed here in the previous iteration of the loop | argument requires that `list.0.0.0.0.0.next` is borrowed for `'a` diff --git a/src/test/ui/nll/region-ends-after-if-condition.nll.stderr b/src/test/ui/nll/region-ends-after-if-condition.nll.stderr deleted file mode 100644 index 322930984a..0000000000 --- a/src/test/ui/nll/region-ends-after-if-condition.nll.stderr +++ /dev/null @@ -1,15 +0,0 @@ -error[E0502]: cannot borrow `my_struct.field` as mutable because it is also borrowed as immutable - --> $DIR/region-ends-after-if-condition.rs:26:9 - | -LL | let value = &my_struct.field; - | ---------------- immutable borrow occurs here -LL | if value.is_empty() { -LL | my_struct.field.push_str("Hello, world!"); - | ^^^^^^^^^^^^^^^ mutable borrow occurs here -... -LL | drop(value); - | ----- immutable borrow later used here - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0502`. diff --git a/src/test/ui/nll/relate_tys/fn-subtype.stderr b/src/test/ui/nll/relate_tys/fn-subtype.stderr index 94def69008..6256c4a01d 100644 --- a/src/test/ui/nll/relate_tys/fn-subtype.stderr +++ b/src/test/ui/nll/relate_tys/fn-subtype.stderr @@ -4,7 +4,7 @@ error[E0308]: mismatched types LL | let y: for<'a> fn(&'a ()) = x; | ^ one type is more general than the other | - = note: expected fn pointer `for<'r> fn(&'r ())` + = note: expected fn pointer `for<'a> fn(&'a ())` found fn pointer `fn(&())` error: aborting due to previous error diff --git a/src/test/ui/nll/relate_tys/hr-fn-aaa-as-aba.stderr b/src/test/ui/nll/relate_tys/hr-fn-aaa-as-aba.stderr index 8c1eaeb6aa..b839015f97 100644 --- a/src/test/ui/nll/relate_tys/hr-fn-aaa-as-aba.stderr +++ b/src/test/ui/nll/relate_tys/hr-fn-aaa-as-aba.stderr @@ -4,7 +4,7 @@ error[E0308]: mismatched types LL | let a: for<'a, 'b> fn(&'a u32, &'b u32) -> &'a u32 = make_it(); | ^^^^^^^^^ one type is more general than the other | - = note: expected fn pointer `for<'r, 's> fn(&'r u32, &'s u32) -> &'r u32` + = note: expected fn pointer `for<'a, 'b> fn(&'a u32, &'b u32) -> &'a u32` found fn pointer `for<'a> fn(&'a u32, &'a u32) -> &'a u32` error[E0308]: mismatched types @@ -14,7 +14,7 @@ LL | let _: for<'a, 'b> fn(&'a u32, &'b u32) -> &'a u32 = make_it(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other | = note: expected fn pointer `for<'a, 'b> fn(&'a u32, &'b u32) -> &'a u32` - found fn pointer `for<'r> fn(&'r u32, &'r u32) -> &'r u32` + found fn pointer `for<'a> fn(&'a u32, &'a u32) -> &'a u32` error: aborting due to 2 previous errors diff --git a/src/test/ui/nll/relate_tys/trait-hrtb.stderr b/src/test/ui/nll/relate_tys/trait-hrtb.stderr index 60a7f20444..6d144a4be6 100644 --- a/src/test/ui/nll/relate_tys/trait-hrtb.stderr +++ b/src/test/ui/nll/relate_tys/trait-hrtb.stderr @@ -4,7 +4,7 @@ error[E0308]: mismatched types LL | let y: Box Foo<'a>> = x; | ^ one type is more general than the other | - = note: expected trait object `dyn for<'r> Foo<'r>` + = note: expected trait object `dyn for<'a> Foo<'a>` found trait object `dyn Foo<'_>` error: aborting due to previous error diff --git a/src/test/ui/nll/return_from_loop.stderr b/src/test/ui/nll/return_from_loop.stderr index efd56ea2dd..bd2b8b1585 100644 --- a/src/test/ui/nll/return_from_loop.stderr +++ b/src/test/ui/nll/return_from_loop.stderr @@ -5,10 +5,10 @@ LL | let value = &mut my_struct.field; | -------------------- first mutable borrow occurs here LL | loop { LL | my_struct.field.push_str("Hello, world!"); - | ^^^^^^^^^^^^^^^ second mutable borrow occurs here + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ second mutable borrow occurs here LL | LL | value.len(); - | ----- first borrow later used here + | ----------- first borrow later used here error: aborting due to previous error diff --git a/src/test/ui/nll/trait-associated-constant.stderr b/src/test/ui/nll/trait-associated-constant.stderr index 2af5b2a2e0..000ebc7165 100644 --- a/src/test/ui/nll/trait-associated-constant.stderr +++ b/src/test/ui/nll/trait-associated-constant.stderr @@ -6,12 +6,12 @@ LL | const AC: Option<&'c str> = None; | = note: expected enum `Option<&'b str>` found enum `Option<&'c str>` -note: the lifetime `'c` as defined on the impl at 20:18... +note: the lifetime `'c` as defined here... --> $DIR/trait-associated-constant.rs:20:18 | LL | impl<'a: 'b, 'b, 'c> Anything<'a, 'b> for FailStruct { | ^^ -note: ...does not necessarily outlive the lifetime `'b` as defined on the impl at 20:14 +note: ...does not necessarily outlive the lifetime `'b` as defined here --> $DIR/trait-associated-constant.rs:20:14 | LL | impl<'a: 'b, 'b, 'c> Anything<'a, 'b> for FailStruct { diff --git a/src/test/ui/nll/ty-outlives/wf-unreachable.stderr b/src/test/ui/nll/ty-outlives/wf-unreachable.stderr index f15c2ffd0d..9128fd1647 100644 --- a/src/test/ui/nll/ty-outlives/wf-unreachable.stderr +++ b/src/test/ui/nll/ty-outlives/wf-unreachable.stderr @@ -6,8 +6,6 @@ LL | fn uninit<'a>() { LL | return; LL | let x: &'static &'a (); | ^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static` - | - = help: consider replacing `'a` with `'static` error: lifetime may not live long enough --> $DIR/wf-unreachable.rs:13:12 @@ -17,8 +15,6 @@ LL | fn var_type<'a>() { LL | return; LL | let x: &'static &'a () = &&(); | ^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static` - | - = help: consider replacing `'a` with `'static` error: lifetime may not live long enough --> $DIR/wf-unreachable.rs:17:12 @@ -27,8 +23,6 @@ LL | fn uninit_infer<'a>() { | -- lifetime `'a` defined here LL | let x: &'static &'a _; | ^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static` - | - = help: consider replacing `'a` with `'static` error: lifetime may not live long enough --> $DIR/wf-unreachable.rs:23:12 @@ -38,8 +32,6 @@ LL | fn infer<'a>() { LL | return; LL | let x: &'static &'a _ = &&(); | ^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static` - | - = help: consider replacing `'a` with `'static` error: lifetime may not live long enough --> $DIR/wf-unreachable.rs:28:12 @@ -49,8 +41,6 @@ LL | fn uninit_no_var<'a>() { LL | return; LL | let _: &'static &'a (); | ^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static` - | - = help: consider replacing `'a` with `'static` error: lifetime may not live long enough --> $DIR/wf-unreachable.rs:33:12 @@ -60,8 +50,6 @@ LL | fn no_var<'a>() { LL | return; LL | let _: &'static &'a () = &&(); | ^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static` - | - = help: consider replacing `'a` with `'static` error: lifetime may not live long enough --> $DIR/wf-unreachable.rs:38:12 @@ -71,8 +59,6 @@ LL | fn infer_no_var<'a>() { LL | return; LL | let _: &'static &'a _ = &&(); | ^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static` - | - = help: consider replacing `'a` with `'static` error: lifetime may not live long enough --> $DIR/wf-unreachable.rs:51:12 @@ -82,8 +68,6 @@ LL | fn required_substs<'a>() { LL | return; LL | let _: C<'static, 'a, _> = C((), &(), &()); | ^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static` - | - = help: consider replacing `'a` with `'static` error: aborting due to 8 previous errors diff --git a/src/test/ui/nll/type-alias-free-regions.stderr b/src/test/ui/nll/type-alias-free-regions.stderr index 6498ecfbe6..71f5f8fb17 100644 --- a/src/test/ui/nll/type-alias-free-regions.stderr +++ b/src/test/ui/nll/type-alias-free-regions.stderr @@ -4,7 +4,7 @@ error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` d LL | C { f: b } | ^ | -note: first, the lifetime cannot outlive the anonymous lifetime defined on the method body at 16:24... +note: first, the lifetime cannot outlive the anonymous lifetime defined here... --> $DIR/type-alias-free-regions.rs:16:24 | LL | fn from_box(b: Box) -> Self { @@ -16,12 +16,12 @@ LL | C { f: b } | ^ = note: expected `Box>` found `Box>` -note: but, the lifetime must be valid for the lifetime `'a` as defined on the impl at 15:6... +note: but, the lifetime must be valid for the lifetime `'a` as defined here... --> $DIR/type-alias-free-regions.rs:15:6 | LL | impl<'a> FromBox<'a> for C<'a> { | ^^ -note: ...so that the expression is assignable +note: ...so that the types are compatible --> $DIR/type-alias-free-regions.rs:17:9 | LL | C { f: b } @@ -35,7 +35,7 @@ error[E0495]: cannot infer an appropriate lifetime due to conflicting requiremen LL | C { f: Box::new(b.0) } | ^^^^^^^^^^^^^ | -note: first, the lifetime cannot outlive the anonymous lifetime defined on the method body at 26:23... +note: first, the lifetime cannot outlive the anonymous lifetime defined here... --> $DIR/type-alias-free-regions.rs:26:23 | LL | fn from_tuple(b: (B,)) -> Self { @@ -47,12 +47,12 @@ LL | C { f: Box::new(b.0) } | ^^^ = note: expected `Box<&isize>` found `Box<&isize>` -note: but, the lifetime must be valid for the lifetime `'a` as defined on the impl at 25:6... +note: but, the lifetime must be valid for the lifetime `'a` as defined here... --> $DIR/type-alias-free-regions.rs:25:6 | LL | impl<'a> FromTuple<'a> for C<'a> { | ^^ -note: ...so that the expression is assignable +note: ...so that the types are compatible --> $DIR/type-alias-free-regions.rs:27:9 | LL | C { f: Box::new(b.0) } diff --git a/src/test/ui/nll/user-annotations/adt-brace-enums.stderr b/src/test/ui/nll/user-annotations/adt-brace-enums.stderr index e38b77fdce..253e382511 100644 --- a/src/test/ui/nll/user-annotations/adt-brace-enums.stderr +++ b/src/test/ui/nll/user-annotations/adt-brace-enums.stderr @@ -5,7 +5,7 @@ LL | SomeEnum::SomeVariant::<&'static u32> { t: &c }; | ^^ | | | borrowed value does not live long enough - | requires that `c` is borrowed for `'static` + | this usage requires that `c` is borrowed for `'static` LL | } | - `c` dropped here while still borrowed @@ -19,7 +19,7 @@ LL | SomeEnum::SomeVariant::<&'a u32> { t: &c }; | ^^ | | | borrowed value does not live long enough - | requires that `c` is borrowed for `'a` + | this usage requires that `c` is borrowed for `'a` LL | } | - `c` dropped here while still borrowed @@ -33,7 +33,7 @@ LL | SomeEnum::SomeVariant::<&'a u32> { t: &c }; | ^^ | | | borrowed value does not live long enough - | requires that `c` is borrowed for `'a` + | this usage requires that `c` is borrowed for `'a` LL | }; | - `c` dropped here while still borrowed diff --git a/src/test/ui/nll/user-annotations/adt-brace-structs.stderr b/src/test/ui/nll/user-annotations/adt-brace-structs.stderr index 3c3003477c..8b9d1705df 100644 --- a/src/test/ui/nll/user-annotations/adt-brace-structs.stderr +++ b/src/test/ui/nll/user-annotations/adt-brace-structs.stderr @@ -5,7 +5,7 @@ LL | SomeStruct::<&'static u32> { t: &c }; | ^^ | | | borrowed value does not live long enough - | requires that `c` is borrowed for `'static` + | this usage requires that `c` is borrowed for `'static` LL | } | - `c` dropped here while still borrowed @@ -19,7 +19,7 @@ LL | SomeStruct::<&'a u32> { t: &c }; | ^^ | | | borrowed value does not live long enough - | requires that `c` is borrowed for `'a` + | this usage requires that `c` is borrowed for `'a` LL | } | - `c` dropped here while still borrowed @@ -33,7 +33,7 @@ LL | SomeStruct::<&'a u32> { t: &c }; | ^^ | | | borrowed value does not live long enough - | requires that `c` is borrowed for `'a` + | this usage requires that `c` is borrowed for `'a` LL | }; | - `c` dropped here while still borrowed diff --git a/src/test/ui/nll/user-annotations/adt-tuple-enums.stderr b/src/test/ui/nll/user-annotations/adt-tuple-enums.stderr index 810912bf88..2fa7042631 100644 --- a/src/test/ui/nll/user-annotations/adt-tuple-enums.stderr +++ b/src/test/ui/nll/user-annotations/adt-tuple-enums.stderr @@ -5,7 +5,7 @@ LL | SomeEnum::SomeVariant::<&'static u32>(&c); | ^^ | | | borrowed value does not live long enough - | requires that `c` is borrowed for `'static` + | this usage requires that `c` is borrowed for `'static` LL | } | - `c` dropped here while still borrowed @@ -19,7 +19,7 @@ LL | SomeEnum::SomeVariant::<&'a u32>(&c); | ^^ | | | borrowed value does not live long enough - | requires that `c` is borrowed for `'a` + | this usage requires that `c` is borrowed for `'a` LL | } | - `c` dropped here while still borrowed @@ -33,7 +33,7 @@ LL | SomeEnum::SomeVariant::<&'a u32>(&c); | ^^ | | | borrowed value does not live long enough - | requires that `c` is borrowed for `'a` + | this usage requires that `c` is borrowed for `'a` LL | }; | - `c` dropped here while still borrowed diff --git a/src/test/ui/nll/user-annotations/adt-tuple-struct.stderr b/src/test/ui/nll/user-annotations/adt-tuple-struct.stderr index 4d2140eca1..76b5252258 100644 --- a/src/test/ui/nll/user-annotations/adt-tuple-struct.stderr +++ b/src/test/ui/nll/user-annotations/adt-tuple-struct.stderr @@ -5,7 +5,7 @@ LL | SomeStruct::<&'static u32>(&c); | ^^ | | | borrowed value does not live long enough - | requires that `c` is borrowed for `'static` + | this usage requires that `c` is borrowed for `'static` LL | } | - `c` dropped here while still borrowed @@ -19,7 +19,7 @@ LL | SomeStruct::<&'a u32>(&c); | ^^ | | | borrowed value does not live long enough - | requires that `c` is borrowed for `'a` + | this usage requires that `c` is borrowed for `'a` LL | } | - `c` dropped here while still borrowed @@ -33,7 +33,7 @@ LL | SomeStruct::<&'a u32>(&c); | ^^ | | | borrowed value does not live long enough - | requires that `c` is borrowed for `'a` + | this usage requires that `c` is borrowed for `'a` LL | }; | - `c` dropped here while still borrowed diff --git a/src/test/ui/nll/user-annotations/closure-substs.stderr b/src/test/ui/nll/user-annotations/closure-substs.stderr index 37e751aeb6..20002e4591 100644 --- a/src/test/ui/nll/user-annotations/closure-substs.stderr +++ b/src/test/ui/nll/user-annotations/closure-substs.stderr @@ -6,8 +6,6 @@ LL | fn foo<'a>() { ... LL | return x; | ^ returning this value requires that `'a` must outlive `'static` - | - = help: consider replacing `'a` with `'static` error: lifetime may not live long enough --> $DIR/closure-substs.rs:15:16 @@ -25,16 +23,19 @@ LL | fn bar<'a>() { ... LL | b(x); | ^^^^ argument requires that `'a` must outlive `'static` - | - = help: consider replacing `'a` with `'static` error[E0521]: borrowed data escapes outside of closure --> $DIR/closure-substs.rs:29:9 | LL | |x: &i32, b: fn(&'static i32)| { - | - `x` is a reference that is only valid in the closure body + | - - let's call the lifetime of this reference `'1` + | | + | `x` is a reference that is only valid in the closure body LL | b(x); - | ^^^^ `x` escapes the closure body here + | ^^^^ + | | + | `x` escapes the closure body here + | argument requires that `'1` must outlive `'static` error: aborting due to 4 previous errors diff --git a/src/test/ui/nll/user-annotations/constant-in-expr-inherent-1.nll.stderr b/src/test/ui/nll/user-annotations/constant-in-expr-inherent-1.nll.stderr index e9a0b8173c..c39301588a 100644 --- a/src/test/ui/nll/user-annotations/constant-in-expr-inherent-1.nll.stderr +++ b/src/test/ui/nll/user-annotations/constant-in-expr-inherent-1.nll.stderr @@ -5,8 +5,6 @@ LL | fn foo<'a>(_: &'a u32) -> &'static u32 { | -- lifetime `'a` defined here LL | >::C | ^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static` - | - = help: consider replacing `'a` with `'static` error: aborting due to previous error diff --git a/src/test/ui/nll/user-annotations/constant-in-expr-normalize.nll.stderr b/src/test/ui/nll/user-annotations/constant-in-expr-normalize.nll.stderr index 52ec36ef54..541a2cfaf2 100644 --- a/src/test/ui/nll/user-annotations/constant-in-expr-normalize.nll.stderr +++ b/src/test/ui/nll/user-annotations/constant-in-expr-normalize.nll.stderr @@ -5,8 +5,6 @@ LL | fn foo<'a>(_: &'a u32) -> &'static u32 { | -- lifetime `'a` defined here LL | <() as Foo<'a>>::C | ^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static` - | - = help: consider replacing `'a` with `'static` error: aborting due to previous error diff --git a/src/test/ui/nll/user-annotations/constant-in-expr-normalize.stderr b/src/test/ui/nll/user-annotations/constant-in-expr-normalize.stderr index 4c7adf75d2..d33c458421 100644 --- a/src/test/ui/nll/user-annotations/constant-in-expr-normalize.stderr +++ b/src/test/ui/nll/user-annotations/constant-in-expr-normalize.stderr @@ -5,7 +5,7 @@ LL | <() as Foo<'a>>::C | ^^^^^^^^^^^^^^^^^^ | = note: ...the reference is valid for the static lifetime... -note: ...but the borrowed content is only valid for the lifetime `'a` as defined on the function body at 17:8 +note: ...but the borrowed content is only valid for the lifetime `'a` as defined here --> $DIR/constant-in-expr-normalize.rs:17:8 | LL | fn foo<'a>(_: &'a u32) -> &'static u32 { diff --git a/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-1.nll.stderr b/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-1.nll.stderr index 5f3212eb9a..ea0fcb6d63 100644 --- a/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-1.nll.stderr +++ b/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-1.nll.stderr @@ -5,8 +5,6 @@ LL | fn foo<'a>(_: &'a u32) -> &'static u32 { | -- lifetime `'a` defined here LL | <() as Foo<'a>>::C | ^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static` - | - = help: consider replacing `'a` with `'static` error: aborting due to previous error diff --git a/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-1.stderr b/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-1.stderr index d01d022cba..3ec3a2af8c 100644 --- a/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-1.stderr +++ b/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-1.stderr @@ -5,7 +5,7 @@ LL | <() as Foo<'a>>::C | ^^^^^^^^^^^^^^^^^^ | = note: ...the reference is valid for the static lifetime... -note: ...but the borrowed content is only valid for the lifetime `'a` as defined on the function body at 9:8 +note: ...but the borrowed content is only valid for the lifetime `'a` as defined here --> $DIR/constant-in-expr-trait-item-1.rs:9:8 | LL | fn foo<'a>(_: &'a u32) -> &'static u32 { diff --git a/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-2.nll.stderr b/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-2.nll.stderr index 490030d30f..ff549f1d88 100644 --- a/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-2.nll.stderr +++ b/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-2.nll.stderr @@ -5,8 +5,6 @@ LL | fn foo<'a, T: Foo<'a>>() -> &'static u32 { | -- lifetime `'a` defined here LL | >::C | ^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static` - | - = help: consider replacing `'a` with `'static` error: aborting due to previous error diff --git a/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-2.stderr b/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-2.stderr index dd294280b9..b36bc3bdd9 100644 --- a/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-2.stderr +++ b/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-2.stderr @@ -5,7 +5,7 @@ LL | >::C | ^^^^^^^^^^^^^^^^^ | = note: ...the reference is valid for the static lifetime... -note: ...but the borrowed content is only valid for the lifetime `'a` as defined on the function body at 9:8 +note: ...but the borrowed content is only valid for the lifetime `'a` as defined here --> $DIR/constant-in-expr-trait-item-2.rs:9:8 | LL | fn foo<'a, T: Foo<'a>>() -> &'static u32 { diff --git a/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-3.nll.stderr b/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-3.nll.stderr index 5e687805c6..7f160d8e39 100644 --- a/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-3.nll.stderr +++ b/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-3.nll.stderr @@ -5,8 +5,6 @@ LL | fn foo<'a, T: Foo<'a>>() -> &'static u32 { | -- lifetime `'a` defined here LL | T::C | ^^^^ returning this value requires that `'a` must outlive `'static` - | - = help: consider replacing `'a` with `'static` error: aborting due to previous error diff --git a/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-3.stderr b/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-3.stderr index ba0a1748c5..806492b71f 100644 --- a/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-3.stderr +++ b/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-3.stderr @@ -4,7 +4,7 @@ error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` d LL | T::C | ^^^^ | -note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 9:8... +note: first, the lifetime cannot outlive the lifetime `'a` as defined here... --> $DIR/constant-in-expr-trait-item-3.rs:9:8 | LL | fn foo<'a, T: Foo<'a>>() -> &'static u32 { diff --git a/src/test/ui/nll/user-annotations/inherent-associated-constants.stderr b/src/test/ui/nll/user-annotations/inherent-associated-constants.stderr index 7b5646de77..7684546989 100644 --- a/src/test/ui/nll/user-annotations/inherent-associated-constants.stderr +++ b/src/test/ui/nll/user-annotations/inherent-associated-constants.stderr @@ -5,8 +5,6 @@ LL | fn non_wf_associated_const<'a>(x: i32) { | -- lifetime `'a` defined here LL | A::<'a>::IC; | ^^^^^^^^^^^ requires that `'a` must outlive `'static` - | - = help: consider replacing `'a` with `'static` error: aborting due to previous error diff --git a/src/test/ui/nll/user-annotations/issue-54124.stderr b/src/test/ui/nll/user-annotations/issue-54124.stderr index 97653b8c19..6cfccf7cb6 100644 --- a/src/test/ui/nll/user-annotations/issue-54124.stderr +++ b/src/test/ui/nll/user-annotations/issue-54124.stderr @@ -15,8 +15,6 @@ LL | fn test<'a>() { | -- lifetime `'a` defined here LL | let _:fn(&()) = |_:&'a ()| {}; | ^ requires that `'a` must outlive `'static` - | - = help: consider replacing `'a` with `'static` error: aborting due to 2 previous errors diff --git a/src/test/ui/nll/user-annotations/issue-55748-pat-types-constrain-bindings.stderr b/src/test/ui/nll/user-annotations/issue-55748-pat-types-constrain-bindings.stderr index f23ea9fdb5..5929707e41 100644 --- a/src/test/ui/nll/user-annotations/issue-55748-pat-types-constrain-bindings.stderr +++ b/src/test/ui/nll/user-annotations/issue-55748-pat-types-constrain-bindings.stderr @@ -6,8 +6,6 @@ LL | fn coupled_regions_lhs<'a>(_x: &'a u32, s: &'static u32) -> &'static u32 { ... LL | y | ^ returning this value requires that `'a` must outlive `'static` - | - = help: consider replacing `'a` with `'static` error: lifetime may not live long enough --> $DIR/issue-55748-pat-types-constrain-bindings.rs:49:5 @@ -17,8 +15,6 @@ LL | fn coupled_types_lhs<'a>(_x: &'a u32, s: &'static u32) -> &'static u32 { ... LL | y | ^ returning this value requires that `'a` must outlive `'static` - | - = help: consider replacing `'a` with `'static` error: lifetime may not live long enough --> $DIR/issue-55748-pat-types-constrain-bindings.rs:62:5 @@ -28,8 +24,6 @@ LL | fn coupled_wilds_lhs<'a>(_x: &'a u32, s: &'static u32) -> &'static u32 { ... LL | y | ^ returning this value requires that `'a` must outlive `'static` - | - = help: consider replacing `'a` with `'static` error: aborting due to 3 previous errors diff --git a/src/test/ui/nll/user-annotations/issue-57731-ascibed-coupled-types.stderr b/src/test/ui/nll/user-annotations/issue-57731-ascibed-coupled-types.stderr index 426c57ef9c..c99f53c5aa 100644 --- a/src/test/ui/nll/user-annotations/issue-57731-ascibed-coupled-types.stderr +++ b/src/test/ui/nll/user-annotations/issue-57731-ascibed-coupled-types.stderr @@ -6,8 +6,6 @@ LL | fn coupled_wilds_rhs<'a>(_x: &'a u32, s: &'static u32) -> &'static u32 { LL | let ((y, _z),) = ((s, _x),): (PairCoupledTypes<_>,); LL | y | ^ returning this value requires that `'a` must outlive `'static` - | - = help: consider replacing `'a` with `'static` error: lifetime may not live long enough --> $DIR/issue-57731-ascibed-coupled-types.rs:22:5 @@ -17,8 +15,6 @@ LL | fn coupled_regions_rhs<'a>(_x: &'a u32, s: &'static u32) -> &'static u32 { LL | let ((y, _z),) = ((s, _x),): (PairCoupledRegions<_>,); LL | y | ^ returning this value requires that `'a` must outlive `'static` - | - = help: consider replacing `'a` with `'static` error: lifetime may not live long enough --> $DIR/issue-57731-ascibed-coupled-types.rs:32:5 @@ -28,8 +24,6 @@ LL | fn cast_coupled_wilds_rhs<'a>(_x: &'a u32, s: &'static u32) -> &'static u32 LL | let ((y, _z),) = ((s, _x),) as (PairCoupledTypes<_>,); LL | y | ^ returning this value requires that `'a` must outlive `'static` - | - = help: consider replacing `'a` with `'static` error: lifetime may not live long enough --> $DIR/issue-57731-ascibed-coupled-types.rs:37:5 @@ -39,8 +33,6 @@ LL | fn cast_coupled_regions_rhs<'a>(_x: &'a u32, s: &'static u32) -> &'static u LL | let ((y, _z),) = ((s, _x),) as (PairCoupledRegions<_>,); LL | y | ^ returning this value requires that `'a` must outlive `'static` - | - = help: consider replacing `'a` with `'static` error: aborting due to 4 previous errors diff --git a/src/test/ui/nll/user-annotations/patterns.stderr b/src/test/ui/nll/user-annotations/patterns.stderr index c2786f0e8c..7ebd0ae227 100644 --- a/src/test/ui/nll/user-annotations/patterns.stderr +++ b/src/test/ui/nll/user-annotations/patterns.stderr @@ -156,8 +156,6 @@ LL | fn static_to_a_to_static_through_variable<'a>(x: &'a u32) -> &'static u32 { ... LL | y | ^ returning this value requires that `'a` must outlive `'static` - | - = help: consider replacing `'a` with `'static` error: lifetime may not live long enough --> $DIR/patterns.rs:125:5 @@ -167,8 +165,6 @@ LL | fn static_to_a_to_static_through_tuple<'a>(x: &'a u32) -> &'static u32 { ... LL | y | ^ returning this value requires that `'a` must outlive `'static` - | - = help: consider replacing `'a` with `'static` error: lifetime may not live long enough --> $DIR/patterns.rs:130:5 @@ -178,8 +174,6 @@ LL | fn static_to_a_to_static_through_struct<'a>(_x: &'a u32) -> &'static u32 { LL | let Single { value: y }: Single<&'a u32> = Single { value: &22 }; LL | y | ^ returning this value requires that `'a` must outlive `'static` - | - = help: consider replacing `'a` with `'static` error: lifetime may not live long enough --> $DIR/patterns.rs:134:18 @@ -188,8 +182,6 @@ LL | fn a_to_static_then_static<'a>(x: &'a u32) -> &'static u32 { | -- lifetime `'a` defined here LL | let (y, _z): (&'static u32, u32) = (x, 44); | ^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static` - | - = help: consider replacing `'a` with `'static` error: aborting due to 19 previous errors diff --git a/src/test/ui/nll/where_clauses_in_structs.stderr b/src/test/ui/nll/where_clauses_in_structs.stderr index 2e990131e6..8499b00f6f 100644 --- a/src/test/ui/nll/where_clauses_in_structs.stderr +++ b/src/test/ui/nll/where_clauses_in_structs.stderr @@ -6,7 +6,7 @@ LL | fn bar<'a, 'b>(x: Cell<&'a u32>, y: Cell<&'b u32>) { | | | lifetime `'a` defined here LL | Foo { x, y }; - | ^ requires that `'a` must outlive `'b` + | ^ this usage requires that `'a` must outlive `'b` | = help: consider adding the following bound: `'a: 'b` diff --git a/src/test/ui/no_crate_type.stderr b/src/test/ui/no_crate_type.stderr index f34df4e2dd..93da7c3e0d 100644 --- a/src/test/ui/no_crate_type.stderr +++ b/src/test/ui/no_crate_type.stderr @@ -2,7 +2,7 @@ error: malformed `crate_type` attribute input --> $DIR/no_crate_type.rs:2:1 | LL | #![crate_type] - | ^^^^^^^^^^^^^^ help: must be of the form: `#[crate_type = "bin|lib|..."]` + | ^^^^^^^^^^^^^^ help: must be of the form: `#![crate_type = "bin|lib|..."]` error: aborting due to previous error diff --git a/src/test/ui/no_send-rc.stderr b/src/test/ui/no_send-rc.stderr index f8be5e76f7..ce25da559d 100644 --- a/src/test/ui/no_send-rc.stderr +++ b/src/test/ui/no_send-rc.stderr @@ -2,7 +2,9 @@ error[E0277]: `Rc<{integer}>` cannot be sent between threads safely --> $DIR/no_send-rc.rs:7:9 | LL | bar(x); - | ^ `Rc<{integer}>` cannot be sent between threads safely + | --- ^ `Rc<{integer}>` cannot be sent between threads safely + | | + | required by a bound introduced by this call | = help: the trait `Send` is not implemented for `Rc<{integer}>` note: required by a bound in `bar` diff --git a/src/test/ui/no_send-struct.stderr b/src/test/ui/no_send-struct.stderr index 2f8cf3569a..ee7bdf282b 100644 --- a/src/test/ui/no_send-struct.stderr +++ b/src/test/ui/no_send-struct.stderr @@ -2,7 +2,9 @@ error[E0277]: `Foo` cannot be sent between threads safely --> $DIR/no_send-struct.rs:15:9 | LL | bar(x); - | ^ `Foo` cannot be sent between threads safely + | --- ^ `Foo` cannot be sent between threads safely + | | + | required by a bound introduced by this call | = help: the trait `Send` is not implemented for `Foo` note: required by a bound in `bar` diff --git a/src/test/ui/no_share-struct.stderr b/src/test/ui/no_share-struct.stderr index 8983b08678..9ce3a318f1 100644 --- a/src/test/ui/no_share-struct.stderr +++ b/src/test/ui/no_share-struct.stderr @@ -2,7 +2,9 @@ error[E0277]: `Foo` cannot be shared between threads safely --> $DIR/no_share-struct.rs:12:9 | LL | bar(x); - | ^ `Foo` cannot be shared between threads safely + | --- ^ `Foo` cannot be shared between threads safely + | | + | required by a bound introduced by this call | = help: the trait `Sync` is not implemented for `Foo` note: required by a bound in `bar` diff --git a/src/test/ui/non-fmt-panic.stderr b/src/test/ui/non-fmt-panic.stderr index b62cc378aa..f9e6d89513 100644 --- a/src/test/ui/non-fmt-panic.stderr +++ b/src/test/ui/non-fmt-panic.stderr @@ -199,7 +199,7 @@ warning: panic message contains braces --> $DIR/non-fmt-panic.rs:31:5 | LL | panic!(concat!("{", "{")); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: this message is not used as a format string, but will be in Rust 2021 help: add a "{}" format string to use the message literally diff --git a/src/test/ui/nullable-pointer-iotareduction.rs b/src/test/ui/nullable-pointer-iotareduction.rs index 568c3e144b..f9edba6743 100644 --- a/src/test/ui/nullable-pointer-iotareduction.rs +++ b/src/test/ui/nullable-pointer-iotareduction.rs @@ -1,7 +1,5 @@ // run-pass -#![feature(box_syntax)] - // Iota-reduction is a rule in the Calculus of (Co-)Inductive Constructions, // which "says that a destructor applied to an object built from a constructor // behaves as expected". -- https://coq.inria.fr/doc/language/core/conversion.html#iota-reduction @@ -64,7 +62,7 @@ macro_rules! check_type { pub fn main() { check_type!(&17, &isize); - check_type!(box 18, Box); + check_type!(Box::new(18), Box); check_type!("foo".to_string(), String); check_type!(vec![20, 22], Vec); check_type!(main, fn(), |pthing| { diff --git a/src/test/ui/numeric/const-scope.stderr b/src/test/ui/numeric/const-scope.stderr index 6732391e1a..4e4bcdf234 100644 --- a/src/test/ui/numeric/const-scope.stderr +++ b/src/test/ui/numeric/const-scope.stderr @@ -7,7 +7,7 @@ LL | const C: i32 = 1i8; help: change the type of the numeric literal from `i8` to `i32` | LL | const C: i32 = 1i32; - | ~~~~ + | ~~~ error[E0308]: mismatched types --> $DIR/const-scope.rs:2:15 @@ -26,7 +26,7 @@ LL | let c: i32 = 1i8; help: change the type of the numeric literal from `i8` to `i32` | LL | let c: i32 = 1i32; - | ~~~~ + | ~~~ error[E0308]: mismatched types --> $DIR/const-scope.rs:6:17 @@ -47,7 +47,7 @@ LL | let c: i32 = 1i8; help: change the type of the numeric literal from `i8` to `i32` | LL | let c: i32 = 1i32; - | ~~~~ + | ~~~ error[E0308]: mismatched types --> $DIR/const-scope.rs:11:17 @@ -60,7 +60,7 @@ LL | let d: i8 = c; help: you can convert an `i32` to an `i8` and panic if the converted value doesn't fit | LL | let d: i8 = c.try_into().unwrap(); - | ~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error: aborting due to 6 previous errors diff --git a/src/test/ui/numeric/len.stderr b/src/test/ui/numeric/len.stderr index 9a3248c572..6319c1ead2 100644 --- a/src/test/ui/numeric/len.stderr +++ b/src/test/ui/numeric/len.stderr @@ -7,7 +7,7 @@ LL | test(array.len()); help: you can convert a `usize` to a `u32` and panic if the converted value doesn't fit | LL | test(array.len().try_into().unwrap()); - | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error: aborting due to previous error diff --git a/src/test/ui/numeric/numeric-cast-2.stderr b/src/test/ui/numeric/numeric-cast-2.stderr index 83d8ce5eea..a7b342739a 100644 --- a/src/test/ui/numeric/numeric-cast-2.stderr +++ b/src/test/ui/numeric/numeric-cast-2.stderr @@ -9,27 +9,33 @@ LL | let x: u16 = foo(); help: you can convert an `i32` to a `u16` and panic if the converted value doesn't fit | LL | let x: u16 = foo().try_into().unwrap(); - | ~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast-2.rs:7:18 | LL | let y: i64 = x + x; - | --- ^^^^^ - | | | - | | expected `i64`, found `u16` - | | help: you can convert a `u16` to an `i64`: `(x + x).into()` + | --- ^^^^^ expected `i64`, found `u16` + | | | expected due to this + | +help: you can convert a `u16` to an `i64` + | +LL | let y: i64 = (x + x).into(); + | + ++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast-2.rs:9:18 | LL | let z: i32 = x + x; - | --- ^^^^^ - | | | - | | expected `i32`, found `u16` - | | help: you can convert a `u16` to an `i32`: `(x + x).into()` + | --- ^^^^^ expected `i32`, found `u16` + | | | expected due to this + | +help: you can convert a `u16` to an `i32` + | +LL | let z: i32 = (x + x).into(); + | + ++++++++ error: aborting due to 3 previous errors diff --git a/src/test/ui/numeric/numeric-cast-binop.stderr b/src/test/ui/numeric/numeric-cast-binop.stderr index b0ff50748f..2f58f16498 100644 --- a/src/test/ui/numeric/numeric-cast-binop.stderr +++ b/src/test/ui/numeric/numeric-cast-binop.stderr @@ -7,7 +7,7 @@ LL | x_u8 > x_u16; help: you can convert `x_u8` from `u8` to `u16`, matching the type of `x_u16` | LL | u16::from(x_u8) > x_u16; - | ~~~~~~~~~~~~~~~ + | ++++++++++ + error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:25:16 @@ -18,7 +18,7 @@ LL | x_u8 > x_u32; help: you can convert `x_u8` from `u8` to `u32`, matching the type of `x_u32` | LL | u32::from(x_u8) > x_u32; - | ~~~~~~~~~~~~~~~ + | ++++++++++ + error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:27:16 @@ -29,7 +29,7 @@ LL | x_u8 > x_u64; help: you can convert `x_u8` from `u8` to `u64`, matching the type of `x_u64` | LL | u64::from(x_u8) > x_u64; - | ~~~~~~~~~~~~~~~ + | ++++++++++ + error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:29:16 @@ -40,7 +40,7 @@ LL | x_u8 > x_u128; help: you can convert `x_u8` from `u8` to `u128`, matching the type of `x_u128` | LL | u128::from(x_u8) > x_u128; - | ~~~~~~~~~~~~~~~~ + | +++++++++++ + error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:31:16 @@ -51,16 +51,18 @@ LL | x_u8 > x_usize; help: you can convert `x_u8` from `u8` to `usize`, matching the type of `x_usize` | LL | usize::from(x_u8) > x_usize; - | ~~~~~~~~~~~~~~~~~ + | ++++++++++++ + error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:34:17 | LL | x_u16 > x_u8; - | ^^^^ - | | - | expected `u16`, found `u8` - | help: you can convert a `u8` to a `u16`: `x_u8.into()` + | ^^^^ expected `u16`, found `u8` + | +help: you can convert a `u8` to a `u16` + | +LL | x_u16 > x_u8.into(); + | +++++++ error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:36:17 @@ -71,7 +73,7 @@ LL | x_u16 > x_u32; help: you can convert `x_u16` from `u16` to `u32`, matching the type of `x_u32` | LL | u32::from(x_u16) > x_u32; - | ~~~~~~~~~~~~~~~~ + | ++++++++++ + error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:38:17 @@ -82,7 +84,7 @@ LL | x_u16 > x_u64; help: you can convert `x_u16` from `u16` to `u64`, matching the type of `x_u64` | LL | u64::from(x_u16) > x_u64; - | ~~~~~~~~~~~~~~~~ + | ++++++++++ + error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:40:17 @@ -93,7 +95,7 @@ LL | x_u16 > x_u128; help: you can convert `x_u16` from `u16` to `u128`, matching the type of `x_u128` | LL | u128::from(x_u16) > x_u128; - | ~~~~~~~~~~~~~~~~~ + | +++++++++++ + error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:42:17 @@ -104,25 +106,29 @@ LL | x_u16 > x_usize; help: you can convert `x_u16` from `u16` to `usize`, matching the type of `x_usize` | LL | usize::from(x_u16) > x_usize; - | ~~~~~~~~~~~~~~~~~~ + | ++++++++++++ + error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:45:17 | LL | x_u32 > x_u8; - | ^^^^ - | | - | expected `u32`, found `u8` - | help: you can convert a `u8` to a `u32`: `x_u8.into()` + | ^^^^ expected `u32`, found `u8` + | +help: you can convert a `u8` to a `u32` + | +LL | x_u32 > x_u8.into(); + | +++++++ error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:47:17 | LL | x_u32 > x_u16; - | ^^^^^ - | | - | expected `u32`, found `u16` - | help: you can convert a `u16` to a `u32`: `x_u16.into()` + | ^^^^^ expected `u32`, found `u16` + | +help: you can convert a `u16` to a `u32` + | +LL | x_u32 > x_u16.into(); + | +++++++ error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:49:17 @@ -133,7 +139,7 @@ LL | x_u32 > x_u64; help: you can convert `x_u32` from `u32` to `u64`, matching the type of `x_u64` | LL | u64::from(x_u32) > x_u64; - | ~~~~~~~~~~~~~~~~ + | ++++++++++ + error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:51:17 @@ -144,7 +150,7 @@ LL | x_u32 > x_u128; help: you can convert `x_u32` from `u32` to `u128`, matching the type of `x_u128` | LL | u128::from(x_u32) > x_u128; - | ~~~~~~~~~~~~~~~~~ + | +++++++++++ + error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:53:17 @@ -155,34 +161,40 @@ LL | x_u32 > x_usize; help: you can convert a `usize` to a `u32` and panic if the converted value doesn't fit | LL | x_u32 > x_usize.try_into().unwrap(); - | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:56:17 | LL | x_u64 > x_u8; - | ^^^^ - | | - | expected `u64`, found `u8` - | help: you can convert a `u8` to a `u64`: `x_u8.into()` + | ^^^^ expected `u64`, found `u8` + | +help: you can convert a `u8` to a `u64` + | +LL | x_u64 > x_u8.into(); + | +++++++ error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:58:17 | LL | x_u64 > x_u16; - | ^^^^^ - | | - | expected `u64`, found `u16` - | help: you can convert a `u16` to a `u64`: `x_u16.into()` + | ^^^^^ expected `u64`, found `u16` + | +help: you can convert a `u16` to a `u64` + | +LL | x_u64 > x_u16.into(); + | +++++++ error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:60:17 | LL | x_u64 > x_u32; - | ^^^^^ - | | - | expected `u64`, found `u32` - | help: you can convert a `u32` to a `u64`: `x_u32.into()` + | ^^^^^ expected `u64`, found `u32` + | +help: you can convert a `u32` to a `u64` + | +LL | x_u64 > x_u32.into(); + | +++++++ error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:62:17 @@ -193,7 +205,7 @@ LL | x_u64 > x_u128; help: you can convert `x_u64` from `u64` to `u128`, matching the type of `x_u128` | LL | u128::from(x_u64) > x_u128; - | ~~~~~~~~~~~~~~~~~ + | +++++++++++ + error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:64:17 @@ -204,43 +216,51 @@ LL | x_u64 > x_usize; help: you can convert a `usize` to a `u64` and panic if the converted value doesn't fit | LL | x_u64 > x_usize.try_into().unwrap(); - | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:67:18 | LL | x_u128 > x_u8; - | ^^^^ - | | - | expected `u128`, found `u8` - | help: you can convert a `u8` to a `u128`: `x_u8.into()` + | ^^^^ expected `u128`, found `u8` + | +help: you can convert a `u8` to a `u128` + | +LL | x_u128 > x_u8.into(); + | +++++++ error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:69:18 | LL | x_u128 > x_u16; - | ^^^^^ - | | - | expected `u128`, found `u16` - | help: you can convert a `u16` to a `u128`: `x_u16.into()` + | ^^^^^ expected `u128`, found `u16` + | +help: you can convert a `u16` to a `u128` + | +LL | x_u128 > x_u16.into(); + | +++++++ error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:71:18 | LL | x_u128 > x_u32; - | ^^^^^ - | | - | expected `u128`, found `u32` - | help: you can convert a `u32` to a `u128`: `x_u32.into()` + | ^^^^^ expected `u128`, found `u32` + | +help: you can convert a `u32` to a `u128` + | +LL | x_u128 > x_u32.into(); + | +++++++ error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:73:18 | LL | x_u128 > x_u64; - | ^^^^^ - | | - | expected `u128`, found `u64` - | help: you can convert a `u64` to a `u128`: `x_u64.into()` + | ^^^^^ expected `u128`, found `u64` + | +help: you can convert a `u64` to a `u128` + | +LL | x_u128 > x_u64.into(); + | +++++++ error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:75:18 @@ -251,25 +271,29 @@ LL | x_u128 > x_usize; help: you can convert a `usize` to a `u128` and panic if the converted value doesn't fit | LL | x_u128 > x_usize.try_into().unwrap(); - | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:78:19 | LL | x_usize > x_u8; - | ^^^^ - | | - | expected `usize`, found `u8` - | help: you can convert a `u8` to a `usize`: `x_u8.into()` + | ^^^^ expected `usize`, found `u8` + | +help: you can convert a `u8` to a `usize` + | +LL | x_usize > x_u8.into(); + | +++++++ error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:80:19 | LL | x_usize > x_u16; - | ^^^^^ - | | - | expected `usize`, found `u16` - | help: you can convert a `u16` to a `usize`: `x_u16.into()` + | ^^^^^ expected `usize`, found `u16` + | +help: you can convert a `u16` to a `usize` + | +LL | x_usize > x_u16.into(); + | +++++++ error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:82:19 @@ -280,7 +304,7 @@ LL | x_usize > x_u32; help: you can convert a `u32` to a `usize` and panic if the converted value doesn't fit | LL | x_usize > x_u32.try_into().unwrap(); - | ~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:84:19 @@ -291,7 +315,7 @@ LL | x_usize > x_u64; help: you can convert a `u64` to a `usize` and panic if the converted value doesn't fit | LL | x_usize > x_u64.try_into().unwrap(); - | ~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:86:19 @@ -302,7 +326,7 @@ LL | x_usize > x_u128; help: you can convert a `u128` to a `usize` and panic if the converted value doesn't fit | LL | x_usize > x_u128.try_into().unwrap(); - | ~~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:92:16 @@ -313,7 +337,7 @@ LL | x_i8 > x_i16; help: you can convert `x_i8` from `i8` to `i16`, matching the type of `x_i16` | LL | i16::from(x_i8) > x_i16; - | ~~~~~~~~~~~~~~~ + | ++++++++++ + error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:94:16 @@ -324,7 +348,7 @@ LL | x_i8 > x_i32; help: you can convert `x_i8` from `i8` to `i32`, matching the type of `x_i32` | LL | i32::from(x_i8) > x_i32; - | ~~~~~~~~~~~~~~~ + | ++++++++++ + error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:96:16 @@ -335,7 +359,7 @@ LL | x_i8 > x_i64; help: you can convert `x_i8` from `i8` to `i64`, matching the type of `x_i64` | LL | i64::from(x_i8) > x_i64; - | ~~~~~~~~~~~~~~~ + | ++++++++++ + error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:98:16 @@ -346,7 +370,7 @@ LL | x_i8 > x_i128; help: you can convert `x_i8` from `i8` to `i128`, matching the type of `x_i128` | LL | i128::from(x_i8) > x_i128; - | ~~~~~~~~~~~~~~~~ + | +++++++++++ + error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:100:16 @@ -357,16 +381,18 @@ LL | x_i8 > x_isize; help: you can convert `x_i8` from `i8` to `isize`, matching the type of `x_isize` | LL | isize::from(x_i8) > x_isize; - | ~~~~~~~~~~~~~~~~~ + | ++++++++++++ + error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:103:17 | LL | x_i16 > x_i8; - | ^^^^ - | | - | expected `i16`, found `i8` - | help: you can convert an `i8` to an `i16`: `x_i8.into()` + | ^^^^ expected `i16`, found `i8` + | +help: you can convert an `i8` to an `i16` + | +LL | x_i16 > x_i8.into(); + | +++++++ error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:105:17 @@ -377,7 +403,7 @@ LL | x_i16 > x_i32; help: you can convert `x_i16` from `i16` to `i32`, matching the type of `x_i32` | LL | i32::from(x_i16) > x_i32; - | ~~~~~~~~~~~~~~~~ + | ++++++++++ + error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:107:17 @@ -388,7 +414,7 @@ LL | x_i16 > x_i64; help: you can convert `x_i16` from `i16` to `i64`, matching the type of `x_i64` | LL | i64::from(x_i16) > x_i64; - | ~~~~~~~~~~~~~~~~ + | ++++++++++ + error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:109:17 @@ -399,7 +425,7 @@ LL | x_i16 > x_i128; help: you can convert `x_i16` from `i16` to `i128`, matching the type of `x_i128` | LL | i128::from(x_i16) > x_i128; - | ~~~~~~~~~~~~~~~~~ + | +++++++++++ + error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:111:17 @@ -410,25 +436,29 @@ LL | x_i16 > x_isize; help: you can convert `x_i16` from `i16` to `isize`, matching the type of `x_isize` | LL | isize::from(x_i16) > x_isize; - | ~~~~~~~~~~~~~~~~~~ + | ++++++++++++ + error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:114:17 | LL | x_i32 > x_i8; - | ^^^^ - | | - | expected `i32`, found `i8` - | help: you can convert an `i8` to an `i32`: `x_i8.into()` + | ^^^^ expected `i32`, found `i8` + | +help: you can convert an `i8` to an `i32` + | +LL | x_i32 > x_i8.into(); + | +++++++ error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:116:17 | LL | x_i32 > x_i16; - | ^^^^^ - | | - | expected `i32`, found `i16` - | help: you can convert an `i16` to an `i32`: `x_i16.into()` + | ^^^^^ expected `i32`, found `i16` + | +help: you can convert an `i16` to an `i32` + | +LL | x_i32 > x_i16.into(); + | +++++++ error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:118:17 @@ -439,7 +469,7 @@ LL | x_i32 > x_i64; help: you can convert `x_i32` from `i32` to `i64`, matching the type of `x_i64` | LL | i64::from(x_i32) > x_i64; - | ~~~~~~~~~~~~~~~~ + | ++++++++++ + error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:120:17 @@ -450,7 +480,7 @@ LL | x_i32 > x_i128; help: you can convert `x_i32` from `i32` to `i128`, matching the type of `x_i128` | LL | i128::from(x_i32) > x_i128; - | ~~~~~~~~~~~~~~~~~ + | +++++++++++ + error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:122:17 @@ -461,34 +491,40 @@ LL | x_i32 > x_isize; help: you can convert an `isize` to an `i32` and panic if the converted value doesn't fit | LL | x_i32 > x_isize.try_into().unwrap(); - | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:125:17 | LL | x_i64 > x_i8; - | ^^^^ - | | - | expected `i64`, found `i8` - | help: you can convert an `i8` to an `i64`: `x_i8.into()` + | ^^^^ expected `i64`, found `i8` + | +help: you can convert an `i8` to an `i64` + | +LL | x_i64 > x_i8.into(); + | +++++++ error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:127:17 | LL | x_i64 > x_i16; - | ^^^^^ - | | - | expected `i64`, found `i16` - | help: you can convert an `i16` to an `i64`: `x_i16.into()` + | ^^^^^ expected `i64`, found `i16` + | +help: you can convert an `i16` to an `i64` + | +LL | x_i64 > x_i16.into(); + | +++++++ error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:129:17 | LL | x_i64 > x_i32; - | ^^^^^ - | | - | expected `i64`, found `i32` - | help: you can convert an `i32` to an `i64`: `x_i32.into()` + | ^^^^^ expected `i64`, found `i32` + | +help: you can convert an `i32` to an `i64` + | +LL | x_i64 > x_i32.into(); + | +++++++ error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:131:17 @@ -499,7 +535,7 @@ LL | x_i64 > x_i128; help: you can convert `x_i64` from `i64` to `i128`, matching the type of `x_i128` | LL | i128::from(x_i64) > x_i128; - | ~~~~~~~~~~~~~~~~~ + | +++++++++++ + error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:133:17 @@ -510,43 +546,51 @@ LL | x_i64 > x_isize; help: you can convert an `isize` to an `i64` and panic if the converted value doesn't fit | LL | x_i64 > x_isize.try_into().unwrap(); - | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:136:18 | LL | x_i128 > x_i8; - | ^^^^ - | | - | expected `i128`, found `i8` - | help: you can convert an `i8` to an `i128`: `x_i8.into()` + | ^^^^ expected `i128`, found `i8` + | +help: you can convert an `i8` to an `i128` + | +LL | x_i128 > x_i8.into(); + | +++++++ error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:138:18 | LL | x_i128 > x_i16; - | ^^^^^ - | | - | expected `i128`, found `i16` - | help: you can convert an `i16` to an `i128`: `x_i16.into()` + | ^^^^^ expected `i128`, found `i16` + | +help: you can convert an `i16` to an `i128` + | +LL | x_i128 > x_i16.into(); + | +++++++ error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:140:18 | LL | x_i128 > x_i32; - | ^^^^^ - | | - | expected `i128`, found `i32` - | help: you can convert an `i32` to an `i128`: `x_i32.into()` + | ^^^^^ expected `i128`, found `i32` + | +help: you can convert an `i32` to an `i128` + | +LL | x_i128 > x_i32.into(); + | +++++++ error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:142:18 | LL | x_i128 > x_i64; - | ^^^^^ - | | - | expected `i128`, found `i64` - | help: you can convert an `i64` to an `i128`: `x_i64.into()` + | ^^^^^ expected `i128`, found `i64` + | +help: you can convert an `i64` to an `i128` + | +LL | x_i128 > x_i64.into(); + | +++++++ error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:144:18 @@ -557,25 +601,29 @@ LL | x_i128 > x_isize; help: you can convert an `isize` to an `i128` and panic if the converted value doesn't fit | LL | x_i128 > x_isize.try_into().unwrap(); - | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:147:19 | LL | x_isize > x_i8; - | ^^^^ - | | - | expected `isize`, found `i8` - | help: you can convert an `i8` to an `isize`: `x_i8.into()` + | ^^^^ expected `isize`, found `i8` + | +help: you can convert an `i8` to an `isize` + | +LL | x_isize > x_i8.into(); + | +++++++ error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:149:19 | LL | x_isize > x_i16; - | ^^^^^ - | | - | expected `isize`, found `i16` - | help: you can convert an `i16` to an `isize`: `x_i16.into()` + | ^^^^^ expected `isize`, found `i16` + | +help: you can convert an `i16` to an `isize` + | +LL | x_isize > x_i16.into(); + | +++++++ error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:151:19 @@ -586,7 +634,7 @@ LL | x_isize > x_i32; help: you can convert an `i32` to an `isize` and panic if the converted value doesn't fit | LL | x_isize > x_i32.try_into().unwrap(); - | ~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:153:19 @@ -597,7 +645,7 @@ LL | x_isize > x_i64; help: you can convert an `i64` to an `isize` and panic if the converted value doesn't fit | LL | x_isize > x_i64.try_into().unwrap(); - | ~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:155:19 @@ -608,7 +656,7 @@ LL | x_isize > x_i128; help: you can convert an `i128` to an `isize` and panic if the converted value doesn't fit | LL | x_isize > x_i128.try_into().unwrap(); - | ~~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:161:16 @@ -619,7 +667,7 @@ LL | x_u8 > x_i8; help: you can convert an `i8` to a `u8` and panic if the converted value doesn't fit | LL | x_u8 > x_i8.try_into().unwrap(); - | ~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:163:16 @@ -630,7 +678,7 @@ LL | x_u8 > x_i16; help: you can convert `x_u8` from `u8` to `i16`, matching the type of `x_i16` | LL | i16::from(x_u8) > x_i16; - | ~~~~~~~~~~~~~~~ + | ++++++++++ + error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:165:16 @@ -641,7 +689,7 @@ LL | x_u8 > x_i32; help: you can convert `x_u8` from `u8` to `i32`, matching the type of `x_i32` | LL | i32::from(x_u8) > x_i32; - | ~~~~~~~~~~~~~~~ + | ++++++++++ + error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:167:16 @@ -652,7 +700,7 @@ LL | x_u8 > x_i64; help: you can convert `x_u8` from `u8` to `i64`, matching the type of `x_i64` | LL | i64::from(x_u8) > x_i64; - | ~~~~~~~~~~~~~~~ + | ++++++++++ + error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:169:16 @@ -663,7 +711,7 @@ LL | x_u8 > x_i128; help: you can convert `x_u8` from `u8` to `i128`, matching the type of `x_i128` | LL | i128::from(x_u8) > x_i128; - | ~~~~~~~~~~~~~~~~ + | +++++++++++ + error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:171:16 @@ -674,7 +722,7 @@ LL | x_u8 > x_isize; help: you can convert `x_u8` from `u8` to `isize`, matching the type of `x_isize` | LL | isize::from(x_u8) > x_isize; - | ~~~~~~~~~~~~~~~~~ + | ++++++++++++ + error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:174:17 @@ -685,7 +733,7 @@ LL | x_u16 > x_i8; help: you can convert an `i8` to a `u16` and panic if the converted value doesn't fit | LL | x_u16 > x_i8.try_into().unwrap(); - | ~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:176:17 @@ -696,7 +744,7 @@ LL | x_u16 > x_i16; help: you can convert an `i16` to a `u16` and panic if the converted value doesn't fit | LL | x_u16 > x_i16.try_into().unwrap(); - | ~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:178:17 @@ -707,7 +755,7 @@ LL | x_u16 > x_i32; help: you can convert `x_u16` from `u16` to `i32`, matching the type of `x_i32` | LL | i32::from(x_u16) > x_i32; - | ~~~~~~~~~~~~~~~~ + | ++++++++++ + error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:180:17 @@ -718,7 +766,7 @@ LL | x_u16 > x_i64; help: you can convert `x_u16` from `u16` to `i64`, matching the type of `x_i64` | LL | i64::from(x_u16) > x_i64; - | ~~~~~~~~~~~~~~~~ + | ++++++++++ + error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:182:17 @@ -729,7 +777,7 @@ LL | x_u16 > x_i128; help: you can convert `x_u16` from `u16` to `i128`, matching the type of `x_i128` | LL | i128::from(x_u16) > x_i128; - | ~~~~~~~~~~~~~~~~~ + | +++++++++++ + error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:184:17 @@ -740,7 +788,7 @@ LL | x_u16 > x_isize; help: you can convert an `isize` to a `u16` and panic if the converted value doesn't fit | LL | x_u16 > x_isize.try_into().unwrap(); - | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:187:17 @@ -751,7 +799,7 @@ LL | x_u32 > x_i8; help: you can convert an `i8` to a `u32` and panic if the converted value doesn't fit | LL | x_u32 > x_i8.try_into().unwrap(); - | ~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:189:17 @@ -762,7 +810,7 @@ LL | x_u32 > x_i16; help: you can convert an `i16` to a `u32` and panic if the converted value doesn't fit | LL | x_u32 > x_i16.try_into().unwrap(); - | ~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:191:17 @@ -773,7 +821,7 @@ LL | x_u32 > x_i32; help: you can convert an `i32` to a `u32` and panic if the converted value doesn't fit | LL | x_u32 > x_i32.try_into().unwrap(); - | ~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:193:17 @@ -784,7 +832,7 @@ LL | x_u32 > x_i64; help: you can convert `x_u32` from `u32` to `i64`, matching the type of `x_i64` | LL | i64::from(x_u32) > x_i64; - | ~~~~~~~~~~~~~~~~ + | ++++++++++ + error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:195:17 @@ -795,7 +843,7 @@ LL | x_u32 > x_i128; help: you can convert `x_u32` from `u32` to `i128`, matching the type of `x_i128` | LL | i128::from(x_u32) > x_i128; - | ~~~~~~~~~~~~~~~~~ + | +++++++++++ + error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:197:17 @@ -806,7 +854,7 @@ LL | x_u32 > x_isize; help: you can convert an `isize` to a `u32` and panic if the converted value doesn't fit | LL | x_u32 > x_isize.try_into().unwrap(); - | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:200:17 @@ -817,7 +865,7 @@ LL | x_u64 > x_i8; help: you can convert an `i8` to a `u64` and panic if the converted value doesn't fit | LL | x_u64 > x_i8.try_into().unwrap(); - | ~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:202:17 @@ -828,7 +876,7 @@ LL | x_u64 > x_i16; help: you can convert an `i16` to a `u64` and panic if the converted value doesn't fit | LL | x_u64 > x_i16.try_into().unwrap(); - | ~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:204:17 @@ -839,7 +887,7 @@ LL | x_u64 > x_i32; help: you can convert an `i32` to a `u64` and panic if the converted value doesn't fit | LL | x_u64 > x_i32.try_into().unwrap(); - | ~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:206:17 @@ -850,7 +898,7 @@ LL | x_u64 > x_i64; help: you can convert an `i64` to a `u64` and panic if the converted value doesn't fit | LL | x_u64 > x_i64.try_into().unwrap(); - | ~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:208:17 @@ -861,7 +909,7 @@ LL | x_u64 > x_i128; help: you can convert `x_u64` from `u64` to `i128`, matching the type of `x_i128` | LL | i128::from(x_u64) > x_i128; - | ~~~~~~~~~~~~~~~~~ + | +++++++++++ + error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:210:17 @@ -872,7 +920,7 @@ LL | x_u64 > x_isize; help: you can convert an `isize` to a `u64` and panic if the converted value doesn't fit | LL | x_u64 > x_isize.try_into().unwrap(); - | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:213:18 @@ -883,7 +931,7 @@ LL | x_u128 > x_i8; help: you can convert an `i8` to a `u128` and panic if the converted value doesn't fit | LL | x_u128 > x_i8.try_into().unwrap(); - | ~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:215:18 @@ -894,7 +942,7 @@ LL | x_u128 > x_i16; help: you can convert an `i16` to a `u128` and panic if the converted value doesn't fit | LL | x_u128 > x_i16.try_into().unwrap(); - | ~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:217:18 @@ -905,7 +953,7 @@ LL | x_u128 > x_i32; help: you can convert an `i32` to a `u128` and panic if the converted value doesn't fit | LL | x_u128 > x_i32.try_into().unwrap(); - | ~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:219:18 @@ -916,7 +964,7 @@ LL | x_u128 > x_i64; help: you can convert an `i64` to a `u128` and panic if the converted value doesn't fit | LL | x_u128 > x_i64.try_into().unwrap(); - | ~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:221:18 @@ -927,7 +975,7 @@ LL | x_u128 > x_i128; help: you can convert an `i128` to a `u128` and panic if the converted value doesn't fit | LL | x_u128 > x_i128.try_into().unwrap(); - | ~~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:223:18 @@ -938,7 +986,7 @@ LL | x_u128 > x_isize; help: you can convert an `isize` to a `u128` and panic if the converted value doesn't fit | LL | x_u128 > x_isize.try_into().unwrap(); - | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:226:19 @@ -949,7 +997,7 @@ LL | x_usize > x_i8; help: you can convert an `i8` to a `usize` and panic if the converted value doesn't fit | LL | x_usize > x_i8.try_into().unwrap(); - | ~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:228:19 @@ -960,7 +1008,7 @@ LL | x_usize > x_i16; help: you can convert an `i16` to a `usize` and panic if the converted value doesn't fit | LL | x_usize > x_i16.try_into().unwrap(); - | ~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:230:19 @@ -971,7 +1019,7 @@ LL | x_usize > x_i32; help: you can convert an `i32` to a `usize` and panic if the converted value doesn't fit | LL | x_usize > x_i32.try_into().unwrap(); - | ~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:232:19 @@ -982,7 +1030,7 @@ LL | x_usize > x_i64; help: you can convert an `i64` to a `usize` and panic if the converted value doesn't fit | LL | x_usize > x_i64.try_into().unwrap(); - | ~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:234:19 @@ -993,7 +1041,7 @@ LL | x_usize > x_i128; help: you can convert an `i128` to a `usize` and panic if the converted value doesn't fit | LL | x_usize > x_i128.try_into().unwrap(); - | ~~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:236:19 @@ -1004,7 +1052,7 @@ LL | x_usize > x_isize; help: you can convert an `isize` to a `usize` and panic if the converted value doesn't fit | LL | x_usize > x_isize.try_into().unwrap(); - | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:242:16 @@ -1015,7 +1063,7 @@ LL | x_i8 > x_u8; help: you can convert a `u8` to an `i8` and panic if the converted value doesn't fit | LL | x_i8 > x_u8.try_into().unwrap(); - | ~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:244:16 @@ -1026,7 +1074,7 @@ LL | x_i8 > x_u16; help: you can convert a `u16` to an `i8` and panic if the converted value doesn't fit | LL | x_i8 > x_u16.try_into().unwrap(); - | ~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:246:16 @@ -1037,7 +1085,7 @@ LL | x_i8 > x_u32; help: you can convert a `u32` to an `i8` and panic if the converted value doesn't fit | LL | x_i8 > x_u32.try_into().unwrap(); - | ~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:248:16 @@ -1048,7 +1096,7 @@ LL | x_i8 > x_u64; help: you can convert a `u64` to an `i8` and panic if the converted value doesn't fit | LL | x_i8 > x_u64.try_into().unwrap(); - | ~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:250:16 @@ -1059,7 +1107,7 @@ LL | x_i8 > x_u128; help: you can convert a `u128` to an `i8` and panic if the converted value doesn't fit | LL | x_i8 > x_u128.try_into().unwrap(); - | ~~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:252:16 @@ -1070,16 +1118,18 @@ LL | x_i8 > x_usize; help: you can convert a `usize` to an `i8` and panic if the converted value doesn't fit | LL | x_i8 > x_usize.try_into().unwrap(); - | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:255:17 | LL | x_i16 > x_u8; - | ^^^^ - | | - | expected `i16`, found `u8` - | help: you can convert a `u8` to an `i16`: `x_u8.into()` + | ^^^^ expected `i16`, found `u8` + | +help: you can convert a `u8` to an `i16` + | +LL | x_i16 > x_u8.into(); + | +++++++ error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:257:17 @@ -1090,7 +1140,7 @@ LL | x_i16 > x_u16; help: you can convert a `u16` to an `i16` and panic if the converted value doesn't fit | LL | x_i16 > x_u16.try_into().unwrap(); - | ~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:259:17 @@ -1101,7 +1151,7 @@ LL | x_i16 > x_u32; help: you can convert a `u32` to an `i16` and panic if the converted value doesn't fit | LL | x_i16 > x_u32.try_into().unwrap(); - | ~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:261:17 @@ -1112,7 +1162,7 @@ LL | x_i16 > x_u64; help: you can convert a `u64` to an `i16` and panic if the converted value doesn't fit | LL | x_i16 > x_u64.try_into().unwrap(); - | ~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:263:17 @@ -1123,7 +1173,7 @@ LL | x_i16 > x_u128; help: you can convert a `u128` to an `i16` and panic if the converted value doesn't fit | LL | x_i16 > x_u128.try_into().unwrap(); - | ~~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:265:17 @@ -1134,25 +1184,29 @@ LL | x_i16 > x_usize; help: you can convert a `usize` to an `i16` and panic if the converted value doesn't fit | LL | x_i16 > x_usize.try_into().unwrap(); - | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:268:17 | LL | x_i32 > x_u8; - | ^^^^ - | | - | expected `i32`, found `u8` - | help: you can convert a `u8` to an `i32`: `x_u8.into()` + | ^^^^ expected `i32`, found `u8` + | +help: you can convert a `u8` to an `i32` + | +LL | x_i32 > x_u8.into(); + | +++++++ error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:270:17 | LL | x_i32 > x_u16; - | ^^^^^ - | | - | expected `i32`, found `u16` - | help: you can convert a `u16` to an `i32`: `x_u16.into()` + | ^^^^^ expected `i32`, found `u16` + | +help: you can convert a `u16` to an `i32` + | +LL | x_i32 > x_u16.into(); + | +++++++ error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:272:17 @@ -1163,7 +1217,7 @@ LL | x_i32 > x_u32; help: you can convert a `u32` to an `i32` and panic if the converted value doesn't fit | LL | x_i32 > x_u32.try_into().unwrap(); - | ~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:274:17 @@ -1174,7 +1228,7 @@ LL | x_i32 > x_u64; help: you can convert a `u64` to an `i32` and panic if the converted value doesn't fit | LL | x_i32 > x_u64.try_into().unwrap(); - | ~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:276:17 @@ -1185,7 +1239,7 @@ LL | x_i32 > x_u128; help: you can convert a `u128` to an `i32` and panic if the converted value doesn't fit | LL | x_i32 > x_u128.try_into().unwrap(); - | ~~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:278:17 @@ -1196,34 +1250,40 @@ LL | x_i32 > x_usize; help: you can convert a `usize` to an `i32` and panic if the converted value doesn't fit | LL | x_i32 > x_usize.try_into().unwrap(); - | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:281:17 | LL | x_i64 > x_u8; - | ^^^^ - | | - | expected `i64`, found `u8` - | help: you can convert a `u8` to an `i64`: `x_u8.into()` + | ^^^^ expected `i64`, found `u8` + | +help: you can convert a `u8` to an `i64` + | +LL | x_i64 > x_u8.into(); + | +++++++ error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:283:17 | LL | x_i64 > x_u16; - | ^^^^^ - | | - | expected `i64`, found `u16` - | help: you can convert a `u16` to an `i64`: `x_u16.into()` + | ^^^^^ expected `i64`, found `u16` + | +help: you can convert a `u16` to an `i64` + | +LL | x_i64 > x_u16.into(); + | +++++++ error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:285:17 | LL | x_i64 > x_u32; - | ^^^^^ - | | - | expected `i64`, found `u32` - | help: you can convert a `u32` to an `i64`: `x_u32.into()` + | ^^^^^ expected `i64`, found `u32` + | +help: you can convert a `u32` to an `i64` + | +LL | x_i64 > x_u32.into(); + | +++++++ error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:287:17 @@ -1234,7 +1294,7 @@ LL | x_i64 > x_u64; help: you can convert a `u64` to an `i64` and panic if the converted value doesn't fit | LL | x_i64 > x_u64.try_into().unwrap(); - | ~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:289:17 @@ -1245,7 +1305,7 @@ LL | x_i64 > x_u128; help: you can convert a `u128` to an `i64` and panic if the converted value doesn't fit | LL | x_i64 > x_u128.try_into().unwrap(); - | ~~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:291:17 @@ -1256,43 +1316,51 @@ LL | x_i64 > x_usize; help: you can convert a `usize` to an `i64` and panic if the converted value doesn't fit | LL | x_i64 > x_usize.try_into().unwrap(); - | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:294:18 | LL | x_i128 > x_u8; - | ^^^^ - | | - | expected `i128`, found `u8` - | help: you can convert a `u8` to an `i128`: `x_u8.into()` + | ^^^^ expected `i128`, found `u8` + | +help: you can convert a `u8` to an `i128` + | +LL | x_i128 > x_u8.into(); + | +++++++ error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:296:18 | LL | x_i128 > x_u16; - | ^^^^^ - | | - | expected `i128`, found `u16` - | help: you can convert a `u16` to an `i128`: `x_u16.into()` + | ^^^^^ expected `i128`, found `u16` + | +help: you can convert a `u16` to an `i128` + | +LL | x_i128 > x_u16.into(); + | +++++++ error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:298:18 | LL | x_i128 > x_u32; - | ^^^^^ - | | - | expected `i128`, found `u32` - | help: you can convert a `u32` to an `i128`: `x_u32.into()` + | ^^^^^ expected `i128`, found `u32` + | +help: you can convert a `u32` to an `i128` + | +LL | x_i128 > x_u32.into(); + | +++++++ error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:300:18 | LL | x_i128 > x_u64; - | ^^^^^ - | | - | expected `i128`, found `u64` - | help: you can convert a `u64` to an `i128`: `x_u64.into()` + | ^^^^^ expected `i128`, found `u64` + | +help: you can convert a `u64` to an `i128` + | +LL | x_i128 > x_u64.into(); + | +++++++ error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:302:18 @@ -1303,7 +1371,7 @@ LL | x_i128 > x_u128; help: you can convert a `u128` to an `i128` and panic if the converted value doesn't fit | LL | x_i128 > x_u128.try_into().unwrap(); - | ~~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:304:18 @@ -1314,16 +1382,18 @@ LL | x_i128 > x_usize; help: you can convert a `usize` to an `i128` and panic if the converted value doesn't fit | LL | x_i128 > x_usize.try_into().unwrap(); - | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:307:19 | LL | x_isize > x_u8; - | ^^^^ - | | - | expected `isize`, found `u8` - | help: you can convert a `u8` to an `isize`: `x_u8.into()` + | ^^^^ expected `isize`, found `u8` + | +help: you can convert a `u8` to an `isize` + | +LL | x_isize > x_u8.into(); + | +++++++ error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:309:19 @@ -1334,7 +1404,7 @@ LL | x_isize > x_u16; help: you can convert a `u16` to an `isize` and panic if the converted value doesn't fit | LL | x_isize > x_u16.try_into().unwrap(); - | ~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:311:19 @@ -1345,7 +1415,7 @@ LL | x_isize > x_u32; help: you can convert a `u32` to an `isize` and panic if the converted value doesn't fit | LL | x_isize > x_u32.try_into().unwrap(); - | ~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:313:19 @@ -1356,7 +1426,7 @@ LL | x_isize > x_u64; help: you can convert a `u64` to an `isize` and panic if the converted value doesn't fit | LL | x_isize > x_u64.try_into().unwrap(); - | ~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:315:19 @@ -1367,7 +1437,7 @@ LL | x_isize > x_u128; help: you can convert a `u128` to an `isize` and panic if the converted value doesn't fit | LL | x_isize > x_u128.try_into().unwrap(); - | ~~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast-binop.rs:317:19 @@ -1378,7 +1448,7 @@ LL | x_isize > x_usize; help: you can convert a `usize` to an `isize` and panic if the converted value doesn't fit | LL | x_isize > x_usize.try_into().unwrap(); - | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error: aborting due to 132 previous errors diff --git a/src/test/ui/numeric/numeric-cast-no-fix.stderr b/src/test/ui/numeric/numeric-cast-no-fix.stderr index 4510ce10b3..e4843206de 100644 --- a/src/test/ui/numeric/numeric-cast-no-fix.stderr +++ b/src/test/ui/numeric/numeric-cast-no-fix.stderr @@ -47,7 +47,7 @@ LL | x_u8 > -1_isize; help: you can convert `x_u8` from `u8` to `isize`, matching the type of `-1_isize` | LL | isize::from(x_u8) > -1_isize; - | ~~~~~~~~~~~~~~~~~ + | ++++++++++++ + error[E0308]: mismatched types --> $DIR/numeric-cast-no-fix.rs:23:15 @@ -74,7 +74,7 @@ LL | x_u64 > -1_i128; help: you can convert `x_u64` from `u64` to `i128`, matching the type of `-1_i128` | LL | i128::from(x_u64) > -1_i128; - | ~~~~~~~~~~~~~~~~~ + | +++++++++++ + error[E0308]: mismatched types --> $DIR/numeric-cast-no-fix.rs:29:13 @@ -85,7 +85,7 @@ LL | x_u32 > -1_i128; help: you can convert `x_u32` from `u32` to `i128`, matching the type of `-1_i128` | LL | i128::from(x_u32) > -1_i128; - | ~~~~~~~~~~~~~~~~~ + | +++++++++++ + error[E0308]: mismatched types --> $DIR/numeric-cast-no-fix.rs:31:13 @@ -96,7 +96,7 @@ LL | x_u16 > -1_i128; help: you can convert `x_u16` from `u16` to `i128`, matching the type of `-1_i128` | LL | i128::from(x_u16) > -1_i128; - | ~~~~~~~~~~~~~~~~~ + | +++++++++++ + error[E0308]: mismatched types --> $DIR/numeric-cast-no-fix.rs:33:12 @@ -107,7 +107,7 @@ LL | x_u8 > -1_i128; help: you can convert `x_u8` from `u8` to `i128`, matching the type of `-1_i128` | LL | i128::from(x_u8) > -1_i128; - | ~~~~~~~~~~~~~~~~ + | +++++++++++ + error[E0308]: mismatched types --> $DIR/numeric-cast-no-fix.rs:36:15 @@ -142,7 +142,7 @@ LL | x_u32 > -1_i64; help: you can convert `x_u32` from `u32` to `i64`, matching the type of `-1_i64` | LL | i64::from(x_u32) > -1_i64; - | ~~~~~~~~~~~~~~~~ + | ++++++++++ + error[E0308]: mismatched types --> $DIR/numeric-cast-no-fix.rs:44:13 @@ -153,7 +153,7 @@ LL | x_u16 > -1_i64; help: you can convert `x_u16` from `u16` to `i64`, matching the type of `-1_i64` | LL | i64::from(x_u16) > -1_i64; - | ~~~~~~~~~~~~~~~~ + | ++++++++++ + error[E0308]: mismatched types --> $DIR/numeric-cast-no-fix.rs:46:12 @@ -164,7 +164,7 @@ LL | x_u8 > -1_i64; help: you can convert `x_u8` from `u8` to `i64`, matching the type of `-1_i64` | LL | i64::from(x_u8) > -1_i64; - | ~~~~~~~~~~~~~~~ + | ++++++++++ + error[E0308]: mismatched types --> $DIR/numeric-cast-no-fix.rs:49:15 @@ -207,7 +207,7 @@ LL | x_u16 > -1_i32; help: you can convert `x_u16` from `u16` to `i32`, matching the type of `-1_i32` | LL | i32::from(x_u16) > -1_i32; - | ~~~~~~~~~~~~~~~~ + | ++++++++++ + error[E0308]: mismatched types --> $DIR/numeric-cast-no-fix.rs:59:12 @@ -218,7 +218,7 @@ LL | x_u8 > -1_i32; help: you can convert `x_u8` from `u8` to `i32`, matching the type of `-1_i32` | LL | i32::from(x_u8) > -1_i32; - | ~~~~~~~~~~~~~~~ + | ++++++++++ + error[E0308]: mismatched types --> $DIR/numeric-cast-no-fix.rs:62:15 @@ -269,7 +269,7 @@ LL | x_u8 > -1_i16; help: you can convert `x_u8` from `u8` to `i16`, matching the type of `-1_i16` | LL | i16::from(x_u8) > -1_i16; - | ~~~~~~~~~~~~~~~ + | ++++++++++ + error[E0308]: mismatched types --> $DIR/numeric-cast-no-fix.rs:75:15 diff --git a/src/test/ui/numeric/numeric-cast.stderr b/src/test/ui/numeric/numeric-cast.stderr index 8bc617be57..3e2bc5bc82 100644 --- a/src/test/ui/numeric/numeric-cast.stderr +++ b/src/test/ui/numeric/numeric-cast.stderr @@ -7,7 +7,7 @@ LL | foo::(x_u64); help: you can convert a `u64` to a `usize` and panic if the converted value doesn't fit | LL | foo::(x_u64.try_into().unwrap()); - | ~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:25:18 @@ -18,25 +18,29 @@ LL | foo::(x_u32); help: you can convert a `u32` to a `usize` and panic if the converted value doesn't fit | LL | foo::(x_u32.try_into().unwrap()); - | ~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:27:18 | LL | foo::(x_u16); - | ^^^^^ - | | - | expected `usize`, found `u16` - | help: you can convert a `u16` to a `usize`: `x_u16.into()` + | ^^^^^ expected `usize`, found `u16` + | +help: you can convert a `u16` to a `usize` + | +LL | foo::(x_u16.into()); + | +++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:29:18 | LL | foo::(x_u8); - | ^^^^ - | | - | expected `usize`, found `u8` - | help: you can convert a `u8` to a `usize`: `x_u8.into()` + | ^^^^ expected `usize`, found `u8` + | +help: you can convert a `u8` to a `usize` + | +LL | foo::(x_u8.into()); + | +++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:31:18 @@ -47,7 +51,7 @@ LL | foo::(x_isize); help: you can convert an `isize` to a `usize` and panic if the converted value doesn't fit | LL | foo::(x_isize.try_into().unwrap()); - | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:33:18 @@ -58,7 +62,7 @@ LL | foo::(x_i64); help: you can convert an `i64` to a `usize` and panic if the converted value doesn't fit | LL | foo::(x_i64.try_into().unwrap()); - | ~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:35:18 @@ -69,7 +73,7 @@ LL | foo::(x_i32); help: you can convert an `i32` to a `usize` and panic if the converted value doesn't fit | LL | foo::(x_i32.try_into().unwrap()); - | ~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:37:18 @@ -80,7 +84,7 @@ LL | foo::(x_i16); help: you can convert an `i16` to a `usize` and panic if the converted value doesn't fit | LL | foo::(x_i16.try_into().unwrap()); - | ~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:39:18 @@ -91,7 +95,7 @@ LL | foo::(x_i8); help: you can convert an `i8` to a `usize` and panic if the converted value doesn't fit | LL | foo::(x_i8.try_into().unwrap()); - | ~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:44:18 @@ -102,7 +106,7 @@ LL | foo::(x_usize); help: you can convert a `usize` to an `isize` and panic if the converted value doesn't fit | LL | foo::(x_usize.try_into().unwrap()); - | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:46:18 @@ -113,7 +117,7 @@ LL | foo::(x_u64); help: you can convert a `u64` to an `isize` and panic if the converted value doesn't fit | LL | foo::(x_u64.try_into().unwrap()); - | ~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:48:18 @@ -124,7 +128,7 @@ LL | foo::(x_u32); help: you can convert a `u32` to an `isize` and panic if the converted value doesn't fit | LL | foo::(x_u32.try_into().unwrap()); - | ~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:50:18 @@ -135,16 +139,18 @@ LL | foo::(x_u16); help: you can convert a `u16` to an `isize` and panic if the converted value doesn't fit | LL | foo::(x_u16.try_into().unwrap()); - | ~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:52:18 | LL | foo::(x_u8); - | ^^^^ - | | - | expected `isize`, found `u8` - | help: you can convert a `u8` to an `isize`: `x_u8.into()` + | ^^^^ expected `isize`, found `u8` + | +help: you can convert a `u8` to an `isize` + | +LL | foo::(x_u8.into()); + | +++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:55:18 @@ -155,7 +161,7 @@ LL | foo::(x_i64); help: you can convert an `i64` to an `isize` and panic if the converted value doesn't fit | LL | foo::(x_i64.try_into().unwrap()); - | ~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:57:18 @@ -166,25 +172,29 @@ LL | foo::(x_i32); help: you can convert an `i32` to an `isize` and panic if the converted value doesn't fit | LL | foo::(x_i32.try_into().unwrap()); - | ~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:59:18 | LL | foo::(x_i16); - | ^^^^^ - | | - | expected `isize`, found `i16` - | help: you can convert an `i16` to an `isize`: `x_i16.into()` + | ^^^^^ expected `isize`, found `i16` + | +help: you can convert an `i16` to an `isize` + | +LL | foo::(x_i16.into()); + | +++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:61:18 | LL | foo::(x_i8); - | ^^^^ - | | - | expected `isize`, found `i8` - | help: you can convert an `i8` to an `isize`: `x_i8.into()` + | ^^^^ expected `isize`, found `i8` + | +help: you can convert an `i8` to an `isize` + | +LL | foo::(x_i8.into()); + | +++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:66:16 @@ -195,34 +205,40 @@ LL | foo::(x_usize); help: you can convert a `usize` to a `u64` and panic if the converted value doesn't fit | LL | foo::(x_usize.try_into().unwrap()); - | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:69:16 | LL | foo::(x_u32); - | ^^^^^ - | | - | expected `u64`, found `u32` - | help: you can convert a `u32` to a `u64`: `x_u32.into()` + | ^^^^^ expected `u64`, found `u32` + | +help: you can convert a `u32` to a `u64` + | +LL | foo::(x_u32.into()); + | +++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:71:16 | LL | foo::(x_u16); - | ^^^^^ - | | - | expected `u64`, found `u16` - | help: you can convert a `u16` to a `u64`: `x_u16.into()` + | ^^^^^ expected `u64`, found `u16` + | +help: you can convert a `u16` to a `u64` + | +LL | foo::(x_u16.into()); + | +++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:73:16 | LL | foo::(x_u8); - | ^^^^ - | | - | expected `u64`, found `u8` - | help: you can convert a `u8` to a `u64`: `x_u8.into()` + | ^^^^ expected `u64`, found `u8` + | +help: you can convert a `u8` to a `u64` + | +LL | foo::(x_u8.into()); + | +++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:75:16 @@ -233,7 +249,7 @@ LL | foo::(x_isize); help: you can convert an `isize` to a `u64` and panic if the converted value doesn't fit | LL | foo::(x_isize.try_into().unwrap()); - | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:77:16 @@ -244,7 +260,7 @@ LL | foo::(x_i64); help: you can convert an `i64` to a `u64` and panic if the converted value doesn't fit | LL | foo::(x_i64.try_into().unwrap()); - | ~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:79:16 @@ -255,7 +271,7 @@ LL | foo::(x_i32); help: you can convert an `i32` to a `u64` and panic if the converted value doesn't fit | LL | foo::(x_i32.try_into().unwrap()); - | ~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:81:16 @@ -266,7 +282,7 @@ LL | foo::(x_i16); help: you can convert an `i16` to a `u64` and panic if the converted value doesn't fit | LL | foo::(x_i16.try_into().unwrap()); - | ~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:83:16 @@ -277,7 +293,7 @@ LL | foo::(x_i8); help: you can convert an `i8` to a `u64` and panic if the converted value doesn't fit | LL | foo::(x_i8.try_into().unwrap()); - | ~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:88:16 @@ -288,7 +304,7 @@ LL | foo::(x_usize); help: you can convert a `usize` to an `i64` and panic if the converted value doesn't fit | LL | foo::(x_usize.try_into().unwrap()); - | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:90:16 @@ -299,34 +315,40 @@ LL | foo::(x_u64); help: you can convert a `u64` to an `i64` and panic if the converted value doesn't fit | LL | foo::(x_u64.try_into().unwrap()); - | ~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:92:16 | LL | foo::(x_u32); - | ^^^^^ - | | - | expected `i64`, found `u32` - | help: you can convert a `u32` to an `i64`: `x_u32.into()` + | ^^^^^ expected `i64`, found `u32` + | +help: you can convert a `u32` to an `i64` + | +LL | foo::(x_u32.into()); + | +++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:94:16 | LL | foo::(x_u16); - | ^^^^^ - | | - | expected `i64`, found `u16` - | help: you can convert a `u16` to an `i64`: `x_u16.into()` + | ^^^^^ expected `i64`, found `u16` + | +help: you can convert a `u16` to an `i64` + | +LL | foo::(x_u16.into()); + | +++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:96:16 | LL | foo::(x_u8); - | ^^^^ - | | - | expected `i64`, found `u8` - | help: you can convert a `u8` to an `i64`: `x_u8.into()` + | ^^^^ expected `i64`, found `u8` + | +help: you can convert a `u8` to an `i64` + | +LL | foo::(x_u8.into()); + | +++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:98:16 @@ -337,34 +359,40 @@ LL | foo::(x_isize); help: you can convert an `isize` to an `i64` and panic if the converted value doesn't fit | LL | foo::(x_isize.try_into().unwrap()); - | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:101:16 | LL | foo::(x_i32); - | ^^^^^ - | | - | expected `i64`, found `i32` - | help: you can convert an `i32` to an `i64`: `x_i32.into()` + | ^^^^^ expected `i64`, found `i32` + | +help: you can convert an `i32` to an `i64` + | +LL | foo::(x_i32.into()); + | +++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:103:16 | LL | foo::(x_i16); - | ^^^^^ - | | - | expected `i64`, found `i16` - | help: you can convert an `i16` to an `i64`: `x_i16.into()` + | ^^^^^ expected `i64`, found `i16` + | +help: you can convert an `i16` to an `i64` + | +LL | foo::(x_i16.into()); + | +++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:105:16 | LL | foo::(x_i8); - | ^^^^ - | | - | expected `i64`, found `i8` - | help: you can convert an `i8` to an `i64`: `x_i8.into()` + | ^^^^ expected `i64`, found `i8` + | +help: you can convert an `i8` to an `i64` + | +LL | foo::(x_i8.into()); + | +++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:110:16 @@ -375,7 +403,7 @@ LL | foo::(x_usize); help: you can convert a `usize` to a `u32` and panic if the converted value doesn't fit | LL | foo::(x_usize.try_into().unwrap()); - | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:112:16 @@ -386,25 +414,29 @@ LL | foo::(x_u64); help: you can convert a `u64` to a `u32` and panic if the converted value doesn't fit | LL | foo::(x_u64.try_into().unwrap()); - | ~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:115:16 | LL | foo::(x_u16); - | ^^^^^ - | | - | expected `u32`, found `u16` - | help: you can convert a `u16` to a `u32`: `x_u16.into()` + | ^^^^^ expected `u32`, found `u16` + | +help: you can convert a `u16` to a `u32` + | +LL | foo::(x_u16.into()); + | +++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:117:16 | LL | foo::(x_u8); - | ^^^^ - | | - | expected `u32`, found `u8` - | help: you can convert a `u8` to a `u32`: `x_u8.into()` + | ^^^^ expected `u32`, found `u8` + | +help: you can convert a `u8` to a `u32` + | +LL | foo::(x_u8.into()); + | +++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:119:16 @@ -415,7 +447,7 @@ LL | foo::(x_isize); help: you can convert an `isize` to a `u32` and panic if the converted value doesn't fit | LL | foo::(x_isize.try_into().unwrap()); - | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:121:16 @@ -426,7 +458,7 @@ LL | foo::(x_i64); help: you can convert an `i64` to a `u32` and panic if the converted value doesn't fit | LL | foo::(x_i64.try_into().unwrap()); - | ~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:123:16 @@ -437,7 +469,7 @@ LL | foo::(x_i32); help: you can convert an `i32` to a `u32` and panic if the converted value doesn't fit | LL | foo::(x_i32.try_into().unwrap()); - | ~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:125:16 @@ -448,7 +480,7 @@ LL | foo::(x_i16); help: you can convert an `i16` to a `u32` and panic if the converted value doesn't fit | LL | foo::(x_i16.try_into().unwrap()); - | ~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:127:16 @@ -459,7 +491,7 @@ LL | foo::(x_i8); help: you can convert an `i8` to a `u32` and panic if the converted value doesn't fit | LL | foo::(x_i8.try_into().unwrap()); - | ~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:132:16 @@ -470,7 +502,7 @@ LL | foo::(x_usize); help: you can convert a `usize` to an `i32` and panic if the converted value doesn't fit | LL | foo::(x_usize.try_into().unwrap()); - | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:134:16 @@ -481,7 +513,7 @@ LL | foo::(x_u64); help: you can convert a `u64` to an `i32` and panic if the converted value doesn't fit | LL | foo::(x_u64.try_into().unwrap()); - | ~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:136:16 @@ -492,25 +524,29 @@ LL | foo::(x_u32); help: you can convert a `u32` to an `i32` and panic if the converted value doesn't fit | LL | foo::(x_u32.try_into().unwrap()); - | ~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:138:16 | LL | foo::(x_u16); - | ^^^^^ - | | - | expected `i32`, found `u16` - | help: you can convert a `u16` to an `i32`: `x_u16.into()` + | ^^^^^ expected `i32`, found `u16` + | +help: you can convert a `u16` to an `i32` + | +LL | foo::(x_u16.into()); + | +++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:140:16 | LL | foo::(x_u8); - | ^^^^ - | | - | expected `i32`, found `u8` - | help: you can convert a `u8` to an `i32`: `x_u8.into()` + | ^^^^ expected `i32`, found `u8` + | +help: you can convert a `u8` to an `i32` + | +LL | foo::(x_u8.into()); + | +++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:142:16 @@ -521,7 +557,7 @@ LL | foo::(x_isize); help: you can convert an `isize` to an `i32` and panic if the converted value doesn't fit | LL | foo::(x_isize.try_into().unwrap()); - | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:144:16 @@ -532,25 +568,29 @@ LL | foo::(x_i64); help: you can convert an `i64` to an `i32` and panic if the converted value doesn't fit | LL | foo::(x_i64.try_into().unwrap()); - | ~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:147:16 | LL | foo::(x_i16); - | ^^^^^ - | | - | expected `i32`, found `i16` - | help: you can convert an `i16` to an `i32`: `x_i16.into()` + | ^^^^^ expected `i32`, found `i16` + | +help: you can convert an `i16` to an `i32` + | +LL | foo::(x_i16.into()); + | +++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:149:16 | LL | foo::(x_i8); - | ^^^^ - | | - | expected `i32`, found `i8` - | help: you can convert an `i8` to an `i32`: `x_i8.into()` + | ^^^^ expected `i32`, found `i8` + | +help: you can convert an `i8` to an `i32` + | +LL | foo::(x_i8.into()); + | +++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:154:16 @@ -561,7 +601,7 @@ LL | foo::(x_usize); help: you can convert a `usize` to a `u16` and panic if the converted value doesn't fit | LL | foo::(x_usize.try_into().unwrap()); - | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:156:16 @@ -572,7 +612,7 @@ LL | foo::(x_u64); help: you can convert a `u64` to a `u16` and panic if the converted value doesn't fit | LL | foo::(x_u64.try_into().unwrap()); - | ~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:158:16 @@ -583,16 +623,18 @@ LL | foo::(x_u32); help: you can convert a `u32` to a `u16` and panic if the converted value doesn't fit | LL | foo::(x_u32.try_into().unwrap()); - | ~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:161:16 | LL | foo::(x_u8); - | ^^^^ - | | - | expected `u16`, found `u8` - | help: you can convert a `u8` to a `u16`: `x_u8.into()` + | ^^^^ expected `u16`, found `u8` + | +help: you can convert a `u8` to a `u16` + | +LL | foo::(x_u8.into()); + | +++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:163:16 @@ -603,7 +645,7 @@ LL | foo::(x_isize); help: you can convert an `isize` to a `u16` and panic if the converted value doesn't fit | LL | foo::(x_isize.try_into().unwrap()); - | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:165:16 @@ -614,7 +656,7 @@ LL | foo::(x_i64); help: you can convert an `i64` to a `u16` and panic if the converted value doesn't fit | LL | foo::(x_i64.try_into().unwrap()); - | ~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:167:16 @@ -625,7 +667,7 @@ LL | foo::(x_i32); help: you can convert an `i32` to a `u16` and panic if the converted value doesn't fit | LL | foo::(x_i32.try_into().unwrap()); - | ~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:169:16 @@ -636,7 +678,7 @@ LL | foo::(x_i16); help: you can convert an `i16` to a `u16` and panic if the converted value doesn't fit | LL | foo::(x_i16.try_into().unwrap()); - | ~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:171:16 @@ -647,7 +689,7 @@ LL | foo::(x_i8); help: you can convert an `i8` to a `u16` and panic if the converted value doesn't fit | LL | foo::(x_i8.try_into().unwrap()); - | ~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:176:16 @@ -658,7 +700,7 @@ LL | foo::(x_usize); help: you can convert a `usize` to an `i16` and panic if the converted value doesn't fit | LL | foo::(x_usize.try_into().unwrap()); - | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:178:16 @@ -669,7 +711,7 @@ LL | foo::(x_u64); help: you can convert a `u64` to an `i16` and panic if the converted value doesn't fit | LL | foo::(x_u64.try_into().unwrap()); - | ~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:180:16 @@ -680,7 +722,7 @@ LL | foo::(x_u32); help: you can convert a `u32` to an `i16` and panic if the converted value doesn't fit | LL | foo::(x_u32.try_into().unwrap()); - | ~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:182:16 @@ -691,16 +733,18 @@ LL | foo::(x_u16); help: you can convert a `u16` to an `i16` and panic if the converted value doesn't fit | LL | foo::(x_u16.try_into().unwrap()); - | ~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:184:16 | LL | foo::(x_u8); - | ^^^^ - | | - | expected `i16`, found `u8` - | help: you can convert a `u8` to an `i16`: `x_u8.into()` + | ^^^^ expected `i16`, found `u8` + | +help: you can convert a `u8` to an `i16` + | +LL | foo::(x_u8.into()); + | +++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:186:16 @@ -711,7 +755,7 @@ LL | foo::(x_isize); help: you can convert an `isize` to an `i16` and panic if the converted value doesn't fit | LL | foo::(x_isize.try_into().unwrap()); - | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:188:16 @@ -722,7 +766,7 @@ LL | foo::(x_i64); help: you can convert an `i64` to an `i16` and panic if the converted value doesn't fit | LL | foo::(x_i64.try_into().unwrap()); - | ~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:190:16 @@ -733,16 +777,18 @@ LL | foo::(x_i32); help: you can convert an `i32` to an `i16` and panic if the converted value doesn't fit | LL | foo::(x_i32.try_into().unwrap()); - | ~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:193:16 | LL | foo::(x_i8); - | ^^^^ - | | - | expected `i16`, found `i8` - | help: you can convert an `i8` to an `i16`: `x_i8.into()` + | ^^^^ expected `i16`, found `i8` + | +help: you can convert an `i8` to an `i16` + | +LL | foo::(x_i8.into()); + | +++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:198:15 @@ -753,7 +799,7 @@ LL | foo::(x_usize); help: you can convert a `usize` to a `u8` and panic if the converted value doesn't fit | LL | foo::(x_usize.try_into().unwrap()); - | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:200:15 @@ -764,7 +810,7 @@ LL | foo::(x_u64); help: you can convert a `u64` to a `u8` and panic if the converted value doesn't fit | LL | foo::(x_u64.try_into().unwrap()); - | ~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:202:15 @@ -775,7 +821,7 @@ LL | foo::(x_u32); help: you can convert a `u32` to a `u8` and panic if the converted value doesn't fit | LL | foo::(x_u32.try_into().unwrap()); - | ~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:204:15 @@ -786,7 +832,7 @@ LL | foo::(x_u16); help: you can convert a `u16` to a `u8` and panic if the converted value doesn't fit | LL | foo::(x_u16.try_into().unwrap()); - | ~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:207:15 @@ -797,7 +843,7 @@ LL | foo::(x_isize); help: you can convert an `isize` to a `u8` and panic if the converted value doesn't fit | LL | foo::(x_isize.try_into().unwrap()); - | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:209:15 @@ -808,7 +854,7 @@ LL | foo::(x_i64); help: you can convert an `i64` to a `u8` and panic if the converted value doesn't fit | LL | foo::(x_i64.try_into().unwrap()); - | ~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:211:15 @@ -819,7 +865,7 @@ LL | foo::(x_i32); help: you can convert an `i32` to a `u8` and panic if the converted value doesn't fit | LL | foo::(x_i32.try_into().unwrap()); - | ~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:213:15 @@ -830,7 +876,7 @@ LL | foo::(x_i16); help: you can convert an `i16` to a `u8` and panic if the converted value doesn't fit | LL | foo::(x_i16.try_into().unwrap()); - | ~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:215:15 @@ -841,7 +887,7 @@ LL | foo::(x_i8); help: you can convert an `i8` to a `u8` and panic if the converted value doesn't fit | LL | foo::(x_i8.try_into().unwrap()); - | ~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:220:15 @@ -852,7 +898,7 @@ LL | foo::(x_usize); help: you can convert a `usize` to an `i8` and panic if the converted value doesn't fit | LL | foo::(x_usize.try_into().unwrap()); - | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:222:15 @@ -863,7 +909,7 @@ LL | foo::(x_u64); help: you can convert a `u64` to an `i8` and panic if the converted value doesn't fit | LL | foo::(x_u64.try_into().unwrap()); - | ~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:224:15 @@ -874,7 +920,7 @@ LL | foo::(x_u32); help: you can convert a `u32` to an `i8` and panic if the converted value doesn't fit | LL | foo::(x_u32.try_into().unwrap()); - | ~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:226:15 @@ -885,7 +931,7 @@ LL | foo::(x_u16); help: you can convert a `u16` to an `i8` and panic if the converted value doesn't fit | LL | foo::(x_u16.try_into().unwrap()); - | ~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:228:15 @@ -896,7 +942,7 @@ LL | foo::(x_u8); help: you can convert a `u8` to an `i8` and panic if the converted value doesn't fit | LL | foo::(x_u8.try_into().unwrap()); - | ~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:230:15 @@ -907,7 +953,7 @@ LL | foo::(x_isize); help: you can convert an `isize` to an `i8` and panic if the converted value doesn't fit | LL | foo::(x_isize.try_into().unwrap()); - | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:232:15 @@ -918,7 +964,7 @@ LL | foo::(x_i64); help: you can convert an `i64` to an `i8` and panic if the converted value doesn't fit | LL | foo::(x_i64.try_into().unwrap()); - | ~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:234:15 @@ -929,7 +975,7 @@ LL | foo::(x_i32); help: you can convert an `i32` to an `i8` and panic if the converted value doesn't fit | LL | foo::(x_i32.try_into().unwrap()); - | ~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:236:15 @@ -940,7 +986,7 @@ LL | foo::(x_i16); help: you can convert an `i16` to an `i8` and panic if the converted value doesn't fit | LL | foo::(x_i16.try_into().unwrap()); - | ~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:242:16 @@ -951,7 +997,7 @@ LL | foo::(x_usize); help: you can cast a `usize` to an `f64`, producing the floating point representation of the integer, | rounded if necessary LL | foo::(x_usize as f64); - | ~~~~~~~~~~~~~~ + | ++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:244:16 @@ -962,7 +1008,7 @@ LL | foo::(x_u64); help: you can cast a `u64` to an `f64`, producing the floating point representation of the integer, | rounded if necessary LL | foo::(x_u64 as f64); - | ~~~~~~~~~~~~ + | ++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:246:16 @@ -973,7 +1019,7 @@ LL | foo::(x_u32); help: you can convert a `u32` to an `f64`, producing the floating point representation of the integer | LL | foo::(x_u32.into()); - | ~~~~~~~~~~~~ + | +++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:248:16 @@ -984,7 +1030,7 @@ LL | foo::(x_u16); help: you can convert a `u16` to an `f64`, producing the floating point representation of the integer | LL | foo::(x_u16.into()); - | ~~~~~~~~~~~~ + | +++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:250:16 @@ -995,7 +1041,7 @@ LL | foo::(x_u8); help: you can convert a `u8` to an `f64`, producing the floating point representation of the integer | LL | foo::(x_u8.into()); - | ~~~~~~~~~~~ + | +++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:252:16 @@ -1006,7 +1052,7 @@ LL | foo::(x_isize); help: you can convert an `isize` to an `f64`, producing the floating point representation of the integer, rounded if necessary | LL | foo::(x_isize as f64); - | ~~~~~~~~~~~~~~ + | ++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:254:16 @@ -1017,7 +1063,7 @@ LL | foo::(x_i64); help: you can convert an `i64` to an `f64`, producing the floating point representation of the integer, rounded if necessary | LL | foo::(x_i64 as f64); - | ~~~~~~~~~~~~ + | ++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:256:16 @@ -1028,7 +1074,7 @@ LL | foo::(x_i32); help: you can convert an `i32` to an `f64`, producing the floating point representation of the integer | LL | foo::(x_i32.into()); - | ~~~~~~~~~~~~ + | +++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:258:16 @@ -1039,7 +1085,7 @@ LL | foo::(x_i16); help: you can convert an `i16` to an `f64`, producing the floating point representation of the integer | LL | foo::(x_i16.into()); - | ~~~~~~~~~~~~ + | +++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:260:16 @@ -1050,16 +1096,18 @@ LL | foo::(x_i8); help: you can convert an `i8` to an `f64`, producing the floating point representation of the integer | LL | foo::(x_i8.into()); - | ~~~~~~~~~~~ + | +++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:263:16 | LL | foo::(x_f32); - | ^^^^^ - | | - | expected `f64`, found `f32` - | help: you can convert an `f32` to an `f64`: `x_f32.into()` + | ^^^^^ expected `f64`, found `f32` + | +help: you can convert an `f32` to an `f64` + | +LL | foo::(x_f32.into()); + | +++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:266:16 @@ -1070,7 +1118,7 @@ LL | foo::(x_usize); help: you can cast a `usize` to an `f32`, producing the floating point representation of the integer, | rounded if necessary LL | foo::(x_usize as f32); - | ~~~~~~~~~~~~~~ + | ++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:268:16 @@ -1081,7 +1129,7 @@ LL | foo::(x_u64); help: you can cast a `u64` to an `f32`, producing the floating point representation of the integer, | rounded if necessary LL | foo::(x_u64 as f32); - | ~~~~~~~~~~~~ + | ++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:270:16 @@ -1092,7 +1140,7 @@ LL | foo::(x_u32); help: you can cast a `u32` to an `f32`, producing the floating point representation of the integer, | rounded if necessary LL | foo::(x_u32 as f32); - | ~~~~~~~~~~~~ + | ++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:272:16 @@ -1103,7 +1151,7 @@ LL | foo::(x_u16); help: you can convert a `u16` to an `f32`, producing the floating point representation of the integer | LL | foo::(x_u16.into()); - | ~~~~~~~~~~~~ + | +++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:274:16 @@ -1114,7 +1162,7 @@ LL | foo::(x_u8); help: you can convert a `u8` to an `f32`, producing the floating point representation of the integer | LL | foo::(x_u8.into()); - | ~~~~~~~~~~~ + | +++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:276:16 @@ -1125,7 +1173,7 @@ LL | foo::(x_isize); help: you can convert an `isize` to an `f32`, producing the floating point representation of the integer, rounded if necessary | LL | foo::(x_isize as f32); - | ~~~~~~~~~~~~~~ + | ++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:278:16 @@ -1136,7 +1184,7 @@ LL | foo::(x_i64); help: you can convert an `i64` to an `f32`, producing the floating point representation of the integer, rounded if necessary | LL | foo::(x_i64 as f32); - | ~~~~~~~~~~~~ + | ++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:280:16 @@ -1147,7 +1195,7 @@ LL | foo::(x_i32); help: you can convert an `i32` to an `f32`, producing the floating point representation of the integer, rounded if necessary | LL | foo::(x_i32 as f32); - | ~~~~~~~~~~~~ + | ++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:282:16 @@ -1158,7 +1206,7 @@ LL | foo::(x_i16); help: you can convert an `i16` to an `f32`, producing the floating point representation of the integer | LL | foo::(x_i16.into()); - | ~~~~~~~~~~~~ + | +++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:284:16 @@ -1169,25 +1217,29 @@ LL | foo::(x_i8); help: you can convert an `i8` to an `f32`, producing the floating point representation of the integer | LL | foo::(x_i8.into()); - | ~~~~~~~~~~~ + | +++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:289:16 | LL | foo::(x_u8 as u16); - | ^^^^^^^^^^^ - | | - | expected `u32`, found `u16` - | help: you can convert a `u16` to a `u32`: `(x_u8 as u16).into()` + | ^^^^^^^^^^^ expected `u32`, found `u16` + | +help: you can convert a `u16` to a `u32` + | +LL | foo::((x_u8 as u16).into()); + | + ++++++++ error[E0308]: mismatched types --> $DIR/numeric-cast.rs:291:16 | LL | foo::(-x_i8); - | ^^^^^ - | | - | expected `i32`, found `i8` - | help: you can convert an `i8` to an `i32`: `(-x_i8).into()` + | ^^^^^ expected `i32`, found `i8` + | +help: you can convert an `i8` to an `i32` + | +LL | foo::((-x_i8).into()); + | + ++++++++ error: aborting due to 113 previous errors diff --git a/src/test/ui/numeric/numeric-fields.stderr b/src/test/ui/numeric/numeric-fields.stderr index 13b6cfae4e..668405ed63 100644 --- a/src/test/ui/numeric/numeric-fields.stderr +++ b/src/test/ui/numeric/numeric-fields.stderr @@ -5,15 +5,21 @@ LL | struct S(u8, u16); | - `S` defined here ... LL | let s = S{0b1: 10, 0: 11}; - | - ^^^ field does not exist - | | - | help: `S` is a tuple struct, use the appropriate syntax: `S(/* fields */)` + | ^^^ field does not exist + | +help: `S` is a tuple struct, use the appropriate syntax + | +LL | let s = S(/* fields */); + | ~~~~~~~~~~~~~~~ error[E0026]: struct `S` does not have a field named `0x1` --> $DIR/numeric-fields.rs:7:17 | LL | S{0: a, 0x1: b, ..} => {} - | ^^^ struct `S` does not have this field + | ^^^ + | | + | struct `S` does not have this field + | help: `S` has a field named `1` error: aborting due to 2 previous errors diff --git a/src/test/ui/numeric/numeric-suffix.stderr b/src/test/ui/numeric/numeric-suffix.stderr index d3f02214e3..b829946e52 100644 --- a/src/test/ui/numeric/numeric-suffix.stderr +++ b/src/test/ui/numeric/numeric-suffix.stderr @@ -7,7 +7,7 @@ LL | foo::(42_u64); help: change the type of the numeric literal from `u64` to `usize` | LL | foo::(42_usize); - | ~~~~~~~~ + | ~~~~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:9:18 @@ -18,7 +18,7 @@ LL | foo::(42_u32); help: change the type of the numeric literal from `u32` to `usize` | LL | foo::(42_usize); - | ~~~~~~~~ + | ~~~~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:11:18 @@ -29,7 +29,7 @@ LL | foo::(42_u16); help: change the type of the numeric literal from `u16` to `usize` | LL | foo::(42_usize); - | ~~~~~~~~ + | ~~~~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:13:18 @@ -40,7 +40,7 @@ LL | foo::(42_u8); help: change the type of the numeric literal from `u8` to `usize` | LL | foo::(42_usize); - | ~~~~~~~~ + | ~~~~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:15:18 @@ -51,7 +51,7 @@ LL | foo::(42_isize); help: change the type of the numeric literal from `isize` to `usize` | LL | foo::(42_usize); - | ~~~~~~~~ + | ~~~~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:17:18 @@ -62,7 +62,7 @@ LL | foo::(42_i64); help: change the type of the numeric literal from `i64` to `usize` | LL | foo::(42_usize); - | ~~~~~~~~ + | ~~~~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:19:18 @@ -73,7 +73,7 @@ LL | foo::(42_i32); help: change the type of the numeric literal from `i32` to `usize` | LL | foo::(42_usize); - | ~~~~~~~~ + | ~~~~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:21:18 @@ -84,7 +84,7 @@ LL | foo::(42_i16); help: change the type of the numeric literal from `i16` to `usize` | LL | foo::(42_usize); - | ~~~~~~~~ + | ~~~~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:23:18 @@ -95,7 +95,7 @@ LL | foo::(42_i8); help: change the type of the numeric literal from `i8` to `usize` | LL | foo::(42_usize); - | ~~~~~~~~ + | ~~~~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:25:18 @@ -106,7 +106,7 @@ LL | foo::(42.0_f64); help: change the type of the numeric literal from `f64` to `usize` | LL | foo::(42usize); - | ~~~~~~~ + | ~~~~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:27:18 @@ -117,7 +117,7 @@ LL | foo::(42.0_f32); help: change the type of the numeric literal from `f32` to `usize` | LL | foo::(42usize); - | ~~~~~~~ + | ~~~~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:30:18 @@ -128,7 +128,7 @@ LL | foo::(42_usize); help: change the type of the numeric literal from `usize` to `isize` | LL | foo::(42_isize); - | ~~~~~~~~ + | ~~~~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:32:18 @@ -139,7 +139,7 @@ LL | foo::(42_u64); help: change the type of the numeric literal from `u64` to `isize` | LL | foo::(42_isize); - | ~~~~~~~~ + | ~~~~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:34:18 @@ -150,7 +150,7 @@ LL | foo::(42_u32); help: change the type of the numeric literal from `u32` to `isize` | LL | foo::(42_isize); - | ~~~~~~~~ + | ~~~~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:36:18 @@ -161,7 +161,7 @@ LL | foo::(42_u16); help: change the type of the numeric literal from `u16` to `isize` | LL | foo::(42_isize); - | ~~~~~~~~ + | ~~~~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:38:18 @@ -172,7 +172,7 @@ LL | foo::(42_u8); help: change the type of the numeric literal from `u8` to `isize` | LL | foo::(42_isize); - | ~~~~~~~~ + | ~~~~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:41:18 @@ -183,7 +183,7 @@ LL | foo::(42_i64); help: change the type of the numeric literal from `i64` to `isize` | LL | foo::(42_isize); - | ~~~~~~~~ + | ~~~~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:43:18 @@ -194,7 +194,7 @@ LL | foo::(42_i32); help: change the type of the numeric literal from `i32` to `isize` | LL | foo::(42_isize); - | ~~~~~~~~ + | ~~~~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:45:18 @@ -205,7 +205,7 @@ LL | foo::(42_i16); help: change the type of the numeric literal from `i16` to `isize` | LL | foo::(42_isize); - | ~~~~~~~~ + | ~~~~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:47:18 @@ -216,7 +216,7 @@ LL | foo::(42_i8); help: change the type of the numeric literal from `i8` to `isize` | LL | foo::(42_isize); - | ~~~~~~~~ + | ~~~~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:49:18 @@ -227,7 +227,7 @@ LL | foo::(42.0_f64); help: change the type of the numeric literal from `f64` to `isize` | LL | foo::(42isize); - | ~~~~~~~ + | ~~~~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:51:18 @@ -238,7 +238,7 @@ LL | foo::(42.0_f32); help: change the type of the numeric literal from `f32` to `isize` | LL | foo::(42isize); - | ~~~~~~~ + | ~~~~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:54:16 @@ -249,7 +249,7 @@ LL | foo::(42_usize); help: change the type of the numeric literal from `usize` to `u64` | LL | foo::(42_u64); - | ~~~~~~ + | ~~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:57:16 @@ -260,7 +260,7 @@ LL | foo::(42_u32); help: change the type of the numeric literal from `u32` to `u64` | LL | foo::(42_u64); - | ~~~~~~ + | ~~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:59:16 @@ -271,7 +271,7 @@ LL | foo::(42_u16); help: change the type of the numeric literal from `u16` to `u64` | LL | foo::(42_u64); - | ~~~~~~ + | ~~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:61:16 @@ -282,7 +282,7 @@ LL | foo::(42_u8); help: change the type of the numeric literal from `u8` to `u64` | LL | foo::(42_u64); - | ~~~~~~ + | ~~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:63:16 @@ -293,7 +293,7 @@ LL | foo::(42_isize); help: change the type of the numeric literal from `isize` to `u64` | LL | foo::(42_u64); - | ~~~~~~ + | ~~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:65:16 @@ -304,7 +304,7 @@ LL | foo::(42_i64); help: change the type of the numeric literal from `i64` to `u64` | LL | foo::(42_u64); - | ~~~~~~ + | ~~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:67:16 @@ -315,7 +315,7 @@ LL | foo::(42_i32); help: change the type of the numeric literal from `i32` to `u64` | LL | foo::(42_u64); - | ~~~~~~ + | ~~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:69:16 @@ -326,7 +326,7 @@ LL | foo::(42_i16); help: change the type of the numeric literal from `i16` to `u64` | LL | foo::(42_u64); - | ~~~~~~ + | ~~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:71:16 @@ -337,7 +337,7 @@ LL | foo::(42_i8); help: change the type of the numeric literal from `i8` to `u64` | LL | foo::(42_u64); - | ~~~~~~ + | ~~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:73:16 @@ -348,7 +348,7 @@ LL | foo::(42.0_f64); help: change the type of the numeric literal from `f64` to `u64` | LL | foo::(42u64); - | ~~~~~ + | ~~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:75:16 @@ -359,7 +359,7 @@ LL | foo::(42.0_f32); help: change the type of the numeric literal from `f32` to `u64` | LL | foo::(42u64); - | ~~~~~ + | ~~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:78:16 @@ -370,7 +370,7 @@ LL | foo::(42_usize); help: change the type of the numeric literal from `usize` to `i64` | LL | foo::(42_i64); - | ~~~~~~ + | ~~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:80:16 @@ -381,7 +381,7 @@ LL | foo::(42_u64); help: change the type of the numeric literal from `u64` to `i64` | LL | foo::(42_i64); - | ~~~~~~ + | ~~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:82:16 @@ -392,7 +392,7 @@ LL | foo::(42_u32); help: change the type of the numeric literal from `u32` to `i64` | LL | foo::(42_i64); - | ~~~~~~ + | ~~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:84:16 @@ -403,7 +403,7 @@ LL | foo::(42_u16); help: change the type of the numeric literal from `u16` to `i64` | LL | foo::(42_i64); - | ~~~~~~ + | ~~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:86:16 @@ -414,7 +414,7 @@ LL | foo::(42_u8); help: change the type of the numeric literal from `u8` to `i64` | LL | foo::(42_i64); - | ~~~~~~ + | ~~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:88:16 @@ -425,7 +425,7 @@ LL | foo::(42_isize); help: change the type of the numeric literal from `isize` to `i64` | LL | foo::(42_i64); - | ~~~~~~ + | ~~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:91:16 @@ -436,7 +436,7 @@ LL | foo::(42_i32); help: change the type of the numeric literal from `i32` to `i64` | LL | foo::(42_i64); - | ~~~~~~ + | ~~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:93:16 @@ -447,7 +447,7 @@ LL | foo::(42_i16); help: change the type of the numeric literal from `i16` to `i64` | LL | foo::(42_i64); - | ~~~~~~ + | ~~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:95:16 @@ -458,7 +458,7 @@ LL | foo::(42_i8); help: change the type of the numeric literal from `i8` to `i64` | LL | foo::(42_i64); - | ~~~~~~ + | ~~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:97:16 @@ -469,7 +469,7 @@ LL | foo::(42.0_f64); help: change the type of the numeric literal from `f64` to `i64` | LL | foo::(42i64); - | ~~~~~ + | ~~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:99:16 @@ -480,7 +480,7 @@ LL | foo::(42.0_f32); help: change the type of the numeric literal from `f32` to `i64` | LL | foo::(42i64); - | ~~~~~ + | ~~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:102:16 @@ -491,7 +491,7 @@ LL | foo::(42_usize); help: change the type of the numeric literal from `usize` to `u32` | LL | foo::(42_u32); - | ~~~~~~ + | ~~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:104:16 @@ -502,7 +502,7 @@ LL | foo::(42_u64); help: change the type of the numeric literal from `u64` to `u32` | LL | foo::(42_u32); - | ~~~~~~ + | ~~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:107:16 @@ -513,7 +513,7 @@ LL | foo::(42_u16); help: change the type of the numeric literal from `u16` to `u32` | LL | foo::(42_u32); - | ~~~~~~ + | ~~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:109:16 @@ -524,7 +524,7 @@ LL | foo::(42_u8); help: change the type of the numeric literal from `u8` to `u32` | LL | foo::(42_u32); - | ~~~~~~ + | ~~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:111:16 @@ -535,7 +535,7 @@ LL | foo::(42_isize); help: change the type of the numeric literal from `isize` to `u32` | LL | foo::(42_u32); - | ~~~~~~ + | ~~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:113:16 @@ -546,7 +546,7 @@ LL | foo::(42_i64); help: change the type of the numeric literal from `i64` to `u32` | LL | foo::(42_u32); - | ~~~~~~ + | ~~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:115:16 @@ -557,7 +557,7 @@ LL | foo::(42_i32); help: change the type of the numeric literal from `i32` to `u32` | LL | foo::(42_u32); - | ~~~~~~ + | ~~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:117:16 @@ -568,7 +568,7 @@ LL | foo::(42_i16); help: change the type of the numeric literal from `i16` to `u32` | LL | foo::(42_u32); - | ~~~~~~ + | ~~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:119:16 @@ -579,7 +579,7 @@ LL | foo::(42_i8); help: change the type of the numeric literal from `i8` to `u32` | LL | foo::(42_u32); - | ~~~~~~ + | ~~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:121:16 @@ -590,7 +590,7 @@ LL | foo::(42.0_f64); help: change the type of the numeric literal from `f64` to `u32` | LL | foo::(42u32); - | ~~~~~ + | ~~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:123:16 @@ -601,7 +601,7 @@ LL | foo::(42.0_f32); help: change the type of the numeric literal from `f32` to `u32` | LL | foo::(42u32); - | ~~~~~ + | ~~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:126:16 @@ -612,7 +612,7 @@ LL | foo::(42_usize); help: change the type of the numeric literal from `usize` to `i32` | LL | foo::(42_i32); - | ~~~~~~ + | ~~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:128:16 @@ -623,7 +623,7 @@ LL | foo::(42_u64); help: change the type of the numeric literal from `u64` to `i32` | LL | foo::(42_i32); - | ~~~~~~ + | ~~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:130:16 @@ -634,7 +634,7 @@ LL | foo::(42_u32); help: change the type of the numeric literal from `u32` to `i32` | LL | foo::(42_i32); - | ~~~~~~ + | ~~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:132:16 @@ -645,7 +645,7 @@ LL | foo::(42_u16); help: change the type of the numeric literal from `u16` to `i32` | LL | foo::(42_i32); - | ~~~~~~ + | ~~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:134:16 @@ -656,7 +656,7 @@ LL | foo::(42_u8); help: change the type of the numeric literal from `u8` to `i32` | LL | foo::(42_i32); - | ~~~~~~ + | ~~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:136:16 @@ -667,7 +667,7 @@ LL | foo::(42_isize); help: change the type of the numeric literal from `isize` to `i32` | LL | foo::(42_i32); - | ~~~~~~ + | ~~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:138:16 @@ -678,7 +678,7 @@ LL | foo::(42_i64); help: change the type of the numeric literal from `i64` to `i32` | LL | foo::(42_i32); - | ~~~~~~ + | ~~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:141:16 @@ -689,7 +689,7 @@ LL | foo::(42_i16); help: change the type of the numeric literal from `i16` to `i32` | LL | foo::(42_i32); - | ~~~~~~ + | ~~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:143:16 @@ -700,7 +700,7 @@ LL | foo::(42_i8); help: change the type of the numeric literal from `i8` to `i32` | LL | foo::(42_i32); - | ~~~~~~ + | ~~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:145:16 @@ -711,7 +711,7 @@ LL | foo::(42.0_f64); help: change the type of the numeric literal from `f64` to `i32` | LL | foo::(42i32); - | ~~~~~ + | ~~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:147:16 @@ -722,7 +722,7 @@ LL | foo::(42.0_f32); help: change the type of the numeric literal from `f32` to `i32` | LL | foo::(42i32); - | ~~~~~ + | ~~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:150:16 @@ -733,7 +733,7 @@ LL | foo::(42_usize); help: change the type of the numeric literal from `usize` to `u16` | LL | foo::(42_u16); - | ~~~~~~ + | ~~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:152:16 @@ -744,7 +744,7 @@ LL | foo::(42_u64); help: change the type of the numeric literal from `u64` to `u16` | LL | foo::(42_u16); - | ~~~~~~ + | ~~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:154:16 @@ -755,7 +755,7 @@ LL | foo::(42_u32); help: change the type of the numeric literal from `u32` to `u16` | LL | foo::(42_u16); - | ~~~~~~ + | ~~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:157:16 @@ -766,7 +766,7 @@ LL | foo::(42_u8); help: change the type of the numeric literal from `u8` to `u16` | LL | foo::(42_u16); - | ~~~~~~ + | ~~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:159:16 @@ -777,7 +777,7 @@ LL | foo::(42_isize); help: change the type of the numeric literal from `isize` to `u16` | LL | foo::(42_u16); - | ~~~~~~ + | ~~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:161:16 @@ -788,7 +788,7 @@ LL | foo::(42_i64); help: change the type of the numeric literal from `i64` to `u16` | LL | foo::(42_u16); - | ~~~~~~ + | ~~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:163:16 @@ -799,7 +799,7 @@ LL | foo::(42_i32); help: change the type of the numeric literal from `i32` to `u16` | LL | foo::(42_u16); - | ~~~~~~ + | ~~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:165:16 @@ -810,7 +810,7 @@ LL | foo::(42_i16); help: change the type of the numeric literal from `i16` to `u16` | LL | foo::(42_u16); - | ~~~~~~ + | ~~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:167:16 @@ -821,7 +821,7 @@ LL | foo::(42_i8); help: change the type of the numeric literal from `i8` to `u16` | LL | foo::(42_u16); - | ~~~~~~ + | ~~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:169:16 @@ -832,7 +832,7 @@ LL | foo::(42.0_f64); help: change the type of the numeric literal from `f64` to `u16` | LL | foo::(42u16); - | ~~~~~ + | ~~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:171:16 @@ -843,7 +843,7 @@ LL | foo::(42.0_f32); help: change the type of the numeric literal from `f32` to `u16` | LL | foo::(42u16); - | ~~~~~ + | ~~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:174:16 @@ -854,7 +854,7 @@ LL | foo::(42_usize); help: change the type of the numeric literal from `usize` to `i16` | LL | foo::(42_i16); - | ~~~~~~ + | ~~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:176:16 @@ -865,7 +865,7 @@ LL | foo::(42_u64); help: change the type of the numeric literal from `u64` to `i16` | LL | foo::(42_i16); - | ~~~~~~ + | ~~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:178:16 @@ -876,7 +876,7 @@ LL | foo::(42_u32); help: change the type of the numeric literal from `u32` to `i16` | LL | foo::(42_i16); - | ~~~~~~ + | ~~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:180:16 @@ -887,7 +887,7 @@ LL | foo::(42_u16); help: change the type of the numeric literal from `u16` to `i16` | LL | foo::(42_i16); - | ~~~~~~ + | ~~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:182:16 @@ -898,7 +898,7 @@ LL | foo::(42_u8); help: change the type of the numeric literal from `u8` to `i16` | LL | foo::(42_i16); - | ~~~~~~ + | ~~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:184:16 @@ -909,7 +909,7 @@ LL | foo::(42_isize); help: change the type of the numeric literal from `isize` to `i16` | LL | foo::(42_i16); - | ~~~~~~ + | ~~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:186:16 @@ -920,7 +920,7 @@ LL | foo::(42_i64); help: change the type of the numeric literal from `i64` to `i16` | LL | foo::(42_i16); - | ~~~~~~ + | ~~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:188:16 @@ -931,7 +931,7 @@ LL | foo::(42_i32); help: change the type of the numeric literal from `i32` to `i16` | LL | foo::(42_i16); - | ~~~~~~ + | ~~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:191:16 @@ -942,7 +942,7 @@ LL | foo::(42_i8); help: change the type of the numeric literal from `i8` to `i16` | LL | foo::(42_i16); - | ~~~~~~ + | ~~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:193:16 @@ -953,7 +953,7 @@ LL | foo::(42.0_f64); help: change the type of the numeric literal from `f64` to `i16` | LL | foo::(42i16); - | ~~~~~ + | ~~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:195:16 @@ -964,7 +964,7 @@ LL | foo::(42.0_f32); help: change the type of the numeric literal from `f32` to `i16` | LL | foo::(42i16); - | ~~~~~ + | ~~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:198:15 @@ -975,7 +975,7 @@ LL | foo::(42_usize); help: change the type of the numeric literal from `usize` to `u8` | LL | foo::(42_u8); - | ~~~~~ + | ~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:200:15 @@ -986,7 +986,7 @@ LL | foo::(42_u64); help: change the type of the numeric literal from `u64` to `u8` | LL | foo::(42_u8); - | ~~~~~ + | ~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:202:15 @@ -997,7 +997,7 @@ LL | foo::(42_u32); help: change the type of the numeric literal from `u32` to `u8` | LL | foo::(42_u8); - | ~~~~~ + | ~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:204:15 @@ -1008,7 +1008,7 @@ LL | foo::(42_u16); help: change the type of the numeric literal from `u16` to `u8` | LL | foo::(42_u8); - | ~~~~~ + | ~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:207:15 @@ -1019,7 +1019,7 @@ LL | foo::(42_isize); help: change the type of the numeric literal from `isize` to `u8` | LL | foo::(42_u8); - | ~~~~~ + | ~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:209:15 @@ -1030,7 +1030,7 @@ LL | foo::(42_i64); help: change the type of the numeric literal from `i64` to `u8` | LL | foo::(42_u8); - | ~~~~~ + | ~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:211:15 @@ -1041,7 +1041,7 @@ LL | foo::(42_i32); help: change the type of the numeric literal from `i32` to `u8` | LL | foo::(42_u8); - | ~~~~~ + | ~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:213:15 @@ -1052,7 +1052,7 @@ LL | foo::(42_i16); help: change the type of the numeric literal from `i16` to `u8` | LL | foo::(42_u8); - | ~~~~~ + | ~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:215:15 @@ -1063,7 +1063,7 @@ LL | foo::(42_i8); help: change the type of the numeric literal from `i8` to `u8` | LL | foo::(42_u8); - | ~~~~~ + | ~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:217:15 @@ -1074,7 +1074,7 @@ LL | foo::(42.0_f64); help: change the type of the numeric literal from `f64` to `u8` | LL | foo::(42u8); - | ~~~~ + | ~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:219:15 @@ -1085,7 +1085,7 @@ LL | foo::(42.0_f32); help: change the type of the numeric literal from `f32` to `u8` | LL | foo::(42u8); - | ~~~~ + | ~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:222:15 @@ -1096,7 +1096,7 @@ LL | foo::(42_usize); help: change the type of the numeric literal from `usize` to `i8` | LL | foo::(42_i8); - | ~~~~~ + | ~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:224:15 @@ -1107,7 +1107,7 @@ LL | foo::(42_u64); help: change the type of the numeric literal from `u64` to `i8` | LL | foo::(42_i8); - | ~~~~~ + | ~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:226:15 @@ -1118,7 +1118,7 @@ LL | foo::(42_u32); help: change the type of the numeric literal from `u32` to `i8` | LL | foo::(42_i8); - | ~~~~~ + | ~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:228:15 @@ -1129,7 +1129,7 @@ LL | foo::(42_u16); help: change the type of the numeric literal from `u16` to `i8` | LL | foo::(42_i8); - | ~~~~~ + | ~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:230:15 @@ -1140,7 +1140,7 @@ LL | foo::(42_u8); help: change the type of the numeric literal from `u8` to `i8` | LL | foo::(42_i8); - | ~~~~~ + | ~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:232:15 @@ -1151,7 +1151,7 @@ LL | foo::(42_isize); help: change the type of the numeric literal from `isize` to `i8` | LL | foo::(42_i8); - | ~~~~~ + | ~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:234:15 @@ -1162,7 +1162,7 @@ LL | foo::(42_i64); help: change the type of the numeric literal from `i64` to `i8` | LL | foo::(42_i8); - | ~~~~~ + | ~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:236:15 @@ -1173,7 +1173,7 @@ LL | foo::(42_i32); help: change the type of the numeric literal from `i32` to `i8` | LL | foo::(42_i8); - | ~~~~~ + | ~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:238:15 @@ -1184,7 +1184,7 @@ LL | foo::(42_i16); help: change the type of the numeric literal from `i16` to `i8` | LL | foo::(42_i8); - | ~~~~~ + | ~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:241:15 @@ -1195,7 +1195,7 @@ LL | foo::(42.0_f64); help: change the type of the numeric literal from `f64` to `i8` | LL | foo::(42i8); - | ~~~~ + | ~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:243:15 @@ -1206,7 +1206,7 @@ LL | foo::(42.0_f32); help: change the type of the numeric literal from `f32` to `i8` | LL | foo::(42i8); - | ~~~~ + | ~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:246:16 @@ -1217,7 +1217,7 @@ LL | foo::(42_usize); help: change the type of the numeric literal from `usize` to `f64` | LL | foo::(42_f64); - | ~~~~~~ + | ~~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:248:16 @@ -1228,7 +1228,7 @@ LL | foo::(42_u64); help: change the type of the numeric literal from `u64` to `f64` | LL | foo::(42_f64); - | ~~~~~~ + | ~~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:250:16 @@ -1239,7 +1239,7 @@ LL | foo::(42_u32); help: you can convert a `u32` to an `f64`, producing the floating point representation of the integer | LL | foo::(42_u32.into()); - | ~~~~~~~~~~~~~ + | +++++++ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:252:16 @@ -1250,7 +1250,7 @@ LL | foo::(42_u16); help: you can convert a `u16` to an `f64`, producing the floating point representation of the integer | LL | foo::(42_u16.into()); - | ~~~~~~~~~~~~~ + | +++++++ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:254:16 @@ -1261,7 +1261,7 @@ LL | foo::(42_u8); help: you can convert a `u8` to an `f64`, producing the floating point representation of the integer | LL | foo::(42_u8.into()); - | ~~~~~~~~~~~~ + | +++++++ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:256:16 @@ -1272,7 +1272,7 @@ LL | foo::(42_isize); help: change the type of the numeric literal from `isize` to `f64` | LL | foo::(42_f64); - | ~~~~~~ + | ~~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:258:16 @@ -1283,7 +1283,7 @@ LL | foo::(42_i64); help: change the type of the numeric literal from `i64` to `f64` | LL | foo::(42_f64); - | ~~~~~~ + | ~~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:260:16 @@ -1294,7 +1294,7 @@ LL | foo::(42_i32); help: you can convert an `i32` to an `f64`, producing the floating point representation of the integer | LL | foo::(42_i32.into()); - | ~~~~~~~~~~~~~ + | +++++++ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:262:16 @@ -1305,7 +1305,7 @@ LL | foo::(42_i16); help: you can convert an `i16` to an `f64`, producing the floating point representation of the integer | LL | foo::(42_i16.into()); - | ~~~~~~~~~~~~~ + | +++++++ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:264:16 @@ -1316,7 +1316,7 @@ LL | foo::(42_i8); help: you can convert an `i8` to an `f64`, producing the floating point representation of the integer | LL | foo::(42_i8.into()); - | ~~~~~~~~~~~~ + | +++++++ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:267:16 @@ -1327,7 +1327,7 @@ LL | foo::(42.0_f32); help: change the type of the numeric literal from `f32` to `f64` | LL | foo::(42.0_f64); - | ~~~~~~~~ + | ~~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:270:16 @@ -1338,7 +1338,7 @@ LL | foo::(42_usize); help: change the type of the numeric literal from `usize` to `f32` | LL | foo::(42_f32); - | ~~~~~~ + | ~~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:272:16 @@ -1349,7 +1349,7 @@ LL | foo::(42_u64); help: change the type of the numeric literal from `u64` to `f32` | LL | foo::(42_f32); - | ~~~~~~ + | ~~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:274:16 @@ -1360,7 +1360,7 @@ LL | foo::(42_u32); help: change the type of the numeric literal from `u32` to `f32` | LL | foo::(42_f32); - | ~~~~~~ + | ~~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:276:16 @@ -1371,7 +1371,7 @@ LL | foo::(42_u16); help: you can convert a `u16` to an `f32`, producing the floating point representation of the integer | LL | foo::(42_u16.into()); - | ~~~~~~~~~~~~~ + | +++++++ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:278:16 @@ -1382,7 +1382,7 @@ LL | foo::(42_u8); help: you can convert a `u8` to an `f32`, producing the floating point representation of the integer | LL | foo::(42_u8.into()); - | ~~~~~~~~~~~~ + | +++++++ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:280:16 @@ -1393,7 +1393,7 @@ LL | foo::(42_isize); help: change the type of the numeric literal from `isize` to `f32` | LL | foo::(42_f32); - | ~~~~~~ + | ~~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:282:16 @@ -1404,7 +1404,7 @@ LL | foo::(42_i64); help: change the type of the numeric literal from `i64` to `f32` | LL | foo::(42_f32); - | ~~~~~~ + | ~~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:284:16 @@ -1415,7 +1415,7 @@ LL | foo::(42_i32); help: change the type of the numeric literal from `i32` to `f32` | LL | foo::(42_f32); - | ~~~~~~ + | ~~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:286:16 @@ -1426,7 +1426,7 @@ LL | foo::(42_i16); help: you can convert an `i16` to an `f32`, producing the floating point representation of the integer | LL | foo::(42_i16.into()); - | ~~~~~~~~~~~~~ + | +++++++ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:288:16 @@ -1437,7 +1437,7 @@ LL | foo::(42_i8); help: you can convert an `i8` to an `f32`, producing the floating point representation of the integer | LL | foo::(42_i8.into()); - | ~~~~~~~~~~~~ + | +++++++ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:290:16 @@ -1448,25 +1448,29 @@ LL | foo::(42.0_f64); help: change the type of the numeric literal from `f64` to `f32` | LL | foo::(42.0_f32); - | ~~~~~~~~ + | ~~~ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:294:16 | LL | foo::(42_u8 as u16); - | ^^^^^^^^^^^^ - | | - | expected `u32`, found `u16` - | help: you can convert a `u16` to a `u32`: `(42_u8 as u16).into()` + | ^^^^^^^^^^^^ expected `u32`, found `u16` + | +help: you can convert a `u16` to a `u32` + | +LL | foo::((42_u8 as u16).into()); + | + ++++++++ error[E0308]: mismatched types --> $DIR/numeric-suffix.rs:296:16 | LL | foo::(-42_i8); - | ^^^^^^ - | | - | expected `i32`, found `i8` - | help: you can convert an `i8` to an `i32`: `(-42_i8).into()` + | ^^^^^^ expected `i32`, found `i8` + | +help: you can convert an `i8` to an `i32` + | +LL | foo::((-42_i8).into()); + | + ++++++++ error: aborting due to 134 previous errors diff --git a/src/test/ui/object-does-not-impl-trait.stderr b/src/test/ui/object-does-not-impl-trait.stderr index bf1641167c..f1dd508a46 100644 --- a/src/test/ui/object-does-not-impl-trait.stderr +++ b/src/test/ui/object-does-not-impl-trait.stderr @@ -2,7 +2,9 @@ error[E0277]: the trait bound `Box: Foo` is not satisfied --> $DIR/object-does-not-impl-trait.rs:6:44 | LL | fn take_object(f: Box) { take_foo(f); } - | ^ the trait `Foo` is not implemented for `Box` + | -------- ^ the trait `Foo` is not implemented for `Box` + | | + | required by a bound introduced by this call | note: required by a bound in `take_foo` --> $DIR/object-does-not-impl-trait.rs:5:15 diff --git a/src/test/ui/object-lifetime/object-lifetime-default-elision.stderr b/src/test/ui/object-lifetime/object-lifetime-default-elision.stderr index 79ded5fc87..5af4c5bdfa 100644 --- a/src/test/ui/object-lifetime/object-lifetime-default-elision.stderr +++ b/src/test/ui/object-lifetime/object-lifetime-default-elision.stderr @@ -4,7 +4,7 @@ error[E0495]: cannot infer an appropriate lifetime for automatic coercion due to LL | ss | ^^ | -note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 54:10... +note: first, the lifetime cannot outlive the lifetime `'a` as defined here... --> $DIR/object-lifetime-default-elision.rs:54:10 | LL | fn load3<'a,'b>(ss: &'a dyn SomeTrait) -> &'b dyn SomeTrait { @@ -14,12 +14,12 @@ note: ...so that reference does not outlive borrowed content | LL | ss | ^^ -note: but, the lifetime must be valid for the lifetime `'b` as defined on the function body at 54:13... +note: but, the lifetime must be valid for the lifetime `'b` as defined here... --> $DIR/object-lifetime-default-elision.rs:54:13 | LL | fn load3<'a,'b>(ss: &'a dyn SomeTrait) -> &'b dyn SomeTrait { | ^^ -note: ...so that the expression is assignable +note: ...so that the types are compatible --> $DIR/object-lifetime-default-elision.rs:71:5 | LL | ss @@ -33,7 +33,7 @@ error[E0495]: cannot infer an appropriate lifetime due to conflicting requiremen LL | ss | ^^ | -note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 54:10... +note: first, the lifetime cannot outlive the lifetime `'a` as defined here... --> $DIR/object-lifetime-default-elision.rs:54:10 | LL | fn load3<'a,'b>(ss: &'a dyn SomeTrait) -> &'b dyn SomeTrait { @@ -43,12 +43,12 @@ note: ...so that the declared lifetime parameter bounds are satisfied | LL | ss | ^^ -note: but, the lifetime must be valid for the lifetime `'b` as defined on the function body at 54:13... +note: but, the lifetime must be valid for the lifetime `'b` as defined here... --> $DIR/object-lifetime-default-elision.rs:54:13 | LL | fn load3<'a,'b>(ss: &'a dyn SomeTrait) -> &'b dyn SomeTrait { | ^^ -note: ...so that the expression is assignable +note: ...so that the types are compatible --> $DIR/object-lifetime-default-elision.rs:71:5 | LL | ss diff --git a/src/test/ui/object-lifetime/object-lifetime-default-from-rptr-box-error.nll.stderr b/src/test/ui/object-lifetime/object-lifetime-default-from-rptr-box-error.nll.stderr index defffe2b84..7d6f9f39d1 100644 --- a/src/test/ui/object-lifetime/object-lifetime-default-from-rptr-box-error.nll.stderr +++ b/src/test/ui/object-lifetime/object-lifetime-default-from-rptr-box-error.nll.stderr @@ -5,8 +5,6 @@ LL | fn c<'a>(t: &'a Box, mut ss: SomeStruct<'a>) { | -- lifetime `'a` defined here LL | ss.t = t; | ^^^^^^^^ assignment requires that `'a` must outlive `'static` - | - = help: consider replacing `'a` with `'static` error: aborting due to previous error diff --git a/src/test/ui/object-lifetime/object-lifetime-default-from-rptr-box-error.stderr b/src/test/ui/object-lifetime/object-lifetime-default-from-rptr-box-error.stderr index a789c4906e..e7fab9ecef 100644 --- a/src/test/ui/object-lifetime/object-lifetime-default-from-rptr-box-error.stderr +++ b/src/test/ui/object-lifetime/object-lifetime-default-from-rptr-box-error.stderr @@ -6,7 +6,7 @@ LL | ss.t = t; | = note: expected reference `&'a Box<(dyn Test + 'static)>` found reference `&'a Box<(dyn Test + 'a)>` -note: the lifetime `'a` as defined on the function body at 14:6... +note: the lifetime `'a` as defined here... --> $DIR/object-lifetime-default-from-rptr-box-error.rs:14:6 | LL | fn c<'a>(t: &'a Box, mut ss: SomeStruct<'a>) { diff --git a/src/test/ui/object-lifetime/object-lifetime-default-from-rptr-struct-error.nll.stderr b/src/test/ui/object-lifetime/object-lifetime-default-from-rptr-struct-error.nll.stderr index 8c28a7a011..6df54638ce 100644 --- a/src/test/ui/object-lifetime/object-lifetime-default-from-rptr-struct-error.nll.stderr +++ b/src/test/ui/object-lifetime/object-lifetime-default-from-rptr-struct-error.nll.stderr @@ -5,8 +5,6 @@ LL | fn c<'a>(t: &'a MyBox, mut ss: SomeStruct<'a>) { | -- lifetime `'a` defined here LL | ss.t = t; | ^^^^^^^^ assignment requires that `'a` must outlive `'static` - | - = help: consider replacing `'a` with `'static` error: aborting due to previous error diff --git a/src/test/ui/object-lifetime/object-lifetime-default-from-rptr-struct-error.stderr b/src/test/ui/object-lifetime/object-lifetime-default-from-rptr-struct-error.stderr index 65f8a32f06..07c321ed8c 100644 --- a/src/test/ui/object-lifetime/object-lifetime-default-from-rptr-struct-error.stderr +++ b/src/test/ui/object-lifetime/object-lifetime-default-from-rptr-struct-error.stderr @@ -6,7 +6,7 @@ LL | ss.t = t; | = note: expected reference `&'a MyBox<(dyn Test + 'static)>` found reference `&'a MyBox<(dyn Test + 'a)>` -note: the lifetime `'a` as defined on the function body at 20:6... +note: the lifetime `'a` as defined here... --> $DIR/object-lifetime-default-from-rptr-struct-error.rs:20:6 | LL | fn c<'a>(t: &'a MyBox, mut ss: SomeStruct<'a>) { diff --git a/src/test/ui/object-lifetime/object-lifetime-default-mybox.nll.stderr b/src/test/ui/object-lifetime/object-lifetime-default-mybox.nll.stderr index 42dae7e40d..af20c5e5fc 100644 --- a/src/test/ui/object-lifetime/object-lifetime-default-mybox.nll.stderr +++ b/src/test/ui/object-lifetime/object-lifetime-default-mybox.nll.stderr @@ -15,11 +15,14 @@ error[E0521]: borrowed data escapes outside of function --> $DIR/object-lifetime-default-mybox.rs:31:5 | LL | fn load2<'a>(ss: &MyBox) -> MyBox { - | -- `ss` is a reference that is only valid in the function body + | -- -- `ss` is a reference that is only valid in the function body + | | + | lifetime `'a` defined here LL | load0(ss) - | ^^^^^^^^^ `ss` escapes the function body here - | - = help: consider replacing `'a` with `'static` + | ^^^^^^^^^ + | | + | `ss` escapes the function body here + | argument requires that `'a` must outlive `'static` error: aborting due to 2 previous errors diff --git a/src/test/ui/object-lifetime/object-lifetime-default-mybox.stderr b/src/test/ui/object-lifetime/object-lifetime-default-mybox.stderr index 404717ff55..4c5fb452eb 100644 --- a/src/test/ui/object-lifetime/object-lifetime-default-mybox.stderr +++ b/src/test/ui/object-lifetime/object-lifetime-default-mybox.stderr @@ -18,7 +18,7 @@ LL | load0(ss) | = note: expected reference `&MyBox<(dyn SomeTrait + 'static)>` found reference `&MyBox<(dyn SomeTrait + 'a)>` -note: the lifetime `'a` as defined on the function body at 30:10... +note: the lifetime `'a` as defined here... --> $DIR/object-lifetime-default-mybox.rs:30:10 | LL | fn load2<'a>(ss: &MyBox) -> MyBox { diff --git a/src/test/ui/object-safety/object-safety-associated-consts.curr.stderr b/src/test/ui/object-safety/object-safety-associated-consts.curr.stderr index 35ec586892..9dd144fee2 100644 --- a/src/test/ui/object-safety/object-safety-associated-consts.curr.stderr +++ b/src/test/ui/object-safety/object-safety-associated-consts.curr.stderr @@ -4,7 +4,6 @@ error[E0038]: the trait `Bar` cannot be made into an object LL | fn make_bar(t: &T) -> &dyn Bar { | ^^^^^^^^ `Bar` cannot be made into an object | - = help: consider moving `X` to another trait note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit --> $DIR/object-safety-associated-consts.rs:9:11 | @@ -12,6 +11,7 @@ LL | trait Bar { | --- this trait cannot be made into an object... LL | const X: usize; | ^ ...because it contains this associated `const` + = help: consider moving `X` to another trait error: aborting due to previous error diff --git a/src/test/ui/object-safety/object-safety-associated-consts.object_safe_for_dispatch.stderr b/src/test/ui/object-safety/object-safety-associated-consts.object_safe_for_dispatch.stderr index d51734ed23..9ba3b251e6 100644 --- a/src/test/ui/object-safety/object-safety-associated-consts.object_safe_for_dispatch.stderr +++ b/src/test/ui/object-safety/object-safety-associated-consts.object_safe_for_dispatch.stderr @@ -4,7 +4,6 @@ error[E0038]: the trait `Bar` cannot be made into an object LL | t | ^ `Bar` cannot be made into an object | - = help: consider moving `X` to another trait note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit --> $DIR/object-safety-associated-consts.rs:9:11 | @@ -12,6 +11,7 @@ LL | trait Bar { | --- this trait cannot be made into an object... LL | const X: usize; | ^ ...because it contains this associated `const` + = help: consider moving `X` to another trait = note: required because of the requirements on the impl of `CoerceUnsized<&dyn Bar>` for `&T` = note: required by cast to type `&dyn Bar` diff --git a/src/test/ui/object-safety/object-safety-by-value-self-use.stderr b/src/test/ui/object-safety/object-safety-by-value-self-use.stderr index 1497aa4208..7ccc0cbdd5 100644 --- a/src/test/ui/object-safety/object-safety-by-value-self-use.stderr +++ b/src/test/ui/object-safety/object-safety-by-value-self-use.stderr @@ -2,7 +2,7 @@ error[E0161]: cannot move a value of type dyn Bar: the size of dyn Bar cannot be --> $DIR/object-safety-by-value-self-use.rs:15:5 | LL | t.bar() - | ^ + | ^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/object-safety/object-safety-generics.curr.stderr b/src/test/ui/object-safety/object-safety-generics.curr.stderr index 8d6094c514..345950f1ae 100644 --- a/src/test/ui/object-safety/object-safety-generics.curr.stderr +++ b/src/test/ui/object-safety/object-safety-generics.curr.stderr @@ -4,7 +4,6 @@ error[E0038]: the trait `Bar` cannot be made into an object LL | fn make_bar(t: &T) -> &dyn Bar { | ^^^^^^^^ `Bar` cannot be made into an object | - = help: consider moving `bar` to another trait note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit --> $DIR/object-safety-generics.rs:10:8 | @@ -12,6 +11,7 @@ LL | trait Bar { | --- this trait cannot be made into an object... LL | fn bar(&self, t: T); | ^^^ ...because method `bar` has generic type parameters + = help: consider moving `bar` to another trait error[E0038]: the trait `Bar` cannot be made into an object --> $DIR/object-safety-generics.rs:24:39 @@ -19,7 +19,6 @@ error[E0038]: the trait `Bar` cannot be made into an object LL | fn make_bar_explicit(t: &T) -> &dyn Bar { | ^^^^^^^^ `Bar` cannot be made into an object | - = help: consider moving `bar` to another trait note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit --> $DIR/object-safety-generics.rs:10:8 | @@ -27,6 +26,7 @@ LL | trait Bar { | --- this trait cannot be made into an object... LL | fn bar(&self, t: T); | ^^^ ...because method `bar` has generic type parameters + = help: consider moving `bar` to another trait error: aborting due to 2 previous errors diff --git a/src/test/ui/object-safety/object-safety-generics.object_safe_for_dispatch.stderr b/src/test/ui/object-safety/object-safety-generics.object_safe_for_dispatch.stderr index 3d2b2bb228..86355627c7 100644 --- a/src/test/ui/object-safety/object-safety-generics.object_safe_for_dispatch.stderr +++ b/src/test/ui/object-safety/object-safety-generics.object_safe_for_dispatch.stderr @@ -4,7 +4,6 @@ error[E0038]: the trait `Bar` cannot be made into an object LL | t | ^ `Bar` cannot be made into an object | - = help: consider moving `bar` to another trait note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit --> $DIR/object-safety-generics.rs:10:8 | @@ -12,6 +11,7 @@ LL | trait Bar { | --- this trait cannot be made into an object... LL | fn bar(&self, t: T); | ^^^ ...because method `bar` has generic type parameters + = help: consider moving `bar` to another trait = note: required because of the requirements on the impl of `CoerceUnsized<&dyn Bar>` for `&T` = note: required by cast to type `&dyn Bar` @@ -21,7 +21,6 @@ error[E0038]: the trait `Bar` cannot be made into an object LL | t as &dyn Bar | ^ `Bar` cannot be made into an object | - = help: consider moving `bar` to another trait note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit --> $DIR/object-safety-generics.rs:10:8 | @@ -29,6 +28,7 @@ LL | trait Bar { | --- this trait cannot be made into an object... LL | fn bar(&self, t: T); | ^^^ ...because method `bar` has generic type parameters + = help: consider moving `bar` to another trait = note: required because of the requirements on the impl of `CoerceUnsized<&dyn Bar>` for `&T` = note: required by cast to type `&dyn Bar` diff --git a/src/test/ui/object-safety/object-safety-mentions-Self.curr.stderr b/src/test/ui/object-safety/object-safety-mentions-Self.curr.stderr index 336929702e..f91c9b9856 100644 --- a/src/test/ui/object-safety/object-safety-mentions-Self.curr.stderr +++ b/src/test/ui/object-safety/object-safety-mentions-Self.curr.stderr @@ -4,7 +4,6 @@ error[E0038]: the trait `Bar` cannot be made into an object LL | fn make_bar(t: &T) -> &dyn Bar { | ^^^^^^^^ `Bar` cannot be made into an object | - = help: consider moving `bar` to another trait note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit --> $DIR/object-safety-mentions-Self.rs:11:22 | @@ -12,6 +11,7 @@ LL | trait Bar { | --- this trait cannot be made into an object... LL | fn bar(&self, x: &Self); | ^^^^^ ...because method `bar` references the `Self` type in this parameter + = help: consider moving `bar` to another trait error[E0038]: the trait `Baz` cannot be made into an object --> $DIR/object-safety-mentions-Self.rs:28:30 @@ -19,7 +19,6 @@ error[E0038]: the trait `Baz` cannot be made into an object LL | fn make_baz(t: &T) -> &dyn Baz { | ^^^^^^^^ `Baz` cannot be made into an object | - = help: consider moving `baz` to another trait note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit --> $DIR/object-safety-mentions-Self.rs:15:22 | @@ -27,6 +26,7 @@ LL | trait Baz { | --- this trait cannot be made into an object... LL | fn baz(&self) -> Self; | ^^^^ ...because method `baz` references the `Self` type in its return type + = help: consider moving `baz` to another trait error: aborting due to 2 previous errors diff --git a/src/test/ui/object-safety/object-safety-mentions-Self.object_safe_for_dispatch.stderr b/src/test/ui/object-safety/object-safety-mentions-Self.object_safe_for_dispatch.stderr index 6e7896e309..f48628c9d1 100644 --- a/src/test/ui/object-safety/object-safety-mentions-Self.object_safe_for_dispatch.stderr +++ b/src/test/ui/object-safety/object-safety-mentions-Self.object_safe_for_dispatch.stderr @@ -4,7 +4,6 @@ error[E0038]: the trait `Bar` cannot be made into an object LL | t | ^ `Bar` cannot be made into an object | - = help: consider moving `bar` to another trait note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit --> $DIR/object-safety-mentions-Self.rs:11:22 | @@ -12,6 +11,7 @@ LL | trait Bar { | --- this trait cannot be made into an object... LL | fn bar(&self, x: &Self); | ^^^^^ ...because method `bar` references the `Self` type in this parameter + = help: consider moving `bar` to another trait = note: required because of the requirements on the impl of `CoerceUnsized<&dyn Bar>` for `&T` = note: required by cast to type `&dyn Bar` @@ -21,7 +21,6 @@ error[E0038]: the trait `Baz` cannot be made into an object LL | t | ^ `Baz` cannot be made into an object | - = help: consider moving `baz` to another trait note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit --> $DIR/object-safety-mentions-Self.rs:15:22 | @@ -29,6 +28,7 @@ LL | trait Baz { | --- this trait cannot be made into an object... LL | fn baz(&self) -> Self; | ^^^^ ...because method `baz` references the `Self` type in its return type + = help: consider moving `baz` to another trait = note: required because of the requirements on the impl of `CoerceUnsized<&dyn Baz>` for `&T` = note: required by cast to type `&dyn Baz` diff --git a/src/test/ui/objects-owned-object-borrowed-method-headerless.rs b/src/test/ui/objects-owned-object-borrowed-method-headerless.rs index 9b88d8ea7b..fce1341fc7 100644 --- a/src/test/ui/objects-owned-object-borrowed-method-headerless.rs +++ b/src/test/ui/objects-owned-object-borrowed-method-headerless.rs @@ -3,9 +3,6 @@ // closed over do not contain managed values, and thus the boxes do // not have headers. -#![feature(box_syntax)] - - trait FooTrait { fn foo(&self) -> usize; } @@ -22,9 +19,9 @@ impl FooTrait for BarStruct { pub fn main() { let foos: Vec> = vec![ - box BarStruct{ x: 0 } as Box, - box BarStruct{ x: 1 } as Box, - box BarStruct{ x: 2 } as Box + Box::new(BarStruct{ x: 0 }) as Box, + Box::new(BarStruct{ x: 1 }) as Box, + Box::new(BarStruct{ x: 2 }) as Box, ]; for i in 0..foos.len() { diff --git a/src/test/ui/objects-owned-object-owned-method.rs b/src/test/ui/objects-owned-object-owned-method.rs index 4b7b68f221..15677a5185 100644 --- a/src/test/ui/objects-owned-object-owned-method.rs +++ b/src/test/ui/objects-owned-object-owned-method.rs @@ -3,8 +3,6 @@ // closed over contain managed values. This implies that the boxes // will have headers that must be skipped over. -#![feature(box_syntax)] - trait FooTrait { fn foo(self: Box) -> usize; } @@ -20,6 +18,6 @@ impl FooTrait for BarStruct { } pub fn main() { - let foo = box BarStruct{ x: 22 } as Box; + let foo = Box::new(BarStruct{ x: 22 }) as Box; assert_eq!(22, foo.foo()); } diff --git a/src/test/ui/occurs-check-2.rs b/src/test/ui/occurs-check-2.rs index 213fd2619c..f36682a3dd 100644 --- a/src/test/ui/occurs-check-2.rs +++ b/src/test/ui/occurs-check-2.rs @@ -1,10 +1,10 @@ -#![feature(box_syntax)] - fn main() { + let f; let g; + g = f; - f = box g; + f = Box::new(g); //~^ ERROR mismatched types //~| cyclic type of infinite size } diff --git a/src/test/ui/occurs-check-2.stderr b/src/test/ui/occurs-check-2.stderr index c004043307..dcbfc81b4d 100644 --- a/src/test/ui/occurs-check-2.stderr +++ b/src/test/ui/occurs-check-2.stderr @@ -1,13 +1,10 @@ error[E0308]: mismatched types --> $DIR/occurs-check-2.rs:7:9 | -LL | f = box g; - | ^^^^^ cyclic type of infinite size - | -help: try using a conversion method - | -LL | f = (box g).to_string(); - | + +++++++++++++ +LL | f = Box::new(g); + | ^^^^^^^^^^^- help: try using a conversion method: `.to_string()` + | | + | cyclic type of infinite size error: aborting due to previous error diff --git a/src/test/ui/occurs-check.rs b/src/test/ui/occurs-check.rs index 5f2c2362d2..aec52d8397 100644 --- a/src/test/ui/occurs-check.rs +++ b/src/test/ui/occurs-check.rs @@ -1,8 +1,8 @@ -#![feature(box_syntax)] - fn main() { + let f; - f = box f; + + f = Box::new(f); //~^ ERROR mismatched types //~| cyclic type of infinite size } diff --git a/src/test/ui/occurs-check.stderr b/src/test/ui/occurs-check.stderr index 452163e2fa..3e1ef2e719 100644 --- a/src/test/ui/occurs-check.stderr +++ b/src/test/ui/occurs-check.stderr @@ -1,13 +1,10 @@ error[E0308]: mismatched types --> $DIR/occurs-check.rs:5:9 | -LL | f = box f; - | ^^^^^ cyclic type of infinite size - | -help: try using a conversion method - | -LL | f = (box f).to_string(); - | + +++++++++++++ +LL | f = Box::new(f); + | ^^^^^^^^^^^- help: try using a conversion method: `.to_string()` + | | + | cyclic type of infinite size error: aborting due to previous error diff --git a/src/test/ui/on-unimplemented/enclosing-scope.stderr b/src/test/ui/on-unimplemented/enclosing-scope.stderr index abd156dd5a..67759d02a1 100644 --- a/src/test/ui/on-unimplemented/enclosing-scope.stderr +++ b/src/test/ui/on-unimplemented/enclosing-scope.stderr @@ -4,7 +4,9 @@ error[E0277]: the trait bound `Foo: Trait` is not satisfied LL | let x = || { | _____________- LL | | f(Foo{}); - | | ^^^^^ the trait `Trait` is not implemented for `Foo` + | | - ^^^^^ the trait `Trait` is not implemented for `Foo` + | | | + | | required by a bound introduced by this call LL | | let y = || { LL | | f(Foo{}); LL | | }; @@ -23,7 +25,9 @@ error[E0277]: the trait bound `Foo: Trait` is not satisfied LL | let y = || { | _________________- LL | | f(Foo{}); - | | ^^^^^ the trait `Trait` is not implemented for `Foo` + | | - ^^^^^ the trait `Trait` is not implemented for `Foo` + | | | + | | required by a bound introduced by this call LL | | }; | |_________- in this scope | @@ -42,7 +46,9 @@ LL | | f(Foo{}); LL | | let y = || { ... | LL | | f(Foo{}); - | | ^^^^^ the trait `Trait` is not implemented for `Foo` + | | - ^^^^^ the trait `Trait` is not implemented for `Foo` + | | | + | | required by a bound introduced by this call ... | LL | | f(Foo{}); LL | | } @@ -63,7 +69,9 @@ LL | | f(Foo{}); LL | | let y = || { ... | LL | | f(Foo{}); - | | ^^^^^ the trait `Trait` is not implemented for `Foo` + | | - ^^^^^ the trait `Trait` is not implemented for `Foo` + | | | + | | required by a bound introduced by this call LL | | } | |_- in this scope | diff --git a/src/test/ui/on-unimplemented/multiple-impls.stderr b/src/test/ui/on-unimplemented/multiple-impls.stderr index 804b628220..a3658f2242 100644 --- a/src/test/ui/on-unimplemented/multiple-impls.stderr +++ b/src/test/ui/on-unimplemented/multiple-impls.stderr @@ -2,7 +2,9 @@ error[E0277]: the trait bound `[i32]: Index` is not satisfied --> $DIR/multiple-impls.rs:33:18 | LL | Index::index(&[] as &[i32], 2u32); - | ^^^^^^^^^^^^^ trait message + | ------------ ^^^^^^^^^^^^^ trait message + | | + | required by a bound introduced by this call | = help: the trait `Index` is not implemented for `[i32]` note: required by `Index::index` @@ -15,7 +17,9 @@ error[E0277]: the trait bound `[i32]: Index>` is not satisfied --> $DIR/multiple-impls.rs:36:18 | LL | Index::index(&[] as &[i32], Foo(2u32)); - | ^^^^^^^^^^^^^ on impl for Foo + | ------------ ^^^^^^^^^^^^^ on impl for Foo + | | + | required by a bound introduced by this call | = help: the trait `Index>` is not implemented for `[i32]` note: required by `Index::index` @@ -28,7 +32,9 @@ error[E0277]: the trait bound `[i32]: Index>` is not satisfied --> $DIR/multiple-impls.rs:39:18 | LL | Index::index(&[] as &[i32], Bar(2u32)); - | ^^^^^^^^^^^^^ on impl for Bar + | ------------ ^^^^^^^^^^^^^ on impl for Bar + | | + | required by a bound introduced by this call | = help: the trait `Index>` is not implemented for `[i32]` note: required by `Index::index` diff --git a/src/test/ui/on-unimplemented/on-impl.stderr b/src/test/ui/on-unimplemented/on-impl.stderr index bfd438e5cc..18eca06ba6 100644 --- a/src/test/ui/on-unimplemented/on-impl.stderr +++ b/src/test/ui/on-unimplemented/on-impl.stderr @@ -2,7 +2,9 @@ error[E0277]: the trait bound `[i32]: Index` is not satisfied --> $DIR/on-impl.rs:22:25 | LL | Index::::index(&[1, 2, 3] as &[i32], 2u32); - | ^^^^^^^^^^^^^^^^^^^^ a usize is required to index into a slice + | ------------------- ^^^^^^^^^^^^^^^^^^^^ a usize is required to index into a slice + | | + | required by a bound introduced by this call | = help: the trait `Index` is not implemented for `[i32]` note: required by `Index::index` diff --git a/src/test/ui/or-patterns/or-patterns-syntactic-fail.stderr b/src/test/ui/or-patterns/or-patterns-syntactic-fail.stderr index 5406d51c64..c94adfe4ab 100644 --- a/src/test/ui/or-patterns/or-patterns-syntactic-fail.stderr +++ b/src/test/ui/or-patterns/or-patterns-syntactic-fail.stderr @@ -30,7 +30,22 @@ LL | let _ = |A | B: E| (); | | | E | - = note: an implementation of `std::ops::BitOr` might be missing for `E` +note: an implementation of `BitOr<_>` might be missing for `E` + --> $DIR/or-patterns-syntactic-fail.rs:6:1 + | +LL | enum E { A, B } + | ^^^^^^ must implement `BitOr<_>` +note: the following trait must be implemented + --> $SRC_DIR/core/src/ops/bit.rs:LL:COL + | +LL | / pub trait BitOr { +LL | | /// The resulting type after applying the `|` operator. +LL | | #[stable(feature = "rust1", since = "1.0.0")] +LL | | type Output; +... | +LL | | fn bitor(self, rhs: Rhs) -> Self::Output; +LL | | } + | |_^ error: aborting due to 5 previous errors diff --git a/src/test/ui/output-slot-variants.rs b/src/test/ui/output-slot-variants.rs index af4caf7566..7c20a2b2f9 100644 --- a/src/test/ui/output-slot-variants.rs +++ b/src/test/ui/output-slot-variants.rs @@ -7,22 +7,21 @@ #![allow(dead_assignment)] #![allow(unused_variables)] -#![feature(box_syntax)] struct A { a: isize, b: isize } struct Abox { a: Box, b: Box } fn ret_int_i() -> isize { 10 } -fn ret_ext_i() -> Box { box 10 } +fn ret_ext_i() -> Box { Box::new(10) } fn ret_int_rec() -> A { A {a: 10, b: 10} } -fn ret_ext_rec() -> Box { box A {a: 10, b: 10} } +fn ret_ext_rec() -> Box { Box::new(A {a: 10, b: 10}) } -fn ret_ext_mem() -> Abox { Abox {a: box 10, b: box 10} } +fn ret_ext_mem() -> Abox { Abox {a: Box::new(10), b: Box::new(10) } } -fn ret_ext_ext_mem() -> Box { box Abox{a: box 10, b: box 10} } +fn ret_ext_ext_mem() -> Box { Box::new(Abox{a: Box::new(10), b: Box::new(10) }) } pub fn main() { let mut int_i: isize; diff --git a/src/test/ui/overloaded/overloaded-autoderef-order.rs b/src/test/ui/overloaded/overloaded-autoderef-order.rs index 1ae16d2a7f..f48bae55f5 100644 --- a/src/test/ui/overloaded/overloaded-autoderef-order.rs +++ b/src/test/ui/overloaded/overloaded-autoderef-order.rs @@ -1,5 +1,7 @@ // run-pass +#![allow(dead_code)] + use std::rc::Rc; use std::ops::Deref; diff --git a/src/test/ui/overloaded/overloaded-autoderef.rs b/src/test/ui/overloaded/overloaded-autoderef.rs index e850633e34..cae3ec9062 100644 --- a/src/test/ui/overloaded/overloaded-autoderef.rs +++ b/src/test/ui/overloaded/overloaded-autoderef.rs @@ -2,8 +2,6 @@ #![allow(unused_variables)] #![allow(stable_features)] -#![feature(box_syntax, core)] - use std::cell::RefCell; use std::rc::Rc; @@ -14,7 +12,7 @@ struct Point { } pub fn main() { - let box_5: Box<_> = box 5_usize; + let box_5: Box<_> = Box::new(5_usize); let point = Rc::new(Point {x: 2, y: 4}); assert_eq!(point.x, 2); assert_eq!(point.y, 4); diff --git a/src/test/ui/overloaded/overloaded-index-autoderef.rs b/src/test/ui/overloaded/overloaded-index-autoderef.rs index 6996ee3293..41f9efa8c1 100644 --- a/src/test/ui/overloaded/overloaded-index-autoderef.rs +++ b/src/test/ui/overloaded/overloaded-index-autoderef.rs @@ -3,8 +3,6 @@ // Test overloaded indexing combined with autoderef. -#![feature(box_syntax, core)] - use std::ops::{Index, IndexMut}; struct Foo { @@ -47,10 +45,10 @@ impl Int for isize { } fn main() { - let mut f: Box<_> = box Foo { + let mut f: Box<_> = Box::new(Foo { x: 1, y: 2, - }; + }); assert_eq!(f[1], 2); diff --git a/src/test/ui/panics/args-panic.rs b/src/test/ui/panics/args-panic.rs index 322054caf1..7636025c25 100644 --- a/src/test/ui/panics/args-panic.rs +++ b/src/test/ui/panics/args-panic.rs @@ -2,12 +2,10 @@ // error-pattern:meep // ignore-emscripten no processes -#![feature(box_syntax)] - fn f(_a: isize, _b: isize, _c: Box) { panic!("moop"); } fn main() { - f(1, panic!("meep"), box 42); + f(1, panic!("meep"), Box::new(42)); } diff --git a/src/test/ui/panics/panic-macro-any.rs b/src/test/ui/panics/panic-macro-any.rs index 08acc6e807..c7df536547 100644 --- a/src/test/ui/panics/panic-macro-any.rs +++ b/src/test/ui/panics/panic-macro-any.rs @@ -2,9 +2,8 @@ // error-pattern:panicked at 'Box' // ignore-emscripten no processes -#![feature(box_syntax)] #![allow(non_fmt_panics)] fn main() { - panic!(box 413 as Box); + panic!(Box::new(413) as Box); } diff --git a/src/test/ui/parser/attr-stmt-expr-attr-bad.stderr b/src/test/ui/parser/attr-stmt-expr-attr-bad.stderr index cec6980c00..d38b98a190 100644 --- a/src/test/ui/parser/attr-stmt-expr-attr-bad.stderr +++ b/src/test/ui/parser/attr-stmt-expr-attr-bad.stderr @@ -4,7 +4,8 @@ error: an inner attribute is not permitted in this context LL | #[cfg(FALSE)] fn e() { let _ = box #![attr] 0; } | ^^^^^^^^ | - = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them. + = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files + = note: outer attributes, like `#[test]`, annotate the item following them error: expected expression, found `]` --> $DIR/attr-stmt-expr-attr-bad.rs:7:40 @@ -24,7 +25,8 @@ error: an inner attribute is not permitted in this context LL | #[cfg(FALSE)] fn e() { let _ = foo(#![attr]); } | ^^^^^^^^ | - = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them. + = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files + = note: outer attributes, like `#[test]`, annotate the item following them error: expected expression, found `)` --> $DIR/attr-stmt-expr-attr-bad.rs:11:44 @@ -38,7 +40,8 @@ error: an inner attribute is not permitted in this context LL | #[cfg(FALSE)] fn e() { let _ = x.foo(#![attr]); } | ^^^^^^^^ | - = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them. + = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files + = note: outer attributes, like `#[test]`, annotate the item following them error: expected expression, found `)` --> $DIR/attr-stmt-expr-attr-bad.rs:14:46 @@ -52,7 +55,8 @@ error: an inner attribute is not permitted in this context LL | #[cfg(FALSE)] fn e() { let _ = 0 + #![attr] 0; } | ^^^^^^^^ | - = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them. + = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files + = note: outer attributes, like `#[test]`, annotate the item following them error: an inner attribute is not permitted in this context --> $DIR/attr-stmt-expr-attr-bad.rs:19:33 @@ -60,7 +64,8 @@ error: an inner attribute is not permitted in this context LL | #[cfg(FALSE)] fn e() { let _ = !#![attr] 0; } | ^^^^^^^^ | - = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them. + = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files + = note: outer attributes, like `#[test]`, annotate the item following them error: an inner attribute is not permitted in this context --> $DIR/attr-stmt-expr-attr-bad.rs:21:33 @@ -68,7 +73,8 @@ error: an inner attribute is not permitted in this context LL | #[cfg(FALSE)] fn e() { let _ = -#![attr] 0; } | ^^^^^^^^ | - = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them. + = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files + = note: outer attributes, like `#[test]`, annotate the item following them error: expected one of `!`, `.`, `::`, `;`, `?`, `else`, `{`, or an operator, found `#` --> $DIR/attr-stmt-expr-attr-bad.rs:23:34 @@ -82,7 +88,8 @@ error: an inner attribute is not permitted in this context LL | #[cfg(FALSE)] fn e() { let _ = || #![attr] foo; } | ^^^^^^^^ | - = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them. + = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files + = note: outer attributes, like `#[test]`, annotate the item following them error: an inner attribute is not permitted in this context --> $DIR/attr-stmt-expr-attr-bad.rs:27:40 @@ -90,7 +97,8 @@ error: an inner attribute is not permitted in this context LL | #[cfg(FALSE)] fn e() { let _ = move || #![attr] foo; } | ^^^^^^^^ | - = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them. + = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files + = note: outer attributes, like `#[test]`, annotate the item following them error: an inner attribute is not permitted in this context --> $DIR/attr-stmt-expr-attr-bad.rs:29:35 @@ -98,7 +106,8 @@ error: an inner attribute is not permitted in this context LL | #[cfg(FALSE)] fn e() { let _ = || #![attr] {foo}; } | ^^^^^^^^ | - = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them. + = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files + = note: outer attributes, like `#[test]`, annotate the item following them error: an inner attribute is not permitted in this context --> $DIR/attr-stmt-expr-attr-bad.rs:31:40 @@ -106,7 +115,8 @@ error: an inner attribute is not permitted in this context LL | #[cfg(FALSE)] fn e() { let _ = move || #![attr] {foo}; } | ^^^^^^^^ | - = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them. + = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files + = note: outer attributes, like `#[test]`, annotate the item following them error: expected expression, found `..` --> $DIR/attr-stmt-expr-attr-bad.rs:33:40 @@ -126,7 +136,8 @@ error: an inner attribute is not permitted in this context LL | #[cfg(FALSE)] fn e() { let _ = #[attr] &#![attr] 0; } | ^^^^^^^^ | - = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them. + = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files + = note: outer attributes, like `#[test]`, annotate the item following them error: an inner attribute is not permitted in this context --> $DIR/attr-stmt-expr-attr-bad.rs:39:45 @@ -134,7 +145,8 @@ error: an inner attribute is not permitted in this context LL | #[cfg(FALSE)] fn e() { let _ = #[attr] &mut #![attr] 0; } | ^^^^^^^^ | - = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them. + = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files + = note: outer attributes, like `#[test]`, annotate the item following them error: outer attributes are not allowed on `if` and `else` branches --> $DIR/attr-stmt-expr-attr-bad.rs:41:37 @@ -151,7 +163,8 @@ error: an inner attribute is not permitted in this context LL | #[cfg(FALSE)] fn e() { let _ = if 0 {#![attr]}; } | ^^^^^^^^ | - = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them. + = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files + = note: outer attributes, like `#[test]`, annotate the item following them error: expected one of `.`, `;`, `?`, `else`, or an operator, found `#` --> $DIR/attr-stmt-expr-attr-bad.rs:45:40 @@ -174,7 +187,8 @@ error: an inner attribute is not permitted in this context LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else {#![attr]}; } | ^^^^^^^^ | - = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them. + = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files + = note: outer attributes, like `#[test]`, annotate the item following them error: outer attributes are not allowed on `if` and `else` branches --> $DIR/attr-stmt-expr-attr-bad.rs:51:45 @@ -200,7 +214,8 @@ error: an inner attribute is not permitted in this context LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else if 0 {#![attr]}; } | ^^^^^^^^ | - = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them. + = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files + = note: outer attributes, like `#[test]`, annotate the item following them error: outer attributes are not allowed on `if` and `else` branches --> $DIR/attr-stmt-expr-attr-bad.rs:57:45 @@ -217,7 +232,8 @@ error: an inner attribute is not permitted in this context LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {#![attr]}; } | ^^^^^^^^ | - = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them. + = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files + = note: outer attributes, like `#[test]`, annotate the item following them error: expected one of `.`, `;`, `?`, `else`, or an operator, found `#` --> $DIR/attr-stmt-expr-attr-bad.rs:61:48 @@ -240,7 +256,8 @@ error: an inner attribute is not permitted in this context LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else {#![attr]}; } | ^^^^^^^^ | - = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them. + = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files + = note: outer attributes, like `#[test]`, annotate the item following them error: outer attributes are not allowed on `if` and `else` branches --> $DIR/attr-stmt-expr-attr-bad.rs:67:53 @@ -266,7 +283,8 @@ error: an inner attribute is not permitted in this context LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else if let _ = 0 {#![attr]}; } | ^^^^^^^^ | - = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them. + = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files + = note: outer attributes, like `#[test]`, annotate the item following them error: an inner attribute is not permitted following an outer attribute --> $DIR/attr-stmt-expr-attr-bad.rs:74:32 @@ -276,7 +294,8 @@ LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] let _ = 0; } | | | previous outer attribute | - = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them. + = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files + = note: outer attributes, like `#[test]`, annotate the item following them error: an inner attribute is not permitted following an outer attribute --> $DIR/attr-stmt-expr-attr-bad.rs:76:32 @@ -286,37 +305,56 @@ LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] 0; } | | | previous outer attribute | - = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them. + = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files + = note: outer attributes, like `#[test]`, annotate the item following them error: an inner attribute is not permitted following an outer attribute --> $DIR/attr-stmt-expr-attr-bad.rs:78:32 | LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] foo!(); } - | ------- ^^^^^^^^ not permitted following an outer attribute - | | + | ------- ^^^^^^^^ ------- the inner attribute doesn't annotate this item macro invocation + | | | + | | not permitted following an outer attribute | previous outer attribute | - = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them. + = 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 item macro invocation, change the attribute from inner to outer style + | +LL - #[cfg(FALSE)] fn s() { #[attr] #![attr] foo!(); } +LL + #[cfg(FALSE)] fn s() { #[attr] #[attr] foo!(); } + | error: an inner attribute is not permitted following an outer attribute --> $DIR/attr-stmt-expr-attr-bad.rs:80:32 | LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] foo![]; } - | ------- ^^^^^^^^ not permitted following an outer attribute - | | + | ------- ^^^^^^^^ ------- the inner attribute doesn't annotate this item macro invocation + | | | + | | not permitted following an outer attribute | previous outer attribute | - = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them. + = 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 item macro invocation, change the attribute from inner to outer style + | +LL - #[cfg(FALSE)] fn s() { #[attr] #![attr] foo![]; } +LL + #[cfg(FALSE)] fn s() { #[attr] #[attr] foo![]; } + | error: an inner attribute is not permitted following an outer attribute --> $DIR/attr-stmt-expr-attr-bad.rs:82:32 | LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] foo!{}; } - | ------- ^^^^^^^^ not permitted following an outer attribute - | | + | ------- ^^^^^^^^ ------ the inner attribute doesn't annotate this item macro invocation + | | | + | | not permitted following an outer attribute | previous outer attribute | - = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them. + = 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 item macro invocation, change the attribute from inner to outer style + | +LL - #[cfg(FALSE)] fn s() { #[attr] #![attr] foo!{}; } +LL + #[cfg(FALSE)] fn s() { #[attr] #[attr] foo!{}; } + | error[E0586]: inclusive range with no end --> $DIR/attr-stmt-expr-attr-bad.rs:88:35 diff --git a/src/test/ui/parser/attr.stderr b/src/test/ui/parser/attr.stderr index 400a0276b3..3cec61fe41 100644 --- a/src/test/ui/parser/attr.stderr +++ b/src/test/ui/parser/attr.stderr @@ -3,8 +3,16 @@ error: an inner attribute is not permitted in this context | LL | #![lang = "foo"] | ^^^^^^^^^^^^^^^^ +LL | +LL | fn foo() {} + | ----------- the inner attribute doesn't annotate this function | - = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them. + = 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 function, change the attribute from inner to outer style + | +LL - #![lang = "foo"] +LL + #[lang = "foo"] + | error[E0522]: definition of an unknown language item: `foo` --> $DIR/attr.rs:5:1 diff --git a/src/test/ui/parser/bad-interpolated-block.stderr b/src/test/ui/parser/bad-interpolated-block.stderr index 9a6957a040..77933b1bce 100644 --- a/src/test/ui/parser/bad-interpolated-block.stderr +++ b/src/test/ui/parser/bad-interpolated-block.stderr @@ -7,7 +7,7 @@ LL | 'lab: $b; | the `block` fragment is within this context ... LL | m!({}); - | ------- in this macro invocation + | ------ in this macro invocation | = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -20,7 +20,7 @@ LL | unsafe $b; | the `block` fragment is within this context ... LL | m!({}); - | ------- in this macro invocation + | ------ in this macro invocation | = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -31,7 +31,7 @@ LL | |x: u8| -> () $b; | ^^ the `block` fragment is within this context ... LL | m!({}); - | ------- in this macro invocation + | ------ in this macro invocation | = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/parser/doc-comment-in-if-statement.stderr b/src/test/ui/parser/doc-comment-in-if-statement.stderr index be52a0afd4..b7c1847fc7 100644 --- a/src/test/ui/parser/doc-comment-in-if-statement.stderr +++ b/src/test/ui/parser/doc-comment-in-if-statement.stderr @@ -5,6 +5,11 @@ LL | if true /*!*/ {} | ^^^^^ | = note: inner doc comments like this (starting with `//!` or `/*!`) can only appear before items +help: you might have meant to write a regular comment + | +LL - if true /*!*/ {} +LL + if true /**/ {} + | error: outer attributes are not allowed on `if` and `else` branches --> $DIR/doc-comment-in-if-statement.rs:2:13 diff --git a/src/test/ui/parser/expr-as-stmt.fixed b/src/test/ui/parser/expr-as-stmt.fixed index c217ab9774..101959d6da 100644 --- a/src/test/ui/parser/expr-as-stmt.fixed +++ b/src/test/ui/parser/expr-as-stmt.fixed @@ -10,7 +10,7 @@ fn foo() -> i32 { } fn bar() -> i32 { - ({2}) + 2 //~ ERROR expected expression, found `+` + ({2}) + 2 //~ ERROR leading `+` is not supported //~^ ERROR mismatched types } @@ -32,4 +32,9 @@ fn moo(x: u32) -> bool { }) > 0 //~ ERROR expected expression } +fn qux() -> u32 { + ({2}) - 2 //~ ERROR cannot apply unary operator `-` to type `u32` + //~^ ERROR mismatched types +} + fn main() {} diff --git a/src/test/ui/parser/expr-as-stmt.rs b/src/test/ui/parser/expr-as-stmt.rs index b04025faae..45c4f97750 100644 --- a/src/test/ui/parser/expr-as-stmt.rs +++ b/src/test/ui/parser/expr-as-stmt.rs @@ -10,7 +10,7 @@ fn foo() -> i32 { } fn bar() -> i32 { - {2} + 2 //~ ERROR expected expression, found `+` + {2} + 2 //~ ERROR leading `+` is not supported //~^ ERROR mismatched types } @@ -32,4 +32,9 @@ fn moo(x: u32) -> bool { } > 0 //~ ERROR expected expression } +fn qux() -> u32 { + {2} - 2 //~ ERROR cannot apply unary operator `-` to type `u32` + //~^ ERROR mismatched types +} + fn main() {} diff --git a/src/test/ui/parser/expr-as-stmt.stderr b/src/test/ui/parser/expr-as-stmt.stderr index ba5cd01abf..cae775099e 100644 --- a/src/test/ui/parser/expr-as-stmt.stderr +++ b/src/test/ui/parser/expr-as-stmt.stderr @@ -9,11 +9,11 @@ help: parentheses are required to parse this as an expression LL | ({2}) + {2} | + + -error: expected expression, found `+` +error: leading `+` is not supported --> $DIR/expr-as-stmt.rs:13:9 | LL | {2} + 2 - | ^ expected expression + | ^ unexpected `+` | help: parentheses are required to parse this as an expression | @@ -99,7 +99,29 @@ help: parentheses are required to parse this as an expression LL | ({ 3 }) * 3 | + + -error: aborting due to 9 previous errors +error[E0308]: mismatched types + --> $DIR/expr-as-stmt.rs:36:6 + | +LL | {2} - 2 + | ^ expected `()`, found integer + | +help: you might have meant to return this value + | +LL | {return 2;} - 2 + | ++++++ + -Some errors have detailed explanations: E0308, E0614. +error[E0600]: cannot apply unary operator `-` to type `u32` + --> $DIR/expr-as-stmt.rs:36:9 + | +LL | {2} - 2 + | ^^^ cannot apply unary operator `-` + | +help: parentheses are required to parse this as an expression + | +LL | ({2}) - 2 + | + + + +error: aborting due to 11 previous errors + +Some errors have detailed explanations: E0308, E0600, E0614. For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/parser/float-field-interpolated.stderr b/src/test/ui/parser/float-field-interpolated.stderr index 4b03427cd5..664adb3581 100644 --- a/src/test/ui/parser/float-field-interpolated.stderr +++ b/src/test/ui/parser/float-field-interpolated.stderr @@ -5,7 +5,7 @@ LL | { s.$b; } | ^^ ... LL | generate_field_accesses!(1.1, 1.1, 1.1); - | ---------------------------------------- in this macro invocation + | --------------------------------------- in this macro invocation | = note: this error originates in the macro `generate_field_accesses` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -16,7 +16,7 @@ LL | { s.$b; } | ^^ expected one of `.`, `;`, `?`, `}`, or an operator ... LL | generate_field_accesses!(1.1, 1.1, 1.1); - | ---------------------------------------- in this macro invocation + | --------------------------------------- in this macro invocation | = note: this error originates in the macro `generate_field_accesses` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -27,7 +27,7 @@ LL | { s.$c; } | ^^ ... LL | generate_field_accesses!(1.1, 1.1, 1.1); - | ---------------------------------------- in this macro invocation + | --------------------------------------- in this macro invocation | = note: this error originates in the macro `generate_field_accesses` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -38,7 +38,7 @@ LL | { s.$c; } | ^^ expected one of `.`, `;`, `?`, `}`, or an operator ... LL | generate_field_accesses!(1.1, 1.1, 1.1); - | ---------------------------------------- in this macro invocation + | --------------------------------------- in this macro invocation | = note: this error originates in the macro `generate_field_accesses` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/parser/inner-attr-after-doc-comment.stderr b/src/test/ui/parser/inner-attr-after-doc-comment.stderr index c1e9e7a427..404800ee15 100644 --- a/src/test/ui/parser/inner-attr-after-doc-comment.stderr +++ b/src/test/ui/parser/inner-attr-after-doc-comment.stderr @@ -8,8 +8,16 @@ LL | | */ LL | LL | #![recursion_limit="100"] | ^^^^^^^^^^^^^^^^^^^^^^^^^ not permitted following an outer attribute +LL | +LL | fn main() {} + | ------------ the inner attribute doesn't annotate this function | - = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them. + = 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 function, change the attribute from inner to outer style + | +LL - #![recursion_limit="100"] +LL + #[recursion_limit="100"] + | error: aborting due to previous error diff --git a/src/test/ui/parser/inner-attr.stderr b/src/test/ui/parser/inner-attr.stderr index e1bf2cca1c..1adac74590 100644 --- a/src/test/ui/parser/inner-attr.stderr +++ b/src/test/ui/parser/inner-attr.stderr @@ -6,8 +6,15 @@ LL | #[feature(lang_items)] LL | LL | #![recursion_limit="100"] | ^^^^^^^^^^^^^^^^^^^^^^^^^ not permitted following an outer attribute +LL | fn main() {} + | ------------ the inner attribute doesn't annotate this function | - = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them. + = 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 function, change the attribute from inner to outer style + | +LL - #![recursion_limit="100"] +LL + #[recursion_limit="100"] + | error: aborting due to previous error diff --git a/src/test/ui/parser/inverted-parameters.stderr b/src/test/ui/parser/inverted-parameters.stderr index d1a249389f..8662277820 100644 --- a/src/test/ui/parser/inverted-parameters.stderr +++ b/src/test/ui/parser/inverted-parameters.stderr @@ -38,15 +38,15 @@ LL | fn fizz(i32) {} help: if this is a `self` type, give it a parameter name | LL | fn fizz(self: i32) {} - | ~~~~~~~~~ + | +++++ help: if this is a parameter name, give it a type | LL | fn fizz(i32: TypeName) {} - | ~~~~~~~~~~~~~ + | ++++++++++ help: if this is a type, explicitly ignore the parameter name | LL | fn fizz(_: i32) {} - | ~~~~~~ + | ++ error: expected one of `:`, `@`, or `|`, found `S` --> $DIR/inverted-parameters.rs:27:23 diff --git a/src/test/ui/parser/issue-30318.fixed b/src/test/ui/parser/issue-30318.fixed new file mode 100644 index 0000000000..71fc82172a --- /dev/null +++ b/src/test/ui/parser/issue-30318.fixed @@ -0,0 +1,27 @@ +// run-rustfix +#![allow(unused)] +fn foo() { } + +/// Misplaced comment... +//~^ ERROR expected outer doc comment +fn bar() { } //~ NOTE the inner doc comment doesn't annotate this function + +#[test] //~ ERROR an inner attribute is not permitted in this context +fn baz() { } //~ NOTE the inner attribute doesn't annotate this function +//~^^ NOTE inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually + +/** Misplaced comment... */ +//~^ ERROR expected outer doc comment +fn bat() { } //~ NOTE the inner doc comment doesn't annotate this function + +fn main() { } + +// Misplaced comment... +//~^ ERROR expected outer doc comment +//~| NOTE inner doc comments like this (starting with `//!` or `/*!`) can only appear before items +//~| NOTE other attributes here +/* Misplaced comment... */ +//~^ ERROR expected outer doc comment +//~| NOTE this doc comment doesn't document anything +//~| ERROR expected item after doc comment +//~| NOTE inner doc comments like this (starting with `//!` or `/*!`) can only appear before items diff --git a/src/test/ui/parser/issue-30318.rs b/src/test/ui/parser/issue-30318.rs index 38e30de716..465dca2ff8 100644 --- a/src/test/ui/parser/issue-30318.rs +++ b/src/test/ui/parser/issue-30318.rs @@ -1,7 +1,27 @@ +// run-rustfix +#![allow(unused)] fn foo() { } //! Misplaced comment... //~^ ERROR expected outer doc comment -//~| NOTE inner doc comments like this (starting with `//!` or `/*!`) can only appear before items +fn bar() { } //~ NOTE the inner doc comment doesn't annotate this function + +#![test] //~ ERROR an inner attribute is not permitted in this context +fn baz() { } //~ NOTE the inner attribute doesn't annotate this function +//~^^ NOTE inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually + +/*! Misplaced comment... */ +//~^ ERROR expected outer doc comment +fn bat() { } //~ NOTE the inner doc comment doesn't annotate this function fn main() { } + +//! Misplaced comment... +//~^ ERROR expected outer doc comment +//~| NOTE inner doc comments like this (starting with `//!` or `/*!`) can only appear before items +//~| NOTE other attributes here +/*! Misplaced comment... */ +//~^ ERROR expected outer doc comment +//~| NOTE this doc comment doesn't document anything +//~| ERROR expected item after doc comment +//~| NOTE inner doc comments like this (starting with `//!` or `/*!`) can only appear before items diff --git a/src/test/ui/parser/issue-30318.stderr b/src/test/ui/parser/issue-30318.stderr index b3a27f1985..7e71088455 100644 --- a/src/test/ui/parser/issue-30318.stderr +++ b/src/test/ui/parser/issue-30318.stderr @@ -1,11 +1,81 @@ error[E0753]: expected outer doc comment - --> $DIR/issue-30318.rs:3:1 + --> $DIR/issue-30318.rs:5:1 + | +LL | //! Misplaced comment... + | ^^^^^^^^^^^^^^^^^^^^^^^^ +LL | +LL | fn bar() { } + | ------------ the inner doc comment doesn't annotate this function + | +help: to annotate the function, change the doc comment from inner to outer style + | +LL | /// Misplaced comment... + | ~ + +error: an inner attribute is not permitted in this context + --> $DIR/issue-30318.rs:9:1 + | +LL | #![test] + | ^^^^^^^^ +LL | fn baz() { } + | ------------ the inner attribute doesn't annotate this function + | + = 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 function, change the attribute from inner to outer style + | +LL - #![test] +LL + #[test] + | + +error[E0753]: expected outer doc comment + --> $DIR/issue-30318.rs:13:1 + | +LL | /*! Misplaced comment... */ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | +LL | fn bat() { } + | ------------ the inner doc comment doesn't annotate this function + | +help: to annotate the function, change the doc comment from inner to outer style + | +LL | /** Misplaced comment... */ + | ~ + +error[E0753]: expected outer doc comment + --> $DIR/issue-30318.rs:19:1 | LL | //! Misplaced comment... | ^^^^^^^^^^^^^^^^^^^^^^^^ | = note: inner doc comments like this (starting with `//!` or `/*!`) can only appear before items +help: you might have meant to write a regular comment + | +LL - //! Misplaced comment... +LL + // Misplaced comment... + | -error: aborting due to previous error +error[E0753]: expected outer doc comment + --> $DIR/issue-30318.rs:23:1 + | +LL | /*! Misplaced comment... */ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: inner doc comments like this (starting with `//!` or `/*!`) can only appear before items +help: you might have meant to write a regular comment + | +LL - /*! Misplaced comment... */ +LL + /* Misplaced comment... */ + | + +error: expected item after doc comment + --> $DIR/issue-30318.rs:23:1 + | +LL | //! Misplaced comment... + | ------------------------ other attributes here +... +LL | /*! Misplaced comment... */ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ this doc comment doesn't document anything + +error: aborting due to 6 previous errors For more information about this error, try `rustc --explain E0753`. diff --git a/src/test/ui/parser/issue-44406.rs b/src/test/ui/parser/issue-44406.rs index 83bbf884a4..a5b7e83a01 100644 --- a/src/test/ui/parser/issue-44406.rs +++ b/src/test/ui/parser/issue-44406.rs @@ -1,10 +1,10 @@ macro_rules! foo { ($rest: tt) => { - bar(baz: $rest) + bar(baz: $rest) //~ ERROR invalid `struct` delimiters or `fn` call arguments } } fn main() { - foo!(true); //~ ERROR expected type, found keyword + foo!(true); //~^ ERROR expected identifier, found keyword } diff --git a/src/test/ui/parser/issue-44406.stderr b/src/test/ui/parser/issue-44406.stderr index 372387131e..61419040b3 100644 --- a/src/test/ui/parser/issue-44406.stderr +++ b/src/test/ui/parser/issue-44406.stderr @@ -9,17 +9,25 @@ help: you can escape reserved keywords to use them as identifiers LL | foo!(r#true); | ~~~~~~ -error: expected type, found keyword `true` - --> $DIR/issue-44406.rs:8:10 +error: invalid `struct` delimiters or `fn` call arguments + --> $DIR/issue-44406.rs:3:9 | LL | bar(baz: $rest) - | - help: try using a semicolon: `;` + | ^^^^^^^^^^^^^^^ ... LL | foo!(true); - | ^^^^ expected type + | ---------- in this macro invocation | - = note: `#![feature(type_ascription)]` lets you annotate an expression with a type: `: ` - = note: see issue #23416 for more information + = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) +help: if `bar` is a struct, use braces as delimiters + | +LL | bar { } + | ~ +help: if `bar` is a function, use the arguments directly + | +LL - bar(baz: $rest) +LL + bar(: $rest) + | error: aborting due to 2 previous errors diff --git a/src/test/ui/parser/issue-45296.rs b/src/test/ui/parser/issue-45296.rs index f242c1d293..d3a97e89f9 100644 --- a/src/test/ui/parser/issue-45296.rs +++ b/src/test/ui/parser/issue-45296.rs @@ -2,4 +2,5 @@ fn main() { let unused = (); #![allow(unused_variables)] //~ ERROR not permitted in this context + fn foo() {} } diff --git a/src/test/ui/parser/issue-45296.stderr b/src/test/ui/parser/issue-45296.stderr index c0d4ce1243..6abe266d4e 100644 --- a/src/test/ui/parser/issue-45296.stderr +++ b/src/test/ui/parser/issue-45296.stderr @@ -3,8 +3,15 @@ error: an inner attribute is not permitted in this context | LL | #![allow(unused_variables)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | fn foo() {} + | ----------- the inner attribute doesn't annotate this function | - = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them. + = 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 function, change the attribute from inner to outer style + | +LL - #![allow(unused_variables)] +LL + #[allow(unused_variables)] + | error: aborting due to previous error diff --git a/src/test/ui/parser/issue-48137-macros-cannot-interpolate-impl-items-bad-variants.stderr b/src/test/ui/parser/issue-48137-macros-cannot-interpolate-impl-items-bad-variants.stderr index 0ab718d8bd..fdef8ff6df 100644 --- a/src/test/ui/parser/issue-48137-macros-cannot-interpolate-impl-items-bad-variants.stderr +++ b/src/test/ui/parser/issue-48137-macros-cannot-interpolate-impl-items-bad-variants.stderr @@ -13,7 +13,7 @@ LL | enum BadE {} | ^^^^^^^^^ ... LL | expand_to_enum!(); - | ------------------ in this macro invocation + | ----------------- in this macro invocation | = help: consider moving the enum out to a nearby module scope = note: this error originates in the macro `expand_to_enum` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -33,7 +33,7 @@ LL | enum BadE {} | ^^^^^^^^^ ... LL | expand_to_enum!(); - | ------------------ in this macro invocation + | ----------------- in this macro invocation | = help: consider moving the enum out to a nearby module scope = note: this error originates in the macro `expand_to_enum` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -53,7 +53,7 @@ LL | enum BadE {} | ^^^^^^^^^ ... LL | expand_to_enum!(); - | ------------------ in this macro invocation + | ----------------- in this macro invocation | = help: consider moving the enum out to a nearby module scope = note: this error originates in the macro `expand_to_enum` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/parser/issue-73568-lifetime-after-mut.stderr b/src/test/ui/parser/issue-73568-lifetime-after-mut.stderr index 6f26f36e76..48c2b2a19d 100644 --- a/src/test/ui/parser/issue-73568-lifetime-after-mut.stderr +++ b/src/test/ui/parser/issue-73568-lifetime-after-mut.stderr @@ -17,7 +17,7 @@ LL | fn w<$lt>(w: &mut $lt i32) {} | ^^^^^^^^ help: place the lifetime before `mut`: `&$lt mut` ... LL | mac!('a); - | --------- in this macro invocation + | -------- in this macro invocation | = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/parser/issue-87812-path.stderr b/src/test/ui/parser/issue-87812-path.stderr index 0c8e6fdd30..f8ee051753 100644 --- a/src/test/ui/parser/issue-87812-path.stderr +++ b/src/test/ui/parser/issue-87812-path.stderr @@ -7,7 +7,7 @@ LL | let _: usize = $f; | expected due to this ... LL | foo!(Baz); - | ---------- in this macro invocation + | --------- in this macro invocation | = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/parser/issue-88276-unary-plus.fixed b/src/test/ui/parser/issue-88276-unary-plus.fixed new file mode 100644 index 0000000000..25b7c340f6 --- /dev/null +++ b/src/test/ui/parser/issue-88276-unary-plus.fixed @@ -0,0 +1,8 @@ +// run-rustfix +#[allow(unused_parens)] +fn main() { + let _ = 1; //~ ERROR leading `+` is not supported + let _ = (1.0 + 2.0) * 3.0; //~ ERROR leading `+` is not supported + //~| ERROR leading `+` is not supported + let _ = [3, 4+6]; //~ ERROR leading `+` is not supported +} diff --git a/src/test/ui/parser/issue-88276-unary-plus.rs b/src/test/ui/parser/issue-88276-unary-plus.rs new file mode 100644 index 0000000000..11b2e9d601 --- /dev/null +++ b/src/test/ui/parser/issue-88276-unary-plus.rs @@ -0,0 +1,8 @@ +// run-rustfix +#[allow(unused_parens)] +fn main() { + let _ = +1; //~ ERROR leading `+` is not supported + let _ = (1.0 + +2.0) * +3.0; //~ ERROR leading `+` is not supported + //~| ERROR leading `+` is not supported + let _ = [+3, 4+6]; //~ ERROR leading `+` is not supported +} diff --git a/src/test/ui/parser/issue-88276-unary-plus.stderr b/src/test/ui/parser/issue-88276-unary-plus.stderr new file mode 100644 index 0000000000..b26761729a --- /dev/null +++ b/src/test/ui/parser/issue-88276-unary-plus.stderr @@ -0,0 +1,50 @@ +error: leading `+` is not supported + --> $DIR/issue-88276-unary-plus.rs:4:13 + | +LL | let _ = +1; + | ^ unexpected `+` + | +help: try removing the `+` + | +LL - let _ = +1; +LL + let _ = 1; + | + +error: leading `+` is not supported + --> $DIR/issue-88276-unary-plus.rs:5:20 + | +LL | let _ = (1.0 + +2.0) * +3.0; + | ^ unexpected `+` + | +help: try removing the `+` + | +LL - let _ = (1.0 + +2.0) * +3.0; +LL + let _ = (1.0 + 2.0) * +3.0; + | + +error: leading `+` is not supported + --> $DIR/issue-88276-unary-plus.rs:5:28 + | +LL | let _ = (1.0 + +2.0) * +3.0; + | ^ unexpected `+` + | +help: try removing the `+` + | +LL - let _ = (1.0 + +2.0) * +3.0; +LL + let _ = (1.0 + +2.0) * 3.0; + | + +error: leading `+` is not supported + --> $DIR/issue-88276-unary-plus.rs:7:14 + | +LL | let _ = [+3, 4+6]; + | ^ unexpected `+` + | +help: try removing the `+` + | +LL - let _ = [+3, 4+6]; +LL + let _ = [3, 4+6]; + | + +error: aborting due to 4 previous errors + diff --git a/src/test/ui/parser/issue-88770.rs b/src/test/ui/parser/issue-88770.rs new file mode 100644 index 0000000000..bf89033f56 --- /dev/null +++ b/src/test/ui/parser/issue-88770.rs @@ -0,0 +1,11 @@ +// Regression test for the ICE described in #88770. + +// error-pattern:this file contains an unclosed delimiter +// error-pattern:expected one of +// error-pattern:missing `in` in `for` loop +// error-pattern:expected `;`, found `e` + +fn m(){print!("",(c for&g +u +e +e diff --git a/src/test/ui/parser/issue-88770.stderr b/src/test/ui/parser/issue-88770.stderr new file mode 100644 index 0000000000..c7e24155d1 --- /dev/null +++ b/src/test/ui/parser/issue-88770.stderr @@ -0,0 +1,66 @@ +error: this file contains an unclosed delimiter + --> $DIR/issue-88770.rs:11:3 + | +LL | fn m(){print!("",(c for&g + | - - - unclosed delimiter + | | | + | | unclosed delimiter + | unclosed delimiter +... +LL | e + | ^ + +error: this file contains an unclosed delimiter + --> $DIR/issue-88770.rs:11:3 + | +LL | fn m(){print!("",(c for&g + | - - - unclosed delimiter + | | | + | | unclosed delimiter + | unclosed delimiter +... +LL | e + | ^ + +error: this file contains an unclosed delimiter + --> $DIR/issue-88770.rs:11:3 + | +LL | fn m(){print!("",(c for&g + | - - - unclosed delimiter + | | | + | | unclosed delimiter + | unclosed delimiter +... +LL | e + | ^ + +error: missing `in` in `for` loop + --> $DIR/issue-88770.rs:8:26 + | +LL | fn m(){print!("",(c for&g + | __________________________^ +LL | | u + | |_ help: try adding `in` here + +error: expected one of `!`, `)`, `,`, `.`, `::`, `?`, `{`, or an operator, found keyword `for` + --> $DIR/issue-88770.rs:8:21 + | +LL | fn m(){print!("",(c for&g + | ^^^ expected one of 8 possible tokens + +error: expected `;`, found `e` + --> $DIR/issue-88770.rs:10:2 + | +LL | e + | ^ help: add `;` here +LL | e + | - unexpected token + +error: expected one of `!`, `,`, `.`, `::`, `?`, `{`, or an operator, found `)` + --> $DIR/issue-88770.rs:11:3 + | +LL | e + | ^ expected one of 7 possible tokens + +error: aborting due to 7 previous errors + diff --git a/src/test/ui/parser/issue-88818.rs b/src/test/ui/parser/issue-88818.rs new file mode 100644 index 0000000000..b9233ca833 --- /dev/null +++ b/src/test/ui/parser/issue-88818.rs @@ -0,0 +1,10 @@ +// Regression test for #88818 (improve error message for missing trait +// in `impl for X`). + +struct S { } +impl for S { } +//~^ ERROR: missing trait in a trait impl +//~| HELP: add a trait here +//~| HELP: for an inherent impl, drop this `for` + +fn main() {} diff --git a/src/test/ui/parser/issue-88818.stderr b/src/test/ui/parser/issue-88818.stderr new file mode 100644 index 0000000000..d30990ae58 --- /dev/null +++ b/src/test/ui/parser/issue-88818.stderr @@ -0,0 +1,18 @@ +error: missing trait in a trait impl + --> $DIR/issue-88818.rs:5:5 + | +LL | impl for S { } + | ^ + | +help: add a trait here + | +LL | impl Trait for S { } + | +++++ +help: for an inherent impl, drop this `for` + | +LL - impl for S { } +LL + impl S { } + | + +error: aborting due to previous error + diff --git a/src/test/ui/parser/issue-89388.rs b/src/test/ui/parser/issue-89388.rs new file mode 100644 index 0000000000..9153c071e8 --- /dev/null +++ b/src/test/ui/parser/issue-89388.rs @@ -0,0 +1,7 @@ +// Regression test for #89388. + +fn main() { + let option: Option<&[u8]> = Some(b"..."); + let _ = option.map([_]::to_vec); + //~^ ERROR: missing angle brackets in associated item path +} diff --git a/src/test/ui/parser/issue-89388.stderr b/src/test/ui/parser/issue-89388.stderr new file mode 100644 index 0000000000..cf28bef0f4 --- /dev/null +++ b/src/test/ui/parser/issue-89388.stderr @@ -0,0 +1,8 @@ +error: missing angle brackets in associated item path + --> $DIR/issue-89388.rs:5:24 + | +LL | let _ = option.map([_]::to_vec); + | ^^^^^^^^^^^ help: try: `<[_]>::to_vec` + +error: aborting due to previous error + diff --git a/src/test/ui/parser/issue-89396.fixed b/src/test/ui/parser/issue-89396.fixed new file mode 100644 index 0000000000..823ad8cd1f --- /dev/null +++ b/src/test/ui/parser/issue-89396.fixed @@ -0,0 +1,16 @@ +// Regression test for issue #89396: Try to recover from a +// `=>` -> `=` or `->` typo in a match arm. + +// run-rustfix + +fn main() { + let opt = Some(42); + let _ = match opt { + Some(_) => true, + //~^ ERROR: expected one of + //~| HELP: try using a fat arrow here + None => false, + //~^ ERROR: expected one of + //~| HELP: try using a fat arrow here + }; +} diff --git a/src/test/ui/parser/issue-89396.rs b/src/test/ui/parser/issue-89396.rs new file mode 100644 index 0000000000..f1d9efa524 --- /dev/null +++ b/src/test/ui/parser/issue-89396.rs @@ -0,0 +1,16 @@ +// Regression test for issue #89396: Try to recover from a +// `=>` -> `=` or `->` typo in a match arm. + +// run-rustfix + +fn main() { + let opt = Some(42); + let _ = match opt { + Some(_) = true, + //~^ ERROR: expected one of + //~| HELP: try using a fat arrow here + None -> false, + //~^ ERROR: expected one of + //~| HELP: try using a fat arrow here + }; +} diff --git a/src/test/ui/parser/issue-89396.stderr b/src/test/ui/parser/issue-89396.stderr new file mode 100644 index 0000000000..504420574e --- /dev/null +++ b/src/test/ui/parser/issue-89396.stderr @@ -0,0 +1,20 @@ +error: expected one of `=>`, `if`, or `|`, found `=` + --> $DIR/issue-89396.rs:9:17 + | +LL | Some(_) = true, + | ^ + | | + | expected one of `=>`, `if`, or `|` + | help: try using a fat arrow here: `=>` + +error: expected one of `=>`, `@`, `if`, or `|`, found `->` + --> $DIR/issue-89396.rs:12:14 + | +LL | None -> false, + | ^^ + | | + | expected one of `=>`, `@`, `if`, or `|` + | help: try using a fat arrow here: `=>` + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/parser/labeled-no-colon-expr.stderr b/src/test/ui/parser/labeled-no-colon-expr.stderr index 50995895bc..26884dc5d7 100644 --- a/src/test/ui/parser/labeled-no-colon-expr.stderr +++ b/src/test/ui/parser/labeled-no-colon-expr.stderr @@ -68,7 +68,7 @@ LL | 'l5 $b; | the `block` fragment is within this context ... LL | m!({}); - | ------- in this macro invocation + | ------ in this macro invocation | = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/parser/lifetime-in-pattern.stderr b/src/test/ui/parser/lifetime-in-pattern.stderr index bf73595e5b..a1d721e746 100644 --- a/src/test/ui/parser/lifetime-in-pattern.stderr +++ b/src/test/ui/parser/lifetime-in-pattern.stderr @@ -13,16 +13,16 @@ LL | fn test(&'a str) { = note: anonymous parameters are removed in the 2018 edition (see RFC 1685) help: if this is a `self` type, give it a parameter name | -LL | fn test(self: &str) { - | ~~~~~~~~~~ +LL | fn test(self: &'a str) { + | +++++ help: if this is a parameter name, give it a type | LL | fn test(str: &TypeName) { | ~~~~~~~~~~~~~~ help: if this is a type, explicitly ignore the parameter name | -LL | fn test(_: &str) { - | ~~~~~~~ +LL | fn test(_: &'a str) { + | ++ error: aborting due to 2 previous errors diff --git a/src/test/ui/parser/macro-braces-dot-question.rs b/src/test/ui/parser/macro-braces-dot-question.rs new file mode 100644 index 0000000000..016b434a61 --- /dev/null +++ b/src/test/ui/parser/macro-braces-dot-question.rs @@ -0,0 +1,11 @@ +// check-pass + +use std::io::Write; + +fn main() -> Result<(), std::io::Error> { + vec! { 1, 2, 3 }.len(); + write! { vec![], "" }?; + println!{""} + [0]; // separate statement, not indexing into the result of println. + Ok(()) +} diff --git a/src/test/ui/parser/macro/issue-37113.stderr b/src/test/ui/parser/macro/issue-37113.stderr index f9f53e65d7..0912858ddc 100644 --- a/src/test/ui/parser/macro/issue-37113.stderr +++ b/src/test/ui/parser/macro/issue-37113.stderr @@ -5,7 +5,7 @@ LL | $( $t, )* | ^^ expected identifier ... LL | test_macro!(String,); - | --------------------- in this macro invocation + | -------------------- in this macro invocation | = note: this error originates in the macro `test_macro` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/parser/macro/issue-37234.stderr b/src/test/ui/parser/macro/issue-37234.stderr index 8d9636d401..d791962044 100644 --- a/src/test/ui/parser/macro/issue-37234.stderr +++ b/src/test/ui/parser/macro/issue-37234.stderr @@ -5,7 +5,7 @@ LL | let x = 5 ""; | ^^ expected one of `.`, `;`, `?`, `else`, or an operator ... LL | failed!(); - | ---------- in this macro invocation + | --------- in this macro invocation | = note: this error originates in the macro `failed` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/parser/macro/macro-incomplete-parse.stderr b/src/test/ui/parser/macro/macro-incomplete-parse.stderr index 186b22dce9..707417b725 100644 --- a/src/test/ui/parser/macro/macro-incomplete-parse.stderr +++ b/src/test/ui/parser/macro/macro-incomplete-parse.stderr @@ -5,7 +5,7 @@ LL | , | ^ ... LL | ignored_item!(); - | ---------------- caused by the macro expansion here + | --------------- caused by the macro expansion here | = note: the usage of `ignored_item!` is likely invalid in item context @@ -16,7 +16,7 @@ LL | () => ( 1, | ^ expected one of `.`, `;`, `?`, `}`, or an operator ... LL | ignored_expr!(); - | ---------------- in this macro invocation + | --------------- in this macro invocation | = note: this error originates in the macro `ignored_expr` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/parser/macro/pub-item-macro.stderr b/src/test/ui/parser/macro/pub-item-macro.stderr index 0b81d2074b..4f82acf38e 100644 --- a/src/test/ui/parser/macro/pub-item-macro.stderr +++ b/src/test/ui/parser/macro/pub-item-macro.stderr @@ -5,7 +5,7 @@ LL | pub priv_x!(); | ^^^ help: remove the visibility ... LL | pub_x!(); - | --------- in this macro invocation + | -------- in this macro invocation | = help: try adjusting the macro to put `pub` inside the invocation = note: this error originates in the macro `pub_x` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -23,7 +23,7 @@ LL | static x: u32 = 0; | ^^^^^^^^^^^^^^^^^^ ... LL | pub_x!(); - | --------- in this macro invocation + | -------- in this macro invocation = note: this error originates in the macro `priv_x` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 2 previous errors diff --git a/src/test/ui/parser/macro/trait-non-item-macros.stderr b/src/test/ui/parser/macro/trait-non-item-macros.stderr index 35e5bfe62f..db20e6b24a 100644 --- a/src/test/ui/parser/macro/trait-non-item-macros.stderr +++ b/src/test/ui/parser/macro/trait-non-item-macros.stderr @@ -5,7 +5,7 @@ LL | $a | ^^ ... LL | bah!(2); - | -------- caused by the macro expansion here + | ------- caused by the macro expansion here | = note: the usage of `bah!` is likely invalid in trait item context diff --git a/src/test/ui/parser/missing-semicolon.stderr b/src/test/ui/parser/missing-semicolon.stderr index 72f76b6fe3..e0d5e84ec3 100644 --- a/src/test/ui/parser/missing-semicolon.stderr +++ b/src/test/ui/parser/missing-semicolon.stderr @@ -5,7 +5,7 @@ LL | $( let x = $e1 )*; | ^^^ expected one of `.`, `;`, `?`, `else`, or an operator ... LL | fn main() { m!(0, 0; 0, 0); } - | --------------- in this macro invocation + | -------------- in this macro invocation | = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/parser/mut-patterns.stderr b/src/test/ui/parser/mut-patterns.stderr index bfa443a7f0..59dba4ae21 100644 --- a/src/test/ui/parser/mut-patterns.stderr +++ b/src/test/ui/parser/mut-patterns.stderr @@ -106,7 +106,7 @@ LL | let mut $p = 0; | ^^ expected identifier ... LL | foo!(x); - | -------- in this macro invocation + | ------- in this macro invocation | = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/parser/omitted-arg-in-item-fn.stderr b/src/test/ui/parser/omitted-arg-in-item-fn.stderr index 329fa8776f..ce2eab051a 100644 --- a/src/test/ui/parser/omitted-arg-in-item-fn.stderr +++ b/src/test/ui/parser/omitted-arg-in-item-fn.stderr @@ -8,15 +8,15 @@ LL | fn foo(x) { help: if this is a `self` type, give it a parameter name | LL | fn foo(self: x) { - | ~~~~~~~ + | +++++ help: if this is a parameter name, give it a type | LL | fn foo(x: TypeName) { - | ~~~~~~~~~~~ + | ++++++++++ help: if this is a type, explicitly ignore the parameter name | LL | fn foo(_: x) { - | ~~~~ + | ++ error: aborting due to previous error diff --git a/src/test/ui/parser/pat-lt-bracket-2.stderr b/src/test/ui/parser/pat-lt-bracket-2.stderr index 762733cc97..c78f96e1ad 100644 --- a/src/test/ui/parser/pat-lt-bracket-2.stderr +++ b/src/test/ui/parser/pat-lt-bracket-2.stderr @@ -8,11 +8,11 @@ LL | fn a(B<) {} help: if this is a `self` type, give it a parameter name | LL | fn a(self: B<) {} - | ~~~~~~~ + | +++++ help: if this is a type, explicitly ignore the parameter name | LL | fn a(_: B<) {} - | ~~~~ + | ++ error: aborting due to previous error 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 779e164634..8080dbc332 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 closing `)` + //~| ERROR unexpected parenthesis 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 e97cf544ac..2199134832 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,14 +4,17 @@ error: expected one of `)`, `,`, `@`, or `|`, found keyword `in` LL | for ( elem in vec ) { | ^^ expected one of `)`, `,`, `@`, or `|` -error: unexpected closing `)` - --> $DIR/recover-for-loop-parens-around-head.rs:10:23 +error: unexpected parenthesis surrounding `for` loop head + --> $DIR/recover-for-loop-parens-around-head.rs:10:9 | LL | for ( elem in vec ) { - | --------------^ - | | - | opening `(` - | help: remove parenthesis in `for` loop: `elem in vec` + | ^ ^ + | +help: remove parenthesis in `for` loop + | +LL - for ( elem in vec ) { +LL + for elem in vec { + | error[E0308]: mismatched types --> $DIR/recover-for-loop-parens-around-head.rs:13:38 diff --git a/src/test/ui/parser/recover-from-bad-variant.rs b/src/test/ui/parser/recover-from-bad-variant.rs index 1bcef450bb..e8887147cb 100644 --- a/src/test/ui/parser/recover-from-bad-variant.rs +++ b/src/test/ui/parser/recover-from-bad-variant.rs @@ -5,7 +5,7 @@ enum Enum { fn main() { let x = Enum::Foo(a: 3, b: 4); - //~^ ERROR expected type, found `3` + //~^ ERROR invalid `struct` delimiters or `fn` call arguments match x { Enum::Foo(a, b) => {} //~^ ERROR expected tuple struct or tuple variant, found struct variant `Enum::Foo` diff --git a/src/test/ui/parser/recover-from-bad-variant.stderr b/src/test/ui/parser/recover-from-bad-variant.stderr index 61ea3695ee..8cb71069bd 100644 --- a/src/test/ui/parser/recover-from-bad-variant.stderr +++ b/src/test/ui/parser/recover-from-bad-variant.stderr @@ -1,13 +1,18 @@ -error: expected type, found `3` - --> $DIR/recover-from-bad-variant.rs:7:26 +error: invalid `struct` delimiters or `fn` call arguments + --> $DIR/recover-from-bad-variant.rs:7:13 | LL | let x = Enum::Foo(a: 3, b: 4); - | - ^ expected type - | | - | tried to parse a type due to this type ascription + | ^^^^^^^^^^^^^^^^^^^^^ | - = note: `#![feature(type_ascription)]` lets you annotate an expression with a type: `: ` - = note: see issue #23416 for more information +help: if `Enum::Foo` is a struct, use braces as delimiters + | +LL | let x = Enum::Foo { a: 3, b: 4 }; + | ~ ~ +help: if `Enum::Foo` is a function, use the arguments directly + | +LL - let x = Enum::Foo(a: 3, b: 4); +LL + let x = Enum::Foo(3, 4); + | error[E0532]: expected tuple struct or tuple variant, found struct variant `Enum::Foo` --> $DIR/recover-from-bad-variant.rs:10:9 diff --git a/src/test/ui/parser/recover-range-pats.stderr b/src/test/ui/parser/recover-range-pats.stderr index 762066825d..9296ad2e33 100644 --- a/src/test/ui/parser/recover-range-pats.stderr +++ b/src/test/ui/parser/recover-range-pats.stderr @@ -165,7 +165,7 @@ LL | let ...$e; | ^^^ help: use `..=` instead ... LL | mac!(0); - | -------- in this macro invocation + | ------- in this macro invocation | = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -176,7 +176,7 @@ LL | let $e...; | ^^^ help: use `..` instead ... LL | mac!(0); - | -------- in this macro invocation + | ------- in this macro invocation | = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -188,7 +188,7 @@ LL | let $e..=; | ^^^ help: use `..` instead ... LL | mac!(0); - | -------- in this macro invocation + | ------- in this macro invocation | = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -277,7 +277,7 @@ LL | let $e1...$e2; | ^^^ help: use `..=` for an inclusive range ... LL | mac2!(0, 1); - | ------------ in this macro invocation + | ----------- in this macro invocation | = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see diff --git a/src/test/ui/parser/stmt_expr_attrs_placement.stderr b/src/test/ui/parser/stmt_expr_attrs_placement.stderr index 808903d9c6..bf4005698a 100644 --- a/src/test/ui/parser/stmt_expr_attrs_placement.stderr +++ b/src/test/ui/parser/stmt_expr_attrs_placement.stderr @@ -4,7 +4,8 @@ error: an inner attribute is not permitted in this context LL | let a = #![allow(warnings)] (1, 2); | ^^^^^^^^^^^^^^^^^^^ | - = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them. + = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files + = note: outer attributes, like `#[test]`, annotate the item following them error: an inner attribute is not permitted in this context --> $DIR/stmt_expr_attrs_placement.rs:10:14 @@ -12,7 +13,8 @@ error: an inner attribute is not permitted in this context LL | let b = (#![allow(warnings)] 1, 2); | ^^^^^^^^^^^^^^^^^^^ | - = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them. + = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files + = note: outer attributes, like `#[test]`, annotate the item following them error: an inner attribute is not permitted in this context --> $DIR/stmt_expr_attrs_placement.rs:15:10 @@ -20,7 +22,8 @@ error: an inner attribute is not permitted in this context LL | (#![allow(warnings)] 1, 2) | ^^^^^^^^^^^^^^^^^^^ | - = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them. + = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files + = note: outer attributes, like `#[test]`, annotate the item following them error: an inner attribute is not permitted in this context --> $DIR/stmt_expr_attrs_placement.rs:21:18 @@ -28,7 +31,8 @@ error: an inner attribute is not permitted in this context LL | let e = (#![allow(warnings)] 1, 2); | ^^^^^^^^^^^^^^^^^^^ | - = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them. + = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files + = note: outer attributes, like `#[test]`, annotate the item following them error: an inner attribute is not permitted in this context --> $DIR/stmt_expr_attrs_placement.rs:26:14 @@ -36,7 +40,8 @@ error: an inner attribute is not permitted in this context LL | let e = [#![allow(warnings)] 1, 2]; | ^^^^^^^^^^^^^^^^^^^ | - = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them. + = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files + = note: outer attributes, like `#[test]`, annotate the item following them error: an inner attribute is not permitted in this context --> $DIR/stmt_expr_attrs_placement.rs:29:14 @@ -44,7 +49,8 @@ error: an inner attribute is not permitted in this context LL | let f = [#![allow(warnings)] 1; 0]; | ^^^^^^^^^^^^^^^^^^^ | - = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them. + = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files + = note: outer attributes, like `#[test]`, annotate the item following them error: an inner attribute is not permitted in this context --> $DIR/stmt_expr_attrs_placement.rs:36:24 @@ -52,7 +58,8 @@ error: an inner attribute is not permitted in this context LL | let h = MyStruct { #![allow(warnings)] field: 0 }; | ^^^^^^^^^^^^^^^^^^^ | - = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them. + = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files + = note: outer attributes, like `#[test]`, annotate the item following them error: aborting due to 7 previous errors diff --git a/src/test/ui/parser/trailing-plus-in-bounds.rs b/src/test/ui/parser/trailing-plus-in-bounds.rs index 33c30d7310..61819cabdf 100644 --- a/src/test/ui/parser/trailing-plus-in-bounds.rs +++ b/src/test/ui/parser/trailing-plus-in-bounds.rs @@ -1,10 +1,9 @@ // build-pass (FIXME(62277): could be check-pass?) -#![feature(box_syntax)] #![allow(bare_trait_objects)] use std::fmt::Debug; fn main() { - let x: Box = box 3 as Box; // Trailing `+` is OK + let x: Box = Box::new(3) as Box; // Trailing `+` is OK } diff --git a/src/test/ui/parser/trait-object-delimiters.stderr b/src/test/ui/parser/trait-object-delimiters.stderr index ee638d8a4f..75eeeda864 100644 --- a/src/test/ui/parser/trait-object-delimiters.stderr +++ b/src/test/ui/parser/trait-object-delimiters.stderr @@ -52,7 +52,7 @@ LL | fn foo1(_: &dyn Drop + AsRef) {} | | | first non-auto trait | - = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Drop + AsRef {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Drop + AsRef {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error[E0224]: at least one trait is required for an object type @@ -69,7 +69,7 @@ LL | fn foo5(_: &(dyn Drop + dyn AsRef)) {} | | | first non-auto trait | - = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Drop + AsRef {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Drop + AsRef {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error: aborting due to 9 previous errors diff --git a/src/test/ui/parser/trait-object-trait-parens.stderr b/src/test/ui/parser/trait-object-trait-parens.stderr index b39fe4646a..657288c70f 100644 --- a/src/test/ui/parser/trait-object-trait-parens.stderr +++ b/src/test/ui/parser/trait-object-trait-parens.stderr @@ -52,7 +52,7 @@ LL | let _: Box<(Obj) + (?Sized) + (for<'a> Trait<'a>)>; | | | first non-auto trait | - = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Obj + for<'a> Trait<'a> {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + for<'a> Trait<'a> {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error[E0225]: only auto traits can be used as additional traits in a trait object @@ -63,7 +63,7 @@ LL | let _: Box Trait<'a>) + (Obj)>; | | | first non-auto trait | - = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: for<'a> Trait<'a> + Obj {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: for<'a> Trait<'a> + Obj {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error[E0225]: only auto traits can be used as additional traits in a trait object @@ -74,7 +74,7 @@ LL | let _: Box Trait<'a> + (Obj) + (?Sized)>; | | | first non-auto trait | - = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: for<'a> Trait<'a> + Obj {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: for<'a> Trait<'a> + Obj {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error: aborting due to 6 previous errors; 3 warnings emitted diff --git a/src/test/ui/parser/unicode-character-literal.fixed b/src/test/ui/parser/unicode-character-literal.fixed new file mode 100644 index 0000000000..26ef5ffa11 --- /dev/null +++ b/src/test/ui/parser/unicode-character-literal.fixed @@ -0,0 +1,21 @@ +// Regression test for #88684: Improve diagnostics for combining marks +// in character literals. + +// run-rustfix + +fn main() { + let _spade = "♠️"; + //~^ ERROR: character literal may only contain one codepoint + //~| NOTE: this `♠` is followed by the combining mark `\u{fe0f}` + //~| HELP: if you meant to write a `str` literal, use double quotes + + let _s = "ṩ̂̊"; + //~^ ERROR: character literal may only contain one codepoint + //~| NOTE: this `s` is followed by the combining marks `\u{323}\u{307}\u{302}\u{30a}` + //~| HELP: if you meant to write a `str` literal, use double quotes + + let _a = 'Å'; + //~^ ERROR: character literal may only contain one codepoint + //~| NOTE: this `A` is followed by the combining mark `\u{30a}` + //~| HELP: consider using the normalized form `\u{c5}` of this character +} diff --git a/src/test/ui/parser/unicode-character-literal.rs b/src/test/ui/parser/unicode-character-literal.rs new file mode 100644 index 0000000000..d331522c04 --- /dev/null +++ b/src/test/ui/parser/unicode-character-literal.rs @@ -0,0 +1,21 @@ +// Regression test for #88684: Improve diagnostics for combining marks +// in character literals. + +// run-rustfix + +fn main() { + let _spade = '♠️'; + //~^ ERROR: character literal may only contain one codepoint + //~| NOTE: this `♠` is followed by the combining mark `\u{fe0f}` + //~| HELP: if you meant to write a `str` literal, use double quotes + + let _s = 'ṩ̂̊'; + //~^ ERROR: character literal may only contain one codepoint + //~| NOTE: this `s` is followed by the combining marks `\u{323}\u{307}\u{302}\u{30a}` + //~| HELP: if you meant to write a `str` literal, use double quotes + + let _a = 'Å'; + //~^ ERROR: character literal may only contain one codepoint + //~| NOTE: this `A` is followed by the combining mark `\u{30a}` + //~| HELP: consider using the normalized form `\u{c5}` of this character +} diff --git a/src/test/ui/parser/unicode-character-literal.stderr b/src/test/ui/parser/unicode-character-literal.stderr new file mode 100644 index 0000000000..5cd3bd0fe6 --- /dev/null +++ b/src/test/ui/parser/unicode-character-literal.stderr @@ -0,0 +1,48 @@ +error: character literal may only contain one codepoint + --> $DIR/unicode-character-literal.rs:7:18 + | +LL | let _spade = '♠️'; + | ^^^ + | +note: this `♠` is followed by the combining mark `\u{fe0f}` + --> $DIR/unicode-character-literal.rs:7:19 + | +LL | let _spade = '♠️'; + | ^ +help: if you meant to write a `str` literal, use double quotes + | +LL | let _spade = "♠️"; + | ~~~ + +error: character literal may only contain one codepoint + --> $DIR/unicode-character-literal.rs:12:14 + | +LL | let _s = 'ṩ̂̊'; + | ^^^ + | +note: this `s` is followed by the combining marks `\u{323}\u{307}\u{302}\u{30a}` + --> $DIR/unicode-character-literal.rs:12:15 + | +LL | let _s = 'ṩ̂̊'; + | ^ +help: if you meant to write a `str` literal, use double quotes + | +LL | let _s = "ṩ̂̊"; + | ~~~ + +error: character literal may only contain one codepoint + --> $DIR/unicode-character-literal.rs:17:14 + | +LL | let _a = 'Å'; + | ^-^ + | | + | help: consider using the normalized form `\u{c5}` of this character: `Å` + | +note: this `A` is followed by the combining mark `\u{30a}` + --> $DIR/unicode-character-literal.rs:17:15 + | +LL | let _a = 'Å'; + | ^ + +error: aborting due to 3 previous errors + diff --git a/src/test/ui/parser/unicode-control-codepoints.rs b/src/test/ui/parser/unicode-control-codepoints.rs new file mode 100644 index 0000000000..5af0b585a1 --- /dev/null +++ b/src/test/ui/parser/unicode-control-codepoints.rs @@ -0,0 +1,39 @@ +fn main() { + // if access_level != "us‫e‪r" { // Check if admin + //~^ ERROR unicode codepoint changing visible direction of text present in comment + println!("us\u{202B}e\u{202A}r"); + println!("{:?}", r#"us\u{202B}e\u{202A}r"#); + println!("{:?}", b"us\u{202B}e\u{202A}r"); + //~^ ERROR unicode escape in byte string + //~| ERROR unicode escape in byte string + println!("{:?}", br##"us\u{202B}e\u{202A}r"##); + + println!("{:?}", "/*‮ } ⁦if isAdmin⁩ ⁦ begin admins only "); + //~^ ERROR unicode codepoint changing visible direction of text present in literal + + println!("{:?}", r##"/*‮ } ⁦if isAdmin⁩ ⁦ begin admins only "##); + //~^ ERROR unicode codepoint changing visible direction of text present in literal + println!("{:?}", b"/*‮ } ⁦if isAdmin⁩ ⁦ begin admins only "); + //~^ ERROR non-ASCII character in byte constant + //~| ERROR non-ASCII character in byte constant + //~| ERROR non-ASCII character in byte constant + //~| ERROR non-ASCII character in byte constant + println!("{:?}", br##"/*‮ } ⁦if isAdmin⁩ ⁦ begin admins only "##); + //~^ ERROR raw byte string must be ASCII + //~| ERROR raw byte string must be ASCII + //~| ERROR raw byte string must be ASCII + //~| ERROR raw byte string must be ASCII + println!("{:?}", '‮'); + //~^ ERROR unicode codepoint changing visible direction of text present in literal +} + +//"/*‮ } ⁦if isAdmin⁩ ⁦ begin admins only */" +//~^ ERROR unicode codepoint changing visible direction of text present in comment + +/** '‮'); */fn foo() {} +//~^ ERROR unicode codepoint changing visible direction of text present in doc comment + +/** + * + * '‮'); */fn bar() {} +//~^^^ ERROR unicode codepoint changing visible direction of text present in doc comment diff --git a/src/test/ui/parser/unicode-control-codepoints.stderr b/src/test/ui/parser/unicode-control-codepoints.stderr new file mode 100644 index 0000000000..71509fe41a --- /dev/null +++ b/src/test/ui/parser/unicode-control-codepoints.stderr @@ -0,0 +1,192 @@ +error: unicode escape in byte string + --> $DIR/unicode-control-codepoints.rs:6:26 + | +LL | println!("{:?}", b"us\u{202B}e\u{202A}r"); + | ^^^^^^^^ unicode escape in byte string + | + = help: unicode escape sequences cannot be used as a byte or in a byte string + +error: unicode escape in byte string + --> $DIR/unicode-control-codepoints.rs:6:35 + | +LL | println!("{:?}", b"us\u{202B}e\u{202A}r"); + | ^^^^^^^^ unicode escape in byte string + | + = help: unicode escape sequences cannot be used as a byte or in a byte string + +error: non-ASCII character in byte constant + --> $DIR/unicode-control-codepoints.rs:16:26 + | +LL | println!("{:?}", b"/* } if isAdmin begin admins only "); + | ^ byte constant must be ASCII but is '\u{202e}' + | +help: if you meant to use the UTF-8 encoding of '\u{202e}', use \xHH escapes + | +LL | println!("{:?}", b"/*\xE2\x80\xAE } if isAdmin begin admins only "); + | ~~~~~~~~~~~~ + +error: non-ASCII character in byte constant + --> $DIR/unicode-control-codepoints.rs:16:30 + | +LL | println!("{:?}", b"/* } if isAdmin begin admins only "); + | ^ byte constant must be ASCII but is '\u{2066}' + | +help: if you meant to use the UTF-8 encoding of '\u{2066}', use \xHH escapes + | +LL | println!("{:?}", b"/* } \xE2\x81\xA6if isAdmin begin admins only "); + | ~~~~~~~~~~~~ + +error: non-ASCII character in byte constant + --> $DIR/unicode-control-codepoints.rs:16:41 + | +LL | println!("{:?}", b"/* } if isAdmin begin admins only "); + | ^ byte constant must be ASCII but is '\u{2069}' + | +help: if you meant to use the UTF-8 encoding of '\u{2069}', use \xHH escapes + | +LL | println!("{:?}", b"/* } if isAdmin\xE2\x81\xA9 begin admins only "); + | ~~~~~~~~~~~~ + +error: non-ASCII character in byte constant + --> $DIR/unicode-control-codepoints.rs:16:43 + | +LL | println!("{:?}", b"/* } if isAdmin begin admins only "); + | ^ byte constant must be ASCII but is '\u{2066}' + | +help: if you meant to use the UTF-8 encoding of '\u{2066}', use \xHH escapes + | +LL | println!("{:?}", b"/* } if isAdmin \xE2\x81\xA6 begin admins only "); + | ~~~~~~~~~~~~ + +error: raw byte string must be ASCII + --> $DIR/unicode-control-codepoints.rs:21:29 + | +LL | println!("{:?}", br##"/* } if isAdmin begin admins only "##); + | ^ must be ASCII but is '\u{202e}' + +error: raw byte string must be ASCII + --> $DIR/unicode-control-codepoints.rs:21:33 + | +LL | println!("{:?}", br##"/* } if isAdmin begin admins only "##); + | ^ must be ASCII but is '\u{2066}' + +error: raw byte string must be ASCII + --> $DIR/unicode-control-codepoints.rs:21:44 + | +LL | println!("{:?}", br##"/* } if isAdmin begin admins only "##); + | ^ must be ASCII but is '\u{2069}' + +error: raw byte string must be ASCII + --> $DIR/unicode-control-codepoints.rs:21:46 + | +LL | println!("{:?}", br##"/* } if isAdmin begin admins only "##); + | ^ must be ASCII but is '\u{2066}' + +error: unicode codepoint changing visible direction of text present in comment + --> $DIR/unicode-control-codepoints.rs:2:5 + | +LL | // if access_level != "user" { // Check if admin + | ^^^^^^^^^^^^^^^^^^^^^^^^^--^^^^^^^^^^^^^^^^^^^^^ + | | || + | | |'\u{202a}' + | | '\u{202b}' + | this comment contains invisible unicode text flow control codepoints + | + = note: `#[deny(text_direction_codepoint_in_comment)]` on by default + = note: these kind of unicode codepoints change the way text flows on applications that support them, but can cause confusion because they change the order of characters on the screen + = help: if their presence wasn't intentional, you can remove them + +error: unicode codepoint changing visible direction of text present in comment + --> $DIR/unicode-control-codepoints.rs:30:1 + | +LL | //"/* } if isAdmin begin admins only */" + | ^^^^^-^^-^^^^^^^^^--^^^^^^^^^^^^^^^^^^^^^ + | | | | || + | | | | |'\u{2066}' + | | | | '\u{2069}' + | | | '\u{2066}' + | | '\u{202e}' + | this comment contains invisible unicode text flow control codepoints + | + = note: these kind of unicode codepoints change the way text flows on applications that support them, but can cause confusion because they change the order of characters on the screen + = help: if their presence wasn't intentional, you can remove them + +error: unicode codepoint changing visible direction of text present in literal + --> $DIR/unicode-control-codepoints.rs:11:22 + | +LL | println!("{:?}", "/* } if isAdmin begin admins only "); + | ^^^-^^-^^^^^^^^^--^^^^^^^^^^^^^^^^^^^ + | | | | || + | | | | |'\u{2066}' + | | | | '\u{2069}' + | | | '\u{2066}' + | | '\u{202e}' + | this literal contains invisible unicode text flow control codepoints + | + = note: `#[deny(text_direction_codepoint_in_literal)]` on by default + = note: these kind of unicode codepoints change the way text flows on applications that support them, but can cause confusion because they change the order of characters on the screen + = help: if their presence wasn't intentional, you can remove them +help: if you want to keep them but make them visible in your source code, you can escape them + | +LL | println!("{:?}", "/*\u{202e} } \u{2066}if isAdmin\u{2069} \u{2066} begin admins only "); + | ~~~~~~~~ ~~~~~~~~ ~~~~~~~~ ~~~~~~~~ + +error: unicode codepoint changing visible direction of text present in literal + --> $DIR/unicode-control-codepoints.rs:14:22 + | +LL | println!("{:?}", r##"/* } if isAdmin begin admins only "##); + | ^^^^^^-^^-^^^^^^^^^--^^^^^^^^^^^^^^^^^^^^^ + | | | | || + | | | | |'\u{2066}' + | | | | '\u{2069}' + | | | '\u{2066}' + | | '\u{202e}' + | this literal contains invisible unicode text flow control codepoints + | + = note: these kind of unicode codepoints change the way text flows on applications that support them, but can cause confusion because they change the order of characters on the screen + = help: if their presence wasn't intentional, you can remove them +help: if you want to keep them but make them visible in your source code, you can escape them + | +LL | println!("{:?}", r##"/*\u{202e} } \u{2066}if isAdmin\u{2069} \u{2066} begin admins only "##); + | ~~~~~~~~ ~~~~~~~~ ~~~~~~~~ ~~~~~~~~ + +error: unicode codepoint changing visible direction of text present in literal + --> $DIR/unicode-control-codepoints.rs:26:22 + | +LL | println!("{:?}", ''); + | ^- + | || + | |'\u{202e}' + | this literal contains an invisible unicode text flow control codepoint + | + = note: these kind of unicode codepoints change the way text flows on applications that support them, but can cause confusion because they change the order of characters on the screen + = help: if their presence wasn't intentional, you can remove them +help: if you want to keep them but make them visible in your source code, you can escape them + | +LL | println!("{:?}", '\u{202e}'); + | ~~~~~~~~ + +error: unicode codepoint changing visible direction of text present in doc comment + --> $DIR/unicode-control-codepoints.rs:33:1 + | +LL | /** ''); */fn foo() {} + | ^^^^^^^^^^^^ this doc comment contains an invisible unicode text flow control codepoint + | + = note: these kind of unicode codepoints change the way text flows on applications that support them, but can cause confusion because they change the order of characters on the screen + = note: if their presence wasn't intentional, you can remove them + = note: if you want to keep them but make them visible in your source code, you can escape them: '\u{202e}' + +error: unicode codepoint changing visible direction of text present in doc comment + --> $DIR/unicode-control-codepoints.rs:36:1 + | +LL | / /** +LL | | * +LL | | * ''); */fn bar() {} + | |___________^ this doc comment contains an invisible unicode text flow control codepoint + | + = note: these kind of unicode codepoints change the way text flows on applications that support them, but can cause confusion because they change the order of characters on the screen + = note: if their presence wasn't intentional, you can remove them + = note: if you want to keep them but make them visible in your source code, you can escape them: '\u{202e}' + +error: aborting due to 17 previous errors + diff --git a/src/test/ui/path-lookahead.stderr b/src/test/ui/path-lookahead.stderr index dcf235a9e2..8adf02b150 100644 --- a/src/test/ui/path-lookahead.stderr +++ b/src/test/ui/path-lookahead.stderr @@ -2,13 +2,18 @@ warning: unnecessary parentheses around `return` value --> $DIR/path-lookahead.rs:10:12 | LL | return (::to_string(&arg)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove these parentheses + | ^ ^ | note: the lint level is defined here --> $DIR/path-lookahead.rs:5:9 | LL | #![warn(unused_parens)] | ^^^^^^^^^^^^^ +help: remove these parentheses + | +LL - return (::to_string(&arg)); +LL + return ::to_string(&arg); + | warning: 1 warning emitted diff --git a/src/test/ui/pattern/bindings-after-at/nested-type-ascription-syntactically-invalid.rs b/src/test/ui/pattern/bindings-after-at/nested-type-ascription-syntactically-invalid.rs index 5c7769ce60..a709e34b50 100644 --- a/src/test/ui/pattern/bindings-after-at/nested-type-ascription-syntactically-invalid.rs +++ b/src/test/ui/pattern/bindings-after-at/nested-type-ascription-syntactically-invalid.rs @@ -1,5 +1,5 @@ // Here we check that type ascription is syntactically invalid when -// not in the top position of a ascribing a let binding or function parameter. +// not in the top position of an ascribing `let` binding or function parameter. // This has no effect. diff --git a/src/test/ui/pattern/issue-88074-pat-range-type-inference-err.rs b/src/test/ui/pattern/issue-88074-pat-range-type-inference-err.rs new file mode 100644 index 0000000000..16df272df6 --- /dev/null +++ b/src/test/ui/pattern/issue-88074-pat-range-type-inference-err.rs @@ -0,0 +1,28 @@ +trait Zero { + const ZERO: Self; +} + +impl Zero for String { + const ZERO: Self = String::new(); +} + +fn foo() { + match String::new() { + Zero::ZERO ..= Zero::ZERO => {}, + //~^ ERROR only `char` and numeric types are allowed in range patterns + _ => {}, + } +} + +fn bar() { + match Zero::ZERO { + Zero::ZERO ..= Zero::ZERO => {}, + //~^ ERROR type annotations needed [E0282] + _ => {}, + } +} + +fn main() { + foo(); + bar(); +} diff --git a/src/test/ui/pattern/issue-88074-pat-range-type-inference-err.stderr b/src/test/ui/pattern/issue-88074-pat-range-type-inference-err.stderr new file mode 100644 index 0000000000..06a279925e --- /dev/null +++ b/src/test/ui/pattern/issue-88074-pat-range-type-inference-err.stderr @@ -0,0 +1,21 @@ +error[E0029]: only `char` and numeric types are allowed in range patterns + --> $DIR/issue-88074-pat-range-type-inference-err.rs:11:9 + | +LL | Zero::ZERO ..= Zero::ZERO => {}, + | ----------^^^^^---------- + | | | + | | this is of type `String` but it should be `char` or numeric + | this is of type `String` but it should be `char` or numeric + +error[E0282]: type annotations needed + --> $DIR/issue-88074-pat-range-type-inference-err.rs:19:9 + | +LL | Zero::ZERO ..= Zero::ZERO => {}, + | ^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type + | + = note: type must be known at this point + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0029, E0282. +For more information about an error, try `rustc --explain E0029`. diff --git a/src/test/ui/pattern/issue-88074-pat-range-type-inference.rs b/src/test/ui/pattern/issue-88074-pat-range-type-inference.rs new file mode 100644 index 0000000000..27db7d8c7a --- /dev/null +++ b/src/test/ui/pattern/issue-88074-pat-range-type-inference.rs @@ -0,0 +1,16 @@ +// check-pass + +trait Zero { + const ZERO: Self; +} + +impl Zero for i32 { + const ZERO: Self = 0; +} + +fn main() { + match 1 { + Zero::ZERO ..= 1 => {}, + _ => {}, + } +} diff --git a/src/test/ui/pattern/patkind-litrange-no-expr.rs b/src/test/ui/pattern/patkind-litrange-no-expr.rs index 9464f277fb..7ef541cb58 100644 --- a/src/test/ui/pattern/patkind-litrange-no-expr.rs +++ b/src/test/ui/pattern/patkind-litrange-no-expr.rs @@ -19,7 +19,6 @@ enum_number!(Change { Neg = -1, Arith = 1 + 1, //~ ERROR arbitrary expressions aren't allowed in patterns //~| ERROR arbitrary expressions aren't allowed in patterns - //~| ERROR only `char` and numeric types are allowed in range patterns }); fn main() {} diff --git a/src/test/ui/pattern/patkind-litrange-no-expr.stderr b/src/test/ui/pattern/patkind-litrange-no-expr.stderr index 51af167a7c..eb1ee7e456 100644 --- a/src/test/ui/pattern/patkind-litrange-no-expr.stderr +++ b/src/test/ui/pattern/patkind-litrange-no-expr.stderr @@ -10,15 +10,5 @@ error: arbitrary expressions aren't allowed in patterns LL | Arith = 1 + 1, | ^^^^^ -error[E0029]: only `char` and numeric types are allowed in range patterns - --> $DIR/patkind-litrange-no-expr.rs:20:13 - | -LL | $( $value ..= 42 => Some($name::$variant), )* // PatKind::Range - | -- this is of type `{integer}` -... -LL | Arith = 1 + 1, - | ^^^^^ this is of type `_` but it should be `char` or numeric +error: aborting due to 2 previous errors -error: aborting due to 3 previous errors - -For more information about this error, try `rustc --explain E0029`. diff --git a/src/test/ui/pattern/usefulness/auxiliary/hidden.rs b/src/test/ui/pattern/usefulness/auxiliary/hidden.rs new file mode 100644 index 0000000000..742b7e82c1 --- /dev/null +++ b/src/test/ui/pattern/usefulness/auxiliary/hidden.rs @@ -0,0 +1,6 @@ +pub enum Foo { + A, + B, + #[doc(hidden)] + C, +} diff --git a/src/test/ui/pattern/usefulness/auxiliary/unstable.rs b/src/test/ui/pattern/usefulness/auxiliary/unstable.rs new file mode 100644 index 0000000000..3142489c86 --- /dev/null +++ b/src/test/ui/pattern/usefulness/auxiliary/unstable.rs @@ -0,0 +1,12 @@ +#![feature(staged_api)] +#![stable(feature = "stable_test_feature", since = "1.0.0")] + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +pub enum Foo { + #[stable(feature = "stable_test_feature", since = "1.0.0")] + Stable, + #[stable(feature = "stable_test_feature", since = "1.0.0")] + Stable2, + #[unstable(feature = "unstable_test_feature", issue = "none")] + Unstable, +} diff --git a/src/test/ui/pattern/usefulness/const-private-fields.rs b/src/test/ui/pattern/usefulness/const-private-fields.rs new file mode 100644 index 0000000000..06c832ca46 --- /dev/null +++ b/src/test/ui/pattern/usefulness/const-private-fields.rs @@ -0,0 +1,30 @@ +// check-pass +// +// Check that we don't ignore private fields in usefulness checking +#![deny(unreachable_patterns)] + +mod inner { + #[derive(PartialEq, Eq)] + pub struct PrivateField { + pub x: bool, + y: bool, + } + + pub const FOO: PrivateField = PrivateField { x: true, y: true }; + pub const BAR: PrivateField = PrivateField { x: true, y: false }; +} +use inner::*; + +fn main() { + match FOO { + FOO => {} + BAR => {} + _ => {} + } + + match FOO { + FOO => {} + PrivateField { x: true, .. } => {} + _ => {} + } +} diff --git a/src/test/ui/pattern/usefulness/consts-opaque.stderr b/src/test/ui/pattern/usefulness/consts-opaque.stderr index 68451043cf..05c009a6f3 100644 --- a/src/test/ui/pattern/usefulness/consts-opaque.stderr +++ b/src/test/ui/pattern/usefulness/consts-opaque.stderr @@ -7,8 +7,11 @@ LL | FOO => {} error: unreachable pattern --> $DIR/consts-opaque.rs:32:9 | +LL | FOO => {} + | --- matches any value +LL | LL | _ => {} // should not be emitting unreachable warning - | ^ + | ^ unreachable pattern | note: the lint level is defined here --> $DIR/consts-opaque.rs:6:9 @@ -25,8 +28,11 @@ LL | FOO_REF => {} error: unreachable pattern --> $DIR/consts-opaque.rs:39:9 | +LL | FOO_REF => {} + | ------- matches any value +LL | LL | Foo(_) => {} // should not be emitting unreachable warning - | ^^^^^^ + | ^^^^^^ unreachable pattern warning: to use a constant of type `Foo` in a pattern, `Foo` must be annotated with `#[derive(PartialEq, Eq)]` --> $DIR/consts-opaque.rs:45:9 @@ -70,15 +76,18 @@ LL | BAR => {} error: unreachable pattern --> $DIR/consts-opaque.rs:63:9 | +LL | BAR => {} + | --- matches any value +LL | LL | Bar => {} // should not be emitting unreachable warning - | ^^^ + | ^^^ unreachable pattern error: unreachable pattern --> $DIR/consts-opaque.rs:65:9 | -LL | Bar => {} // should not be emitting unreachable warning +LL | BAR => {} | --- matches any value -LL | +... LL | _ => {} | ^ unreachable pattern @@ -97,14 +106,20 @@ LL | BAR => {} // should not be emitting unreachable warning error: unreachable pattern --> $DIR/consts-opaque.rs:72:9 | +LL | BAR => {} + | --- matches any value +LL | LL | BAR => {} // should not be emitting unreachable warning - | ^^^ + | ^^^ unreachable pattern error: unreachable pattern --> $DIR/consts-opaque.rs:75:9 | +LL | BAR => {} + | --- matches any value +... LL | _ => {} // should not be emitting unreachable warning - | ^ + | ^ unreachable pattern error: to use a constant of type `Baz` in a pattern, `Baz` must be annotated with `#[derive(PartialEq, Eq)]` --> $DIR/consts-opaque.rs:80:9 @@ -115,14 +130,20 @@ LL | BAZ => {} error: unreachable pattern --> $DIR/consts-opaque.rs:82:9 | +LL | BAZ => {} + | --- matches any value +LL | LL | Baz::Baz1 => {} // should not be emitting unreachable warning - | ^^^^^^^^^ + | ^^^^^^^^^ unreachable pattern error: unreachable pattern --> $DIR/consts-opaque.rs:84:9 | +LL | BAZ => {} + | --- matches any value +... LL | _ => {} - | ^ + | ^ unreachable pattern error: to use a constant of type `Baz` in a pattern, `Baz` must be annotated with `#[derive(PartialEq, Eq)]` --> $DIR/consts-opaque.rs:90:9 @@ -133,8 +154,11 @@ LL | BAZ => {} error: unreachable pattern --> $DIR/consts-opaque.rs:92:9 | +LL | BAZ => {} + | --- matches any value +LL | LL | _ => {} - | ^ + | ^ unreachable pattern error: to use a constant of type `Baz` in a pattern, `Baz` must be annotated with `#[derive(PartialEq, Eq)]` --> $DIR/consts-opaque.rs:97:9 @@ -145,20 +169,28 @@ LL | BAZ => {} error: unreachable pattern --> $DIR/consts-opaque.rs:99:9 | +LL | BAZ => {} + | --- matches any value +LL | LL | Baz::Baz2 => {} // should not be emitting unreachable warning - | ^^^^^^^^^ + | ^^^^^^^^^ unreachable pattern error: unreachable pattern --> $DIR/consts-opaque.rs:101:9 | +LL | BAZ => {} + | --- matches any value +... LL | _ => {} // should not be emitting unreachable warning - | ^ + | ^ unreachable pattern error: unreachable pattern --> $DIR/consts-opaque.rs:127:9 | +LL | Wrap(_) => {} + | ------- matches any value LL | WRAPQUUX => {} // detected unreachable because we do inspect the `Wrap` layer - | ^^^^^^^^ + | ^^^^^^^^ unreachable pattern error: unreachable pattern --> $DIR/consts-opaque.rs:141:9 diff --git a/src/test/ui/pattern/usefulness/doc-hidden-non-exhaustive.rs b/src/test/ui/pattern/usefulness/doc-hidden-non-exhaustive.rs new file mode 100644 index 0000000000..a1dcab0931 --- /dev/null +++ b/src/test/ui/pattern/usefulness/doc-hidden-non-exhaustive.rs @@ -0,0 +1,30 @@ +// aux-build:hidden.rs + +extern crate hidden; + +use hidden::Foo; + +fn main() { + match Foo::A { + Foo::A => {} + Foo::B => {} + } + //~^^^^ non-exhaustive patterns: `_` not covered + + match Foo::A { + Foo::A => {} + Foo::C => {} + } + //~^^^^ non-exhaustive patterns: `B` not covered + + match Foo::A { + Foo::A => {} + } + //~^^^ non-exhaustive patterns: `B` and `_` not covered + + match None { + None => {} + Some(Foo::A) => {} + } + //~^^^^ non-exhaustive patterns: `Some(B)` and `Some(_)` not covered +} diff --git a/src/test/ui/pattern/usefulness/doc-hidden-non-exhaustive.stderr b/src/test/ui/pattern/usefulness/doc-hidden-non-exhaustive.stderr new file mode 100644 index 0000000000..6c9539822b --- /dev/null +++ b/src/test/ui/pattern/usefulness/doc-hidden-non-exhaustive.stderr @@ -0,0 +1,54 @@ +error[E0004]: non-exhaustive patterns: `_` not covered + --> $DIR/doc-hidden-non-exhaustive.rs:8:11 + | +LL | match Foo::A { + | ^^^^^^ pattern `_` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + = note: the matched value is of type `Foo` + +error[E0004]: non-exhaustive patterns: `B` not covered + --> $DIR/doc-hidden-non-exhaustive.rs:14:11 + | +LL | match Foo::A { + | ^^^^^^ pattern `B` not covered + | + ::: $DIR/auxiliary/hidden.rs:3:5 + | +LL | B, + | - not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + = note: the matched value is of type `Foo` + +error[E0004]: non-exhaustive patterns: `B` and `_` not covered + --> $DIR/doc-hidden-non-exhaustive.rs:20:11 + | +LL | match Foo::A { + | ^^^^^^ patterns `B` and `_` not covered + | + ::: $DIR/auxiliary/hidden.rs:3:5 + | +LL | B, + | - not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + = note: the matched value is of type `Foo` + +error[E0004]: non-exhaustive patterns: `Some(B)` and `Some(_)` not covered + --> $DIR/doc-hidden-non-exhaustive.rs:25:11 + | +LL | match None { + | ^^^^ patterns `Some(B)` and `Some(_)` not covered + | + ::: $SRC_DIR/core/src/option.rs:LL:COL + | +LL | Some(#[stable(feature = "rust1", since = "1.0.0")] T), + | ---- not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + = note: the matched value is of type `Option` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0004`. diff --git a/src/test/ui/pattern/usefulness/integer-ranges/reachability.stderr b/src/test/ui/pattern/usefulness/integer-ranges/reachability.stderr index 9a02fac6a7..0ffb0ffd82 100644 --- a/src/test/ui/pattern/usefulness/integer-ranges/reachability.stderr +++ b/src/test/ui/pattern/usefulness/integer-ranges/reachability.stderr @@ -133,8 +133,10 @@ LL | 5..15 => {}, error: unreachable pattern --> $DIR/reachability.rs:83:9 | +LL | _ => {}, + | - matches any value LL | '\u{D7FF}'..='\u{E000}' => {}, - | ^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^ unreachable pattern error: unreachable pattern --> $DIR/reachability.rs:104:9 diff --git a/src/test/ui/pattern/usefulness/issue-12116.rs b/src/test/ui/pattern/usefulness/issue-12116.rs index 8b391cd95d..3cb92a5402 100644 --- a/src/test/ui/pattern/usefulness/issue-12116.rs +++ b/src/test/ui/pattern/usefulness/issue-12116.rs @@ -1,9 +1,9 @@ #![feature(box_patterns)] -#![feature(box_syntax)] #![allow(dead_code)] #![allow(unused_variables)] #![deny(unreachable_patterns)] + enum IntList { Cons(isize, Box), Nil @@ -12,9 +12,9 @@ enum IntList { fn tail(source_list: &IntList) -> IntList { match source_list { &IntList::Cons(val, box ref next_list) => tail(next_list), - &IntList::Cons(val, box IntList::Nil) => IntList::Cons(val, box IntList::Nil), -//~^ ERROR unreachable pattern - _ => panic!() + &IntList::Cons(val, box IntList::Nil) => IntList::Cons(val, Box::new(IntList::Nil)), + //~^ ERROR unreachable pattern + _ => panic!(), } } diff --git a/src/test/ui/pattern/usefulness/issue-12116.stderr b/src/test/ui/pattern/usefulness/issue-12116.stderr index 4d162eb77e..7f15c4703a 100644 --- a/src/test/ui/pattern/usefulness/issue-12116.stderr +++ b/src/test/ui/pattern/usefulness/issue-12116.stderr @@ -1,11 +1,11 @@ error: unreachable pattern --> $DIR/issue-12116.rs:15:9 | -LL | &IntList::Cons(val, box IntList::Nil) => IntList::Cons(val, box IntList::Nil), +LL | &IntList::Cons(val, box IntList::Nil) => IntList::Cons(val, Box::new(IntList::Nil)), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: the lint level is defined here - --> $DIR/issue-12116.rs:5:9 + --> $DIR/issue-12116.rs:4:9 | LL | #![deny(unreachable_patterns)] | ^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/pattern/usefulness/issue-3601.rs b/src/test/ui/pattern/usefulness/issue-3601.rs index e33359becc..6215a23980 100644 --- a/src/test/ui/pattern/usefulness/issue-3601.rs +++ b/src/test/ui/pattern/usefulness/issue-3601.rs @@ -1,5 +1,4 @@ #![feature(box_patterns)] -#![feature(box_syntax)] struct HTMLImageData { image: Option @@ -23,8 +22,9 @@ struct NodeData { fn main() { let mut id = HTMLImageData { image: None }; - let ed = ElementData { kind: box ElementKind::HTMLImageElement(id) }; - let n = NodeData {kind : box NodeKind::Element(ed)}; + let ed = ElementData { kind: Box::new(ElementKind::HTMLImageElement(id)) }; + let n = NodeData { kind: Box::new(NodeKind::Element(ed)) }; + // n.b. span could be better match n.kind { box NodeKind::Element(ed) => match ed.kind { //~ ERROR non-exhaustive patterns diff --git a/src/test/ui/pattern/usefulness/issue-3601.stderr b/src/test/ui/pattern/usefulness/issue-3601.stderr index c873c20cca..48ed149150 100644 --- a/src/test/ui/pattern/usefulness/issue-3601.stderr +++ b/src/test/ui/pattern/usefulness/issue-3601.stderr @@ -1,8 +1,8 @@ -error[E0004]: non-exhaustive patterns: `Box(_, _)` not covered +error[E0004]: non-exhaustive patterns: `box _` not covered --> $DIR/issue-3601.rs:30:44 | LL | box NodeKind::Element(ed) => match ed.kind { - | ^^^^^^^ pattern `Box(_, _)` not covered + | ^^^^^^^ pattern `box _` not covered | = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms = note: the matched value is of type `Box` diff --git a/src/test/ui/pattern/usefulness/issue-72476-and-89393-associated-type.rs b/src/test/ui/pattern/usefulness/issue-72476-and-89393-associated-type.rs new file mode 100644 index 0000000000..058f419679 --- /dev/null +++ b/src/test/ui/pattern/usefulness/issue-72476-and-89393-associated-type.rs @@ -0,0 +1,56 @@ +// check-pass + +// From https://github.com/rust-lang/rust/issues/72476 +// and https://github.com/rust-lang/rust/issues/89393 + +trait Trait { + type Projection; +} + +struct A; +impl Trait for A { + type Projection = bool; +} + +struct B; +impl Trait for B { + type Projection = (u32, u32); +} + +struct Next(T::Projection); + +fn foo1(item: Next) { + match item { + Next(true) => {} + Next(false) => {} + } +} + +fn foo2(x: ::Projection) { + match x { + true => {} + false => {} + } +} + +fn foo3(x: Next) { + let Next((_, _)) = x; + match x { + Next((_, _)) => {} + } +} + +fn foo4(x: ::Projection) { + let (_, _) = x; + match x { + (_, _) => {} + } +} + +fn foo5(x: ::Projection) { + match x { + _ => {} + } +} + +fn main() {} diff --git a/src/test/ui/pattern/usefulness/issue-72476-associated-type.rs b/src/test/ui/pattern/usefulness/issue-72476-associated-type.rs deleted file mode 100644 index 1e1d21433b..0000000000 --- a/src/test/ui/pattern/usefulness/issue-72476-associated-type.rs +++ /dev/null @@ -1,22 +0,0 @@ -// check-pass - -// From https://github.com/rust-lang/rust/issues/72476 - -trait A { - type Projection; -} - -impl A for () { - type Projection = bool; -} - -struct Next(T::Projection); - -fn f(item: Next<()>) { - match item { - Next(true) => {} - Next(false) => {} - } -} - -fn main() {} diff --git a/src/test/ui/pattern/usefulness/issue-82772-match-box-as-struct.rs b/src/test/ui/pattern/usefulness/issue-82772-match-box-as-struct.rs new file mode 100644 index 0000000000..c1bfcc7340 --- /dev/null +++ b/src/test/ui/pattern/usefulness/issue-82772-match-box-as-struct.rs @@ -0,0 +1,6 @@ +// This used to ICE in exhaustiveness checking. Explanation here: +// https://github.com/rust-lang/rust/issues/82772#issuecomment-905946768 +fn main() { + let Box { 1: _, .. }: Box<()>; //~ ERROR field `1` of + let Box { .. }: Box<()>; +} diff --git a/src/test/ui/pattern/usefulness/issue-82772-match-box-as-struct.stderr b/src/test/ui/pattern/usefulness/issue-82772-match-box-as-struct.stderr new file mode 100644 index 0000000000..2c8c85bb1e --- /dev/null +++ b/src/test/ui/pattern/usefulness/issue-82772-match-box-as-struct.stderr @@ -0,0 +1,9 @@ +error[E0451]: field `1` of struct `Box` is private + --> $DIR/issue-82772-match-box-as-struct.rs:4:15 + | +LL | let Box { 1: _, .. }: Box<()>; + | ^^^^ private field + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0451`. diff --git a/src/test/ui/pattern/usefulness/stable-gated-patterns.rs b/src/test/ui/pattern/usefulness/stable-gated-patterns.rs new file mode 100644 index 0000000000..2e023a3be4 --- /dev/null +++ b/src/test/ui/pattern/usefulness/stable-gated-patterns.rs @@ -0,0 +1,18 @@ +// aux-build:unstable.rs + +extern crate unstable; + +use unstable::Foo; + +fn main() { + match Foo::Stable { + Foo::Stable => {} + } + //~^^^ non-exhaustive patterns: `Stable2` and `_` not covered + + match Foo::Stable { + Foo::Stable => {} + Foo::Stable2 => {} + } + //~^^^^ non-exhaustive patterns: `_` not covered +} diff --git a/src/test/ui/pattern/usefulness/stable-gated-patterns.stderr b/src/test/ui/pattern/usefulness/stable-gated-patterns.stderr new file mode 100644 index 0000000000..9b42565ac7 --- /dev/null +++ b/src/test/ui/pattern/usefulness/stable-gated-patterns.stderr @@ -0,0 +1,26 @@ +error[E0004]: non-exhaustive patterns: `Stable2` and `_` not covered + --> $DIR/stable-gated-patterns.rs:8:11 + | +LL | match Foo::Stable { + | ^^^^^^^^^^^ patterns `Stable2` and `_` not covered + | + ::: $DIR/auxiliary/unstable.rs:9:5 + | +LL | Stable2, + | ------- not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + = note: the matched value is of type `Foo` + +error[E0004]: non-exhaustive patterns: `_` not covered + --> $DIR/stable-gated-patterns.rs:13:11 + | +LL | match Foo::Stable { + | ^^^^^^^^^^^ pattern `_` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + = note: the matched value is of type `Foo` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0004`. diff --git a/src/test/ui/pattern/usefulness/unstable-gated-patterns.rs b/src/test/ui/pattern/usefulness/unstable-gated-patterns.rs new file mode 100644 index 0000000000..b9804b0ffe --- /dev/null +++ b/src/test/ui/pattern/usefulness/unstable-gated-patterns.rs @@ -0,0 +1,22 @@ +#![feature(unstable_test_feature)] + +// aux-build:unstable.rs + +extern crate unstable; + +use unstable::Foo; + +fn main() { + match Foo::Stable { + Foo::Stable => {} + Foo::Stable2 => {} + } + //~^^^^ non-exhaustive patterns: `Unstable` not covered + + // Ok: all variants are explicitly matched + match Foo::Stable { + Foo::Stable => {} + Foo::Stable2 => {} + Foo::Unstable => {} + } +} diff --git a/src/test/ui/pattern/usefulness/unstable-gated-patterns.stderr b/src/test/ui/pattern/usefulness/unstable-gated-patterns.stderr new file mode 100644 index 0000000000..f9c0196b76 --- /dev/null +++ b/src/test/ui/pattern/usefulness/unstable-gated-patterns.stderr @@ -0,0 +1,17 @@ +error[E0004]: non-exhaustive patterns: `Unstable` not covered + --> $DIR/unstable-gated-patterns.rs:10:11 + | +LL | match Foo::Stable { + | ^^^^^^^^^^^ pattern `Unstable` not covered + | + ::: $DIR/auxiliary/unstable.rs:11:5 + | +LL | Unstable, + | -------- not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + = note: the matched value is of type `Foo` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0004`. diff --git a/src/test/ui/phantom-auto-trait.stderr b/src/test/ui/phantom-auto-trait.stderr index e7b5528dae..1cc653c51c 100644 --- a/src/test/ui/phantom-auto-trait.stderr +++ b/src/test/ui/phantom-auto-trait.stderr @@ -2,7 +2,9 @@ error[E0277]: `T` cannot be shared between threads safely --> $DIR/phantom-auto-trait.rs:21:12 | LL | is_zen(x) - | ^ `T` cannot be shared between threads safely + | ------ ^ `T` cannot be shared between threads safely + | | + | required by a bound introduced by this call | note: required because of the requirements on the impl of `Zen` for `&T` --> $DIR/phantom-auto-trait.rs:10:24 @@ -29,7 +31,9 @@ error[E0277]: `T` cannot be shared between threads safely --> $DIR/phantom-auto-trait.rs:26:12 | LL | is_zen(x) - | ^ `T` cannot be shared between threads safely + | ------ ^ `T` cannot be shared between threads safely + | | + | required by a bound introduced by this call | note: required because of the requirements on the impl of `Zen` for `&T` --> $DIR/phantom-auto-trait.rs:10:24 diff --git a/src/test/ui/issues/issue-74614.rs b/src/test/ui/polymorphization/issue-74614.rs similarity index 100% rename from src/test/ui/issues/issue-74614.rs rename to src/test/ui/polymorphization/issue-74614.rs diff --git a/src/test/ui/polymorphization/predicates.rs b/src/test/ui/polymorphization/predicates.rs index 97f1ef2c90..dea1e21e77 100644 --- a/src/test/ui/polymorphization/predicates.rs +++ b/src/test/ui/polymorphization/predicates.rs @@ -12,6 +12,7 @@ fn bar() { #[rustc_polymorphize_error] fn foo(_: I) +//~^ ERROR item has unused generic parameters where I: Iterator, { @@ -20,6 +21,7 @@ where #[rustc_polymorphize_error] fn baz(_: I) +//~^ ERROR item has unused generic parameters where std::iter::Repeat: Iterator, { @@ -40,6 +42,7 @@ where #[rustc_polymorphize_error] fn next(&mut self) -> Option { self.find(|_| true) + //~^ ERROR item has unused generic parameters } } @@ -53,6 +56,7 @@ impl Baz for u16 {} #[rustc_polymorphize_error] fn quux() -> usize +//~^ ERROR item has unused generic parameters where A: Baz, B: Baz, @@ -69,6 +73,7 @@ impl Foobar for () {} #[rustc_polymorphize_error] fn foobar() -> usize +//~^ ERROR item has unused generic parameters where (): Foobar, { diff --git a/src/test/ui/polymorphization/predicates.stderr b/src/test/ui/polymorphization/predicates.stderr index c23730fc99..5fc51e58d7 100644 --- a/src/test/ui/polymorphization/predicates.stderr +++ b/src/test/ui/polymorphization/predicates.stderr @@ -1,8 +1,45 @@ +error: item has unused generic parameters + --> $DIR/predicates.rs:14:4 + | +LL | fn foo(_: I) + | ^^^ - generic parameter `T` is unused + +error: item has unused generic parameters + --> $DIR/predicates.rs:23:4 + | +LL | fn baz(_: I) + | ^^^ - generic parameter `T` is unused + +error: item has unused generic parameters + --> $DIR/predicates.rs:44:19 + | +LL | impl<'a, I, T: 'a, E> Iterator for Foo<'a, I, E> + | - - generic parameter `E` is unused + | | + | generic parameter `I` is unused +... +LL | self.find(|_| true) + | ^^^^^^^^ + +error: item has unused generic parameters + --> $DIR/predicates.rs:58:4 + | +LL | fn quux() -> usize + | ^^^^ - - generic parameter `B` is unused + | | + | generic parameter `A` is unused + +error: item has unused generic parameters + --> $DIR/predicates.rs:75:4 + | +LL | fn foobar() -> usize + | ^^^^^^ - generic parameter `F` is unused + error: item has unused generic parameters --> $DIR/predicates.rs:9:4 | LL | fn bar() { | ^^^ - generic parameter `I` is unused -error: aborting due to previous error +error: aborting due to 6 previous errors diff --git a/src/test/ui/pptypedef.stderr b/src/test/ui/pptypedef.stderr index c42d9e6bbf..49895f3db4 100644 --- a/src/test/ui/pptypedef.stderr +++ b/src/test/ui/pptypedef.stderr @@ -7,7 +7,7 @@ LL | let_in(3u32, |i| { assert!(i == 3i32); }); help: change the type of the numeric literal from `i32` to `u32` | LL | let_in(3u32, |i| { assert!(i == 3u32); }); - | ~~~~ + | ~~~ error[E0308]: mismatched types --> $DIR/pptypedef.rs:8:37 @@ -18,7 +18,7 @@ LL | let_in(3i32, |i| { assert!(i == 3u32); }); help: change the type of the numeric literal from `u32` to `i32` | LL | let_in(3i32, |i| { assert!(i == 3i32); }); - | ~~~~ + | ~~~ error: aborting due to 2 previous errors diff --git a/src/test/ui/print_type_sizes/uninhabited.rs b/src/test/ui/print_type_sizes/uninhabited.rs index c234547bd1..06a62db4eb 100644 --- a/src/test/ui/print_type_sizes/uninhabited.rs +++ b/src/test/ui/print_type_sizes/uninhabited.rs @@ -11,5 +11,5 @@ fn start(_: isize, _: *const *const u8) -> isize { let _x: Option = None; let _y: Result = Ok(42); - 0 + let _z: Result = loop {}; } diff --git a/src/test/ui/print_type_sizes/uninhabited.stdout b/src/test/ui/print_type_sizes/uninhabited.stdout index 2a8706f7ac..5eb5384bce 100644 --- a/src/test/ui/print_type_sizes/uninhabited.stdout +++ b/src/test/ui/print_type_sizes/uninhabited.stdout @@ -3,3 +3,4 @@ print-type-size variant `Ok`: 4 bytes print-type-size field `.0`: 4 bytes print-type-size type: `std::option::Option`: 0 bytes, alignment: 1 bytes print-type-size variant `None`: 0 bytes +print-type-size type: `std::result::Result`: 0 bytes, alignment: 1 bytes diff --git a/src/test/ui/privacy/associated-item-privacy-inherent.stderr b/src/test/ui/privacy/associated-item-privacy-inherent.stderr index 08b282e187..4478e5c2ab 100644 --- a/src/test/ui/privacy/associated-item-privacy-inherent.stderr +++ b/src/test/ui/privacy/associated-item-privacy-inherent.stderr @@ -5,7 +5,7 @@ LL | let value = Pub::method; | ^^^^^^^^^^^ private type ... LL | priv_nominal::mac!(); - | --------------------- in this macro invocation + | -------------------- in this macro invocation | = note: this error originates in the macro `priv_nominal::mac` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -16,7 +16,7 @@ LL | value; | ^^^^^ private type ... LL | priv_nominal::mac!(); - | --------------------- in this macro invocation + | -------------------- in this macro invocation | = note: this error originates in the macro `priv_nominal::mac` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -27,7 +27,7 @@ LL | Pub.method(); | ^^^^^^ private type ... LL | priv_nominal::mac!(); - | --------------------- in this macro invocation + | -------------------- in this macro invocation | = note: this error originates in the macro `priv_nominal::mac` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -38,7 +38,7 @@ LL | Pub::CONST; | ^^^^^^^^^^ private associated constant ... LL | priv_nominal::mac!(); - | --------------------- in this macro invocation + | -------------------- in this macro invocation | = note: this error originates in the macro `priv_nominal::mac` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -49,7 +49,7 @@ LL | let value = Pub::method; | ^^^^^^^^^^^ private type ... LL | priv_signature::mac!(); - | ----------------------- in this macro invocation + | ---------------------- in this macro invocation | = note: this error originates in the macro `priv_signature::mac` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -60,7 +60,7 @@ LL | value; | ^^^^^ private type ... LL | priv_signature::mac!(); - | ----------------------- in this macro invocation + | ---------------------- in this macro invocation | = note: this error originates in the macro `priv_signature::mac` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -71,7 +71,7 @@ LL | Pub.method(loop {}); | ^^^^^^ private type ... LL | priv_signature::mac!(); - | ----------------------- in this macro invocation + | ---------------------- in this macro invocation | = note: this error originates in the macro `priv_signature::mac` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -82,7 +82,7 @@ LL | let value = Pub::method::; | ^^^^^^^^^^^^^^^^^^^ private type ... LL | priv_substs::mac!(); - | -------------------- in this macro invocation + | ------------------- in this macro invocation | = note: this error originates in the macro `priv_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -93,7 +93,7 @@ LL | value; | ^^^^^ private type ... LL | priv_substs::mac!(); - | -------------------- in this macro invocation + | ------------------- in this macro invocation | = note: this error originates in the macro `priv_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -104,7 +104,7 @@ LL | Pub.method::(); | ^^^^^^^^^^^^^^^^^^^^ private type ... LL | priv_substs::mac!(); - | -------------------- in this macro invocation + | ------------------- in this macro invocation | = note: this error originates in the macro `priv_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -115,7 +115,7 @@ LL | let value = ::method; | ^^^^^^^^^^^^^ private type ... LL | priv_parent_substs::mac!(); - | --------------------------- in this macro invocation + | -------------------------- in this macro invocation | = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -126,7 +126,7 @@ LL | value; | ^^^^^ private type ... LL | priv_parent_substs::mac!(); - | --------------------------- in this macro invocation + | -------------------------- in this macro invocation | = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -137,7 +137,7 @@ LL | let value = Pub::method; | ^^^^^^^^^^^ private type ... LL | priv_parent_substs::mac!(); - | --------------------------- in this macro invocation + | -------------------------- in this macro invocation | = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -148,7 +148,7 @@ LL | value; | ^^^^^ private type ... LL | priv_parent_substs::mac!(); - | --------------------------- in this macro invocation + | -------------------------- in this macro invocation | = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -159,7 +159,7 @@ LL | let value = ::static_method; | ^^^^^^^^^^^^^^^^^^^^ private type ... LL | priv_parent_substs::mac!(); - | --------------------------- in this macro invocation + | -------------------------- in this macro invocation | = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -170,7 +170,7 @@ LL | value; | ^^^^^ private type ... LL | priv_parent_substs::mac!(); - | --------------------------- in this macro invocation + | -------------------------- in this macro invocation | = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -181,7 +181,7 @@ LL | let value = Pub::static_method; | ^^^^^^^^^^^^^^^^^^ private type ... LL | priv_parent_substs::mac!(); - | --------------------------- in this macro invocation + | -------------------------- in this macro invocation | = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -192,7 +192,7 @@ LL | value; | ^^^^^ private type ... LL | priv_parent_substs::mac!(); - | --------------------------- in this macro invocation + | -------------------------- in this macro invocation | = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -203,7 +203,7 @@ LL | Pub(Priv).method(); | ^^^^^^ private type ... LL | priv_parent_substs::mac!(); - | --------------------------- in this macro invocation + | -------------------------- in this macro invocation | = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -214,7 +214,7 @@ LL | ::CONST; | ^^^ private type ... LL | priv_parent_substs::mac!(); - | --------------------------- in this macro invocation + | -------------------------- in this macro invocation | = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -225,7 +225,7 @@ LL | Pub::CONST; | ^^^ private type ... LL | priv_parent_substs::mac!(); - | --------------------------- in this macro invocation + | -------------------------- in this macro invocation | = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/privacy/associated-item-privacy-trait.stderr b/src/test/ui/privacy/associated-item-privacy-trait.stderr index 3a42415e47..6095f5f42b 100644 --- a/src/test/ui/privacy/associated-item-privacy-trait.stderr +++ b/src/test/ui/privacy/associated-item-privacy-trait.stderr @@ -5,7 +5,7 @@ LL | let value = ::method; | ^^^^^^^^^^^^^^^^^^^^^^^ private type ... LL | priv_trait::mac!(); - | ------------------- in this macro invocation + | ------------------ in this macro invocation | = note: this error originates in the macro `priv_trait::mac` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -16,7 +16,7 @@ LL | value; | ^^^^^ private type ... LL | priv_trait::mac!(); - | ------------------- in this macro invocation + | ------------------ in this macro invocation | = note: this error originates in the macro `priv_trait::mac` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -27,7 +27,7 @@ LL | Pub.method(); | ^^^^^^ private type ... LL | priv_trait::mac!(); - | ------------------- in this macro invocation + | ------------------ in this macro invocation | = note: this error originates in the macro `priv_trait::mac` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -38,7 +38,7 @@ LL | ::CONST; | ^^^^^^^^^^^^^^^^^^^^^^ private associated constant ... LL | priv_trait::mac!(); - | ------------------- in this macro invocation + | ------------------ in this macro invocation | = note: this error originates in the macro `priv_trait::mac` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -49,7 +49,7 @@ LL | let _: ::AssocTy; | ^^^^^^^^^^^^^^^^^^^^^^^^ private associated type ... LL | priv_trait::mac!(); - | ------------------- in this macro invocation + | ------------------ in this macro invocation | = note: this error originates in the macro `priv_trait::mac` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -60,7 +60,7 @@ LL | pub type InSignatureTy = ::AssocTy; | ^^^^^^^^^^^^^^^^^^^^^^^^ private trait ... LL | priv_trait::mac!(); - | ------------------- in this macro invocation + | ------------------ in this macro invocation | = note: this error originates in the macro `priv_trait::mac` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -71,7 +71,7 @@ LL | pub trait InSignatureTr: PrivTr {} | ^^^^^^ private trait ... LL | priv_trait::mac!(); - | ------------------- in this macro invocation + | ------------------ in this macro invocation | = note: this error originates in the macro `priv_trait::mac` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -82,7 +82,7 @@ LL | impl PrivTr for u8 {} | ^^^^^^ private trait ... LL | priv_trait::mac!(); - | ------------------- in this macro invocation + | ------------------ in this macro invocation | = note: this error originates in the macro `priv_trait::mac` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -93,7 +93,7 @@ LL | let value = ::method; | ^^^^^^^^^^^^^^^^^^^^^^ private type ... LL | priv_signature::mac!(); - | ----------------------- in this macro invocation + | ---------------------- in this macro invocation | = note: this error originates in the macro `priv_signature::mac` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -104,7 +104,7 @@ LL | value; | ^^^^^ private type ... LL | priv_signature::mac!(); - | ----------------------- in this macro invocation + | ---------------------- in this macro invocation | = note: this error originates in the macro `priv_signature::mac` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -115,7 +115,7 @@ LL | Pub.method(loop {}); | ^^^^^^ private type ... LL | priv_signature::mac!(); - | ----------------------- in this macro invocation + | ---------------------- in this macro invocation | = note: this error originates in the macro `priv_signature::mac` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -126,7 +126,7 @@ LL | let value = ::method::; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ private type ... LL | priv_substs::mac!(); - | -------------------- in this macro invocation + | ------------------- in this macro invocation | = note: this error originates in the macro `priv_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -137,7 +137,7 @@ LL | value; | ^^^^^ private type ... LL | priv_substs::mac!(); - | -------------------- in this macro invocation + | ------------------- in this macro invocation | = note: this error originates in the macro `priv_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -148,7 +148,7 @@ LL | Pub.method::(); | ^^^^^^^^^^^^^^^^^^^^ private type ... LL | priv_substs::mac!(); - | -------------------- in this macro invocation + | ------------------- in this macro invocation | = note: this error originates in the macro `priv_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -159,7 +159,7 @@ LL | let value = ::method; | ^^^^^^^^^^^^^^^^^^^^^^ private type ... LL | priv_parent_substs::mac!(); - | --------------------------- in this macro invocation + | -------------------------- in this macro invocation | = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -170,7 +170,7 @@ LL | value; | ^^^^^ private type ... LL | priv_parent_substs::mac!(); - | --------------------------- in this macro invocation + | -------------------------- in this macro invocation | = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -181,7 +181,7 @@ LL | let value = >::method; | ^^^^^^^^^^^^^^^^^^^^^^^^^ private type ... LL | priv_parent_substs::mac!(); - | --------------------------- in this macro invocation + | -------------------------- in this macro invocation | = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -192,7 +192,7 @@ LL | value; | ^^^^^ private type ... LL | priv_parent_substs::mac!(); - | --------------------------- in this macro invocation + | -------------------------- in this macro invocation | = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -203,7 +203,7 @@ LL | Pub.method(); | ^^^^^^^^^^^^ private type ... LL | priv_parent_substs::mac!(); - | --------------------------- in this macro invocation + | -------------------------- in this macro invocation | = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -214,7 +214,7 @@ LL | let value = >::method; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ private type ... LL | priv_parent_substs::mac!(); - | --------------------------- in this macro invocation + | -------------------------- in this macro invocation | = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -225,7 +225,7 @@ LL | value; | ^^^^^ private type ... LL | priv_parent_substs::mac!(); - | --------------------------- in this macro invocation + | -------------------------- in this macro invocation | = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -236,7 +236,7 @@ LL | Priv.method(); | ^^^^^^^^^^^^^ private type ... LL | priv_parent_substs::mac!(); - | --------------------------- in this macro invocation + | -------------------------- in this macro invocation | = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -247,7 +247,7 @@ LL | ::CONST; | ^^^^^^^^^^^^^^^^^^^^^ private type ... LL | priv_parent_substs::mac!(); - | --------------------------- in this macro invocation + | -------------------------- in this macro invocation | = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -258,7 +258,7 @@ LL | >::CONST; | ^^^^^^^^^^^^^^^^^^^^^^^^ private type ... LL | priv_parent_substs::mac!(); - | --------------------------- in this macro invocation + | -------------------------- in this macro invocation | = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -269,7 +269,7 @@ LL | >::CONST; | ^^^^^^^^^^^^^^^^^^^^^^^^^ private type ... LL | priv_parent_substs::mac!(); - | --------------------------- in this macro invocation + | -------------------------- in this macro invocation | = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -280,7 +280,7 @@ LL | let _: >::AssocTy; | ^ private type ... LL | priv_parent_substs::mac!(); - | --------------------------- in this macro invocation + | -------------------------- in this macro invocation | = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -291,7 +291,7 @@ LL | let _: >::AssocTy; | ^^^^ private type ... LL | priv_parent_substs::mac!(); - | --------------------------- in this macro invocation + | -------------------------- in this macro invocation | = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -302,7 +302,7 @@ LL | pub type InSignatureTy1 = ::AssocTy; | ^^^^^^^^^^^^^^^^^^^^^^^ private type ... LL | priv_parent_substs::mac!(); - | --------------------------- in this macro invocation + | -------------------------- in this macro invocation | = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -313,7 +313,7 @@ LL | pub type InSignatureTy2 = >::AssocTy; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ private type ... LL | priv_parent_substs::mac!(); - | --------------------------- in this macro invocation + | -------------------------- in this macro invocation | = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -324,7 +324,7 @@ LL | impl PubTr for u8 {} | ^^^^^ private type ... LL | priv_parent_substs::mac!(); - | --------------------------- in this macro invocation + | -------------------------- in this macro invocation | = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/privacy/associated-item-privacy-type-binding.stderr b/src/test/ui/privacy/associated-item-privacy-type-binding.stderr index c275413b45..de9893816f 100644 --- a/src/test/ui/privacy/associated-item-privacy-type-binding.stderr +++ b/src/test/ui/privacy/associated-item-privacy-type-binding.stderr @@ -5,7 +5,7 @@ LL | let _: Box>; | ^ private trait ... LL | priv_trait::mac1!(); - | -------------------- in this macro invocation + | ------------------- in this macro invocation | = note: this error originates in the macro `priv_trait::mac1` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -16,7 +16,7 @@ LL | let _: Box>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ private trait ... LL | priv_trait::mac1!(); - | -------------------- in this macro invocation + | ------------------- in this macro invocation | = note: this error originates in the macro `priv_trait::mac1` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -27,7 +27,7 @@ LL | type InSignatureTy2 = Box>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ private trait ... LL | priv_trait::mac1!(); - | -------------------- in this macro invocation + | ------------------- in this macro invocation | = note: this error originates in the macro `priv_trait::mac1` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -38,7 +38,7 @@ LL | trait InSignatureTr2: PubTr {} | ^^^^^^^^^^^^^^^^^^^ private trait ... LL | priv_trait::mac1!(); - | -------------------- in this macro invocation + | ------------------- in this macro invocation | = note: this error originates in the macro `priv_trait::mac1` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -49,7 +49,7 @@ LL | let _: Box>; | ^ private trait ... LL | priv_trait::mac2!(); - | -------------------- in this macro invocation + | ------------------- in this macro invocation | = note: this error originates in the macro `priv_trait::mac2` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -60,7 +60,7 @@ LL | let _: Box>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ private trait ... LL | priv_trait::mac2!(); - | -------------------- in this macro invocation + | ------------------- in this macro invocation | = note: this error originates in the macro `priv_trait::mac2` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -71,7 +71,7 @@ LL | type InSignatureTy1 = Box>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ private trait ... LL | priv_trait::mac2!(); - | -------------------- in this macro invocation + | ------------------- in this macro invocation | = note: this error originates in the macro `priv_trait::mac2` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -82,7 +82,7 @@ LL | trait InSignatureTr1: PrivTr {} | ^^^^^^^^^^^^^^^^^^^^ private trait ... LL | priv_trait::mac2!(); - | -------------------- in this macro invocation + | ------------------- in this macro invocation | = note: this error originates in the macro `priv_trait::mac2` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -93,7 +93,7 @@ LL | let _: Box>; | ^ private type ... LL | priv_parent_substs::mac!(); - | --------------------------- in this macro invocation + | -------------------------- in this macro invocation | = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -104,7 +104,7 @@ LL | let _: Box>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ private type ... LL | priv_parent_substs::mac!(); - | --------------------------- in this macro invocation + | -------------------------- in this macro invocation | = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -115,7 +115,7 @@ LL | let _: Box>; | ^ private type ... LL | priv_parent_substs::mac!(); - | --------------------------- in this macro invocation + | -------------------------- in this macro invocation | = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -126,7 +126,7 @@ LL | let _: Box>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ private type ... LL | priv_parent_substs::mac!(); - | --------------------------- in this macro invocation + | -------------------------- in this macro invocation | = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -137,7 +137,7 @@ LL | pub type InSignatureTy1 = Box>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ private type ... LL | priv_parent_substs::mac!(); - | --------------------------- in this macro invocation + | -------------------------- in this macro invocation | = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -148,7 +148,7 @@ LL | pub type InSignatureTy2 = Box>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ private type ... LL | priv_parent_substs::mac!(); - | --------------------------- in this macro invocation + | -------------------------- in this macro invocation | = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -159,7 +159,7 @@ LL | trait InSignatureTr1: PubTrWithParam {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ private type ... LL | priv_parent_substs::mac!(); - | --------------------------- in this macro invocation + | -------------------------- in this macro invocation | = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -170,7 +170,7 @@ LL | trait InSignatureTr2: PubTr {} | ^^^^^^^^^^^^^^^^^^^ private type ... LL | priv_parent_substs::mac!(); - | --------------------------- in this macro invocation + | -------------------------- in this macro invocation | = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/issues/issue-79593.rs b/src/test/ui/privacy/issue-79593.rs similarity index 100% rename from src/test/ui/issues/issue-79593.rs rename to src/test/ui/privacy/issue-79593.rs diff --git a/src/test/ui/issues/issue-79593.stderr b/src/test/ui/privacy/issue-79593.stderr similarity index 100% rename from src/test/ui/issues/issue-79593.stderr rename to src/test/ui/privacy/issue-79593.stderr diff --git a/src/test/ui/privacy/privacy2.stderr b/src/test/ui/privacy/privacy2.stderr index c2a33ce1f5..882f314655 100644 --- a/src/test/ui/privacy/privacy2.stderr +++ b/src/test/ui/privacy/privacy2.stderr @@ -23,7 +23,13 @@ LL | pub fn foo() {} error: requires `sized` lang_item -error: aborting due to 3 previous errors +error: requires `sized` lang_item + +error: requires `sized` lang_item + +error: requires `sized` lang_item + +error: aborting due to 6 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 22c1e48b07..42ce456d96 100644 --- a/src/test/ui/privacy/privacy3.stderr +++ b/src/test/ui/privacy/privacy3.stderr @@ -6,6 +6,12 @@ LL | use bar::gpriv; error: requires `sized` lang_item -error: aborting due to 2 previous errors +error: requires `sized` lang_item + +error: requires `sized` lang_item + +error: requires `sized` lang_item + +error: aborting due to 5 previous errors For more information about this error, try `rustc --explain E0432`. diff --git a/src/test/ui/privacy/private-inferred-type-3.stderr b/src/test/ui/privacy/private-inferred-type-3.stderr index 3cd4b4d26c..f9dd1c3d03 100644 --- a/src/test/ui/privacy/private-inferred-type-3.stderr +++ b/src/test/ui/privacy/private-inferred-type-3.stderr @@ -2,7 +2,7 @@ error: type `fn() {ext::priv_fn}` is private --> $DIR/private-inferred-type-3.rs:16:5 | LL | ext::m!(); - | ^^^^^^^^^^ private type + | ^^^^^^^^^ private type | = note: this error originates in the macro `ext::m` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -10,7 +10,7 @@ error: static `PRIV_STATIC` is private --> $DIR/private-inferred-type-3.rs:16:5 | LL | ext::m!(); - | ^^^^^^^^^^ private static + | ^^^^^^^^^ private static | = note: this error originates in the macro `ext::m` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -18,7 +18,7 @@ error: type `ext::PrivEnum` is private --> $DIR/private-inferred-type-3.rs:16:5 | LL | ext::m!(); - | ^^^^^^^^^^ private type + | ^^^^^^^^^ private type | = note: this error originates in the macro `ext::m` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -26,7 +26,7 @@ error: type `fn() {::method}` is private --> $DIR/private-inferred-type-3.rs:16:5 | LL | ext::m!(); - | ^^^^^^^^^^ private type + | ^^^^^^^^^ private type | = note: this error originates in the macro `ext::m` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -34,7 +34,7 @@ error: type `fn(u8) -> ext::PrivTupleStruct {ext::PrivTupleStruct}` is private --> $DIR/private-inferred-type-3.rs:16:5 | LL | ext::m!(); - | ^^^^^^^^^^ private type + | ^^^^^^^^^ private type | = note: this error originates in the macro `ext::m` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -42,7 +42,7 @@ error: type `fn(u8) -> PubTupleStruct {PubTupleStruct}` is private --> $DIR/private-inferred-type-3.rs:16:5 | LL | ext::m!(); - | ^^^^^^^^^^ private type + | ^^^^^^^^^ private type | = note: this error originates in the macro `ext::m` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -50,7 +50,7 @@ error: type `for<'r> fn(&'r Pub) {Pub::::priv_method}` is private --> $DIR/private-inferred-type-3.rs:16:5 | LL | ext::m!(); - | ^^^^^^^^^^ private type + | ^^^^^^^^^ private type | = note: this error originates in the macro `ext::m` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/privacy/private-inferred-type.stderr b/src/test/ui/privacy/private-inferred-type.stderr index c6bdb898f9..e7e968839b 100644 --- a/src/test/ui/privacy/private-inferred-type.stderr +++ b/src/test/ui/privacy/private-inferred-type.stderr @@ -113,7 +113,7 @@ LL | priv_fn; | ^^^^^^^ private type ... LL | m::m!(); - | -------- in this macro invocation + | ------- in this macro invocation | = note: this error originates in the macro `m::m` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -124,7 +124,7 @@ LL | PrivEnum::Variant; | ^^^^^^^^^^^^^^^^^ private type ... LL | m::m!(); - | -------- in this macro invocation + | ------- in this macro invocation | = note: this error originates in the macro `m::m` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -135,7 +135,7 @@ LL | ::method; | ^^^^^^^^^^^^^^^^^^^^^^^^^ private type ... LL | m::m!(); - | -------- in this macro invocation + | ------- in this macro invocation | = note: this error originates in the macro `m::m` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -146,7 +146,7 @@ LL | PrivTupleStruct; | ^^^^^^^^^^^^^^^ private type ... LL | m::m!(); - | -------- in this macro invocation + | ------- in this macro invocation | = note: this error originates in the macro `m::m` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -157,7 +157,7 @@ LL | PubTupleStruct; | ^^^^^^^^^^^^^^ private type ... LL | m::m!(); - | -------- in this macro invocation + | ------- in this macro invocation | = note: this error originates in the macro `m::m` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -168,7 +168,7 @@ LL | Pub(0u8).priv_method(); | ^^^^^^^^^^^ private type ... LL | m::m!(); - | -------- in this macro invocation + | ------- in this macro invocation | = note: this error originates in the macro `m::m` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/proc-macro/attribute-after-derive-feature-gate.rs b/src/test/ui/proc-macro/attribute-after-derive-feature-gate.rs deleted file mode 100644 index f0fec67824..0000000000 --- a/src/test/ui/proc-macro/attribute-after-derive-feature-gate.rs +++ /dev/null @@ -1,37 +0,0 @@ -// gate-test-macro_attributes_in_derive_output -// aux-build: test-macros.rs - -#![feature(proc_macro_hygiene)] -#![feature(stmt_expr_attributes)] - -#[macro_use] -extern crate test_macros; - -#[derive(Empty)] -#[empty_attr] //~ ERROR macro attributes in `#[derive]` output are unstable -struct S1 { - field: [u8; 10], -} - -#[derive(Empty)] -#[empty_helper] -#[empty_attr] //~ ERROR macro attributes in `#[derive]` output are unstable -struct S2 { - field: [u8; 10], -} - -#[derive(Empty)] -struct S3 { - field: [u8; #[identity_attr] 10], //~ ERROR macro attributes in `#[derive]` output are unstable -} - -#[derive(Empty)] -struct S4 { - field: [u8; { - #[derive(Empty)] // OK, not gated - struct Inner; - 10 - }] -} - -fn main() {} diff --git a/src/test/ui/proc-macro/attribute-after-derive-feature-gate.stderr b/src/test/ui/proc-macro/attribute-after-derive-feature-gate.stderr deleted file mode 100644 index 74cace628b..0000000000 --- a/src/test/ui/proc-macro/attribute-after-derive-feature-gate.stderr +++ /dev/null @@ -1,30 +0,0 @@ -error[E0658]: macro attributes in `#[derive]` output are unstable - --> $DIR/attribute-after-derive-feature-gate.rs:11:3 - | -LL | #[empty_attr] - | ^^^^^^^^^^ - | - = note: see issue #81119 for more information - = help: add `#![feature(macro_attributes_in_derive_output)]` to the crate attributes to enable - -error[E0658]: macro attributes in `#[derive]` output are unstable - --> $DIR/attribute-after-derive-feature-gate.rs:18:3 - | -LL | #[empty_attr] - | ^^^^^^^^^^ - | - = note: see issue #81119 for more information - = help: add `#![feature(macro_attributes_in_derive_output)]` to the crate attributes to enable - -error[E0658]: macro attributes in `#[derive]` output are unstable - --> $DIR/attribute-after-derive-feature-gate.rs:25:19 - | -LL | field: [u8; #[identity_attr] 10], - | ^^^^^^^^^^^^^ - | - = note: see issue #81119 for more information - = help: add `#![feature(macro_attributes_in_derive_output)]` to the crate attributes to enable - -error: aborting due to 3 previous errors - -For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/proc-macro/attribute-after-derive.rs b/src/test/ui/proc-macro/attribute-after-derive.rs index ac3f28b6ef..0f0f27bff9 100644 --- a/src/test/ui/proc-macro/attribute-after-derive.rs +++ b/src/test/ui/proc-macro/attribute-after-derive.rs @@ -5,8 +5,6 @@ // compile-flags: -Z span-debug // aux-build: test-macros.rs -#![feature(macro_attributes_in_derive_output)] - #![no_std] // Don't load unnecessary hygiene information from std extern crate std; diff --git a/src/test/ui/proc-macro/attribute-after-derive.stdout b/src/test/ui/proc-macro/attribute-after-derive.stdout index 4c48e41ff3..c5b84b0367 100644 --- a/src/test/ui/proc-macro/attribute-after-derive.stdout +++ b/src/test/ui/proc-macro/attribute-after-derive.stdout @@ -3,35 +3,35 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [ Punct { ch: '#', spacing: Alone, - span: $DIR/attribute-after-derive.rs:17:1: 17:2 (#0), + span: $DIR/attribute-after-derive.rs:15:1: 15:2 (#0), }, Group { delimiter: Bracket, stream: TokenStream [ Ident { ident: "derive", - span: $DIR/attribute-after-derive.rs:17:3: 17:9 (#0), + span: $DIR/attribute-after-derive.rs:15:3: 15:9 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "Print", - span: $DIR/attribute-after-derive.rs:17:10: 17:15 (#0), + span: $DIR/attribute-after-derive.rs:15:10: 15:15 (#0), }, ], - span: $DIR/attribute-after-derive.rs:17:9: 17:16 (#0), + span: $DIR/attribute-after-derive.rs:15:9: 15:16 (#0), }, ], - span: $DIR/attribute-after-derive.rs:17:2: 17:17 (#0), + span: $DIR/attribute-after-derive.rs:15:2: 15:17 (#0), }, Ident { ident: "struct", - span: $DIR/attribute-after-derive.rs:18:1: 18:7 (#0), + span: $DIR/attribute-after-derive.rs:16:1: 16:7 (#0), }, Ident { ident: "AttributeDerive", - span: $DIR/attribute-after-derive.rs:18:8: 18:23 (#0), + span: $DIR/attribute-after-derive.rs:16:8: 16:23 (#0), }, Group { delimiter: Brace, @@ -39,64 +39,64 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [ Punct { ch: '#', spacing: Alone, - span: $DIR/attribute-after-derive.rs:19:5: 19:6 (#0), + span: $DIR/attribute-after-derive.rs:17:5: 17:6 (#0), }, Group { delimiter: Bracket, stream: TokenStream [ Ident { ident: "cfg", - span: $DIR/attribute-after-derive.rs:19:7: 19:10 (#0), + span: $DIR/attribute-after-derive.rs:17:7: 17:10 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "FALSE", - span: $DIR/attribute-after-derive.rs:19:11: 19:16 (#0), + span: $DIR/attribute-after-derive.rs:17:11: 17:16 (#0), }, ], - span: $DIR/attribute-after-derive.rs:19:10: 19:17 (#0), + span: $DIR/attribute-after-derive.rs:17:10: 17:17 (#0), }, ], - span: $DIR/attribute-after-derive.rs:19:6: 19:18 (#0), + span: $DIR/attribute-after-derive.rs:17:6: 17:18 (#0), }, Ident { ident: "field", - span: $DIR/attribute-after-derive.rs:20:5: 20:10 (#0), + span: $DIR/attribute-after-derive.rs:18:5: 18:10 (#0), }, Punct { ch: ':', spacing: Alone, - span: $DIR/attribute-after-derive.rs:20:10: 20:11 (#0), + span: $DIR/attribute-after-derive.rs:18:10: 18:11 (#0), }, Ident { ident: "u8", - span: $DIR/attribute-after-derive.rs:20:12: 20:14 (#0), + span: $DIR/attribute-after-derive.rs:18:12: 18:14 (#0), }, Punct { ch: ',', spacing: Alone, - span: $DIR/attribute-after-derive.rs:20:14: 20:15 (#0), + span: $DIR/attribute-after-derive.rs:18:14: 18:15 (#0), }, ], - span: $DIR/attribute-after-derive.rs:18:24: 21:2 (#0), + span: $DIR/attribute-after-derive.rs:16:24: 19:2 (#0), }, ] PRINT-DERIVE INPUT (DISPLAY): struct AttributeDerive { } PRINT-DERIVE INPUT (DEBUG): TokenStream [ Ident { ident: "struct", - span: $DIR/attribute-after-derive.rs:18:1: 18:7 (#0), + span: $DIR/attribute-after-derive.rs:16:1: 16:7 (#0), }, Ident { ident: "AttributeDerive", - span: $DIR/attribute-after-derive.rs:18:8: 18:23 (#0), + span: $DIR/attribute-after-derive.rs:16:8: 16:23 (#0), }, Group { delimiter: Brace, stream: TokenStream [], - span: $DIR/attribute-after-derive.rs:18:24: 21:2 (#0), + span: $DIR/attribute-after-derive.rs:16:24: 19:2 (#0), }, ] PRINT-DERIVE INPUT (DISPLAY): #[print_attr] struct DeriveAttribute { } @@ -104,45 +104,89 @@ PRINT-DERIVE INPUT (DEBUG): TokenStream [ Punct { ch: '#', spacing: Alone, - span: $DIR/attribute-after-derive.rs:24:1: 24:2 (#0), + span: $DIR/attribute-after-derive.rs:22:1: 22:2 (#0), }, Group { delimiter: Bracket, stream: TokenStream [ Ident { ident: "print_attr", - span: $DIR/attribute-after-derive.rs:24:3: 24:13 (#0), + span: $DIR/attribute-after-derive.rs:22:3: 22:13 (#0), }, ], - span: $DIR/attribute-after-derive.rs:24:2: 24:14 (#0), + span: $DIR/attribute-after-derive.rs:22:2: 22:14 (#0), }, Ident { ident: "struct", - span: $DIR/attribute-after-derive.rs:25:1: 25:7 (#0), + span: $DIR/attribute-after-derive.rs:23:1: 23:7 (#0), }, Ident { ident: "DeriveAttribute", - span: $DIR/attribute-after-derive.rs:25:8: 25:23 (#0), + span: $DIR/attribute-after-derive.rs:23:8: 23:23 (#0), }, Group { delimiter: Brace, stream: TokenStream [], - span: $DIR/attribute-after-derive.rs:25:24: 28:2 (#0), + span: $DIR/attribute-after-derive.rs:23:24: 26:2 (#0), }, ] -PRINT-ATTR INPUT (DISPLAY): struct DeriveAttribute { } +PRINT-ATTR INPUT (DISPLAY): struct DeriveAttribute { #[cfg(FALSE)] field : u8, } PRINT-ATTR INPUT (DEBUG): TokenStream [ Ident { ident: "struct", - span: $DIR/attribute-after-derive.rs:25:1: 25:7 (#0), + span: $DIR/attribute-after-derive.rs:23:1: 23:7 (#0), }, Ident { ident: "DeriveAttribute", - span: $DIR/attribute-after-derive.rs:25:8: 25:23 (#0), + span: $DIR/attribute-after-derive.rs:23:8: 23:23 (#0), }, Group { delimiter: Brace, - stream: TokenStream [], - span: $DIR/attribute-after-derive.rs:25:24: 28:2 (#0), + stream: TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/attribute-after-derive.rs:24:5: 24:6 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "cfg", + span: $DIR/attribute-after-derive.rs:24:7: 24:10 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "FALSE", + span: $DIR/attribute-after-derive.rs:24:11: 24:16 (#0), + }, + ], + span: $DIR/attribute-after-derive.rs:24:10: 24:17 (#0), + }, + ], + span: $DIR/attribute-after-derive.rs:24:6: 24:18 (#0), + }, + Ident { + ident: "field", + span: $DIR/attribute-after-derive.rs:25:5: 25:10 (#0), + }, + Punct { + ch: ':', + spacing: Alone, + span: $DIR/attribute-after-derive.rs:25:10: 25:11 (#0), + }, + Ident { + ident: "u8", + span: $DIR/attribute-after-derive.rs:25:12: 25:14 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/attribute-after-derive.rs:25:14: 25:15 (#0), + }, + ], + span: $DIR/attribute-after-derive.rs:23:24: 26:2 (#0), }, ] diff --git a/src/test/ui/proc-macro/auxiliary/is-available.rs b/src/test/ui/proc-macro/auxiliary/is-available.rs index 0caf186db1..03f5265e37 100644 --- a/src/test/ui/proc-macro/auxiliary/is-available.rs +++ b/src/test/ui/proc-macro/auxiliary/is-available.rs @@ -2,7 +2,6 @@ // no-prefer-dynamic #![crate_type = "proc-macro"] -#![feature(proc_macro_is_available)] extern crate proc_macro; diff --git a/src/test/ui/proc-macro/derive-helper-shadowing.stderr b/src/test/ui/proc-macro/derive-helper-shadowing.stderr index 3b160935a2..df462903fc 100644 --- a/src/test/ui/proc-macro/derive-helper-shadowing.stderr +++ b/src/test/ui/proc-macro/derive-helper-shadowing.stderr @@ -27,7 +27,7 @@ LL | #[empty_helper] | ^^^^^^^^^^^^ ... LL | gen_helper_use!(); - | ------------------ in this macro invocation + | ----------------- in this macro invocation | = note: consider importing this attribute macro: crate::empty_helper diff --git a/src/test/ui/proc-macro/gen-macro-rules-hygiene.stderr b/src/test/ui/proc-macro/gen-macro-rules-hygiene.stderr index b16b24b9dc..6060f872f2 100644 --- a/src/test/ui/proc-macro/gen-macro-rules-hygiene.stderr +++ b/src/test/ui/proc-macro/gen-macro-rules-hygiene.stderr @@ -2,10 +2,10 @@ error[E0426]: use of undeclared label `'label_use` --> $DIR/gen-macro-rules-hygiene.rs:12:1 | LL | gen_macro_rules!(); - | ^^^^^^^^^^^^^^^^^^^ undeclared label `'label_use` + | ^^^^^^^^^^^^^^^^^^ undeclared label `'label_use` ... LL | generated!(); - | ------------- in this macro invocation + | ------------ in this macro invocation | = note: this error originates in the macro `generated` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -13,10 +13,10 @@ error[E0425]: cannot find value `local_use` in this scope --> $DIR/gen-macro-rules-hygiene.rs:12:1 | LL | gen_macro_rules!(); - | ^^^^^^^^^^^^^^^^^^^ not found in this scope + | ^^^^^^^^^^^^^^^^^^ not found in this scope ... LL | generated!(); - | ------------- in this macro invocation + | ------------ in this macro invocation | = note: this error originates in the macro `generated` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/proc-macro/generate-mod.stderr b/src/test/ui/proc-macro/generate-mod.stderr index 285876aadb..be58cc40ed 100644 --- a/src/test/ui/proc-macro/generate-mod.stderr +++ b/src/test/ui/proc-macro/generate-mod.stderr @@ -2,7 +2,7 @@ error[E0412]: cannot find type `FromOutside` in this scope --> $DIR/generate-mod.rs:9:1 | LL | generate_mod::check!(); - | ^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope + | ^^^^^^^^^^^^^^^^^^^^^^ not found in this scope | = note: consider importing this struct: FromOutside @@ -12,7 +12,7 @@ error[E0412]: cannot find type `Outer` in this scope --> $DIR/generate-mod.rs:9:1 | LL | generate_mod::check!(); - | ^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope + | ^^^^^^^^^^^^^^^^^^^^^^ not found in this scope | = note: consider importing this struct: Outer @@ -82,3 +82,75 @@ LL | #[derive(generate_mod::CheckDerive)] error: aborting due to 4 previous errors; 4 warnings emitted For more information about this error, try `rustc --explain E0412`. +Future incompatibility report: Future breakage diagnostic: +warning: 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 + = warning: this was previously accepted 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 + = note: this warning 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 + --> $DIR/generate-mod.rs:16:10 + | +LL | #[derive(generate_mod::CheckDerive)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ names from parent modules are not accessible without an explicit import + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #83583 + = note: this warning 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 + --> $DIR/generate-mod.rs:23:14 + | +LL | #[derive(generate_mod::CheckDerive)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ names from parent modules are not accessible without an explicit import + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #83583 + = note: this warning 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 + --> $DIR/generate-mod.rs:23:14 + | +LL | #[derive(generate_mod::CheckDerive)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ names from parent modules are not accessible without an explicit import + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #83583 + = note: this warning 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 + --> $DIR/generate-mod.rs:30:10 + | +LL | #[derive(generate_mod::CheckDeriveLint)] // OK, lint is suppressed + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ names from parent modules are not accessible without an explicit import + | +note: the lint level is defined here + --> $DIR/generate-mod.rs:30:10 + | +LL | #[derive(generate_mod::CheckDeriveLint)] // OK, lint is suppressed + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = warning: this was previously accepted 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 + = note: this warning originates in the derive macro `generate_mod::CheckDeriveLint` (in Nightly builds, run with -Z macro-backtrace for more info) + +Future breakage diagnostic: +warning: cannot find type `OuterDeriveLint` in this scope + --> $DIR/generate-mod.rs:30:10 + | +LL | #[derive(generate_mod::CheckDeriveLint)] // OK, lint is suppressed + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ names from parent modules are not accessible without an explicit import + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #83583 + = note: this warning originates in the derive macro `generate_mod::CheckDeriveLint` (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.stderr b/src/test/ui/proc-macro/group-compat-hack/group-compat-hack.stderr index 001b345204..1a56291896 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 @@ -7,7 +7,7 @@ LL | #[my_macro] struct One($name); ::: $DIR/group-compat-hack.rs:27:5 | LL | impl_macros!(Foo); - | ------------------ in this macro invocation + | ----------------- in this macro invocation | = note: `#[warn(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! @@ -24,7 +24,7 @@ LL | #[my_macro] struct One($name); ::: $DIR/group-compat-hack.rs:44:5 | LL | impl_macros!(Foo); - | ------------------ in this macro invocation + | ----------------- in this macro invocation | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #83125 @@ -40,7 +40,7 @@ LL | #[my_macro] struct Two($name); ::: $DIR/group-compat-hack.rs:46:5 | LL | arrays!(Foo); - | ------------- in this macro invocation + | ------------ in this macro invocation | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #83125 @@ -56,7 +56,7 @@ LL | #[my_macro] struct Three($T); ::: $DIR/group-compat-hack.rs:55:5 | LL | tuple_from_req!(Foo); - | --------------------- in this macro invocation + | -------------------- in this macro invocation | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #83125 @@ -72,7 +72,7 @@ LL | #[my_macro] struct Three($T); ::: $DIR/group-compat-hack.rs:63:5 | LL | tuple_from_req!(Foo); - | --------------------- in this macro invocation + | -------------------- in this macro invocation | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #83125 @@ -91,7 +91,7 @@ LL | #[my_macro] struct One($name); ::: $DIR/group-compat-hack.rs:27:5 | LL | impl_macros!(Foo); - | ------------------ in this macro invocation + | ----------------- in this macro invocation | = note: `#[warn(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! @@ -109,7 +109,7 @@ LL | #[my_macro] struct One($name); ::: $DIR/group-compat-hack.rs:44:5 | LL | impl_macros!(Foo); - | ------------------ in this macro invocation + | ----------------- in this macro invocation | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #83125 @@ -126,7 +126,7 @@ LL | #[my_macro] struct Two($name); ::: $DIR/group-compat-hack.rs:46:5 | LL | arrays!(Foo); - | ------------- in this macro invocation + | ------------ in this macro invocation | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #83125 @@ -143,7 +143,7 @@ LL | #[my_macro] struct Three($T); ::: $DIR/group-compat-hack.rs:55:5 | LL | tuple_from_req!(Foo); - | --------------------- in this macro invocation + | -------------------- in this macro invocation | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #83125 @@ -160,7 +160,7 @@ LL | #[my_macro] struct Three($T); ::: $DIR/group-compat-hack.rs:63:5 | LL | tuple_from_req!(Foo); - | --------------------- in this macro invocation + | -------------------- in this macro invocation | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #83125 diff --git a/src/test/ui/proc-macro/invalid-punct-ident-1.stderr b/src/test/ui/proc-macro/invalid-punct-ident-1.stderr index 5ef22709cb..eaf41c080f 100644 --- a/src/test/ui/proc-macro/invalid-punct-ident-1.stderr +++ b/src/test/ui/proc-macro/invalid-punct-ident-1.stderr @@ -2,7 +2,7 @@ error: proc macro panicked --> $DIR/invalid-punct-ident-1.rs:19:1 | LL | invalid_punct!(); - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ | = help: message: unsupported character `'`'` diff --git a/src/test/ui/proc-macro/invalid-punct-ident-2.stderr b/src/test/ui/proc-macro/invalid-punct-ident-2.stderr index 4bd7a5351d..f7e1f4bc7d 100644 --- a/src/test/ui/proc-macro/invalid-punct-ident-2.stderr +++ b/src/test/ui/proc-macro/invalid-punct-ident-2.stderr @@ -2,7 +2,7 @@ error: proc macro panicked --> $DIR/invalid-punct-ident-2.rs:19:1 | LL | invalid_ident!(); - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ | = help: message: `"*"` is not a valid identifier diff --git a/src/test/ui/proc-macro/invalid-punct-ident-3.stderr b/src/test/ui/proc-macro/invalid-punct-ident-3.stderr index 072d13956a..541c71d74d 100644 --- a/src/test/ui/proc-macro/invalid-punct-ident-3.stderr +++ b/src/test/ui/proc-macro/invalid-punct-ident-3.stderr @@ -2,7 +2,7 @@ error: proc macro panicked --> $DIR/invalid-punct-ident-3.rs:19:1 | LL | invalid_raw_ident!(); - | ^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^ | = help: message: `self` cannot be a raw identifier diff --git a/src/test/ui/proc-macro/invalid-punct-ident-4.stderr b/src/test/ui/proc-macro/invalid-punct-ident-4.stderr index 59cf767c55..deb93b8936 100644 --- a/src/test/ui/proc-macro/invalid-punct-ident-4.stderr +++ b/src/test/ui/proc-macro/invalid-punct-ident-4.stderr @@ -2,7 +2,7 @@ error: unexpected closing delimiter: `)` --> $DIR/invalid-punct-ident-4.rs:6:1 | LL | lexer_failure!(); - | ^^^^^^^^^^^^^^^^^ unexpected closing delimiter + | ^^^^^^^^^^^^^^^^ unexpected closing delimiter | = note: this error originates in the macro `lexer_failure` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -10,7 +10,7 @@ error: proc macro panicked --> $DIR/invalid-punct-ident-4.rs:6:1 | LL | lexer_failure!(); - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ error[E0308]: mismatched types --> $DIR/invalid-punct-ident-4.rs:11:33 diff --git a/src/test/ui/proc-macro/is-available.rs b/src/test/ui/proc-macro/is-available.rs index 52f7e00d57..b32bb61b49 100644 --- a/src/test/ui/proc-macro/is-available.rs +++ b/src/test/ui/proc-macro/is-available.rs @@ -1,7 +1,5 @@ // run-pass -#![feature(proc_macro_is_available)] - extern crate proc_macro; // aux-build:is-available.rs diff --git a/src/test/ui/proc-macro/issue-83510.stderr b/src/test/ui/proc-macro/issue-83510.stderr index 040ace9160..e0628a3179 100644 --- a/src/test/ui/proc-macro/issue-83510.stderr +++ b/src/test/ui/proc-macro/issue-83510.stderr @@ -2,7 +2,7 @@ error[E0412]: cannot find type `Foo` in this scope --> $DIR/issue-83510.rs:5:1 | LL | issue_83510::dance_like_you_want_to_ice!(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope | = note: this error originates in the macro `issue_83510::dance_like_you_want_to_ice` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -10,7 +10,7 @@ error[E0404]: expected trait, found struct `Box` --> $DIR/issue-83510.rs:5:1 | LL | issue_83510::dance_like_you_want_to_ice!(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not a trait + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not a trait | = note: this error originates in the macro `issue_83510::dance_like_you_want_to_ice` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -18,7 +18,7 @@ error[E0405]: cannot find trait `Baz` in this scope --> $DIR/issue-83510.rs:5:1 | LL | issue_83510::dance_like_you_want_to_ice!(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope | = note: this error originates in the macro `issue_83510::dance_like_you_want_to_ice` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -26,7 +26,7 @@ error[E0658]: inherent associated types are unstable --> $DIR/issue-83510.rs:5:1 | LL | issue_83510::dance_like_you_want_to_ice!(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: see issue #8995 for more information = help: add `#![feature(inherent_associated_types)]` to the crate attributes to enable diff --git a/src/test/ui/proc-macro/issue-86781-bad-inner-doc.fixed b/src/test/ui/proc-macro/issue-86781-bad-inner-doc.fixed new file mode 100644 index 0000000000..426a5fa723 --- /dev/null +++ b/src/test/ui/proc-macro/issue-86781-bad-inner-doc.fixed @@ -0,0 +1,12 @@ +// aux-build:test-macros.rs +// run-rustfix + +#[macro_use] +extern crate test_macros; + +/// Inner doc comment +//~^ ERROR expected outer doc comment +#[derive(Empty)] +pub struct Foo; //~ NOTE the inner doc comment doesn't annotate this struct + +fn main() {} diff --git a/src/test/ui/proc-macro/issue-86781-bad-inner-doc.rs b/src/test/ui/proc-macro/issue-86781-bad-inner-doc.rs index 8be1ae7773..31e3f3c859 100644 --- a/src/test/ui/proc-macro/issue-86781-bad-inner-doc.rs +++ b/src/test/ui/proc-macro/issue-86781-bad-inner-doc.rs @@ -1,4 +1,5 @@ // aux-build:test-macros.rs +// run-rustfix #[macro_use] extern crate test_macros; @@ -6,6 +7,6 @@ extern crate test_macros; //! Inner doc comment //~^ ERROR expected outer doc comment #[derive(Empty)] -pub struct Foo; +pub struct Foo; //~ NOTE the inner doc comment doesn't annotate this struct fn main() {} diff --git a/src/test/ui/proc-macro/issue-86781-bad-inner-doc.stderr b/src/test/ui/proc-macro/issue-86781-bad-inner-doc.stderr index 0b2e612ee5..a92f07522e 100644 --- a/src/test/ui/proc-macro/issue-86781-bad-inner-doc.stderr +++ b/src/test/ui/proc-macro/issue-86781-bad-inner-doc.stderr @@ -1,10 +1,16 @@ error[E0753]: expected outer doc comment - --> $DIR/issue-86781-bad-inner-doc.rs:6:1 + --> $DIR/issue-86781-bad-inner-doc.rs:7:1 | LL | //! Inner doc comment | ^^^^^^^^^^^^^^^^^^^^^ +... +LL | pub struct Foo; + | --------------- the inner doc comment doesn't annotate this struct | - = note: inner doc comments like this (starting with `//!` or `/*!`) can only appear before items +help: to annotate the struct, change the doc comment from inner to outer style + | +LL | /// Inner doc comment + | ~ error: aborting due to previous error diff --git a/src/test/ui/proc-macro/lints_in_proc_macros.stderr b/src/test/ui/proc-macro/lints_in_proc_macros.stderr index f36f937fc0..4dd8be7d9b 100644 --- a/src/test/ui/proc-macro/lints_in_proc_macros.stderr +++ b/src/test/ui/proc-macro/lints_in_proc_macros.stderr @@ -2,7 +2,7 @@ error[E0425]: cannot find value `foobar2` in this scope --> $DIR/lints_in_proc_macros.rs:9:5 | LL | bang_proc_macro2!(); - | ^^^^^^^^^^^^^^^^^^^^ help: a local variable with a similar name exists: `foobar` + | ^^^^^^^^^^^^^^^^^^^ help: a local variable with a similar name exists: `foobar` | = note: this error originates in the macro `bang_proc_macro2` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/proc-macro/macro-rules-derive.stderr b/src/test/ui/proc-macro/macro-rules-derive.stderr index 85766548bf..517cbabd5c 100644 --- a/src/test/ui/proc-macro/macro-rules-derive.stderr +++ b/src/test/ui/proc-macro/macro-rules-derive.stderr @@ -5,7 +5,7 @@ LL | field: MissingType | ^^^^^^^^^^^ not found in this scope ... LL | produce_it!(MyName); - | -------------------- in this macro invocation + | ------------------- in this macro invocation | = note: this error originates in the macro `produce_it` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/proc-macro/meta-macro-hygiene.rs b/src/test/ui/proc-macro/meta-macro-hygiene.rs index 2536b2fa90..62968ea54e 100644 --- a/src/test/ui/proc-macro/meta-macro-hygiene.rs +++ b/src/test/ui/proc-macro/meta-macro-hygiene.rs @@ -4,6 +4,7 @@ // compile-flags: -Z span-debug -Z macro-backtrace -Z unpretty=expanded,hygiene -Z trim-diagnostic-paths=no // check-pass // normalize-stdout-test "\d+#" -> "0#" +// normalize-stdout-test "expn\d{3,}" -> "expnNNN" // // We don't care about symbol ids, so we set them all to 0 // in the stdout diff --git a/src/test/ui/proc-macro/meta-macro-hygiene.stdout b/src/test/ui/proc-macro/meta-macro-hygiene.stdout index 2524d8273b..7f7a1009c9 100644 --- a/src/test/ui/proc-macro/meta-macro-hygiene.stdout +++ b/src/test/ui/proc-macro/meta-macro-hygiene.stdout @@ -1,5 +1,5 @@ Def site: $DIR/auxiliary/make-macro.rs:7:9: 7:56 (#5) -Input: TokenStream [Ident { ident: "$crate", span: $DIR/meta-macro-hygiene.rs:23:37: 23:43 (#4) }, Punct { ch: ':', spacing: Joint, span: $DIR/meta-macro-hygiene.rs:23:43: 23:45 (#4) }, Punct { ch: ':', spacing: Alone, span: $DIR/meta-macro-hygiene.rs:23:43: 23:45 (#4) }, Ident { ident: "dummy", span: $DIR/meta-macro-hygiene.rs:23:45: 23:50 (#4) }, Punct { ch: '!', spacing: Alone, span: $DIR/meta-macro-hygiene.rs:23:50: 23:51 (#4) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: $DIR/meta-macro-hygiene.rs:23:51: 23:53 (#4) }] +Input: TokenStream [Ident { ident: "$crate", span: $DIR/meta-macro-hygiene.rs:24:37: 24:43 (#4) }, Punct { ch: ':', spacing: Joint, span: $DIR/meta-macro-hygiene.rs:24:43: 24:45 (#4) }, Punct { ch: ':', spacing: Alone, span: $DIR/meta-macro-hygiene.rs:24:43: 24:45 (#4) }, Ident { ident: "dummy", span: $DIR/meta-macro-hygiene.rs:24:45: 24:50 (#4) }, Punct { ch: '!', spacing: Alone, span: $DIR/meta-macro-hygiene.rs:24:50: 24:51 (#4) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: $DIR/meta-macro-hygiene.rs:24:51: 24:53 (#4) }] Respanned: TokenStream [Ident { ident: "$crate", span: $DIR/auxiliary/make-macro.rs:7:9: 7:56 (#5) }, Punct { ch: ':', spacing: Joint, span: $DIR/auxiliary/make-macro.rs:7:9: 7:56 (#5) }, Punct { ch: ':', spacing: Alone, span: $DIR/auxiliary/make-macro.rs:7:9: 7:56 (#5) }, Ident { ident: "dummy", span: $DIR/auxiliary/make-macro.rs:7:9: 7:56 (#5) }, Punct { ch: '!', spacing: Alone, span: $DIR/auxiliary/make-macro.rs:7:9: 7:56 (#5) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: $DIR/auxiliary/make-macro.rs:7:9: 7:56 (#5) }] #![feature /* 0#0 */(prelude_import)] // aux-build:make-macro.rs @@ -8,6 +8,7 @@ Respanned: TokenStream [Ident { ident: "$crate", span: $DIR/auxiliary/make-macro // compile-flags: -Z span-debug -Z macro-backtrace -Z unpretty=expanded,hygiene -Z trim-diagnostic-paths=no // check-pass // normalize-stdout-test "\d+#" -> "0#" +// normalize-stdout-test "expn\d{3,}" -> "expnNNN" // // We don't care about symbol ids, so we set them all to 0 // in the stdout @@ -48,6 +49,7 @@ 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(Bang, "include") crate2::{{expn1}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: AstPass(StdImports) SyntaxContexts: diff --git a/src/test/ui/proc-macro/mixed-site-span.stderr b/src/test/ui/proc-macro/mixed-site-span.stderr index c8ed20d30c..60f082d177 100644 --- a/src/test/ui/proc-macro/mixed-site-span.stderr +++ b/src/test/ui/proc-macro/mixed-site-span.stderr @@ -2,7 +2,7 @@ error[E0426]: use of undeclared label `'label_use` --> $DIR/mixed-site-span.rs:13:9 | LL | proc_macro_rules!(); - | ^^^^^^^^^^^^^^^^^^^^ undeclared label `'label_use` + | ^^^^^^^^^^^^^^^^^^^ undeclared label `'label_use` | = note: this error originates in the macro `proc_macro_rules` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -10,7 +10,7 @@ error[E0425]: cannot find value `local_use` in this scope --> $DIR/mixed-site-span.rs:13:9 | LL | proc_macro_rules!(); - | ^^^^^^^^^^^^^^^^^^^^ not found in this scope + | ^^^^^^^^^^^^^^^^^^^ not found in this scope | = note: this error originates in the macro `proc_macro_rules` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -24,7 +24,7 @@ error[E0412]: cannot find type `ItemUse` in crate `$crate` --> $DIR/mixed-site-span.rs:24:1 | LL | pass_dollar_crate!(); - | ^^^^^^^^^^^^^^^^^^^^^ not found in `$crate` + | ^^^^^^^^^^^^^^^^^^^^ not found in `$crate` | = note: this error originates in the macro `proc_macro_rules` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/proc-macro/multispan.stderr b/src/test/ui/proc-macro/multispan.stderr index d37df81496..0aea02bbda 100644 --- a/src/test/ui/proc-macro/multispan.stderr +++ b/src/test/ui/proc-macro/multispan.stderr @@ -2,7 +2,7 @@ error: hello to you, too! --> $DIR/multispan.rs:12:5 | LL | hello!(hi); - | ^^^^^^^^^^^ + | ^^^^^^^^^^ | note: found these 'hi's --> $DIR/multispan.rs:12:12 @@ -15,7 +15,7 @@ error: hello to you, too! --> $DIR/multispan.rs:15:5 | LL | hello!(hi hi); - | ^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ | note: found these 'hi's --> $DIR/multispan.rs:15:12 @@ -28,7 +28,7 @@ error: hello to you, too! --> $DIR/multispan.rs:18:5 | LL | hello!(hi hi hi); - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ | note: found these 'hi's --> $DIR/multispan.rs:18:12 @@ -41,7 +41,7 @@ error: hello to you, too! --> $DIR/multispan.rs:21:5 | LL | hello!(hi hey hi yo hi beep beep hi hi); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: found these 'hi's --> $DIR/multispan.rs:21:12 @@ -54,7 +54,7 @@ error: hello to you, too! --> $DIR/multispan.rs:22:5 | LL | hello!(hi there, hi how are you? hi... hi.); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: found these 'hi's --> $DIR/multispan.rs:22:12 @@ -67,7 +67,7 @@ error: hello to you, too! --> $DIR/multispan.rs:23:5 | LL | hello!(whoah. hi di hi di ho); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: found these 'hi's --> $DIR/multispan.rs:23:19 @@ -80,7 +80,7 @@ error: hello to you, too! --> $DIR/multispan.rs:24:5 | LL | hello!(hi good hi and good bye); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: found these 'hi's --> $DIR/multispan.rs:24:12 diff --git a/src/test/ui/proc-macro/nonterminal-token-hygiene.rs b/src/test/ui/proc-macro/nonterminal-token-hygiene.rs index 98fd430600..fa52a975bc 100644 --- a/src/test/ui/proc-macro/nonterminal-token-hygiene.rs +++ b/src/test/ui/proc-macro/nonterminal-token-hygiene.rs @@ -4,6 +4,7 @@ // compile-flags: -Z span-debug -Z macro-backtrace -Z unpretty=expanded,hygiene // compile-flags: -Z trim-diagnostic-paths=no // normalize-stdout-test "\d+#" -> "0#" +// normalize-stdout-test "expn\d{3,}" -> "expnNNN" // aux-build:test-macros.rs #![feature(decl_macro)] diff --git a/src/test/ui/proc-macro/nonterminal-token-hygiene.stdout b/src/test/ui/proc-macro/nonterminal-token-hygiene.stdout index b5ab82737e..0780386381 100644 --- a/src/test/ui/proc-macro/nonterminal-token-hygiene.stdout +++ b/src/test/ui/proc-macro/nonterminal-token-hygiene.stdout @@ -6,19 +6,19 @@ PRINT-BANG INPUT (DEBUG): TokenStream [ stream: TokenStream [ Ident { ident: "struct", - span: $DIR/nonterminal-token-hygiene.rs:30:5: 30:11 (#5), + span: $DIR/nonterminal-token-hygiene.rs:31:5: 31:11 (#5), }, Ident { ident: "S", - span: $DIR/nonterminal-token-hygiene.rs:30:12: 30:13 (#5), + span: $DIR/nonterminal-token-hygiene.rs:31:12: 31:13 (#5), }, Punct { ch: ';', spacing: Alone, - span: $DIR/nonterminal-token-hygiene.rs:30:13: 30:14 (#5), + span: $DIR/nonterminal-token-hygiene.rs:31:13: 31:14 (#5), }, ], - span: $DIR/nonterminal-token-hygiene.rs:20:27: 20:32 (#6), + span: $DIR/nonterminal-token-hygiene.rs:21:27: 21:32 (#6), }, ] #![feature /* 0#0 */(prelude_import)] @@ -29,6 +29,7 @@ PRINT-BANG INPUT (DEBUG): TokenStream [ // compile-flags: -Z span-debug -Z macro-backtrace -Z unpretty=expanded,hygiene // compile-flags: -Z trim-diagnostic-paths=no // normalize-stdout-test "\d+#" -> "0#" +// normalize-stdout-test "expn\d{3,}" -> "expnNNN" // aux-build:test-macros.rs #![feature /* 0#0 */(decl_macro)] @@ -72,6 +73,7 @@ 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(Bang, "include") crate2::{{expn1}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: AstPass(StdImports) SyntaxContexts: diff --git a/src/test/ui/proc-macro/parent-source-spans.stderr b/src/test/ui/proc-macro/parent-source-spans.stderr index 071e103742..4548269b50 100644 --- a/src/test/ui/proc-macro/parent-source-spans.stderr +++ b/src/test/ui/proc-macro/parent-source-spans.stderr @@ -5,7 +5,7 @@ LL | three!($a, $b); | ^^ ... LL | one!("hello", "world"); - | ----------------------- in this macro invocation + | ---------------------- in this macro invocation | = note: this error originates in the macro `two` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -16,7 +16,7 @@ LL | three!($a, $b); | ^^ ... LL | one!("hello", "world"); - | ----------------------- in this macro invocation + | ---------------------- in this macro invocation | = note: this error originates in the macro `two` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -24,10 +24,10 @@ error: first parent: "hello" --> $DIR/parent-source-spans.rs:10:5 | LL | two!($a, $b); - | ^^^^^^^^^^^^^ + | ^^^^^^^^^^^^ ... LL | one!("hello", "world"); - | ----------------------- in this macro invocation + | ---------------------- in this macro invocation | = note: this error originates in the macro `one` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -35,10 +35,10 @@ error: second parent: "world" --> $DIR/parent-source-spans.rs:10:5 | LL | two!($a, $b); - | ^^^^^^^^^^^^^ + | ^^^^^^^^^^^^ ... LL | one!("hello", "world"); - | ----------------------- in this macro invocation + | ---------------------- in this macro invocation | = note: this error originates in the macro `one` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -46,25 +46,25 @@ error: first grandparent: "hello" --> $DIR/parent-source-spans.rs:36:5 | LL | one!("hello", "world"); - | ^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^ error: second grandparent: "world" --> $DIR/parent-source-spans.rs:36:5 | LL | one!("hello", "world"); - | ^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^ error: first source: "hello" --> $DIR/parent-source-spans.rs:36:5 | LL | one!("hello", "world"); - | ^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^ error: second source: "world" --> $DIR/parent-source-spans.rs:36:5 | LL | one!("hello", "world"); - | ^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^ error: first final: "yay" --> $DIR/parent-source-spans.rs:16:12 @@ -73,7 +73,7 @@ LL | three!($a, $b); | ^^ ... LL | two!("yay", "rust"); - | -------------------- in this macro invocation + | ------------------- in this macro invocation | = note: this error originates in the macro `two` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -84,7 +84,7 @@ LL | three!($a, $b); | ^^ ... LL | two!("yay", "rust"); - | -------------------- in this macro invocation + | ------------------- in this macro invocation | = note: this error originates in the macro `two` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -92,25 +92,25 @@ error: first parent: "yay" --> $DIR/parent-source-spans.rs:42:5 | LL | two!("yay", "rust"); - | ^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^ error: second parent: "rust" --> $DIR/parent-source-spans.rs:42:5 | LL | two!("yay", "rust"); - | ^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^ error: first source: "yay" --> $DIR/parent-source-spans.rs:42:5 | LL | two!("yay", "rust"); - | ^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^ error: second source: "rust" --> $DIR/parent-source-spans.rs:42:5 | LL | two!("yay", "rust"); - | ^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^ error: first final: "hip" --> $DIR/parent-source-spans.rs:48:12 @@ -140,10 +140,10 @@ error[E0425]: cannot find value `ok` in this scope --> $DIR/parent-source-spans.rs:29:5 | LL | parent_source_spans!($($tokens)*); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: a tuple variant with a similar name exists: `Ok` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: a tuple variant with a similar name exists: `Ok` ... LL | one!("hello", "world"); - | ----------------------- in this macro invocation + | ---------------------- in this macro invocation | ::: $SRC_DIR/core/src/result.rs:LL:COL | @@ -156,10 +156,10 @@ error[E0425]: cannot find value `ok` in this scope --> $DIR/parent-source-spans.rs:29:5 | LL | parent_source_spans!($($tokens)*); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: a tuple variant with a similar name exists: `Ok` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: a tuple variant with a similar name exists: `Ok` ... LL | two!("yay", "rust"); - | -------------------- in this macro invocation + | ------------------- in this macro invocation | ::: $SRC_DIR/core/src/result.rs:LL:COL | @@ -172,10 +172,10 @@ error[E0425]: cannot find value `ok` in this scope --> $DIR/parent-source-spans.rs:29:5 | LL | parent_source_spans!($($tokens)*); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: a tuple variant with a similar name exists: `Ok` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: a tuple variant with a similar name exists: `Ok` ... LL | three!("hip", "hop"); - | --------------------- in this macro invocation + | -------------------- in this macro invocation | ::: $SRC_DIR/core/src/result.rs:LL:COL | diff --git a/src/test/ui/proc-macro/raw-ident.stderr b/src/test/ui/proc-macro/raw-ident.stderr index ee6dffe93e..905a5f9463 100644 --- a/src/test/ui/proc-macro/raw-ident.stderr +++ b/src/test/ui/proc-macro/raw-ident.stderr @@ -2,7 +2,7 @@ error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found --> $DIR/raw-ident.rs:15:5 | LL | make_bad_struct!(S); - | ^^^^^^^^^^^^^^^^^^^^ expected one of 8 possible tokens + | ^^^^^^^^^^^^^^^^^^^ expected one of 8 possible tokens | = note: this error originates in the macro `make_bad_struct` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/proc-macro/span-api-tests.rs b/src/test/ui/proc-macro/span-api-tests.rs index 5c149e4a1e..914ad54ed0 100644 --- a/src/test/ui/proc-macro/span-api-tests.rs +++ b/src/test/ui/proc-macro/span-api-tests.rs @@ -41,7 +41,7 @@ fn main() { reemit!(macro_stringify!(Hello, world!)), "reemit!(macro_stringify!(Hello, world!))" ); - let r = "reemit!(assert_eq!(macro_stringify!(Hello, world!), r));"; + let r = "reemit!(assert_eq!(macro_stringify!(Hello, world!), r))"; reemit!(assert_eq!(macro_stringify!(Hello, world!), r)); assert_eq!(macro_stringify!( diff --git a/src/test/ui/proc-macro/span-from-proc-macro.stderr b/src/test/ui/proc-macro/span-from-proc-macro.stderr index 11ee20e846..7beed505a7 100644 --- a/src/test/ui/proc-macro/span-from-proc-macro.stderr +++ b/src/test/ui/proc-macro/span-from-proc-macro.stderr @@ -38,7 +38,7 @@ LL | my_ident ::: $DIR/span-from-proc-macro.rs:16:5 | LL | other_error_from_bang!(); - | ------------------------- in this macro invocation + | ------------------------ in this macro invocation error[E0308]: mismatched types --> $DIR/auxiliary/span-from-proc-macro.rs:16:36 @@ -54,7 +54,7 @@ LL | pub fn error_from_bang(_input: TokenStream) -> TokenStream { ::: $DIR/span-from-proc-macro.rs:15:5 | LL | error_from_bang!(); - | ------------------- in this macro invocation + | ------------------ in this macro invocation error: aborting due to 4 previous errors diff --git a/src/test/ui/proc-macro/span-preservation.stderr b/src/test/ui/proc-macro/span-preservation.stderr index 713560772e..e9a44ccb12 100644 --- a/src/test/ui/proc-macro/span-preservation.stderr +++ b/src/test/ui/proc-macro/span-preservation.stderr @@ -18,7 +18,7 @@ LL | Some(x) => { return x }, help: you can convert an `isize` to a `usize` and panic if the converted value doesn't fit | LL | Some(x) => { return x.try_into().unwrap() }, - | ~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/span-preservation.rs:33:22 diff --git a/src/test/ui/proc-macro/subspan.stderr b/src/test/ui/proc-macro/subspan.stderr index d65b1d0cfa..b5dacba0e3 100644 --- a/src/test/ui/proc-macro/subspan.stderr +++ b/src/test/ui/proc-macro/subspan.stderr @@ -2,7 +2,7 @@ error: found 'hi's --> $DIR/subspan.rs:11:1 | LL | subspan!("hi"); - | ^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^ | note: here --> $DIR/subspan.rs:11:11 @@ -15,7 +15,7 @@ error: found 'hi's --> $DIR/subspan.rs:14:1 | LL | subspan!("hihi"); - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ | note: here --> $DIR/subspan.rs:14:11 @@ -28,7 +28,7 @@ error: found 'hi's --> $DIR/subspan.rs:17:1 | LL | subspan!("hihihi"); - | ^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^ | note: here --> $DIR/subspan.rs:17:11 @@ -41,7 +41,7 @@ error: found 'hi's --> $DIR/subspan.rs:20:1 | LL | subspan!("why I hide? hi!"); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: here --> $DIR/subspan.rs:20:17 @@ -54,7 +54,7 @@ error: found 'hi's --> $DIR/subspan.rs:21:1 | LL | subspan!("hey, hi, hidy, hidy, hi hi"); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: here --> $DIR/subspan.rs:21:16 @@ -67,7 +67,7 @@ error: found 'hi's --> $DIR/subspan.rs:22:1 | LL | subspan!("this is a hi, and this is another hi"); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: here --> $DIR/subspan.rs:22:12 @@ -80,7 +80,7 @@ error: found 'hi's --> $DIR/subspan.rs:23:1 | LL | subspan!("how are you this evening"); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: here --> $DIR/subspan.rs:23:24 @@ -93,7 +93,7 @@ error: found 'hi's --> $DIR/subspan.rs:24:1 | LL | subspan!("this is highly eradic"); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: here --> $DIR/subspan.rs:24:12 diff --git a/src/test/ui/proc-macro/three-equals.stderr b/src/test/ui/proc-macro/three-equals.stderr index 485aefe62f..1ce5e02bd8 100644 --- a/src/test/ui/proc-macro/three-equals.stderr +++ b/src/test/ui/proc-macro/three-equals.stderr @@ -2,7 +2,7 @@ error: found 2 equal signs, need exactly 3 --> $DIR/three-equals.rs:12:5 | LL | three_equals!(==); - | ^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^ | = help: input must be: `===` = note: this error originates in the macro `three_equals` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/proc-macro/weird-hygiene.stderr b/src/test/ui/proc-macro/weird-hygiene.stderr index 03a984c58c..b4e7fe444a 100644 --- a/src/test/ui/proc-macro/weird-hygiene.stderr +++ b/src/test/ui/proc-macro/weird-hygiene.stderr @@ -5,7 +5,7 @@ LL | Value = (stringify!($tokens + hidden_ident), 1).1 | ^^^^^^^^^^^^ not found in this scope ... LL | other!(50); - | ----------- in this macro invocation + | ---------- in this macro invocation | = note: this error originates in the macro `inner` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -16,7 +16,7 @@ LL | hidden_ident | ^^^^^^^^^^^^ not found in this scope ... LL | invoke_it!(25); - | --------------- in this macro invocation + | -------------- in this macro invocation | = note: this error originates in the macro `invoke_it` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/process/process-panic-after-fork.rs b/src/test/ui/process/process-panic-after-fork.rs index ad749371be..1ccf6bb051 100644 --- a/src/test/ui/process/process-panic-after-fork.rs +++ b/src/test/ui/process/process-panic-after-fork.rs @@ -23,21 +23,6 @@ use std::sync::atomic::{AtomicU32, Ordering}; use libc::c_int; -#[cfg(not(target_os = "linux"))] -fn getpid() -> u32 { - process::id() -} - -/// We need to directly use the getpid syscall instead of using `process::id()` -/// because the libc wrapper might return incorrect values after a process was -/// forked. -#[cfg(target_os = "linux")] -fn getpid() -> u32 { - unsafe { - libc::syscall(libc::SYS_getpid) as _ - } -} - /// This stunt allocator allows us to spot heap allocations in the child. struct PidChecking { parent: A, @@ -59,7 +44,7 @@ impl PidChecking { fn check(&self) { let require_pid = self.require_pid.load(Ordering::Acquire); if require_pid != 0 { - let actual_pid = getpid(); + let actual_pid = process::id(); if require_pid != actual_pid { unsafe { libc::raise(libc::SIGUSR1); diff --git a/src/test/ui/pure-sum.rs b/src/test/ui/pure-sum.rs index 2ff6f935a0..2f2ece75eb 100644 --- a/src/test/ui/pure-sum.rs +++ b/src/test/ui/pure-sum.rs @@ -5,8 +5,6 @@ // pretty-expanded FIXME #23616 -#![feature(box_syntax)] - fn sums_to(v: Vec , sum: isize) -> bool { let mut i = 0; let mut sum0 = 0; @@ -19,7 +17,7 @@ fn sums_to(v: Vec , sum: isize) -> bool { fn sums_to_using_uniq(v: Vec , sum: isize) -> bool { let mut i = 0; - let mut sum0: Box<_> = box 0; + let mut sum0: Box<_> = 0.into(); while i < v.len() { *sum0 += v[i]; i += 1; @@ -41,7 +39,7 @@ struct F { f: T } fn sums_to_using_uniq_rec(v: Vec , sum: isize) -> bool { let mut i = 0; - let mut sum0 = F::> {f: box 0}; + let mut sum0 = F::> {f: 0.into() }; while i < v.len() { *sum0.f += v[i]; i += 1; diff --git a/src/test/ui/rcvr-borrowed-to-region.rs b/src/test/ui/rcvr-borrowed-to-region.rs index 37113bc0a0..7f32b8b91a 100644 --- a/src/test/ui/rcvr-borrowed-to-region.rs +++ b/src/test/ui/rcvr-borrowed-to-region.rs @@ -1,7 +1,6 @@ // run-pass #![allow(non_camel_case_types)] -#![feature(box_syntax)] trait get { fn get(self) -> isize; @@ -17,7 +16,7 @@ impl<'a> get for &'a isize { } pub fn main() { - let x: Box<_> = box 6; + let x: Box<_> = 6.into(); let y = x.get(); println!("y={}", y); assert_eq!(y, 6); diff --git a/src/test/ui/reachable/expr_again.rs b/src/test/ui/reachable/expr_again.rs index 243fed0c8c..6049321337 100644 --- a/src/test/ui/reachable/expr_again.rs +++ b/src/test/ui/reachable/expr_again.rs @@ -1,5 +1,5 @@ -#![feature(box_syntax)] #![allow(unused_variables)] + #![deny(unreachable_code)] fn main() { diff --git a/src/test/ui/reachable/expr_again.stderr b/src/test/ui/reachable/expr_again.stderr index 0192f4359e..a3c54e1356 100644 --- a/src/test/ui/reachable/expr_again.stderr +++ b/src/test/ui/reachable/expr_again.stderr @@ -4,7 +4,7 @@ error: unreachable statement LL | continue; | -------- any code following this expression is unreachable LL | println!("hi"); - | ^^^^^^^^^^^^^^^ unreachable statement + | ^^^^^^^^^^^^^^ unreachable statement | note: the lint level is defined here --> $DIR/expr_again.rs:3:9 diff --git a/src/test/ui/reachable/expr_block.stderr b/src/test/ui/reachable/expr_block.stderr index 4ed84c566a..d5f248a249 100644 --- a/src/test/ui/reachable/expr_block.stderr +++ b/src/test/ui/reachable/expr_block.stderr @@ -18,7 +18,7 @@ error: unreachable statement LL | return; | ------ any code following this expression is unreachable LL | println!("foo"); - | ^^^^^^^^^^^^^^^^ unreachable statement + | ^^^^^^^^^^^^^^^ unreachable statement | = note: this error originates in the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/reachable/expr_if.stderr b/src/test/ui/reachable/expr_if.stderr index 1112273f44..ebd0b5a3eb 100644 --- a/src/test/ui/reachable/expr_if.stderr +++ b/src/test/ui/reachable/expr_if.stderr @@ -22,7 +22,7 @@ LL | return; | ------ any code following this expression is unreachable ... LL | println!("But I am."); - | ^^^^^^^^^^^^^^^^^^^^^^ unreachable statement + | ^^^^^^^^^^^^^^^^^^^^^ unreachable statement | = note: this error originates in the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/reachable/expr_loop.stderr b/src/test/ui/reachable/expr_loop.stderr index d6c140375e..9185846860 100644 --- a/src/test/ui/reachable/expr_loop.stderr +++ b/src/test/ui/reachable/expr_loop.stderr @@ -4,7 +4,7 @@ error: unreachable statement LL | loop { return; } | ------ any code following this expression is unreachable LL | println!("I am dead."); - | ^^^^^^^^^^^^^^^^^^^^^^^ unreachable statement + | ^^^^^^^^^^^^^^^^^^^^^^ unreachable statement | note: the lint level is defined here --> $DIR/expr_loop.rs:4:9 @@ -19,7 +19,7 @@ error: unreachable statement LL | loop { return; } | ------ any code following this expression is unreachable LL | println!("I am dead."); - | ^^^^^^^^^^^^^^^^^^^^^^^ unreachable statement + | ^^^^^^^^^^^^^^^^^^^^^^ unreachable statement | = note: this error originates in the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -29,7 +29,7 @@ error: unreachable statement LL | loop { 'middle: loop { loop { break 'middle; } } } | -------------------------------------------------- any code following this expression is unreachable LL | println!("I am dead."); - | ^^^^^^^^^^^^^^^^^^^^^^^ unreachable statement + | ^^^^^^^^^^^^^^^^^^^^^^ unreachable statement | = note: this error originates in the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/reachable/expr_match.stderr b/src/test/ui/reachable/expr_match.stderr index 9d660a4386..d15208609c 100644 --- a/src/test/ui/reachable/expr_match.stderr +++ b/src/test/ui/reachable/expr_match.stderr @@ -4,7 +4,7 @@ error: unreachable statement LL | match () { () => return } | ------------------------- any code following this `match` expression is unreachable, as all arms diverge LL | println!("I am dead"); - | ^^^^^^^^^^^^^^^^^^^^^^ unreachable statement + | ^^^^^^^^^^^^^^^^^^^^^ unreachable statement | note: the lint level is defined here --> $DIR/expr_match.rs:4:9 @@ -19,7 +19,7 @@ error: unreachable statement LL | match () { () if false => return, () => return } | ------------------------------------------------ any code following this `match` expression is unreachable, as all arms diverge LL | println!("I am dead"); - | ^^^^^^^^^^^^^^^^^^^^^^ unreachable statement + | ^^^^^^^^^^^^^^^^^^^^^ unreachable statement | = note: this error originates in the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/reachable/unreachable-arm.rs b/src/test/ui/reachable/unreachable-arm.rs index 64c3896851..3277bf0d52 100644 --- a/src/test/ui/reachable/unreachable-arm.rs +++ b/src/test/ui/reachable/unreachable-arm.rs @@ -1,5 +1,5 @@ #![feature(box_patterns)] -#![feature(box_syntax)] + #![allow(dead_code)] #![deny(unreachable_patterns)] diff --git a/src/test/ui/reachable/unreachable-code-ret.stderr b/src/test/ui/reachable/unreachable-code-ret.stderr index 839b585c63..263a1b5a96 100644 --- a/src/test/ui/reachable/unreachable-code-ret.stderr +++ b/src/test/ui/reachable/unreachable-code-ret.stderr @@ -4,7 +4,7 @@ error: unreachable statement LL | return; | ------ any code following this expression is unreachable LL | println!("Paul is dead"); - | ^^^^^^^^^^^^^^^^^^^^^^^^^ unreachable statement + | ^^^^^^^^^^^^^^^^^^^^^^^^ unreachable statement | note: the lint level is defined here --> $DIR/unreachable-code-ret.rs:3:9 diff --git a/src/test/ui/recursion/issue-26548-recursion-via-normalize.rs b/src/test/ui/recursion/issue-26548-recursion-via-normalize.rs index 03cb3e24b7..4fd5622b06 100644 --- a/src/test/ui/recursion/issue-26548-recursion-via-normalize.rs +++ b/src/test/ui/recursion/issue-26548-recursion-via-normalize.rs @@ -1,8 +1,8 @@ //~ ERROR cycle detected when computing layout of `S` -//~| NOTE ...which requires computing layout of `std::option::Option<::It>`... -//~| NOTE ...which requires computing layout of `std::option::Option`... +//~| NOTE ...which requires computing layout of `core::option::Option<::It>`... +//~| NOTE ...which requires computing layout of `core::option::Option`... //~| NOTE ...which again requires computing layout of `S`, completing the cycle -//~| NOTE cycle used when computing layout of `std::option::Option` +//~| NOTE cycle used when computing layout of `core::option::Option` // build-fail diff --git a/src/test/ui/recursion/issue-26548-recursion-via-normalize.stderr b/src/test/ui/recursion/issue-26548-recursion-via-normalize.stderr index 21c0e1e6de..6042379a91 100644 --- a/src/test/ui/recursion/issue-26548-recursion-via-normalize.stderr +++ b/src/test/ui/recursion/issue-26548-recursion-via-normalize.stderr @@ -1,9 +1,9 @@ error[E0391]: cycle detected when computing layout of `S` | - = note: ...which requires computing layout of `std::option::Option<::It>`... - = note: ...which requires computing layout of `std::option::Option`... + = note: ...which requires computing layout of `core::option::Option<::It>`... + = note: ...which requires computing layout of `core::option::Option`... = note: ...which again requires computing layout of `S`, completing the cycle - = note: cycle used when computing layout of `std::option::Option` + = note: cycle used when computing layout of `core::option::Option` error: aborting due to previous error diff --git a/src/test/ui/recursion/issue-83150.stderr b/src/test/ui/recursion/issue-83150.stderr index 943d513309..d45bfc3ca5 100644 --- a/src/test/ui/recursion/issue-83150.stderr +++ b/src/test/ui/recursion/issue-83150.stderr @@ -1,6 +1,6 @@ error[E0275]: overflow evaluating the requirement `Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut std::ops::Range, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>: Iterator` | - = help: consider adding a `#![recursion_limit="256"]` attribute to your crate (`issue_83150`) + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_83150`) = note: required because of the requirements on the impl of `Iterator` for `&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut std::ops::Range, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>` error: aborting due to previous error diff --git a/src/test/ui/recursion_limit/invalid_digit_type.rs b/src/test/ui/recursion_limit/invalid_digit_type.rs new file mode 100644 index 0000000000..e408109b36 --- /dev/null +++ b/src/test/ui/recursion_limit/invalid_digit_type.rs @@ -0,0 +1,3 @@ +#![recursion_limit = 123] //~ ERROR malformed `recursion_limit` attribute + +fn main() {} diff --git a/src/test/ui/recursion_limit/invalid_digit_type.stderr b/src/test/ui/recursion_limit/invalid_digit_type.stderr new file mode 100644 index 0000000000..6d1409bb39 --- /dev/null +++ b/src/test/ui/recursion_limit/invalid_digit_type.stderr @@ -0,0 +1,8 @@ +error: malformed `recursion_limit` attribute input + --> $DIR/invalid_digit_type.rs:1:1 + | +LL | #![recursion_limit = 123] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#![recursion_limit = "N"]` + +error: aborting due to previous error + diff --git a/src/test/ui/recursion_limit/invalid_macro.rs b/src/test/ui/recursion_limit/invalid_macro.rs new file mode 100644 index 0000000000..7db67a8d16 --- /dev/null +++ b/src/test/ui/recursion_limit/invalid_macro.rs @@ -0,0 +1,7 @@ +#![recursion_limit = foo!()] //~ ERROR malformed `recursion_limit` attribute + +macro_rules! foo { + () => {"128"}; +} + +fn main() {} diff --git a/src/test/ui/recursion_limit/invalid_macro.stderr b/src/test/ui/recursion_limit/invalid_macro.stderr new file mode 100644 index 0000000000..0189e99da3 --- /dev/null +++ b/src/test/ui/recursion_limit/invalid_macro.stderr @@ -0,0 +1,8 @@ +error: malformed `recursion_limit` attribute input + --> $DIR/invalid_macro.rs:1:1 + | +LL | #![recursion_limit = foo!()] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#![recursion_limit = "N"]` + +error: aborting due to previous error + diff --git a/src/test/ui/recursion_limit/no-value.rs b/src/test/ui/recursion_limit/no-value.rs new file mode 100644 index 0000000000..2202e5b771 --- /dev/null +++ b/src/test/ui/recursion_limit/no-value.rs @@ -0,0 +1,6 @@ +// Test the parse error for no value provided to recursion_limit + +#![recursion_limit] +//~^ ERROR malformed `recursion_limit` attribute input + +fn main() {} diff --git a/src/test/ui/recursion_limit/no-value.stderr b/src/test/ui/recursion_limit/no-value.stderr new file mode 100644 index 0000000000..35ac2c4cd1 --- /dev/null +++ b/src/test/ui/recursion_limit/no-value.stderr @@ -0,0 +1,8 @@ +error: malformed `recursion_limit` attribute input + --> $DIR/no-value.rs:3:1 + | +LL | #![recursion_limit] + | ^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#![recursion_limit = "N"]` + +error: aborting due to previous error + diff --git a/src/test/ui/recursion_limit/zero-overflow.rs b/src/test/ui/recursion_limit/zero-overflow.rs new file mode 100644 index 0000000000..77bd818567 --- /dev/null +++ b/src/test/ui/recursion_limit/zero-overflow.rs @@ -0,0 +1,7 @@ +//~ ERROR overflow evaluating the requirement `&mut Self: DispatchFromDyn<&mut RustaceansAreAwesome> +//~| HELP consider increasing the recursion limit +// build-fail + +#![recursion_limit = "0"] + +fn main() {} diff --git a/src/test/ui/recursion_limit/zero-overflow.stderr b/src/test/ui/recursion_limit/zero-overflow.stderr new file mode 100644 index 0000000000..9007ec0d78 --- /dev/null +++ b/src/test/ui/recursion_limit/zero-overflow.stderr @@ -0,0 +1,7 @@ +error[E0275]: overflow evaluating the requirement `&mut Self: DispatchFromDyn<&mut RustaceansAreAwesome>` + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "2"]` attribute to your crate (`zero_overflow`) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0275`. diff --git a/src/test/ui/recursion_limit/zero.rs b/src/test/ui/recursion_limit/zero.rs index eb95d7babc..3a2d904cb1 100644 --- a/src/test/ui/recursion_limit/zero.rs +++ b/src/test/ui/recursion_limit/zero.rs @@ -7,6 +7,6 @@ macro_rules! test { ($tt:tt) => { test!(); }; } -test!(test); //~ ERROR 10:1: 10:13: recursion limit reached while expanding `test!` +test!(test); //~ ERROR recursion limit reached while expanding `test!` fn main() {} diff --git a/src/test/ui/recursion_limit/zero.stderr b/src/test/ui/recursion_limit/zero.stderr index 6358805d89..b43565909a 100644 --- a/src/test/ui/recursion_limit/zero.stderr +++ b/src/test/ui/recursion_limit/zero.stderr @@ -2,9 +2,9 @@ error: recursion limit reached while expanding `test!` --> $DIR/zero.rs:10:1 | LL | test!(test); - | ^^^^^^^^^^^^ + | ^^^^^^^^^^^ | - = help: consider adding a `#![recursion_limit="0"]` attribute to your crate (`zero`) + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "2"]` attribute to your crate (`zero`) error: aborting due to previous error diff --git a/src/test/ui/regions/issue-12470.rs b/src/test/ui/regions/issue-12470.rs index 0ade359923..d8f2abb0c3 100644 --- a/src/test/ui/regions/issue-12470.rs +++ b/src/test/ui/regions/issue-12470.rs @@ -1,10 +1,10 @@ -#![feature(box_syntax)] - trait X { fn get_i(&self) -> isize; } + + struct B { i: isize } @@ -24,7 +24,7 @@ fn make_a<'a>(p: &'a dyn X) -> A<'a> { } fn make_make_a<'a>() -> A<'a> { - let b: Box = box B {i:1}; + let b: Box = Box::new(B { i: 1 }); let bb: &B = &*b; make_a(bb) //~ ERROR cannot return value referencing local data `*b` } diff --git a/src/test/ui/regions/issue-28848.stderr b/src/test/ui/regions/issue-28848.stderr index 83313b3431..afa0c9c76b 100644 --- a/src/test/ui/regions/issue-28848.stderr +++ b/src/test/ui/regions/issue-28848.stderr @@ -4,12 +4,12 @@ error[E0478]: lifetime bound not satisfied LL | Foo::<'a, 'b>::xmute(u) | ^^^^^^^^^^^^^ | -note: lifetime parameter instantiated with the lifetime `'b` as defined on the function body at 9:16 +note: lifetime parameter instantiated with the lifetime `'b` as defined here --> $DIR/issue-28848.rs:9:16 | LL | pub fn foo<'a, 'b>(u: &'b ()) -> &'a () { | ^^ -note: but lifetime parameter must outlive the lifetime `'a` as defined on the function body at 9:12 +note: but lifetime parameter must outlive the lifetime `'a` as defined here --> $DIR/issue-28848.rs:9:12 | LL | pub fn foo<'a, 'b>(u: &'b ()) -> &'a () { diff --git a/src/test/ui/regions/issue-78262.default.stderr b/src/test/ui/regions/issue-78262.default.stderr index 5250848a65..dcb67e6a65 100644 --- a/src/test/ui/regions/issue-78262.default.stderr +++ b/src/test/ui/regions/issue-78262.default.stderr @@ -6,7 +6,7 @@ LL | let f = |x: &dyn TT| x.func(); | = note: expected reference `&(dyn TT + 'static)` found reference `&dyn TT` -note: the anonymous lifetime #1 defined on the body at 14:13... +note: the anonymous lifetime #1 defined here... --> $DIR/issue-78262.rs:14:13 | LL | let f = |x: &dyn TT| x.func(); diff --git a/src/test/ui/regions/issue-78262.nll.stderr b/src/test/ui/regions/issue-78262.nll.stderr index a35d6fd9bf..721dafac0b 100644 --- a/src/test/ui/regions/issue-78262.nll.stderr +++ b/src/test/ui/regions/issue-78262.nll.stderr @@ -2,8 +2,11 @@ error[E0521]: borrowed data escapes outside of closure --> $DIR/issue-78262.rs:14:26 | LL | let f = |x: &dyn TT| x.func(); - | - ^^^^^^^^ `x` escapes the closure body here - | | + | - - ^^^^^^^^ + | | | | + | | | `x` escapes the closure body here + | | | argument requires that `'1` must outlive `'static` + | | let's call the lifetime of this reference `'1` | `x` is a reference that is only valid in the closure body error: aborting due to previous error diff --git a/src/test/ui/regions/issue-78262.polonius.stderr b/src/test/ui/regions/issue-78262.polonius.stderr index a35d6fd9bf..721dafac0b 100644 --- a/src/test/ui/regions/issue-78262.polonius.stderr +++ b/src/test/ui/regions/issue-78262.polonius.stderr @@ -2,8 +2,11 @@ error[E0521]: borrowed data escapes outside of closure --> $DIR/issue-78262.rs:14:26 | LL | let f = |x: &dyn TT| x.func(); - | - ^^^^^^^^ `x` escapes the closure body here - | | + | - - ^^^^^^^^ + | | | | + | | | `x` escapes the closure body here + | | | argument requires that `'1` must outlive `'static` + | | let's call the lifetime of this reference `'1` | `x` is a reference that is only valid in the closure body error: aborting due to previous error diff --git a/src/test/ui/regions/region-bounds-on-objects-and-type-parameters.stderr b/src/test/ui/regions/region-bounds-on-objects-and-type-parameters.stderr index 1fff85e766..2ec2ca49b1 100644 --- a/src/test/ui/regions/region-bounds-on-objects-and-type-parameters.stderr +++ b/src/test/ui/regions/region-bounds-on-objects-and-type-parameters.stderr @@ -10,12 +10,12 @@ error[E0478]: lifetime bound not satisfied LL | z: Box+'b+'c>, | ^^^^^^^^^^^^^^^^^^^^^ | -note: lifetime parameter instantiated with the lifetime `'b` as defined on the struct at 11:15 +note: lifetime parameter instantiated with the lifetime `'b` as defined here --> $DIR/region-bounds-on-objects-and-type-parameters.rs:11:15 | LL | struct Foo<'a,'b,'c> { | ^^ -note: but lifetime parameter must outlive the lifetime `'a` as defined on the struct at 11:12 +note: but lifetime parameter must outlive the lifetime `'a` as defined here --> $DIR/region-bounds-on-objects-and-type-parameters.rs:11:12 | LL | struct Foo<'a,'b,'c> { diff --git a/src/test/ui/regions/region-invariant-static-error-reporting.nll.stderr b/src/test/ui/regions/region-invariant-static-error-reporting.nll.stderr index 89a22adc8f..e220cbf555 100644 --- a/src/test/ui/regions/region-invariant-static-error-reporting.nll.stderr +++ b/src/test/ui/regions/region-invariant-static-error-reporting.nll.stderr @@ -2,12 +2,15 @@ error[E0521]: borrowed data escapes outside of function --> $DIR/region-invariant-static-error-reporting.rs:15:9 | LL | fn unify<'a>(x: Option>, f: fn(Invariant<'a>)) { - | - `x` is a reference that is only valid in the function body + | -- - `x` is a reference that is only valid in the function body + | | + | lifetime `'a` defined here LL | let bad = if x.is_some() { LL | x.unwrap() - | ^^^^^^^^^^ `x` escapes the function body here - | - = help: consider replacing `'a` with `'static` + | ^^^^^^^^^^ + | | + | `x` escapes the function body here + | argument requires that `'a` must outlive `'static` error: aborting due to previous error diff --git a/src/test/ui/regions/region-invariant-static-error-reporting.stderr b/src/test/ui/regions/region-invariant-static-error-reporting.stderr index 750cc3566e..34287070ee 100644 --- a/src/test/ui/regions/region-invariant-static-error-reporting.stderr +++ b/src/test/ui/regions/region-invariant-static-error-reporting.stderr @@ -13,7 +13,7 @@ LL | | }; | = note: expected struct `Invariant<'a>` found struct `Invariant<'static>` -note: the lifetime `'a` as defined on the function body at 13:10... +note: the lifetime `'a` as defined here... --> $DIR/region-invariant-static-error-reporting.rs:13:10 | LL | fn unify<'a>(x: Option>, f: fn(Invariant<'a>)) { diff --git a/src/test/ui/regions/region-object-lifetime-2.stderr b/src/test/ui/regions/region-object-lifetime-2.stderr index 74ea1b731e..380e27ab0e 100644 --- a/src/test/ui/regions/region-object-lifetime-2.stderr +++ b/src/test/ui/regions/region-object-lifetime-2.stderr @@ -4,7 +4,7 @@ error[E0495]: cannot infer an appropriate lifetime for autoref due to conflictin LL | x.borrowed() | ^^^^^^^^ | -note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 9:42... +note: first, the lifetime cannot outlive the lifetime `'a` as defined here... --> $DIR/region-object-lifetime-2.rs:9:42 | LL | fn borrowed_receiver_different_lifetimes<'a,'b>(x: &'a dyn Foo) -> &'b () { @@ -14,7 +14,7 @@ note: ...so that reference does not outlive borrowed content | LL | x.borrowed() | ^ -note: but, the lifetime must be valid for the lifetime `'b` as defined on the function body at 9:45... +note: but, the lifetime must be valid for the lifetime `'b` as defined here... --> $DIR/region-object-lifetime-2.rs:9:45 | LL | fn borrowed_receiver_different_lifetimes<'a,'b>(x: &'a dyn Foo) -> &'b () { diff --git a/src/test/ui/regions/region-object-lifetime-4.stderr b/src/test/ui/regions/region-object-lifetime-4.stderr index 1053218290..b59163ef13 100644 --- a/src/test/ui/regions/region-object-lifetime-4.stderr +++ b/src/test/ui/regions/region-object-lifetime-4.stderr @@ -4,7 +4,7 @@ error[E0495]: cannot infer an appropriate lifetime for autoref due to conflictin LL | x.borrowed() | ^^^^^^^^ | -note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 11:41... +note: first, the lifetime cannot outlive the lifetime `'a` as defined here... --> $DIR/region-object-lifetime-4.rs:11:41 | LL | fn borrowed_receiver_related_lifetimes2<'a,'b>(x: &'a (dyn Foo + 'b)) -> &'b () { @@ -14,7 +14,7 @@ note: ...so that reference does not outlive borrowed content | LL | x.borrowed() | ^ -note: but, the lifetime must be valid for the lifetime `'b` as defined on the function body at 11:44... +note: but, the lifetime must be valid for the lifetime `'b` as defined here... --> $DIR/region-object-lifetime-4.rs:11:44 | LL | fn borrowed_receiver_related_lifetimes2<'a,'b>(x: &'a (dyn Foo + 'b)) -> &'b () { diff --git a/src/test/ui/regions/region-object-lifetime-5.rs b/src/test/ui/regions/region-object-lifetime-5.rs index 307bbcbd58..ad35936716 100644 --- a/src/test/ui/regions/region-object-lifetime-5.rs +++ b/src/test/ui/regions/region-object-lifetime-5.rs @@ -8,7 +8,7 @@ trait Foo { // Here, the object is bounded by an anonymous lifetime and returned // as `&'static`, so you get an error. fn owned_receiver(x: Box) -> &'static () { - x.borrowed() //~ ERROR cannot return value referencing local data `*x` + x.borrowed() //~ ERROR cannot return reference to local data `*x` } fn main() {} diff --git a/src/test/ui/regions/region-object-lifetime-5.stderr b/src/test/ui/regions/region-object-lifetime-5.stderr index b86f6e3a2a..b82b58c7a8 100644 --- a/src/test/ui/regions/region-object-lifetime-5.stderr +++ b/src/test/ui/regions/region-object-lifetime-5.stderr @@ -1,11 +1,8 @@ -error[E0515]: cannot return value referencing local data `*x` +error[E0515]: cannot return reference to local data `*x` --> $DIR/region-object-lifetime-5.rs:11:5 | LL | x.borrowed() - | -^^^^^^^^^^^ - | | - | returns a value referencing data owned by the current function - | `*x` is borrowed here + | ^^^^^^^^^^^^ returns a reference to data owned by the current function error: aborting due to previous error diff --git a/src/test/ui/regions/region-object-lifetime-in-coercion.stderr b/src/test/ui/regions/region-object-lifetime-in-coercion.stderr index 1c8840f540..04d22e58a1 100644 --- a/src/test/ui/regions/region-object-lifetime-in-coercion.stderr +++ b/src/test/ui/regions/region-object-lifetime-in-coercion.stderr @@ -52,7 +52,7 @@ error[E0495]: cannot infer an appropriate lifetime due to conflicting requiremen LL | Box::new(v) | ^ | -note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 22:6... +note: first, the lifetime cannot outlive the lifetime `'a` as defined here... --> $DIR/region-object-lifetime-in-coercion.rs:22:6 | LL | fn d<'a,'b>(v: &'a [u8]) -> Box { @@ -64,12 +64,12 @@ LL | Box::new(v) | ^ = note: expected `&[u8]` found `&'a [u8]` -note: but, the lifetime must be valid for the lifetime `'b` as defined on the function body at 22:9... +note: but, the lifetime must be valid for the lifetime `'b` as defined here... --> $DIR/region-object-lifetime-in-coercion.rs:22:9 | LL | fn d<'a,'b>(v: &'a [u8]) -> Box { | ^^ -note: ...so that the expression is assignable +note: ...so that the types are compatible --> $DIR/region-object-lifetime-in-coercion.rs:23:5 | LL | Box::new(v) diff --git a/src/test/ui/regions/regions-addr-of-upvar-self.stderr b/src/test/ui/regions/regions-addr-of-upvar-self.stderr index 62e9058365..f638064ef8 100644 --- a/src/test/ui/regions/regions-addr-of-upvar-self.stderr +++ b/src/test/ui/regions/regions-addr-of-upvar-self.stderr @@ -4,7 +4,7 @@ error[E0495]: cannot infer an appropriate lifetime for borrow expression due to LL | let p: &'static mut usize = &mut self.food; | ^^^^^^^^^^^^^^ | -note: first, the lifetime cannot outlive the lifetime `'_` as defined on the body at 7:18... +note: first, the lifetime cannot outlive the lifetime `'_` as defined here... --> $DIR/regions-addr-of-upvar-self.rs:7:18 | LL | let _f = || { diff --git a/src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.migrate.stderr b/src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.migrate.stderr index c0401780b8..6ae70ec672 100644 --- a/src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.migrate.stderr +++ b/src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.migrate.stderr @@ -4,12 +4,12 @@ error[E0491]: in type `&'a WithAssoc>`, reference has a longer lifet LL | let _: &'a WithAssoc> = loop { }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: the pointer is valid for the lifetime `'a` as defined on the function body at 33:15 +note: the pointer is valid for the lifetime `'a` as defined here --> $DIR/regions-assoc-type-in-supertrait-outlives-container.rs:33:15 | LL | fn with_assoc<'a,'b>() { | ^^ -note: but the referenced data is only valid for the lifetime `'b` as defined on the function body at 33:18 +note: but the referenced data is only valid for the lifetime `'b` as defined here --> $DIR/regions-assoc-type-in-supertrait-outlives-container.rs:33:18 | LL | fn with_assoc<'a,'b>() { diff --git a/src/test/ui/regions/regions-assoc-type-region-bound-in-trait-not-met.stderr b/src/test/ui/regions/regions-assoc-type-region-bound-in-trait-not-met.stderr index 52802848d5..f4153b2a81 100644 --- a/src/test/ui/regions/regions-assoc-type-region-bound-in-trait-not-met.stderr +++ b/src/test/ui/regions/regions-assoc-type-region-bound-in-trait-not-met.stderr @@ -16,7 +16,7 @@ error[E0477]: the type `&'a i32` does not fulfill the required lifetime LL | type Value = &'a i32; | ^^^^^^^^^^^^^^^^^^^^^ | -note: type must outlive the lifetime `'b` as defined on the impl at 19:10 as required by this binding +note: type must outlive the lifetime `'b` as defined here as required by this binding --> $DIR/regions-assoc-type-region-bound-in-trait-not-met.rs:19:10 | LL | impl<'a, 'b> Foo<'b> for &'a i64 { diff --git a/src/test/ui/regions/regions-borrow-at.rs b/src/test/ui/regions/regions-borrow-at.rs index 355e8c9145..152abe109b 100644 --- a/src/test/ui/regions/regions-borrow-at.rs +++ b/src/test/ui/regions/regions-borrow-at.rs @@ -1,12 +1,11 @@ // run-pass -#![feature(box_syntax)] fn foo(x: &usize) -> usize { *x } pub fn main() { - let p: Box<_> = box 22; + let p: Box<_> = Box::new(22); let r = foo(&*p); println!("r={}", r); assert_eq!(r, 22); diff --git a/src/test/ui/regions/regions-borrow-uniq.rs b/src/test/ui/regions/regions-borrow-uniq.rs index 3bf049c151..adc6b1939d 100644 --- a/src/test/ui/regions/regions-borrow-uniq.rs +++ b/src/test/ui/regions/regions-borrow-uniq.rs @@ -1,12 +1,11 @@ // run-pass -#![feature(box_syntax)] fn foo(x: &usize) -> usize { *x } pub fn main() { - let p: Box<_> = box 3; + let p: Box<_> = Box::new(3); let r = foo(&*p); assert_eq!(r, 3); } diff --git a/src/test/ui/regions/regions-bounded-by-trait-requiring-static.nll.stderr b/src/test/ui/regions/regions-bounded-by-trait-requiring-static.nll.stderr index ca153b9d9b..86bd100538 100644 --- a/src/test/ui/regions/regions-bounded-by-trait-requiring-static.nll.stderr +++ b/src/test/ui/regions/regions-bounded-by-trait-requiring-static.nll.stderr @@ -5,8 +5,6 @@ LL | fn param_not_ok<'a>(x: &'a isize) { | -- lifetime `'a` defined here LL | assert_send::<&'a isize>(); | ^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` - | - = help: consider replacing `'a` with `'static` error: lifetime may not live long enough --> $DIR/regions-bounded-by-trait-requiring-static.rs:26:5 @@ -15,8 +13,6 @@ LL | fn param_not_ok1<'a>(_: &'a isize) { | -- lifetime `'a` defined here LL | assert_send::<&'a str>(); | ^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` - | - = help: consider replacing `'a` with `'static` error: lifetime may not live long enough --> $DIR/regions-bounded-by-trait-requiring-static.rs:30:5 @@ -25,8 +21,6 @@ LL | fn param_not_ok2<'a>(_: &'a isize) { | -- lifetime `'a` defined here LL | assert_send::<&'a [isize]>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` - | - = help: consider replacing `'a` with `'static` error: lifetime may not live long enough --> $DIR/regions-bounded-by-trait-requiring-static.rs:44:5 @@ -35,8 +29,6 @@ LL | fn box_with_region_not_ok<'a>() { | -- lifetime `'a` defined here LL | assert_send::>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` - | - = help: consider replacing `'a` with `'static` error: lifetime may not live long enough --> $DIR/regions-bounded-by-trait-requiring-static.rs:55:5 @@ -45,8 +37,6 @@ LL | fn unsafe_ok2<'a>(_: &'a isize) { | -- lifetime `'a` defined here LL | assert_send::<*const &'a isize>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` - | - = help: consider replacing `'a` with `'static` error: lifetime may not live long enough --> $DIR/regions-bounded-by-trait-requiring-static.rs:59:5 @@ -55,8 +45,6 @@ LL | fn unsafe_ok3<'a>(_: &'a isize) { | -- lifetime `'a` defined here LL | assert_send::<*mut &'a isize>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` - | - = help: consider replacing `'a` with `'static` error: aborting due to 6 previous errors diff --git a/src/test/ui/regions/regions-bounded-method-type-parameters-trait-bound.nll.stderr b/src/test/ui/regions/regions-bounded-method-type-parameters-trait-bound.nll.stderr index ed7b17c207..83d6e13dc0 100644 --- a/src/test/ui/regions/regions-bounded-method-type-parameters-trait-bound.nll.stderr +++ b/src/test/ui/regions/regions-bounded-method-type-parameters-trait-bound.nll.stderr @@ -2,12 +2,17 @@ error[E0521]: borrowed data escapes outside of function --> $DIR/regions-bounded-method-type-parameters-trait-bound.rs:20:5 | LL | fn caller2<'a,'b,F:Foo<'a>>(a: Inv<'a>, b: Inv<'b>, f: F) { - | - - `b` is a reference that is only valid in the function body - | | - | `a` declared here, outside of the function body + | -- -- - - `b` is a reference that is only valid in the function body + | | | | + | | | `a` declared here, outside of the function body + | | lifetime `'b` defined here + | lifetime `'a` defined here LL | // Here the value provided for 'y is 'b, and hence 'b:'a does not hold. LL | f.method(b); - | ^^^^^^^^^^^ `b` escapes the function body here + | ^^^^^^^^^^^ + | | + | `b` escapes the function body here + | argument requires that `'b` must outlive `'a` | = help: consider adding the following bound: `'b: 'a` diff --git a/src/test/ui/regions/regions-bounded-method-type-parameters.nll.stderr b/src/test/ui/regions/regions-bounded-method-type-parameters.nll.stderr index 2076772b59..b6d7b8aac5 100644 --- a/src/test/ui/regions/regions-bounded-method-type-parameters.nll.stderr +++ b/src/test/ui/regions/regions-bounded-method-type-parameters.nll.stderr @@ -5,8 +5,6 @@ LL | fn caller<'a>(x: &isize) { | -- lifetime `'a` defined here LL | Foo.some_method::<&'a isize>(); | ^^^^^^^^^^^ requires that `'a` must outlive `'static` - | - = help: consider replacing `'a` with `'static` error: aborting due to previous error diff --git a/src/test/ui/regions/regions-bounds.stderr b/src/test/ui/regions/regions-bounds.stderr index a4eebab386..90227e574a 100644 --- a/src/test/ui/regions/regions-bounds.stderr +++ b/src/test/ui/regions/regions-bounds.stderr @@ -6,12 +6,12 @@ LL | return e; | = note: expected struct `TupleStruct<'b>` found struct `TupleStruct<'a>` -note: the lifetime `'a` as defined on the function body at 8:10... +note: the lifetime `'a` as defined here... --> $DIR/regions-bounds.rs:8:10 | LL | fn a_fn1<'a,'b>(e: TupleStruct<'a>) -> TupleStruct<'b> { | ^^ -note: ...does not necessarily outlive the lifetime `'b` as defined on the function body at 8:13 +note: ...does not necessarily outlive the lifetime `'b` as defined here --> $DIR/regions-bounds.rs:8:13 | LL | fn a_fn1<'a,'b>(e: TupleStruct<'a>) -> TupleStruct<'b> { @@ -25,12 +25,12 @@ LL | return e; | = note: expected struct `Struct<'b>` found struct `Struct<'a>` -note: the lifetime `'a` as defined on the function body at 12:10... +note: the lifetime `'a` as defined here... --> $DIR/regions-bounds.rs:12:10 | LL | fn a_fn3<'a,'b>(e: Struct<'a>) -> Struct<'b> { | ^^ -note: ...does not necessarily outlive the lifetime `'b` as defined on the function body at 12:13 +note: ...does not necessarily outlive the lifetime `'b` as defined here --> $DIR/regions-bounds.rs:12:13 | LL | fn a_fn3<'a,'b>(e: Struct<'a>) -> Struct<'b> { diff --git a/src/test/ui/regions/regions-close-associated-type-into-object.rs b/src/test/ui/regions/regions-close-associated-type-into-object.rs index 0cbdc828c5..428477e248 100644 --- a/src/test/ui/regions/regions-close-associated-type-into-object.rs +++ b/src/test/ui/regions/regions-close-associated-type-into-object.rs @@ -1,7 +1,7 @@ -#![feature(box_syntax)] - trait X {} + + trait Iter { type Item: X; @@ -18,7 +18,7 @@ fn bad1(v: T) -> Box fn bad2(v: T) -> Box where Box : X { - let item: Box<_> = box v.into_item(); + let item: Box<_> = Box::new(v.into_item()); Box::new(item) //~ ERROR associated type `::Item` may not live long enough } @@ -31,7 +31,7 @@ fn bad3<'a, T: Iter>(v: T) -> Box fn bad4<'a, T: Iter>(v: T) -> Box where Box : X { - let item: Box<_> = box v.into_item(); + let item: Box<_> = Box::new(v.into_item()); Box::new(item) //~ ERROR associated type `::Item` may not live long enough } diff --git a/src/test/ui/regions/regions-close-object-into-object-1.rs b/src/test/ui/regions/regions-close-object-into-object-1.rs index 5518c6a94b..2dc33d5671 100644 --- a/src/test/ui/regions/regions-close-object-into-object-1.rs +++ b/src/test/ui/regions/regions-close-object-into-object-1.rs @@ -1,7 +1,7 @@ -#![feature(box_syntax)] #![allow(warnings)] trait A { } + struct B<'a, T:'a>(&'a (A+'a)); trait X { } @@ -9,7 +9,7 @@ trait X { } impl<'a, T> X for B<'a, T> {} fn f<'a, T:'static, U>(v: Box+'static>) -> Box { - box B(&*v) as Box //~ ERROR cannot return value referencing local data `*v` + Box::new(B(&*v)) as Box //~ ERROR cannot return value referencing local data `*v` } fn main() {} diff --git a/src/test/ui/regions/regions-close-object-into-object-1.stderr b/src/test/ui/regions/regions-close-object-into-object-1.stderr index 8e119c4f53..5bfaeb295c 100644 --- a/src/test/ui/regions/regions-close-object-into-object-1.stderr +++ b/src/test/ui/regions/regions-close-object-into-object-1.stderr @@ -1,10 +1,10 @@ error[E0515]: cannot return value referencing local data `*v` --> $DIR/regions-close-object-into-object-1.rs:12:5 | -LL | box B(&*v) as Box - | ^^^^^^---^^^^^^^^^^^ - | | | - | | `*v` is borrowed here +LL | Box::new(B(&*v)) as Box + | ^^^^^^^^^^^---^^^^^^^^^^^^ + | | | + | | `*v` is borrowed here | returns a value referencing data owned by the current function error: aborting due to previous error diff --git a/src/test/ui/regions/regions-close-object-into-object-2.nll.stderr b/src/test/ui/regions/regions-close-object-into-object-2.nll.stderr index 882faf4ece..6a0e958616 100644 --- a/src/test/ui/regions/regions-close-object-into-object-2.nll.stderr +++ b/src/test/ui/regions/regions-close-object-into-object-2.nll.stderr @@ -1,20 +1,18 @@ error: lifetime may not live long enough - --> $DIR/regions-close-object-into-object-2.rs:10:5 + --> $DIR/regions-close-object-into-object-2.rs:9:5 | LL | fn g<'a, T: 'static>(v: Box + 'a>) -> Box { | -- lifetime `'a` defined here -LL | box B(&*v) as Box - | ^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static` - | - = help: consider replacing `'a` with `'static` +LL | Box::new(B(&*v)) as Box + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static` error[E0515]: cannot return value referencing local data `*v` - --> $DIR/regions-close-object-into-object-2.rs:10:5 + --> $DIR/regions-close-object-into-object-2.rs:9:5 | -LL | box B(&*v) as Box - | ^^^^^^---^^^^^^^^^^^^^^^ - | | | - | | `*v` is borrowed here +LL | Box::new(B(&*v)) as Box + | ^^^^^^^^^^^---^^^^^^^^^^^^^^^^ + | | | + | | `*v` is borrowed here | returns a value referencing data owned by the current function error: aborting due to 2 previous errors diff --git a/src/test/ui/regions/regions-close-object-into-object-2.rs b/src/test/ui/regions/regions-close-object-into-object-2.rs index 7144ab5a24..9c41174e24 100644 --- a/src/test/ui/regions/regions-close-object-into-object-2.rs +++ b/src/test/ui/regions/regions-close-object-into-object-2.rs @@ -1,13 +1,12 @@ -#![feature(box_syntax)] - trait A { } + struct B<'a, T:'a>(&'a (dyn A + 'a)); trait X { } impl<'a, T> X for B<'a, T> {} fn g<'a, T: 'static>(v: Box + 'a>) -> Box { - box B(&*v) as Box //~ ERROR E0759 + Box::new(B(&*v)) as Box //~ ERROR E0759 } fn main() { } diff --git a/src/test/ui/regions/regions-close-object-into-object-2.stderr b/src/test/ui/regions/regions-close-object-into-object-2.stderr index 78d2371cf5..9a7df8c018 100644 --- a/src/test/ui/regions/regions-close-object-into-object-2.stderr +++ b/src/test/ui/regions/regions-close-object-into-object-2.stderr @@ -1,10 +1,10 @@ error[E0759]: `v` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement - --> $DIR/regions-close-object-into-object-2.rs:10:11 + --> $DIR/regions-close-object-into-object-2.rs:9:16 | LL | fn g<'a, T: 'static>(v: Box + 'a>) -> Box { | ------------------ this data with lifetime `'a`... -LL | box B(&*v) as Box - | ^^^ ...is captured here, requiring it to live as long as `'static` +LL | Box::new(B(&*v)) as Box + | ^^^ ...is captured here, requiring it to live as long as `'static` | help: consider changing the trait object's explicit `'static` bound to the lifetime of argument `v` | diff --git a/src/test/ui/regions/regions-close-object-into-object-3.rs b/src/test/ui/regions/regions-close-object-into-object-3.rs index 6f6b3a1700..78d93b0ece 100644 --- a/src/test/ui/regions/regions-close-object-into-object-3.rs +++ b/src/test/ui/regions/regions-close-object-into-object-3.rs @@ -1,14 +1,14 @@ -#![feature(box_syntax)] #![allow(warnings)] trait A { } + struct B<'a, T:'a>(&'a (A+'a)); trait X { } impl<'a, T> X for B<'a, T> {} fn h<'a, T, U:'static>(v: Box+'static>) -> Box { - box B(&*v) as Box //~ ERROR cannot return value referencing local data `*v` + Box::new(B(&*v)) as Box //~ ERROR cannot return value referencing local data `*v` } fn main() {} diff --git a/src/test/ui/regions/regions-close-object-into-object-3.stderr b/src/test/ui/regions/regions-close-object-into-object-3.stderr index 9ea13638f5..9f92c40e1e 100644 --- a/src/test/ui/regions/regions-close-object-into-object-3.stderr +++ b/src/test/ui/regions/regions-close-object-into-object-3.stderr @@ -1,10 +1,10 @@ error[E0515]: cannot return value referencing local data `*v` --> $DIR/regions-close-object-into-object-3.rs:11:5 | -LL | box B(&*v) as Box - | ^^^^^^---^^^^^^^^^^^ - | | | - | | `*v` is borrowed here +LL | Box::new(B(&*v)) as Box + | ^^^^^^^^^^^---^^^^^^^^^^^^ + | | | + | | `*v` is borrowed here | returns a value referencing data owned by the current function error: aborting due to previous error diff --git a/src/test/ui/regions/regions-close-object-into-object-4.nll.stderr b/src/test/ui/regions/regions-close-object-into-object-4.nll.stderr index 93ac17810d..b30626830a 100644 --- a/src/test/ui/regions/regions-close-object-into-object-4.nll.stderr +++ b/src/test/ui/regions/regions-close-object-into-object-4.nll.stderr @@ -1,39 +1,53 @@ error[E0310]: the parameter type `U` may not live long enough - --> $DIR/regions-close-object-into-object-4.rs:10:5 + --> $DIR/regions-close-object-into-object-4.rs:9:5 | -LL | box B(&*v) as Box - | ^^^^^^^^^^ +LL | Box::new(B(&*v)) as Box + | ^^^^^^^^ + | + = help: consider adding an explicit lifetime bound `U: 'static`... + +error[E0310]: the parameter type `U` may not live long enough + --> $DIR/regions-close-object-into-object-4.rs:9:5 + | +LL | Box::new(B(&*v)) as Box + | ^^^^^^^^^^^^^^^^ + | + = help: consider adding an explicit lifetime bound `U: 'static`... + +error[E0310]: the parameter type `U` may not live long enough + --> $DIR/regions-close-object-into-object-4.rs:9:5 + | +LL | Box::new(B(&*v)) as Box + | ^^^^^^^^^^^^^^^^ | = help: consider adding an explicit lifetime bound `U: 'static`... error: lifetime may not live long enough - --> $DIR/regions-close-object-into-object-4.rs:10:5 + --> $DIR/regions-close-object-into-object-4.rs:9:5 | LL | fn i<'a, T, U>(v: Box+'a>) -> Box { | -- lifetime `'a` defined here -LL | box B(&*v) as Box - | ^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static` - | - = help: consider replacing `'a` with `'static` +LL | Box::new(B(&*v)) as Box + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static` error[E0515]: cannot return value referencing local data `*v` - --> $DIR/regions-close-object-into-object-4.rs:10:5 + --> $DIR/regions-close-object-into-object-4.rs:9:5 | -LL | box B(&*v) as Box - | ^^^^^^---^^^^^^^^^^^^^^^ - | | | - | | `*v` is borrowed here +LL | Box::new(B(&*v)) as Box + | ^^^^^^^^^^^---^^^^^^^^^^^^^^^^ + | | | + | | `*v` is borrowed here | returns a value referencing data owned by the current function error[E0310]: the parameter type `U` may not live long enough - --> $DIR/regions-close-object-into-object-4.rs:10:9 + --> $DIR/regions-close-object-into-object-4.rs:9:14 | -LL | box B(&*v) as Box - | ^^^^^^ +LL | Box::new(B(&*v)) as Box + | ^^^^^^ | = help: consider adding an explicit lifetime bound `U: 'static`... -error: aborting due to 4 previous errors +error: aborting due to 6 previous errors Some errors have detailed explanations: E0310, E0515. For more information about an error, try `rustc --explain E0310`. diff --git a/src/test/ui/regions/regions-close-object-into-object-4.rs b/src/test/ui/regions/regions-close-object-into-object-4.rs index 4c087f264f..2a06a2b7c0 100644 --- a/src/test/ui/regions/regions-close-object-into-object-4.rs +++ b/src/test/ui/regions/regions-close-object-into-object-4.rs @@ -1,13 +1,12 @@ -#![feature(box_syntax)] - trait A { } + struct B<'a, T:'a>(&'a (dyn A + 'a)); trait X { } impl<'a, T> X for B<'a, T> {} fn i<'a, T, U>(v: Box+'a>) -> Box { - box B(&*v) as Box //~ ERROR E0759 + Box::new(B(&*v)) as Box //~ ERROR E0759 } fn main() {} diff --git a/src/test/ui/regions/regions-close-object-into-object-4.stderr b/src/test/ui/regions/regions-close-object-into-object-4.stderr index 8c94b44f20..a7a9b16b08 100644 --- a/src/test/ui/regions/regions-close-object-into-object-4.stderr +++ b/src/test/ui/regions/regions-close-object-into-object-4.stderr @@ -1,10 +1,10 @@ error[E0759]: `v` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement - --> $DIR/regions-close-object-into-object-4.rs:10:11 + --> $DIR/regions-close-object-into-object-4.rs:9:16 | LL | fn i<'a, T, U>(v: Box+'a>) -> Box { | ---------------- this data with lifetime `'a`... -LL | box B(&*v) as Box - | ^^^ ...is captured here, requiring it to live as long as `'static` +LL | Box::new(B(&*v)) as Box + | ^^^ ...is captured here, requiring it to live as long as `'static` | help: consider changing the trait object's explicit `'static` bound to the lifetime of argument `v` | diff --git a/src/test/ui/regions/regions-close-object-into-object-5.nll.stderr b/src/test/ui/regions/regions-close-object-into-object-5.nll.stderr index 08ba1b17b5..7486e73e66 100644 --- a/src/test/ui/regions/regions-close-object-into-object-5.nll.stderr +++ b/src/test/ui/regions/regions-close-object-into-object-5.nll.stderr @@ -1,29 +1,45 @@ error[E0310]: the parameter type `T` may not live long enough --> $DIR/regions-close-object-into-object-5.rs:17:5 | -LL | box B(&*v) as Box - | ^^^^^^^^^^ +LL | Box::new(B(&*v)) as Box + | ^^^^^^^^ + | + = help: consider adding an explicit lifetime bound `T: 'static`... + +error[E0310]: the parameter type `T` may not live long enough + --> $DIR/regions-close-object-into-object-5.rs:17:5 + | +LL | Box::new(B(&*v)) as Box + | ^^^^^^^^^^^^^^^^ + | + = help: consider adding an explicit lifetime bound `T: 'static`... + +error[E0310]: the parameter type `T` may not live long enough + --> $DIR/regions-close-object-into-object-5.rs:17:5 + | +LL | Box::new(B(&*v)) as Box + | ^^^^^^^^^^^^^^^^ | = help: consider adding an explicit lifetime bound `T: 'static`... error[E0515]: cannot return value referencing local data `*v` --> $DIR/regions-close-object-into-object-5.rs:17:5 | -LL | box B(&*v) as Box - | ^^^^^^---^^^^^^^^^^^ - | | | - | | `*v` is borrowed here +LL | Box::new(B(&*v)) as Box + | ^^^^^^^^^^^---^^^^^^^^^^^^^^^^ + | | | + | | `*v` is borrowed here | returns a value referencing data owned by the current function error[E0310]: the parameter type `T` may not live long enough - --> $DIR/regions-close-object-into-object-5.rs:17:9 + --> $DIR/regions-close-object-into-object-5.rs:17:14 | -LL | box B(&*v) as Box - | ^^^^^^ +LL | Box::new(B(&*v)) as Box + | ^^^^^^ | = help: consider adding an explicit lifetime bound `T: 'static`... -error: aborting due to 3 previous errors +error: aborting due to 5 previous errors Some errors have detailed explanations: E0310, E0515. For more information about an error, try `rustc --explain E0310`. diff --git a/src/test/ui/regions/regions-close-object-into-object-5.rs b/src/test/ui/regions/regions-close-object-into-object-5.rs index ff35b9ada4..5471c375b4 100644 --- a/src/test/ui/regions/regions-close-object-into-object-5.rs +++ b/src/test/ui/regions/regions-close-object-into-object-5.rs @@ -1,6 +1,6 @@ -#![feature(box_syntax)] #![allow(warnings)] + trait A { fn get(&self) -> T { panic!() } @@ -14,13 +14,14 @@ impl<'a, T> X for B<'a, T> {} fn f<'a, T, U>(v: Box + 'static>) -> Box { // oh dear! - box B(&*v) as Box + Box::new(B(&*v)) as Box //~^ ERROR the parameter type `T` may not live long enough //~| ERROR the parameter type `T` may not live long enough //~| ERROR the parameter type `T` may not live long enough //~| ERROR the parameter type `T` may not live long enough //~| ERROR the parameter type `T` may not live long enough //~| ERROR the parameter type `T` may not live long enough + //~| ERROR the parameter type `T` may not live long enough } fn main() {} diff --git a/src/test/ui/regions/regions-close-object-into-object-5.stderr b/src/test/ui/regions/regions-close-object-into-object-5.stderr index 5b692cdcc0..83f8d20b9e 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 @@ -4,26 +4,8 @@ error[E0310]: the parameter type `T` may not live long enough LL | fn f<'a, T, U>(v: Box + 'static>) -> Box { | - help: consider adding an explicit lifetime bound...: `T: 'static` LL | // oh dear! -LL | box B(&*v) as Box - | ^^^^^^^^^^ ...so that the type `B<'_, T>` will meet its required lifetime bounds - -error[E0310]: the parameter type `T` may not live long enough - --> $DIR/regions-close-object-into-object-5.rs:17:9 - | -LL | fn f<'a, T, U>(v: Box + 'static>) -> Box { - | - help: consider adding an explicit lifetime bound...: `T: 'static` -LL | // oh dear! -LL | box B(&*v) as Box - | ^ ...so that the type `T` will meet its required lifetime bounds - -error[E0310]: the parameter type `T` may not live long enough - --> $DIR/regions-close-object-into-object-5.rs:17:9 - | -LL | fn f<'a, T, U>(v: Box + 'static>) -> Box { - | - help: consider adding an explicit lifetime bound...: `T: 'static` -LL | // oh dear! -LL | box B(&*v) as Box - | ^^^^^^ ...so that the type `T` will meet its required lifetime bounds... +LL | Box::new(B(&*v)) as Box + | ^^^^^^^^ ...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 @@ -32,32 +14,65 @@ LL | struct B<'a, T: 'a>(&'a (A + 'a)); | ^^ error[E0310]: the parameter type `T` may not live long enough - --> $DIR/regions-close-object-into-object-5.rs:17:11 + --> $DIR/regions-close-object-into-object-5.rs:17:5 | LL | fn f<'a, T, U>(v: Box + 'static>) -> Box { | - help: consider adding an explicit lifetime bound...: `T: 'static` LL | // oh dear! -LL | box B(&*v) as Box - | ^^^ ...so that the reference type `&dyn A` does not outlive the data it points at +LL | Box::new(B(&*v)) as Box + | ^^^^^^^^^^^^^^^^ ...so that the type `B<'_, T>` will meet its required lifetime bounds error[E0310]: the parameter type `T` may not live long enough - --> $DIR/regions-close-object-into-object-5.rs:17:11 + --> $DIR/regions-close-object-into-object-5.rs:17:14 | LL | fn f<'a, T, U>(v: Box + 'static>) -> Box { | - help: consider adding an explicit lifetime bound...: `T: 'static` LL | // oh dear! -LL | box B(&*v) as Box - | ^^^ ...so that the type `(dyn A + 'static)` is not borrowed for too long +LL | Box::new(B(&*v)) as Box + | ^ ...so that the type `T` will meet its required lifetime bounds error[E0310]: the parameter type `T` may not live long enough - --> $DIR/regions-close-object-into-object-5.rs:17:11 + --> $DIR/regions-close-object-into-object-5.rs:17:14 | LL | fn f<'a, T, U>(v: Box + 'static>) -> Box { | - help: consider adding an explicit lifetime bound...: `T: 'static` LL | // oh dear! -LL | box B(&*v) as Box - | ^^^ ...so that the type `(dyn A + 'static)` is not borrowed for too long +LL | Box::new(B(&*v)) as Box + | ^^^^^^ ...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 + 'a)); + | ^^ -error: aborting due to 6 previous errors +error[E0310]: the parameter type `T` may not live long enough + --> $DIR/regions-close-object-into-object-5.rs:17:16 + | +LL | fn f<'a, T, U>(v: Box + 'static>) -> Box { + | - help: consider adding an explicit lifetime bound...: `T: 'static` +LL | // oh dear! +LL | Box::new(B(&*v)) as Box + | ^^^ ...so that the reference type `&dyn A` does not outlive the data it points at + +error[E0310]: the parameter type `T` may not live long enough + --> $DIR/regions-close-object-into-object-5.rs:17:16 + | +LL | fn f<'a, T, U>(v: Box + 'static>) -> Box { + | - help: consider adding an explicit lifetime bound...: `T: 'static` +LL | // oh dear! +LL | Box::new(B(&*v)) as Box + | ^^^ ...so that the type `(dyn A + 'static)` is not borrowed for too long + +error[E0310]: the parameter type `T` may not live long enough + --> $DIR/regions-close-object-into-object-5.rs:17:16 + | +LL | fn f<'a, T, U>(v: Box + 'static>) -> Box { + | - help: consider adding an explicit lifetime bound...: `T: 'static` +LL | // oh dear! +LL | Box::new(B(&*v)) as Box + | ^^^ ...so that the type `(dyn A + 'static)` is not borrowed for too long + +error: aborting due to 7 previous errors For more information about this error, try `rustc --explain E0310`. diff --git a/src/test/ui/regions/regions-close-over-type-parameter-1.nll.stderr b/src/test/ui/regions/regions-close-over-type-parameter-1.nll.stderr index 3101d81588..b576ae8701 100644 --- a/src/test/ui/regions/regions-close-over-type-parameter-1.nll.stderr +++ b/src/test/ui/regions/regions-close-over-type-parameter-1.nll.stderr @@ -1,16 +1,16 @@ error[E0310]: the parameter type `A` may not live long enough --> $DIR/regions-close-over-type-parameter-1.rs:12:5 | -LL | box v as Box - | ^^^^^ +LL | Box::new(v) as Box + | ^^^^^^^^^^^ | = help: consider adding an explicit lifetime bound `A: 'static`... error[E0309]: the parameter type `A` may not live long enough --> $DIR/regions-close-over-type-parameter-1.rs:21:5 | -LL | box v as Box - | ^^^^^ +LL | Box::new(v) as Box + | ^^^^^^^^^^^ | = help: consider adding an explicit lifetime bound `A: 'b`... diff --git a/src/test/ui/regions/regions-close-over-type-parameter-1.rs b/src/test/ui/regions/regions-close-over-type-parameter-1.rs index 6e708a5f70..52d18c5d7a 100644 --- a/src/test/ui/regions/regions-close-over-type-parameter-1.rs +++ b/src/test/ui/regions/regions-close-over-type-parameter-1.rs @@ -1,24 +1,24 @@ -#![feature(box_syntax)] - // Test for what happens when a type parameter `A` is closed over into // an object. This should yield errors unless `A` (and the object) // both have suitable bounds. + trait SomeTrait { fn get(&self) -> isize; } + fn make_object1(v: A) -> Box { - box v as Box + Box::new(v) as Box //~^ ERROR the parameter type `A` may not live long enough } fn make_object2<'a, A: SomeTrait + 'a>(v: A) -> Box { - box v as Box + Box::new(v) as Box } fn make_object3<'a, 'b, A: SomeTrait + 'a>(v: A) -> Box { - box v as Box + Box::new(v) as Box //~^ ERROR the parameter type `A` may not live long enough } diff --git a/src/test/ui/regions/regions-close-over-type-parameter-1.stderr b/src/test/ui/regions/regions-close-over-type-parameter-1.stderr index 50274b066d..063c3b19a1 100644 --- a/src/test/ui/regions/regions-close-over-type-parameter-1.stderr +++ b/src/test/ui/regions/regions-close-over-type-parameter-1.stderr @@ -3,16 +3,16 @@ error[E0310]: the parameter type `A` may not live long enough | LL | fn make_object1(v: A) -> Box { | -- help: consider adding an explicit lifetime bound...: `A: 'static +` -LL | box v as Box - | ^^^^^ ...so that the type `A` will meet its required lifetime bounds +LL | Box::new(v) as Box + | ^^^^^^^^^^^ ...so that the type `A` will meet its required lifetime bounds error[E0309]: the parameter type `A` may not live long enough --> $DIR/regions-close-over-type-parameter-1.rs:21:5 | LL | fn make_object3<'a, 'b, A: SomeTrait + 'a>(v: A) -> Box { | -- help: consider adding an explicit lifetime bound...: `A: 'b +` -LL | box v as Box - | ^^^^^ ...so that the type `A` will meet its required lifetime bounds +LL | Box::new(v) as Box + | ^^^^^^^^^^^ ...so that the type `A` will meet its required lifetime bounds error: aborting due to 2 previous errors diff --git a/src/test/ui/regions/regions-close-over-type-parameter-multiple.nll.stderr b/src/test/ui/regions/regions-close-over-type-parameter-multiple.nll.stderr index 2fb9dcc4e9..c2bd3bbf82 100644 --- a/src/test/ui/regions/regions-close-over-type-parameter-multiple.nll.stderr +++ b/src/test/ui/regions/regions-close-over-type-parameter-multiple.nll.stderr @@ -6,8 +6,8 @@ LL | fn make_object_bad<'a,'b,'c,A:SomeTrait+'a+'b>(v: A) -> Box - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'c` +LL | Box::new(v) as Box + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'c` | = help: consider adding the following bound: `'a: 'c` diff --git a/src/test/ui/regions/regions-close-over-type-parameter-multiple.rs b/src/test/ui/regions/regions-close-over-type-parameter-multiple.rs index 26643e0898..fc7696e7e0 100644 --- a/src/test/ui/regions/regions-close-over-type-parameter-multiple.rs +++ b/src/test/ui/regions/regions-close-over-type-parameter-multiple.rs @@ -1,23 +1,23 @@ -#![feature(box_syntax)] - // Various tests where we over type parameters with multiple lifetime // bounds. + trait SomeTrait { fn get(&self) -> isize; } + fn make_object_good1<'a,'b,A:SomeTrait+'a+'b>(v: A) -> Box { // A outlives 'a AND 'b... - box v as Box // ...hence this type is safe. + Box::new(v) as Box // ...hence this type is safe. } fn make_object_good2<'a,'b,A:SomeTrait+'a+'b>(v: A) -> Box { // A outlives 'a AND 'b... - box v as Box // ...hence this type is safe. + Box::new(v) as Box // ...hence this type is safe. } fn make_object_bad<'a,'b,'c,A:SomeTrait+'a+'b>(v: A) -> Box { // A outlives 'a AND 'b...but not 'c. - box v as Box //~ ERROR cannot infer an appropriate lifetime + Box::new(v) as Box //~ ERROR cannot infer an appropriate lifetime } fn main() { diff --git a/src/test/ui/regions/regions-close-over-type-parameter-multiple.stderr b/src/test/ui/regions/regions-close-over-type-parameter-multiple.stderr index 0cce89215d..aa22fd96de 100644 --- a/src/test/ui/regions/regions-close-over-type-parameter-multiple.stderr +++ b/src/test/ui/regions/regions-close-over-type-parameter-multiple.stderr @@ -1,10 +1,10 @@ error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements --> $DIR/regions-close-over-type-parameter-multiple.rs:20:5 | -LL | box v as Box - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | Box::new(v) as Box + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 18:20... +note: first, the lifetime cannot outlive the lifetime `'a` as defined here... --> $DIR/regions-close-over-type-parameter-multiple.rs:18:20 | LL | fn make_object_bad<'a,'b,'c,A:SomeTrait+'a+'b>(v: A) -> Box { @@ -12,18 +12,18 @@ LL | fn make_object_bad<'a,'b,'c,A:SomeTrait+'a+'b>(v: A) -> Box $DIR/regions-close-over-type-parameter-multiple.rs:20:5 | -LL | box v as Box - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: but, the lifetime must be valid for the lifetime `'c` as defined on the function body at 18:26... +LL | Box::new(v) as Box + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: but, the lifetime must be valid for the lifetime `'c` as defined here... --> $DIR/regions-close-over-type-parameter-multiple.rs:18:26 | LL | fn make_object_bad<'a,'b,'c,A:SomeTrait+'a+'b>(v: A) -> Box { | ^^ -note: ...so that the expression is assignable +note: ...so that the types are compatible --> $DIR/regions-close-over-type-parameter-multiple.rs:20:5 | -LL | box v as Box - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | Box::new(v) as Box + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: expected `Box<(dyn SomeTrait + 'c)>` found `Box` diff --git a/src/test/ui/regions/regions-close-over-type-parameter-successfully.rs b/src/test/ui/regions/regions-close-over-type-parameter-successfully.rs index 4b47ed8c6a..48aad9481b 100644 --- a/src/test/ui/regions/regions-close-over-type-parameter-successfully.rs +++ b/src/test/ui/regions/regions-close-over-type-parameter-successfully.rs @@ -2,8 +2,6 @@ // A test where we (successfully) close over a reference into // an object. -#![feature(box_syntax)] - trait SomeTrait { fn get(&self) -> isize; } impl<'a> SomeTrait for &'a isize { @@ -13,7 +11,7 @@ impl<'a> SomeTrait for &'a isize { } fn make_object<'a,A:SomeTrait+'a>(v: A) -> Box { - box v as Box + Box::new(v) as Box } fn main() { diff --git a/src/test/ui/regions/regions-creating-enums4.stderr b/src/test/ui/regions/regions-creating-enums4.stderr index b24db1df18..8b1b90f5b1 100644 --- a/src/test/ui/regions/regions-creating-enums4.stderr +++ b/src/test/ui/regions/regions-creating-enums4.stderr @@ -4,7 +4,7 @@ error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` d LL | Ast::Add(x, y) | ^^^^^^^^ | -note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 6:16... +note: first, the lifetime cannot outlive the lifetime `'a` as defined here... --> $DIR/regions-creating-enums4.rs:6:16 | LL | fn mk_add_bad2<'a,'b>(x: &'a Ast<'a>, y: &'a Ast<'a>, z: &Ast) -> Ast<'b> { @@ -16,12 +16,12 @@ LL | Ast::Add(x, y) | ^ = note: expected `&Ast<'_>` found `&Ast<'a>` -note: but, the lifetime must be valid for the lifetime `'b` as defined on the function body at 6:19... +note: but, the lifetime must be valid for the lifetime `'b` as defined here... --> $DIR/regions-creating-enums4.rs:6:19 | LL | fn mk_add_bad2<'a,'b>(x: &'a Ast<'a>, y: &'a Ast<'a>, z: &Ast) -> Ast<'b> { | ^^ -note: ...so that the expression is assignable +note: ...so that the types are compatible --> $DIR/regions-creating-enums4.rs:7:5 | LL | Ast::Add(x, y) diff --git a/src/test/ui/regions/regions-dependent-addr-of.rs b/src/test/ui/regions/regions-dependent-addr-of.rs index 0a7e6625c7..a6cb56e315 100644 --- a/src/test/ui/regions/regions-dependent-addr-of.rs +++ b/src/test/ui/regions/regions-dependent-addr-of.rs @@ -3,7 +3,6 @@ // Issue #3148. #![feature(box_patterns)] -#![feature(box_syntax)] struct A { value: B @@ -81,7 +80,7 @@ pub fn main() { v2: [23, 24, 25], v3: vec![26, 27, 28], v4: C { f: 29 }, - v5: box C { f: 30 }, + v5: Box::new(C { f: 30 }), v6: Some(C { f: 31 })}}; let p = get_v1(&a); diff --git a/src/test/ui/regions/regions-early-bound-error-method.stderr b/src/test/ui/regions/regions-early-bound-error-method.stderr index 9095451da0..99a5f0ce4c 100644 --- a/src/test/ui/regions/regions-early-bound-error-method.stderr +++ b/src/test/ui/regions/regions-early-bound-error-method.stderr @@ -4,12 +4,12 @@ error[E0312]: lifetime of reference outlives lifetime of borrowed content... LL | g2.get() | ^^^^^^^^ | -note: ...the reference is valid for the lifetime `'a` as defined on the impl at 18:6... +note: ...the reference is valid for the lifetime `'a` as defined here... --> $DIR/regions-early-bound-error-method.rs:18:6 | LL | impl<'a> Box<'a> { | ^^ -note: ...but the borrowed content is only valid for the lifetime `'b` as defined on the method body at 19:11 +note: ...but the borrowed content is only valid for the lifetime `'b` as defined here --> $DIR/regions-early-bound-error-method.rs:19:11 | LL | fn or<'b,G:GetRef<'b>>(&self, g2: G) -> &'a isize { diff --git a/src/test/ui/regions/regions-early-bound-error.stderr b/src/test/ui/regions/regions-early-bound-error.stderr index 162d573362..df9e979eac 100644 --- a/src/test/ui/regions/regions-early-bound-error.stderr +++ b/src/test/ui/regions/regions-early-bound-error.stderr @@ -4,12 +4,12 @@ error[E0312]: lifetime of reference outlives lifetime of borrowed content... LL | g1.get() | ^^^^^^^^ | -note: ...the reference is valid for the lifetime `'b` as defined on the function body at 18:11... +note: ...the reference is valid for the lifetime `'b` as defined here... --> $DIR/regions-early-bound-error.rs:18:11 | LL | fn get<'a,'b,G:GetRef<'a, isize>>(g1: G, b: &'b isize) -> &'b isize { | ^^ -note: ...but the borrowed content is only valid for the lifetime `'a` as defined on the function body at 18:8 +note: ...but the borrowed content is only valid for the lifetime `'a` as defined here --> $DIR/regions-early-bound-error.rs:18:8 | LL | fn get<'a,'b,G:GetRef<'a, isize>>(g1: G, b: &'b isize) -> &'b isize { diff --git a/src/test/ui/regions/regions-early-bound-trait-param.rs b/src/test/ui/regions/regions-early-bound-trait-param.rs index 276a64b8e9..a28bd14ba8 100644 --- a/src/test/ui/regions/regions-early-bound-trait-param.rs +++ b/src/test/ui/regions/regions-early-bound-trait-param.rs @@ -2,8 +2,6 @@ // Tests that you can use an early-bound lifetime parameter as // on of the generic parameters in a trait. -#![feature(box_syntax)] - trait Trait<'a> { fn long(&'a self) -> isize; fn short<'b>(&'b self) -> isize; @@ -72,7 +70,7 @@ impl<'s> Trait<'s> for (isize,isize) { impl<'t> MakerTrait for Box+'static> { fn mk() -> Box+'static> { - let tup: Box<(isize, isize)> = box (4,5); + let tup: Box<(isize, isize)> = Box::new((4,5)); tup as Box } } diff --git a/src/test/ui/regions/regions-escape-into-other-fn.rs b/src/test/ui/regions/regions-escape-into-other-fn.rs index fd4690463e..65f4c1b6a6 100644 --- a/src/test/ui/regions/regions-escape-into-other-fn.rs +++ b/src/test/ui/regions/regions-escape-into-other-fn.rs @@ -1,10 +1,8 @@ // run-pass -#![feature(box_syntax)] - fn foo(x: &usize) -> &usize { x } fn bar(x: &usize) -> usize { *x } pub fn main() { - let p: Box<_> = box 3; + let p: Box<_> = Box::new(3); assert_eq!(bar(foo(&*p)), 3); } diff --git a/src/test/ui/regions/regions-free-region-ordering-callee-4.stderr b/src/test/ui/regions/regions-free-region-ordering-callee-4.stderr index 5ab423d9e2..1df7ca0e3e 100644 --- a/src/test/ui/regions/regions-free-region-ordering-callee-4.stderr +++ b/src/test/ui/regions/regions-free-region-ordering-callee-4.stderr @@ -4,12 +4,12 @@ error[E0491]: in type `&'a &'b usize`, reference has a longer lifetime than the LL | fn ordering4<'a, 'b, F>(a: &'a usize, b: &'b usize, x: F) where F: FnOnce(&'a &'b usize) { | ^^^^^^^^^^^^^^^^^^^^^ | -note: the pointer is valid for the lifetime `'a` as defined on the function body at 5:14 +note: the pointer is valid for the lifetime `'a` as defined here --> $DIR/regions-free-region-ordering-callee-4.rs:5:14 | LL | fn ordering4<'a, 'b, F>(a: &'a usize, b: &'b usize, x: F) where F: FnOnce(&'a &'b usize) { | ^^ -note: but the referenced data is only valid for the lifetime `'b` as defined on the function body at 5:18 +note: but the referenced data is only valid for the lifetime `'b` as defined here --> $DIR/regions-free-region-ordering-callee-4.rs:5:18 | LL | fn ordering4<'a, 'b, F>(a: &'a usize, b: &'b usize, x: F) where F: FnOnce(&'a &'b usize) { diff --git a/src/test/ui/regions/regions-free-region-ordering-caller.migrate.stderr b/src/test/ui/regions/regions-free-region-ordering-caller.migrate.stderr index 06e1b0f1ac..c0f3b24f68 100644 --- a/src/test/ui/regions/regions-free-region-ordering-caller.migrate.stderr +++ b/src/test/ui/regions/regions-free-region-ordering-caller.migrate.stderr @@ -4,12 +4,12 @@ error[E0491]: in type `&'b &'a usize`, reference has a longer lifetime than the LL | let z: Option<&'b &'a usize> = None; | ^^^^^^^^^^^^^^^^^^^^^ | -note: the pointer is valid for the lifetime `'b` as defined on the function body at 10:14 +note: the pointer is valid for the lifetime `'b` as defined here --> $DIR/regions-free-region-ordering-caller.rs:10:14 | LL | fn call2<'a, 'b>(a: &'a usize, b: &'b usize) { | ^^ -note: but the referenced data is only valid for the lifetime `'a` as defined on the function body at 10:10 +note: but the referenced data is only valid for the lifetime `'a` as defined here --> $DIR/regions-free-region-ordering-caller.rs:10:10 | LL | fn call2<'a, 'b>(a: &'a usize, b: &'b usize) { @@ -21,12 +21,12 @@ error[E0491]: in type `&'b Paramd<'a>`, reference has a longer lifetime than the LL | let z: Option<&'b Paramd<'a>> = None; | ^^^^^^^^^^^^^^^^^^^^^^ | -note: the pointer is valid for the lifetime `'b` as defined on the function body at 15:14 +note: the pointer is valid for the lifetime `'b` as defined here --> $DIR/regions-free-region-ordering-caller.rs:15:14 | LL | fn call3<'a, 'b>(a: &'a usize, b: &'b usize) { | ^^ -note: but the referenced data is only valid for the lifetime `'a` as defined on the function body at 15:10 +note: but the referenced data is only valid for the lifetime `'a` as defined here --> $DIR/regions-free-region-ordering-caller.rs:15:10 | LL | fn call3<'a, 'b>(a: &'a usize, b: &'b usize) { @@ -38,12 +38,12 @@ error[E0491]: in type `&'a &'b usize`, reference has a longer lifetime than the LL | let z: Option<&'a &'b usize> = None; | ^^^^^^^^^^^^^^^^^^^^^ | -note: the pointer is valid for the lifetime `'a` as defined on the function body at 21:10 +note: the pointer is valid for the lifetime `'a` as defined here --> $DIR/regions-free-region-ordering-caller.rs:21:10 | LL | fn call4<'a, 'b>(a: &'a usize, b: &'b usize) { | ^^ -note: but the referenced data is only valid for the lifetime `'b` as defined on the function body at 21:14 +note: but the referenced data is only valid for the lifetime `'b` as defined here --> $DIR/regions-free-region-ordering-caller.rs:21:14 | LL | fn call4<'a, 'b>(a: &'a usize, b: &'b usize) { diff --git a/src/test/ui/regions/regions-free-region-ordering-incorrect.stderr b/src/test/ui/regions/regions-free-region-ordering-incorrect.stderr index 10644174b9..b0a8f4af39 100644 --- a/src/test/ui/regions/regions-free-region-ordering-incorrect.stderr +++ b/src/test/ui/regions/regions-free-region-ordering-incorrect.stderr @@ -4,7 +4,7 @@ error[E0495]: cannot infer an appropriate lifetime for borrow expression due to LL | None => &self.val | ^^^^^^^^^ | -note: first, the lifetime cannot outlive the lifetime `'a` as defined on the method body at 14:12... +note: first, the lifetime cannot outlive the lifetime `'a` as defined here... --> $DIR/regions-free-region-ordering-incorrect.rs:14:12 | LL | fn get<'a>(&'a self) -> &'b T { @@ -14,7 +14,7 @@ note: ...so that reference does not outlive borrowed content | LL | None => &self.val | ^^^^^^^^^ -note: but, the lifetime must be valid for the lifetime `'b` as defined on the impl at 13:6... +note: but, the lifetime must be valid for the lifetime `'b` as defined here... --> $DIR/regions-free-region-ordering-incorrect.rs:13:6 | LL | impl<'b, T> Node<'b, T> { diff --git a/src/test/ui/regions/regions-infer-borrow-scope-within-loop-ok.rs b/src/test/ui/regions/regions-infer-borrow-scope-within-loop-ok.rs index f0ecc5de54..dca26742da 100644 --- a/src/test/ui/regions/regions-infer-borrow-scope-within-loop-ok.rs +++ b/src/test/ui/regions/regions-infer-borrow-scope-within-loop-ok.rs @@ -1,10 +1,9 @@ // run-pass -#![feature(box_syntax)] fn borrow(x: &T) -> &T {x} pub fn main() { - let x: Box<_> = box 3; + let x: Box<_> = Box::new(3); loop { let y = borrow(&*x); assert_eq!(*x, *y); diff --git a/src/test/ui/regions/regions-infer-borrow-scope.rs b/src/test/ui/regions/regions-infer-borrow-scope.rs index 453973d9c5..b4a050bf1e 100644 --- a/src/test/ui/regions/regions-infer-borrow-scope.rs +++ b/src/test/ui/regions/regions-infer-borrow-scope.rs @@ -1,6 +1,5 @@ // run-pass #![allow(dead_code)] -#![feature(box_syntax)] struct Point {x: isize, y: isize} @@ -9,7 +8,7 @@ fn x_coord(p: &Point) -> &isize { } pub fn main() { - let p: Box<_> = box Point {x: 3, y: 4}; + let p: Box<_> = Box::new(Point {x: 3, y: 4}); let xc = x_coord(&*p); assert_eq!(*xc, 3); } diff --git a/src/test/ui/regions/regions-infer-invariance-due-to-decl.nll.stderr b/src/test/ui/regions/regions-infer-invariance-due-to-decl.nll.stderr index 3256e3c0dd..0c1e3989b2 100644 --- a/src/test/ui/regions/regions-infer-invariance-due-to-decl.nll.stderr +++ b/src/test/ui/regions/regions-infer-invariance-due-to-decl.nll.stderr @@ -5,8 +5,6 @@ LL | fn to_longer_lifetime<'r>(b_isize: Invariant<'r>) -> Invariant<'static> { | -- lifetime `'r` defined here LL | b_isize | ^^^^^^^ returning this value requires that `'r` must outlive `'static` - | - = help: consider replacing `'r` with `'static` error: aborting due to previous error diff --git a/src/test/ui/regions/regions-infer-invariance-due-to-decl.stderr b/src/test/ui/regions/regions-infer-invariance-due-to-decl.stderr index 4de380ad03..afd522aa00 100644 --- a/src/test/ui/regions/regions-infer-invariance-due-to-decl.stderr +++ b/src/test/ui/regions/regions-infer-invariance-due-to-decl.stderr @@ -6,7 +6,7 @@ LL | b_isize | = note: expected struct `Invariant<'static>` found struct `Invariant<'r>` -note: the lifetime `'r` as defined on the function body at 11:23... +note: the lifetime `'r` as defined here... --> $DIR/regions-infer-invariance-due-to-decl.rs:11:23 | LL | fn to_longer_lifetime<'r>(b_isize: Invariant<'r>) -> Invariant<'static> { diff --git a/src/test/ui/regions/regions-infer-invariance-due-to-mutability-3.nll.stderr b/src/test/ui/regions/regions-infer-invariance-due-to-mutability-3.nll.stderr index 991f9a287b..0edeb27239 100644 --- a/src/test/ui/regions/regions-infer-invariance-due-to-mutability-3.nll.stderr +++ b/src/test/ui/regions/regions-infer-invariance-due-to-mutability-3.nll.stderr @@ -5,8 +5,6 @@ LL | fn to_longer_lifetime<'r>(b_isize: Invariant<'r>) -> Invariant<'static> { | -- lifetime `'r` defined here LL | b_isize | ^^^^^^^ returning this value requires that `'r` must outlive `'static` - | - = help: consider replacing `'r` with `'static` error: aborting due to previous error diff --git a/src/test/ui/regions/regions-infer-invariance-due-to-mutability-3.stderr b/src/test/ui/regions/regions-infer-invariance-due-to-mutability-3.stderr index a98d2f0222..bb594f3676 100644 --- a/src/test/ui/regions/regions-infer-invariance-due-to-mutability-3.stderr +++ b/src/test/ui/regions/regions-infer-invariance-due-to-mutability-3.stderr @@ -6,7 +6,7 @@ LL | b_isize | = note: expected struct `Invariant<'static>` found struct `Invariant<'r>` -note: the lifetime `'r` as defined on the function body at 9:23... +note: the lifetime `'r` as defined here... --> $DIR/regions-infer-invariance-due-to-mutability-3.rs:9:23 | LL | fn to_longer_lifetime<'r>(b_isize: Invariant<'r>) -> Invariant<'static> { diff --git a/src/test/ui/regions/regions-infer-invariance-due-to-mutability-4.nll.stderr b/src/test/ui/regions/regions-infer-invariance-due-to-mutability-4.nll.stderr index 2d62fb85b8..724dd7e3f6 100644 --- a/src/test/ui/regions/regions-infer-invariance-due-to-mutability-4.nll.stderr +++ b/src/test/ui/regions/regions-infer-invariance-due-to-mutability-4.nll.stderr @@ -5,8 +5,6 @@ LL | fn to_longer_lifetime<'r>(b_isize: Invariant<'r>) -> Invariant<'static> { | -- lifetime `'r` defined here LL | b_isize | ^^^^^^^ returning this value requires that `'r` must outlive `'static` - | - = help: consider replacing `'r` with `'static` error: aborting due to previous error diff --git a/src/test/ui/regions/regions-infer-invariance-due-to-mutability-4.stderr b/src/test/ui/regions/regions-infer-invariance-due-to-mutability-4.stderr index deb08ff862..04d11b5b7c 100644 --- a/src/test/ui/regions/regions-infer-invariance-due-to-mutability-4.stderr +++ b/src/test/ui/regions/regions-infer-invariance-due-to-mutability-4.stderr @@ -6,7 +6,7 @@ LL | b_isize | = note: expected struct `Invariant<'static>` found struct `Invariant<'r>` -note: the lifetime `'r` as defined on the function body at 9:23... +note: the lifetime `'r` as defined here... --> $DIR/regions-infer-invariance-due-to-mutability-4.rs:9:23 | LL | fn to_longer_lifetime<'r>(b_isize: Invariant<'r>) -> Invariant<'static> { diff --git a/src/test/ui/regions/regions-infer-not-param.stderr b/src/test/ui/regions/regions-infer-not-param.stderr index a6e2047559..a23bdeb834 100644 --- a/src/test/ui/regions/regions-infer-not-param.stderr +++ b/src/test/ui/regions/regions-infer-not-param.stderr @@ -6,12 +6,12 @@ LL | fn take_direct<'a,'b>(p: Direct<'a>) -> Direct<'b> { p } | = note: expected struct `Direct<'b>` found struct `Direct<'a>` -note: the lifetime `'a` as defined on the function body at 15:16... +note: the lifetime `'a` as defined here... --> $DIR/regions-infer-not-param.rs:15:16 | LL | fn take_direct<'a,'b>(p: Direct<'a>) -> Direct<'b> { p } | ^^ -note: ...does not necessarily outlive the lifetime `'b` as defined on the function body at 15:19 +note: ...does not necessarily outlive the lifetime `'b` as defined here --> $DIR/regions-infer-not-param.rs:15:19 | LL | fn take_direct<'a,'b>(p: Direct<'a>) -> Direct<'b> { p } @@ -25,12 +25,12 @@ LL | fn take_indirect2<'a,'b>(p: Indirect2<'a>) -> Indirect2<'b> { p } | = note: expected struct `Indirect2<'b>` found struct `Indirect2<'a>` -note: the lifetime `'a` as defined on the function body at 19:19... +note: the lifetime `'a` as defined here... --> $DIR/regions-infer-not-param.rs:19:19 | LL | fn take_indirect2<'a,'b>(p: Indirect2<'a>) -> Indirect2<'b> { p } | ^^ -note: ...does not necessarily outlive the lifetime `'b` as defined on the function body at 19:22 +note: ...does not necessarily outlive the lifetime `'b` as defined here --> $DIR/regions-infer-not-param.rs:19:22 | LL | fn take_indirect2<'a,'b>(p: Indirect2<'a>) -> Indirect2<'b> { p } @@ -44,12 +44,12 @@ LL | fn take_indirect2<'a,'b>(p: Indirect2<'a>) -> Indirect2<'b> { p } | = note: expected struct `Indirect2<'b>` found struct `Indirect2<'a>` -note: the lifetime `'b` as defined on the function body at 19:22... +note: the lifetime `'b` as defined here... --> $DIR/regions-infer-not-param.rs:19:22 | LL | fn take_indirect2<'a,'b>(p: Indirect2<'a>) -> Indirect2<'b> { p } | ^^ -note: ...does not necessarily outlive the lifetime `'a` as defined on the function body at 19:19 +note: ...does not necessarily outlive the lifetime `'a` as defined here --> $DIR/regions-infer-not-param.rs:19:19 | LL | fn take_indirect2<'a,'b>(p: Indirect2<'a>) -> Indirect2<'b> { p } diff --git a/src/test/ui/regions/regions-infer-paramd-indirect.stderr b/src/test/ui/regions/regions-infer-paramd-indirect.stderr index 95eb4d1f75..d2b369fb07 100644 --- a/src/test/ui/regions/regions-infer-paramd-indirect.stderr +++ b/src/test/ui/regions/regions-infer-paramd-indirect.stderr @@ -6,12 +6,12 @@ LL | self.f = b; | = note: expected struct `Box>` found struct `Box>` -note: the anonymous lifetime defined on the method body at 21:36... +note: the anonymous lifetime defined here... --> $DIR/regions-infer-paramd-indirect.rs:21:36 | LL | fn set_f_bad(&mut self, b: Box) { | ^ -note: ...does not necessarily outlive the lifetime `'a` as defined on the impl at 16:6 +note: ...does not necessarily outlive the lifetime `'a` as defined here --> $DIR/regions-infer-paramd-indirect.rs:16:6 | LL | impl<'a> SetF<'a> for C<'a> { diff --git a/src/test/ui/regions/regions-lifetime-nonfree-late-bound.rs b/src/test/ui/regions/regions-lifetime-nonfree-late-bound.rs index c8106f32c6..3852a14d9f 100644 --- a/src/test/ui/regions/regions-lifetime-nonfree-late-bound.rs +++ b/src/test/ui/regions/regions-lifetime-nonfree-late-bound.rs @@ -15,19 +15,17 @@ // pretty-expanded FIXME #23616 -#![feature(box_syntax)] - pub fn main() { fn explicit() { fn test(_x: Option>) where F: FnMut(Box FnMut(&'a isize)>) {} - test(Some(box |_f: Box FnMut(&'a isize)>| {})); + test(Some(Box::new(|_f: Box FnMut(&'a isize)>| {}))); } // The code below is shorthand for the code above (and more likely // to represent what one encounters in practice). fn implicit() { fn test(_x: Option>) where F: FnMut(Box) {} - test(Some(box |_f: Box| {})); + test(Some(Box::new(|_f: Box| {}))); } explicit(); diff --git a/src/test/ui/regions/regions-nested-fns.nll.stderr b/src/test/ui/regions/regions-nested-fns.nll.stderr index 60754f4c22..a0cfa36247 100644 --- a/src/test/ui/regions/regions-nested-fns.nll.stderr +++ b/src/test/ui/regions/regions-nested-fns.nll.stderr @@ -45,8 +45,6 @@ LL | fn nested<'x>(x: &'x isize) { ... LL | if false { return x; } | ^ returning this value requires that `'x` must outlive `'static` - | - = help: consider replacing `'x` with `'static` error: aborting due to 4 previous errors diff --git a/src/test/ui/regions/regions-nested-fns.stderr b/src/test/ui/regions/regions-nested-fns.stderr index eeec0cc786..11affcaaa7 100644 --- a/src/test/ui/regions/regions-nested-fns.stderr +++ b/src/test/ui/regions/regions-nested-fns.stderr @@ -4,7 +4,7 @@ error[E0495]: cannot infer an appropriate lifetime due to conflicting requiremen LL | let mut ay = &y; | ^^ | -note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the body at 7:58... +note: first, the lifetime cannot outlive the anonymous lifetime #1 defined here... --> $DIR/regions-nested-fns.rs:7:58 | LL | ignore:: FnMut(&'z isize)>>(Box::new(|z| { @@ -19,7 +19,7 @@ note: ...so that reference does not outlive borrowed content | LL | ay = z; | ^ -note: but, the lifetime must be valid for the anonymous lifetime #1 defined on the body at 13:72... +note: but, the lifetime must be valid for the anonymous lifetime #1 defined here... --> $DIR/regions-nested-fns.rs:13:72 | LL | ignore::< Box FnMut(&'z isize) -> &'z isize>>(Box::new(|z| { @@ -48,7 +48,7 @@ error[E0312]: lifetime of reference outlives lifetime of borrowed content... LL | if false { return x; } | ^ | -note: ...the reference is valid for the anonymous lifetime #1 defined on the body at 13:72... +note: ...the reference is valid for the anonymous lifetime #1 defined here... --> $DIR/regions-nested-fns.rs:13:72 | LL | ignore::< Box FnMut(&'z isize) -> &'z isize>>(Box::new(|z| { @@ -58,7 +58,7 @@ LL | | if false { return ay; } LL | | return z; LL | | })); | |_____^ -note: ...but the borrowed content is only valid for the lifetime `'x` as defined on the function body at 3:11 +note: ...but the borrowed content is only valid for the lifetime `'x` as defined here --> $DIR/regions-nested-fns.rs:3:11 | LL | fn nested<'x>(x: &'x isize) { diff --git a/src/test/ui/regions/regions-normalize-in-where-clause-list.stderr b/src/test/ui/regions/regions-normalize-in-where-clause-list.stderr index ddb2b31ce1..2bb58b5ec2 100644 --- a/src/test/ui/regions/regions-normalize-in-where-clause-list.stderr +++ b/src/test/ui/regions/regions-normalize-in-where-clause-list.stderr @@ -8,12 +8,12 @@ LL | | where LL | | <() as Project<'a, 'b>>::Item: Eq, | |______________________________________^ | -note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 24:8... +note: first, the lifetime cannot outlive the lifetime `'a` as defined here... --> $DIR/regions-normalize-in-where-clause-list.rs:24:8 | LL | fn bar<'a, 'b>() | ^^ -note: ...but the lifetime must also be valid for the lifetime `'b` as defined on the function body at 24:12... +note: ...but the lifetime must also be valid for the lifetime `'b` as defined here... --> $DIR/regions-normalize-in-where-clause-list.rs:24:12 | LL | fn bar<'a, 'b>() @@ -36,12 +36,12 @@ error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` d LL | fn bar<'a, 'b>() | ^^^ | -note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 24:8... +note: first, the lifetime cannot outlive the lifetime `'a` as defined here... --> $DIR/regions-normalize-in-where-clause-list.rs:24:8 | LL | fn bar<'a, 'b>() | ^^ -note: ...but the lifetime must also be valid for the lifetime `'b` as defined on the function body at 24:12... +note: ...but the lifetime must also be valid for the lifetime `'b` as defined here... --> $DIR/regions-normalize-in-where-clause-list.rs:24:12 | LL | fn bar<'a, 'b>() diff --git a/src/test/ui/regions/regions-outlives-projection-container-hrtb.migrate.stderr b/src/test/ui/regions/regions-outlives-projection-container-hrtb.migrate.stderr index 0992d9bf29..60c115b3f5 100644 --- a/src/test/ui/regions/regions-outlives-projection-container-hrtb.migrate.stderr +++ b/src/test/ui/regions/regions-outlives-projection-container-hrtb.migrate.stderr @@ -4,12 +4,12 @@ error[E0491]: in type `&'a WithHrAssoc>`, reference has a longer lif LL | let _: &'a WithHrAssoc> = loop { }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: the pointer is valid for the lifetime `'a` as defined on the function body at 27:15 +note: the pointer is valid for the lifetime `'a` as defined here --> $DIR/regions-outlives-projection-container-hrtb.rs:27:15 | LL | fn with_assoc<'a,'b>() { | ^^ -note: but the referenced data is only valid for the lifetime `'b` as defined on the function body at 27:18 +note: but the referenced data is only valid for the lifetime `'b` as defined here --> $DIR/regions-outlives-projection-container-hrtb.rs:27:18 | LL | fn with_assoc<'a,'b>() { @@ -21,12 +21,12 @@ error[E0491]: in type `&'a WithHrAssocSub>`, reference has a longer LL | let _: &'a WithHrAssocSub> = loop { }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: the pointer is valid for the lifetime `'a` as defined on the function body at 46:19 +note: the pointer is valid for the lifetime `'a` as defined here --> $DIR/regions-outlives-projection-container-hrtb.rs:46:19 | LL | fn with_assoc_sub<'a,'b>() { | ^^ -note: but the referenced data is only valid for the lifetime `'b` as defined on the function body at 46:22 +note: but the referenced data is only valid for the lifetime `'b` as defined here --> $DIR/regions-outlives-projection-container-hrtb.rs:46:22 | LL | fn with_assoc_sub<'a,'b>() { diff --git a/src/test/ui/regions/regions-outlives-projection-container-wc.migrate.stderr b/src/test/ui/regions/regions-outlives-projection-container-wc.migrate.stderr index 49e28a14d8..8430b69f99 100644 --- a/src/test/ui/regions/regions-outlives-projection-container-wc.migrate.stderr +++ b/src/test/ui/regions/regions-outlives-projection-container-wc.migrate.stderr @@ -4,12 +4,12 @@ error[E0491]: in type `&'a WithAssoc>`, reference has a longer lifet LL | let _: &'a WithAssoc> = loop { }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: the pointer is valid for the lifetime `'a` as defined on the function body at 27:15 +note: the pointer is valid for the lifetime `'a` as defined here --> $DIR/regions-outlives-projection-container-wc.rs:27:15 | LL | fn with_assoc<'a,'b>() { | ^^ -note: but the referenced data is only valid for the lifetime `'b` as defined on the function body at 27:18 +note: but the referenced data is only valid for the lifetime `'b` as defined here --> $DIR/regions-outlives-projection-container-wc.rs:27:18 | LL | fn with_assoc<'a,'b>() { diff --git a/src/test/ui/regions/regions-outlives-projection-container.stderr b/src/test/ui/regions/regions-outlives-projection-container.stderr index dba15fb057..8c2b2c1e24 100644 --- a/src/test/ui/regions/regions-outlives-projection-container.stderr +++ b/src/test/ui/regions/regions-outlives-projection-container.stderr @@ -4,12 +4,12 @@ error[E0491]: in type `&'a WithAssoc>`, reference has a longer lifet LL | let _x: &'a WithAssoc> = loop { }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: the pointer is valid for the lifetime `'a` as defined on the function body at 28:15 +note: the pointer is valid for the lifetime `'a` as defined here --> $DIR/regions-outlives-projection-container.rs:28:15 | LL | fn with_assoc<'a,'b>() { | ^^ -note: but the referenced data is only valid for the lifetime `'b` as defined on the function body at 28:18 +note: but the referenced data is only valid for the lifetime `'b` as defined here --> $DIR/regions-outlives-projection-container.rs:28:18 | LL | fn with_assoc<'a,'b>() { @@ -21,12 +21,12 @@ error[E0491]: in type `&'a WithoutAssoc>`, reference has a longer li LL | let _x: &'a WithoutAssoc> = loop { }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: the pointer is valid for the lifetime `'a` as defined on the function body at 50:18 +note: the pointer is valid for the lifetime `'a` as defined here --> $DIR/regions-outlives-projection-container.rs:50:18 | LL | fn without_assoc<'a,'b>() { | ^^ -note: but the referenced data is only valid for the lifetime `'b` as defined on the function body at 50:21 +note: but the referenced data is only valid for the lifetime `'b` as defined here --> $DIR/regions-outlives-projection-container.rs:50:21 | LL | fn without_assoc<'a,'b>() { @@ -38,12 +38,12 @@ error[E0491]: in type `&'a WithAssoc>`, reference has a longer lifet LL | call::<&'a WithAssoc>>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: the pointer is valid for the lifetime `'a` as defined on the function body at 58:20 +note: the pointer is valid for the lifetime `'a` as defined here --> $DIR/regions-outlives-projection-container.rs:58:20 | LL | fn call_with_assoc<'a,'b>() { | ^^ -note: but the referenced data is only valid for the lifetime `'b` as defined on the function body at 58:23 +note: but the referenced data is only valid for the lifetime `'b` as defined here --> $DIR/regions-outlives-projection-container.rs:58:23 | LL | fn call_with_assoc<'a,'b>() { @@ -55,12 +55,12 @@ error[E0491]: in type `&'a WithoutAssoc>`, reference has a longer li LL | call::<&'a WithoutAssoc>>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: the pointer is valid for the lifetime `'a` as defined on the function body at 67:23 +note: the pointer is valid for the lifetime `'a` as defined here --> $DIR/regions-outlives-projection-container.rs:67:23 | LL | fn call_without_assoc<'a,'b>() { | ^^ -note: but the referenced data is only valid for the lifetime `'b` as defined on the function body at 67:26 +note: but the referenced data is only valid for the lifetime `'b` as defined here --> $DIR/regions-outlives-projection-container.rs:67:26 | LL | fn call_without_assoc<'a,'b>() { diff --git a/src/test/ui/regions/regions-ref-in-fn-arg.rs b/src/test/ui/regions/regions-ref-in-fn-arg.rs index d1cbd279b6..3df529c9f0 100644 --- a/src/test/ui/regions/regions-ref-in-fn-arg.rs +++ b/src/test/ui/regions/regions-ref-in-fn-arg.rs @@ -1,11 +1,11 @@ #![feature(box_patterns)] -#![feature(box_syntax)] + fn arg_item(box ref x: Box) -> &'static isize { x //~ ERROR cannot return value referencing function parameter } -fn with(f: F) -> R where F: FnOnce(Box) -> R { f(box 3) } +fn with(f: F) -> R where F: FnOnce(Box) -> R { f(Box::new(3)) } fn arg_closure() -> &'static isize { with(|box ref x| x) //~ ERROR cannot return value referencing function parameter diff --git a/src/test/ui/regions/regions-relate-bound-regions-on-closures-to-inference-variables.rs b/src/test/ui/regions/regions-relate-bound-regions-on-closures-to-inference-variables.rs index aec05161c1..b1bdb813ac 100644 --- a/src/test/ui/regions/regions-relate-bound-regions-on-closures-to-inference-variables.rs +++ b/src/test/ui/regions/regions-relate-bound-regions-on-closures-to-inference-variables.rs @@ -9,8 +9,6 @@ // changes were caught. However, those uses in the compiler could // easily get changed or refactored away in the future. -#![feature(box_syntax)] - struct Ctxt<'tcx> { x: &'tcx Vec } diff --git a/src/test/ui/regions/regions-ret-borrowed-1.stderr b/src/test/ui/regions/regions-ret-borrowed-1.stderr index bba968cfde..86df7bfeb7 100644 --- a/src/test/ui/regions/regions-ret-borrowed-1.stderr +++ b/src/test/ui/regions/regions-ret-borrowed-1.stderr @@ -4,19 +4,19 @@ error[E0495]: cannot infer an appropriate lifetime due to conflicting requiremen LL | with(|o| o) | ^ | -note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the body at 10:10... +note: first, the lifetime cannot outlive the anonymous lifetime #1 defined here... --> $DIR/regions-ret-borrowed-1.rs:10:10 | LL | with(|o| o) | ^^^^^ -note: ...so that the expression is assignable +note: ...so that the types are compatible --> $DIR/regions-ret-borrowed-1.rs:10:14 | LL | with(|o| o) | ^ = note: expected `&isize` found `&isize` -note: but, the lifetime must be valid for the lifetime `'a` as defined on the function body at 9:14... +note: but, the lifetime must be valid for the lifetime `'a` as defined here... --> $DIR/regions-ret-borrowed-1.rs:9:14 | LL | fn return_it<'a>() -> &'a isize { diff --git a/src/test/ui/regions/regions-ret-borrowed.stderr b/src/test/ui/regions/regions-ret-borrowed.stderr index 4b93ca0ae6..b9a06d9743 100644 --- a/src/test/ui/regions/regions-ret-borrowed.stderr +++ b/src/test/ui/regions/regions-ret-borrowed.stderr @@ -4,19 +4,19 @@ error[E0495]: cannot infer an appropriate lifetime due to conflicting requiremen LL | with(|o| o) | ^ | -note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the body at 13:10... +note: first, the lifetime cannot outlive the anonymous lifetime #1 defined here... --> $DIR/regions-ret-borrowed.rs:13:10 | LL | with(|o| o) | ^^^^^ -note: ...so that the expression is assignable +note: ...so that the types are compatible --> $DIR/regions-ret-borrowed.rs:13:14 | LL | with(|o| o) | ^ = note: expected `&isize` found `&isize` -note: but, the lifetime must be valid for the lifetime `'a` as defined on the function body at 12:14... +note: but, the lifetime must be valid for the lifetime `'a` as defined here... --> $DIR/regions-ret-borrowed.rs:12:14 | LL | fn return_it<'a>() -> &'a isize { diff --git a/src/test/ui/regions/regions-static-bound.migrate.nll.stderr b/src/test/ui/regions/regions-static-bound.migrate.nll.stderr index a4c8e72114..a280c6f0a0 100644 --- a/src/test/ui/regions/regions-static-bound.migrate.nll.stderr +++ b/src/test/ui/regions/regions-static-bound.migrate.nll.stderr @@ -5,8 +5,6 @@ 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` - | - = help: consider replacing `'a` with `'static` error[E0621]: explicit lifetime required in the type of `u` --> $DIR/regions-static-bound.rs:14:5 diff --git a/src/test/ui/regions/regions-static-bound.migrate.stderr b/src/test/ui/regions/regions-static-bound.migrate.stderr index 644458e206..8f11e14822 100644 --- a/src/test/ui/regions/regions-static-bound.migrate.stderr +++ b/src/test/ui/regions/regions-static-bound.migrate.stderr @@ -5,7 +5,7 @@ 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 on the function body at 8:24 +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 { diff --git a/src/test/ui/regions/regions-static-bound.nll.stderr b/src/test/ui/regions/regions-static-bound.nll.stderr index a4c8e72114..a280c6f0a0 100644 --- a/src/test/ui/regions/regions-static-bound.nll.stderr +++ b/src/test/ui/regions/regions-static-bound.nll.stderr @@ -5,8 +5,6 @@ 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` - | - = help: consider replacing `'a` with `'static` error[E0621]: explicit lifetime required in the type of `u` --> $DIR/regions-static-bound.rs:14:5 diff --git a/src/test/ui/regions/regions-trait-object-subtyping.stderr b/src/test/ui/regions/regions-trait-object-subtyping.stderr index 7478b53bd3..d45ca94ad2 100644 --- a/src/test/ui/regions/regions-trait-object-subtyping.stderr +++ b/src/test/ui/regions/regions-trait-object-subtyping.stderr @@ -4,12 +4,12 @@ error[E0478]: lifetime bound not satisfied LL | x | ^ | -note: lifetime parameter instantiated with the lifetime `'a` as defined on the function body at 13:9 +note: lifetime parameter instantiated with the lifetime `'a` as defined here --> $DIR/regions-trait-object-subtyping.rs:13:9 | LL | fn foo3<'a,'b>(x: &'a mut dyn Dummy) -> &'b mut dyn Dummy { | ^^ -note: but lifetime parameter must outlive the lifetime `'b` as defined on the function body at 13:12 +note: but lifetime parameter must outlive the lifetime `'b` as defined here --> $DIR/regions-trait-object-subtyping.rs:13:12 | LL | fn foo3<'a,'b>(x: &'a mut dyn Dummy) -> &'b mut dyn Dummy { @@ -21,7 +21,7 @@ error[E0495]: cannot infer an appropriate lifetime for automatic coercion due to LL | x | ^ | -note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 13:9... +note: first, the lifetime cannot outlive the lifetime `'a` as defined here... --> $DIR/regions-trait-object-subtyping.rs:13:9 | LL | fn foo3<'a,'b>(x: &'a mut dyn Dummy) -> &'b mut dyn Dummy { @@ -31,12 +31,12 @@ note: ...so that reference does not outlive borrowed content | LL | x | ^ -note: but, the lifetime must be valid for the lifetime `'b` as defined on the function body at 13:12... +note: but, the lifetime must be valid for the lifetime `'b` as defined here... --> $DIR/regions-trait-object-subtyping.rs:13:12 | LL | fn foo3<'a,'b>(x: &'a mut dyn Dummy) -> &'b mut dyn Dummy { | ^^ -note: ...so that the expression is assignable +note: ...so that the types are compatible --> $DIR/regions-trait-object-subtyping.rs:15:5 | LL | x @@ -52,12 +52,12 @@ LL | x | = note: expected struct `Wrapper<&'b mut (dyn Dummy + 'b)>` found struct `Wrapper<&'a mut (dyn Dummy + 'a)>` -note: the lifetime `'b` as defined on the function body at 20:15... +note: the lifetime `'b` as defined here... --> $DIR/regions-trait-object-subtyping.rs:20:15 | LL | fn foo4<'a:'b,'b>(x: Wrapper<&'a mut dyn Dummy>) -> Wrapper<&'b mut dyn Dummy> { | ^^ -note: ...does not necessarily outlive the lifetime `'a` as defined on the function body at 20:9 +note: ...does not necessarily outlive the lifetime `'a` as defined here --> $DIR/regions-trait-object-subtyping.rs:20:9 | LL | fn foo4<'a:'b,'b>(x: Wrapper<&'a mut dyn Dummy>) -> Wrapper<&'b mut dyn Dummy> { diff --git a/src/test/ui/regions/regions-trait-variance.rs b/src/test/ui/regions/regions-trait-variance.rs index 9169d457d4..94ffb85c9c 100644 --- a/src/test/ui/regions/regions-trait-variance.rs +++ b/src/test/ui/regions/regions-trait-variance.rs @@ -1,5 +1,3 @@ -#![feature(box_syntax)] - // Issue #12470. trait X { @@ -31,9 +29,11 @@ fn make_a(p: &dyn X) -> A { } fn make_make_a<'a>() -> A<'a> { - let b: Box = box B { + + let b: Box = Box::new(B { i: 1, - }; + }); + let bb: &B = &*b; make_a(bb) //~ ERROR cannot return value referencing local data `*b` } diff --git a/src/test/ui/regions/regions-var-type-out-of-scope.stderr b/src/test/ui/regions/regions-var-type-out-of-scope.stderr index d957176768..476e82f046 100644 --- a/src/test/ui/regions/regions-var-type-out-of-scope.stderr +++ b/src/test/ui/regions/regions-var-type-out-of-scope.stderr @@ -6,7 +6,7 @@ LL | x = &id(3); | | | creates a temporary which is freed while still in use LL | assert_eq!(*x, 3); - | ------------------ borrow later used here + | ----------------- borrow later used here | = note: consider using a `let` binding to create a longer lived value diff --git a/src/test/ui/regions/regions-variance-invariant-use-covariant.nll.stderr b/src/test/ui/regions/regions-variance-invariant-use-covariant.nll.stderr index 90388a1c51..15853e6ca5 100644 --- a/src/test/ui/regions/regions-variance-invariant-use-covariant.nll.stderr +++ b/src/test/ui/regions/regions-variance-invariant-use-covariant.nll.stderr @@ -6,8 +6,6 @@ LL | fn use_<'b>(c: Invariant<'b>) { ... LL | let _: Invariant<'static> = c; | ^^^^^^^^^^^^^^^^^^ type annotation requires that `'b` must outlive `'static` - | - = help: consider replacing `'b` with `'static` error: aborting due to previous error diff --git a/src/test/ui/regions/regions-variance-invariant-use-covariant.stderr b/src/test/ui/regions/regions-variance-invariant-use-covariant.stderr index e7a5db671b..7801517595 100644 --- a/src/test/ui/regions/regions-variance-invariant-use-covariant.stderr +++ b/src/test/ui/regions/regions-variance-invariant-use-covariant.stderr @@ -6,7 +6,7 @@ LL | let _: Invariant<'static> = c; | = note: expected struct `Invariant<'static>` found struct `Invariant<'b>` -note: the lifetime `'b` as defined on the function body at 11:9... +note: the lifetime `'b` as defined here... --> $DIR/regions-variance-invariant-use-covariant.rs:11:9 | LL | fn use_<'b>(c: Invariant<'b>) { diff --git a/src/test/ui/regions/regions-wf-trait-object.stderr b/src/test/ui/regions/regions-wf-trait-object.stderr index 1ddbf73a46..f6006ca046 100644 --- a/src/test/ui/regions/regions-wf-trait-object.stderr +++ b/src/test/ui/regions/regions-wf-trait-object.stderr @@ -4,12 +4,12 @@ error[E0478]: lifetime bound not satisfied LL | x: Box+'b> | ^^^^^^^^^^^^^^^^^^^^^^^^ | -note: lifetime parameter instantiated with the lifetime `'b` as defined on the struct at 6:15 +note: lifetime parameter instantiated with the lifetime `'b` as defined here --> $DIR/regions-wf-trait-object.rs:6:15 | LL | struct Foo<'a,'b> { | ^^ -note: but lifetime parameter must outlive the lifetime `'a` as defined on the struct at 6:12 +note: but lifetime parameter must outlive the lifetime `'a` as defined here --> $DIR/regions-wf-trait-object.rs:6:12 | LL | struct Foo<'a,'b> { diff --git a/src/test/ui/repeat_count.stderr b/src/test/ui/repeat_count.stderr index c85f057203..59bcd954a1 100644 --- a/src/test/ui/repeat_count.stderr +++ b/src/test/ui/repeat_count.stderr @@ -55,7 +55,7 @@ LL | let f = [0; 4u8]; help: change the type of the numeric literal from `u8` to `usize` | LL | let f = [0; 4usize]; - | ~~~~~~ + | ~~~~~ error[E0308]: mismatched types --> $DIR/repeat_count.rs:31:17 diff --git a/src/test/ui/repr/repr-transparent-issue-87496.rs b/src/test/ui/repr/repr-transparent-issue-87496.rs new file mode 100644 index 0000000000..a4dd45c63f --- /dev/null +++ b/src/test/ui/repr/repr-transparent-issue-87496.rs @@ -0,0 +1,12 @@ +// Regression test for the ICE described in #87496. + +// check-pass + +#[repr(transparent)] +struct TransparentCustomZst(()); +extern "C" { + fn good17(p: TransparentCustomZst); + //~^ WARNING: `extern` block uses type `TransparentCustomZst`, which is not FFI-safe +} + +fn main() {} diff --git a/src/test/ui/repr/repr-transparent-issue-87496.stderr b/src/test/ui/repr/repr-transparent-issue-87496.stderr new file mode 100644 index 0000000000..c488755cc2 --- /dev/null +++ b/src/test/ui/repr/repr-transparent-issue-87496.stderr @@ -0,0 +1,16 @@ +warning: `extern` block uses type `TransparentCustomZst`, which is not FFI-safe + --> $DIR/repr-transparent-issue-87496.rs:8:18 + | +LL | fn good17(p: TransparentCustomZst); + | ^^^^^^^^^^^^^^^^^^^^ not FFI-safe + | + = note: `#[warn(improper_ctypes)]` on by default + = note: this struct contains only zero-sized fields +note: the type is defined here + --> $DIR/repr-transparent-issue-87496.rs:6:1 + | +LL | struct TransparentCustomZst(()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: 1 warning emitted + diff --git a/src/test/ui/issues/issue-42944.rs b/src/test/ui/resolve/issue-42944.rs similarity index 100% rename from src/test/ui/issues/issue-42944.rs rename to src/test/ui/resolve/issue-42944.rs diff --git a/src/test/ui/issues/issue-42944.stderr b/src/test/ui/resolve/issue-42944.stderr similarity index 81% rename from src/test/ui/issues/issue-42944.stderr rename to src/test/ui/resolve/issue-42944.stderr index 008492529d..cad3ccc4a0 100644 --- a/src/test/ui/issues/issue-42944.stderr +++ b/src/test/ui/resolve/issue-42944.stderr @@ -16,10 +16,11 @@ error[E0425]: cannot find function, tuple struct or tuple variant `Bx` in this s LL | Bx(()); | ^^ not found in this scope | -help: consider importing this tuple struct - | -LL | use foo::Bx; +note: tuple struct `foo::Bx` exists but is inaccessible + --> $DIR/issue-42944.rs:2:5 | +LL | pub struct Bx(()); + | ^^^^^^^^^^^^^^^^^^ not accessible error: aborting due to 2 previous errors diff --git a/src/test/ui/resolve/issue-82865.stderr b/src/test/ui/resolve/issue-82865.stderr index 0aa0610de7..7898c2a360 100644 --- a/src/test/ui/resolve/issue-82865.stderr +++ b/src/test/ui/resolve/issue-82865.stderr @@ -11,7 +11,7 @@ LL | Box::z | ^ function or associated item not found in `Box<_, _>` ... LL | mac!(); - | ------- in this macro invocation + | ------ in this macro invocation | = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/resolve/issue-85671.rs b/src/test/ui/resolve/issue-85671.rs new file mode 100644 index 0000000000..337ec307ef --- /dev/null +++ b/src/test/ui/resolve/issue-85671.rs @@ -0,0 +1,37 @@ +// check-pass + +// Some trait with a function that returns a slice: +pub trait AsSlice { + type Element; + fn as_slice(&self) -> &[Self::Element]; +} + +// Some type +pub struct A(Cont); + +// Here we say that if A wraps a slice, then it implements AsSlice +impl<'a, Element> AsSlice for A<&'a [Element]> { + type Element = Element; + fn as_slice(&self) -> &[Self::Element] { + self.0 + } +} + +impl A { + // We want this function to work + pub fn failing(&self) + where + Self: AsSlice, + { + self.as_ref_a().as_ref_a(); + } + + pub fn as_ref_a(&self) -> A<&[::Element]> + where + Self: AsSlice, + { + A(self.as_slice()) + } +} + +fn main() {} diff --git a/src/test/ui/resolve/issue-88472.rs b/src/test/ui/resolve/issue-88472.rs new file mode 100644 index 0000000000..6bf7caeddb --- /dev/null +++ b/src/test/ui/resolve/issue-88472.rs @@ -0,0 +1,38 @@ +// Regression test for #88472, where a suggestion was issued to +// import an inaccessible struct. + +#![warn(unused_imports)] +//~^ NOTE: the lint level is defined here + +mod a { + struct Foo; + //~^ NOTE: struct `a::Foo` exists but is inaccessible + //~| NOTE: not accessible +} + +mod b { + use crate::a::*; + //~^ WARNING: unused import + type Bar = Foo; + //~^ ERROR: cannot find type `Foo` in this scope [E0412] + //~| NOTE: not found in this scope +} + +mod c { + enum Eee {} + //~^ NOTE: these enums exist but are inaccessible + //~| NOTE: `c::Eee`: not accessible + + mod d { + enum Eee {} + //~^ NOTE: `c::d::Eee`: not accessible + } +} + +mod e { + type Baz = Eee; + //~^ ERROR: cannot find type `Eee` in this scope [E0412] + //~| NOTE: not found in this scope +} + +fn main() {} diff --git a/src/test/ui/resolve/issue-88472.stderr b/src/test/ui/resolve/issue-88472.stderr new file mode 100644 index 0000000000..8431fc9776 --- /dev/null +++ b/src/test/ui/resolve/issue-88472.stderr @@ -0,0 +1,42 @@ +error[E0412]: cannot find type `Foo` in this scope + --> $DIR/issue-88472.rs:16:16 + | +LL | type Bar = Foo; + | ^^^ not found in this scope + | +note: struct `a::Foo` exists but is inaccessible + --> $DIR/issue-88472.rs:8:5 + | +LL | struct Foo; + | ^^^^^^^^^^^ not accessible + +error[E0412]: cannot find type `Eee` in this scope + --> $DIR/issue-88472.rs:33:16 + | +LL | type Baz = Eee; + | ^^^ not found in this scope + | +note: these enums exist but are inaccessible + --> $DIR/issue-88472.rs:22:5 + | +LL | enum Eee {} + | ^^^^^^^^ `c::Eee`: not accessible +... +LL | enum Eee {} + | ^^^^^^^^ `c::d::Eee`: not accessible + +warning: unused import: `crate::a::*` + --> $DIR/issue-88472.rs:14:9 + | +LL | use crate::a::*; + | ^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/issue-88472.rs:4:9 + | +LL | #![warn(unused_imports)] + | ^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0412`. diff --git a/src/test/ui/resolve/privacy-enum-ctor.stderr b/src/test/ui/resolve/privacy-enum-ctor.stderr index 192349e0fa..ff72b0b563 100644 --- a/src/test/ui/resolve/privacy-enum-ctor.stderr +++ b/src/test/ui/resolve/privacy-enum-ctor.stderr @@ -169,16 +169,13 @@ LL | pub enum E { | ---------- similarly named enum `E` defined here ... LL | let _: Z = m::n::Z; - | ^ + | ^ help: an enum with a similar name exists: `E` | -help: an enum with a similar name exists - | -LL | let _: E = m::n::Z; - | ~ -help: consider importing this enum - | -LL | use m::Z; +note: enum `m::Z` exists but is inaccessible + --> $DIR/privacy-enum-ctor.rs:11:9 | +LL | pub(in m) enum Z { + | ^^^^^^^^^^^^^^^^ not accessible error[E0423]: expected value, found enum `m::n::Z` --> $DIR/privacy-enum-ctor.rs:57:16 @@ -215,16 +212,13 @@ LL | pub enum E { | ---------- similarly named enum `E` defined here ... LL | let _: Z = m::n::Z::Fn; - | ^ + | ^ help: an enum with a similar name exists: `E` | -help: an enum with a similar name exists - | -LL | let _: E = m::n::Z::Fn; - | ~ -help: consider importing this enum - | -LL | use m::Z; +note: enum `m::Z` exists but is inaccessible + --> $DIR/privacy-enum-ctor.rs:11:9 | +LL | pub(in m) enum Z { + | ^^^^^^^^^^^^^^^^ not accessible error[E0412]: cannot find type `Z` in this scope --> $DIR/privacy-enum-ctor.rs:64:12 @@ -233,16 +227,13 @@ LL | pub enum E { | ---------- similarly named enum `E` defined here ... LL | let _: Z = m::n::Z::Struct; - | ^ + | ^ help: an enum with a similar name exists: `E` | -help: an enum with a similar name exists - | -LL | let _: E = m::n::Z::Struct; - | ~ -help: consider importing this enum - | -LL | use m::Z; +note: enum `m::Z` exists but is inaccessible + --> $DIR/privacy-enum-ctor.rs:11:9 | +LL | pub(in m) enum Z { + | ^^^^^^^^^^^^^^^^ not accessible error[E0423]: expected value, found struct variant `m::n::Z::Struct` --> $DIR/privacy-enum-ctor.rs:64:16 @@ -262,16 +253,13 @@ LL | pub enum E { | ---------- similarly named enum `E` defined here ... LL | let _: Z = m::n::Z::Unit {}; - | ^ + | ^ help: an enum with a similar name exists: `E` | -help: an enum with a similar name exists - | -LL | let _: E = m::n::Z::Unit {}; - | ~ -help: consider importing this enum - | -LL | use m::Z; +note: enum `m::Z` exists but is inaccessible + --> $DIR/privacy-enum-ctor.rs:11:9 | +LL | pub(in m) enum Z { + | ^^^^^^^^^^^^^^^^ not accessible error[E0603]: enum `Z` is private --> $DIR/privacy-enum-ctor.rs:57:22 diff --git a/src/test/ui/resolve/privacy-struct-ctor.stderr b/src/test/ui/resolve/privacy-struct-ctor.stderr index e5d6f7e9e2..ada053014e 100644 --- a/src/test/ui/resolve/privacy-struct-ctor.stderr +++ b/src/test/ui/resolve/privacy-struct-ctor.stderr @@ -33,10 +33,11 @@ error[E0423]: expected value, found struct `xcrate::S` LL | xcrate::S; | ^^^^^^^^^ constructor is not visible here due to private fields | -help: consider importing this tuple struct instead - | -LL | use m::S; +note: tuple struct `m::S` exists but is inaccessible + --> $DIR/privacy-struct-ctor.rs:6:5 | +LL | pub struct S(u8); + | ^^^^^^^^^^^^^^^^^ not accessible error[E0603]: tuple struct constructor `Z` is private --> $DIR/privacy-struct-ctor.rs:18:12 diff --git a/src/test/ui/resolve/suggest-path-for-tuple-struct.rs b/src/test/ui/resolve/suggest-path-for-tuple-struct.rs new file mode 100644 index 0000000000..c8bc3e79fe --- /dev/null +++ b/src/test/ui/resolve/suggest-path-for-tuple-struct.rs @@ -0,0 +1,26 @@ +mod module { + pub struct SomeTupleStruct(u8); + pub struct SomeRegularStruct { + foo: u8 + } + + impl SomeTupleStruct { + pub fn new() -> Self { + Self(0) + } + } + impl SomeRegularStruct { + pub fn new() -> Self { + Self { foo: 0 } + } + } +} + +use module::{SomeTupleStruct, SomeRegularStruct}; + +fn main() { + let _ = SomeTupleStruct.new(); + //~^ ERROR expected value, found struct `SomeTupleStruct` + let _ = SomeRegularStruct.new(); + //~^ ERROR expected value, found struct `SomeRegularStruct` +} diff --git a/src/test/ui/resolve/suggest-path-for-tuple-struct.stderr b/src/test/ui/resolve/suggest-path-for-tuple-struct.stderr new file mode 100644 index 0000000000..957045ca74 --- /dev/null +++ b/src/test/ui/resolve/suggest-path-for-tuple-struct.stderr @@ -0,0 +1,19 @@ +error[E0423]: expected value, found struct `SomeTupleStruct` + --> $DIR/suggest-path-for-tuple-struct.rs:22:13 + | +LL | let _ = SomeTupleStruct.new(); + | ^^^^^^^^^^^^^^^---- + | | + | help: use the path separator to refer to an item: `SomeTupleStruct::new` + +error[E0423]: expected value, found struct `SomeRegularStruct` + --> $DIR/suggest-path-for-tuple-struct.rs:24:13 + | +LL | let _ = SomeRegularStruct.new(); + | ^^^^^^^^^^^^^^^^^---- + | | + | help: use the path separator to refer to an item: `SomeRegularStruct::new` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0423`. diff --git a/src/test/ui/use-self-in-inner-fn.rs b/src/test/ui/resolve/use-self-in-inner-fn.rs similarity index 100% rename from src/test/ui/use-self-in-inner-fn.rs rename to src/test/ui/resolve/use-self-in-inner-fn.rs diff --git a/src/test/ui/use-self-in-inner-fn.stderr b/src/test/ui/resolve/use-self-in-inner-fn.stderr similarity index 100% rename from src/test/ui/use-self-in-inner-fn.stderr rename to src/test/ui/resolve/use-self-in-inner-fn.stderr diff --git a/src/test/ui/rfc-1717-dllimport/missing-link-attr.stderr b/src/test/ui/rfc-1717-dllimport/missing-link-attr.stderr index d836741f9e..d4410e1475 100644 --- a/src/test/ui/rfc-1717-dllimport/missing-link-attr.stderr +++ b/src/test/ui/rfc-1717-dllimport/missing-link-attr.stderr @@ -1,4 +1,4 @@ -error: renaming of the library `foo` was specified, however this crate contains no `#[link(...)]` attributes referencing this library. +error: renaming of the library `foo` was specified, however this crate contains no `#[link(...)]` attributes referencing this library error: aborting due to previous error diff --git a/src/test/ui/rfc-1717-dllimport/multiple-renames.stderr b/src/test/ui/rfc-1717-dllimport/multiple-renames.stderr index 4e5a3647fa..a6fec9c4e2 100644 --- a/src/test/ui/rfc-1717-dllimport/multiple-renames.stderr +++ b/src/test/ui/rfc-1717-dllimport/multiple-renames.stderr @@ -1,4 +1,4 @@ -error: multiple renamings were specified for library `foo` . +error: multiple renamings were specified for library `foo` error: aborting due to previous error diff --git a/src/test/ui/rfc-2005-default-binding-mode/borrowck-issue-49631.nll.stderr b/src/test/ui/rfc-2005-default-binding-mode/borrowck-issue-49631.nll.stderr deleted file mode 100644 index c74b82dbbd..0000000000 --- a/src/test/ui/rfc-2005-default-binding-mode/borrowck-issue-49631.nll.stderr +++ /dev/null @@ -1,14 +0,0 @@ -error[E0502]: cannot borrow `foo` as mutable because it is also borrowed as immutable - --> $DIR/borrowck-issue-49631.rs:20:9 - | -LL | while let Some(Ok(string)) = foo.get() { - | --- immutable borrow occurs here -LL | foo.mutate(); - | ^^^ mutable borrow occurs here -LL | -LL | println!("foo={:?}", *string); - | ------- immutable borrow later used here - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0502`. diff --git a/src/test/ui/rfc-2005-default-binding-mode/borrowck-issue-49631.stderr b/src/test/ui/rfc-2005-default-binding-mode/borrowck-issue-49631.stderr index 04572920ee..b7c0b0bb6b 100644 --- a/src/test/ui/rfc-2005-default-binding-mode/borrowck-issue-49631.stderr +++ b/src/test/ui/rfc-2005-default-binding-mode/borrowck-issue-49631.stderr @@ -2,7 +2,7 @@ error[E0502]: cannot borrow `foo` as mutable because it is also borrowed as immu --> $DIR/borrowck-issue-49631.rs:20:9 | LL | while let Some(Ok(string)) = foo.get() { - | --- immutable borrow occurs here + | --------- immutable borrow occurs here LL | foo.mutate(); | ^^^^^^^^^^^^ mutable borrow occurs here LL | diff --git a/src/test/ui/rfc-2008-non-exhaustive/auxiliary/enums.rs b/src/test/ui/rfc-2008-non-exhaustive/auxiliary/enums.rs index 8516bafef9..0098f087d1 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/auxiliary/enums.rs +++ b/src/test/ui/rfc-2008-non-exhaustive/auxiliary/enums.rs @@ -4,8 +4,29 @@ pub enum NonExhaustiveEnum { Unit, Tuple(u32), - Struct { field: u32 } + Struct { field: u32 }, +} + +#[non_exhaustive] +pub enum NestedNonExhaustive { + A(NonExhaustiveEnum), + B, + C, } #[non_exhaustive] pub enum EmptyNonExhaustiveEnum {} + +pub enum VariantNonExhaustive { + #[non_exhaustive] + Bar { + x: u32, + y: u64, + }, + Baz(u32, u16), +} + +#[non_exhaustive] +pub enum NonExhaustiveSingleVariant { + A(bool), +} diff --git a/src/test/ui/rfc-2008-non-exhaustive/auxiliary/structs.rs b/src/test/ui/rfc-2008-non-exhaustive/auxiliary/structs.rs index 6bfe7bf923..78db6b170b 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/auxiliary/structs.rs +++ b/src/test/ui/rfc-2008-non-exhaustive/auxiliary/structs.rs @@ -1,3 +1,4 @@ +#[derive(Default)] #[non_exhaustive] pub struct NormalStruct { pub first_field: u16, @@ -15,7 +16,7 @@ pub struct TupleStruct(pub u16, pub u16); pub struct FunctionalRecord { pub first_field: u16, pub second_field: u16, - pub third_field: bool + pub third_field: bool, } impl Default for FunctionalRecord { @@ -23,3 +24,18 @@ impl Default for FunctionalRecord { FunctionalRecord { first_field: 640, second_field: 480, third_field: false } } } + +#[derive(Default)] +#[non_exhaustive] +pub struct NestedStruct { + pub foo: u16, + pub bar: NormalStruct, +} + +#[derive(Default)] +#[non_exhaustive] +pub struct MixedVisFields { + pub a: u16, + pub b: bool, + pub(crate) foo: bool, +} diff --git a/src/test/ui/rfc-2008-non-exhaustive/auxiliary/unstable.rs b/src/test/ui/rfc-2008-non-exhaustive/auxiliary/unstable.rs new file mode 100644 index 0000000000..de9d6f6594 --- /dev/null +++ b/src/test/ui/rfc-2008-non-exhaustive/auxiliary/unstable.rs @@ -0,0 +1,29 @@ +#![feature(staged_api)] +#![stable(feature = "stable_test_feature", since = "1.0.0")] + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +#[non_exhaustive] +pub enum UnstableEnum { + #[stable(feature = "stable_test_feature", since = "1.0.0")] + Stable, + #[stable(feature = "stable_test_feature", since = "1.0.0")] + Stable2, + #[unstable(feature = "unstable_test_feature", issue = "none")] + Unstable, +} + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +#[non_exhaustive] +pub enum OnlyUnstableEnum { + #[unstable(feature = "unstable_test_feature", issue = "none")] + Unstable, + #[unstable(feature = "unstable_test_feature", issue = "none")] + Unstable2, +} + +impl OnlyUnstableEnum { + #[stable(feature = "stable_test_feature", since = "1.0.0")] + pub fn new() -> Self { + Self::Unstable + } +} diff --git a/src/test/ui/rfc-2008-non-exhaustive/omitted-patterns.rs b/src/test/ui/rfc-2008-non-exhaustive/omitted-patterns.rs new file mode 100644 index 0000000000..fe9734fdc0 --- /dev/null +++ b/src/test/ui/rfc-2008-non-exhaustive/omitted-patterns.rs @@ -0,0 +1,170 @@ +// Test that the `non_exhaustive_omitted_patterns` lint is triggered correctly. + +#![feature(non_exhaustive_omitted_patterns_lint, unstable_test_feature)] + +// aux-build:enums.rs +extern crate enums; +// aux-build:unstable.rs +extern crate unstable; +// aux-build:structs.rs +extern crate structs; + +use enums::{ + EmptyNonExhaustiveEnum, NestedNonExhaustive, NonExhaustiveEnum, NonExhaustiveSingleVariant, + VariantNonExhaustive, +}; +use unstable::{UnstableEnum, OnlyUnstableEnum}; +use structs::{FunctionalRecord, MixedVisFields, NestedStruct, NormalStruct}; + +#[non_exhaustive] +#[derive(Default)] +pub struct Foo { + a: u8, + b: usize, + c: String, +} + +#[non_exhaustive] +pub enum Bar { + A, + B, + C, +} + +fn main() { + let enumeration = Bar::A; + + // Ok: this is a crate local non_exhaustive enum + match enumeration { + Bar::A => {} + Bar::B => {} + #[deny(non_exhaustive_omitted_patterns)] + _ => {} + } + + let non_enum = NonExhaustiveEnum::Unit; + + // Ok: without the attribute + match non_enum { + NonExhaustiveEnum::Unit => {} + NonExhaustiveEnum::Tuple(_) => {} + _ => {} + } + + match non_enum { + NonExhaustiveEnum::Unit => {} + NonExhaustiveEnum::Tuple(_) => {} + #[deny(non_exhaustive_omitted_patterns)] + _ => {} + } + //~^^ some variants are not matched explicitly + + match non_enum { + NonExhaustiveEnum::Unit | NonExhaustiveEnum::Struct { .. } => {} + #[deny(non_exhaustive_omitted_patterns)] + _ => {} + } + //~^^ some variants are not matched explicitly + + let x = 5; + match non_enum { + NonExhaustiveEnum::Unit if x > 10 => {} + NonExhaustiveEnum::Tuple(_) => {} + NonExhaustiveEnum::Struct { .. } => {} + #[deny(non_exhaustive_omitted_patterns)] + _ => {} + } + //~^^ some variants are not matched explicitly + + // Ok: all covered and not `unreachable-patterns` + #[deny(unreachable_patterns)] + match non_enum { + NonExhaustiveEnum::Unit => {} + NonExhaustiveEnum::Tuple(_) => {} + NonExhaustiveEnum::Struct { .. } => {} + #[deny(non_exhaustive_omitted_patterns)] + _ => {} + } + + #[deny(non_exhaustive_omitted_patterns)] + match NestedNonExhaustive::B { + NestedNonExhaustive::A(NonExhaustiveEnum::Unit) => {} + NestedNonExhaustive::A(_) => {} + NestedNonExhaustive::B => {} + _ => {} + } + //~^^ some variants are not matched explicitly + //~^^^^^ some variants are not matched explicitly + + #[warn(non_exhaustive_omitted_patterns)] + match VariantNonExhaustive::Baz(1, 2) { + VariantNonExhaustive::Baz(_, _) => {} + VariantNonExhaustive::Bar { x, .. } => {} + } + //~^^ some fields are not explicitly listed + + #[warn(non_exhaustive_omitted_patterns)] + let FunctionalRecord { first_field, second_field, .. } = FunctionalRecord::default(); + //~^ some fields are not explicitly listed + + // Ok: this is local + #[warn(non_exhaustive_omitted_patterns)] + let Foo { a, b, .. } = Foo::default(); + + #[warn(non_exhaustive_omitted_patterns)] + let NestedStruct { bar: NormalStruct { first_field, .. }, .. } = NestedStruct::default(); + //~^ some fields are not explicitly listed + //~^^ some fields are not explicitly listed + + // Ok: this tests https://github.com/rust-lang/rust/issues/89382 + #[warn(non_exhaustive_omitted_patterns)] + let MixedVisFields { a, b, .. } = MixedVisFields::default(); + + // Ok: because this only has 1 variant + #[deny(non_exhaustive_omitted_patterns)] + match NonExhaustiveSingleVariant::A(true) { + NonExhaustiveSingleVariant::A(true) => {} + _ => {} + } + + #[deny(non_exhaustive_omitted_patterns)] + match NonExhaustiveSingleVariant::A(true) { + _ => {} + } + //~^^ some variants are not matched explicitly + + // Ok: we don't lint on `if let` expressions + #[deny(non_exhaustive_omitted_patterns)] + if let NonExhaustiveEnum::Tuple(_) = non_enum {} + + match UnstableEnum::Stable { + UnstableEnum::Stable => {} + UnstableEnum::Stable2 => {} + #[deny(non_exhaustive_omitted_patterns)] + _ => {} + } + //~^^ some variants are not matched explicitly + + #[deny(non_exhaustive_omitted_patterns)] + match UnstableEnum::Stable { + UnstableEnum::Stable => {} + UnstableEnum::Stable2 => {} + UnstableEnum::Unstable => {} + _ => {} + } + + // Ok: the feature is on and both variants are matched + #[deny(non_exhaustive_omitted_patterns)] + match OnlyUnstableEnum::Unstable { + OnlyUnstableEnum::Unstable => {} + OnlyUnstableEnum::Unstable2 => {} + _ => {} + } + + #[deny(non_exhaustive_omitted_patterns)] + match OnlyUnstableEnum::Unstable { + OnlyUnstableEnum::Unstable => {} + _ => {} + } + //~^^ some variants are not matched explicitly +} diff --git a/src/test/ui/rfc-2008-non-exhaustive/omitted-patterns.stderr b/src/test/ui/rfc-2008-non-exhaustive/omitted-patterns.stderr new file mode 100644 index 0000000000..30f3f88ad9 --- /dev/null +++ b/src/test/ui/rfc-2008-non-exhaustive/omitted-patterns.stderr @@ -0,0 +1,160 @@ +warning: some fields are not explicitly listed + --> $DIR/omitted-patterns.rs:102:9 + | +LL | VariantNonExhaustive::Bar { x, .. } => {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ field `y` not listed + | +note: the lint level is defined here + --> $DIR/omitted-patterns.rs:99:12 + | +LL | #[warn(non_exhaustive_omitted_patterns)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = help: ensure that all fields are mentioned explicitly by adding the suggested fields + = note: the pattern is of type `VariantNonExhaustive` and the `non_exhaustive_omitted_patterns` attribute was found + +warning: some fields are not explicitly listed + --> $DIR/omitted-patterns.rs:107:9 + | +LL | let FunctionalRecord { first_field, second_field, .. } = FunctionalRecord::default(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ field `third_field` not listed + | +note: the lint level is defined here + --> $DIR/omitted-patterns.rs:106:12 + | +LL | #[warn(non_exhaustive_omitted_patterns)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = help: ensure that all fields are mentioned explicitly by adding the suggested fields + = note: the pattern is of type `FunctionalRecord` and the `non_exhaustive_omitted_patterns` attribute was found + +warning: some fields are not explicitly listed + --> $DIR/omitted-patterns.rs:115:29 + | +LL | let NestedStruct { bar: NormalStruct { first_field, .. }, .. } = NestedStruct::default(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ field `second_field` not listed + | +note: the lint level is defined here + --> $DIR/omitted-patterns.rs:114:12 + | +LL | #[warn(non_exhaustive_omitted_patterns)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = help: ensure that all fields are mentioned explicitly by adding the suggested fields + = note: the pattern is of type `NormalStruct` and the `non_exhaustive_omitted_patterns` attribute was found + +warning: some fields are not explicitly listed + --> $DIR/omitted-patterns.rs:115:9 + | +LL | let NestedStruct { bar: NormalStruct { first_field, .. }, .. } = NestedStruct::default(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ field `foo` not listed + | + = help: ensure that all fields are mentioned explicitly by adding the suggested fields + = note: the pattern is of type `NestedStruct` and the `non_exhaustive_omitted_patterns` attribute was found + +error: some variants are not matched explicitly + --> $DIR/omitted-patterns.rs:58:9 + | +LL | _ => {} + | ^ pattern `Struct { .. }` not covered + | +note: the lint level is defined here + --> $DIR/omitted-patterns.rs:57:16 + | +LL | #[deny(non_exhaustive_omitted_patterns)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = help: ensure that all variants are matched explicitly by adding the suggested match arms + = note: the matched value is of type `NonExhaustiveEnum` and the `non_exhaustive_omitted_patterns` attribute was found + +error: some variants are not matched explicitly + --> $DIR/omitted-patterns.rs:65:9 + | +LL | _ => {} + | ^ pattern `Tuple(_)` not covered + | +note: the lint level is defined here + --> $DIR/omitted-patterns.rs:64:16 + | +LL | #[deny(non_exhaustive_omitted_patterns)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = help: ensure that all variants are matched explicitly by adding the suggested match arms + = note: the matched value is of type `NonExhaustiveEnum` and the `non_exhaustive_omitted_patterns` attribute was found + +error: some variants are not matched explicitly + --> $DIR/omitted-patterns.rs:75:9 + | +LL | _ => {} + | ^ pattern `Unit` not covered + | +note: the lint level is defined here + --> $DIR/omitted-patterns.rs:74:16 + | +LL | #[deny(non_exhaustive_omitted_patterns)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = help: ensure that all variants are matched explicitly by adding the suggested match arms + = note: the matched value is of type `NonExhaustiveEnum` and the `non_exhaustive_omitted_patterns` attribute was found + +error: some variants are not matched explicitly + --> $DIR/omitted-patterns.rs:92:32 + | +LL | NestedNonExhaustive::A(_) => {} + | ^ patterns `Tuple(_)` and `Struct { .. }` not covered + | +note: the lint level is defined here + --> $DIR/omitted-patterns.rs:89:12 + | +LL | #[deny(non_exhaustive_omitted_patterns)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = help: ensure that all variants are matched explicitly by adding the suggested match arms + = note: the matched value is of type `NonExhaustiveEnum` and the `non_exhaustive_omitted_patterns` attribute was found + +error: some variants are not matched explicitly + --> $DIR/omitted-patterns.rs:94:9 + | +LL | _ => {} + | ^ pattern `C` not covered + | + = help: ensure that all variants are matched explicitly by adding the suggested match arms + = note: the matched value is of type `NestedNonExhaustive` and the `non_exhaustive_omitted_patterns` attribute was found + +error: some variants are not matched explicitly + --> $DIR/omitted-patterns.rs:132:9 + | +LL | _ => {} + | ^ pattern `A(_)` not covered + | +note: the lint level is defined here + --> $DIR/omitted-patterns.rs:130:12 + | +LL | #[deny(non_exhaustive_omitted_patterns)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = help: ensure that all variants are matched explicitly by adding the suggested match arms + = note: the matched value is of type `NonExhaustiveSingleVariant` and the `non_exhaustive_omitted_patterns` attribute was found + +error: some variants are not matched explicitly + --> $DIR/omitted-patterns.rs:144:9 + | +LL | _ => {} + | ^ pattern `Unstable` not covered + | +note: the lint level is defined here + --> $DIR/omitted-patterns.rs:143:16 + | +LL | #[deny(non_exhaustive_omitted_patterns)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = help: ensure that all variants are matched explicitly by adding the suggested match arms + = note: the matched value is of type `UnstableEnum` and the `non_exhaustive_omitted_patterns` attribute was found + +error: some variants are not matched explicitly + --> $DIR/omitted-patterns.rs:167:9 + | +LL | _ => {} + | ^ pattern `Unstable2` not covered + | +note: the lint level is defined here + --> $DIR/omitted-patterns.rs:164:12 + | +LL | #[deny(non_exhaustive_omitted_patterns)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = help: ensure that all variants are matched explicitly by adding the suggested match arms + = note: the matched value is of type `OnlyUnstableEnum` and the `non_exhaustive_omitted_patterns` attribute was found + +error: aborting due to 8 previous errors; 4 warnings emitted + diff --git a/src/test/ui/rfc-2008-non-exhaustive/stable-omitted-patterns.rs b/src/test/ui/rfc-2008-non-exhaustive/stable-omitted-patterns.rs new file mode 100644 index 0000000000..9621d28f8e --- /dev/null +++ b/src/test/ui/rfc-2008-non-exhaustive/stable-omitted-patterns.rs @@ -0,0 +1,33 @@ +// Test that the `non_exhaustive_omitted_patterns` lint is triggered correctly with variants +// marked stable and unstable. + +#![feature(non_exhaustive_omitted_patterns_lint)] + +// aux-build:unstable.rs +extern crate unstable; + +use unstable::{UnstableEnum, OnlyUnstableEnum}; + +fn main() { + // OK: this matches all the stable variants + match UnstableEnum::Stable { + UnstableEnum::Stable => {} + UnstableEnum::Stable2 => {} + #[deny(non_exhaustive_omitted_patterns)] + _ => {} + } + + match UnstableEnum::Stable { + UnstableEnum::Stable => {} + #[deny(non_exhaustive_omitted_patterns)] + _ => {} + } + //~^^ some variants are not matched explicitly + + // Ok: although this is a bit odd, we don't have anything to report + // since there is no stable variants and the feature is off + #[deny(non_exhaustive_omitted_patterns)] + match OnlyUnstableEnum::new() { + _ => {} + } +} diff --git a/src/test/ui/rfc-2008-non-exhaustive/stable-omitted-patterns.stderr b/src/test/ui/rfc-2008-non-exhaustive/stable-omitted-patterns.stderr new file mode 100644 index 0000000000..b9a281974f --- /dev/null +++ b/src/test/ui/rfc-2008-non-exhaustive/stable-omitted-patterns.stderr @@ -0,0 +1,16 @@ +error: some variants are not matched explicitly + --> $DIR/stable-omitted-patterns.rs:23:9 + | +LL | _ => {} + | ^ pattern `Stable2` not covered + | +note: the lint level is defined here + --> $DIR/stable-omitted-patterns.rs:22:16 + | +LL | #[deny(non_exhaustive_omitted_patterns)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = help: ensure that all variants are matched explicitly by adding the suggested match arms + = note: the matched value is of type `UnstableEnum` and the `non_exhaustive_omitted_patterns` attribute was found + +error: aborting due to previous error + diff --git a/src/test/ui/rfc-2008-non-exhaustive/struct.stderr b/src/test/ui/rfc-2008-non-exhaustive/struct.stderr index b0c319f2c7..272b2ef6ee 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/struct.stderr +++ b/src/test/ui/rfc-2008-non-exhaustive/struct.stderr @@ -16,13 +16,13 @@ error[E0603]: tuple struct constructor `TupleStruct` is private LL | let ts_explicit = structs::TupleStruct(640, 480); | ^^^^^^^^^^^ private tuple struct constructor | - ::: $DIR/auxiliary/structs.rs:11:24 + ::: $DIR/auxiliary/structs.rs:12:24 | LL | pub struct TupleStruct(pub u16, pub u16); | ---------------- a constructor is private if any of the fields is private | note: the tuple struct constructor `TupleStruct` is defined here - --> $DIR/auxiliary/structs.rs:11:1 + --> $DIR/auxiliary/structs.rs:12:1 | LL | pub struct TupleStruct(pub u16, pub u16); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -34,7 +34,7 @@ LL | let us_explicit = structs::UnitStruct; | ^^^^^^^^^^ private unit struct | note: the unit struct `UnitStruct` is defined here - --> $DIR/auxiliary/structs.rs:8:1 + --> $DIR/auxiliary/structs.rs:9:1 | LL | pub struct UnitStruct; | ^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/rfc-2091-track-caller/tracked-closure.rs b/src/test/ui/rfc-2091-track-caller/tracked-closure.rs new file mode 100644 index 0000000000..670c423a7e --- /dev/null +++ b/src/test/ui/rfc-2091-track-caller/tracked-closure.rs @@ -0,0 +1,154 @@ +// run-pass + +#![feature(stmt_expr_attributes)] +#![feature(closure_track_caller)] +#![feature(generator_trait)] +#![feature(generators)] + +use std::ops::{Generator, GeneratorState}; +use std::pin::Pin; +use std::panic::Location; + +type Loc = &'static Location<'static>; + +#[track_caller] +fn mono_invoke_fn (&'static str, bool, Loc)>( + val: &F +) -> (&'static str, bool, Loc) { + val("from_mono", false) +} + +#[track_caller] +fn mono_invoke_fn_once (&'static str, bool, Loc)>( + val: F +) -> (&'static str, bool, Loc) { + val("from_mono", false) +} + +#[track_caller] +fn dyn_invoke_fn_mut( + val: &mut dyn FnMut(&'static str, bool) -> (&'static str, bool, Loc) +) -> (&'static str, bool, Loc) { + val("from_dyn", false) +} + +#[track_caller] +fn dyn_invoke_fn_once( + val: Box (&'static str, bool, Loc)> +) -> (&'static str, bool, Loc) { + val("from_dyn", false) +} + + +fn test_closure() { + let mut track_closure = #[track_caller] |first: &'static str, second: bool| { + (first, second, Location::caller()) + }; + let (first_arg, first_bool, first_loc) = track_closure("first_arg", true); + let first_line = line!() - 1; + assert_eq!(first_arg, "first_arg"); + assert_eq!(first_bool, true); + assert_eq!(first_loc.file(), file!()); + assert_eq!(first_loc.line(), first_line); + assert_eq!(first_loc.column(), 46); + + let (dyn_arg, dyn_bool, dyn_loc) = dyn_invoke_fn_mut(&mut track_closure); + assert_eq!(dyn_arg, "from_dyn"); + assert_eq!(dyn_bool, false); + // `FnMut::call_mut` does not have `#[track_caller]`, + // so this will not match + assert_ne!(dyn_loc.file(), file!()); + + let (dyn_arg, dyn_bool, dyn_loc) = dyn_invoke_fn_once(Box::new(track_closure)); + assert_eq!(dyn_arg, "from_dyn"); + assert_eq!(dyn_bool, false); + // `FnOnce::call_once` does not have `#[track_caller]` + // so this will not match + assert_ne!(dyn_loc.file(), file!()); + + + let (mono_arg, mono_bool, mono_loc) = mono_invoke_fn(&track_closure); + let mono_line = line!() - 1; + assert_eq!(mono_arg, "from_mono"); + assert_eq!(mono_bool, false); + assert_eq!(mono_loc.file(), file!()); + assert_eq!(mono_loc.line(), mono_line); + assert_eq!(mono_loc.column(), 43); + + let (mono_arg, mono_bool, mono_loc) = mono_invoke_fn_once(track_closure); + let mono_line = line!() - 1; + assert_eq!(mono_arg, "from_mono"); + assert_eq!(mono_bool, false); + assert_eq!(mono_loc.file(), file!()); + assert_eq!(mono_loc.line(), mono_line); + assert_eq!(mono_loc.column(), 43); + + let non_tracked_caller = || Location::caller(); + let non_tracked_line = line!() - 1; // This is the line of the closure, not its caller + let non_tracked_loc = non_tracked_caller(); + assert_eq!(non_tracked_loc.file(), file!()); + assert_eq!(non_tracked_loc.line(), non_tracked_line); + assert_eq!(non_tracked_loc.column(), 33); +} + + +#[track_caller] +fn mono_generator>( + val: Pin<&mut F> +) -> (&'static str, String, Loc) { + match val.resume("Mono".to_string()) { + GeneratorState::Yielded(val) => val, + _ => unreachable!() + } +} + +#[track_caller] +fn dyn_generator( + val: Pin<&mut dyn Generator> +) -> (&'static str, String, Loc) { + match val.resume("Dyn".to_string()) { + GeneratorState::Yielded(val) => val, + _ => unreachable!() + } +} + +fn test_generator() { + let generator = #[track_caller] |arg: String| { + yield ("first", arg.clone(), Location::caller()); + yield ("second", arg.clone(), Location::caller()); + }; + + let mut pinned = Box::pin(generator); + let (dyn_ret, dyn_arg, dyn_loc) = dyn_generator(pinned.as_mut()); + assert_eq!(dyn_ret, "first"); + assert_eq!(dyn_arg, "Dyn".to_string()); + // The `Generator` trait does not have `#[track_caller]` on `resume`, so + // this will not match. + assert_ne!(dyn_loc.file(), file!()); + + + let (mono_ret, mono_arg, mono_loc) = mono_generator(pinned.as_mut()); + let mono_line = line!() - 1; + assert_eq!(mono_ret, "second"); + // The generator ignores the argument to the second `resume` call + assert_eq!(mono_arg, "Dyn".to_string()); + assert_eq!(mono_loc.file(), file!()); + assert_eq!(mono_loc.line(), mono_line); + assert_eq!(mono_loc.column(), 42); + + let non_tracked_generator = || { yield Location::caller(); }; + let non_tracked_line = line!() - 1; // This is the line of the generator, not its caller + let non_tracked_loc = match Box::pin(non_tracked_generator).as_mut().resume(()) { + GeneratorState::Yielded(val) => val, + _ => unreachable!() + }; + assert_eq!(non_tracked_loc.file(), file!()); + assert_eq!(non_tracked_loc.line(), non_tracked_line); + assert_eq!(non_tracked_loc.column(), 44); + +} + +fn main() { + test_closure(); + test_generator(); +} diff --git a/src/test/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-region-rev.stderr b/src/test/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-region-rev.stderr index 09b51fe056..5dff4c8fff 100644 --- a/src/test/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-region-rev.stderr +++ b/src/test/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-region-rev.stderr @@ -4,12 +4,12 @@ error[E0491]: in type `&'a Foo<'b>`, reference has a longer lifetime than the da LL | type Out = &'a Foo<'b>; | ^^^^^^^^^^^ | -note: the pointer is valid for the lifetime `'a` as defined on the impl at 16:10 +note: the pointer is valid for the lifetime `'a` as defined here --> $DIR/regions-outlives-nominal-type-region-rev.rs:16:10 | LL | impl<'a, 'b> Trait<'a, 'b> for usize { | ^^ -note: but the referenced data is only valid for the lifetime `'b` as defined on the impl at 16:14 +note: but the referenced data is only valid for the lifetime `'b` as defined here --> $DIR/regions-outlives-nominal-type-region-rev.rs:16:14 | LL | impl<'a, 'b> Trait<'a, 'b> for usize { diff --git a/src/test/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-region.stderr b/src/test/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-region.stderr index 957a9d6dd3..975776cddf 100644 --- a/src/test/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-region.stderr +++ b/src/test/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-region.stderr @@ -4,12 +4,12 @@ error[E0491]: in type `&'a Foo<'b>`, reference has a longer lifetime than the da LL | type Out = &'a Foo<'b>; | ^^^^^^^^^^^ | -note: the pointer is valid for the lifetime `'a` as defined on the impl at 16:10 +note: the pointer is valid for the lifetime `'a` as defined here --> $DIR/regions-outlives-nominal-type-region.rs:16:10 | LL | impl<'a, 'b> Trait<'a, 'b> for usize { | ^^ -note: but the referenced data is only valid for the lifetime `'b` as defined on the impl at 16:14 +note: but the referenced data is only valid for the lifetime `'b` as defined here --> $DIR/regions-outlives-nominal-type-region.rs:16:14 | LL | impl<'a, 'b> Trait<'a, 'b> for usize { diff --git a/src/test/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-type-rev.stderr b/src/test/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-type-rev.stderr index 1589f93d90..be05ecec0c 100644 --- a/src/test/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-type-rev.stderr +++ b/src/test/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-type-rev.stderr @@ -4,12 +4,12 @@ error[E0491]: in type `&'a Foo<&'b i32>`, reference has a longer lifetime than t LL | type Out = &'a Foo<&'b i32>; | ^^^^^^^^^^^^^^^^ | -note: the pointer is valid for the lifetime `'a` as defined on the impl at 16:10 +note: the pointer is valid for the lifetime `'a` as defined here --> $DIR/regions-outlives-nominal-type-type-rev.rs:16:10 | LL | impl<'a, 'b> Trait<'a, 'b> for usize { | ^^ -note: but the referenced data is only valid for the lifetime `'b` as defined on the impl at 16:14 +note: but the referenced data is only valid for the lifetime `'b` as defined here --> $DIR/regions-outlives-nominal-type-type-rev.rs:16:14 | LL | impl<'a, 'b> Trait<'a, 'b> for usize { diff --git a/src/test/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-type.stderr b/src/test/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-type.stderr index 4bfaa1aac7..4ba1778d64 100644 --- a/src/test/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-type.stderr +++ b/src/test/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-type.stderr @@ -4,12 +4,12 @@ error[E0491]: in type `&'a Foo<&'b i32>`, reference has a longer lifetime than t LL | type Out = &'a Foo<&'b i32>; | ^^^^^^^^^^^^^^^^ | -note: the pointer is valid for the lifetime `'a` as defined on the impl at 16:10 +note: the pointer is valid for the lifetime `'a` as defined here --> $DIR/regions-outlives-nominal-type-type.rs:16:10 | LL | impl<'a, 'b> Trait<'a, 'b> for usize { | ^^ -note: but the referenced data is only valid for the lifetime `'b` as defined on the impl at 16:14 +note: but the referenced data is only valid for the lifetime `'b` as defined here --> $DIR/regions-outlives-nominal-type-type.rs:16:14 | LL | impl<'a, 'b> Trait<'a, 'b> for usize { diff --git a/src/test/ui/rfc-2093-infer-outlives/regions-struct-not-wf.stderr b/src/test/ui/rfc-2093-infer-outlives/regions-struct-not-wf.stderr index 1b1a2f7b04..f886126299 100644 --- a/src/test/ui/rfc-2093-infer-outlives/regions-struct-not-wf.stderr +++ b/src/test/ui/rfc-2093-infer-outlives/regions-struct-not-wf.stderr @@ -26,12 +26,12 @@ error[E0491]: in type `&'a &'b T`, reference has a longer lifetime than the data LL | type Out = &'a &'b T; | ^^^^^^^^^ | -note: the pointer is valid for the lifetime `'a` as defined on the impl at 24:6 +note: the pointer is valid for the lifetime `'a` as defined here --> $DIR/regions-struct-not-wf.rs:24:6 | LL | impl<'a, 'b, T> Trait1<'a, 'b, T> for u32 { | ^^ -note: but the referenced data is only valid for the lifetime `'b` as defined on the impl at 24:10 +note: but the referenced data is only valid for the lifetime `'b` as defined here --> $DIR/regions-struct-not-wf.rs:24:10 | LL | impl<'a, 'b, T> Trait1<'a, 'b, T> for u32 { diff --git a/src/test/ui/rfc-2457/extern_block_nonascii_forbidden.stderr b/src/test/ui/rfc-2457/extern_block_nonascii_forbidden.stderr index ab8832e916..ca1b8a6e7b 100644 --- a/src/test/ui/rfc-2457/extern_block_nonascii_forbidden.stderr +++ b/src/test/ui/rfc-2457/extern_block_nonascii_forbidden.stderr @@ -6,7 +6,7 @@ LL | extern "C" { LL | type 一; | ^^ | - = note: This limitation may be lifted in the future; see issue #83942 for more information + = note: this limitation may be lifted in the future; see issue #83942 for more information error: items in `extern` blocks cannot use non-ascii identifiers --> $DIR/extern_block_nonascii_forbidden.rs:5:8 @@ -17,7 +17,7 @@ LL | type 一; LL | fn 二(); | ^^ | - = note: This limitation may be lifted in the future; see issue #83942 for more information + = note: this limitation may be lifted in the future; see issue #83942 for more information error: items in `extern` blocks cannot use non-ascii identifiers --> $DIR/extern_block_nonascii_forbidden.rs:6:12 @@ -28,7 +28,7 @@ LL | extern "C" { LL | static 三: usize; | ^^ | - = note: This limitation may be lifted in the future; see issue #83942 for more information + = note: this limitation may be lifted in the future; see issue #83942 for more information error: aborting due to 3 previous errors diff --git a/src/test/ui/rfc-2565-param-attrs/param-attrs-2018.stderr b/src/test/ui/rfc-2565-param-attrs/param-attrs-2018.stderr index 4514fd96c2..593821bf96 100644 --- a/src/test/ui/rfc-2565-param-attrs/param-attrs-2018.stderr +++ b/src/test/ui/rfc-2565-param-attrs/param-attrs-2018.stderr @@ -8,15 +8,15 @@ LL | trait Trait2015 { fn foo(#[allow(C)] i32); } help: if this is a `self` type, give it a parameter name | LL | trait Trait2015 { fn foo(#[allow(C)] self: i32); } - | ~~~~~~~~~ + | +++++ help: if this is a parameter name, give it a type | LL | trait Trait2015 { fn foo(#[allow(C)] i32: TypeName); } - | ~~~~~~~~~~~~~ + | ++++++++++ help: if this is a type, explicitly ignore the parameter name | LL | trait Trait2015 { fn foo(#[allow(C)] _: i32); } - | ~~~~~~ + | ++ error: aborting due to previous error diff --git a/src/test/ui/rfc-2627-raw-dylib/link-ordinal-missing-argument.rs b/src/test/ui/rfc-2627-raw-dylib/link-ordinal-missing-argument.rs new file mode 100644 index 0000000000..c391ccd1c8 --- /dev/null +++ b/src/test/ui/rfc-2627-raw-dylib/link-ordinal-missing-argument.rs @@ -0,0 +1,11 @@ +#![feature(raw_dylib)] +//~^ WARN the feature `raw_dylib` is incomplete + +#[link(name = "foo")] +extern "C" { + #[link_ordinal()] + //~^ ERROR incorrect number of arguments to `#[link_ordinal]` + fn foo(); +} + +fn main() {} diff --git a/src/test/ui/rfc-2627-raw-dylib/link-ordinal-missing-argument.stderr b/src/test/ui/rfc-2627-raw-dylib/link-ordinal-missing-argument.stderr new file mode 100644 index 0000000000..8e9edfb9d2 --- /dev/null +++ b/src/test/ui/rfc-2627-raw-dylib/link-ordinal-missing-argument.stderr @@ -0,0 +1,19 @@ +warning: the feature `raw_dylib` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/link-ordinal-missing-argument.rs:1:12 + | +LL | #![feature(raw_dylib)] + | ^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #58713 for more information + +error: incorrect number of arguments to `#[link_ordinal]` + --> $DIR/link-ordinal-missing-argument.rs:6:5 + | +LL | #[link_ordinal()] + | ^^^^^^^^^^^^^^^^^ + | + = note: the attribute requires exactly one argument + +error: aborting due to previous error; 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 new file mode 100644 index 0000000000..9874121267 --- /dev/null +++ b/src/test/ui/rfc-2627-raw-dylib/link-ordinal-multiple.rs @@ -0,0 +1,13 @@ +// only-windows-msvc +#![feature(raw_dylib)] +//~^ WARN the feature `raw_dylib` is incomplete + +#[link(name = "foo", kind = "raw-dylib")] +extern "C" { + #[link_ordinal(1)] + #[link_ordinal(2)] + //~^ ERROR multiple `link_ordinal` attributes on a single definition + fn foo(); +} + +fn main() {} 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 new file mode 100644 index 0000000000..a79fb2de94 --- /dev/null +++ b/src/test/ui/rfc-2627-raw-dylib/link-ordinal-multiple.stderr @@ -0,0 +1,17 @@ +warning: the feature `raw_dylib` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/link-ordinal-multiple.rs:2:12 + | +LL | #![feature(raw_dylib)] + | ^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #58713 for more information + +error: multiple `link_ordinal` attributes on a single definition + --> $DIR/link-ordinal-multiple.rs:8:5 + | +LL | #[link_ordinal(2)] + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error; 1 warning emitted + diff --git a/src/test/ui/rfc-2627-raw-dylib/link-ordinal-too-large.rs b/src/test/ui/rfc-2627-raw-dylib/link-ordinal-too-large.rs index 10db497297..b6089d27e7 100644 --- a/src/test/ui/rfc-2627-raw-dylib/link-ordinal-too-large.rs +++ b/src/test/ui/rfc-2627-raw-dylib/link-ordinal-too-large.rs @@ -3,8 +3,8 @@ #[link(name = "foo")] extern "C" { - #[link_ordinal(18446744073709551616)] - //~^ ERROR ordinal value in `link_ordinal` is too large: `18446744073709551616` + #[link_ordinal(72436)] + //~^ ERROR ordinal value in `link_ordinal` is too large: `72436` fn foo(); } diff --git a/src/test/ui/rfc-2627-raw-dylib/link-ordinal-too-large.stderr b/src/test/ui/rfc-2627-raw-dylib/link-ordinal-too-large.stderr index 35f9b53fdf..bbe985fa10 100644 --- a/src/test/ui/rfc-2627-raw-dylib/link-ordinal-too-large.stderr +++ b/src/test/ui/rfc-2627-raw-dylib/link-ordinal-too-large.stderr @@ -7,13 +7,13 @@ LL | #![feature(raw_dylib)] = note: `#[warn(incomplete_features)]` on by default = note: see issue #58713 for more information -error: ordinal value in `link_ordinal` is too large: `18446744073709551616` +error: ordinal value in `link_ordinal` is too large: `72436` --> $DIR/link-ordinal-too-large.rs:6:5 | -LL | #[link_ordinal(18446744073709551616)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #[link_ordinal(72436)] + | ^^^^^^^^^^^^^^^^^^^^^^ | - = note: the value may not exceed `usize::MAX` + = note: the value may not exceed `u16::MAX` error: aborting due to previous error; 1 warning emitted diff --git a/src/test/ui/rfc-2627-raw-dylib/link-ordinal-too-many-arguments.rs b/src/test/ui/rfc-2627-raw-dylib/link-ordinal-too-many-arguments.rs new file mode 100644 index 0000000000..93286c616c --- /dev/null +++ b/src/test/ui/rfc-2627-raw-dylib/link-ordinal-too-many-arguments.rs @@ -0,0 +1,11 @@ +#![feature(raw_dylib)] +//~^ WARN the feature `raw_dylib` is incomplete + +#[link(name = "foo")] +extern "C" { + #[link_ordinal(3, 4)] + //~^ ERROR incorrect number of arguments to `#[link_ordinal]` + fn foo(); +} + +fn main() {} diff --git a/src/test/ui/rfc-2627-raw-dylib/link-ordinal-too-many-arguments.stderr b/src/test/ui/rfc-2627-raw-dylib/link-ordinal-too-many-arguments.stderr new file mode 100644 index 0000000000..484c85a0f4 --- /dev/null +++ b/src/test/ui/rfc-2627-raw-dylib/link-ordinal-too-many-arguments.stderr @@ -0,0 +1,19 @@ +warning: the feature `raw_dylib` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/link-ordinal-too-many-arguments.rs:1:12 + | +LL | #![feature(raw_dylib)] + | ^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #58713 for more information + +error: incorrect number of arguments to `#[link_ordinal]` + --> $DIR/link-ordinal-too-many-arguments.rs:6:5 + | +LL | #[link_ordinal(3, 4)] + | ^^^^^^^^^^^^^^^^^^^^^ + | + = note: the attribute requires exactly one argument + +error: aborting due to previous error; 1 warning emitted + diff --git a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-dup-bound.rs b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-dup-bound.rs index 7185376b44..cc24dbd96d 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-dup-bound.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-dup-bound.rs @@ -16,12 +16,17 @@ impl const PartialEq for S { // This duplicate bound should not result in ambiguities. It should be equivalent to a single ~const // bound. -// const fn equals_self(t: &T) -> bool { -// FIXME(fee1-dead)^ why should the order matter here? -const fn equals_self(t: &T) -> bool { +const fn equals_self(t: &T) -> bool { *t == *t } -pub const EQ: bool = equals_self(&S); +trait A: PartialEq {} +impl A for T {} + +const fn equals_self2(t: &T) -> bool { + *t == *t +} + +pub const EQ: bool = equals_self(&S) && equals_self2(&S); fn main() {} diff --git a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst.stderr b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst.stderr index 9b9bda7c90..0440f17a70 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst.stderr +++ b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst.stderr @@ -2,7 +2,9 @@ error[E0277]: can't compare `S` with `S` --> $DIR/call-generic-method-nonconst.rs:19:34 | LL | pub const EQ: bool = equals_self(&S); - | ^^ no implementation for `S == S` + | ----------- ^^ no implementation for `S == S` + | | + | required by a bound introduced by this call | = help: the trait `PartialEq` is not implemented for `S` note: required by a bound in `equals_self` diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-closures.rs b/src/test/ui/rfc-2632-const-trait-impl/const-closures.rs new file mode 100644 index 0000000000..99e608797f --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/const-closures.rs @@ -0,0 +1,31 @@ +// run-pass + +#![feature(const_trait_impl)] +#![feature(const_fn_trait_bound)] + +const fn answer_p1(f: &F) -> u8 + where + F: ~const FnOnce() -> u8, + F: ~const FnMut() -> u8, + F: ~const Fn() -> u8, +{ + f() * 7 +} + +const fn three() -> u8 { + 3 +} + +const fn answer_p2() -> u8 { + answer_p1(&three) +} + +const fn answer u8>(f: &F) -> u8 { + f() + f() +} + +const ANSWER: u8 = answer(&answer_p2); + +fn main() { + assert_eq!(ANSWER, 42) +} 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 new file mode 100644 index 0000000000..34cd1d2b10 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.precise.stderr @@ -0,0 +1,68 @@ +error: `~const` is not allowed here + --> $DIR/const-drop-fail.rs:27:35 + | +LL | struct ConstDropImplWithBounds(PhantomData); + | ^^^^^^^^ + | + = note: only allowed on bounds on traits' associated types and functions, const fns, const impls and its associated functions + +error[E0277]: the trait bound `NonTrivialDrop: Drop` is not satisfied + --> $DIR/const-drop-fail.rs:45:5 + | +LL | const _: () = check($exp); + | ----- required by a bound introduced by this call +... +LL | NonTrivialDrop, + | ^^^^^^^^^^^^^^ the trait `Drop` is not implemented for `NonTrivialDrop` + | +note: required by a bound in `check` + --> $DIR/const-drop-fail.rs:36:19 + | +LL | const fn check(_: T) {} + | ^^^^^^^^^^^ required by this bound in `check` + +error[E0277]: the trait bound `ConstImplWithDropGlue: Drop` is not satisfied + --> $DIR/const-drop-fail.rs:47:5 + | +LL | const _: () = check($exp); + | ----- required by a bound introduced by this call +... +LL | ConstImplWithDropGlue(NonTrivialDrop), + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Drop` is not implemented for `ConstImplWithDropGlue` + | +note: required by a bound in `check` + --> $DIR/const-drop-fail.rs:36:19 + | +LL | const fn check(_: T) {} + | ^^^^^^^^^^^ required by this bound in `check` + +error[E0277]: the trait bound `NonTrivialDrop: A` is not satisfied + --> $DIR/const-drop-fail.rs:49:5 + | +LL | ConstDropImplWithBounds::(PhantomData), + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `A` is not implemented for `NonTrivialDrop` + | +note: required by `ConstDropImplWithBounds` + --> $DIR/const-drop-fail.rs:27:1 + | +LL | struct ConstDropImplWithBounds(PhantomData); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +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::(PhantomData), + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `A` is not implemented for `NonTrivialDrop` + | +note: required by a bound in `ConstDropImplWithBounds` + --> $DIR/const-drop-fail.rs:27:35 + | +LL | struct ConstDropImplWithBounds(PhantomData); + | ^^^^^^^^ required by this bound in `ConstDropImplWithBounds` + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.rs b/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.rs new file mode 100644 index 0000000000..3d4de088f5 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.rs @@ -0,0 +1,54 @@ +// revisions: stock precise +#![feature(const_trait_impl)] +#![feature(const_mut_refs)] +#![feature(const_fn_trait_bound)] +#![cfg_attr(precise, feature(const_precise_live_drops))] + +use std::marker::PhantomData; + +struct NonTrivialDrop; + +impl Drop for NonTrivialDrop { + fn drop(&mut self) { + println!("Non trivial drop"); + } +} + +struct ConstImplWithDropGlue(NonTrivialDrop); + +impl const Drop for ConstImplWithDropGlue { + fn drop(&mut self) {} +} + +trait A { fn a() { println!("A"); } } + +impl A for NonTrivialDrop {} + +struct ConstDropImplWithBounds(PhantomData); +//~^ ERROR `~const` is not allowed + +impl const Drop for ConstDropImplWithBounds { + fn drop(&mut self) { + T::a(); + } +} + +const fn check(_: T) {} + +macro_rules! check_all { + ($($exp:expr),*$(,)?) => {$( + const _: () = check($exp); + )*}; +} + +check_all! { + NonTrivialDrop, + //~^ ERROR the trait bound + ConstImplWithDropGlue(NonTrivialDrop), + //~^ ERROR the trait bound + ConstDropImplWithBounds::(PhantomData), + //~^ ERROR the trait bound + //~| ERROR the trait bound +} + +fn main() {} 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 new file mode 100644 index 0000000000..34cd1d2b10 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.stock.stderr @@ -0,0 +1,68 @@ +error: `~const` is not allowed here + --> $DIR/const-drop-fail.rs:27:35 + | +LL | struct ConstDropImplWithBounds(PhantomData); + | ^^^^^^^^ + | + = note: only allowed on bounds on traits' associated types and functions, const fns, const impls and its associated functions + +error[E0277]: the trait bound `NonTrivialDrop: Drop` is not satisfied + --> $DIR/const-drop-fail.rs:45:5 + | +LL | const _: () = check($exp); + | ----- required by a bound introduced by this call +... +LL | NonTrivialDrop, + | ^^^^^^^^^^^^^^ the trait `Drop` is not implemented for `NonTrivialDrop` + | +note: required by a bound in `check` + --> $DIR/const-drop-fail.rs:36:19 + | +LL | const fn check(_: T) {} + | ^^^^^^^^^^^ required by this bound in `check` + +error[E0277]: the trait bound `ConstImplWithDropGlue: Drop` is not satisfied + --> $DIR/const-drop-fail.rs:47:5 + | +LL | const _: () = check($exp); + | ----- required by a bound introduced by this call +... +LL | ConstImplWithDropGlue(NonTrivialDrop), + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Drop` is not implemented for `ConstImplWithDropGlue` + | +note: required by a bound in `check` + --> $DIR/const-drop-fail.rs:36:19 + | +LL | const fn check(_: T) {} + | ^^^^^^^^^^^ required by this bound in `check` + +error[E0277]: the trait bound `NonTrivialDrop: A` is not satisfied + --> $DIR/const-drop-fail.rs:49:5 + | +LL | ConstDropImplWithBounds::(PhantomData), + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `A` is not implemented for `NonTrivialDrop` + | +note: required by `ConstDropImplWithBounds` + --> $DIR/const-drop-fail.rs:27:1 + | +LL | struct ConstDropImplWithBounds(PhantomData); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +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::(PhantomData), + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `A` is not implemented for `NonTrivialDrop` + | +note: required by a bound in `ConstDropImplWithBounds` + --> $DIR/const-drop-fail.rs:27:35 + | +LL | struct ConstDropImplWithBounds(PhantomData); + | ^^^^^^^^ required by this bound in `ConstDropImplWithBounds` + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-drop.rs b/src/test/ui/rfc-2632-const-trait-impl/const-drop.rs new file mode 100644 index 0000000000..292017a1de --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/const-drop.rs @@ -0,0 +1,80 @@ +// run-pass +// revisions: stock precise +#![feature(const_trait_impl)] +#![feature(const_fn_trait_bound)] +#![feature(const_mut_refs)] +#![cfg_attr(precise, feature(const_precise_live_drops))] + +struct S<'a>(&'a mut u8); + +impl<'a> const Drop for S<'a> { + fn drop(&mut self) { + *self.0 += 1; + } +} + +const fn a(_: T) {} + +const fn b() -> u8 { + let mut c = 0; + let _ = S(&mut c); + a(S(&mut c)); + c +} + +const C: u8 = b(); + +macro_rules! implements_const_drop { + ($($exp:expr),*$(,)?) => { + $( + const _: () = a($exp); + )* + } +} + +#[allow(dead_code)] +mod t { + pub struct Foo; + pub enum Bar { A } + pub fn foo() {} + pub struct ConstDrop; + + impl const Drop for ConstDrop { + fn drop(&mut self) {} + } + + pub struct HasConstDrop(pub ConstDrop); + pub struct TrivialFields(pub u8, pub i8, pub usize, pub isize); +} + +use t::*; + +implements_const_drop! { + 1u8, + 2, + 3.0, + Foo, + Bar::A, + foo, + ConstDrop, + HasConstDrop(ConstDrop), + TrivialFields(1, 2, 3, 4), + &1, + &1 as *const i32, +} + +fn main() { + struct HasDropGlue(Box); + struct HasDropImpl; + impl Drop for HasDropImpl { + fn drop(&mut self) { + println!("not trivial drop"); + } + } + + // These types should pass because ~const in a non-const context should have no effect. + a(HasDropGlue(Box::new(0))); + a(HasDropImpl); + + assert_eq!(C, 2); +} diff --git a/src/test/ui/rfc-2632-const-trait-impl/impl-with-default-fn.rs b/src/test/ui/rfc-2632-const-trait-impl/impl-with-default-fn-fail.rs similarity index 89% rename from src/test/ui/rfc-2632-const-trait-impl/impl-with-default-fn.rs rename to src/test/ui/rfc-2632-const-trait-impl/impl-with-default-fn-fail.rs index 59de9e9571..8eefb375b8 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/impl-with-default-fn.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/impl-with-default-fn-fail.rs @@ -1,4 +1,5 @@ #![feature(const_trait_impl)] +#![feature(const_fn_trait_bound)] trait Tr { fn req(&self); @@ -18,11 +19,6 @@ impl const Tr for S { fn req(&self) {} } //~^^ ERROR const trait implementations may not use non-const default functions -impl const Tr for u8 { - fn req(&self) {} - fn prov(&self) {} -} - impl const Tr for u16 { fn prov(&self) {} fn default() {} diff --git a/src/test/ui/rfc-2632-const-trait-impl/impl-with-default-fn.stderr b/src/test/ui/rfc-2632-const-trait-impl/impl-with-default-fn-fail.stderr similarity index 84% rename from src/test/ui/rfc-2632-const-trait-impl/impl-with-default-fn.stderr rename to src/test/ui/rfc-2632-const-trait-impl/impl-with-default-fn-fail.stderr index 5301e0ad12..a091679704 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/impl-with-default-fn.stderr +++ b/src/test/ui/rfc-2632-const-trait-impl/impl-with-default-fn-fail.stderr @@ -1,5 +1,5 @@ error: const trait implementations may not use non-const default functions - --> $DIR/impl-with-default-fn.rs:17:1 + --> $DIR/impl-with-default-fn-fail.rs:18:1 | LL | / impl const Tr for S { LL | | fn req(&self) {} @@ -9,7 +9,7 @@ LL | | } = note: `prov` not implemented error: const trait implementations may not use non-const default functions - --> $DIR/impl-with-default-fn.rs:32:1 + --> $DIR/impl-with-default-fn-fail.rs:28:1 | LL | / impl const Tr for u32 { LL | | fn req(&self) {} @@ -20,7 +20,7 @@ LL | | } = note: `prov` not implemented error[E0046]: not all trait items implemented, missing: `req` - --> $DIR/impl-with-default-fn.rs:26:1 + --> $DIR/impl-with-default-fn-fail.rs:22:1 | LL | fn req(&self); | -------------- `req` from trait diff --git a/src/test/ui/rfc-2632-const-trait-impl/impl-with-default-fn-pass.rs b/src/test/ui/rfc-2632-const-trait-impl/impl-with-default-fn-pass.rs new file mode 100644 index 0000000000..ba3fec0882 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/impl-with-default-fn-pass.rs @@ -0,0 +1,34 @@ +// check-pass + +#![feature(const_trait_impl)] +#![feature(const_fn_trait_bound)] + +trait Tr { + fn req(&self); + + fn prov(&self) { + println!("lul"); + self.req(); + } + + #[default_method_body_is_const] + fn default() {} +} + +impl const Tr for u8 { + fn req(&self) {} + fn prov(&self) {} +} + +macro_rules! impl_tr { + ($ty: ty) => { + impl const Tr for $ty { + fn req(&self) {} + fn prov(&self) {} + } + } +} + +impl_tr!(u64); + +fn main() {} diff --git a/src/test/ui/rfc-2632-const-trait-impl/inherent-impl-const-bounds.rs b/src/test/ui/rfc-2632-const-trait-impl/inherent-impl-const-bounds.rs new file mode 100644 index 0000000000..fe1015b3bf --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/inherent-impl-const-bounds.rs @@ -0,0 +1,21 @@ +// check-pass +#![feature(const_trait_impl)] +#![feature(const_fn_trait_bound)] + +struct S; + +trait A {} +trait B {} + +impl const A for S {} +impl const B for S {} + +impl S { + const fn a() where T: ~const B { + + } +} + +const _: () = S::a::(); + +fn main() {} diff --git a/src/test/ui/rfc-2632-const-trait-impl/stability.stderr b/src/test/ui/rfc-2632-const-trait-impl/stability.stderr index 86b685959a..5649f688fe 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/stability.stderr +++ b/src/test/ui/rfc-2632-const-trait-impl/stability.stderr @@ -13,7 +13,7 @@ error: `::add` is not yet stable as a const fn LL | Int(1i32) + Int(2i32) | ^^^^^^^^^^^^^^^^^^^^^ | - = help: Const-stable functions can only call other const-stable functions + = help: const-stable functions can only call other const-stable functions error: aborting due to 2 previous errors diff --git a/src/test/ui/rfc1623.nll.stderr b/src/test/ui/rfc1623.nll.stderr index cc247bbcb1..7f15c1c1f5 100644 --- a/src/test/ui/rfc1623.nll.stderr +++ b/src/test/ui/rfc1623.nll.stderr @@ -31,7 +31,7 @@ LL | | LL | | }; | |_^ one type is more general than the other | - = note: expected type `for<'r, 's> Fn<(&'r Foo<'s>,)>` + = note: expected type `for<'a, 'b> Fn<(&'a Foo<'b>,)>` found type `Fn<(&Foo<'_>,)>` error[E0308]: mismatched types @@ -46,7 +46,7 @@ LL | | LL | | }; | |_^ one type is more general than the other | - = note: expected type `for<'r, 's> Fn<(&'r Foo<'s>,)>` + = note: expected type `for<'a, 'b> Fn<(&'a Foo<'b>,)>` found type `Fn<(&Foo<'_>,)>` error: implementation of `FnOnce` is not general enough @@ -61,7 +61,7 @@ LL | | LL | | }; | |_^ implementation of `FnOnce` is not general enough | - = note: `fn(&'2 Foo<'_>) -> &'2 Foo<'_> {id::<&'2 Foo<'_>>}` must implement `FnOnce<(&'1 Foo<'_>,)>`, for any lifetime `'1`... + = note: `fn(&'2 Foo<'_>) -> &'2 Foo<'_> {id::<&'2 Foo<'_>>}` must implement `FnOnce<(&'1 Foo<'b>,)>`, for any lifetime `'1`... = note: ...but it actually implements `FnOnce<(&'2 Foo<'_>,)>`, for some specific lifetime `'2` error: implementation of `FnOnce` is not general enough @@ -76,7 +76,7 @@ LL | | LL | | }; | |_^ implementation of `FnOnce` is not general enough | - = note: `fn(&Foo<'2>) -> &Foo<'2> {id::<&Foo<'2>>}` must implement `FnOnce<(&Foo<'1>,)>`, for any lifetime `'1`... + = note: `fn(&Foo<'2>) -> &Foo<'2> {id::<&Foo<'2>>}` must implement `FnOnce<(&'a Foo<'1>,)>`, for any lifetime `'1`... = note: ...but it actually implements `FnOnce<(&Foo<'2>,)>`, for some specific lifetime `'2` error: aborting due to 5 previous errors diff --git a/src/test/ui/rfcs/rfc-2005-default-binding-mode/box.rs b/src/test/ui/rfcs/rfc-2005-default-binding-mode/box.rs index b3be41599a..0d1cded36b 100644 --- a/src/test/ui/rfcs/rfc-2005-default-binding-mode/box.rs +++ b/src/test/ui/rfcs/rfc-2005-default-binding-mode/box.rs @@ -1,11 +1,11 @@ // run-pass #![allow(unreachable_patterns)] -#![feature(box_syntax, box_patterns)] +#![feature(box_patterns)] struct Foo{} pub fn main() { - let b = box Foo{}; + let b = Box::new(Foo{}); let box f = &b; let _: &Foo = f; diff --git a/src/test/ui/rfcs/rfc-2396-target_feature-11/fn-traits.stderr b/src/test/ui/rfcs/rfc-2396-target_feature-11/fn-traits.stderr index 81c0c4a787..ea22d1c89b 100644 --- a/src/test/ui/rfcs/rfc-2396-target_feature-11/fn-traits.stderr +++ b/src/test/ui/rfcs/rfc-2396-target_feature-11/fn-traits.stderr @@ -2,7 +2,9 @@ error[E0277]: expected a `Fn<()>` closure, found `fn() {foo}` --> $DIR/fn-traits.rs:24:10 | LL | call(foo); - | ^^^ expected an `Fn<()>` closure, found `fn() {foo}` + | ---- ^^^ expected an `Fn<()>` closure, found `fn() {foo}` + | | + | required by a bound introduced by this call | = help: the trait `Fn<()>` is not implemented for `fn() {foo}` = note: wrap the `fn() {foo}` in a closure with no arguments: `|| { /* code */ }` @@ -17,7 +19,9 @@ error[E0277]: expected a `FnMut<()>` closure, found `fn() {foo}` --> $DIR/fn-traits.rs:25:14 | LL | call_mut(foo); - | ^^^ expected an `FnMut<()>` closure, found `fn() {foo}` + | -------- ^^^ expected an `FnMut<()>` closure, found `fn() {foo}` + | | + | required by a bound introduced by this call | = help: the trait `FnMut<()>` is not implemented for `fn() {foo}` = note: wrap the `fn() {foo}` in a closure with no arguments: `|| { /* code */ }` @@ -32,7 +36,9 @@ error[E0277]: expected a `FnOnce<()>` closure, found `fn() {foo}` --> $DIR/fn-traits.rs:26:15 | LL | call_once(foo); - | ^^^ expected an `FnOnce<()>` closure, found `fn() {foo}` + | --------- ^^^ expected an `FnOnce<()>` closure, found `fn() {foo}` + | | + | required by a bound introduced by this call | = help: the trait `FnOnce<()>` is not implemented for `fn() {foo}` = note: wrap the `fn() {foo}` in a closure with no arguments: `|| { /* code */ }` @@ -47,7 +53,9 @@ error[E0277]: expected a `Fn<()>` closure, found `unsafe fn() {foo_unsafe}` --> $DIR/fn-traits.rs:28:10 | LL | call(foo_unsafe); - | ^^^^^^^^^^ expected an `Fn<()>` closure, found `unsafe fn() {foo_unsafe}` + | ---- ^^^^^^^^^^ expected an `Fn<()>` closure, found `unsafe fn() {foo_unsafe}` + | | + | required by a bound introduced by this call | = help: the trait `Fn<()>` is not implemented for `unsafe fn() {foo_unsafe}` = note: wrap the `unsafe fn() {foo_unsafe}` in a closure with no arguments: `|| { /* code */ }` @@ -62,7 +70,9 @@ error[E0277]: expected a `FnMut<()>` closure, found `unsafe fn() {foo_unsafe}` --> $DIR/fn-traits.rs:30:14 | LL | call_mut(foo_unsafe); - | ^^^^^^^^^^ expected an `FnMut<()>` closure, found `unsafe fn() {foo_unsafe}` + | -------- ^^^^^^^^^^ expected an `FnMut<()>` closure, found `unsafe fn() {foo_unsafe}` + | | + | required by a bound introduced by this call | = help: the trait `FnMut<()>` is not implemented for `unsafe fn() {foo_unsafe}` = note: wrap the `unsafe fn() {foo_unsafe}` in a closure with no arguments: `|| { /* code */ }` @@ -77,7 +87,9 @@ error[E0277]: expected a `FnOnce<()>` closure, found `unsafe fn() {foo_unsafe}` --> $DIR/fn-traits.rs:32:15 | LL | call_once(foo_unsafe); - | ^^^^^^^^^^ expected an `FnOnce<()>` closure, found `unsafe fn() {foo_unsafe}` + | --------- ^^^^^^^^^^ expected an `FnOnce<()>` closure, found `unsafe fn() {foo_unsafe}` + | | + | required by a bound introduced by this call | = help: the trait `FnOnce<()>` is not implemented for `unsafe fn() {foo_unsafe}` = note: wrap the `unsafe fn() {foo_unsafe}` in a closure with no arguments: `|| { /* code */ }` diff --git a/src/test/ui/rust-2018/trait-import-suggestions.stderr b/src/test/ui/rust-2018/trait-import-suggestions.stderr index 2cf5a073fe..eb4e43aaec 100644 --- a/src/test/ui/rust-2018/trait-import-suggestions.stderr +++ b/src/test/ui/rust-2018/trait-import-suggestions.stderr @@ -8,8 +8,10 @@ LL | x.foobar(); | ^^^^^^ method not found in `u32` | = help: items from traits can only be used if the trait is in scope - = note: the following trait is implemented but not in scope; perhaps add a `use` for it: - `use crate::foo::foobar::Foobar;` +help: the following trait is implemented but not in scope; perhaps add a `use` for it: + | +LL | use crate::foo::foobar::Foobar; + | error[E0599]: no method named `bar` found for type `u32` in the current scope --> $DIR/trait-import-suggestions.rs:28:7 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 7819a2588e..2545231a17 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 @@ -15,7 +15,7 @@ LL | | } | |_____________^ ... LL | m!(); - | ----- in this macro invocation + | ---- in this macro invocation = help: use `self::std` to refer to this module unambiguously = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) 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 54f28113cb..af45cd81a3 100644 --- a/src/test/ui/rust-2018/uniform-paths/ambiguity-macros.stderr +++ b/src/test/ui/rust-2018/uniform-paths/ambiguity-macros.stderr @@ -15,7 +15,7 @@ LL | | } | |_________^ ... LL | m!(); - | ----- in this macro invocation + | ---- in this macro invocation = help: use `crate::std` to refer to this module unambiguously = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) 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 e60f9c039b..e4662b430d 100644 --- a/src/test/ui/rust-2021/future-prelude-collision-shadow.stderr +++ b/src/test/ui/rust-2021/future-prelude-collision-shadow.stderr @@ -15,9 +15,6 @@ LL | fn try_into(self) -> Result; | the method is available for `Rc` here | = help: items from traits can only be used if the trait is in scope - = note: the following traits are implemented but not in scope; perhaps add a `use` for one of them: - candidate #1: `use crate::m::TryIntoU32;` - candidate #2: `use std::convert::TryInto;` help: consider wrapping the receiver expression with the appropriate type | LL | let _: u32 = Box::new(3u8).try_into().unwrap(); @@ -34,6 +31,12 @@ help: consider wrapping the receiver expression with the appropriate type | LL | let _: u32 = Rc::new(3u8).try_into().unwrap(); | ++++++++ + +help: the following traits are implemented but not in scope; perhaps add a `use` for one of them: + | +LL | use crate::m::TryIntoU32; + | +LL | use std::convert::TryInto; + | error: aborting due to previous error diff --git a/src/test/ui/rust-2021/reserved-prefixes-via-macro-2.stderr b/src/test/ui/rust-2021/reserved-prefixes-via-macro-2.stderr index 9d7ca570c4..ae7c5d60cb 100644 --- a/src/test/ui/rust-2021/reserved-prefixes-via-macro-2.stderr +++ b/src/test/ui/rust-2021/reserved-prefixes-via-macro-2.stderr @@ -2,7 +2,7 @@ error: prefix `hey` is unknown --> $DIR/reserved-prefixes-via-macro-2.rs:15:5 | LL | m2021::number_of_tokens_in_a_prefixed_integer_literal!(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unknown prefix + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unknown prefix | = note: prefixed identifiers and literals are reserved since Rust 2021 = note: this error originates in the macro `m2021::number_of_tokens_in_a_prefixed_integer_literal` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -11,7 +11,7 @@ error: prefix `hey` is unknown --> $DIR/reserved-prefixes-via-macro-2.rs:17:5 | LL | m2021::number_of_tokens_in_a_prefixed_char_literal!(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unknown prefix + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unknown prefix | = note: prefixed identifiers and literals are reserved since Rust 2021 = note: this error originates in the macro `m2021::number_of_tokens_in_a_prefixed_char_literal` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -20,7 +20,7 @@ error: prefix `hey` is unknown --> $DIR/reserved-prefixes-via-macro-2.rs:19:5 | LL | m2021::number_of_tokens_in_a_prefixed_string_literal!(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unknown prefix + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unknown prefix | = note: prefixed identifiers and literals are reserved since Rust 2021 = note: this error originates in the macro `m2021::number_of_tokens_in_a_prefixed_string_literal` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/sanitize/crt-static.stderr b/src/test/ui/sanitize/crt-static.stderr index 3a9c636d76..9f74235fea 100644 --- a/src/test/ui/sanitize/crt-static.stderr +++ b/src/test/ui/sanitize/crt-static.stderr @@ -1,4 +1,4 @@ -error: Sanitizer is incompatible with statically linked libc, disable it using `-C target-feature=-crt-static` +error: sanitizer is incompatible with statically linked libc, disable it using `-C target-feature=-crt-static` error: aborting due to previous error diff --git a/src/test/ui/self/explicit-self-generic.rs b/src/test/ui/self/explicit-self-generic.rs index 03f72a5513..8f6bed3b0c 100644 --- a/src/test/ui/self/explicit-self-generic.rs +++ b/src/test/ui/self/explicit-self-generic.rs @@ -1,6 +1,5 @@ // run-pass #![allow(dead_code)] -#![feature(box_syntax)] #[derive(Copy, Clone)] struct LM { resize_at: usize, size: usize } @@ -24,6 +23,6 @@ impl HashMap { } pub fn main() { - let mut m: Box<_> = box linear_map::<(),()>(); + let mut m: Box<_> = Box::new(linear_map::<(),()>()); assert_eq!(m.len(), 0); } diff --git a/src/test/ui/self/explicit-self-objects-uniq.rs b/src/test/ui/self/explicit-self-objects-uniq.rs index 0050bc7124..250ea12e57 100644 --- a/src/test/ui/self/explicit-self-objects-uniq.rs +++ b/src/test/ui/self/explicit-self-objects-uniq.rs @@ -1,5 +1,4 @@ // run-pass -#![feature(box_syntax)] trait Foo { fn f(self: Box); @@ -16,7 +15,7 @@ impl Foo for S { } pub fn main() { - let x = box S { x: 3 }; + let x = Box::new(S { x: 3 }); let y = x as Box; y.f(); } diff --git a/src/test/ui/self/explicit-self.rs b/src/test/ui/self/explicit-self.rs index 6d19d33b6f..873c3621a3 100644 --- a/src/test/ui/self/explicit-self.rs +++ b/src/test/ui/self/explicit-self.rs @@ -3,8 +3,6 @@ #![allow(non_camel_case_types)] #![allow(non_upper_case_globals)] -#![feature(box_syntax)] - static tau: f64 = 2.0*3.14159265358979323; struct Point {x: f64, y: f64} @@ -64,7 +62,7 @@ trait Nus { fn f(&self); } impl Nus for thing { fn f(&self) {} } pub fn main() { - let y: Box<_> = box thing(A {a: 10}); + let y: Box<_> = Box::new(thing(A {a: 10})); assert_eq!(y.clone().bar(), 10); assert_eq!(y.quux(), 10); diff --git a/src/test/ui/self/self-impl-2.rs b/src/test/ui/self/self-impl-2.rs index 23d513e3fa..7eed3f056a 100644 --- a/src/test/ui/self/self-impl-2.rs +++ b/src/test/ui/self/self-impl-2.rs @@ -5,8 +5,6 @@ // pretty-expanded FIXME #23616 -#![feature(box_syntax)] - struct Foo; // Test uses on inherent impl. @@ -57,14 +55,14 @@ impl Bar for Box> { let _: Self::SuperQux = true; let _: ::SuperQux = true; - box Baz { f: 42 } + Box::new(Baz { f: 42 }) } } fn main() { - let _: Foo = Foo::foo(Foo, &Foo, box Foo); - let _: Box> = Bar::bar(box Baz { f: 42 }, - &box Baz { f: 42 }, - box box Baz { f: 42 }, + let _: Foo = Foo::foo(Foo, &Foo, Box::new(Foo)); + let _: Box> = Bar::bar(Box::new(Baz { f: 42 }), + &Box::new(Baz { f: 42 }), + Box::new(Box::new(Baz { f: 42 })), true); } diff --git a/src/test/ui/self/self-in-mut-slot-default-method.rs b/src/test/ui/self/self-in-mut-slot-default-method.rs index 82c5f58f02..45e122c8d7 100644 --- a/src/test/ui/self/self-in-mut-slot-default-method.rs +++ b/src/test/ui/self/self-in-mut-slot-default-method.rs @@ -1,5 +1,4 @@ // run-pass -#![feature(box_syntax)] struct X { a: isize @@ -30,7 +29,7 @@ pub fn main() { let new_x = x.change(); assert_eq!(new_x.a, 55); - let x: Box<_> = box new_x; + let x: Box<_> = Box::new(new_x); let new_x = x.change_again(); assert_eq!(new_x.a, 45); } diff --git a/src/test/ui/self/self-re-assign.rs b/src/test/ui/self/self-re-assign.rs index 88e8614683..9595ebf960 100644 --- a/src/test/ui/self/self-re-assign.rs +++ b/src/test/ui/self/self-re-assign.rs @@ -2,13 +2,12 @@ // Ensure assigning an owned or managed variable to itself works. In particular, // that we do not glue_drop before we glue_take (#3290). -#![feature(box_syntax)] #![allow(dead_code)] use std::rc::Rc; pub fn main() { - let mut x: Box<_> = box 3; + let mut x: Box<_> = Box::new(3); x = x; assert_eq!(*x, 3); diff --git a/src/test/ui/self/self_type_keyword.stderr b/src/test/ui/self/self_type_keyword.stderr index 47c04f1eb7..aca08d8116 100644 --- a/src/test/ui/self/self_type_keyword.stderr +++ b/src/test/ui/self/self_type_keyword.stderr @@ -66,10 +66,11 @@ error[E0531]: cannot find unit struct, unit variant or constant `Self` in this s LL | mut Self => (), | ^^^^ not found in this scope | -help: consider importing this unit struct - | -LL | use foo::Self; +note: unit struct `foo::Self` exists but is inaccessible + --> $DIR/self_type_keyword.rs:2:3 | +LL | struct Self; + | ^^^^^^^^^^^^ not accessible error[E0392]: parameter `'Self` is never used --> $DIR/self_type_keyword.rs:6:12 diff --git a/src/test/ui/self/ufcs-explicit-self.rs b/src/test/ui/self/ufcs-explicit-self.rs index 4e2405504f..d83af14d35 100644 --- a/src/test/ui/self/ufcs-explicit-self.rs +++ b/src/test/ui/self/ufcs-explicit-self.rs @@ -1,5 +1,5 @@ // run-pass -#![feature(box_syntax)] +#![allow(dead_code)] #[derive(Copy, Clone)] struct Foo { @@ -36,13 +36,13 @@ impl Bar { } fn main() { - let foo: Box<_> = box Foo { + let foo: Box<_> = Box::new(Foo { f: 1, - }; + }); println!("{} {} {}", foo.foo(2), foo.bar(2), foo.baz(2)); - let bar: Box<_> = box Bar { + let bar: Box<_> = Box::new(Bar { f: 1, - }; + }); println!("{} {} {}", bar.foo(2), bar.bar(2), bar.baz(2)); let bar: Box> = bar; println!("{} {} {}", bar.foo(2), bar.bar(2), bar.baz(2)); diff --git a/src/test/ui/self/uniq-self-in-mut-slot.rs b/src/test/ui/self/uniq-self-in-mut-slot.rs index 695f06ecdd..71e57d8c1f 100644 --- a/src/test/ui/self/uniq-self-in-mut-slot.rs +++ b/src/test/ui/self/uniq-self-in-mut-slot.rs @@ -1,5 +1,4 @@ // run-pass -#![feature(box_syntax)] struct X { a: isize @@ -17,7 +16,7 @@ impl Changer for X { } pub fn main() { - let x: Box<_> = box X { a: 32 }; + let x: Box<_> = Box::new(X { a: 32 }); let new_x = x.change(); assert_eq!(new_x.a, 55); } diff --git a/src/test/ui/shadowed/shadowed-type-parameter.rs b/src/test/ui/shadowed/shadowed-type-parameter.rs index e74620f890..66fd68a9f2 100644 --- a/src/test/ui/shadowed/shadowed-type-parameter.rs +++ b/src/test/ui/shadowed/shadowed-type-parameter.rs @@ -1,9 +1,9 @@ // Test that shadowed lifetimes generate an error. -#![feature(box_syntax)] struct Foo(T); + impl Foo { fn shadow_in_method(&self) {} //~^ ERROR the name `T` is already used diff --git a/src/test/ui/shift-various-bad-types.stderr b/src/test/ui/shift-various-bad-types.stderr index 7c16581686..932a435143 100644 --- a/src/test/ui/shift-various-bad-types.stderr +++ b/src/test/ui/shift-various-bad-types.stderr @@ -33,7 +33,7 @@ LL | let _: i32 = 22_i64 >> 1_i32; help: you can convert an `i64` to an `i32` and panic if the converted value doesn't fit | LL | let _: i32 = (22_i64 >> 1_i32).try_into().unwrap(); - | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + | + +++++++++++++++++++++ error: aborting due to 4 previous errors diff --git a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-bitmask.rs b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-bitmask.rs deleted file mode 100644 index ed267d8411..0000000000 --- a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-bitmask.rs +++ /dev/null @@ -1,92 +0,0 @@ -// build-fail - -// Test that the simd_bitmask intrinsic produces ok-ish error -// messages when misused. - -#![feature(repr_simd, platform_intrinsics)] -#![allow(non_camel_case_types)] - -#[repr(simd)] -#[derive(Copy, Clone)] -pub struct u32x2(pub u32, pub u32); - -#[repr(simd)] -#[derive(Copy, Clone)] -pub struct u32x4(pub u32, pub u32, pub u32, pub u32); - -#[repr(simd)] -#[derive(Copy, Clone)] -struct u8x8( - pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, -); - -#[repr(simd)] -#[derive(Copy, Clone)] -struct u8x16( - pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, - pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, -); - -#[repr(simd)] -#[derive(Copy, Clone)] -struct u8x32( - pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, - pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, - pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, - pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, -); - -#[repr(simd)] -#[derive(Copy, Clone)] -struct u8x64( - pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, - pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, - pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, - pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, - pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, - pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, - pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, - pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, pub u8, -); - -extern "platform-intrinsic" { - fn simd_bitmask(x: T) -> U; -} - -fn main() { - let m2 = u32x2(0, 0); - let m4 = u32x4(0, 0, 0, 0); - let m8 = u8x8(0, 0, 0, 0, 0, 0, 0, 0); - let m16 = u8x16(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); - let m32 = u8x32(0, 0, 0, 0, 0, 0, 0, 0, 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 m64 = u8x64(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); - - unsafe { - let _: u8 = simd_bitmask(m2); - let _: u8 = simd_bitmask(m4); - let _: u8 = simd_bitmask(m8); - let _: u16 = simd_bitmask(m16); - let _: u32 = simd_bitmask(m32); - let _: u64 = simd_bitmask(m64); - - let _: u16 = simd_bitmask(m2); - //~^ ERROR bitmask `u16`, expected `u8` - - let _: u16 = simd_bitmask(m8); - //~^ ERROR bitmask `u16`, expected `u8` - - let _: u32 = simd_bitmask(m16); - //~^ ERROR bitmask `u32`, expected `u16` - - let _: u64 = simd_bitmask(m32); - //~^ ERROR bitmask `u64`, expected `u32` - - let _: u128 = simd_bitmask(m64); - //~^ ERROR bitmask `u128`, expected `u64` - - } -} diff --git a/src/test/ui/simd/simd-array-trait.rs b/src/test/ui/simd/array-trait.rs similarity index 100% rename from src/test/ui/simd/simd-array-trait.rs rename to src/test/ui/simd/array-trait.rs diff --git a/src/test/ui/simd/simd-array-trait.stderr b/src/test/ui/simd/array-trait.stderr similarity index 87% rename from src/test/ui/simd/simd-array-trait.stderr rename to src/test/ui/simd/array-trait.stderr index 0e02883f67..765215c393 100644 --- a/src/test/ui/simd/simd-array-trait.stderr +++ b/src/test/ui/simd/array-trait.stderr @@ -1,5 +1,5 @@ error: unconstrained generic constant - --> $DIR/simd-array-trait.rs:23:23 + --> $DIR/array-trait.rs:23:23 | LL | pub struct T([S::Lane; S::SIZE]); | ^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/simd/simd-array-type.rs b/src/test/ui/simd/array-type.rs similarity index 100% rename from src/test/ui/simd/simd-array-type.rs rename to src/test/ui/simd/array-type.rs diff --git a/src/test/ui/simd/simd-generics.rs b/src/test/ui/simd/generics.rs similarity index 100% rename from src/test/ui/simd/simd-generics.rs rename to src/test/ui/simd/generics.rs diff --git a/src/test/ui/simd/simd-intrinsic-float-math.rs b/src/test/ui/simd/intrinsic/float-math-pass.rs similarity index 100% rename from src/test/ui/simd/simd-intrinsic-float-math.rs rename to src/test/ui/simd/intrinsic/float-math-pass.rs diff --git a/src/test/ui/simd/simd-intrinsic-float-minmax.rs b/src/test/ui/simd/intrinsic/float-minmax-pass.rs similarity index 100% rename from src/test/ui/simd/simd-intrinsic-float-minmax.rs rename to src/test/ui/simd/intrinsic/float-minmax-pass.rs diff --git a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-arithmetic.rs b/src/test/ui/simd/intrinsic/generic-arithmetic-2.rs similarity index 100% rename from src/test/ui/simd-intrinsic/simd-intrinsic-generic-arithmetic.rs rename to src/test/ui/simd/intrinsic/generic-arithmetic-2.rs diff --git a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-arithmetic.stderr b/src/test/ui/simd/intrinsic/generic-arithmetic-2.stderr similarity index 77% rename from src/test/ui/simd-intrinsic/simd-intrinsic-generic-arithmetic.stderr rename to src/test/ui/simd/intrinsic/generic-arithmetic-2.stderr index 99c5196334..0f0a7ea665 100644 --- a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-arithmetic.stderr +++ b/src/test/ui/simd/intrinsic/generic-arithmetic-2.stderr @@ -1,89 +1,89 @@ error[E0511]: invalid monomorphization of `simd_add` intrinsic: expected SIMD input type, found non-SIMD `i32` - --> $DIR/simd-intrinsic-generic-arithmetic.rs:69:9 + --> $DIR/generic-arithmetic-2.rs:69:9 | LL | simd_add(0, 0); | ^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_sub` intrinsic: expected SIMD input type, found non-SIMD `i32` - --> $DIR/simd-intrinsic-generic-arithmetic.rs:71:9 + --> $DIR/generic-arithmetic-2.rs:71:9 | LL | simd_sub(0, 0); | ^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_mul` intrinsic: expected SIMD input type, found non-SIMD `i32` - --> $DIR/simd-intrinsic-generic-arithmetic.rs:73:9 + --> $DIR/generic-arithmetic-2.rs:73:9 | LL | simd_mul(0, 0); | ^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_div` intrinsic: expected SIMD input type, found non-SIMD `i32` - --> $DIR/simd-intrinsic-generic-arithmetic.rs:75:9 + --> $DIR/generic-arithmetic-2.rs:75:9 | LL | simd_div(0, 0); | ^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_shl` intrinsic: expected SIMD input type, found non-SIMD `i32` - --> $DIR/simd-intrinsic-generic-arithmetic.rs:77:9 + --> $DIR/generic-arithmetic-2.rs:77:9 | LL | simd_shl(0, 0); | ^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_shr` intrinsic: expected SIMD input type, found non-SIMD `i32` - --> $DIR/simd-intrinsic-generic-arithmetic.rs:79:9 + --> $DIR/generic-arithmetic-2.rs:79:9 | LL | simd_shr(0, 0); | ^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_and` intrinsic: expected SIMD input type, found non-SIMD `i32` - --> $DIR/simd-intrinsic-generic-arithmetic.rs:81:9 + --> $DIR/generic-arithmetic-2.rs:81:9 | LL | simd_and(0, 0); | ^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_or` intrinsic: expected SIMD input type, found non-SIMD `i32` - --> $DIR/simd-intrinsic-generic-arithmetic.rs:83:9 + --> $DIR/generic-arithmetic-2.rs:83:9 | LL | simd_or(0, 0); | ^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_xor` intrinsic: expected SIMD input type, found non-SIMD `i32` - --> $DIR/simd-intrinsic-generic-arithmetic.rs:85:9 + --> $DIR/generic-arithmetic-2.rs:85:9 | LL | simd_xor(0, 0); | ^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_neg` intrinsic: expected SIMD input type, found non-SIMD `i32` - --> $DIR/simd-intrinsic-generic-arithmetic.rs:88:9 + --> $DIR/generic-arithmetic-2.rs:88:9 | LL | simd_neg(0); | ^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_shl` intrinsic: unsupported operation on `f32x4` with element `f32` - --> $DIR/simd-intrinsic-generic-arithmetic.rs:92:9 + --> $DIR/generic-arithmetic-2.rs:92:9 | LL | simd_shl(z, z); | ^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_shr` intrinsic: unsupported operation on `f32x4` with element `f32` - --> $DIR/simd-intrinsic-generic-arithmetic.rs:94:9 + --> $DIR/generic-arithmetic-2.rs:94:9 | LL | simd_shr(z, z); | ^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_and` intrinsic: unsupported operation on `f32x4` with element `f32` - --> $DIR/simd-intrinsic-generic-arithmetic.rs:96:9 + --> $DIR/generic-arithmetic-2.rs:96:9 | LL | simd_and(z, z); | ^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_or` intrinsic: unsupported operation on `f32x4` with element `f32` - --> $DIR/simd-intrinsic-generic-arithmetic.rs:98:9 + --> $DIR/generic-arithmetic-2.rs:98:9 | LL | simd_or(z, z); | ^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_xor` intrinsic: unsupported operation on `f32x4` with element `f32` - --> $DIR/simd-intrinsic-generic-arithmetic.rs:100:9 + --> $DIR/generic-arithmetic-2.rs:100:9 | LL | simd_xor(z, z); | ^^^^^^^^^^^^^^ diff --git a/src/test/ui/simd/simd-intrinsic-generic-arithmetic.rs b/src/test/ui/simd/intrinsic/generic-arithmetic-pass.rs similarity index 100% rename from src/test/ui/simd/simd-intrinsic-generic-arithmetic.rs rename to src/test/ui/simd/intrinsic/generic-arithmetic-pass.rs diff --git a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-arithmetic-saturating.rs b/src/test/ui/simd/intrinsic/generic-arithmetic-saturating-2.rs similarity index 100% rename from src/test/ui/simd-intrinsic/simd-intrinsic-generic-arithmetic-saturating.rs rename to src/test/ui/simd/intrinsic/generic-arithmetic-saturating-2.rs diff --git a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-arithmetic-saturating.stderr b/src/test/ui/simd/intrinsic/generic-arithmetic-saturating-2.stderr similarity index 82% rename from src/test/ui/simd-intrinsic/simd-intrinsic-generic-arithmetic-saturating.stderr rename to src/test/ui/simd/intrinsic/generic-arithmetic-saturating-2.stderr index 0e88540bcc..f349cb5656 100644 --- a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-arithmetic-saturating.stderr +++ b/src/test/ui/simd/intrinsic/generic-arithmetic-saturating-2.stderr @@ -1,11 +1,11 @@ error[E0511]: invalid monomorphization of `simd_saturating_add` intrinsic: expected element type `f32` of vector type `f32x4` to be a signed or unsigned integer type - --> $DIR/simd-intrinsic-generic-arithmetic-saturating.rs:33:9 + --> $DIR/generic-arithmetic-saturating-2.rs:33:9 | LL | simd_saturating_add(z, z); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_saturating_sub` intrinsic: expected element type `f32` of vector type `f32x4` to be a signed or unsigned integer type - --> $DIR/simd-intrinsic-generic-arithmetic-saturating.rs:35:9 + --> $DIR/generic-arithmetic-saturating-2.rs:35:9 | LL | simd_saturating_sub(z, z); | ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/simd/simd-intrinsic-generic-arithmetic-saturating.rs b/src/test/ui/simd/intrinsic/generic-arithmetic-saturating-pass.rs similarity index 100% rename from src/test/ui/simd/simd-intrinsic-generic-arithmetic-saturating.rs rename to src/test/ui/simd/intrinsic/generic-arithmetic-saturating-pass.rs diff --git a/src/test/ui/simd/simd-intrinsic-generic-bitmask.rs b/src/test/ui/simd/intrinsic/generic-bitmask-pass.rs similarity index 100% rename from src/test/ui/simd/simd-intrinsic-generic-bitmask.rs rename to src/test/ui/simd/intrinsic/generic-bitmask-pass.rs diff --git a/src/test/ui/simd/intrinsic/generic-bitmask.rs b/src/test/ui/simd/intrinsic/generic-bitmask.rs new file mode 100644 index 0000000000..92c4e67dfd --- /dev/null +++ b/src/test/ui/simd/intrinsic/generic-bitmask.rs @@ -0,0 +1,69 @@ +// build-fail + +// Test that the simd_bitmask intrinsic produces ok-ish error +// messages when misused. + +#![feature(repr_simd, platform_intrinsics)] +#![allow(non_camel_case_types)] + +#[repr(simd)] +#[derive(Copy, Clone)] +pub struct u32x2([u32; 2]); + +#[repr(simd)] +#[derive(Copy, Clone)] +pub struct u32x4([u32; 4]); + +#[repr(simd)] +#[derive(Copy, Clone)] +struct u8x8([u8; 8]); + +#[repr(simd)] +#[derive(Copy, Clone)] +struct u8x16([u8; 16]); + +#[repr(simd)] +#[derive(Copy, Clone)] +struct u8x32([u8; 32]); + +#[repr(simd)] +#[derive(Copy, Clone)] +struct u8x64([u8; 64]); + +extern "platform-intrinsic" { + fn simd_bitmask(x: T) -> U; +} + +fn main() { + let m2 = u32x2([0; 2]); + let m4 = u32x4([0; 4]); + let m8 = u8x8([0; 8]); + let m16 = u8x16([0; 16]); + let m32 = u8x32([0; 32]); + let m64 = u8x64([0; 64]); + + unsafe { + let _: u8 = simd_bitmask(m2); + let _: u8 = simd_bitmask(m4); + let _: u8 = simd_bitmask(m8); + let _: u16 = simd_bitmask(m16); + let _: u32 = simd_bitmask(m32); + let _: u64 = simd_bitmask(m64); + + let _: u16 = simd_bitmask(m2); + //~^ ERROR bitmask `u16`, expected `u8` + + let _: u16 = simd_bitmask(m8); + //~^ ERROR bitmask `u16`, expected `u8` + + let _: u32 = simd_bitmask(m16); + //~^ ERROR bitmask `u32`, expected `u16` + + let _: u64 = simd_bitmask(m32); + //~^ ERROR bitmask `u64`, expected `u32` + + let _: u128 = simd_bitmask(m64); + //~^ ERROR bitmask `u128`, expected `u64` + + } +} diff --git a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-bitmask.stderr b/src/test/ui/simd/intrinsic/generic-bitmask.stderr similarity index 80% rename from src/test/ui/simd-intrinsic/simd-intrinsic-generic-bitmask.stderr rename to src/test/ui/simd/intrinsic/generic-bitmask.stderr index 8cb235b778..5aaae68caf 100644 --- a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-bitmask.stderr +++ b/src/test/ui/simd/intrinsic/generic-bitmask.stderr @@ -1,29 +1,29 @@ error[E0511]: invalid monomorphization of `simd_bitmask` intrinsic: bitmask `u16`, expected `u8` - --> $DIR/simd-intrinsic-generic-bitmask.rs:76:22 + --> $DIR/generic-bitmask.rs:53:22 | LL | let _: u16 = simd_bitmask(m2); | ^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_bitmask` intrinsic: bitmask `u16`, expected `u8` - --> $DIR/simd-intrinsic-generic-bitmask.rs:79:22 + --> $DIR/generic-bitmask.rs:56:22 | LL | let _: u16 = simd_bitmask(m8); | ^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_bitmask` intrinsic: bitmask `u32`, expected `u16` - --> $DIR/simd-intrinsic-generic-bitmask.rs:82:22 + --> $DIR/generic-bitmask.rs:59:22 | LL | let _: u32 = simd_bitmask(m16); | ^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_bitmask` intrinsic: bitmask `u64`, expected `u32` - --> $DIR/simd-intrinsic-generic-bitmask.rs:85:22 + --> $DIR/generic-bitmask.rs:62:22 | LL | let _: u64 = simd_bitmask(m32); | ^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_bitmask` intrinsic: bitmask `u128`, expected `u64` - --> $DIR/simd-intrinsic-generic-bitmask.rs:88:23 + --> $DIR/generic-bitmask.rs:65:23 | LL | let _: u128 = simd_bitmask(m64); | ^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/simd/simd-intrinsic-generic-cast.rs b/src/test/ui/simd/intrinsic/generic-cast-pass.rs similarity index 100% rename from src/test/ui/simd/simd-intrinsic-generic-cast.rs rename to src/test/ui/simd/intrinsic/generic-cast-pass.rs diff --git a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-cast.rs b/src/test/ui/simd/intrinsic/generic-cast.rs similarity index 100% rename from src/test/ui/simd-intrinsic/simd-intrinsic-generic-cast.rs rename to src/test/ui/simd/intrinsic/generic-cast.rs diff --git a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-cast.stderr b/src/test/ui/simd/intrinsic/generic-cast.stderr similarity index 83% rename from src/test/ui/simd-intrinsic/simd-intrinsic-generic-cast.stderr rename to src/test/ui/simd/intrinsic/generic-cast.stderr index d794a742b4..2226bbbe1b 100644 --- a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-cast.stderr +++ b/src/test/ui/simd/intrinsic/generic-cast.stderr @@ -1,23 +1,23 @@ error[E0511]: invalid monomorphization of `simd_cast` intrinsic: expected SIMD input type, found non-SIMD `i32` - --> $DIR/simd-intrinsic-generic-cast.rs:34:9 + --> $DIR/generic-cast.rs:34:9 | LL | simd_cast::(0); | ^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_cast` intrinsic: expected SIMD input type, found non-SIMD `i32` - --> $DIR/simd-intrinsic-generic-cast.rs:36:9 + --> $DIR/generic-cast.rs:36:9 | LL | simd_cast::(0); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_cast` intrinsic: expected SIMD return type, found non-SIMD `i32` - --> $DIR/simd-intrinsic-generic-cast.rs:38:9 + --> $DIR/generic-cast.rs:38:9 | LL | simd_cast::(x); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_cast` intrinsic: expected return type with length 4 (same as input type `i32x4`), found `i32x8` with length 8 - --> $DIR/simd-intrinsic-generic-cast.rs:40:9 + --> $DIR/generic-cast.rs:40:9 | LL | simd_cast::<_, i32x8>(x); | ^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/simd/simd-intrinsic-generic-comparison.rs b/src/test/ui/simd/intrinsic/generic-comparison-pass.rs similarity index 100% rename from src/test/ui/simd/simd-intrinsic-generic-comparison.rs rename to src/test/ui/simd/intrinsic/generic-comparison-pass.rs diff --git a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-comparison.rs b/src/test/ui/simd/intrinsic/generic-comparison.rs similarity index 100% rename from src/test/ui/simd-intrinsic/simd-intrinsic-generic-comparison.rs rename to src/test/ui/simd/intrinsic/generic-comparison.rs diff --git a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-comparison.stderr b/src/test/ui/simd/intrinsic/generic-comparison.stderr similarity index 80% rename from src/test/ui/simd-intrinsic/simd-intrinsic-generic-comparison.stderr rename to src/test/ui/simd/intrinsic/generic-comparison.stderr index 36c6b934d5..0eae2688bc 100644 --- a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-comparison.stderr +++ b/src/test/ui/simd/intrinsic/generic-comparison.stderr @@ -1,107 +1,107 @@ error[E0511]: invalid monomorphization of `simd_eq` intrinsic: expected SIMD input type, found non-SIMD `i32` - --> $DIR/simd-intrinsic-generic-comparison.rs:28:9 + --> $DIR/generic-comparison.rs:28:9 | LL | simd_eq::(0, 0); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_ne` intrinsic: expected SIMD input type, found non-SIMD `i32` - --> $DIR/simd-intrinsic-generic-comparison.rs:30:9 + --> $DIR/generic-comparison.rs:30:9 | LL | simd_ne::(0, 0); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_lt` intrinsic: expected SIMD input type, found non-SIMD `i32` - --> $DIR/simd-intrinsic-generic-comparison.rs:32:9 + --> $DIR/generic-comparison.rs:32:9 | LL | simd_lt::(0, 0); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_le` intrinsic: expected SIMD input type, found non-SIMD `i32` - --> $DIR/simd-intrinsic-generic-comparison.rs:34:9 + --> $DIR/generic-comparison.rs:34:9 | LL | simd_le::(0, 0); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_gt` intrinsic: expected SIMD input type, found non-SIMD `i32` - --> $DIR/simd-intrinsic-generic-comparison.rs:36:9 + --> $DIR/generic-comparison.rs:36:9 | LL | simd_gt::(0, 0); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_ge` intrinsic: expected SIMD input type, found non-SIMD `i32` - --> $DIR/simd-intrinsic-generic-comparison.rs:38:9 + --> $DIR/generic-comparison.rs:38:9 | LL | simd_ge::(0, 0); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_eq` intrinsic: expected SIMD return type, found non-SIMD `i32` - --> $DIR/simd-intrinsic-generic-comparison.rs:41:9 + --> $DIR/generic-comparison.rs:41:9 | LL | simd_eq::<_, i32>(x, x); | ^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_ne` intrinsic: expected SIMD return type, found non-SIMD `i32` - --> $DIR/simd-intrinsic-generic-comparison.rs:43:9 + --> $DIR/generic-comparison.rs:43:9 | LL | simd_ne::<_, i32>(x, x); | ^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_lt` intrinsic: expected SIMD return type, found non-SIMD `i32` - --> $DIR/simd-intrinsic-generic-comparison.rs:45:9 + --> $DIR/generic-comparison.rs:45:9 | LL | simd_lt::<_, i32>(x, x); | ^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_le` intrinsic: expected SIMD return type, found non-SIMD `i32` - --> $DIR/simd-intrinsic-generic-comparison.rs:47:9 + --> $DIR/generic-comparison.rs:47:9 | LL | simd_le::<_, i32>(x, x); | ^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_gt` intrinsic: expected SIMD return type, found non-SIMD `i32` - --> $DIR/simd-intrinsic-generic-comparison.rs:49:9 + --> $DIR/generic-comparison.rs:49:9 | LL | simd_gt::<_, i32>(x, x); | ^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_ge` intrinsic: expected SIMD return type, found non-SIMD `i32` - --> $DIR/simd-intrinsic-generic-comparison.rs:51:9 + --> $DIR/generic-comparison.rs:51:9 | LL | simd_ge::<_, i32>(x, x); | ^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_eq` intrinsic: expected return type with length 4 (same as input type `i32x4`), found `i16x8` with length 8 - --> $DIR/simd-intrinsic-generic-comparison.rs:54:9 + --> $DIR/generic-comparison.rs:54:9 | LL | simd_eq::<_, i16x8>(x, x); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_ne` intrinsic: expected return type with length 4 (same as input type `i32x4`), found `i16x8` with length 8 - --> $DIR/simd-intrinsic-generic-comparison.rs:56:9 + --> $DIR/generic-comparison.rs:56:9 | LL | simd_ne::<_, i16x8>(x, x); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_lt` intrinsic: expected return type with length 4 (same as input type `i32x4`), found `i16x8` with length 8 - --> $DIR/simd-intrinsic-generic-comparison.rs:58:9 + --> $DIR/generic-comparison.rs:58:9 | LL | simd_lt::<_, i16x8>(x, x); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_le` intrinsic: expected return type with length 4 (same as input type `i32x4`), found `i16x8` with length 8 - --> $DIR/simd-intrinsic-generic-comparison.rs:60:9 + --> $DIR/generic-comparison.rs:60:9 | LL | simd_le::<_, i16x8>(x, x); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_gt` intrinsic: expected return type with length 4 (same as input type `i32x4`), found `i16x8` with length 8 - --> $DIR/simd-intrinsic-generic-comparison.rs:62:9 + --> $DIR/generic-comparison.rs:62:9 | LL | simd_gt::<_, i16x8>(x, x); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_ge` intrinsic: expected return type with length 4 (same as input type `i32x4`), found `i16x8` with length 8 - --> $DIR/simd-intrinsic-generic-comparison.rs:64:9 + --> $DIR/generic-comparison.rs:64:9 | LL | simd_ge::<_, i16x8>(x, x); | ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/simd/simd-intrinsic-generic-elements.rs b/src/test/ui/simd/intrinsic/generic-elements-pass.rs similarity index 100% rename from src/test/ui/simd/simd-intrinsic-generic-elements.rs rename to src/test/ui/simd/intrinsic/generic-elements-pass.rs diff --git a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-elements.rs b/src/test/ui/simd/intrinsic/generic-elements.rs similarity index 100% rename from src/test/ui/simd-intrinsic/simd-intrinsic-generic-elements.rs rename to src/test/ui/simd/intrinsic/generic-elements.rs diff --git a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-elements.stderr b/src/test/ui/simd/intrinsic/generic-elements.stderr similarity index 82% rename from src/test/ui/simd-intrinsic/simd-intrinsic-generic-elements.stderr rename to src/test/ui/simd/intrinsic/generic-elements.stderr index 4220411114..5b423f7040 100644 --- a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-elements.stderr +++ b/src/test/ui/simd/intrinsic/generic-elements.stderr @@ -1,71 +1,71 @@ error[E0511]: invalid monomorphization of `simd_insert` intrinsic: expected SIMD input type, found non-SIMD `i32` - --> $DIR/simd-intrinsic-generic-elements.rs:46:9 + --> $DIR/generic-elements.rs:46:9 | LL | simd_insert(0, 0, 0); | ^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_insert` intrinsic: expected inserted type `i32` (element of input `i32x4`), found `f64` - --> $DIR/simd-intrinsic-generic-elements.rs:48:9 + --> $DIR/generic-elements.rs:48:9 | LL | simd_insert(x, 0, 1.0); | ^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_extract` intrinsic: expected return type `i32` (element of input `i32x4`), found `f32` - --> $DIR/simd-intrinsic-generic-elements.rs:50:9 + --> $DIR/generic-elements.rs:50:9 | LL | simd_extract::<_, f32>(x, 0); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_shuffle2` intrinsic: expected SIMD input type, found non-SIMD `i32` - --> $DIR/simd-intrinsic-generic-elements.rs:54:9 + --> $DIR/generic-elements.rs:54:9 | LL | simd_shuffle2::(0, 0, IDX2); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_shuffle4` intrinsic: expected SIMD input type, found non-SIMD `i32` - --> $DIR/simd-intrinsic-generic-elements.rs:57:9 + --> $DIR/generic-elements.rs:57:9 | LL | simd_shuffle4::(0, 0, IDX4); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_shuffle8` intrinsic: expected SIMD input type, found non-SIMD `i32` - --> $DIR/simd-intrinsic-generic-elements.rs:60:9 + --> $DIR/generic-elements.rs:60:9 | LL | simd_shuffle8::(0, 0, IDX8); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_shuffle2` intrinsic: expected return element type `i32` (element of input `i32x4`), found `f32x2` with element type `f32` - --> $DIR/simd-intrinsic-generic-elements.rs:63:9 + --> $DIR/generic-elements.rs:63:9 | LL | simd_shuffle2::<_, f32x2>(x, x, IDX2); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_shuffle4` intrinsic: expected return element type `i32` (element of input `i32x4`), found `f32x4` with element type `f32` - --> $DIR/simd-intrinsic-generic-elements.rs:65:9 + --> $DIR/generic-elements.rs:65:9 | LL | simd_shuffle4::<_, f32x4>(x, x, IDX4); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_shuffle8` intrinsic: expected return element type `i32` (element of input `i32x4`), found `f32x8` with element type `f32` - --> $DIR/simd-intrinsic-generic-elements.rs:67:9 + --> $DIR/generic-elements.rs:67:9 | LL | simd_shuffle8::<_, f32x8>(x, x, IDX8); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_shuffle2` intrinsic: expected return type of length 2, found `i32x8` with length 8 - --> $DIR/simd-intrinsic-generic-elements.rs:70:9 + --> $DIR/generic-elements.rs:70:9 | LL | simd_shuffle2::<_, i32x8>(x, x, IDX2); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_shuffle4` intrinsic: expected return type of length 4, found `i32x8` with length 8 - --> $DIR/simd-intrinsic-generic-elements.rs:72:9 + --> $DIR/generic-elements.rs:72:9 | LL | simd_shuffle4::<_, i32x8>(x, x, IDX4); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_shuffle8` intrinsic: expected return type of length 8, found `i32x2` with length 2 - --> $DIR/simd-intrinsic-generic-elements.rs:74:9 + --> $DIR/generic-elements.rs:74:9 | LL | simd_shuffle8::<_, i32x2>(x, x, IDX8); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/simd/simd-intrinsic-generic-gather.rs b/src/test/ui/simd/intrinsic/generic-gather-pass.rs similarity index 100% rename from src/test/ui/simd/simd-intrinsic-generic-gather.rs rename to src/test/ui/simd/intrinsic/generic-gather-pass.rs diff --git a/src/test/ui/simd/simd-intrinsic-generic-reduction.rs b/src/test/ui/simd/intrinsic/generic-reduction-pass.rs similarity index 95% rename from src/test/ui/simd/simd-intrinsic-generic-reduction.rs rename to src/test/ui/simd/intrinsic/generic-reduction-pass.rs index 7193fb3527..4a54afee80 100644 --- a/src/test/ui/simd/simd-intrinsic-generic-reduction.rs +++ b/src/test/ui/simd/intrinsic/generic-reduction-pass.rs @@ -24,15 +24,6 @@ struct f32x4(pub f32, pub f32, pub f32, pub f32); #[derive(Copy, Clone)] struct b8x4(pub i8, pub i8, pub i8, pub i8); -#[repr(simd)] -#[derive(Copy, Clone)] -struct b8x16( - pub i8, pub i8, pub i8, pub i8, - pub i8, pub i8, pub i8, pub i8, - pub i8, pub i8, pub i8, pub i8, - pub i8, pub i8, pub i8, pub i8 -); - extern "platform-intrinsic" { fn simd_reduce_add_unordered(x: T) -> U; fn simd_reduce_mul_unordered(x: T) -> U; diff --git a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-reduction.rs b/src/test/ui/simd/intrinsic/generic-reduction.rs similarity index 100% rename from src/test/ui/simd-intrinsic/simd-intrinsic-generic-reduction.rs rename to src/test/ui/simd/intrinsic/generic-reduction.rs diff --git a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-reduction.stderr b/src/test/ui/simd/intrinsic/generic-reduction.stderr similarity index 82% rename from src/test/ui/simd-intrinsic/simd-intrinsic-generic-reduction.stderr rename to src/test/ui/simd/intrinsic/generic-reduction.stderr index 91a62f6a1c..1028faf69a 100644 --- a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-reduction.stderr +++ b/src/test/ui/simd/intrinsic/generic-reduction.stderr @@ -1,59 +1,59 @@ error[E0511]: invalid monomorphization of `simd_reduce_add_ordered` intrinsic: expected return type `f32` (element of input `f32x4`), found `i32` - --> $DIR/simd-intrinsic-generic-reduction.rs:34:9 + --> $DIR/generic-reduction.rs:34:9 | LL | simd_reduce_add_ordered(z, 0); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_reduce_mul_ordered` intrinsic: expected return type `f32` (element of input `f32x4`), found `i32` - --> $DIR/simd-intrinsic-generic-reduction.rs:36:9 + --> $DIR/generic-reduction.rs:36:9 | LL | simd_reduce_mul_ordered(z, 1); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_reduce_and` intrinsic: expected return type `u32` (element of input `u32x4`), found `f32` - --> $DIR/simd-intrinsic-generic-reduction.rs:39:22 + --> $DIR/generic-reduction.rs:39:22 | LL | let _: f32 = simd_reduce_and(x); | ^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_reduce_or` intrinsic: expected return type `u32` (element of input `u32x4`), found `f32` - --> $DIR/simd-intrinsic-generic-reduction.rs:41:22 + --> $DIR/generic-reduction.rs:41:22 | LL | let _: f32 = simd_reduce_or(x); | ^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_reduce_xor` intrinsic: expected return type `u32` (element of input `u32x4`), found `f32` - --> $DIR/simd-intrinsic-generic-reduction.rs:43:22 + --> $DIR/generic-reduction.rs:43:22 | LL | let _: f32 = simd_reduce_xor(x); | ^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_reduce_and` intrinsic: unsupported simd_reduce_and from `f32x4` with element `f32` to `f32` - --> $DIR/simd-intrinsic-generic-reduction.rs:46:22 + --> $DIR/generic-reduction.rs:46:22 | LL | let _: f32 = simd_reduce_and(z); | ^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_reduce_or` intrinsic: unsupported simd_reduce_or from `f32x4` with element `f32` to `f32` - --> $DIR/simd-intrinsic-generic-reduction.rs:48:22 + --> $DIR/generic-reduction.rs:48:22 | LL | let _: f32 = simd_reduce_or(z); | ^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_reduce_xor` intrinsic: unsupported simd_reduce_xor from `f32x4` with element `f32` to `f32` - --> $DIR/simd-intrinsic-generic-reduction.rs:50:22 + --> $DIR/generic-reduction.rs:50:22 | LL | let _: f32 = simd_reduce_xor(z); | ^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_reduce_all` intrinsic: unsupported simd_reduce_all from `f32x4` with element `f32` to `bool` - --> $DIR/simd-intrinsic-generic-reduction.rs:53:23 + --> $DIR/generic-reduction.rs:53:23 | LL | let _: bool = simd_reduce_all(z); | ^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_reduce_any` intrinsic: unsupported simd_reduce_any from `f32x4` with element `f32` to `bool` - --> $DIR/simd-intrinsic-generic-reduction.rs:55:23 + --> $DIR/generic-reduction.rs:55:23 | LL | let _: bool = simd_reduce_any(z); | ^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/simd/simd-intrinsic-generic-select.rs b/src/test/ui/simd/intrinsic/generic-select-pass.rs similarity index 100% rename from src/test/ui/simd/simd-intrinsic-generic-select.rs rename to src/test/ui/simd/intrinsic/generic-select-pass.rs diff --git a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-select.rs b/src/test/ui/simd/intrinsic/generic-select.rs similarity index 100% rename from src/test/ui/simd-intrinsic/simd-intrinsic-generic-select.rs rename to src/test/ui/simd/intrinsic/generic-select.rs diff --git a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-select.stderr b/src/test/ui/simd/intrinsic/generic-select.stderr similarity index 81% rename from src/test/ui/simd-intrinsic/simd-intrinsic-generic-select.stderr rename to src/test/ui/simd/intrinsic/generic-select.stderr index a1ef0bb8ee..c53d581745 100644 --- a/src/test/ui/simd-intrinsic/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/simd-intrinsic-generic-select.rs:40:9 + --> $DIR/generic-select.rs:40:9 | LL | simd_select(m8, x, x); | ^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_select` intrinsic: mask element type is `u32`, expected `i_` - --> $DIR/simd-intrinsic-generic-select.rs:43:9 + --> $DIR/generic-select.rs:43:9 | LL | simd_select(x, x, x); | ^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_select` intrinsic: mask element type is `f32`, expected `i_` - --> $DIR/simd-intrinsic-generic-select.rs:46:9 + --> $DIR/generic-select.rs:46:9 | LL | simd_select(z, z, z); | ^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_select` intrinsic: expected SIMD argument type, found non-SIMD `u32` - --> $DIR/simd-intrinsic-generic-select.rs:49:9 + --> $DIR/generic-select.rs:49: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/simd-intrinsic-generic-select.rs:52:9 + --> $DIR/generic-select.rs:52: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/simd-intrinsic-generic-select.rs:55:9 + --> $DIR/generic-select.rs:55:9 | LL | simd_select_bitmask(0u8, 1u32, 2u32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_select_bitmask` intrinsic: `f32` is not an integral type - --> $DIR/simd-intrinsic-generic-select.rs:58:9 + --> $DIR/generic-select.rs:58: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/simd-intrinsic-generic-select.rs:61:9 + --> $DIR/generic-select.rs:61:9 | LL | simd_select_bitmask("x", x, x); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/simd/intrinsic/generic-shuffle.rs b/src/test/ui/simd/intrinsic/generic-shuffle.rs new file mode 100644 index 0000000000..9611780ac0 --- /dev/null +++ b/src/test/ui/simd/intrinsic/generic-shuffle.rs @@ -0,0 +1,33 @@ +// build-fail + +// Test that the simd_shuffle intrinsic produces ok-ish error +// messages when misused. + +#![feature(repr_simd, platform_intrinsics)] + +#[repr(simd)] +#[derive(Copy, Clone)] +pub struct Simd([T; N]); + +extern "platform-intrinsic" { + fn simd_shuffle(a: T, b: T, i: I) -> U; +} + +fn main() { + const I: [u32; 2] = [0; 2]; + const I2: [f32; 2] = [0.; 2]; + let v = Simd::([0; 4]); + + unsafe { + let _: Simd = simd_shuffle(v, v, I); + + let _: Simd = simd_shuffle(v, v, I); + //~^ ERROR invalid monomorphization of `simd_shuffle` intrinsic + + let _: Simd = simd_shuffle(v, v, I); + //~^ ERROR invalid monomorphization of `simd_shuffle` intrinsic + + let _: Simd = simd_shuffle(v, v, I2); + //~^ ERROR invalid monomorphization of `simd_shuffle` intrinsic + } +} diff --git a/src/test/ui/simd/intrinsic/generic-shuffle.stderr b/src/test/ui/simd/intrinsic/generic-shuffle.stderr new file mode 100644 index 0000000000..44c57cd7c4 --- /dev/null +++ b/src/test/ui/simd/intrinsic/generic-shuffle.stderr @@ -0,0 +1,21 @@ +error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected return type of length 2, found `Simd` with length 4 + --> $DIR/generic-shuffle.rs:24:31 + | +LL | let _: Simd = simd_shuffle(v, v, I); + | ^^^^^^^^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected return element type `u32` (element of input `Simd`), found `Simd` with element type `f32` + --> $DIR/generic-shuffle.rs:27:31 + | +LL | let _: Simd = simd_shuffle(v, v, I); + | ^^^^^^^^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: simd_shuffle index must be an array of `u32`, got `[f32; 2]` + --> $DIR/generic-shuffle.rs:30:31 + | +LL | let _: Simd = simd_shuffle(v, v, I2); + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0511`. diff --git a/src/test/ui/simd-intrinsic/simd-intrinsic-inlining-issue67557-ice.rs b/src/test/ui/simd/intrinsic/inlining-issue67557-ice.rs similarity index 100% rename from src/test/ui/simd-intrinsic/simd-intrinsic-inlining-issue67557-ice.rs rename to src/test/ui/simd/intrinsic/inlining-issue67557-ice.rs diff --git a/src/test/ui/simd-intrinsic/simd-intrinsic-inlining-issue67557.rs b/src/test/ui/simd/intrinsic/inlining-issue67557.rs similarity index 100% rename from src/test/ui/simd-intrinsic/simd-intrinsic-inlining-issue67557.rs rename to src/test/ui/simd/intrinsic/inlining-issue67557.rs diff --git a/src/test/ui/simd-intrinsic/issue-85855.rs b/src/test/ui/simd/intrinsic/issue-85855.rs similarity index 100% rename from src/test/ui/simd-intrinsic/issue-85855.rs rename to src/test/ui/simd/intrinsic/issue-85855.rs diff --git a/src/test/ui/simd-intrinsic/issue-85855.stderr b/src/test/ui/simd/intrinsic/issue-85855.stderr similarity index 100% rename from src/test/ui/simd-intrinsic/issue-85855.stderr rename to src/test/ui/simd/intrinsic/issue-85855.stderr diff --git a/src/test/ui/simd/issue-89193.rs b/src/test/ui/simd/issue-89193.rs new file mode 100644 index 0000000000..79c4e6a312 --- /dev/null +++ b/src/test/ui/simd/issue-89193.rs @@ -0,0 +1,51 @@ +// run-pass + +// Test that simd gather instructions on slice of usize don't cause crash +// See issue #89183 - https://github.com/rust-lang/rust/issues/89193 + +#![feature(repr_simd, platform_intrinsics)] +#![allow(non_camel_case_types)] + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +struct x4(pub T, pub T, pub T, pub T); + +extern "platform-intrinsic" { + fn simd_gather(x: T, y: U, z: V) -> T; +} + +fn main() { + let x: [usize; 4] = [10, 11, 12, 13]; + let default = x4(0_usize, 1, 2, 3); + let mask = x4(1_i32, 1, 1, 1); + let expected = x4(10_usize, 11, 12, 13); + + unsafe { + let pointer = &x[0] as *const usize; + let pointers = x4( + pointer.offset(0) as *const usize, + pointer.offset(1), + pointer.offset(2), + pointer.offset(3) + ); + let result = simd_gather(default, pointers, mask); + assert_eq!(result, expected); + } + + // and again for isize + let x: [isize; 4] = [10, 11, 12, 13]; + let default = x4(0_isize, 1, 2, 3); + let expected = x4(10_isize, 11, 12, 13); + + unsafe { + let pointer = &x[0] as *const isize; + let pointers = x4( + pointer.offset(0) as *const isize, + pointer.offset(1), + pointer.offset(2), + pointer.offset(3) + ); + let result = simd_gather(default, pointers, mask); + assert_eq!(result, expected); + } +} diff --git a/src/test/ui/simd/monomorphize-shuffle-index.rs b/src/test/ui/simd/monomorphize-shuffle-index.rs new file mode 100644 index 0000000000..2467baa08b --- /dev/null +++ b/src/test/ui/simd/monomorphize-shuffle-index.rs @@ -0,0 +1,40 @@ +//run-pass +#![feature(repr_simd, platform_intrinsics)] + +extern "platform-intrinsic" { + fn simd_shuffle(a: T, b: T, i: I) -> U; +} + +#[derive(Copy, Clone)] +#[repr(simd)] +struct Simd([T; N]); + +trait Shuffle { + const I: [u32; N]; + + unsafe fn shuffle(&self, a: Simd, b: Simd) -> Simd { + simd_shuffle(a, b, Self::I) + } +} + +fn main() { + struct I1; + impl Shuffle<4> for I1 { + const I: [u32; 4] = [0, 2, 4, 6]; + } + + struct I2; + impl Shuffle<2> for I2 { + const I: [u32; 2] = [1, 5]; + } + + let a = Simd::([0, 1, 2, 3]); + let b = Simd::([4, 5, 6, 7]); + unsafe { + let x: Simd = I1.shuffle(a, b); + assert_eq!(x.0, [0, 2, 4, 6]); + + let y: Simd = I2.shuffle(a, b); + assert_eq!(y.0, [1, 5]); + } +} diff --git a/src/test/ui/simd/shuffle-not-out-of-bounds.rs b/src/test/ui/simd/shuffle-not-out-of-bounds.rs index 8a533453e7..0dee3a0e86 100644 --- a/src/test/ui/simd/shuffle-not-out-of-bounds.rs +++ b/src/test/ui/simd/shuffle-not-out-of-bounds.rs @@ -6,148 +6,42 @@ #[repr(simd)] #[derive(Copy, Clone)] -struct u8x2(u8, u8); +struct u8x2([u8; 2]); #[repr(simd)] #[derive(Copy, Clone)] -struct u8x4(u8, u8, u8, u8); +struct u8x4([u8; 4]); #[repr(simd)] #[derive(Copy, Clone)] -struct u8x8(u8, u8, u8, u8, u8, u8, u8, u8); +struct u8x8([u8; 8]); #[repr(simd)] #[derive(Copy, Clone)] -struct u8x16( - u8, - u8, - u8, - u8, - u8, - u8, - u8, - u8, - u8, - u8, - u8, - u8, - u8, - u8, - u8, - u8, -); +struct u8x16([u8; 16]); #[repr(simd)] #[derive(Copy, Clone)] -struct u8x32( - u8, - u8, - u8, - u8, - u8, - u8, - u8, - u8, - u8, - u8, - u8, - u8, - u8, - u8, - u8, - u8, - u8, - u8, - u8, - u8, - u8, - u8, - u8, - u8, - u8, - u8, - u8, - u8, - u8, - u8, - u8, - u8, -); +struct u8x32([u8; 32]); #[repr(simd)] #[derive(Copy, Clone)] -struct u8x64( - u8, - u8, - u8, - u8, - u8, - u8, - u8, - u8, - u8, - u8, - u8, - u8, - u8, - u8, - u8, - u8, - u8, - u8, - u8, - u8, - u8, - u8, - u8, - u8, - u8, - u8, - u8, - u8, - u8, - u8, - u8, - u8, - u8, - u8, - u8, - u8, - u8, - u8, - u8, - u8, - u8, - u8, - u8, - u8, - u8, - u8, - u8, - u8, - u8, - u8, - u8, - u8, - u8, - u8, - u8, - u8, - u8, - u8, - u8, - u8, - u8, - u8, - u8, - u8, -); +struct u8x64([u8; 64]); + +extern "platform-intrinsic" { + pub fn simd_shuffle2(x: T, y: T, idx: [u32; 2]) -> U; + pub fn simd_shuffle4(x: T, y: T, idx: [u32; 4]) -> U; + pub fn simd_shuffle8(x: T, y: T, idx: [u32; 8]) -> U; + pub fn simd_shuffle16(x: T, y: T, idx: [u32; 16]) -> U; + pub fn simd_shuffle32(x: T, y: T, idx: [u32; 32]) -> U; + pub fn simd_shuffle64(x: T, y: T, idx: [u32; 64]) -> U; +} // Test vectors by lane size. Since LLVM does not distinguish between a shuffle // over two f32s and a shuffle over two u64s, or any other such combination, // it is not necessary to test every possible vector, only lane counts. macro_rules! test_shuffle_lanes { - ($n:literal, $x:ident, $y:ident, $t:tt) => { + ($n:literal, $x:ident, $y:ident) => { unsafe { let shuffle: $x = { const ARR: [u32; $n] = { @@ -155,11 +49,10 @@ macro_rules! test_shuffle_lanes { arr[0] = $n * 2; arr }; - extern "platform-intrinsic" { - pub fn $y(x: T, y: T, idx: [u32; $n]) -> U; - } - let vec1 = $x$t; - let vec2 = $x$t; + let mut n: u8 = $n; + let vals = [0; $n].map(|_| { n = n - 1; n }); + let vec1 = $x(vals); + let vec2 = $x(vals); $y(vec1, vec2, ARR) }; } @@ -175,17 +68,20 @@ macro_rules! test_shuffle_lanes { // And unfortunately, standard comments, as in the UI test harness, disappear in macros! fn main() { - test_shuffle_lanes!(2, u8x2, simd_shuffle2, (2, 1)); - test_shuffle_lanes!(4, u8x4, simd_shuffle4, (4, 3, 2, 1)); - test_shuffle_lanes!(8, u8x8, simd_shuffle8, (8, 7, 6, 5, 4, 3, 2, 1)); - test_shuffle_lanes!(16, u8x16, simd_shuffle16, - (16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1)); - test_shuffle_lanes!(32, u8x32, simd_shuffle32, - (32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, - 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1)); - test_shuffle_lanes!(64, u8x64, simd_shuffle64, - (64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, - 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, - 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, - 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1)); + test_shuffle_lanes!(2, u8x2, simd_shuffle2); + test_shuffle_lanes!(4, u8x4, simd_shuffle4); + test_shuffle_lanes!(8, u8x8, simd_shuffle8); + test_shuffle_lanes!(16, u8x16, simd_shuffle16); + test_shuffle_lanes!(32, u8x32, simd_shuffle32); + test_shuffle_lanes!(64, u8x64, simd_shuffle64); + + extern "platform-intrinsic" { + fn simd_shuffle(a: T, b: T, i: I) -> U; + } + let v = u8x2([0, 0]); + const I: [u32; 2] = [4, 4]; + unsafe { + let _: u8x2 = simd_shuffle(v, v, I); + //~^ ERROR invalid monomorphization of `simd_shuffle` intrinsic + } } diff --git a/src/test/ui/simd/shuffle-not-out-of-bounds.stderr b/src/test/ui/simd/shuffle-not-out-of-bounds.stderr index 07253a4ae4..415f04d933 100644 --- a/src/test/ui/simd/shuffle-not-out-of-bounds.stderr +++ b/src/test/ui/simd/shuffle-not-out-of-bounds.stderr @@ -1,76 +1,75 @@ error[E0511]: invalid monomorphization of `simd_shuffle2` intrinsic: shuffle index #0 is out of bounds (limit 4) - --> $DIR/shuffle-not-out-of-bounds.rs:163:21 + --> $DIR/shuffle-not-out-of-bounds.rs:56:21 | LL | $y(vec1, vec2, ARR) | ^^^^^^^^^^^^^^^^^^^ ... -LL | test_shuffle_lanes!(2, u8x2, simd_shuffle2, (2, 1)); - | ---------------------------------------------------- in this macro invocation +LL | test_shuffle_lanes!(2, u8x2, simd_shuffle2); + | ------------------------------------------- in this macro invocation | = note: this error originates in the macro `test_shuffle_lanes` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0511]: invalid monomorphization of `simd_shuffle4` intrinsic: shuffle index #0 is out of bounds (limit 8) - --> $DIR/shuffle-not-out-of-bounds.rs:163:21 + --> $DIR/shuffle-not-out-of-bounds.rs:56:21 | LL | $y(vec1, vec2, ARR) | ^^^^^^^^^^^^^^^^^^^ ... -LL | test_shuffle_lanes!(4, u8x4, simd_shuffle4, (4, 3, 2, 1)); - | ---------------------------------------------------------- in this macro invocation +LL | test_shuffle_lanes!(4, u8x4, simd_shuffle4); + | ------------------------------------------- in this macro invocation | = note: this error originates in the macro `test_shuffle_lanes` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0511]: invalid monomorphization of `simd_shuffle8` intrinsic: shuffle index #0 is out of bounds (limit 16) - --> $DIR/shuffle-not-out-of-bounds.rs:163:21 + --> $DIR/shuffle-not-out-of-bounds.rs:56:21 | LL | $y(vec1, vec2, ARR) | ^^^^^^^^^^^^^^^^^^^ ... -LL | test_shuffle_lanes!(8, u8x8, simd_shuffle8, (8, 7, 6, 5, 4, 3, 2, 1)); - | ---------------------------------------------------------------------- in this macro invocation +LL | test_shuffle_lanes!(8, u8x8, simd_shuffle8); + | ------------------------------------------- in this macro invocation | = note: this error originates in the macro `test_shuffle_lanes` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0511]: invalid monomorphization of `simd_shuffle16` intrinsic: shuffle index #0 is out of bounds (limit 32) - --> $DIR/shuffle-not-out-of-bounds.rs:163:21 + --> $DIR/shuffle-not-out-of-bounds.rs:56:21 | -LL | $y(vec1, vec2, ARR) - | ^^^^^^^^^^^^^^^^^^^ +LL | $y(vec1, vec2, ARR) + | ^^^^^^^^^^^^^^^^^^^ ... -LL | / test_shuffle_lanes!(16, u8x16, simd_shuffle16, -LL | | (16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1)); - | |_________________________________________________________________- in this macro invocation +LL | test_shuffle_lanes!(16, u8x16, simd_shuffle16); + | ---------------------------------------------- in this macro invocation | = note: this error originates in the macro `test_shuffle_lanes` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0511]: invalid monomorphization of `simd_shuffle32` intrinsic: shuffle index #0 is out of bounds (limit 64) - --> $DIR/shuffle-not-out-of-bounds.rs:163:21 + --> $DIR/shuffle-not-out-of-bounds.rs:56:21 | -LL | $y(vec1, vec2, ARR) - | ^^^^^^^^^^^^^^^^^^^ +LL | $y(vec1, vec2, ARR) + | ^^^^^^^^^^^^^^^^^^^ ... -LL | / test_shuffle_lanes!(32, u8x32, simd_shuffle32, -LL | | (32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, -LL | | 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1)); - | |_____________________________________________________________- in this macro invocation +LL | test_shuffle_lanes!(32, u8x32, simd_shuffle32); + | ---------------------------------------------- in this macro invocation | = note: this error originates in the macro `test_shuffle_lanes` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0511]: invalid monomorphization of `simd_shuffle64` intrinsic: shuffle index #0 is out of bounds (limit 128) - --> $DIR/shuffle-not-out-of-bounds.rs:163:21 + --> $DIR/shuffle-not-out-of-bounds.rs:56:21 | -LL | $y(vec1, vec2, ARR) - | ^^^^^^^^^^^^^^^^^^^ +LL | $y(vec1, vec2, ARR) + | ^^^^^^^^^^^^^^^^^^^ ... -LL | / test_shuffle_lanes!(64, u8x64, simd_shuffle64, -LL | | (64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, -LL | | 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, -LL | | 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, -LL | | 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1)); - | |_________________________________________________________________- in this macro invocation +LL | test_shuffle_lanes!(64, u8x64, simd_shuffle64); + | ---------------------------------------------- in this macro invocation | = note: this error originates in the macro `test_shuffle_lanes` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 6 previous errors +error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: shuffle index #0 is out of bounds (limit 4) + --> $DIR/shuffle-not-out-of-bounds.rs:84:23 + | +LL | let _: u8x2 = simd_shuffle(v, v, I); + | ^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 7 previous errors For more information about this error, try `rustc --explain E0511`. diff --git a/src/test/ui/simd/shuffle.rs b/src/test/ui/simd/shuffle.rs new file mode 100644 index 0000000000..3592adfdc6 --- /dev/null +++ b/src/test/ui/simd/shuffle.rs @@ -0,0 +1,24 @@ +//run-pass +#![feature(repr_simd, platform_intrinsics)] + +extern "platform-intrinsic" { + fn simd_shuffle(a: T, b: T, i: I) -> U; +} + +#[derive(Copy, Clone)] +#[repr(simd)] +struct Simd([T; N]); + +fn main() { + const I1: [u32; 4] = [0, 2, 4, 6]; + const I2: [u32; 2] = [1, 5]; + let a = Simd::([0, 1, 2, 3]); + let b = Simd::([4, 5, 6, 7]); + unsafe { + let x: Simd = simd_shuffle(a, b, I1); + assert_eq!(x.0, [0, 2, 4, 6]); + + let y: Simd = simd_shuffle(a, b, I2); + assert_eq!(y.0, [1, 5]); + } +} diff --git a/src/test/ui/simd/simd-size-align.rs b/src/test/ui/simd/size-align.rs similarity index 100% rename from src/test/ui/simd/simd-size-align.rs rename to src/test/ui/simd/size-align.rs diff --git a/src/test/ui/simd/simd-target-feature-mixup.rs b/src/test/ui/simd/target-feature-mixup.rs similarity index 100% rename from src/test/ui/simd/simd-target-feature-mixup.rs rename to src/test/ui/simd/target-feature-mixup.rs diff --git a/src/test/ui/simd/simd-type-generic-monomorphisation-empty.rs b/src/test/ui/simd/type-generic-monomorphisation-empty.rs similarity index 100% rename from src/test/ui/simd/simd-type-generic-monomorphisation-empty.rs rename to src/test/ui/simd/type-generic-monomorphisation-empty.rs diff --git a/src/test/ui/simd/simd-type-generic-monomorphisation-empty.stderr b/src/test/ui/simd/type-generic-monomorphisation-empty.stderr similarity index 100% rename from src/test/ui/simd/simd-type-generic-monomorphisation-empty.stderr rename to src/test/ui/simd/type-generic-monomorphisation-empty.stderr diff --git a/src/test/ui/simd/simd-type-generic-monomorphisation-extern-nonnull-ptr.rs b/src/test/ui/simd/type-generic-monomorphisation-extern-nonnull-ptr.rs similarity index 100% rename from src/test/ui/simd/simd-type-generic-monomorphisation-extern-nonnull-ptr.rs rename to src/test/ui/simd/type-generic-monomorphisation-extern-nonnull-ptr.rs diff --git a/src/test/ui/simd/simd-type-generic-monomorphisation-non-primitive.rs b/src/test/ui/simd/type-generic-monomorphisation-non-primitive.rs similarity index 100% rename from src/test/ui/simd/simd-type-generic-monomorphisation-non-primitive.rs rename to src/test/ui/simd/type-generic-monomorphisation-non-primitive.rs diff --git a/src/test/ui/simd/simd-type-generic-monomorphisation-non-primitive.stderr b/src/test/ui/simd/type-generic-monomorphisation-non-primitive.stderr similarity index 100% rename from src/test/ui/simd/simd-type-generic-monomorphisation-non-primitive.stderr rename to src/test/ui/simd/type-generic-monomorphisation-non-primitive.stderr diff --git a/src/test/ui/simd/simd-type-generic-monomorphisation-oversized.rs b/src/test/ui/simd/type-generic-monomorphisation-oversized.rs similarity index 100% rename from src/test/ui/simd/simd-type-generic-monomorphisation-oversized.rs rename to src/test/ui/simd/type-generic-monomorphisation-oversized.rs diff --git a/src/test/ui/simd/simd-type-generic-monomorphisation-oversized.stderr b/src/test/ui/simd/type-generic-monomorphisation-oversized.stderr similarity index 100% rename from src/test/ui/simd/simd-type-generic-monomorphisation-oversized.stderr rename to src/test/ui/simd/type-generic-monomorphisation-oversized.stderr diff --git a/src/test/ui/simd/simd-type-generic-monomorphisation-power-of-two.rs b/src/test/ui/simd/type-generic-monomorphisation-power-of-two.rs similarity index 100% rename from src/test/ui/simd/simd-type-generic-monomorphisation-power-of-two.rs rename to src/test/ui/simd/type-generic-monomorphisation-power-of-two.rs diff --git a/src/test/ui/simd/simd-type-generic-monomorphisation-wide-ptr.rs b/src/test/ui/simd/type-generic-monomorphisation-wide-ptr.rs similarity index 100% rename from src/test/ui/simd/simd-type-generic-monomorphisation-wide-ptr.rs rename to src/test/ui/simd/type-generic-monomorphisation-wide-ptr.rs diff --git a/src/test/ui/simd/simd-type-generic-monomorphisation-wide-ptr.stderr b/src/test/ui/simd/type-generic-monomorphisation-wide-ptr.stderr similarity index 100% rename from src/test/ui/simd/simd-type-generic-monomorphisation-wide-ptr.stderr rename to src/test/ui/simd/type-generic-monomorphisation-wide-ptr.stderr diff --git a/src/test/ui/simd/simd-type-generic-monomorphisation.rs b/src/test/ui/simd/type-generic-monomorphisation.rs similarity index 100% rename from src/test/ui/simd/simd-type-generic-monomorphisation.rs rename to src/test/ui/simd/type-generic-monomorphisation.rs diff --git a/src/test/ui/simd/simd-type-generic-monomorphisation.stderr b/src/test/ui/simd/type-generic-monomorphisation.stderr similarity index 100% rename from src/test/ui/simd/simd-type-generic-monomorphisation.stderr rename to src/test/ui/simd/type-generic-monomorphisation.stderr diff --git a/src/test/ui/simd/simd-type.rs b/src/test/ui/simd/type-len.rs similarity index 100% rename from src/test/ui/simd/simd-type.rs rename to src/test/ui/simd/type-len.rs diff --git a/src/test/ui/simd/simd-type.stderr b/src/test/ui/simd/type-len.stderr similarity index 84% rename from src/test/ui/simd/simd-type.stderr rename to src/test/ui/simd/type-len.stderr index 4e4a19ea32..f122d8bb0d 100644 --- a/src/test/ui/simd/simd-type.stderr +++ b/src/test/ui/simd/type-len.stderr @@ -1,35 +1,35 @@ error[E0075]: SIMD vector cannot be empty - --> $DIR/simd-type.rs:6:1 + --> $DIR/type-len.rs:6:1 | LL | struct empty; | ^^^^^^^^^^^^^ error[E0075]: SIMD vector cannot be empty - --> $DIR/simd-type.rs:9:1 + --> $DIR/type-len.rs:9:1 | LL | struct empty2([f32; 0]); | ^^^^^^^^^^^^^^^^^^^^^^^^ error[E0076]: SIMD vector should be homogeneous - --> $DIR/simd-type.rs:15:1 + --> $DIR/type-len.rs:15:1 | LL | struct i64f64(i64, f64); | ^^^^^^^^^^^^^^^^^^^^^^^^ SIMD elements must have the same type error[E0077]: SIMD vector element type should be a primitive scalar (integer/float/pointer) type - --> $DIR/simd-type.rs:20:1 + --> $DIR/type-len.rs:20:1 | LL | struct FooV(Foo, Foo); | ^^^^^^^^^^^^^^^^^^^^^^ error[E0077]: SIMD vector element type should be a primitive scalar (integer/float/pointer) type - --> $DIR/simd-type.rs:23:1 + --> $DIR/type-len.rs:23:1 | LL | struct FooV2([Foo; 2]); | ^^^^^^^^^^^^^^^^^^^^^^^ error[E0075]: SIMD vector cannot have more than 32768 elements - --> $DIR/simd-type.rs:26:1 + --> $DIR/type-len.rs:26:1 | LL | struct TooBig([f32; 65536]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/simd/simd-type-wide-ptr.rs b/src/test/ui/simd/type-wide-ptr.rs similarity index 100% rename from src/test/ui/simd/simd-type-wide-ptr.rs rename to src/test/ui/simd/type-wide-ptr.rs diff --git a/src/test/ui/simd/simd-type-wide-ptr.stderr b/src/test/ui/simd/type-wide-ptr.stderr similarity index 100% rename from src/test/ui/simd/simd-type-wide-ptr.stderr rename to src/test/ui/simd/type-wide-ptr.stderr diff --git a/src/test/ui/span/borrowck-borrow-overloaded-auto-deref-mut.stderr b/src/test/ui/span/borrowck-borrow-overloaded-auto-deref-mut.stderr index 8fceef64c8..e4ec9f8757 100644 --- a/src/test/ui/span/borrowck-borrow-overloaded-auto-deref-mut.stderr +++ b/src/test/ui/span/borrowck-borrow-overloaded-auto-deref-mut.stderr @@ -56,7 +56,7 @@ error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable LL | fn deref_mut_method1(x: Own) { | - help: consider changing this to be mutable: `mut x` LL | x.set(0, 0); - | ^ cannot borrow as mutable + | ^^^^^^^^^^^ cannot borrow as mutable error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:121:5 @@ -64,7 +64,7 @@ error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference LL | fn deref_extend_mut_method1(x: &Own) -> &mut isize { | ----------- help: consider changing this to be a mutable reference: `&mut Own` LL | x.y_mut() - | ^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | ^^^^^^^^^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:129:6 @@ -72,7 +72,7 @@ error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable LL | fn assign_method1<'a>(x: Own) { | - help: consider changing this to be mutable: `mut x` LL | *x.y_mut() = 3; - | ^ cannot borrow as mutable + | ^^^^^^^^^ cannot borrow as mutable error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:133:6 @@ -80,7 +80,7 @@ error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference LL | fn assign_method2<'a>(x: &'a Own) { | -------------- help: consider changing this to be a mutable reference: `&'a mut Own` LL | *x.y_mut() = 3; - | ^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | ^^^^^^^^^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable error: aborting due to 10 previous errors diff --git a/src/test/ui/span/borrowck-call-is-borrow-issue-12224.stderr b/src/test/ui/span/borrowck-call-is-borrow-issue-12224.stderr index ab1fa2a4d8..b4693b7242 100644 --- a/src/test/ui/span/borrowck-call-is-borrow-issue-12224.stderr +++ b/src/test/ui/span/borrowck-call-is-borrow-issue-12224.stderr @@ -24,16 +24,22 @@ error[E0596]: cannot borrow `f.f` as mutable, as it is behind a `&` reference LL | fn test4(f: &Test) { | ----- help: consider changing this to be a mutable reference: `&mut Test<'_>` LL | f.f.call_mut(()) - | ^^^ `f` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | ^^^^^^^^^^^^^^^^ `f` is a `&` reference, so the data it refers to cannot be borrowed as mutable error[E0507]: cannot move out of `f`, a captured variable in an `FnMut` closure --> $DIR/borrowck-call-is-borrow-issue-12224.rs:57:13 | -LL | let mut f = move |g: Box, b: isize| { - | ----- captured outer variable +LL | let mut f = move |g: Box, b: isize| { + | ----- captured outer variable ... -LL | foo(f); - | ^ move occurs because `f` has type `[closure@$DIR/borrowck-call-is-borrow-issue-12224.rs:52:17: 54:6]`, which does not implement the `Copy` trait +LL | f(Box::new(|a| { + | ________________- +LL | | +LL | | foo(f); + | | ^ move occurs because `f` has type `[closure@$DIR/borrowck-call-is-borrow-issue-12224.rs:52:17: 54:6]`, which does not implement the `Copy` trait +LL | | +LL | | }), 3); + | |_____- captured by this `FnMut` closure error[E0505]: cannot move out of `f` because it is borrowed --> $DIR/borrowck-call-is-borrow-issue-12224.rs:55:16 diff --git a/src/test/ui/span/borrowck-call-method-from-mut-aliasable.stderr b/src/test/ui/span/borrowck-call-method-from-mut-aliasable.stderr index 6b5e0779e5..1864f5de10 100644 --- a/src/test/ui/span/borrowck-call-method-from-mut-aliasable.stderr +++ b/src/test/ui/span/borrowck-call-method-from-mut-aliasable.stderr @@ -5,7 +5,7 @@ LL | fn b(x: &Foo) { | ---- help: consider changing this to be a mutable reference: `&mut Foo` LL | x.f(); LL | x.h(); - | ^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | ^^^^^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable error: aborting due to previous error diff --git a/src/test/ui/span/borrowck-fn-in-const-b.stderr b/src/test/ui/span/borrowck-fn-in-const-b.stderr index 8949a10481..1f5d8bd32b 100644 --- a/src/test/ui/span/borrowck-fn-in-const-b.stderr +++ b/src/test/ui/span/borrowck-fn-in-const-b.stderr @@ -4,7 +4,7 @@ error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference LL | fn broken(x: &Vec) { | ------------ help: consider changing this to be a mutable reference: `&mut Vec` LL | x.push(format!("this is broken")); - | ^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable error: aborting due to previous error diff --git a/src/test/ui/span/borrowck-let-suggestion-suffixes.stderr b/src/test/ui/span/borrowck-let-suggestion-suffixes.stderr index 7ba909d208..7c5caba6ea 100644 --- a/src/test/ui/span/borrowck-let-suggestion-suffixes.stderr +++ b/src/test/ui/span/borrowck-let-suggestion-suffixes.stderr @@ -32,7 +32,7 @@ LL | v4.push(&id('y')); | creates a temporary which is freed while still in use ... LL | v4.use_ref(); - | -- borrow later used here + | ------------ borrow later used here | = note: consider using a `let` binding to create a longer lived value diff --git a/src/test/ui/span/borrowck-object-mutability.stderr b/src/test/ui/span/borrowck-object-mutability.stderr index fe6d05c588..cc43f6d092 100644 --- a/src/test/ui/span/borrowck-object-mutability.stderr +++ b/src/test/ui/span/borrowck-object-mutability.stderr @@ -5,7 +5,7 @@ LL | fn borrowed_receiver(x: &dyn Foo) { | -------- help: consider changing this to be a mutable reference: `&mut dyn Foo` LL | x.borrowed(); LL | x.borrowed_mut(); - | ^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | ^^^^^^^^^^^^^^^^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable error[E0596]: cannot borrow `*x` as mutable, as `x` is not declared as mutable --> $DIR/borrowck-object-mutability.rs:18:5 @@ -14,7 +14,7 @@ LL | fn owned_receiver(x: Box) { | - help: consider changing this to be mutable: `mut x` LL | x.borrowed(); LL | x.borrowed_mut(); - | ^ cannot borrow as mutable + | ^^^^^^^^^^^^^^^^ cannot borrow as mutable error: aborting due to 2 previous errors diff --git a/src/test/ui/span/coerce-suggestions.rs b/src/test/ui/span/coerce-suggestions.rs index c461f825d9..7920ae0b26 100644 --- a/src/test/ui/span/coerce-suggestions.rs +++ b/src/test/ui/span/coerce-suggestions.rs @@ -1,8 +1,8 @@ -#![feature(box_syntax)] - fn test(_x: &mut String) {} + fn test2(_x: &mut i32) {} + fn main() { let x: usize = String::new(); //~^ ERROR E0308 @@ -14,7 +14,7 @@ fn main() { test2(&y); //~^ ERROR E0308 let f; - f = box f; + f = Box::new(f); //~^ ERROR E0308 let s = &mut String::new(); diff --git a/src/test/ui/span/coerce-suggestions.stderr b/src/test/ui/span/coerce-suggestions.stderr index 2487684c1d..74caae8645 100644 --- a/src/test/ui/span/coerce-suggestions.stderr +++ b/src/test/ui/span/coerce-suggestions.stderr @@ -37,13 +37,10 @@ LL | test2(&y); error[E0308]: mismatched types --> $DIR/coerce-suggestions.rs:17:9 | -LL | f = box f; - | ^^^^^ cyclic type of infinite size - | -help: try using a conversion method - | -LL | f = (box f).to_string(); - | + +++++++++++++ +LL | f = Box::new(f); + | ^^^^^^^^^^^- help: try using a conversion method: `.to_string()` + | | + | cyclic type of infinite size error[E0308]: mismatched types --> $DIR/coerce-suggestions.rs:21:9 diff --git a/src/test/ui/span/destructor-restrictions.stderr b/src/test/ui/span/destructor-restrictions.stderr index 8f75c388f6..53c9404620 100644 --- a/src/test/ui/span/destructor-restrictions.stderr +++ b/src/test/ui/span/destructor-restrictions.stderr @@ -2,7 +2,7 @@ error[E0597]: `*a` does not live long enough --> $DIR/destructor-restrictions.rs:8:10 | LL | *a.borrow() + 1 - | ^--------- + | ^^^^^^^^^^ | | | borrowed value does not live long enough | a temporary with access to the borrow is created here ... diff --git a/src/test/ui/span/issue-11925.rs b/src/test/ui/span/issue-11925.rs index 0f6472b05f..d9c08fbdd0 100644 --- a/src/test/ui/span/issue-11925.rs +++ b/src/test/ui/span/issue-11925.rs @@ -1,10 +1,10 @@ -#![feature(box_syntax, unboxed_closures)] +#![feature(unboxed_closures)] fn to_fn_once>(f: F) -> F { f } fn main() { let r = { - let x: Box<_> = box 42; + let x: Box<_> = Box::new(42); let f = to_fn_once(move|| &x); //~ ERROR cannot return reference to local data `x` f() }; diff --git a/src/test/ui/span/issue-23338-locals-die-before-temps-of-body.stderr b/src/test/ui/span/issue-23338-locals-die-before-temps-of-body.stderr index 8d4709d660..3c2022748f 100644 --- a/src/test/ui/span/issue-23338-locals-die-before-temps-of-body.stderr +++ b/src/test/ui/span/issue-23338-locals-die-before-temps-of-body.stderr @@ -2,7 +2,7 @@ error[E0597]: `y` does not live long enough --> $DIR/issue-23338-locals-die-before-temps-of-body.rs:10:5 | LL | y.borrow().clone() - | ^--------- + | ^^^^^^^^^^ | | | borrowed value does not live long enough | a temporary with access to the borrow is created here ... @@ -23,7 +23,7 @@ error[E0597]: `y` does not live long enough --> $DIR/issue-23338-locals-die-before-temps-of-body.rs:17:9 | LL | y.borrow().clone() - | ^--------- + | ^^^^^^^^^^ | | | borrowed value does not live long enough | a temporary with access to the borrow is created here ... diff --git a/src/test/ui/span/issue-34264.stderr b/src/test/ui/span/issue-34264.stderr index da0a3c8b47..8d26ca4ac7 100644 --- a/src/test/ui/span/issue-34264.stderr +++ b/src/test/ui/span/issue-34264.stderr @@ -8,11 +8,11 @@ LL | fn foo(Option, String) {} help: if this is a `self` type, give it a parameter name | LL | fn foo(self: Option, String) {} - | ~~~~~~~~~~~~ + | +++++ help: if this is a type, explicitly ignore the parameter name | LL | fn foo(_: Option, String) {} - | ~~~~~~~~~ + | ++ error: expected one of `:`, `@`, or `|`, found `)` --> $DIR/issue-34264.rs:1:27 @@ -24,11 +24,11 @@ LL | fn foo(Option, String) {} help: if this is a parameter name, give it a type | LL | fn foo(Option, String: TypeName) {} - | ~~~~~~~~~~~~~~~~ + | ++++++++++ help: if this is a type, explicitly ignore the parameter name | LL | fn foo(Option, _: String) {} - | ~~~~~~~~~ + | ++ error: expected one of `:`, `@`, or `|`, found `,` --> $DIR/issue-34264.rs:3:9 @@ -40,15 +40,15 @@ LL | fn bar(x, y: usize) {} help: if this is a `self` type, give it a parameter name | LL | fn bar(self: x, y: usize) {} - | ~~~~~~~ + | +++++ help: if this is a parameter name, give it a type | LL | fn bar(x: TypeName, y: usize) {} - | ~~~~~~~~~~~ + | ++++++++++ help: if this is a type, explicitly ignore the parameter name | LL | fn bar(_: x, y: usize) {} - | ~~~~ + | ++ error[E0061]: this function takes 2 arguments but 3 arguments were supplied --> $DIR/issue-34264.rs:7:5 diff --git a/src/test/ui/span/issue-36537.stderr b/src/test/ui/span/issue-36537.stderr index 0939584380..79a0ebaeb8 100644 --- a/src/test/ui/span/issue-36537.stderr +++ b/src/test/ui/span/issue-36537.stderr @@ -7,7 +7,7 @@ LL | p = &a; LL | } | - `a` dropped here while still borrowed LL | p.use_ref(); - | - borrow later used here + | ----------- borrow later used here error: aborting due to previous error diff --git a/src/test/ui/span/issue-39018.stderr b/src/test/ui/span/issue-39018.stderr index c5a0448e79..92e86bf5d6 100644 --- a/src/test/ui/span/issue-39018.stderr +++ b/src/test/ui/span/issue-39018.stderr @@ -20,7 +20,22 @@ LL | let y = World::Hello + World::Goodbye; | | | World | - = note: an implementation of `std::ops::Add` might be missing for `World` +note: an implementation of `Add<_>` might be missing for `World` + --> $DIR/issue-39018.rs:15:1 + | +LL | enum World { + | ^^^^^^^^^^ must implement `Add<_>` +note: the following trait must be implemented + --> $SRC_DIR/core/src/ops/arith.rs:LL:COL + | +LL | / pub trait Add { +LL | | /// The resulting type after applying the `+` operator. +LL | | #[stable(feature = "rust1", since = "1.0.0")] +LL | | type Output; +... | +LL | | fn add(self, rhs: Rhs) -> Self::Output; +LL | | } + | |_^ error[E0369]: cannot add `String` to `&str` --> $DIR/issue-39018.rs:11:22 diff --git a/src/test/ui/span/issue-40157.stderr b/src/test/ui/span/issue-40157.stderr index 0b365c3f7b..57f80214a4 100644 --- a/src/test/ui/span/issue-40157.stderr +++ b/src/test/ui/span/issue-40157.stderr @@ -2,7 +2,7 @@ error[E0597]: `foo` does not live long enough --> $DIR/issue-40157.rs:2:53 | LL | {println!("{:?}", match { let foo = vec![1, 2]; foo.get(1) } { x => x });} - | ------------------------^^^--------- + | ------------------------^^^^^^^^^^-- | | | | | | | `foo` dropped here while still borrowed | | borrowed value does not live long enough diff --git a/src/test/ui/span/issue-7575.stderr b/src/test/ui/span/issue-7575.stderr index 288c1042a2..783f5aca41 100644 --- a/src/test/ui/span/issue-7575.stderr +++ b/src/test/ui/span/issue-7575.stderr @@ -27,16 +27,16 @@ LL | fn f9(_: usize) -> usize; candidate #3: `UnusedTrait` help: disambiguate the associated function for candidate #1 | -LL | u.f8(42) + CtxtFn::f9(u, 342) + m.fff(42) - | ~~~~~~~~~~~~~~~~~~ +LL | u.f8(42) + ::f9(u, 342) + m.fff(42) + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ help: disambiguate the associated function for candidate #2 | -LL | u.f8(42) + OtherTrait::f9(u, 342) + m.fff(42) - | ~~~~~~~~~~~~~~~~~~~~~~ +LL | u.f8(42) + ::f9(u, 342) + m.fff(42) + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ help: disambiguate the associated function for candidate #3 | -LL | u.f8(42) + UnusedTrait::f9(u, 342) + m.fff(42) - | ~~~~~~~~~~~~~~~~~~~~~~~ +LL | u.f8(42) + ::f9(u, 342) + m.fff(42) + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error[E0599]: no method named `fff` found for struct `Myisize` in the current scope --> $DIR/issue-7575.rs:62:30 @@ -72,7 +72,7 @@ LL | fn is_str() -> bool { = help: items from traits can only be used if the type parameter is bounded by the trait help: disambiguate the associated function for the candidate | -LL | ManyImplTrait::is_str(t) +LL | ::is_str(t) | error: aborting due to 3 previous errors diff --git a/src/test/ui/span/macro-span-replacement.stderr b/src/test/ui/span/macro-span-replacement.stderr index afdf036f83..d08b24e956 100644 --- a/src/test/ui/span/macro-span-replacement.stderr +++ b/src/test/ui/span/macro-span-replacement.stderr @@ -5,7 +5,7 @@ LL | $b $a; | ^ ... LL | m!(S struct); - | ------------- in this macro invocation + | ------------ in this macro invocation | note: the lint level is defined here --> $DIR/macro-span-replacement.rs:3:9 diff --git a/src/test/ui/span/mut-arg-hint.stderr b/src/test/ui/span/mut-arg-hint.stderr index e04e4cbdab..8a7c504f00 100644 --- a/src/test/ui/span/mut-arg-hint.stderr +++ b/src/test/ui/span/mut-arg-hint.stderr @@ -4,7 +4,7 @@ error[E0596]: cannot borrow `*a` as mutable, as it is behind a `&` reference LL | fn foo(mut a: &String) { | ------- help: consider changing this to be a mutable reference: `&mut String` LL | a.push_str("bar"); - | ^ `a` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | ^^^^^^^^^^^^^^^^^ `a` is a `&` reference, so the data it refers to cannot be borrowed as mutable error[E0596]: cannot borrow `*a` as mutable, as it is behind a `&` reference --> $DIR/mut-arg-hint.rs:8:5 @@ -12,7 +12,7 @@ error[E0596]: cannot borrow `*a` as mutable, as it is behind a `&` reference LL | pub fn foo<'a>(mut a: &'a String) { | ---------- help: consider changing this to be a mutable reference: `&'a mut String` LL | a.push_str("foo"); - | ^ `a` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | ^^^^^^^^^^^^^^^^^ `a` is a `&` reference, so the data it refers to cannot be borrowed as mutable error[E0596]: cannot borrow `*a` as mutable, as it is behind a `&` reference --> $DIR/mut-arg-hint.rs:15:9 @@ -20,7 +20,7 @@ error[E0596]: cannot borrow `*a` as mutable, as it is behind a `&` reference LL | pub fn foo(mut a: &String) { | ------- help: consider changing this to be a mutable reference: `&mut String` LL | a.push_str("foo"); - | ^ `a` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | ^^^^^^^^^^^^^^^^^ `a` is a `&` reference, so the data it refers to cannot be borrowed as mutable error: aborting due to 3 previous errors diff --git a/src/test/ui/span/mut-ptr-cant-outlive-ref.stderr b/src/test/ui/span/mut-ptr-cant-outlive-ref.stderr index 21b29464df..4d976a7bbf 100644 --- a/src/test/ui/span/mut-ptr-cant-outlive-ref.stderr +++ b/src/test/ui/span/mut-ptr-cant-outlive-ref.stderr @@ -7,7 +7,7 @@ LL | } | - `b` dropped here while still borrowed LL | LL | p.use_ref(); - | - borrow later used here + | ----------- borrow later used here error: aborting due to previous error diff --git a/src/test/ui/span/regionck-unboxed-closure-lifetimes.stderr b/src/test/ui/span/regionck-unboxed-closure-lifetimes.stderr index 8e9cd59515..0b985de609 100644 --- a/src/test/ui/span/regionck-unboxed-closure-lifetimes.stderr +++ b/src/test/ui/span/regionck-unboxed-closure-lifetimes.stderr @@ -7,7 +7,7 @@ LL | let c_ref = &c; LL | } | - `c` dropped here while still borrowed LL | f.use_mut(); - | - borrow later used here + | ----------- borrow later used here error: aborting due to previous error diff --git a/src/test/ui/span/regions-close-over-borrowed-ref-in-obj.rs b/src/test/ui/span/regions-close-over-borrowed-ref-in-obj.rs index e34f84683b..16b4cc2586 100644 --- a/src/test/ui/span/regions-close-over-borrowed-ref-in-obj.rs +++ b/src/test/ui/span/regions-close-over-borrowed-ref-in-obj.rs @@ -1,5 +1,3 @@ -#![feature(box_syntax)] - fn id(x: T) -> T { x } trait Foo { } @@ -7,10 +5,12 @@ trait Foo { } impl<'a> Foo for &'a isize { } fn main() { + let blah; + { let ss: &isize = &id(1); //~^ ERROR temporary value dropped while borrowed - blah = box ss as Box; + blah = Box::new(ss) as Box; } } diff --git a/src/test/ui/span/regions-close-over-type-parameter-2.rs b/src/test/ui/span/regions-close-over-type-parameter-2.rs index 29083154b8..aca3972cb6 100644 --- a/src/test/ui/span/regions-close-over-type-parameter-2.rs +++ b/src/test/ui/span/regions-close-over-type-parameter-2.rs @@ -1,5 +1,3 @@ -#![feature(box_syntax)] - // Test for what happens when a type parameter `A` is closed over into // an object. This should yield errors unless `A` (and the object) // both have suitable bounds. @@ -7,14 +5,16 @@ trait Foo { fn get(&self); } impl Foo for A { - fn get(&self) { } + fn get(&self) { + } } fn repeater3<'a,A:'a>(v: A) -> Box { - box v as Box + Box::new(v) as Box } fn main() { + // Error results because the type of is inferred to be // ~Repeat<&'blk isize> where blk is the lifetime of the block below. diff --git a/src/test/ui/span/regions-escape-loop-via-vec.stderr b/src/test/ui/span/regions-escape-loop-via-vec.stderr index b47250db72..2b64930773 100644 --- a/src/test/ui/span/regions-escape-loop-via-vec.stderr +++ b/src/test/ui/span/regions-escape-loop-via-vec.stderr @@ -7,7 +7,7 @@ LL | while x < 10 { | ^ use of borrowed `x` LL | let mut z = x; LL | _y.push(&mut z); - | -- borrow later used here + | --------------- borrow later used here error[E0503]: cannot use `x` because it was mutably borrowed --> $DIR/regions-escape-loop-via-vec.rs:6:21 @@ -18,14 +18,15 @@ LL | while x < 10 { LL | let mut z = x; | ^ use of borrowed `x` LL | _y.push(&mut z); - | -- borrow later used here + | --------------- borrow later used here error[E0597]: `z` does not live long enough --> $DIR/regions-escape-loop-via-vec.rs:7:17 | LL | _y.push(&mut z); - | -- ^^^^^^ borrowed value does not live long enough - | | + | --------^^^^^^- + | | | + | | borrowed value does not live long enough | borrow later used here ... LL | } @@ -38,7 +39,7 @@ LL | let mut _y = vec![&mut x]; | ------ borrow of `x` occurs here ... LL | _y.push(&mut z); - | -- borrow later used here + | --------------- borrow later used here LL | LL | x += 1; | ^^^^^^ use of borrowed `x` diff --git a/src/test/ui/span/send-is-not-static-std-sync.stderr b/src/test/ui/span/send-is-not-static-std-sync.stderr index 81de8c2990..5d493a3e4e 100644 --- a/src/test/ui/span/send-is-not-static-std-sync.stderr +++ b/src/test/ui/span/send-is-not-static-std-sync.stderr @@ -7,7 +7,7 @@ LL | drop(y); | ^ move out of `y` occurs here ... LL | *lock.lock().unwrap() = &z; - | ---- borrow later used here + | ----------- borrow later used here error[E0597]: `z` does not live long enough --> $DIR/send-is-not-static-std-sync.rs:16:33 @@ -18,7 +18,7 @@ LL | } | - `z` dropped here while still borrowed LL | LL | lock.use_ref(); // (Mutex is #[may_dangle] so its dtor does not use `z` => needs explicit use) - | ---- borrow later used here + | -------------- borrow later used here error[E0505]: cannot move out of `y` because it is borrowed --> $DIR/send-is-not-static-std-sync.rs:27:10 @@ -29,7 +29,7 @@ LL | drop(y); | ^ move out of `y` occurs here ... LL | *lock.write().unwrap() = &z; - | ---- borrow later used here + | ------------ borrow later used here error[E0597]: `z` does not live long enough --> $DIR/send-is-not-static-std-sync.rs:30:34 @@ -40,7 +40,7 @@ LL | } | - `z` dropped here while still borrowed LL | LL | lock.use_ref(); // (RwLock is #[may_dangle] so its dtor does not use `z` => needs explicit use) - | ---- borrow later used here + | -------------- borrow later used here error[E0505]: cannot move out of `y` because it is borrowed --> $DIR/send-is-not-static-std-sync.rs:43:10 @@ -51,7 +51,7 @@ LL | drop(y); | ^ move out of `y` occurs here ... LL | tx.send(&z).unwrap(); - | -- borrow later used here + | ----------- borrow later used here error[E0597]: `z` does not live long enough --> $DIR/send-is-not-static-std-sync.rs:46:17 diff --git a/src/test/ui/span/slice-borrow.stderr b/src/test/ui/span/slice-borrow.stderr index 62a4a6009d..27df25be3f 100644 --- a/src/test/ui/span/slice-borrow.stderr +++ b/src/test/ui/span/slice-borrow.stderr @@ -7,7 +7,7 @@ LL | let x: &[isize] = &vec![1, 2, 3, 4, 5]; LL | } | - temporary value is freed at the end of this statement LL | y.use_ref(); - | - borrow later used here + | ----------- borrow later used here | = note: consider using a `let` binding to create a longer lived value = note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/span/transitive-dep-span.stderr b/src/test/ui/span/transitive-dep-span.stderr index 1787b0ee19..2b3dfc5c13 100644 --- a/src/test/ui/span/transitive-dep-span.stderr +++ b/src/test/ui/span/transitive-dep-span.stderr @@ -10,7 +10,7 @@ LL | | } ::: $DIR/transitive-dep-span.rs:13:1 | LL | transitive_dep_two::parse_error!(); - | ----------------------------------- + | ---------------------------------- | | | in this macro invocation | in this macro invocation diff --git a/src/test/ui/specialization/README-rpass.md b/src/test/ui/specialization/README-rpass.md index 1373a2cf81..c1486ce1ee 100644 --- a/src/test/ui/specialization/README-rpass.md +++ b/src/test/ui/specialization/README-rpass.md @@ -8,7 +8,7 @@ Tests that specialization is working correctly: - Specialization via concrete types vs unknown types - In top level of the trait reference - Embedded within another type (`Vec` vs `Vec`) - - [Specialization based on super trait relationships](specialization-super-traits.rs) + - [Specialization based on super trait relationships](specialization-supertraits.rs) - [On assoc fns](specialization-assoc-fns.rs) - [Ensure that impl order doesn't matter](specialization-out-of-order.rs) 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 16ffc661fe..ce981bc009 100644 --- a/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr +++ b/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr @@ -22,6 +22,14 @@ LL | println!("{}", MyStruct.foo_one()); | = note: the following trait bounds were not satisfied: `MyStruct: Foo` +note: the following trait must be implemented + --> $DIR/specialization-trait-not-implemented.rs:7:1 + | +LL | / trait Foo { +LL | | fn foo_one(&self) -> &'static str; +LL | | fn foo_two(&self) -> &'static str; +LL | | } + | |_^ = help: items from traits can only be used if the trait is implemented and in scope note: `Foo` defines an item `foo_one`, perhaps you need to implement it --> $DIR/specialization-trait-not-implemented.rs:7:1 diff --git a/src/test/ui/issues/issue-35376.rs b/src/test/ui/specialization/issue-35376.rs similarity index 100% rename from src/test/ui/issues/issue-35376.rs rename to src/test/ui/specialization/issue-35376.rs diff --git a/src/test/ui/issues/issue-35376.stderr b/src/test/ui/specialization/issue-35376.stderr similarity index 100% rename from src/test/ui/issues/issue-35376.stderr rename to src/test/ui/specialization/issue-35376.stderr diff --git a/src/test/ui/specialization/min_specialization/spec-marker-supertraits.rs b/src/test/ui/specialization/min_specialization/spec-marker-supertraits.rs new file mode 100644 index 0000000000..3bb2480e9e --- /dev/null +++ b/src/test/ui/specialization/min_specialization/spec-marker-supertraits.rs @@ -0,0 +1,29 @@ +// Check that supertraits cannot be used to work around min_specialization +// limitations. + +#![feature(min_specialization)] +#![feature(rustc_attrs)] + +trait HasMethod { + fn method(&self); +} + +#[rustc_unsafe_specialization_marker] +trait Marker: HasMethod {} + +trait Spec { + fn spec_me(&self); +} + +impl Spec for T { + default fn spec_me(&self) {} +} + +impl Spec for T { + //~^ ERROR cannot specialize on trait `HasMethod` + fn spec_me(&self) { + self.method(); + } +} + +fn main() {} diff --git a/src/test/ui/specialization/min_specialization/spec-marker-supertraits.stderr b/src/test/ui/specialization/min_specialization/spec-marker-supertraits.stderr new file mode 100644 index 0000000000..964109dd10 --- /dev/null +++ b/src/test/ui/specialization/min_specialization/spec-marker-supertraits.stderr @@ -0,0 +1,13 @@ +error: cannot specialize on trait `HasMethod` + --> $DIR/spec-marker-supertraits.rs:22:1 + | +LL | / impl Spec for T { +LL | | +LL | | fn spec_me(&self) { +LL | | self.method(); +LL | | } +LL | | } + | |_^ + +error: aborting due to previous error + diff --git a/src/test/ui/specialization/specialization-super-traits.rs b/src/test/ui/specialization/specialization-supertraits.rs similarity index 100% rename from src/test/ui/specialization/specialization-super-traits.rs rename to src/test/ui/specialization/specialization-supertraits.rs diff --git a/src/test/ui/specialization/specialization-super-traits.stderr b/src/test/ui/specialization/specialization-supertraits.stderr similarity index 90% rename from src/test/ui/specialization/specialization-super-traits.stderr rename to src/test/ui/specialization/specialization-supertraits.stderr index 165703d636..d32e47a24c 100644 --- a/src/test/ui/specialization/specialization-super-traits.stderr +++ b/src/test/ui/specialization/specialization-supertraits.stderr @@ -1,5 +1,5 @@ warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/specialization-super-traits.rs:3:12 + --> $DIR/specialization-supertraits.rs:3:12 | LL | #![feature(specialization)] | ^^^^^^^^^^^^^^ diff --git a/src/test/ui/issues/issue-34194.rs b/src/test/ui/static/issue-34194.rs similarity index 100% rename from src/test/ui/issues/issue-34194.rs rename to src/test/ui/static/issue-34194.rs diff --git a/src/test/ui/static/static-lifetime.stderr b/src/test/ui/static/static-lifetime.stderr index bda325dc01..4af3370c79 100644 --- a/src/test/ui/static/static-lifetime.stderr +++ b/src/test/ui/static/static-lifetime.stderr @@ -4,7 +4,7 @@ error[E0478]: lifetime bound not satisfied LL | impl<'a, A: Clone> Arbitrary for ::std::borrow::Cow<'a, A> {} | ^^^^^^^^^ | -note: lifetime parameter instantiated with the lifetime `'a` as defined on the impl at 3:6 +note: lifetime parameter instantiated with the lifetime `'a` as defined here --> $DIR/static-lifetime.rs:3:6 | LL | impl<'a, A: Clone> Arbitrary for ::std::borrow::Cow<'a, A> {} diff --git a/src/test/ui/static/static-region-bound.rs b/src/test/ui/static/static-region-bound.rs index f133133b33..d70706e576 100644 --- a/src/test/ui/static/static-region-bound.rs +++ b/src/test/ui/static/static-region-bound.rs @@ -1,12 +1,12 @@ -#![feature(box_syntax)] - fn id(x: T) -> T { x } fn f(_: T) {} fn main() { - let x: Box<_> = box 3; + + let x: Box<_> = Box::new(3); f(x); + let x = &id(3); //~ ERROR temporary value dropped while borrowed f(x); } diff --git a/src/test/ui/str/str-idx.stderr b/src/test/ui/str/str-idx.stderr index f323ba03c0..47bd6f6bfa 100644 --- a/src/test/ui/str/str-idx.stderr +++ b/src/test/ui/str/str-idx.stderr @@ -13,7 +13,9 @@ error[E0277]: the type `str` cannot be indexed by `{integer}` --> $DIR/str-idx.rs:4:19 | LL | let _ = s.get(4); - | ^ string indices are ranges of `usize` + | --- ^ string indices are ranges of `usize` + | | + | required by a bound introduced by this call | = help: the trait `SliceIndex` is not implemented for `{integer}` = note: you can use `.chars().nth()` or `.bytes().nth()` @@ -23,7 +25,9 @@ error[E0277]: the type `str` cannot be indexed by `{integer}` --> $DIR/str-idx.rs:5:29 | LL | let _ = s.get_unchecked(4); - | ^ string indices are ranges of `usize` + | ------------- ^ string indices are ranges of `usize` + | | + | required by a bound introduced by this call | = help: the trait `SliceIndex` is not implemented for `{integer}` = note: you can use `.chars().nth()` or `.bytes().nth()` diff --git a/src/test/ui/str/str-mut-idx.stderr b/src/test/ui/str/str-mut-idx.stderr index 3e49c8394a..ab647c75cf 100644 --- a/src/test/ui/str/str-mut-idx.stderr +++ b/src/test/ui/str/str-mut-idx.stderr @@ -37,7 +37,9 @@ error[E0277]: the type `str` cannot be indexed by `{integer}` --> $DIR/str-mut-idx.rs:9:15 | LL | s.get_mut(1); - | ^ string indices are ranges of `usize` + | ------- ^ string indices are ranges of `usize` + | | + | required by a bound introduced by this call | = help: the trait `SliceIndex` is not implemented for `{integer}` = note: you can use `.chars().nth()` or `.bytes().nth()` @@ -47,7 +49,9 @@ error[E0277]: the type `str` cannot be indexed by `{integer}` --> $DIR/str-mut-idx.rs:11:25 | LL | s.get_unchecked_mut(1); - | ^ string indices are ranges of `usize` + | ----------------- ^ string indices are ranges of `usize` + | | + | required by a bound introduced by this call | = help: the trait `SliceIndex` is not implemented for `{integer}` = note: you can use `.chars().nth()` or `.bytes().nth()` diff --git a/src/test/ui/structs-enums/class-cast-to-trait-cross-crate-2.rs b/src/test/ui/structs-enums/class-cast-to-trait-cross-crate-2.rs index bf1ba8a643..f870096fdd 100644 --- a/src/test/ui/structs-enums/class-cast-to-trait-cross-crate-2.rs +++ b/src/test/ui/structs-enums/class-cast-to-trait-cross-crate-2.rs @@ -1,8 +1,6 @@ // run-pass // aux-build:cci_class_cast.rs -#![feature(box_syntax)] - extern crate cci_class_cast; use std::string::ToString; @@ -15,6 +13,6 @@ fn print_out(thing: Box, expected: String) { } pub fn main() { - let nyan: Box = box cat(0, 2, "nyan".to_string()) as Box; + let nyan: Box = Box::new(cat(0, 2, "nyan".to_string())) as Box; print_out(nyan, "nyan".to_string()); } diff --git a/src/test/ui/structs-enums/class-cast-to-trait-multiple-types.rs b/src/test/ui/structs-enums/class-cast-to-trait-multiple-types.rs index 55975cbdb5..ca35a615d2 100644 --- a/src/test/ui/structs-enums/class-cast-to-trait-multiple-types.rs +++ b/src/test/ui/structs-enums/class-cast-to-trait-multiple-types.rs @@ -1,5 +1,6 @@ // run-pass #![allow(non_camel_case_types)] +#![allow(dead_code)] trait noisy { fn speak(&mut self) -> isize; diff --git a/src/test/ui/structs-enums/class-implement-traits.rs b/src/test/ui/structs-enums/class-implement-traits.rs index c9e98e21b9..732aa146ce 100644 --- a/src/test/ui/structs-enums/class-implement-traits.rs +++ b/src/test/ui/structs-enums/class-implement-traits.rs @@ -1,5 +1,6 @@ // run-pass #![allow(non_camel_case_types)] +#![allow(dead_code)] trait noisy { fn speak(&mut self); diff --git a/src/test/ui/structs-enums/class-separate-impl.rs b/src/test/ui/structs-enums/class-separate-impl.rs index 947690b51f..3d6da1cc28 100644 --- a/src/test/ui/structs-enums/class-separate-impl.rs +++ b/src/test/ui/structs-enums/class-separate-impl.rs @@ -2,8 +2,6 @@ #![allow(dead_code)] #![allow(non_camel_case_types)] -#![feature(box_syntax)] - use std::fmt; struct cat { @@ -60,6 +58,6 @@ fn print_out(thing: Box, expected: String) { } pub fn main() { - let nyan: Box = box cat(0, 2, "nyan".to_string()) as Box; + let nyan: Box = Box::new(cat(0, 2, "nyan".to_string())) as Box; print_out(nyan, "nyan".to_string()); } diff --git a/src/test/ui/structs-enums/enum-nullable-simplifycfg-misopt.rs b/src/test/ui/structs-enums/enum-nullable-simplifycfg-misopt.rs index 77419e1132..53892a4e0a 100644 --- a/src/test/ui/structs-enums/enum-nullable-simplifycfg-misopt.rs +++ b/src/test/ui/structs-enums/enum-nullable-simplifycfg-misopt.rs @@ -1,5 +1,4 @@ // run-pass -#![feature(box_syntax)] /*! * This is a regression test for a bug in LLVM, fixed in upstream r179587, @@ -9,7 +8,7 @@ enum List { Nil, Cons(X, Box>) } pub fn main() { - match List::Cons(10, box List::Nil) { + match List::Cons(10, Box::new(List::Nil)) { List::Cons(10, _) => {} List::Nil => {} _ => panic!() diff --git a/src/test/ui/structs-enums/functional-struct-upd.rs b/src/test/ui/structs-enums/functional-struct-upd.rs index 51c6b6d7e4..68ff73a080 100644 --- a/src/test/ui/structs-enums/functional-struct-upd.rs +++ b/src/test/ui/structs-enums/functional-struct-upd.rs @@ -1,4 +1,7 @@ // run-pass + +#![allow(dead_code)] + #[derive(Debug)] struct Foo { x: isize, diff --git a/src/test/ui/issues/issue-38002.rs b/src/test/ui/structs-enums/issue-38002.rs similarity index 100% rename from src/test/ui/issues/issue-38002.rs rename to src/test/ui/structs-enums/issue-38002.rs diff --git a/src/test/ui/structs-enums/tag-align-shape.rs b/src/test/ui/structs-enums/tag-align-shape.rs index 87282ddbcc..ce59958237 100644 --- a/src/test/ui/structs-enums/tag-align-shape.rs +++ b/src/test/ui/structs-enums/tag-align-shape.rs @@ -1,5 +1,6 @@ // run-pass #![allow(non_camel_case_types)] +#![allow(dead_code)] #[derive(Debug)] enum a_tag { 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 300c2a66c2..78ebb3d6bf 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 @@ -5,7 +5,9 @@ LL | async fn foo() {} | --- consider calling this function ... LL | bar(foo); - | ^^^ `fn() -> impl Future {foo}` is not a future + | --- ^^^ `fn() -> impl Future {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}` note: required by a bound in `bar` @@ -24,7 +26,9 @@ error[E0277]: `[closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-be LL | let async_closure = async || (); | -------- consider calling this closure LL | bar(async_closure); - | ^^^^^^^^^^^^^ `[closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:36]` is not a future + | --- ^^^^^^^^^^^^^ `[closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:36]` is not a future + | | + | required by a bound introduced by this call | = help: the trait `Future` is not implemented for `[closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:36]` note: required by a bound in `bar` diff --git a/src/test/ui/suggestions/box-future-wrong-output.rs b/src/test/ui/suggestions/box-future-wrong-output.rs new file mode 100644 index 0000000000..d49819fcb1 --- /dev/null +++ b/src/test/ui/suggestions/box-future-wrong-output.rs @@ -0,0 +1,22 @@ +// Issue #72117 +// edition:2018 + +use core::future::Future; +use core::pin::Pin; + +pub type BoxFuture<'a, T> = Pin + Send + 'a>>; + +impl FutureExt for T where T: Future {} +trait FutureExt: Future { + fn boxed<'a>(self) -> BoxFuture<'a, Self::Output> + where + Self: Sized + Send + 'a, + { + Box::pin(self) + } +} + +fn main() { + let _: BoxFuture<'static, bool> = async {}.boxed(); + //~^ ERROR: mismatched types +} diff --git a/src/test/ui/suggestions/box-future-wrong-output.stderr b/src/test/ui/suggestions/box-future-wrong-output.stderr new file mode 100644 index 0000000000..e0c57af25b --- /dev/null +++ b/src/test/ui/suggestions/box-future-wrong-output.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/box-future-wrong-output.rs:20:39 + | +LL | let _: BoxFuture<'static, bool> = async {}.boxed(); + | ------------------------ ^^^^^^^^^^^^^^^^ expected `bool`, found `()` + | | + | expected due to this + | + = note: expected struct `Pin + Send + 'static)>>` + found struct `Pin + Send>>` + +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.rs b/src/test/ui/suggestions/core-std-import-order-issue-83564.rs new file mode 100644 index 0000000000..b7fe5af7bf --- /dev/null +++ b/src/test/ui/suggestions/core-std-import-order-issue-83564.rs @@ -0,0 +1,10 @@ +// edition:2018 + +// This is a regression test for #83564. +// For some reason, Rust 2018 or higher is required to reproduce the bug. + +fn main() { + //~^ HELP consider importing one of these items + let _x = NonZeroU32::new(5).unwrap(); + //~^ ERROR failed to resolve: use of undeclared type `NonZeroU32` +} 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 new file mode 100644 index 0000000000..d484fb8cbe --- /dev/null +++ b/src/test/ui/suggestions/core-std-import-order-issue-83564.stderr @@ -0,0 +1,16 @@ +error[E0433]: failed to resolve: use of undeclared type `NonZeroU32` + --> $DIR/core-std-import-order-issue-83564.rs:8:14 + | +LL | let _x = NonZeroU32::new(5).unwrap(); + | ^^^^^^^^^^ not found in this scope + | +help: consider importing one of these items + | +LL | use std::num::NonZeroU32; + | +LL | use core::num::NonZeroU32; + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0433`. diff --git a/src/test/ui/suggestions/crate-or-module-typo.rs b/src/test/ui/suggestions/crate-or-module-typo.rs new file mode 100644 index 0000000000..2471b11c61 --- /dev/null +++ b/src/test/ui/suggestions/crate-or-module-typo.rs @@ -0,0 +1,17 @@ +// edition:2018 + +use st::cell::Cell; //~ ERROR failed to resolve: use of undeclared crate or module `st` + +mod bar { + pub fn bar() { bar::baz(); } //~ ERROR failed to resolve: use of undeclared crate or module `bar` + + fn baz() {} +} + +use bas::bar; //~ ERROR unresolved import `bas` + +struct Foo { + bar: st::cell::Cell //~ ERROR failed to resolve: use of undeclared crate or module `st` +} + +fn main() {} diff --git a/src/test/ui/suggestions/crate-or-module-typo.stderr b/src/test/ui/suggestions/crate-or-module-typo.stderr new file mode 100644 index 0000000000..e8250c9fa5 --- /dev/null +++ b/src/test/ui/suggestions/crate-or-module-typo.stderr @@ -0,0 +1,43 @@ +error[E0433]: failed to resolve: use of undeclared crate or module `st` + --> $DIR/crate-or-module-typo.rs:3:5 + | +LL | use st::cell::Cell; + | ^^ use of undeclared crate or module `st` + | +help: there is a crate or module with a similar name + | +LL | use std::cell::Cell; + | ~~~ + +error[E0432]: unresolved import `bas` + --> $DIR/crate-or-module-typo.rs:11:5 + | +LL | use bas::bar; + | ^^^ use of undeclared crate or module `bas` + | +help: there is a crate or module with a similar name + | +LL | use bar::bar; + | ~~~ + +error[E0433]: failed to resolve: use of undeclared crate or module `bar` + --> $DIR/crate-or-module-typo.rs:6:20 + | +LL | pub fn bar() { bar::baz(); } + | ^^^ use of undeclared crate or module `bar` + +error[E0433]: failed to resolve: use of undeclared crate or module `st` + --> $DIR/crate-or-module-typo.rs:14:10 + | +LL | bar: st::cell::Cell + | ^^ use of undeclared crate or module `st` + | +help: there is a crate or module with a similar name + | +LL | bar: std::cell::Cell + | ~~~ + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0432, E0433. +For more information about an error, try `rustc --explain E0432`. diff --git a/src/test/ui/suggestions/derive-trait-for-method-call.rs b/src/test/ui/suggestions/derive-trait-for-method-call.rs new file mode 100644 index 0000000000..25043da52a --- /dev/null +++ b/src/test/ui/suggestions/derive-trait-for-method-call.rs @@ -0,0 +1,44 @@ +use std::time::Instant; + +enum Enum { + First +} + +#[derive(Clone)] +enum CloneEnum { + First +} + +struct Struct { +} + +#[derive(Clone)] +struct CloneStruct { +} + +struct Foo (X, Y); +impl Foo { + fn test(&self) -> (X, Y) { + (self.0, self.1) + } +} + +fn test1() { + let x = Foo(Enum::First, CloneEnum::First); + let y = x.test(); + //~^the method `test` exists for struct `Foo`, but its trait bounds were not satisfied [E0599] +} + +fn test2() { + let x = Foo(Struct{}, CloneStruct{}); + let y = x.test(); + //~^the method `test` exists for struct `Foo`, but its trait bounds were not satisfied [E0599] +} + +fn test3() { + let x = Foo(Vec::::new(), Instant::now()); + let y = x.test(); + //~^the method `test` exists for struct `Foo, Instant>`, but its trait bounds were not satisfied [E0599] +} + +fn main() {} diff --git a/src/test/ui/suggestions/derive-trait-for-method-call.stderr b/src/test/ui/suggestions/derive-trait-for-method-call.stderr new file mode 100644 index 0000000000..2af3ba1d5b --- /dev/null +++ b/src/test/ui/suggestions/derive-trait-for-method-call.stderr @@ -0,0 +1,95 @@ +error[E0599]: the method `test` exists for struct `Foo`, but its trait bounds were not satisfied + --> $DIR/derive-trait-for-method-call.rs:28:15 + | +LL | enum Enum { + | --------- + | | + | doesn't satisfy `Enum: Clone` + | doesn't satisfy `Enum: Default` +... +LL | enum CloneEnum { + | -------------- doesn't satisfy `CloneEnum: Default` +... +LL | struct Foo (X, Y); + | ------------------------ method `test` not found for this +... +LL | let y = x.test(); + | ^^^^ method cannot be called on `Foo` due to unsatisfied trait bounds + | + = note: the following trait bounds were not satisfied: + `Enum: Clone` + `Enum: Default` + `CloneEnum: Default` +note: the following trait must be implemented + --> $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 | | } + | |_^ +help: consider annotating `Enum` with `#[derive(Clone)]` + | +LL | #[derive(Clone)] + | + +error[E0599]: the method `test` exists for struct `Foo`, but its trait bounds were not satisfied + --> $DIR/derive-trait-for-method-call.rs:34:15 + | +LL | struct Struct { + | ------------- + | | + | doesn't satisfy `Struct: Clone` + | doesn't satisfy `Struct: Default` +... +LL | struct CloneStruct { + | ------------------ doesn't satisfy `CloneStruct: Default` +... +LL | struct Foo (X, Y); + | ------------------------ method `test` not found for this +... +LL | let y = x.test(); + | ^^^^ method cannot be called on `Foo` due to unsatisfied trait bounds + | + = note: the following trait bounds were not satisfied: + `Struct: Clone` + `Struct: Default` + `CloneStruct: Default` +help: consider annotating `CloneStruct` with `#[derive(Default)]` + | +LL | #[derive(Default)] + | +help: consider annotating `Struct` with `#[derive(Clone, Default)]` + | +LL | #[derive(Clone, Default)] + | + +error[E0599]: the method `test` exists for struct `Foo, Instant>`, but its trait bounds were not satisfied + --> $DIR/derive-trait-for-method-call.rs:40:15 + | +LL | struct Foo (X, Y); + | ------------------------ method `test` not found for this +... +LL | let y = x.test(); + | ^^^^ method cannot be called on `Foo, Instant>` due to unsatisfied trait bounds + | + ::: $SRC_DIR/std/src/time.rs:LL:COL + | +LL | pub struct Instant(time::Instant); + | ---------------------------------- doesn't satisfy `Instant: Default` + | + ::: $SRC_DIR/alloc/src/vec/mod.rs:LL:COL + | +LL | pub struct Vec { + | ------------------------------------------------------------------------------------------------ doesn't satisfy `Vec: Clone` + | + = note: the following trait bounds were not satisfied: + `Vec: Clone` + `Instant: Default` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/suggestions/dont-suggest-deref-inside-macro-issue-58298.stderr b/src/test/ui/suggestions/dont-suggest-deref-inside-macro-issue-58298.stderr index 59e7cfc6f0..3599d53d2a 100644 --- a/src/test/ui/suggestions/dont-suggest-deref-inside-macro-issue-58298.stderr +++ b/src/test/ui/suggestions/dont-suggest-deref-inside-macro-issue-58298.stderr @@ -4,7 +4,7 @@ error[E0308]: mismatched types LL | / intrinsic_match! { LL | | "abc" LL | | }; - | |______^ expected `&str`, found struct `String` + | |_____^ expected `&str`, found struct `String` | = note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/suggestions/dont-suggest-ref/move-into-closure.stderr b/src/test/ui/suggestions/dont-suggest-ref/move-into-closure.stderr index c50cbcde85..fb1055c9c3 100644 --- a/src/test/ui/suggestions/dont-suggest-ref/move-into-closure.stderr +++ b/src/test/ui/suggestions/dont-suggest-ref/move-into-closure.stderr @@ -1,281 +1,487 @@ error[E0507]: cannot move out of `x.0`, as `x` is a captured variable in an `Fn` closure --> $DIR/move-into-closure.rs:28:21 | -LL | let x = X(Y); - | - captured outer variable +LL | let x = X(Y); + | - captured outer variable ... -LL | let X(_t) = x; - | -- ^ help: consider borrowing here: `&x` - | | - | data moved here - | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait +LL | consume_fn(|| { + | ________________- +LL | | let X(_t) = x; + | | -- ^ help: consider borrowing here: `&x` + | | | + | | data moved here + | | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait +LL | | +LL | | +... | +LL | | } +LL | | }); + | |_____- captured by this `Fn` closure error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `Fn` closure --> $DIR/move-into-closure.rs:32:34 | -LL | let e = Either::One(X(Y)); - | - captured outer variable +LL | let e = Either::One(X(Y)); + | - captured outer variable ... -LL | if let Either::One(_t) = e { } - | -- ^ help: consider borrowing here: `&e` - | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait +LL | consume_fn(|| { + | ________________- +LL | | let X(_t) = x; +LL | | +LL | | +LL | | +LL | | if let Either::One(_t) = e { } + | | -- ^ help: consider borrowing here: `&e` + | | | + | | data moved here + | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait +... | +LL | | } +LL | | }); + | |_____- captured by this `Fn` closure error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `Fn` closure --> $DIR/move-into-closure.rs:36:37 | -LL | let e = Either::One(X(Y)); - | - captured outer variable +LL | let e = Either::One(X(Y)); + | - captured outer variable ... -LL | while let Either::One(_t) = e { } - | -- ^ help: consider borrowing here: `&e` - | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait +LL | consume_fn(|| { + | ________________- +LL | | let X(_t) = x; +LL | | +LL | | +... | +LL | | while let Either::One(_t) = e { } + | | -- ^ help: consider borrowing here: `&e` + | | | + | | data moved here + | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait +... | +LL | | } +LL | | }); + | |_____- captured by this `Fn` closure error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `Fn` closure --> $DIR/move-into-closure.rs:40:15 | -LL | let e = Either::One(X(Y)); - | - captured outer variable +LL | let e = Either::One(X(Y)); + | - captured outer variable ... -LL | match e { - | ^ help: consider borrowing here: `&e` -... -LL | Either::One(_t) - | -- - | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait +LL | consume_fn(|| { + | ________________- +LL | | let X(_t) = x; +LL | | +LL | | +... | +LL | | match e { + | | ^ help: consider borrowing here: `&e` +... | +LL | | Either::One(_t) + | | -- + | | | + | | data moved here + | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait +... | +LL | | } +LL | | }); + | |_____- captured by this `Fn` closure error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `Fn` closure --> $DIR/move-into-closure.rs:47:15 | -LL | let e = Either::One(X(Y)); - | - captured outer variable +LL | let e = Either::One(X(Y)); + | - captured outer variable ... -LL | match e { - | ^ help: consider borrowing here: `&e` -... -LL | Either::One(_t) => (), - | -- - | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait +LL | consume_fn(|| { + | ________________- +LL | | let X(_t) = x; +LL | | +LL | | +... | +LL | | match e { + | | ^ help: consider borrowing here: `&e` +... | +LL | | Either::One(_t) => (), + | | -- + | | | + | | data moved here + | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait +... | +LL | | } +LL | | }); + | |_____- captured by this `Fn` closure error[E0507]: cannot move out of `x.0`, as `x` is a captured variable in an `Fn` closure --> $DIR/move-into-closure.rs:56:25 | -LL | let x = X(Y); - | - captured outer variable +LL | let x = X(Y); + | - captured outer variable ... -LL | let X(mut _t) = x; - | ------ ^ help: consider borrowing here: `&x` - | | - | data moved here - | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait +LL | consume_fn(|| { + | ________________- +LL | | let X(_t) = x; +LL | | +LL | | +... | +LL | | let X(mut _t) = x; + | | ------ ^ help: consider borrowing here: `&x` + | | | + | | data moved here + | | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait +... | +LL | | } +LL | | }); + | |_____- captured by this `Fn` closure error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `Fn` closure --> $DIR/move-into-closure.rs:60:38 | -LL | let mut em = Either::One(X(Y)); - | ------ captured outer variable +LL | let mut em = Either::One(X(Y)); + | ------ captured outer variable ... -LL | if let Either::One(mut _t) = em { } - | ------ ^^ help: consider borrowing here: `&em` - | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait +LL | consume_fn(|| { + | ________________- +LL | | let X(_t) = x; +LL | | +LL | | +... | +LL | | if let Either::One(mut _t) = em { } + | | ------ ^^ help: consider borrowing here: `&em` + | | | + | | data moved here + | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait +... | +LL | | } +LL | | }); + | |_____- captured by this `Fn` closure error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `Fn` closure --> $DIR/move-into-closure.rs:64:41 | -LL | let mut em = Either::One(X(Y)); - | ------ captured outer variable +LL | let mut em = Either::One(X(Y)); + | ------ captured outer variable ... -LL | while let Either::One(mut _t) = em { } - | ------ ^^ help: consider borrowing here: `&em` - | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait +LL | consume_fn(|| { + | ________________- +LL | | let X(_t) = x; +LL | | +LL | | +... | +LL | | while let Either::One(mut _t) = em { } + | | ------ ^^ help: consider borrowing here: `&em` + | | | + | | data moved here + | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait +... | +LL | | } +LL | | }); + | |_____- captured by this `Fn` closure error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `Fn` closure --> $DIR/move-into-closure.rs:68:15 | -LL | let mut em = Either::One(X(Y)); - | ------ captured outer variable +LL | let mut em = Either::One(X(Y)); + | ------ captured outer variable ... -LL | match em { - | ^^ help: consider borrowing here: `&em` -... -LL | Either::One(mut _t) - | ------ - | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait +LL | consume_fn(|| { + | ________________- +LL | | let X(_t) = x; +LL | | +LL | | +... | +LL | | match em { + | | ^^ help: consider borrowing here: `&em` +... | +LL | | Either::One(mut _t) + | | ------ + | | | + | | data moved here + | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait +... | +LL | | } +LL | | }); + | |_____- captured by this `Fn` closure error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `Fn` closure --> $DIR/move-into-closure.rs:75:15 | -LL | let mut em = Either::One(X(Y)); - | ------ captured outer variable +LL | let mut em = Either::One(X(Y)); + | ------ captured outer variable ... -LL | match em { - | ^^ help: consider borrowing here: `&em` -... -LL | Either::One(mut _t) => (), - | ------ - | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait +LL | consume_fn(|| { + | ________________- +LL | | let X(_t) = x; +LL | | +LL | | +... | +LL | | match em { + | | ^^ help: consider borrowing here: `&em` +... | +LL | | Either::One(mut _t) => (), + | | ------ + | | | + | | data moved here + | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait +... | +LL | | } +LL | | }); + | |_____- captured by this `Fn` closure error[E0507]: cannot move out of `x.0`, as `x` is a captured variable in an `FnMut` closure --> $DIR/move-into-closure.rs:95:21 | -LL | let x = X(Y); - | - captured outer variable +LL | let x = X(Y); + | - captured outer variable ... -LL | let X(_t) = x; - | -- ^ help: consider borrowing here: `&x` - | | - | data moved here - | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait +LL | consume_fnmut(|| { + | ___________________- +LL | | let X(_t) = x; + | | -- ^ help: consider borrowing here: `&x` + | | | + | | data moved here + | | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait +LL | | +LL | | +... | +LL | | } +LL | | }); + | |_____- captured by this `FnMut` closure error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `FnMut` closure --> $DIR/move-into-closure.rs:99:34 | -LL | let e = Either::One(X(Y)); - | - captured outer variable +LL | let e = Either::One(X(Y)); + | - captured outer variable ... -LL | if let Either::One(_t) = e { } - | -- ^ help: consider borrowing here: `&e` - | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait +LL | consume_fnmut(|| { + | ___________________- +LL | | let X(_t) = x; +LL | | +LL | | +LL | | +LL | | if let Either::One(_t) = e { } + | | -- ^ help: consider borrowing here: `&e` + | | | + | | data moved here + | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait +... | +LL | | } +LL | | }); + | |_____- captured by this `FnMut` closure error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `FnMut` closure --> $DIR/move-into-closure.rs:103:37 | -LL | let e = Either::One(X(Y)); - | - captured outer variable +LL | let e = Either::One(X(Y)); + | - captured outer variable ... -LL | while let Either::One(_t) = e { } - | -- ^ help: consider borrowing here: `&e` - | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait +LL | consume_fnmut(|| { + | ___________________- +LL | | let X(_t) = x; +LL | | +LL | | +... | +LL | | while let Either::One(_t) = e { } + | | -- ^ help: consider borrowing here: `&e` + | | | + | | data moved here + | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait +... | +LL | | } +LL | | }); + | |_____- captured by this `FnMut` closure error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `FnMut` closure --> $DIR/move-into-closure.rs:107:15 | -LL | let e = Either::One(X(Y)); - | - captured outer variable +LL | let e = Either::One(X(Y)); + | - captured outer variable ... -LL | match e { - | ^ help: consider borrowing here: `&e` -... -LL | Either::One(_t) - | -- - | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait +LL | consume_fnmut(|| { + | ___________________- +LL | | let X(_t) = x; +LL | | +LL | | +... | +LL | | match e { + | | ^ help: consider borrowing here: `&e` +... | +LL | | Either::One(_t) + | | -- + | | | + | | data moved here + | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait +... | +LL | | } +LL | | }); + | |_____- captured by this `FnMut` closure error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `FnMut` closure --> $DIR/move-into-closure.rs:114:15 | -LL | let e = Either::One(X(Y)); - | - captured outer variable +LL | let e = Either::One(X(Y)); + | - captured outer variable ... -LL | match e { - | ^ help: consider borrowing here: `&e` -... -LL | Either::One(_t) => (), - | -- - | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait +LL | consume_fnmut(|| { + | ___________________- +LL | | let X(_t) = x; +LL | | +LL | | +... | +LL | | match e { + | | ^ help: consider borrowing here: `&e` +... | +LL | | Either::One(_t) => (), + | | -- + | | | + | | data moved here + | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait +... | +LL | | } +LL | | }); + | |_____- captured by this `FnMut` closure error[E0507]: cannot move out of `x.0`, as `x` is a captured variable in an `FnMut` closure --> $DIR/move-into-closure.rs:123:25 | -LL | let x = X(Y); - | - captured outer variable +LL | let x = X(Y); + | - captured outer variable ... -LL | let X(mut _t) = x; - | ------ ^ help: consider borrowing here: `&x` - | | - | data moved here - | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait +LL | consume_fnmut(|| { + | ___________________- +LL | | let X(_t) = x; +LL | | +LL | | +... | +LL | | let X(mut _t) = x; + | | ------ ^ help: consider borrowing here: `&x` + | | | + | | data moved here + | | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait +... | +LL | | } +LL | | }); + | |_____- captured by this `FnMut` closure error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `FnMut` closure --> $DIR/move-into-closure.rs:127:38 | -LL | let mut em = Either::One(X(Y)); - | ------ captured outer variable +LL | let mut em = Either::One(X(Y)); + | ------ captured outer variable ... -LL | if let Either::One(mut _t) = em { } - | ------ ^^ help: consider borrowing here: `&em` - | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait +LL | consume_fnmut(|| { + | ___________________- +LL | | let X(_t) = x; +LL | | +LL | | +... | +LL | | if let Either::One(mut _t) = em { } + | | ------ ^^ help: consider borrowing here: `&em` + | | | + | | data moved here + | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait +... | +LL | | } +LL | | }); + | |_____- captured by this `FnMut` closure error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `FnMut` closure --> $DIR/move-into-closure.rs:131:41 | -LL | let mut em = Either::One(X(Y)); - | ------ captured outer variable +LL | let mut em = Either::One(X(Y)); + | ------ captured outer variable ... -LL | while let Either::One(mut _t) = em { } - | ------ ^^ help: consider borrowing here: `&em` - | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait +LL | consume_fnmut(|| { + | ___________________- +LL | | let X(_t) = x; +LL | | +LL | | +... | +LL | | while let Either::One(mut _t) = em { } + | | ------ ^^ help: consider borrowing here: `&em` + | | | + | | data moved here + | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait +... | +LL | | } +LL | | }); + | |_____- captured by this `FnMut` closure error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `FnMut` closure --> $DIR/move-into-closure.rs:135:15 | -LL | let mut em = Either::One(X(Y)); - | ------ captured outer variable +LL | let mut em = Either::One(X(Y)); + | ------ captured outer variable ... -LL | match em { - | ^^ help: consider borrowing here: `&em` -... -LL | Either::One(mut _t) - | ------ - | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait +LL | consume_fnmut(|| { + | ___________________- +LL | | let X(_t) = x; +LL | | +LL | | +... | +LL | | match em { + | | ^^ help: consider borrowing here: `&em` +... | +LL | | Either::One(mut _t) + | | ------ + | | | + | | data moved here + | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait +... | +LL | | } +LL | | }); + | |_____- captured by this `FnMut` closure error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `FnMut` closure --> $DIR/move-into-closure.rs:142:15 | -LL | let mut em = Either::One(X(Y)); - | ------ captured outer variable +LL | let mut em = Either::One(X(Y)); + | ------ captured outer variable ... -LL | match em { - | ^^ help: consider borrowing here: `&em` -... -LL | Either::One(mut _t) => (), - | ------ - | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait +LL | consume_fnmut(|| { + | ___________________- +LL | | let X(_t) = x; +LL | | +LL | | +... | +LL | | match em { + | | ^^ help: consider borrowing here: `&em` +... | +LL | | Either::One(mut _t) => (), + | | ------ + | | | + | | data moved here + | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait +... | +LL | | } +LL | | }); + | |_____- captured by this `FnMut` closure error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `FnMut` closure --> $DIR/move-into-closure.rs:150:15 | -LL | let mut em = Either::One(X(Y)); - | ------ captured outer variable +LL | let mut em = Either::One(X(Y)); + | ------ captured outer variable ... -LL | match em { - | ^^ help: consider borrowing here: `&em` -... -LL | Either::One(mut _t) => (), - | ------ - | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait +LL | consume_fnmut(|| { + | ___________________- +LL | | let X(_t) = x; +LL | | +LL | | +... | +LL | | match em { + | | ^^ help: consider borrowing here: `&em` +... | +LL | | Either::One(mut _t) => (), + | | ------ + | | | + | | data moved here + | | move occurs because `_t` has type `X`, which does not implement the `Copy` trait +... | +LL | | } +LL | | }); + | |_____- captured by this `FnMut` closure error: aborting due to 21 previous errors diff --git a/src/test/ui/suggestions/dont-suggest-try_into-in-macros.stderr b/src/test/ui/suggestions/dont-suggest-try_into-in-macros.stderr index e15e7e905c..4e21d36014 100644 --- a/src/test/ui/suggestions/dont-suggest-try_into-in-macros.stderr +++ b/src/test/ui/suggestions/dont-suggest-try_into-in-macros.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/dont-suggest-try_into-in-macros.rs:2:5 | LL | assert_eq!(10u64, 10usize); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `u64`, found `usize` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `u64`, found `usize` | = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/suggestions/expected-boxed-future-isnt-pinned.rs b/src/test/ui/suggestions/expected-boxed-future-isnt-pinned.rs index 5dee0f5dae..7e9c5492d1 100644 --- a/src/test/ui/suggestions/expected-boxed-future-isnt-pinned.rs +++ b/src/test/ui/suggestions/expected-boxed-future-isnt-pinned.rs @@ -11,9 +11,6 @@ fn foo + Send + 'static>(x: F) -> BoxFuture<'static, i32> x //~ ERROR mismatched types } -// This case is still subpar: -// `Pin::new(x)`: store this in the heap by calling `Box::new`: `Box::new(x)` -// Should suggest changing the code from `Pin::new` to `Box::pin`. fn bar + Send + 'static>(x: F) -> BoxFuture<'static, i32> { Box::new(x) //~ ERROR mismatched types } 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 ff08178cb7..aa3175dae2 100644 --- a/src/test/ui/suggestions/expected-boxed-future-isnt-pinned.stderr +++ b/src/test/ui/suggestions/expected-boxed-future-isnt-pinned.stderr @@ -15,7 +15,7 @@ LL | Box::pin(x) | +++++++++ + error[E0308]: mismatched types - --> $DIR/expected-boxed-future-isnt-pinned.rs:18:5 + --> $DIR/expected-boxed-future-isnt-pinned.rs:15:5 | LL | fn bar + Send + 'static>(x: F) -> BoxFuture<'static, i32> { | ----------------------- expected `Pin + Send + 'static)>>` because of return type @@ -27,23 +27,20 @@ LL | Box::new(x) = help: use `Box::pin` error[E0308]: mismatched types - --> $DIR/expected-boxed-future-isnt-pinned.rs:22:14 + --> $DIR/expected-boxed-future-isnt-pinned.rs:19:14 | LL | fn baz + Send + 'static>(x: F) -> BoxFuture<'static, i32> { | - this type parameter LL | Pin::new(x) - | ^ expected struct `Box`, found type parameter `F` + | -------- ^ expected struct `Box`, found type parameter `F` + | | + | help: use `Box::pin` to pin and box this expression: `Box::pin` | = note: expected struct `Box + Send>` found type parameter `F` - = note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html -help: store this in the heap by calling `Box::new` - | -LL | Pin::new(Box::new(x)) - | +++++++++ + error[E0277]: `dyn Future + Send` cannot be unpinned - --> $DIR/expected-boxed-future-isnt-pinned.rs:22:5 + --> $DIR/expected-boxed-future-isnt-pinned.rs:19:5 | LL | Pin::new(x) | ^^^^^^^^ the trait `Unpin` is not implemented for `dyn Future + Send` @@ -56,7 +53,7 @@ LL | pub const fn new(pointer: P) -> Pin

{ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `dyn Future + Send` cannot be unpinned - --> $DIR/expected-boxed-future-isnt-pinned.rs:27:5 + --> $DIR/expected-boxed-future-isnt-pinned.rs:24:5 | LL | Pin::new(Box::new(x)) | ^^^^^^^^ the trait `Unpin` is not implemented for `dyn Future + Send` @@ -69,7 +66,7 @@ LL | pub const fn new(pointer: P) -> Pin

{ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0308]: mismatched types - --> $DIR/expected-boxed-future-isnt-pinned.rs:31:5 + --> $DIR/expected-boxed-future-isnt-pinned.rs:28:5 | LL | fn zap() -> BoxFuture<'static, i32> { | ----------------------- expected `Pin + Send + 'static)>>` because of return type 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 93048107e5..b111df49f6 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 @@ -5,7 +5,9 @@ LL | fn foo() -> impl T { 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 {foo}` + | | + | required by a bound introduced by this call | note: required by a bound in `bar` --> $DIR/fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:14:16 @@ -23,7 +25,9 @@ error[E0277]: the trait bound `[closure@$DIR/fn-ctor-passed-as-arg-where-it-shou LL | let closure = || S; | -- consider calling this closure LL | bar(closure); - | ^^^^^^^ the trait `T` is not implemented for `[closure@$DIR/fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:18:19: 18:23]` + | --- ^^^^^^^ the trait `T` is not implemented for `[closure@$DIR/fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:18:19: 18:23]` + | | + | required by a bound introduced by this call | note: required by a bound in `bar` --> $DIR/fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:14:16 diff --git a/src/test/ui/suggestions/ignore-nested-field-binding.fixed b/src/test/ui/suggestions/ignore-nested-field-binding.fixed new file mode 100644 index 0000000000..1dc44838e8 --- /dev/null +++ b/src/test/ui/suggestions/ignore-nested-field-binding.fixed @@ -0,0 +1,20 @@ +// Regression test for #88403, where prefixing with an underscore was +// erroneously suggested for a nested shorthand struct field binding. + +// run-rustfix +#![allow(unused)] +#![forbid(unused_variables)] + +struct Inner { i: i32 } +struct Outer { o: Inner } + +fn foo(Outer { o: Inner { i: _ } }: Outer) {} +//~^ ERROR: unused variable: `i` +//~| HELP: try ignoring the field + +fn main() { + let s = Outer { o: Inner { i: 42 } }; + let Outer { o: Inner { i: _ } } = s; + //~^ ERROR: unused variable: `i` + //~| HELP: try ignoring the field +} diff --git a/src/test/ui/suggestions/ignore-nested-field-binding.rs b/src/test/ui/suggestions/ignore-nested-field-binding.rs new file mode 100644 index 0000000000..6dc0263ec9 --- /dev/null +++ b/src/test/ui/suggestions/ignore-nested-field-binding.rs @@ -0,0 +1,20 @@ +// Regression test for #88403, where prefixing with an underscore was +// erroneously suggested for a nested shorthand struct field binding. + +// run-rustfix +#![allow(unused)] +#![forbid(unused_variables)] + +struct Inner { i: i32 } +struct Outer { o: Inner } + +fn foo(Outer { o: Inner { i } }: Outer) {} +//~^ ERROR: unused variable: `i` +//~| HELP: try ignoring the field + +fn main() { + let s = Outer { o: Inner { i: 42 } }; + let Outer { o: Inner { i } } = s; + //~^ ERROR: unused variable: `i` + //~| HELP: try ignoring the field +} diff --git a/src/test/ui/suggestions/ignore-nested-field-binding.stderr b/src/test/ui/suggestions/ignore-nested-field-binding.stderr new file mode 100644 index 0000000000..b2936a22a2 --- /dev/null +++ b/src/test/ui/suggestions/ignore-nested-field-binding.stderr @@ -0,0 +1,20 @@ +error: unused variable: `i` + --> $DIR/ignore-nested-field-binding.rs:11:27 + | +LL | fn foo(Outer { o: Inner { i } }: Outer) {} + | ^ help: try ignoring the field: `i: _` + | +note: the lint level is defined here + --> $DIR/ignore-nested-field-binding.rs:6:11 + | +LL | #![forbid(unused_variables)] + | ^^^^^^^^^^^^^^^^ + +error: unused variable: `i` + --> $DIR/ignore-nested-field-binding.rs:17:28 + | +LL | let Outer { o: Inner { i } } = s; + | ^ help: try ignoring the field: `i: _` + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/suggestions/imm-ref-trait-object-literal.stderr b/src/test/ui/suggestions/imm-ref-trait-object-literal.stderr index 39bde52c55..001af27b24 100644 --- a/src/test/ui/suggestions/imm-ref-trait-object-literal.stderr +++ b/src/test/ui/suggestions/imm-ref-trait-object-literal.stderr @@ -2,7 +2,9 @@ error[E0277]: the trait bound `&S: Trait` is not satisfied --> $DIR/imm-ref-trait-object-literal.rs:12:7 | LL | foo(&s); - | ^^ the trait `Trait` is not implemented for `&S` + | --- ^^ the trait `Trait` is not implemented for `&S` + | | + | required by a bound introduced by this call | = help: the following implementations were found: <&'a mut S as Trait> @@ -20,16 +22,19 @@ error[E0277]: the trait bound `S: Trait` is not satisfied --> $DIR/imm-ref-trait-object-literal.rs:13:7 | LL | foo(s); - | ^ - | | - | expected an implementor of trait `Trait` - | help: consider mutably borrowing here: `&mut s` + | --- ^ expected an implementor of trait `Trait` + | | + | required by a bound introduced by this call | note: required by a bound in `foo` --> $DIR/imm-ref-trait-object-literal.rs:7:11 | LL | fn foo(_: X) {} | ^^^^^ required by this bound in `foo` +help: consider mutably borrowing here + | +LL | foo(&mut s); + | ++++ error: aborting due to 2 previous errors 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 043a771129..80d3c940eb 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 @@ -4,7 +4,7 @@ error[E0597]: `val` does not live long enough LL | fn use_it<'a>(val: Box>) -> 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 + | ^^^^^^^^^^^^^^ borrowed value does not live long enough LL | } | - `val` dropped here while still borrowed | @@ -13,23 +13,17 @@ help: you can add a bound to the opaque type to make it last less than `'static` LL | fn use_it<'a>(val: Box>) -> impl OtherTrait<'a> + 'a { | ++++ -error[E0515]: cannot return value referencing function parameter `val` +error[E0515]: cannot return reference to function parameter `val` --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:43:9 | LL | val.use_self() - | ---^^^^^^^^^^^ - | | - | returns a value referencing data owned by the current function - | `val` is borrowed here + | ^^^^^^^^^^^^^^ returns a reference to data owned by the current function -error[E0515]: cannot return value referencing function parameter `val` +error[E0515]: cannot return reference to function parameter `val` --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:109:9 | LL | val.use_self() - | ---^^^^^^^^^^^ - | | - | returns a value referencing data owned by the current function - | `val` is borrowed here + | ^^^^^^^^^^^^^^ returns a reference to data owned by the current function error: aborting due to 3 previous errors 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 29991b6572..e8c3a7908f 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 @@ -4,7 +4,7 @@ error[E0597]: `val` does not live long enough LL | fn use_it<'a>(val: Box>) -> 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 + | ^^^^^^^^^^^^^^ borrowed value does not live long enough LL | } | - `val` dropped here while still borrowed | @@ -13,23 +13,17 @@ help: you can add a bound to the opaque type to make it last less than `'static` LL | fn use_it<'a>(val: Box>) -> impl OtherTrait<'a> + 'a { | ++++ -error[E0515]: cannot return value referencing function parameter `val` +error[E0515]: cannot return reference to function parameter `val` --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:43:9 | LL | val.use_self() - | ---^^^^^^^^^^^ - | | - | returns a value referencing data owned by the current function - | `val` is borrowed here + | ^^^^^^^^^^^^^^ returns a reference to data owned by the current function -error[E0515]: cannot return value referencing function parameter `val` +error[E0515]: cannot return reference to function parameter `val` --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:109:9 | LL | val.use_self() - | ---^^^^^^^^^^^ - | | - | returns a value referencing data owned by the current function - | `val` is borrowed here + | ^^^^^^^^^^^^^^ returns a reference to data owned by the current function error[E0772]: `val` has lifetime `'a` but calling `use_self` introduces an implicit `'static` lifetime requirement --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:66:13 diff --git a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.nll.stderr b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.nll.stderr index 6c235ae8f0..a1ef32c544 100644 --- a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.nll.stderr +++ b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.nll.stderr @@ -2,41 +2,53 @@ error[E0521]: borrowed data escapes outside of function --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:20:9 | LL | fn use_it<'a, T>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { - | --- `val` is a reference that is only valid in the function body + | -- --- `val` is a reference that is only valid in the function body + | | + | lifetime `'a` defined here LL | val.use_self::() - | ^^^^^^^^^^^^^^^^^^^ `val` escapes the function body here - | - = help: consider replacing `'a` with `'static` + | ^^^^^^^^^^^^^^^^^^^ + | | + | `val` escapes the function body here + | argument requires that `'a` must outlive `'static` error[E0521]: borrowed data escapes outside of function --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:69:9 | LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { - | --- `val` is a reference that is only valid in the function body + | -- --- `val` is a reference that is only valid in the function body + | | + | lifetime `'a` defined here LL | val.use_self() - | ^^^^^^^^^^^^^^ `val` escapes the function body here - | - = help: consider replacing `'a` with `'static` + | ^^^^^^^^^^^^^^ + | | + | `val` escapes the function body here + | argument requires that `'a` must outlive `'static` error[E0521]: borrowed data escapes outside of function --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:88:9 | LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> { - | --- `val` is a reference that is only valid in the function body + | -- --- `val` is a reference that is only valid in the function body + | | + | lifetime `'a` defined here LL | val.use_self() - | ^^^^^^^^^^^^^^ `val` escapes the function body here - | - = help: consider replacing `'a` with `'static` + | ^^^^^^^^^^^^^^ + | | + | `val` escapes the function body here + | argument requires that `'a` must outlive `'static` error[E0521]: borrowed data escapes outside of function --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:108:9 | LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { - | --- `val` is a reference that is only valid in the function body + | -- --- `val` is a reference that is only valid in the function body + | | + | lifetime `'a` defined here LL | MyTrait::use_self(val) - | ^^^^^^^^^^^^^^^^^^^^^^ `val` escapes the function body here - | - = help: consider replacing `'a` with `'static` + | ^^^^^^^^^^^^^^^^^^^^^^ + | | + | `val` escapes the function body here + | argument requires that `'a` must outlive `'static` error: aborting due to 4 previous errors diff --git a/src/test/ui/suggestions/impl-trait-with-missing-bounds.stderr b/src/test/ui/suggestions/impl-trait-with-missing-bounds.stderr index bb7919ebb7..229c4b824f 100644 --- a/src/test/ui/suggestions/impl-trait-with-missing-bounds.stderr +++ b/src/test/ui/suggestions/impl-trait-with-missing-bounds.stderr @@ -2,7 +2,9 @@ error[E0277]: `::Item` doesn't implement `Debug` --> $DIR/impl-trait-with-missing-bounds.rs:14:13 | LL | qux(constraint); - | ^^^^^^^^^^ `::Item` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | --- ^^^^^^^^^^ `::Item` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | | + | required by a bound introduced by this call | = help: the trait `Debug` is not implemented for `::Item` note: required by a bound in `qux` @@ -19,7 +21,9 @@ error[E0277]: `::Item` doesn't implement `Debug` --> $DIR/impl-trait-with-missing-bounds.rs:22:13 | LL | qux(constraint); - | ^^^^^^^^^^ `::Item` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | --- ^^^^^^^^^^ `::Item` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | | + | required by a bound introduced by this call | = help: the trait `Debug` is not implemented for `::Item` note: required by a bound in `qux` @@ -36,7 +40,9 @@ error[E0277]: `::Item` doesn't implement `Debug` --> $DIR/impl-trait-with-missing-bounds.rs:30:13 | LL | qux(constraint); - | ^^^^^^^^^^ `::Item` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | --- ^^^^^^^^^^ `::Item` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | | + | required by a bound introduced by this call | = help: the trait `Debug` is not implemented for `::Item` note: required by a bound in `qux` @@ -53,7 +59,9 @@ error[E0277]: `::Item` doesn't impl --> $DIR/impl-trait-with-missing-bounds.rs:37:13 | LL | qux(constraint); - | ^^^^^^^^^^ `::Item` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | --- ^^^^^^^^^^ `::Item` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | | + | required by a bound introduced by this call | = help: the trait `Debug` is not implemented for `::Item` note: required by a bound in `qux` @@ -70,7 +78,9 @@ error[E0277]: `::Item` doesn't implement `Debug` --> $DIR/impl-trait-with-missing-bounds.rs:6:13 | LL | qux(constraint); - | ^^^^^^^^^^ `::Item` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | --- ^^^^^^^^^^ `::Item` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | | + | required by a bound introduced by this call | = help: the trait `Debug` is not implemented for `::Item` note: required by a bound in `qux` @@ -87,7 +97,9 @@ error[E0277]: `::Item` doesn't implement `Debug` --> $DIR/impl-trait-with-missing-bounds.rs:45:13 | LL | qux(constraint); - | ^^^^^^^^^^ `::Item` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | --- ^^^^^^^^^^ `::Item` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | | + | required by a bound introduced by this call | = help: the trait `Debug` is not implemented for `::Item` note: required by a bound in `qux` diff --git a/src/test/ui/suggestions/invalid-bin-op.stderr b/src/test/ui/suggestions/invalid-bin-op.stderr index 7668eddf60..d18c24e53d 100644 --- a/src/test/ui/suggestions/invalid-bin-op.stderr +++ b/src/test/ui/suggestions/invalid-bin-op.stderr @@ -6,7 +6,16 @@ LL | let _ = s == t; | | | S | +note: an implementation of `PartialEq<_>` might be missing for `S` + --> $DIR/invalid-bin-op.rs:5:1 + | +LL | struct S(T); + | ^^^^^^^^^^^^^^^ must implement `PartialEq<_>` = note: the trait `std::cmp::PartialEq` is not implemented for `S` +help: consider annotating `S` with `#[derive(PartialEq)]` + | +LL | #[derive(PartialEq)] + | error: aborting due to previous error diff --git a/src/test/ui/suggestions/issue-62843.stderr b/src/test/ui/suggestions/issue-62843.stderr index b2be09a4c7..29ba39cbe1 100644 --- a/src/test/ui/suggestions/issue-62843.stderr +++ b/src/test/ui/suggestions/issue-62843.stderr @@ -2,13 +2,16 @@ error[E0277]: expected a `FnMut<(char,)>` closure, found `String` --> $DIR/issue-62843.rs:4:32 | LL | println!("{:?}", line.find(pattern)); - | ^^^^^^^ - | | - | expected an implementor of trait `Pattern<'_>` - | help: consider borrowing here: `&pattern` + | ---- ^^^^^^^ expected an implementor of trait `Pattern<'_>` + | | + | required by a bound introduced by this call | = note: the trait bound `String: Pattern<'_>` is not satisfied = note: required because of the requirements on the impl of `Pattern<'_>` for `String` +help: consider borrowing here + | +LL | println!("{:?}", line.find(&pattern)); + | + error: aborting due to previous error diff --git a/src/test/ui/suggestions/issue-64252-self-type.stderr b/src/test/ui/suggestions/issue-64252-self-type.stderr index 009707a3a6..c3418dab0e 100644 --- a/src/test/ui/suggestions/issue-64252-self-type.stderr +++ b/src/test/ui/suggestions/issue-64252-self-type.stderr @@ -8,11 +8,11 @@ LL | pub fn foo(Box) { } help: if this is a `self` type, give it a parameter name | LL | pub fn foo(self: Box) { } - | ~~~~~~~~~ + | +++++ help: if this is a type, explicitly ignore the parameter name | LL | pub fn foo(_: Box) { } - | ~~~~~~ + | ++ error: expected one of `:`, `@`, or `|`, found `<` --> $DIR/issue-64252-self-type.rs:10:15 @@ -24,11 +24,11 @@ LL | fn bar(Box) { } help: if this is a `self` type, give it a parameter name | LL | fn bar(self: Box) { } - | ~~~~~~~~~ + | +++++ help: if this is a type, explicitly ignore the parameter name | LL | fn bar(_: Box) { } - | ~~~~~~ + | ++ error: aborting due to 2 previous errors diff --git a/src/test/ui/suggestions/issue-72766.rs b/src/test/ui/suggestions/issue-72766.rs index 0448f07195..c54be7f5df 100644 --- a/src/test/ui/suggestions/issue-72766.rs +++ b/src/test/ui/suggestions/issue-72766.rs @@ -1,5 +1,5 @@ // edition:2018 -// compile-flags: -Cincremental=tmp/issue-72766 +// incremental pub struct SadGirl; diff --git a/src/test/ui/suggestions/issue-79843-impl-trait-with-missing-bounds-on-async-fn.stderr b/src/test/ui/suggestions/issue-79843-impl-trait-with-missing-bounds-on-async-fn.stderr index cd1a8c4be8..a3ab0b8efb 100644 --- a/src/test/ui/suggestions/issue-79843-impl-trait-with-missing-bounds-on-async-fn.stderr +++ b/src/test/ui/suggestions/issue-79843-impl-trait-with-missing-bounds-on-async-fn.stderr @@ -2,7 +2,9 @@ error[E0277]: `::Bar` cannot be sent between threads safely --> $DIR/issue-79843-impl-trait-with-missing-bounds-on-async-fn.rs:14:20 | LL | assert_is_send(&bar); - | ^^^^ `::Bar` cannot be sent between threads safely + | -------------- ^^^^ `::Bar` cannot be sent between threads safely + | | + | required by a bound introduced by this call | = help: the trait `Send` is not implemented for `::Bar` note: required by a bound in `assert_is_send` @@ -19,7 +21,9 @@ error[E0277]: `::Bar` cannot be sent between threads safely --> $DIR/issue-79843-impl-trait-with-missing-bounds-on-async-fn.rs:24:20 | LL | assert_is_send(&bar); - | ^^^^ `::Bar` cannot be sent between threads safely + | -------------- ^^^^ `::Bar` cannot be sent between threads safely + | | + | required by a bound introduced by this call | = help: the trait `Send` is not implemented for `::Bar` note: required by a bound in `assert_is_send` diff --git a/src/test/ui/suggestions/issue-84973-2.stderr b/src/test/ui/suggestions/issue-84973-2.stderr index df1eeb7a2b..2c54ea6724 100644 --- a/src/test/ui/suggestions/issue-84973-2.stderr +++ b/src/test/ui/suggestions/issue-84973-2.stderr @@ -2,16 +2,19 @@ error[E0277]: the trait bound `i32: Tr` is not satisfied --> $DIR/issue-84973-2.rs:11:9 | LL | foo(a); - | ^ - | | - | expected an implementor of trait `Tr` - | help: consider mutably borrowing here: `&mut a` + | --- ^ expected an implementor of trait `Tr` + | | + | required by a bound introduced by this call | note: required by a bound in `foo` --> $DIR/issue-84973-2.rs:7:11 | LL | fn foo(i: T) {} | ^^ required by this bound in `foo` +help: consider mutably borrowing here + | +LL | foo(&mut a); + | ++++ error: aborting due to previous error diff --git a/src/test/ui/suggestions/issue-84973-blacklist.rs b/src/test/ui/suggestions/issue-84973-blacklist.rs index db954530b1..6813b07a2e 100644 --- a/src/test/ui/suggestions/issue-84973-blacklist.rs +++ b/src/test/ui/suggestions/issue-84973-blacklist.rs @@ -21,7 +21,6 @@ fn main() { let ref_cl: &dyn Fn() -> () = &cl; f_sized(*ref_cl); //~^ ERROR: the size for values of type `dyn Fn()` cannot be known at compilation time [E0277] - //~| ERROR: the size for values of type `dyn Fn()` cannot be known at compilation time [E0277] use std::rc::Rc; let rc = Rc::new(0); diff --git a/src/test/ui/suggestions/issue-84973-blacklist.stderr b/src/test/ui/suggestions/issue-84973-blacklist.stderr index 2ffe2f5a2b..ae55c96702 100644 --- a/src/test/ui/suggestions/issue-84973-blacklist.stderr +++ b/src/test/ui/suggestions/issue-84973-blacklist.stderr @@ -2,7 +2,9 @@ error[E0277]: the trait bound `String: Copy` is not satisfied --> $DIR/issue-84973-blacklist.rs:15:12 | LL | f_copy("".to_string()); - | ^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `String` + | ------ ^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `String` + | | + | required by a bound introduced by this call | note: required by a bound in `f_copy` --> $DIR/issue-84973-blacklist.rs:6:14 @@ -14,7 +16,9 @@ error[E0277]: the trait bound `S: Clone` is not satisfied --> $DIR/issue-84973-blacklist.rs:16:13 | LL | f_clone(S); - | ^ the trait `Clone` is not implemented for `S` + | ------- ^ the trait `Clone` is not implemented for `S` + | | + | required by a bound introduced by this call | note: required by a bound in `f_clone` --> $DIR/issue-84973-blacklist.rs:7:15 @@ -39,7 +43,9 @@ error[E0277]: the size for values of type `dyn Fn()` cannot be known at compilat --> $DIR/issue-84973-blacklist.rs:22:13 | LL | f_sized(*ref_cl); - | ^^^^^^^ doesn't have a size known at compile-time + | ------- ^^^^^^^ 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 `dyn Fn()` note: required by a bound in `f_sized` @@ -49,10 +55,12 @@ LL | fn f_sized(t: T) {} | ^ required by this bound in `f_sized` error[E0277]: `Rc<{integer}>` cannot be sent between threads safely - --> $DIR/issue-84973-blacklist.rs:28:12 + --> $DIR/issue-84973-blacklist.rs:27:12 | LL | f_send(rc); - | ^^ `Rc<{integer}>` cannot be sent between threads safely + | ------ ^^ `Rc<{integer}>` cannot be sent between threads safely + | | + | required by a bound introduced by this call | = help: the trait `Send` is not implemented for `Rc<{integer}>` note: required by a bound in `f_send` @@ -61,16 +69,6 @@ note: required by a bound in `f_send` LL | fn f_send(t: T) {} | ^^^^ required by this bound in `f_send` -error[E0277]: the size for values of type `dyn Fn()` cannot be known at compilation time - --> $DIR/issue-84973-blacklist.rs:22:5 - | -LL | f_sized(*ref_cl); - | ^^^^^^^ doesn't have a size known at compile-time - | - = help: the trait `Sized` is not implemented for `dyn Fn()` - = note: all function arguments must have a statically known size - = help: unsized fn params are gated as an unstable feature - -error: aborting due to 6 previous errors +error: aborting due to 5 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/suggestions/issue-84973-negative.stderr b/src/test/ui/suggestions/issue-84973-negative.stderr index bd1cf6ba61..1f33374eb2 100644 --- a/src/test/ui/suggestions/issue-84973-negative.stderr +++ b/src/test/ui/suggestions/issue-84973-negative.stderr @@ -2,7 +2,9 @@ error[E0277]: the trait bound `i32: Tr` is not satisfied --> $DIR/issue-84973-negative.rs:10:9 | LL | bar(a); - | ^ the trait `Tr` is not implemented for `i32` + | --- ^ the trait `Tr` is not implemented for `i32` + | | + | required by a bound introduced by this call | note: required by a bound in `bar` --> $DIR/issue-84973-negative.rs:5:11 @@ -14,16 +16,19 @@ error[E0277]: the trait bound `f32: Tr` is not satisfied --> $DIR/issue-84973-negative.rs:11:9 | LL | bar(b); - | ^ - | | - | expected an implementor of trait `Tr` - | help: consider borrowing here: `&b` + | --- ^ expected an implementor of trait `Tr` + | | + | required by a bound introduced by this call | note: required by a bound in `bar` --> $DIR/issue-84973-negative.rs:5:11 | LL | fn bar(t: T) {} | ^^ required by this bound in `bar` +help: consider borrowing here + | +LL | bar(&b); + | + error: aborting due to 2 previous errors diff --git a/src/test/ui/suggestions/issue-84973.stderr b/src/test/ui/suggestions/issue-84973.stderr index 649517b7d9..16a28c73aa 100644 --- a/src/test/ui/suggestions/issue-84973.stderr +++ b/src/test/ui/suggestions/issue-84973.stderr @@ -2,16 +2,19 @@ error[E0277]: the trait bound `Fancy: SomeTrait` is not satisfied --> $DIR/issue-84973.rs:6:24 | LL | let o = Other::new(f); - | ^ - | | - | expected an implementor of trait `SomeTrait` - | help: consider borrowing here: `&f` + | ---------- ^ expected an implementor of trait `SomeTrait` + | | + | required by a bound introduced by this call | note: required by `Other::<'a, G>::new` --> $DIR/issue-84973.rs:27:5 | LL | pub fn new(g: G) -> Self { | ^^^^^^^^^^^^^^^^^^^^^^^^ +help: consider borrowing here + | +LL | let o = Other::new(&f); + | + error: aborting due to previous error diff --git a/src/test/ui/suggestions/issue-88730.rs b/src/test/ui/suggestions/issue-88730.rs new file mode 100644 index 0000000000..e63210a3e9 --- /dev/null +++ b/src/test/ui/suggestions/issue-88730.rs @@ -0,0 +1,16 @@ +#![allow(unused, nonstandard_style)] +#![deny(bindings_with_variant_name)] + +// If an enum has two different variants, +// then it cannot be matched upon in a function argument. +// It still gets a warning, but no suggestions. +enum Foo { + C, + D, +} + +fn foo(C: Foo) {} //~ERROR + +fn main() { + let C = Foo::D; //~ERROR +} diff --git a/src/test/ui/suggestions/issue-88730.stderr b/src/test/ui/suggestions/issue-88730.stderr new file mode 100644 index 0000000000..eb22b0ea5c --- /dev/null +++ b/src/test/ui/suggestions/issue-88730.stderr @@ -0,0 +1,21 @@ +error[E0170]: pattern binding `C` is named the same as one of the variants of the type `Foo` + --> $DIR/issue-88730.rs:12:8 + | +LL | fn foo(C: Foo) {} + | ^ + | +note: the lint level is defined here + --> $DIR/issue-88730.rs:2:9 + | +LL | #![deny(bindings_with_variant_name)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0170]: pattern binding `C` is named the same as one of the variants of the type `Foo` + --> $DIR/issue-88730.rs:15:9 + | +LL | let C = Foo::D; + | ^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0170`. diff --git a/src/test/ui/suggestions/issue-89333.rs b/src/test/ui/suggestions/issue-89333.rs new file mode 100644 index 0000000000..03ed28ede2 --- /dev/null +++ b/src/test/ui/suggestions/issue-89333.rs @@ -0,0 +1,11 @@ +// check-fail +// Ensure we don't error when emitting trait bound not satisfied when self type +// has late bound var + +fn main() { + test(&|| 0); //~ ERROR the trait bound +} + +trait Trait {} + +fn test(arg: &impl Fn() -> T) where for<'a> &'a T: Trait {} diff --git a/src/test/ui/suggestions/issue-89333.stderr b/src/test/ui/suggestions/issue-89333.stderr new file mode 100644 index 0000000000..f73f1147d5 --- /dev/null +++ b/src/test/ui/suggestions/issue-89333.stderr @@ -0,0 +1,15 @@ +error[E0277]: the trait bound `for<'a> &'a _: Trait` is not satisfied + --> $DIR/issue-89333.rs:6:5 + | +LL | test(&|| 0); + | ^^^^ the trait `for<'a> Trait` is not implemented for `&'a _` + | +note: required by a bound in `test` + --> $DIR/issue-89333.rs:11:55 + | +LL | fn test(arg: &impl Fn() -> T) where for<'a> &'a T: Trait {} + | ^^^^^ required by this bound in `test` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/suggestions/issue-90213-expected-boxfuture-self-ice.rs b/src/test/ui/suggestions/issue-90213-expected-boxfuture-self-ice.rs new file mode 100644 index 0000000000..1e36b2fabf --- /dev/null +++ b/src/test/ui/suggestions/issue-90213-expected-boxfuture-self-ice.rs @@ -0,0 +1,13 @@ +// Checks that we do not ICE when comparing `Self` to `Pin` +// edition:2021 + +struct S; + +impl S { + fn foo(_: Box>) {} + fn bar() { + Self::foo(None) //~ ERROR mismatched types + } +} + +fn main() {} diff --git a/src/test/ui/suggestions/issue-90213-expected-boxfuture-self-ice.stderr b/src/test/ui/suggestions/issue-90213-expected-boxfuture-self-ice.stderr new file mode 100644 index 0000000000..c15b772b79 --- /dev/null +++ b/src/test/ui/suggestions/issue-90213-expected-boxfuture-self-ice.stderr @@ -0,0 +1,17 @@ +error[E0308]: mismatched types + --> $DIR/issue-90213-expected-boxfuture-self-ice.rs:9:19 + | +LL | Self::foo(None) + | ^^^^ expected struct `Box`, found enum `Option` + | + = note: expected struct `Box>` + found enum `Option<_>` + = note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html +help: store this in the heap by calling `Box::new` + | +LL | Self::foo(Box::new(None)) + | +++++++++ + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature-2.nll.stderr b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature-2.nll.stderr index 7e07a5775b..536494c734 100644 --- a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature-2.nll.stderr +++ b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature-2.nll.stderr @@ -7,7 +7,7 @@ LL | | t.test(); LL | | }); | |______^ | -note: the parameter type `T` must be valid for the anonymous lifetime defined on the function body at 19:24... +note: the parameter type `T` must be valid for the anonymous lifetime defined here... --> $DIR/missing-lifetimes-in-signature-2.rs:19:24 | LL | fn func(foo: &Foo, t: T) { 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 4e7d529784..0cf0074dc3 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 @@ -6,7 +6,7 @@ LL | fn func(foo: &Foo, t: T) { LL | foo.bar(move |_| { | ^^^ | -note: the parameter type `T` must be valid for the anonymous lifetime defined on the function body at 19:24... +note: the parameter type `T` must be valid for the anonymous lifetime defined here... --> $DIR/missing-lifetimes-in-signature-2.rs:19:24 | LL | fn func(foo: &Foo, t: T) { 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 b279803003..b579635ca7 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 @@ -32,8 +32,6 @@ LL | | current: None, LL | | remaining: self.0.iter(), LL | | } | |_________^ returning this value requires that `'a` must outlive `'static` - | - = help: consider replacing `'a` with `'static` error: lifetime may not live long enough --> $DIR/trait-object-nested-in-impl-trait.rs:60:30 @@ -43,7 +41,6 @@ LL | fn iter<'a>(&'a self) -> impl Iterator> { | | | lifetime `'a` defined here | - = help: consider replacing `'a` with `'static` help: to allow this `impl Trait` to capture borrowed data with lifetime `'a`, add `'a` as a bound | LL | fn iter<'a>(&'a self) -> impl Iterator> + 'a { diff --git a/src/test/ui/suggestions/missing-type-param-used-in-param.fixed b/src/test/ui/suggestions/missing-type-param-used-in-param.fixed new file mode 100644 index 0000000000..cc4120041b --- /dev/null +++ b/src/test/ui/suggestions/missing-type-param-used-in-param.fixed @@ -0,0 +1,8 @@ +// run-rustfix + +fn two_type_params(_: B) {} + +fn main() { + two_type_params::(100); //~ ERROR this function takes 2 generic arguments + two_type_params::(100); +} diff --git a/src/test/ui/suggestions/missing-type-param-used-in-param.rs b/src/test/ui/suggestions/missing-type-param-used-in-param.rs new file mode 100644 index 0000000000..19286331b6 --- /dev/null +++ b/src/test/ui/suggestions/missing-type-param-used-in-param.rs @@ -0,0 +1,8 @@ +// run-rustfix + +fn two_type_params(_: B) {} + +fn main() { + two_type_params::(100); //~ ERROR this function takes 2 generic arguments + two_type_params::(100); +} diff --git a/src/test/ui/suggestions/missing-type-param-used-in-param.stderr b/src/test/ui/suggestions/missing-type-param-used-in-param.stderr new file mode 100644 index 0000000000..4f7058a649 --- /dev/null +++ b/src/test/ui/suggestions/missing-type-param-used-in-param.stderr @@ -0,0 +1,21 @@ +error[E0107]: this function takes 2 generic arguments but 1 generic argument was supplied + --> $DIR/missing-type-param-used-in-param.rs:6:5 + | +LL | two_type_params::(100); + | ^^^^^^^^^^^^^^^ ------ supplied 1 generic argument + | | + | expected 2 generic arguments + | +note: function defined here, with 2 generic parameters: `A`, `B` + --> $DIR/missing-type-param-used-in-param.rs:3:4 + | +LL | fn two_type_params(_: B) {} + | ^^^^^^^^^^^^^^^ - - +help: add missing generic argument + | +LL | two_type_params::(100); + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0107`. 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 3b71d5cee9..e6a2231390 100644 --- a/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr +++ b/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr @@ -2,7 +2,9 @@ error[E0277]: the trait bound `&dyn std::io::Write: std::io::Write` is not satis --> $DIR/mut-borrow-needed-by-trait.rs:17:29 | LL | let fp = BufWriter::new(fp); - | ^^ the trait `std::io::Write` is not implemented for `&dyn std::io::Write` + | -------------- ^^ the trait `std::io::Write` is not implemented for `&dyn std::io::Write` + | | + | 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::::new` diff --git a/src/test/ui/suggestions/negative-literal-index.fixed b/src/test/ui/suggestions/negative-literal-index.fixed new file mode 100644 index 0000000000..e52714cf97 --- /dev/null +++ b/src/test/ui/suggestions/negative-literal-index.fixed @@ -0,0 +1,22 @@ +// run-rustfix + +use std::ops::Index; +struct X; +impl Index for X { + type Output = (); + + fn index(&self, _: i32) -> &() { + &() + } +} + +fn main() { + let x = vec![1, 2, 3]; + x[x.len() -1]; //~ ERROR negative integers cannot be used to index on a + let x = [1, 2, 3]; + x[x.len() -1]; //~ ERROR negative integers cannot be used to index on a + let x = &[1, 2, 3]; + x[x.len() -1]; //~ ERROR negative integers cannot be used to index on a + let _ = x; + X[-1]; +} diff --git a/src/test/ui/suggestions/negative-literal-index.rs b/src/test/ui/suggestions/negative-literal-index.rs new file mode 100644 index 0000000000..d88b66e679 --- /dev/null +++ b/src/test/ui/suggestions/negative-literal-index.rs @@ -0,0 +1,22 @@ +// run-rustfix + +use std::ops::Index; +struct X; +impl Index for X { + type Output = (); + + fn index(&self, _: i32) -> &() { + &() + } +} + +fn main() { + let x = vec![1, 2, 3]; + x[-1]; //~ ERROR negative integers cannot be used to index on a + let x = [1, 2, 3]; + x[-1]; //~ ERROR negative integers cannot be used to index on a + let x = &[1, 2, 3]; + x[-1]; //~ ERROR negative integers cannot be used to index on a + let _ = x; + X[-1]; +} diff --git a/src/test/ui/suggestions/negative-literal-index.stderr b/src/test/ui/suggestions/negative-literal-index.stderr new file mode 100644 index 0000000000..2b51bf7b7c --- /dev/null +++ b/src/test/ui/suggestions/negative-literal-index.stderr @@ -0,0 +1,35 @@ +error: negative integers cannot be used to index on a `Vec<{integer}>` + --> $DIR/negative-literal-index.rs:15:7 + | +LL | x[-1]; + | ^^ cannot use a negative integer for indexing on `Vec<{integer}>` + | +help: to access an element starting from the end of the `Vec<{integer}>`, compute the index + | +LL | x[x.len() -1]; + | +++++++ + +error: negative integers cannot be used to index on a `[{integer}; 3]` + --> $DIR/negative-literal-index.rs:17:7 + | +LL | x[-1]; + | ^^ cannot use a negative integer for indexing on `[{integer}; 3]` + | +help: to access an element starting from the end of the `[{integer}; 3]`, compute the index + | +LL | x[x.len() -1]; + | +++++++ + +error: negative integers cannot be used to index on a `[{integer}; 3]` + --> $DIR/negative-literal-index.rs:19:7 + | +LL | x[-1]; + | ^^ cannot use a negative integer for indexing on `[{integer}; 3]` + | +help: to access an element starting from the end of the `[{integer}; 3]`, compute the index + | +LL | x[x.len() -1]; + | +++++++ + +error: aborting due to 3 previous errors + diff --git a/src/test/ui/suggestions/nested-non-tuple-tuple-struct.rs b/src/test/ui/suggestions/nested-non-tuple-tuple-struct.rs new file mode 100644 index 0000000000..308adcf01f --- /dev/null +++ b/src/test/ui/suggestions/nested-non-tuple-tuple-struct.rs @@ -0,0 +1,18 @@ +pub struct S(f32, f32); + +pub enum E { + V(f32, f32), +} + +fn main() { + let _x = (S { x: 1.0, y: 2.0 }, S { x: 3.0, y: 4.0 }); + //~^ ERROR struct `S` has no field named `x` + //~| ERROR struct `S` has no field named `y` + //~| ERROR struct `S` has no field named `x` + //~| ERROR struct `S` has no field named `y` + let _y = (E::V { x: 1.0, y: 2.0 }, E::V { x: 3.0, y: 4.0 }); + //~^ ERROR variant `E::V` has no field named `x` + //~| ERROR variant `E::V` has no field named `y` + //~| ERROR variant `E::V` has no field named `x` + //~| ERROR variant `E::V` has no field named `y` +} diff --git a/src/test/ui/suggestions/nested-non-tuple-tuple-struct.stderr b/src/test/ui/suggestions/nested-non-tuple-tuple-struct.stderr new file mode 100644 index 0000000000..948f09fc3f --- /dev/null +++ b/src/test/ui/suggestions/nested-non-tuple-tuple-struct.stderr @@ -0,0 +1,116 @@ +error[E0560]: struct `S` has no field named `x` + --> $DIR/nested-non-tuple-tuple-struct.rs:8:19 + | +LL | pub struct S(f32, f32); + | - `S` defined here +... +LL | let _x = (S { x: 1.0, y: 2.0 }, S { x: 3.0, y: 4.0 }); + | ^ field does not exist + | +help: `S` is a tuple struct, use the appropriate syntax + | +LL | let _x = (S(/* fields */), S { x: 3.0, y: 4.0 }); + | ~~~~~~~~~~~~~~~ + +error[E0560]: struct `S` has no field named `y` + --> $DIR/nested-non-tuple-tuple-struct.rs:8:27 + | +LL | pub struct S(f32, f32); + | - `S` defined here +... +LL | let _x = (S { x: 1.0, y: 2.0 }, S { x: 3.0, y: 4.0 }); + | ^ field does not exist + | +help: `S` is a tuple struct, use the appropriate syntax + | +LL | let _x = (S(/* fields */), S { x: 3.0, y: 4.0 }); + | ~~~~~~~~~~~~~~~ + +error[E0560]: struct `S` has no field named `x` + --> $DIR/nested-non-tuple-tuple-struct.rs:8:41 + | +LL | pub struct S(f32, f32); + | - `S` defined here +... +LL | let _x = (S { x: 1.0, y: 2.0 }, S { x: 3.0, y: 4.0 }); + | ^ field does not exist + | +help: `S` is a tuple struct, use the appropriate syntax + | +LL | let _x = (S { x: 1.0, y: 2.0 }, S(/* fields */)); + | ~~~~~~~~~~~~~~~ + +error[E0560]: struct `S` has no field named `y` + --> $DIR/nested-non-tuple-tuple-struct.rs:8:49 + | +LL | pub struct S(f32, f32); + | - `S` defined here +... +LL | let _x = (S { x: 1.0, y: 2.0 }, S { x: 3.0, y: 4.0 }); + | ^ field does not exist + | +help: `S` is a tuple struct, use the appropriate syntax + | +LL | let _x = (S { x: 1.0, y: 2.0 }, S(/* fields */)); + | ~~~~~~~~~~~~~~~ + +error[E0559]: variant `E::V` has no field named `x` + --> $DIR/nested-non-tuple-tuple-struct.rs:13:22 + | +LL | V(f32, f32), + | - `E::V` defined here +... +LL | let _y = (E::V { x: 1.0, y: 2.0 }, E::V { x: 3.0, y: 4.0 }); + | ^ field does not exist + | +help: `E::V` is a tuple variant, use the appropriate syntax + | +LL | let _y = (E::V(/* fields */), E::V { x: 3.0, y: 4.0 }); + | ~~~~~~~~~~~~~~~~~~ + +error[E0559]: variant `E::V` has no field named `y` + --> $DIR/nested-non-tuple-tuple-struct.rs:13:30 + | +LL | V(f32, f32), + | - `E::V` defined here +... +LL | let _y = (E::V { x: 1.0, y: 2.0 }, E::V { x: 3.0, y: 4.0 }); + | ^ field does not exist + | +help: `E::V` is a tuple variant, use the appropriate syntax + | +LL | let _y = (E::V(/* fields */), E::V { x: 3.0, y: 4.0 }); + | ~~~~~~~~~~~~~~~~~~ + +error[E0559]: variant `E::V` has no field named `x` + --> $DIR/nested-non-tuple-tuple-struct.rs:13:47 + | +LL | V(f32, f32), + | - `E::V` defined here +... +LL | let _y = (E::V { x: 1.0, y: 2.0 }, E::V { x: 3.0, y: 4.0 }); + | ^ field does not exist + | +help: `E::V` is a tuple variant, use the appropriate syntax + | +LL | let _y = (E::V { x: 1.0, y: 2.0 }, E::V(/* fields */)); + | ~~~~~~~~~~~~~~~~~~ + +error[E0559]: variant `E::V` has no field named `y` + --> $DIR/nested-non-tuple-tuple-struct.rs:13:55 + | +LL | V(f32, f32), + | - `E::V` defined here +... +LL | let _y = (E::V { x: 1.0, y: 2.0 }, E::V { x: 3.0, y: 4.0 }); + | ^ field does not exist + | +help: `E::V` is a tuple variant, use the appropriate syntax + | +LL | let _y = (E::V { x: 1.0, y: 2.0 }, E::V(/* fields */)); + | ~~~~~~~~~~~~~~~~~~ + +error: aborting due to 8 previous errors + +Some errors have detailed explanations: E0559, E0560. +For more information about an error, try `rustc --explain E0559`. diff --git a/src/test/ui/suggestions/object-unsafe-trait-references-self.stderr b/src/test/ui/suggestions/object-unsafe-trait-references-self.stderr index f332b7213d..54f19fe9da 100644 --- a/src/test/ui/suggestions/object-unsafe-trait-references-self.stderr +++ b/src/test/ui/suggestions/object-unsafe-trait-references-self.stderr @@ -4,8 +4,6 @@ error[E0038]: the trait `Trait` cannot be made into an object LL | fn bar(x: &dyn Trait) {} | ^^^^^^^^^ `Trait` cannot be made into an object | - = help: consider moving `baz` to another trait - = help: consider moving `bat` to another trait note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit --> $DIR/object-unsafe-trait-references-self.rs:2:22 | @@ -15,6 +13,8 @@ LL | fn baz(&self, _: Self) {} | ^^^^ ...because method `baz` references the `Self` type in this parameter LL | fn bat(&self) -> Self {} | ^^^^ ...because method `bat` references the `Self` type in its return type + = help: consider moving `baz` to another trait + = help: consider moving `bat` to another trait error[E0038]: the trait `Other` cannot be made into an object --> $DIR/object-unsafe-trait-references-self.rs:10:12 diff --git a/src/test/ui/suggestions/option-content-move2.stderr b/src/test/ui/suggestions/option-content-move2.stderr index cfbee1518c..a0ce7d05b4 100644 --- a/src/test/ui/suggestions/option-content-move2.stderr +++ b/src/test/ui/suggestions/option-content-move2.stderr @@ -1,17 +1,22 @@ error[E0507]: cannot move out of `var`, a captured variable in an `FnMut` closure --> $DIR/option-content-move2.rs:9:9 | -LL | let mut var = None; - | ------- captured outer variable -... -LL | move || { - | ^^^^^^^ move out of `var` occurs here -LL | -LL | var = Some(NotCopyable); - | --- - | | - | move occurs because `var` has type `Option`, which does not implement the `Copy` trait - | move occurs due to use in closure +LL | let mut var = None; + | ------- captured outer variable +LL | func(|| { + | __________- +LL | | // Shouldn't suggest `move ||.as_ref()` here +LL | | move || { + | | ^^^^^^^ move out of `var` occurs here +LL | | +LL | | var = Some(NotCopyable); + | | --- + | | | + | | move occurs because `var` has type `Option`, which does not implement the `Copy` trait + | | move occurs due to use in closure +LL | | } +LL | | }); + | |_____- captured by this `FnMut` closure error: aborting due to previous error diff --git a/src/test/ui/suggestions/restrict-type-argument.stderr b/src/test/ui/suggestions/restrict-type-argument.stderr index b62502fb6a..551a7c5060 100644 --- a/src/test/ui/suggestions/restrict-type-argument.stderr +++ b/src/test/ui/suggestions/restrict-type-argument.stderr @@ -2,7 +2,9 @@ error[E0277]: `impl Sync` cannot be sent between threads safely --> $DIR/restrict-type-argument.rs:4:13 | LL | is_send(val); - | ^^^ `impl Sync` cannot be sent between threads safely + | ------- ^^^ `impl Sync` cannot be sent between threads safely + | | + | required by a bound introduced by this call | note: required by a bound in `is_send` --> $DIR/restrict-type-argument.rs:1:15 @@ -18,7 +20,9 @@ error[E0277]: `S` cannot be sent between threads safely --> $DIR/restrict-type-argument.rs:8:13 | LL | is_send(val); - | ^^^ `S` cannot be sent between threads safely + | ------- ^^^ `S` cannot be sent between threads safely + | | + | required by a bound introduced by this call | note: required by a bound in `is_send` --> $DIR/restrict-type-argument.rs:1:15 @@ -34,7 +38,9 @@ error[E0277]: `S` cannot be sent between threads safely --> $DIR/restrict-type-argument.rs:12:13 | LL | is_send(val); - | ^^^ `S` cannot be sent between threads safely + | ------- ^^^ `S` cannot be sent between threads safely + | | + | required by a bound introduced by this call | note: required by a bound in `is_send` --> $DIR/restrict-type-argument.rs:1:15 @@ -50,7 +56,9 @@ error[E0277]: `S` cannot be sent between threads safely --> $DIR/restrict-type-argument.rs:20:13 | LL | is_send(val); - | ^^^ `S` cannot be sent between threads safely + | ------- ^^^ `S` cannot be sent between threads safely + | | + | required by a bound introduced by this call | note: required by a bound in `is_send` --> $DIR/restrict-type-argument.rs:1:15 @@ -66,7 +74,9 @@ error[E0277]: `S` cannot be sent between threads safely --> $DIR/restrict-type-argument.rs:24:13 | LL | is_send(val); - | ^^^ `S` cannot be sent between threads safely + | ------- ^^^ `S` cannot be sent between threads safely + | | + | required by a bound introduced by this call | note: required by a bound in `is_send` --> $DIR/restrict-type-argument.rs:1:15 @@ -82,7 +92,9 @@ error[E0277]: `S` cannot be sent between threads safely --> $DIR/restrict-type-argument.rs:28:13 | LL | is_send(val); - | ^^^ `S` cannot be sent between threads safely + | ------- ^^^ `S` cannot be sent between threads safely + | | + | required by a bound introduced by this call | note: required by a bound in `is_send` --> $DIR/restrict-type-argument.rs:1:15 diff --git a/src/test/ui/suggestions/slice-issue-87994.rs b/src/test/ui/suggestions/slice-issue-87994.rs new file mode 100644 index 0000000000..ecb7f54ea2 --- /dev/null +++ b/src/test/ui/suggestions/slice-issue-87994.rs @@ -0,0 +1,16 @@ +fn main() { + let v = vec![1i32, 2, 3]; + for _ in v[1..] { + //~^ ERROR [i32]` is not an iterator [E0277] + //~^^ ERROR known at compilation time + } + struct K { + n: i32, + } + let mut v2 = vec![K { n: 1 }, K { n: 1 }, K { n: 1 }]; + for i2 in v2[1..] { + //~^ ERROR [K]` is not an iterator [E0277] + //~^^ ERROR known at compilation time + i2.n = 2; + } +} diff --git a/src/test/ui/suggestions/slice-issue-87994.stderr b/src/test/ui/suggestions/slice-issue-87994.stderr new file mode 100644 index 0000000000..0275fd475d --- /dev/null +++ b/src/test/ui/suggestions/slice-issue-87994.stderr @@ -0,0 +1,83 @@ +error[E0277]: the size for values of type `[i32]` cannot be known at compilation time + --> $DIR/slice-issue-87994.rs:3:12 + | +LL | for _ in v[1..] { + | ^^^^^^ expected an implementor of trait `IntoIterator` + | + = 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..] { + | + +LL | for _ in &mut v[1..] { + | ++++ + +error[E0277]: `[i32]` is not an iterator + --> $DIR/slice-issue-87994.rs:3:12 + | +LL | for _ in v[1..] { + | ^^^^^^ expected an implementor of trait `IntoIterator` + | + = 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..] { + | + +LL | for _ in &mut v[1..] { + | ++++ + +error[E0277]: the size for values of type `[K]` cannot be known at compilation time + --> $DIR/slice-issue-87994.rs:11:13 + | +LL | for i2 in v2[1..] { + | ^^^^^^^ expected an implementor of trait `IntoIterator` + | + = 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..] { + | + +LL | for i2 in &mut v2[1..] { + | ++++ + +error[E0277]: `[K]` is not an iterator + --> $DIR/slice-issue-87994.rs:11:13 + | +LL | for i2 in v2[1..] { + | ^^^^^^^ expected an implementor of trait `IntoIterator` + | + = 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..] { + | + +LL | for i2 in &mut v2[1..] { + | ++++ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/suggestions/suggest-change-mut.stderr b/src/test/ui/suggestions/suggest-change-mut.stderr index 1f14ebae84..8dfab8dfa1 100644 --- a/src/test/ui/suggestions/suggest-change-mut.stderr +++ b/src/test/ui/suggestions/suggest-change-mut.stderr @@ -2,7 +2,9 @@ error[E0277]: the trait bound `&T: std::io::Read` is not satisfied --> $DIR/suggest-change-mut.rs:12:48 | LL | let mut stream_reader = BufReader::new(&stream); - | ^^^^^^^ the trait `std::io::Read` is not implemented for `&T` + | -------------- ^^^^^^^ the trait `std::io::Read` is not implemented for `&T` + | | + | required by a bound introduced by this call | note: required by `BufReader::::new` --> $SRC_DIR/std/src/io/buffered/bufreader.rs:LL:COL diff --git a/src/test/ui/suggestions/suggest-imm-mut-trait-implementations.rs b/src/test/ui/suggestions/suggest-imm-mut-trait-implementations.rs new file mode 100644 index 0000000000..a62669d5b2 --- /dev/null +++ b/src/test/ui/suggestions/suggest-imm-mut-trait-implementations.rs @@ -0,0 +1,23 @@ +trait Trait {} + +struct A; +struct B; +struct C; + +impl Trait for &A {} +impl Trait for &mut A {} + +impl Trait for &B {} + +impl Trait for &mut C {} + +fn foo(_: X) {} + +fn main() { + let a = A; + let b = B; + let c = C; + foo(a); //~ ERROR the trait bound `A: Trait` is not satisfied + foo(b); //~ ERROR the trait bound `B: Trait` is not satisfied + foo(c); //~ ERROR the trait bound `C: Trait` is not satisfied +} diff --git a/src/test/ui/suggestions/suggest-imm-mut-trait-implementations.stderr b/src/test/ui/suggestions/suggest-imm-mut-trait-implementations.stderr new file mode 100644 index 0000000000..6583cabe18 --- /dev/null +++ b/src/test/ui/suggestions/suggest-imm-mut-trait-implementations.stderr @@ -0,0 +1,59 @@ +error[E0277]: the trait bound `A: Trait` is not satisfied + --> $DIR/suggest-imm-mut-trait-implementations.rs:20:9 + | +LL | foo(a); + | --- ^ expected an implementor of trait `Trait` + | | + | required by a bound introduced by this call + | +note: required by a bound in `foo` + --> $DIR/suggest-imm-mut-trait-implementations.rs:14:11 + | +LL | fn foo(_: X) {} + | ^^^^^ required by this bound in `foo` +help: consider borrowing here + | +LL | foo(&a); + | + +LL | foo(&mut a); + | ++++ + +error[E0277]: the trait bound `B: Trait` is not satisfied + --> $DIR/suggest-imm-mut-trait-implementations.rs:21:9 + | +LL | foo(b); + | --- ^ expected an implementor of trait `Trait` + | | + | required by a bound introduced by this call + | +note: required by a bound in `foo` + --> $DIR/suggest-imm-mut-trait-implementations.rs:14:11 + | +LL | fn foo(_: X) {} + | ^^^^^ required by this bound in `foo` +help: consider borrowing here + | +LL | foo(&b); + | + + +error[E0277]: the trait bound `C: Trait` is not satisfied + --> $DIR/suggest-imm-mut-trait-implementations.rs:22:9 + | +LL | foo(c); + | --- ^ expected an implementor of trait `Trait` + | | + | required by a bound introduced by this call + | +note: required by a bound in `foo` + --> $DIR/suggest-imm-mut-trait-implementations.rs:14:11 + | +LL | fn foo(_: X) {} + | ^^^^^ required by this bound in `foo` +help: consider mutably borrowing here + | +LL | foo(&mut c); + | ++++ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/suggestions/suggest-ref-macro.stderr b/src/test/ui/suggestions/suggest-ref-macro.stderr index 1f41d2329e..5c05810e58 100644 --- a/src/test/ui/suggestions/suggest-ref-macro.stderr +++ b/src/test/ui/suggestions/suggest-ref-macro.stderr @@ -8,7 +8,7 @@ LL | x(123); | help: consider mutably borrowing here: `&mut 123` ... LL | bla!(); - | ------- in this macro invocation + | ------ in this macro invocation | = note: this error originates in the macro `bla` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/suggestions/suggest-trait-items.rs b/src/test/ui/suggestions/suggest-trait-items.rs new file mode 100644 index 0000000000..9d42a73426 --- /dev/null +++ b/src/test/ui/suggestions/suggest-trait-items.rs @@ -0,0 +1,48 @@ +trait Foo { + type Type; + + fn foo(); + fn bar(); + fn qux(); +} + +struct A; + +impl Foo for A { +//~^ ERROR not all trait items implemented + type Typ = (); + //~^ ERROR type `Typ` is not a member of trait + //~| HELP there is an associated type with a similar name + + fn fooo() {} + //~^ ERROR method `fooo` is not a member of trait + //~| HELP there is an associated function with a similar name + + fn barr() {} + //~^ ERROR method `barr` is not a member of trait + //~| HELP there is an associated function with a similar name + + fn quux() {} + //~^ ERROR method `quux` is not a member of trait + //~| HELP there is an associated function with a similar name +} +//~^ HELP implement the missing item +//~| HELP implement the missing item +//~| HELP implement the missing item +//~| HELP implement the missing item + +trait Bar { + const Const: i32; +} + +struct B; + +impl Bar for B { +//~^ ERROR not all trait items implemented + const Cnst: i32 = 0; + //~^ ERROR const `Cnst` is not a member of trait + //~| HELP there is an associated constant with a similar name +} +//~^ HELP implement the missing item + +fn main() {} diff --git a/src/test/ui/suggestions/suggest-trait-items.stderr b/src/test/ui/suggestions/suggest-trait-items.stderr new file mode 100644 index 0000000000..151bae7d1b --- /dev/null +++ b/src/test/ui/suggestions/suggest-trait-items.stderr @@ -0,0 +1,74 @@ +error[E0437]: type `Typ` is not a member of trait `Foo` + --> $DIR/suggest-trait-items.rs:13:5 + | +LL | type Typ = (); + | ^^^^^---^^^^^^ + | | | + | | help: there is an associated type with a similar name: `Type` + | not a member of trait `Foo` + +error[E0407]: method `fooo` is not a member of trait `Foo` + --> $DIR/suggest-trait-items.rs:17:5 + | +LL | fn fooo() {} + | ^^^----^^^^^ + | | | + | | help: there is an associated function with a similar name: `foo` + | not a member of trait `Foo` + +error[E0407]: method `barr` is not a member of trait `Foo` + --> $DIR/suggest-trait-items.rs:21:5 + | +LL | fn barr() {} + | ^^^----^^^^^ + | | | + | | help: there is an associated function with a similar name: `bar` + | not a member of trait `Foo` + +error[E0407]: method `quux` is not a member of trait `Foo` + --> $DIR/suggest-trait-items.rs:25:5 + | +LL | fn quux() {} + | ^^^----^^^^^ + | | | + | | help: there is an associated function with a similar name: `qux` + | not a member of trait `Foo` + +error[E0438]: const `Cnst` is not a member of trait `Bar` + --> $DIR/suggest-trait-items.rs:42:5 + | +LL | const Cnst: i32 = 0; + | ^^^^^^----^^^^^^^^^^ + | | | + | | help: there is an associated constant with a similar name: `Const` + | not a member of trait `Bar` + +error[E0046]: not all trait items implemented, missing: `Type`, `foo`, `bar`, `qux` + --> $DIR/suggest-trait-items.rs:11:1 + | +LL | type Type; + | ---------- `Type` from trait +LL | +LL | fn foo(); + | --------- `foo` from trait +LL | fn bar(); + | --------- `bar` from trait +LL | fn qux(); + | --------- `qux` from trait +... +LL | impl Foo for A { + | ^^^^^^^^^^^^^^ missing `Type`, `foo`, `bar`, `qux` in implementation + +error[E0046]: not all trait items implemented, missing: `Const` + --> $DIR/suggest-trait-items.rs:40:1 + | +LL | const Const: i32; + | ----------------- `Const` from trait +... +LL | impl Bar for B { + | ^^^^^^^^^^^^^^ missing `Const` in implementation + +error: aborting due to 7 previous errors + +Some errors have detailed explanations: E0046, E0407, E0437, E0438. +For more information about an error, try `rustc --explain E0046`. diff --git a/src/test/ui/suggestions/type-mismatch-struct-field-shorthand-2.stderr b/src/test/ui/suggestions/type-mismatch-struct-field-shorthand-2.stderr index b391cd4beb..12466868f0 100644 --- a/src/test/ui/suggestions/type-mismatch-struct-field-shorthand-2.stderr +++ b/src/test/ui/suggestions/type-mismatch-struct-field-shorthand-2.stderr @@ -2,19 +2,23 @@ error[E0308]: mismatched types --> $DIR/type-mismatch-struct-field-shorthand-2.rs:5:19 | LL | let _ = RGB { r, g, c }; - | ^ - | | - | expected `f64`, found `f32` - | help: you can convert an `f32` to an `f64`: `r: r.into()` + | ^ expected `f64`, found `f32` + | +help: you can convert an `f32` to an `f64` + | +LL | let _ = RGB { r: r.into(), g, c }; + | ++ +++++++ error[E0308]: mismatched types --> $DIR/type-mismatch-struct-field-shorthand-2.rs:5:22 | LL | let _ = RGB { r, g, c }; - | ^ - | | - | expected `f64`, found `f32` - | help: you can convert an `f32` to an `f64`: `g: g.into()` + | ^ expected `f64`, found `f32` + | +help: you can convert an `f32` to an `f64` + | +LL | let _ = RGB { r, g: g.into(), c }; + | ++ +++++++ error[E0560]: struct `RGB` has no field named `c` --> $DIR/type-mismatch-struct-field-shorthand-2.rs:5:25 diff --git a/src/test/ui/suggestions/type-mismatch-struct-field-shorthand.stderr b/src/test/ui/suggestions/type-mismatch-struct-field-shorthand.stderr index 61ea852a8c..72c84d1671 100644 --- a/src/test/ui/suggestions/type-mismatch-struct-field-shorthand.stderr +++ b/src/test/ui/suggestions/type-mismatch-struct-field-shorthand.stderr @@ -2,28 +2,34 @@ error[E0308]: mismatched types --> $DIR/type-mismatch-struct-field-shorthand.rs:8:19 | LL | let _ = RGB { r, g, b }; - | ^ - | | - | expected `f64`, found `f32` - | help: you can convert an `f32` to an `f64`: `r: r.into()` + | ^ expected `f64`, found `f32` + | +help: you can convert an `f32` to an `f64` + | +LL | let _ = RGB { r: r.into(), g, b }; + | ++ +++++++ error[E0308]: mismatched types --> $DIR/type-mismatch-struct-field-shorthand.rs:8:22 | LL | let _ = RGB { r, g, b }; - | ^ - | | - | expected `f64`, found `f32` - | help: you can convert an `f32` to an `f64`: `g: g.into()` + | ^ expected `f64`, found `f32` + | +help: you can convert an `f32` to an `f64` + | +LL | let _ = RGB { r, g: g.into(), b }; + | ++ +++++++ error[E0308]: mismatched types --> $DIR/type-mismatch-struct-field-shorthand.rs:8:25 | LL | let _ = RGB { r, g, b }; - | ^ - | | - | expected `f64`, found `f32` - | help: you can convert an `f32` to an `f64`: `b: b.into()` + | ^ expected `f64`, found `f32` + | +help: you can convert an `f32` to an `f64` + | +LL | let _ = RGB { r, g, b: b.into() }; + | ++ +++++++ error: aborting due to 3 previous errors diff --git a/src/test/ui/symbol-names/const-generics-structural-demangling.stderr b/src/test/ui/symbol-names/const-generics-structural-demangling.stderr index b3c5bd2b89..45cbcecaca 100644 --- a/src/test/ui/symbol-names/const-generics-structural-demangling.stderr +++ b/src/test/ui/symbol-names/const-generics-structural-demangling.stderr @@ -131,7 +131,7 @@ LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ ... LL | duplicate_field_name_test!(x); - | ------------------------------ in this macro invocation + | ----------------------------- in this macro invocation | = note: this error originates in the macro `duplicate_field_name_test` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -142,7 +142,7 @@ LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ ... LL | duplicate_field_name_test!(x); - | ------------------------------ in this macro invocation + | ----------------------------- in this macro invocation | = note: this error originates in the macro `duplicate_field_name_test` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -153,7 +153,7 @@ LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ ... LL | duplicate_field_name_test!(x); - | ------------------------------ in this macro invocation + | ----------------------------- in this macro invocation | = note: this error originates in the macro `duplicate_field_name_test` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/issues/issue-53912.rs b/src/test/ui/symbol-names/issue-53912.rs similarity index 100% rename from src/test/ui/issues/issue-53912.rs rename to src/test/ui/symbol-names/issue-53912.rs diff --git a/src/test/ui/tail-typeck.stderr b/src/test/ui/tail-typeck.stderr index 422aa904e1..10dfd2de74 100644 --- a/src/test/ui/tail-typeck.stderr +++ b/src/test/ui/tail-typeck.stderr @@ -9,7 +9,7 @@ LL | fn f() -> isize { return g(); } help: you can convert a `usize` to an `isize` and panic if the converted value doesn't fit | LL | fn f() -> isize { return g().try_into().unwrap(); } - | ~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-36768.rs b/src/test/ui/test-attrs/issue-36768.rs similarity index 100% rename from src/test/ui/issues/issue-36768.rs rename to src/test/ui/test-attrs/issue-36768.rs diff --git a/src/test/ui/test-attrs/test-should-panic-attr.stderr b/src/test/ui/test-attrs/test-should-panic-attr.stderr index 375ee79ca5..492d1d5e03 100644 --- a/src/test/ui/test-attrs/test-should-panic-attr.stderr +++ b/src/test/ui/test-attrs/test-should-panic-attr.stderr @@ -4,7 +4,7 @@ warning: argument must be of the form: `expected = "error message"` LL | #[should_panic(expected)] | ^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: errors in this attribute were erroneously allowed and will become a hard error in a future release. + = note: errors in this attribute were erroneously allowed and will become a hard error in a future release warning: argument must be of the form: `expected = "error message"` --> $DIR/test-should-panic-attr.rs:18:1 @@ -12,7 +12,7 @@ warning: argument must be of the form: `expected = "error message"` LL | #[should_panic(expect)] | ^^^^^^^^^^^^^^^^^^^^^^^ | - = note: errors in this attribute were erroneously allowed and will become a hard error in a future release. + = note: errors in this attribute were erroneously allowed and will become a hard error in a future release warning: argument must be of the form: `expected = "error message"` --> $DIR/test-should-panic-attr.rs:25:1 @@ -20,7 +20,7 @@ warning: argument must be of the form: `expected = "error message"` LL | #[should_panic(expected(foo, bar))] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: errors in this attribute were erroneously allowed and will become a hard error in a future release. + = note: errors in this attribute were erroneously allowed and will become a hard error in a future release warning: argument must be of the form: `expected = "error message"` --> $DIR/test-should-panic-attr.rs:32:1 @@ -28,7 +28,7 @@ warning: argument must be of the form: `expected = "error message"` LL | #[should_panic(expected = "foo", bar)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: errors in this attribute were erroneously allowed and will become a hard error in a future release. + = note: errors in this attribute were erroneously allowed and will become a hard error in a future release warning: 4 warnings emitted diff --git a/src/test/ui/tls.rs b/src/test/ui/thread-local/tls.rs similarity index 100% rename from src/test/ui/tls.rs rename to src/test/ui/thread-local/tls.rs diff --git a/src/test/ui/threads-sendsync/sendfn-spawn-with-fn-arg.rs b/src/test/ui/threads-sendsync/sendfn-spawn-with-fn-arg.rs index 8c40b2a5f1..1e598b9e70 100644 --- a/src/test/ui/threads-sendsync/sendfn-spawn-with-fn-arg.rs +++ b/src/test/ui/threads-sendsync/sendfn-spawn-with-fn-arg.rs @@ -1,8 +1,6 @@ // run-pass // ignore-emscripten no threads support -#![feature(box_syntax)] - use std::thread; pub fn main() { test05(); } @@ -12,7 +10,7 @@ fn test05_start(f: F) { } fn test05() { - let three: Box<_> = box 3; + let three: Box<_> = Box::new(3); let fn_to_send = move|n:isize| { println!("{}", *three + n); // will copy x into the closure assert_eq!(*three, 3); diff --git a/src/test/ui/threads-sendsync/task-spawn-move-and-copy.rs b/src/test/ui/threads-sendsync/task-spawn-move-and-copy.rs index 458f565388..a639037780 100644 --- a/src/test/ui/threads-sendsync/task-spawn-move-and-copy.rs +++ b/src/test/ui/threads-sendsync/task-spawn-move-and-copy.rs @@ -2,15 +2,13 @@ #![allow(unused_must_use)] // ignore-emscripten no threads support -#![feature(box_syntax)] - use std::thread; use std::sync::mpsc::channel; pub fn main() { let (tx, rx) = channel::(); - let x: Box = box 1; + let x: Box = Box::new(1); let x_in_parent = &(*x) as *const isize as usize; let t = thread::spawn(move || { diff --git a/src/test/ui/trace_macros-format.stderr b/src/test/ui/trace_macros-format.stderr index 650b870769..c32027086a 100644 --- a/src/test/ui/trace_macros-format.stderr +++ b/src/test/ui/trace_macros-format.stderr @@ -2,37 +2,37 @@ error: trace_macros! accepts only `true` or `false` --> $DIR/trace_macros-format.rs:4:5 | LL | trace_macros!(); - | ^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^ error: trace_macros! accepts only `true` or `false` --> $DIR/trace_macros-format.rs:5:5 | LL | trace_macros!(1); - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ error: trace_macros! accepts only `true` or `false` --> $DIR/trace_macros-format.rs:6:5 | LL | trace_macros!(ident); - | ^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^ error: trace_macros! accepts only `true` or `false` --> $DIR/trace_macros-format.rs:7:5 | LL | trace_macros!(for); - | ^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^ error: trace_macros! accepts only `true` or `false` --> $DIR/trace_macros-format.rs:8:5 | LL | trace_macros!(true,); - | ^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^ error: trace_macros! accepts only `true` or `false` --> $DIR/trace_macros-format.rs:9:5 | LL | trace_macros!(false 1); - | ^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 6 previous errors diff --git a/src/test/ui/traits/alias/no-duplicates.stderr b/src/test/ui/traits/alias/no-duplicates.stderr index 9f38dd40c3..d3002db46a 100644 --- a/src/test/ui/traits/alias/no-duplicates.stderr +++ b/src/test/ui/traits/alias/no-duplicates.stderr @@ -12,7 +12,7 @@ LL | type _T00 = dyn _0 + _0; | | | trait alias used in trait object type (first use) | - = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Obj + Obj {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error[E0225]: only auto traits can be used as additional traits in a trait object @@ -31,7 +31,7 @@ LL | type _T01 = dyn _1 + _0; | | | trait alias used in trait object type (first use) | - = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Obj + Obj {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error[E0225]: only auto traits can be used as additional traits in a trait object @@ -53,7 +53,7 @@ LL | type _T02 = dyn _1 + _1; | | | trait alias used in trait object type (first use) | - = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Obj + Obj {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error[E0225]: only auto traits can be used as additional traits in a trait object @@ -69,7 +69,7 @@ LL | type _T03 = dyn Obj + _1; | | | first non-auto trait | - = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Obj + Obj {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error[E0225]: only auto traits can be used as additional traits in a trait object @@ -85,7 +85,7 @@ LL | type _T04 = dyn _1 + Obj; | | | trait alias used in trait object type (first use) | - = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Obj + Obj {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error[E0225]: only auto traits can be used as additional traits in a trait object @@ -110,7 +110,7 @@ LL | type _T10 = dyn _2 + _3; | trait alias used in trait object type (additional use) | trait alias used in trait object type (first use) | - = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Obj + Obj + Obj {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj + Obj {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error[E0225]: only auto traits can be used as additional traits in a trait object @@ -129,7 +129,7 @@ LL | type _T11 = dyn _3 + _2; | | | trait alias used in trait object type (first use) | - = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Obj + Obj + Obj {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj + Obj {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error[E0225]: only auto traits can be used as additional traits in a trait object @@ -146,7 +146,7 @@ LL | type _T12 = dyn Obj + _2; | | | first non-auto trait | - = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Obj + Obj + Obj {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj + Obj {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error[E0225]: only auto traits can be used as additional traits in a trait object @@ -171,7 +171,7 @@ LL | type _T13 = dyn _2 + Obj; | trait alias used in trait object type (additional use) | trait alias used in trait object type (first use) | - = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Obj + Obj + Obj {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj + Obj {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error[E0225]: only auto traits can be used as additional traits in a trait object @@ -190,7 +190,7 @@ LL | type _T14 = dyn _1 + _3; | | | trait alias used in trait object type (first use) | - = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Obj + Obj {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error[E0225]: only auto traits can be used as additional traits in a trait object @@ -209,7 +209,7 @@ LL | type _T15 = dyn _3 + _1; | | | trait alias used in trait object type (first use) | - = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Obj + Obj {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error[E0225]: only auto traits can be used as additional traits in a trait object @@ -230,7 +230,7 @@ LL | type _T16 = dyn _1 + _4; | | | trait alias used in trait object type (first use) | - = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Obj + Obj {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error[E0225]: only auto traits can be used as additional traits in a trait object @@ -251,7 +251,7 @@ LL | type _T17 = dyn _4 + _1; | | | trait alias used in trait object type (first use) | - = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Obj + Obj {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error[E0225]: only auto traits can be used as additional traits in a trait object @@ -268,7 +268,7 @@ LL | type _T20 = dyn _5 + _5; | | | trait alias used in trait object type (first use) | - = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Obj + Obj {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error[E0225]: only auto traits can be used as additional traits in a trait object @@ -282,7 +282,7 @@ LL | type _T21 = dyn Obj + _5; | | | first non-auto trait | - = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Obj + Obj {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error[E0225]: only auto traits can be used as additional traits in a trait object @@ -296,7 +296,7 @@ LL | type _T22 = dyn _5 + Obj; | | | trait alias used in trait object type (first use) | - = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Obj + Obj {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error[E0225]: only auto traits can be used as additional traits in a trait object @@ -310,7 +310,7 @@ LL | type _T23 = dyn _5 + Send + Sync + Obj; | | | trait alias used in trait object type (first use) | - = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Obj + Obj {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error[E0225]: only auto traits can be used as additional traits in a trait object @@ -333,7 +333,7 @@ LL | type _T30 = dyn _6; | trait alias used in trait object type (additional use) | trait alias used in trait object type (first use) | - = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Obj + Obj {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error[E0225]: only auto traits can be used as additional traits in a trait object @@ -356,7 +356,7 @@ LL | type _T31 = dyn _6 + Send; | trait alias used in trait object type (additional use) | trait alias used in trait object type (first use) | - = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Obj + Obj {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error[E0225]: only auto traits can be used as additional traits in a trait object @@ -379,7 +379,7 @@ LL | type _T32 = dyn Send + _6; | trait alias used in trait object type (additional use) | trait alias used in trait object type (first use) | - = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Obj + Obj {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error[E0225]: only auto traits can be used as additional traits in a trait object @@ -398,7 +398,7 @@ LL | type _T40 = dyn _8 + Obj; | | | trait alias used in trait object type (first use) | - = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Obj + Obj {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error[E0225]: only auto traits can be used as additional traits in a trait object @@ -417,7 +417,7 @@ LL | type _T41 = dyn Obj + _8; | | | first non-auto trait | - = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Obj + Obj {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error[E0225]: only auto traits can be used as additional traits in a trait object @@ -441,7 +441,7 @@ LL | type _T42 = dyn _8 + _4; | | | trait alias used in trait object type (first use) | - = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Obj + Obj {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error[E0225]: only auto traits can be used as additional traits in a trait object @@ -465,7 +465,7 @@ LL | type _T43 = dyn _4 + _8; | | | trait alias used in trait object type (first use) | - = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Obj + Obj {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error[E0225]: only auto traits can be used as additional traits in a trait object @@ -489,7 +489,7 @@ LL | type _T44 = dyn _4 + Send + Sync + _8; | | | trait alias used in trait object type (first use) | - = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Obj + Obj {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error[E0225]: only auto traits can be used as additional traits in a trait object @@ -504,7 +504,7 @@ LL | type _T50 = dyn _9 + _10; | | | trait alias used in trait object type (first use) | - = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: for<'a> ObjL<'a> + for<'b> ObjL<'b> {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: for<'a> ObjL<'a> + for<'b> ObjL<'b> {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error[E0225]: only auto traits can be used as additional traits in a trait object @@ -519,7 +519,7 @@ LL | type _T60 = dyn _11 + _12; | | | trait alias used in trait object type (first use) | - = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: ObjT fn(&'a u8)> + ObjT fn(&'b u8)> {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjT fn(&'a u8)> + ObjT fn(&'b u8)> {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error: aborting due to 27 previous errors diff --git a/src/test/ui/traits/alias/no-extra-traits.stderr b/src/test/ui/traits/alias/no-extra-traits.stderr index cdb5cd90b8..eaba70d7ce 100644 --- a/src/test/ui/traits/alias/no-extra-traits.stderr +++ b/src/test/ui/traits/alias/no-extra-traits.stderr @@ -9,7 +9,7 @@ LL | type _T00 = dyn _0 + ObjB; | | | trait alias used in trait object type (first use) | - = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error[E0225]: only auto traits can be used as additional traits in a trait object @@ -23,7 +23,7 @@ LL | type _T01 = dyn ObjB + _0; | | | first non-auto trait | - = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error[E0225]: only auto traits can be used as additional traits in a trait object @@ -39,7 +39,7 @@ LL | type _T02 = dyn ObjB + _1; | | | first non-auto trait | - = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error[E0225]: only auto traits can be used as additional traits in a trait object @@ -55,7 +55,7 @@ LL | type _T03 = dyn _1 + ObjB; | | | trait alias used in trait object type (first use) | - = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error[E0225]: only auto traits can be used as additional traits in a trait object @@ -74,7 +74,7 @@ LL | type _T10 = dyn _2 + _3; | | | trait alias used in trait object type (first use) | - = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: ObjB + ObjB {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjB + ObjB {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error[E0225]: only auto traits can be used as additional traits in a trait object @@ -93,7 +93,7 @@ LL | type _T11 = dyn _3 + _2; | | | trait alias used in trait object type (first use) | - = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: ObjB + ObjB {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjB + ObjB {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error[E0225]: only auto traits can be used as additional traits in a trait object @@ -114,7 +114,7 @@ LL | type _T12 = dyn _2 + _4; | | | trait alias used in trait object type (first use) | - = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: ObjB + ObjB {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjB + ObjB {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error[E0225]: only auto traits can be used as additional traits in a trait object @@ -135,7 +135,7 @@ LL | type _T13 = dyn _4 + _2; | | | trait alias used in trait object type (first use) | - = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: ObjB + ObjB {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjB + ObjB {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error[E0225]: only auto traits can be used as additional traits in a trait object @@ -154,7 +154,7 @@ LL | type _T20 = dyn _5 + _1; | | | trait alias used in trait object type (first use) | - = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error[E0225]: only auto traits can be used as additional traits in a trait object @@ -173,7 +173,7 @@ LL | type _T21 = dyn _1 + _5; | | | trait alias used in trait object type (first use) | - = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error[E0225]: only auto traits can be used as additional traits in a trait object @@ -187,7 +187,7 @@ LL | type _T22 = dyn _5 + ObjA; | | | trait alias used in trait object type (first use) | - = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error[E0225]: only auto traits can be used as additional traits in a trait object @@ -201,7 +201,7 @@ LL | type _T23 = dyn ObjA + _5; | | | first non-auto trait | - = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error[E0225]: only auto traits can be used as additional traits in a trait object @@ -220,7 +220,7 @@ LL | type _T24 = dyn Send + _5 + _1 + Sync; | | | trait alias used in trait object type (first use) | - = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error[E0225]: only auto traits can be used as additional traits in a trait object @@ -239,7 +239,7 @@ LL | type _T25 = dyn _1 + Sync + _5 + Send; | | | trait alias used in trait object type (first use) | - = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error[E0225]: only auto traits can be used as additional traits in a trait object @@ -253,7 +253,7 @@ LL | type _T26 = dyn Sync + Send + _5 + ObjA; | | | trait alias used in trait object type (first use) | - = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error[E0225]: only auto traits can be used as additional traits in a trait object @@ -267,7 +267,7 @@ LL | type _T27 = dyn Send + Sync + ObjA + _5; | | | first non-auto trait | - = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error[E0225]: only auto traits can be used as additional traits in a trait object @@ -292,7 +292,7 @@ LL | type _T30 = dyn _6; | trait alias used in trait object type (additional use) | trait alias used in trait object type (first use) | - = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error[E0225]: only auto traits can be used as additional traits in a trait object @@ -317,7 +317,7 @@ LL | type _T31 = dyn _6 + Send; | trait alias used in trait object type (additional use) | trait alias used in trait object type (first use) | - = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error[E0225]: only auto traits can be used as additional traits in a trait object @@ -342,7 +342,7 @@ LL | type _T32 = dyn Send + _6; | trait alias used in trait object type (additional use) | trait alias used in trait object type (first use) | - = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error[E0225]: only auto traits can be used as additional traits in a trait object @@ -377,7 +377,7 @@ LL | type _T33 = dyn _8; | trait alias used in trait object type (additional use) | trait alias used in trait object type (first use) | - = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error[E0225]: only auto traits can be used as additional traits in a trait object @@ -412,7 +412,7 @@ LL | type _T34 = dyn _8 + Send; | trait alias used in trait object type (additional use) | trait alias used in trait object type (first use) | - = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error[E0225]: only auto traits can be used as additional traits in a trait object @@ -447,7 +447,7 @@ LL | type _T35 = dyn Send + _8; | trait alias used in trait object type (additional use) | trait alias used in trait object type (first use) | - = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error[E0225]: only auto traits can be used as additional traits in a trait object @@ -466,7 +466,7 @@ LL | type _T40 = dyn _10 + ObjA; | | | trait alias used in trait object type (first use) | - = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error[E0225]: only auto traits can be used as additional traits in a trait object @@ -485,7 +485,7 @@ LL | type _T41 = dyn ObjA + _10; | | | first non-auto trait | - = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error[E0225]: only auto traits can be used as additional traits in a trait object @@ -509,7 +509,7 @@ LL | type _T42 = dyn _10 + _1; | | | trait alias used in trait object type (first use) | - = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error[E0225]: only auto traits can be used as additional traits in a trait object @@ -528,7 +528,7 @@ LL | type _T43 = dyn Send + _10 + Sync + ObjA; | | | trait alias used in trait object type (first use) | - = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error[E0225]: only auto traits can be used as additional traits in a trait object @@ -547,7 +547,7 @@ LL | type _T44 = dyn ObjA + _10 + Send + Sync; | | | first non-auto trait | - = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error[E0225]: only auto traits can be used as additional traits in a trait object @@ -571,7 +571,7 @@ LL | type _T45 = dyn Sync + Send + _10 + _1; | | | trait alias used in trait object type (first use) | - = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error: aborting due to 28 previous errors diff --git a/src/test/ui/traits/auxiliary/issue_89119_intercrate_caching.rs b/src/test/ui/traits/auxiliary/issue_89119_intercrate_caching.rs new file mode 100644 index 0000000000..769e897316 --- /dev/null +++ b/src/test/ui/traits/auxiliary/issue_89119_intercrate_caching.rs @@ -0,0 +1,60 @@ +// This is the auxiliary crate for the regression test for issue #89119, minimized +// from `zvariant-2.8.0`. + +use std::convert::TryFrom; +use std::borrow::Cow; + +pub struct Str<'a>(Cow<'a, str>); +impl<'a> Str<'a> { + pub fn to_owned(&self) -> Str<'static> { + todo!() + } +} + +pub enum Value<'a> { + Str(Str<'a>), + Value(Box>), +} +impl<'a> Value<'a> { + pub fn to_owned(&self) -> Value<'static> { + match self { + Value::Str(v) => Value::Str(v.to_owned()), + Value::Value(v) => { + let o = OwnedValue::from(&**v); + Value::Value(Box::new(o.into_inner())) + } + } + } +} + +struct OwnedValue(Value<'static>); +impl OwnedValue { + pub(crate) fn into_inner(self) -> Value<'static> { + todo!() + } +} +impl<'a, T> TryFrom for Vec +where + T: TryFrom, Error = ()>, +{ + type Error = (); + fn try_from(_: OwnedValue) -> Result { + todo!() + } +} +impl TryFrom for Vec { + type Error = (); + fn try_from(_: OwnedValue) -> Result { + todo!() + } +} +impl<'a> From> for OwnedValue { + fn from(_: Value<'a>) -> Self { + todo!() + } +} +impl<'a> From<&Value<'a>> for OwnedValue { + fn from(_: &Value<'a>) -> Self { + todo!() + } +} diff --git a/src/test/ui/traits/bad-sized.stderr b/src/test/ui/traits/bad-sized.stderr index 1322b66003..5421e71509 100644 --- a/src/test/ui/traits/bad-sized.stderr +++ b/src/test/ui/traits/bad-sized.stderr @@ -6,7 +6,7 @@ LL | let x: Vec = Vec::new(); | | | first non-auto trait | - = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Trait + Sized {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Trait + Sized {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error[E0277]: the size for values of type `dyn Trait` cannot be known at compilation time diff --git a/src/test/ui/traits/bound/in-arc.rs b/src/test/ui/traits/bound/in-arc.rs index 941f66c056..a1492c0b98 100644 --- a/src/test/ui/traits/bound/in-arc.rs +++ b/src/test/ui/traits/bound/in-arc.rs @@ -5,8 +5,6 @@ // ignore-emscripten no threads support -#![feature(box_syntax)] - use std::sync::Arc; use std::sync::mpsc::channel; use std::thread; @@ -67,10 +65,11 @@ pub fn main() { swim_speed: 998, name: "alec_guinness".to_string(), }; - let arc = Arc::new(vec![box catte as Box, - box dogge1 as Box, - box fishe as Box, - box dogge2 as Box]); + let arc = Arc::new(vec![ + Box::new(catte) as Box, + Box::new(dogge1) as Box, + Box::new(fishe) as Box, + Box::new(dogge2) as Box]); let (tx1, rx1) = channel(); let arc1 = arc.clone(); let t1 = thread::spawn(move|| { check_legs(arc1); tx1.send(()); }); diff --git a/src/test/ui/traits/bound/same-crate-name.stderr b/src/test/ui/traits/bound/same-crate-name.stderr index 15f5fe16bc..81e5589d6e 100644 --- a/src/test/ui/traits/bound/same-crate-name.stderr +++ b/src/test/ui/traits/bound/same-crate-name.stderr @@ -2,7 +2,9 @@ error[E0277]: the trait bound `Foo: main::a::Bar` is not satisfied --> $DIR/same-crate-name.rs:31:20 | LL | a::try_foo(foo); - | ^^^ the trait `main::a::Bar` is not implemented for `Foo` + | ---------- ^^^ the trait `main::a::Bar` is not implemented for `Foo` + | | + | required by a bound introduced by this call | help: trait impl with same name found --> $DIR/auxiliary/crate_a2.rs:5:1 @@ -20,7 +22,9 @@ error[E0277]: the trait bound `DoesNotImplementTrait: main::a::Bar` is not satis --> $DIR/same-crate-name.rs:38:20 | LL | a::try_foo(implements_no_traits); - | ^^^^^^^^^^^^^^^^^^^^ the trait `main::a::Bar` is not implemented for `DoesNotImplementTrait` + | ---------- ^^^^^^^^^^^^^^^^^^^^ the trait `main::a::Bar` is not implemented for `DoesNotImplementTrait` + | | + | required by a bound introduced by this call | note: required by a bound in `try_foo` --> $DIR/auxiliary/crate_a1.rs:3:24 @@ -32,7 +36,9 @@ error[E0277]: the trait bound `ImplementsWrongTraitConditionally: main::a --> $DIR/same-crate-name.rs:45:20 | LL | a::try_foo(other_variant_implements_mismatched_trait); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `main::a::Bar` is not implemented for `ImplementsWrongTraitConditionally` + | ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `main::a::Bar` is not implemented for `ImplementsWrongTraitConditionally` + | | + | required by a bound introduced by this call | help: trait impl with same name found --> $DIR/auxiliary/crate_a2.rs:13:1 @@ -50,7 +56,9 @@ error[E0277]: the trait bound `ImplementsTraitForUsize: main::a::Bar` is --> $DIR/same-crate-name.rs:51:20 | LL | a::try_foo(other_variant_implements_correct_trait); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `main::a::Bar` is not implemented for `ImplementsTraitForUsize` + | ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `main::a::Bar` is not implemented for `ImplementsTraitForUsize` + | | + | required by a bound introduced by this call | = help: the following implementations were found: as main::a::Bar> diff --git a/src/test/ui/bug-7183-generics.rs b/src/test/ui/traits/bug-7183-generics.rs similarity index 100% rename from src/test/ui/bug-7183-generics.rs rename to src/test/ui/traits/bug-7183-generics.rs diff --git a/src/test/ui/traits/coercion.rs b/src/test/ui/traits/coercion.rs index cba33af1f1..e62742bac5 100644 --- a/src/test/ui/traits/coercion.rs +++ b/src/test/ui/traits/coercion.rs @@ -2,7 +2,6 @@ #![allow(dead_code)] #![allow(unused_mut)] #![allow(unused_variables)] -#![feature(box_syntax)] use std::io::{self, Write}; diff --git a/src/test/ui/traits/conditional-dispatch.rs b/src/test/ui/traits/conditional-dispatch.rs index a9c194486f..dd882dce66 100644 --- a/src/test/ui/traits/conditional-dispatch.rs +++ b/src/test/ui/traits/conditional-dispatch.rs @@ -3,7 +3,6 @@ // blanket impl for T:Copy coexists with an impl for Box, because // Box does not impl Copy. -#![feature(box_syntax)] trait Get { fn get(&self) -> Self; @@ -20,7 +19,7 @@ impl Get for T { } impl Get for Box { - fn get(&self) -> Box { box get_it(&**self) } + fn get(&self) -> Box { Box::new(get_it(&**self)) } } fn get_it(t: &T) -> T { diff --git a/src/test/ui/traits/impl-of-supertrait-has-wrong-lifetime-parameters.stderr b/src/test/ui/traits/impl-of-supertrait-has-wrong-lifetime-parameters.stderr index 539a56f010..5572c6515f 100644 --- a/src/test/ui/traits/impl-of-supertrait-has-wrong-lifetime-parameters.stderr +++ b/src/test/ui/traits/impl-of-supertrait-has-wrong-lifetime-parameters.stderr @@ -4,12 +4,12 @@ error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'b` d LL | impl<'a,'b> T2<'a, 'b> for S<'a, 'b> { | ^^^^^^^^^^ | -note: first, the lifetime cannot outlive the lifetime `'a` as defined on the impl at 24:6... +note: first, the lifetime cannot outlive the lifetime `'a` as defined here... --> $DIR/impl-of-supertrait-has-wrong-lifetime-parameters.rs:24:6 | LL | impl<'a,'b> T2<'a, 'b> for S<'a, 'b> { | ^^ -note: ...but the lifetime must also be valid for the lifetime `'b` as defined on the impl at 24:9... +note: ...but the lifetime must also be valid for the lifetime `'b` as defined here... --> $DIR/impl-of-supertrait-has-wrong-lifetime-parameters.rs:24:9 | LL | impl<'a,'b> T2<'a, 'b> for S<'a, 'b> { diff --git a/src/test/ui/traits/inductive-overflow/supertrait-auto-trait.stderr b/src/test/ui/traits/inductive-overflow/supertrait-auto-trait.stderr index 5206b57210..8405d7ddc7 100644 --- a/src/test/ui/traits/inductive-overflow/supertrait-auto-trait.stderr +++ b/src/test/ui/traits/inductive-overflow/supertrait-auto-trait.stderr @@ -1,16 +1,18 @@ -error[E0568]: auto traits cannot have super traits - --> $DIR/supertrait-auto-trait.rs:8:19 +error[E0568]: auto traits cannot have super traits or lifetime bounds + --> $DIR/supertrait-auto-trait.rs:8:17 | LL | auto trait Magic: Copy {} - | ----- ^^^^ help: remove the super traits + | -----^^^^^^ help: remove the super traits or lifetime bounds | | - | auto trait cannot have super traits + | auto trait cannot have super traits or lifetime bounds error[E0277]: the trait bound `NoClone: Copy` is not satisfied --> $DIR/supertrait-auto-trait.rs:16:23 | LL | let (a, b) = copy(NoClone); - | ^^^^^^^ the trait `Copy` is not implemented for `NoClone` + | ---- ^^^^^^^ the trait `Copy` is not implemented for `NoClone` + | | + | required by a bound introduced by this call | = note: required because of the requirements on the impl of `Magic` for `NoClone` note: required by a bound in `copy` diff --git a/src/test/ui/issues/issue-20692.rs b/src/test/ui/traits/issue-20692.rs similarity index 100% rename from src/test/ui/issues/issue-20692.rs rename to src/test/ui/traits/issue-20692.rs diff --git a/src/test/ui/issues/issue-20692.stderr b/src/test/ui/traits/issue-20692.stderr similarity index 100% rename from src/test/ui/issues/issue-20692.stderr rename to src/test/ui/traits/issue-20692.stderr diff --git a/src/test/ui/issues/issue-23825.rs b/src/test/ui/traits/issue-23825.rs similarity index 100% rename from src/test/ui/issues/issue-23825.rs rename to src/test/ui/traits/issue-23825.rs diff --git a/src/test/ui/traits/issue-52893.rs b/src/test/ui/traits/issue-52893.rs new file mode 100644 index 0000000000..d72598d5d5 --- /dev/null +++ b/src/test/ui/traits/issue-52893.rs @@ -0,0 +1,57 @@ +// check-fail +// +// regression test for issue 52893 +trait At { + type AtRes; + fn at(self) -> Self::AtRes; +} + +trait Push { + type PushRes; + fn push(self, other: T) -> Self::PushRes; +} + +trait AddClass { + type AddRes; + fn init(self, func: F); +} + +trait ToRef { + type RefRes; + fn to_ref(&self) -> Self::RefRes; +} + +struct Class

(P); + +impl

Class

{ + fn with(self) -> >::AddRes + where + Self: AddClass, + { + todo!() + } + + fn from(self) -> >::AddRes + where + Self: AddClass, + { + todo!() + } +} + +impl AddClass for Class

+where + Self: At, + >::AtRes: Push, + <>::AtRes as Push>::PushRes: ToRef + Push, +{ + type AddRes = (); + + fn init(self, func: F) { + let builder = self.at().push(func); + let output = builder.to_ref(); + builder.push(output); //~ ERROR mismatched types [E0308] + } +} + +fn main() {} diff --git a/src/test/ui/traits/issue-52893.stderr b/src/test/ui/traits/issue-52893.stderr new file mode 100644 index 0000000000..bf732e2491 --- /dev/null +++ b/src/test/ui/traits/issue-52893.stderr @@ -0,0 +1,15 @@ +error[E0308]: mismatched types + --> $DIR/issue-52893.rs:53:22 + | +LL | impl AddClass for Class

+ | - this type parameter +... +LL | builder.push(output); + | ^^^^^^ expected type parameter `F`, found struct `Class` + | + = note: expected type parameter `F` + found struct `Class

` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/traits/issue-6128.rs b/src/test/ui/traits/issue-6128.rs index 8859fbe6af..07d92f8f8a 100644 --- a/src/test/ui/traits/issue-6128.rs +++ b/src/test/ui/traits/issue-6128.rs @@ -1,7 +1,5 @@ // run-pass -#![feature(box_syntax)] - use std::collections::HashMap; trait Graph { @@ -19,6 +17,6 @@ impl Graph for HashMap { } pub fn main() { - let g : Box> = box HashMap::new(); + let g : Box> = Box::new(HashMap::new()); let _g2 : Box> = g as Box>; } diff --git a/src/test/ui/traits/issue-68295.rs b/src/test/ui/traits/issue-68295.rs new file mode 100644 index 0000000000..7ff54539ad --- /dev/null +++ b/src/test/ui/traits/issue-68295.rs @@ -0,0 +1,47 @@ +// check-fail +// +// regression test for #68295 + +struct Matrix(R, C, S); + +impl Matrix { + fn into_owned(self) -> Matrix> + where + (): Allocator, + { + unimplemented!() + } +} + +impl Matrix { + fn hermitian_part(&self) -> Matrix> + where + (): Allocator, + { + unimplemented!() + } +} + +trait Allocator { + type Buffer; +} + +trait Trait { + type Power; +} + +impl> Trait for () { + type Power = A::Buffer; +} + +type Owned = >::Power; + +fn crash(input: Matrix) -> Matrix +where + (): Allocator, +{ + input.into_owned() + //~^ ERROR mismatched types [E0308] +} + +fn main() {} diff --git a/src/test/ui/traits/issue-68295.stderr b/src/test/ui/traits/issue-68295.stderr new file mode 100644 index 0000000000..cb6e6e0769 --- /dev/null +++ b/src/test/ui/traits/issue-68295.stderr @@ -0,0 +1,17 @@ +error[E0308]: mismatched types + --> $DIR/issue-68295.rs:43:5 + | +LL | fn crash(input: Matrix) -> Matrix + | ----------------- expected `Matrix` because of return type +... +LL | input.into_owned() + | ^^^^^^^^^^^^^^^^^^ expected `u32`, found associated type + | + = note: expected struct `Matrix<_, _, u32>` + found struct `Matrix<_, _, <() as Allocator>::Buffer>` + = help: consider constraining the associated type `<() as Allocator>::Buffer` to `u32` + = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/traits/issue-89119.rs b/src/test/ui/traits/issue-89119.rs new file mode 100644 index 0000000000..170f69915e --- /dev/null +++ b/src/test/ui/traits/issue-89119.rs @@ -0,0 +1,11 @@ +// This is a regression test for issue #89119: an issue in intercrate mode caching. +// +// It requires multiple crates, of course, but the bug is triggered by the code in the dependency, +// not the main crate. This is why this file is empty. +// +// The auxiliary crate used in the test contains the code minimized from `zvariant-2.8.0`. + +// check-pass +// aux-build: issue_89119_intercrate_caching.rs + +fn main() {} diff --git a/src/test/ui/traits/item-privacy.stderr b/src/test/ui/traits/item-privacy.stderr index 2260dcfc70..ef5d5cdff8 100644 --- a/src/test/ui/traits/item-privacy.stderr +++ b/src/test/ui/traits/item-privacy.stderr @@ -127,9 +127,6 @@ error[E0038]: the trait `assoc_const::C` cannot be made into an object LL | ::A; | ^^^^^ `assoc_const::C` cannot be made into an object | - = help: consider moving `C` to another trait - = help: consider moving `B` to another trait - = help: consider moving `A` to another trait note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit --> $DIR/item-privacy.rs:25:15 | @@ -143,6 +140,9 @@ LL | pub trait C: A + B { | - this trait cannot be made into an object... LL | const C: u8 = 0; | ^ ...because it contains this associated `const` + = help: consider moving `C` to another trait + = help: consider moving `A` to another trait + = help: consider moving `B` to another trait error[E0223]: ambiguous associated type --> $DIR/item-privacy.rs:115:12 diff --git a/src/test/ui/traits/kindck-owned-contains-1.rs b/src/test/ui/traits/kindck-owned-contains-1.rs index 23b91f924b..8adb06ba3d 100644 --- a/src/test/ui/traits/kindck-owned-contains-1.rs +++ b/src/test/ui/traits/kindck-owned-contains-1.rs @@ -2,8 +2,6 @@ #![allow(non_snake_case)] #![allow(non_camel_case_types)] -#![feature(box_syntax)] - trait repeat { fn get(&self) -> A; } impl repeat for Box { @@ -13,11 +11,11 @@ impl repeat for Box { } fn repeater(v: Box) -> Box+'static> { - box v as Box+'static> // No + Box::new(v) as Box+'static> // No } pub fn main() { let x = 3; - let y = repeater(box x); + let y = repeater(Box::new(x)); assert_eq!(x, y.get()); } diff --git a/src/test/ui/traits/matching-lifetimes.stderr b/src/test/ui/traits/matching-lifetimes.stderr index 5c28d40160..de1c878a51 100644 --- a/src/test/ui/traits/matching-lifetimes.stderr +++ b/src/test/ui/traits/matching-lifetimes.stderr @@ -6,12 +6,12 @@ LL | fn foo(x: Foo<'b,'a>) { | = note: expected fn pointer `fn(Foo<'a, 'b>)` found fn pointer `fn(Foo<'b, 'a>)` -note: the lifetime `'b` as defined on the impl at 13:9... +note: the lifetime `'b` as defined here... --> $DIR/matching-lifetimes.rs:13:9 | LL | impl<'a,'b> Tr for Foo<'a,'b> { | ^^ -note: ...does not necessarily outlive the lifetime `'a` as defined on the impl at 13:6 +note: ...does not necessarily outlive the lifetime `'a` as defined here --> $DIR/matching-lifetimes.rs:13:6 | LL | impl<'a,'b> Tr for Foo<'a,'b> { @@ -25,12 +25,12 @@ LL | fn foo(x: Foo<'b,'a>) { | = note: expected fn pointer `fn(Foo<'a, 'b>)` found fn pointer `fn(Foo<'b, 'a>)` -note: the lifetime `'a` as defined on the impl at 13:6... +note: the lifetime `'a` as defined here... --> $DIR/matching-lifetimes.rs:13:6 | LL | impl<'a,'b> Tr for Foo<'a,'b> { | ^^ -note: ...does not necessarily outlive the lifetime `'b` as defined on the impl at 13:9 +note: ...does not necessarily outlive the lifetime `'b` as defined here --> $DIR/matching-lifetimes.rs:13:9 | LL | impl<'a,'b> Tr for Foo<'a,'b> { diff --git a/src/test/ui/traits/multidispatch-bad.stderr b/src/test/ui/traits/multidispatch-bad.stderr index ccdace1957..6caa23d8f4 100644 --- a/src/test/ui/traits/multidispatch-bad.stderr +++ b/src/test/ui/traits/multidispatch-bad.stderr @@ -7,7 +7,7 @@ LL | test(22i32, 44i32); help: change the type of the numeric literal from `i32` to `u32` | LL | test(22i32, 44u32); - | ~~~~~ + | ~~~ error: aborting due to previous error diff --git a/src/test/ui/traits/mutual-recursion-issue-75860.stderr b/src/test/ui/traits/mutual-recursion-issue-75860.stderr index d2ac3a836f..920f66121e 100644 --- a/src/test/ui/traits/mutual-recursion-issue-75860.stderr +++ b/src/test/ui/traits/mutual-recursion-issue-75860.stderr @@ -4,7 +4,7 @@ error[E0275]: overflow evaluating the requirement `Option<_>: Sized` LL | iso(left, right) | ^^^ | - = help: consider adding a `#![recursion_limit="256"]` attribute to your crate (`mutual_recursion_issue_75860`) + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`mutual_recursion_issue_75860`) note: required by a bound in `Option` --> $SRC_DIR/core/src/option.rs:LL:COL | 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 ad95e06eb4..8059a8ca71 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 @@ -2,7 +2,9 @@ error[E0277]: `dummy::TestType` cannot be sent between threads safely --> $DIR/negated-auto-traits-error.rs:23:11 | LL | Outer(TestType); - | ^^^^^^^^ `dummy::TestType` cannot be sent between threads safely + | ----- ^^^^^^^^ `dummy::TestType` cannot be sent between threads safely + | | + | required by a bound introduced by this call | = help: the trait `Send` is not implemented for `dummy::TestType` note: required by `Outer` @@ -28,7 +30,9 @@ error[E0277]: `dummy1b::TestType` cannot be sent between threads safely --> $DIR/negated-auto-traits-error.rs:32:13 | LL | is_send(TestType); - | ^^^^^^^^ `dummy1b::TestType` cannot be sent between threads safely + | ------- ^^^^^^^^ `dummy1b::TestType` cannot be sent between threads safely + | | + | required by a bound introduced by this call | = help: the trait `Send` is not implemented for `dummy1b::TestType` note: required by a bound in `is_send` @@ -41,9 +45,11 @@ error[E0277]: `dummy1c::TestType` cannot be sent between threads safely --> $DIR/negated-auto-traits-error.rs:40:13 | LL | is_send((8, TestType)); - | ^^^^^^^^^^^^^ `dummy1c::TestType` cannot be sent between threads safely + | ------- ^^^^^^^^^^^^^ `dummy1c::TestType` cannot be sent between threads safely + | | + | required by a bound introduced by this call | - = help: within `({integer}, dummy1c::TestType)`, the trait `Send` is not implemented for `dummy1c::TestType` + = help: 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 @@ -55,10 +61,9 @@ error[E0277]: `dummy2::TestType` cannot be sent between threads safely --> $DIR/negated-auto-traits-error.rs:48:13 | LL | is_send(Box::new(TestType)); - | ^^^^^^^^^^^^^^^^^^ - | | - | expected an implementor of trait `Send` - | help: consider borrowing here: `&Box::new(TestType)` + | ------- ^^^^^^^^^^^^^^^^^^ expected an implementor of trait `Send` + | | + | required by a bound introduced by this call | = note: the trait bound `dummy2::TestType: Send` is not satisfied = note: required because of the requirements on the impl of `Send` for `Unique` @@ -68,14 +73,20 @@ note: required by a bound in `is_send` | LL | fn is_send(_: T) {} | ^^^^ required by this bound in `is_send` +help: consider borrowing here + | +LL | is_send(&Box::new(TestType)); + | + error[E0277]: `dummy3::TestType` cannot be sent between threads safely --> $DIR/negated-auto-traits-error.rs:56:13 | LL | is_send(Box::new(Outer2(TestType))); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ `dummy3::TestType` cannot be sent between threads safely + | ------- ^^^^^^^^^^^^^^^^^^^^^^^^^^ `dummy3::TestType` cannot be sent between threads safely + | | + | required by a bound introduced by this call | - = help: within `Outer2`, the trait `Send` is not implemented for `dummy3::TestType` + = help: the trait `Send` is not implemented for `dummy3::TestType` note: required because it appears within the type `Outer2` --> $DIR/negated-auto-traits-error.rs:12:8 | @@ -93,10 +104,9 @@ 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` - | help: consider borrowing here: `&Outer2(TestType)` + | ------- ^^^^^^^^^^^^^^^^ expected an implementor of trait `Sync` + | | + | required by a bound introduced by this call | = note: the trait bound `main::TestType: Sync` is not satisfied note: required because of the requirements on the impl of `Sync` for `Outer2` @@ -109,6 +119,12 @@ note: required by a bound in `is_sync` | LL | fn is_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/normalize-super-trait.rs b/src/test/ui/traits/normalize-supertrait.rs similarity index 100% rename from src/test/ui/traits/normalize-super-trait.rs rename to src/test/ui/traits/normalize-supertrait.rs diff --git a/src/test/ui/traits/object-one-type-two-traits.rs b/src/test/ui/traits/object-one-type-two-traits.rs index b92a2ab7b4..86a2094eee 100644 --- a/src/test/ui/traits/object-one-type-two-traits.rs +++ b/src/test/ui/traits/object-one-type-two-traits.rs @@ -4,8 +4,6 @@ // Testing creating two vtables with the same self type, but different // traits. -#![feature(box_syntax)] - use std::any::Any; trait Wrap { @@ -27,7 +25,7 @@ fn is(x: &dyn Any) -> bool { } fn main() { - let x = box 22isize as Box; + let x = Box::new(22isize) as Box; println!("x={}", x.get()); let y = x.wrap(); } diff --git a/src/test/ui/traits/object/generics.rs b/src/test/ui/traits/object/generics.rs index c18754302b..e5a96af381 100644 --- a/src/test/ui/traits/object/generics.rs +++ b/src/test/ui/traits/object/generics.rs @@ -1,8 +1,6 @@ // run-pass // test for #8664 -#![feature(box_syntax)] - use std::marker; pub trait Trait2 { @@ -38,6 +36,6 @@ impl Trait for () { } pub fn main() { - let a = box () as Box>; + let a = Box::new(()) as Box>; assert_eq!(a.method(Type::Constant((1, 2))), 0); } diff --git a/src/test/ui/traits/reservation-impl/no-use.stderr b/src/test/ui/traits/reservation-impl/no-use.stderr index 526c0e9ed5..e7d1ee616b 100644 --- a/src/test/ui/traits/reservation-impl/no-use.stderr +++ b/src/test/ui/traits/reservation-impl/no-use.stderr @@ -2,7 +2,9 @@ error[E0277]: the trait bound `(): MyTrait` is not satisfied --> $DIR/no-use.rs:10:26 | LL | <() as MyTrait>::foo(&()); - | ^^^ the trait `MyTrait` is not implemented for `()` + | -------------------- ^^^ the trait `MyTrait` is not implemented for `()` + | | + | required by a bound introduced by this call | = help: the following implementations were found: <() as MyTrait> diff --git a/src/test/ui/traits/suggest-deferences/issue-39029.stderr b/src/test/ui/traits/suggest-deferences/issue-39029.stderr index 10eeec20d9..2c225f4311 100644 --- a/src/test/ui/traits/suggest-deferences/issue-39029.stderr +++ b/src/test/ui/traits/suggest-deferences/issue-39029.stderr @@ -2,10 +2,11 @@ error[E0277]: the trait bound `NoToSocketAddrs: ToSocketAddrs` is not satisfied --> $DIR/issue-39029.rs:16:37 | LL | let _errors = TcpListener::bind(&bad); - | ^^^^ - | | - | the trait `ToSocketAddrs` is not implemented for `NoToSocketAddrs` - | help: consider adding dereference here: `&*bad` + | ----------------- ^^^^ + | | | + | | the trait `ToSocketAddrs` is not implemented for `NoToSocketAddrs` + | | help: consider adding dereference here: `&*bad` + | required by a bound introduced by this call | = note: required because of the requirements on the impl of `ToSocketAddrs` for `&NoToSocketAddrs` note: required by a bound in `TcpListener::bind` diff --git a/src/test/ui/traits/suggest-deferences/issue-62530.stderr b/src/test/ui/traits/suggest-deferences/issue-62530.stderr index 750c8a86c5..b77af7ddf4 100644 --- a/src/test/ui/traits/suggest-deferences/issue-62530.stderr +++ b/src/test/ui/traits/suggest-deferences/issue-62530.stderr @@ -2,10 +2,11 @@ error[E0277]: the trait bound `&String: SomeTrait` is not satisfied --> $DIR/issue-62530.rs:13:26 | LL | takes_type_parameter(&string); // Error - | ^^^^^^^ - | | - | the trait `SomeTrait` is not implemented for `&String` - | help: consider adding dereference here: `&*string` + | -------------------- ^^^^^^^ + | | | + | | the trait `SomeTrait` is not implemented for `&String` + | | help: consider adding dereference here: `&*string` + | required by a bound introduced by this call | note: required by a bound in `takes_type_parameter` --> $DIR/issue-62530.rs:4:44 diff --git a/src/test/ui/traits/suggest-deferences/multiple-0.stderr b/src/test/ui/traits/suggest-deferences/multiple-0.stderr index 6fcf8780d6..bf9f85f1b4 100644 --- a/src/test/ui/traits/suggest-deferences/multiple-0.stderr +++ b/src/test/ui/traits/suggest-deferences/multiple-0.stderr @@ -2,10 +2,11 @@ error[E0277]: the trait bound `&Baz: Happy` is not satisfied --> $DIR/multiple-0.rs:34:9 | LL | foo(&baz); - | ^^^^ - | | - | the trait `Happy` is not implemented for `&Baz` - | help: consider adding dereference here: `&***baz` + | --- ^^^^ + | | | + | | the trait `Happy` is not implemented for `&Baz` + | | help: consider adding dereference here: `&***baz` + | required by a bound introduced by this call | note: required by a bound in `foo` --> $DIR/multiple-0.rs:30:26 diff --git a/src/test/ui/traits/suggest-deferences/multiple-1.stderr b/src/test/ui/traits/suggest-deferences/multiple-1.stderr index 268f375050..040fbb3e3e 100644 --- a/src/test/ui/traits/suggest-deferences/multiple-1.stderr +++ b/src/test/ui/traits/suggest-deferences/multiple-1.stderr @@ -2,7 +2,9 @@ error[E0277]: the trait bound `&mut Baz: Happy` is not satisfied --> $DIR/multiple-1.rs:52:9 | LL | foo(&mut baz); - | ^^^^^^^^ the trait `Happy` is not implemented for `&mut Baz` + | --- ^^^^^^^^ the trait `Happy` is not implemented for `&mut Baz` + | | + | required by a bound introduced by this call | note: required by a bound in `foo` --> $DIR/multiple-1.rs:45:26 diff --git a/src/test/ui/traits/test-2.rs b/src/test/ui/traits/test-2.rs index 183c779607..342928e882 100644 --- a/src/test/ui/traits/test-2.rs +++ b/src/test/ui/traits/test-2.rs @@ -1,6 +1,6 @@ -#![feature(box_syntax)] - #[allow(non_camel_case_types)] + + trait bar { fn dup(&self) -> Self; fn blah(&self); } impl bar for i32 { fn dup(&self) -> i32 { *self } fn blah(&self) {} } impl bar for u32 { fn dup(&self) -> u32 { *self } fn blah(&self) {} } @@ -10,7 +10,8 @@ fn main() { //~^ ERROR this associated function takes 0 generic arguments but 1 10.blah::(); //~^ ERROR this associated function takes 1 generic argument but 2 - (box 10 as Box).dup(); + (Box::new(10) as Box).dup(); //~^ ERROR E0038 //~| ERROR E0038 + //~| ERROR E0038 } diff --git a/src/test/ui/traits/test-2.stderr b/src/test/ui/traits/test-2.stderr index 0289424510..77ea4e4e97 100644 --- a/src/test/ui/traits/test-2.stderr +++ b/src/test/ui/traits/test-2.stderr @@ -27,13 +27,11 @@ LL | trait bar { fn dup(&self) -> Self; fn blah(&self); } | ^^^^ - error[E0038]: the trait `bar` cannot be made into an object - --> $DIR/test-2.rs:13:16 + --> $DIR/test-2.rs:13:22 | -LL | (box 10 as Box).dup(); - | ^^^^^^^^^^^^ `bar` cannot be made into an object +LL | (Box::new(10) as Box).dup(); + | ^^^^^^^^^^^^ `bar` cannot be made into an object | - = help: consider moving `dup` to another trait - = help: consider moving `blah` to another trait note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit --> $DIR/test-2.rs:4:30 | @@ -42,15 +40,32 @@ LL | trait bar { fn dup(&self) -> Self; fn blah(&self); } | | | | | ...because method `dup` references the `Self` type in its return type | this trait cannot be made into an object... + = help: consider moving `dup` to another trait + = help: consider moving `blah` to another trait + +error[E0038]: the trait `bar` cannot be made into an object + --> $DIR/test-2.rs:13:5 + | +LL | (Box::new(10) as Box).dup(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `bar` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/test-2.rs:4:30 + | +LL | trait bar { fn dup(&self) -> Self; fn blah(&self); } + | --- ^^^^ ^^^^ ...because method `blah` has generic type parameters + | | | + | | ...because method `dup` references the `Self` type in its return type + | this trait cannot be made into an object... + = help: consider moving `dup` to another trait + = help: consider moving `blah` to another trait error[E0038]: the trait `bar` cannot be made into an object --> $DIR/test-2.rs:13:6 | -LL | (box 10 as Box).dup(); - | ^^^^^^ `bar` cannot be made into an object +LL | (Box::new(10) as Box).dup(); + | ^^^^^^^^^^^^ `bar` cannot be made into an object | - = help: consider moving `dup` to another trait - = help: consider moving `blah` to another trait note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit --> $DIR/test-2.rs:4:30 | @@ -59,10 +74,12 @@ LL | trait bar { fn dup(&self) -> Self; fn blah(&self); } | | | | | ...because method `dup` references the `Self` type in its return type | this trait cannot be made into an object... + = help: consider moving `dup` to another trait + = help: consider moving `blah` to another trait = note: required because of the requirements on the impl of `CoerceUnsized>` for `Box<{integer}>` = note: required by cast to type `Box` -error: aborting due to 4 previous errors +error: aborting due to 5 previous errors Some errors have detailed explanations: E0038, E0107. For more information about an error, try `rustc --explain E0038`. diff --git a/src/test/ui/traits/trait-upcasting/issue-11515-upcast-fn_mut-fn.rs b/src/test/ui/traits/trait-upcasting/issue-11515-upcast-fn_mut-fn.rs index 277d9eabe4..6d88002540 100644 --- a/src/test/ui/traits/trait-upcasting/issue-11515-upcast-fn_mut-fn.rs +++ b/src/test/ui/traits/trait-upcasting/issue-11515-upcast-fn_mut-fn.rs @@ -1,5 +1,5 @@ // run-pass -#![feature(box_syntax, trait_upcasting)] +#![feature(trait_upcasting)] #![allow(incomplete_features)] struct Test { @@ -8,6 +8,6 @@ struct Test { fn main() { let closure: Box = Box::new(|| ()); - let mut test = box Test { func: closure }; + let mut test = Box::new(Test { func: closure }); (test.func)(); } diff --git a/src/test/ui/traits/trait-upcasting/migrate-lint-deny.rs b/src/test/ui/traits/trait-upcasting/migrate-lint-deny.rs new file mode 100644 index 0000000000..c672510185 --- /dev/null +++ b/src/test/ui/traits/trait-upcasting/migrate-lint-deny.rs @@ -0,0 +1,25 @@ +#![deny(deref_into_dyn_supertrait)] + +extern crate core; + +use core::ops::Deref; + +// issue 89190 +trait A {} +trait B: A {} +impl<'a> Deref for dyn 'a + B { + type Target = dyn A; + fn deref(&self) -> &Self::Target { + todo!() + } +} + +fn take_a(_: &dyn A) {} + +fn whoops(b: &dyn B) { + take_a(b) + //~^ ERROR `dyn B` implements `Deref` with supertrait `(dyn A + 'static)` as output + //~^^ WARN this was previously accepted by the compiler but is being phased out; +} + +fn main() {} diff --git a/src/test/ui/traits/trait-upcasting/migrate-lint-deny.stderr b/src/test/ui/traits/trait-upcasting/migrate-lint-deny.stderr new file mode 100644 index 0000000000..35af9112a2 --- /dev/null +++ b/src/test/ui/traits/trait-upcasting/migrate-lint-deny.stderr @@ -0,0 +1,16 @@ +error: `dyn B` implements `Deref` with supertrait `(dyn A + 'static)` as output + --> $DIR/migrate-lint-deny.rs:20:12 + | +LL | take_a(b) + | ^ + | +note: the lint level is defined here + --> $DIR/migrate-lint-deny.rs:1:9 + | +LL | #![deny(deref_into_dyn_supertrait)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #89460 + +error: aborting due to previous error + diff --git a/src/test/ui/traits/trait-upcasting/type-checking-test-3.stderr b/src/test/ui/traits/trait-upcasting/type-checking-test-3.stderr index 593ee0a343..641e5c97c1 100644 --- a/src/test/ui/traits/trait-upcasting/type-checking-test-3.stderr +++ b/src/test/ui/traits/trait-upcasting/type-checking-test-3.stderr @@ -6,7 +6,7 @@ LL | let _ = x as &dyn Bar<'a>; // Error | = note: expected trait object `dyn Bar<'a>` found trait object `dyn Bar<'static>` -note: the lifetime `'a` as defined on the function body at 12:16... +note: the lifetime `'a` as defined here... --> $DIR/type-checking-test-3.rs:12:16 | LL | fn test_wrong1<'a>(x: &dyn Foo<'static>, y: &'a u32) { @@ -21,7 +21,7 @@ LL | let _ = x as &dyn Bar<'static>; // Error | = note: expected trait object `dyn Bar<'static>` found trait object `dyn Bar<'a>` -note: the lifetime `'a` as defined on the function body at 17:16... +note: the lifetime `'a` as defined here... --> $DIR/type-checking-test-3.rs:17:16 | LL | fn test_wrong2<'a>(x: &dyn Foo<'a>) { diff --git a/src/test/ui/traits/trait-upcasting/type-checking-test-4.stderr b/src/test/ui/traits/trait-upcasting/type-checking-test-4.stderr index 811e524eda..4967f3dc2c 100644 --- a/src/test/ui/traits/trait-upcasting/type-checking-test-4.stderr +++ b/src/test/ui/traits/trait-upcasting/type-checking-test-4.stderr @@ -6,7 +6,7 @@ LL | let _ = x as &dyn Bar<'static, 'a>; // Error | = note: expected trait object `dyn Bar<'static, 'a>` found trait object `dyn Bar<'static, 'static>` -note: the lifetime `'a` as defined on the function body at 16:16... +note: the lifetime `'a` as defined here... --> $DIR/type-checking-test-4.rs:16:16 | LL | fn test_wrong1<'a>(x: &dyn Foo<'static>, y: &'a u32) { @@ -21,7 +21,7 @@ LL | let _ = x as &dyn Bar<'a, 'static>; // Error | = note: expected trait object `dyn Bar<'a, 'static>` found trait object `dyn Bar<'static, 'static>` -note: the lifetime `'a` as defined on the function body at 21:16... +note: the lifetime `'a` as defined here... --> $DIR/type-checking-test-4.rs:21:16 | LL | fn test_wrong2<'a>(x: &dyn Foo<'static>, y: &'a u32) { diff --git a/src/test/ui/traits/vtable/vtable-diamond.rs b/src/test/ui/traits/vtable/vtable-diamond.rs index f64ae95f1d..ec25e8a707 100644 --- a/src/test/ui/traits/vtable/vtable-diamond.rs +++ b/src/test/ui/traits/vtable/vtable-diamond.rs @@ -13,13 +13,13 @@ trait B: A { #[rustc_dump_vtable] trait C: A { - //~^ error Vtable + //~^ error vtable fn foo_c(&self) {} } #[rustc_dump_vtable] trait D: B + C { - //~^ error Vtable + //~^ error vtable fn foo_d(&self) {} } diff --git a/src/test/ui/traits/vtable/vtable-diamond.stderr b/src/test/ui/traits/vtable/vtable-diamond.stderr index 92a7f29536..f2b64fac3b 100644 --- a/src/test/ui/traits/vtable/vtable-diamond.stderr +++ b/src/test/ui/traits/vtable/vtable-diamond.stderr @@ -1,4 +1,4 @@ -error: Vtable entries for ``: [ +error: vtable entries for ``: [ MetadataDropInPlace, MetadataSize, MetadataAlign, @@ -16,7 +16,7 @@ LL | | fn foo_d(&self) {} LL | | } | |_^ -error: Vtable entries for ``: [ +error: vtable entries for ``: [ MetadataDropInPlace, MetadataSize, MetadataAlign, diff --git a/src/test/ui/traits/vtable/vtable-multi-level.rs b/src/test/ui/traits/vtable/vtable-multi-level.rs index 33112b4eaa..fcb5fd5274 100644 --- a/src/test/ui/traits/vtable/vtable-multi-level.rs +++ b/src/test/ui/traits/vtable/vtable-multi-level.rs @@ -17,7 +17,7 @@ trait A { #[rustc_dump_vtable] trait B { - //~^ error Vtable + //~^ error vtable fn foo_b(&self) {} } @@ -28,19 +28,19 @@ trait C: A + B { #[rustc_dump_vtable] trait D { - //~^ error Vtable + //~^ error vtable fn foo_d(&self) {} } #[rustc_dump_vtable] trait E { - //~^ error Vtable + //~^ error vtable fn foo_e(&self) {} } #[rustc_dump_vtable] trait F: D + E { - //~^ error Vtable + //~^ error vtable fn foo_f(&self) {} } @@ -51,49 +51,49 @@ trait G: C + F { #[rustc_dump_vtable] trait H { - //~^ error Vtable + //~^ error vtable fn foo_h(&self) {} } #[rustc_dump_vtable] trait I { - //~^ error Vtable + //~^ error vtable fn foo_i(&self) {} } #[rustc_dump_vtable] trait J: H + I { - //~^ error Vtable + //~^ error vtable fn foo_j(&self) {} } #[rustc_dump_vtable] trait K { - //~^ error Vtable + //~^ error vtable fn foo_k(&self) {} } #[rustc_dump_vtable] trait L { - //~^ error Vtable + //~^ error vtable fn foo_l(&self) {} } #[rustc_dump_vtable] trait M: K + L { - //~^ error Vtable + //~^ error vtable fn foo_m(&self) {} } #[rustc_dump_vtable] trait N: J + M { - //~^ error Vtable + //~^ error vtable fn foo_n(&self) {} } #[rustc_dump_vtable] trait O: G + N { - //~^ error Vtable + //~^ error vtable fn foo_o(&self) {} } diff --git a/src/test/ui/traits/vtable/vtable-multi-level.stderr b/src/test/ui/traits/vtable/vtable-multi-level.stderr index 7700db98e0..742b88ea8a 100644 --- a/src/test/ui/traits/vtable/vtable-multi-level.stderr +++ b/src/test/ui/traits/vtable/vtable-multi-level.stderr @@ -1,4 +1,4 @@ -error: Vtable entries for ``: [ +error: vtable entries for ``: [ MetadataDropInPlace, MetadataSize, MetadataAlign, @@ -37,7 +37,7 @@ LL | | fn foo_o(&self) {} LL | | } | |_^ -error: Vtable entries for ``: [ +error: vtable entries for ``: [ MetadataDropInPlace, MetadataSize, MetadataAlign, @@ -51,7 +51,7 @@ LL | | fn foo_b(&self) {} LL | | } | |_^ -error: Vtable entries for ``: [ +error: vtable entries for ``: [ MetadataDropInPlace, MetadataSize, MetadataAlign, @@ -65,7 +65,7 @@ LL | | fn foo_d(&self) {} LL | | } | |_^ -error: Vtable entries for ``: [ +error: vtable entries for ``: [ MetadataDropInPlace, MetadataSize, MetadataAlign, @@ -79,7 +79,7 @@ LL | | fn foo_e(&self) {} LL | | } | |_^ -error: Vtable entries for ``: [ +error: vtable entries for ``: [ MetadataDropInPlace, MetadataSize, MetadataAlign, @@ -96,7 +96,7 @@ LL | | fn foo_f(&self) {} LL | | } | |_^ -error: Vtable entries for ``: [ +error: vtable entries for ``: [ MetadataDropInPlace, MetadataSize, MetadataAlign, @@ -110,7 +110,7 @@ LL | | fn foo_h(&self) {} LL | | } | |_^ -error: Vtable entries for ``: [ +error: vtable entries for ``: [ MetadataDropInPlace, MetadataSize, MetadataAlign, @@ -124,7 +124,7 @@ LL | | fn foo_i(&self) {} LL | | } | |_^ -error: Vtable entries for ``: [ +error: vtable entries for ``: [ MetadataDropInPlace, MetadataSize, MetadataAlign, @@ -141,7 +141,7 @@ LL | | fn foo_j(&self) {} LL | | } | |_^ -error: Vtable entries for ``: [ +error: vtable entries for ``: [ MetadataDropInPlace, MetadataSize, MetadataAlign, @@ -155,7 +155,7 @@ LL | | fn foo_k(&self) {} LL | | } | |_^ -error: Vtable entries for ``: [ +error: vtable entries for ``: [ MetadataDropInPlace, MetadataSize, MetadataAlign, @@ -169,7 +169,7 @@ LL | | fn foo_l(&self) {} LL | | } | |_^ -error: Vtable entries for ``: [ +error: vtable entries for ``: [ MetadataDropInPlace, MetadataSize, MetadataAlign, @@ -186,7 +186,7 @@ LL | | fn foo_m(&self) {} LL | | } | |_^ -error: Vtable entries for ``: [ +error: vtable entries for ``: [ MetadataDropInPlace, MetadataSize, MetadataAlign, diff --git a/src/test/ui/traits/vtable/vtable-multiple.rs b/src/test/ui/traits/vtable/vtable-multiple.rs index cb0d0b7248..8e7098a495 100644 --- a/src/test/ui/traits/vtable/vtable-multiple.rs +++ b/src/test/ui/traits/vtable/vtable-multiple.rs @@ -8,13 +8,13 @@ trait A { #[rustc_dump_vtable] trait B { - //~^ error Vtable + //~^ error vtable fn foo_b(&self) {} } #[rustc_dump_vtable] trait C: A + B { - //~^ error Vtable + //~^ error vtable fn foo_c(&self) {} } diff --git a/src/test/ui/traits/vtable/vtable-multiple.stderr b/src/test/ui/traits/vtable/vtable-multiple.stderr index f51b083de2..f25ac76fbe 100644 --- a/src/test/ui/traits/vtable/vtable-multiple.stderr +++ b/src/test/ui/traits/vtable/vtable-multiple.stderr @@ -1,4 +1,4 @@ -error: Vtable entries for ``: [ +error: vtable entries for ``: [ MetadataDropInPlace, MetadataSize, MetadataAlign, @@ -15,7 +15,7 @@ LL | | fn foo_c(&self) {} LL | | } | |_^ -error: Vtable entries for ``: [ +error: vtable entries for ``: [ MetadataDropInPlace, MetadataSize, MetadataAlign, diff --git a/src/test/ui/traits/vtable/vtable-non-object-safe.rs b/src/test/ui/traits/vtable/vtable-non-object-safe.rs new file mode 100644 index 0000000000..7661bb5746 --- /dev/null +++ b/src/test/ui/traits/vtable/vtable-non-object-safe.rs @@ -0,0 +1,18 @@ +// build-fail +#![feature(rustc_attrs)] + +// Ensure that non-object-safe methods in Iterator does not generate +// vtable entries. + +#[rustc_dump_vtable] +trait A: Iterator {} +//~^ error vtable + +impl A for T where T: Iterator {} + +fn foo(_a: &mut dyn A) { +} + +fn main() { + foo(&mut vec![0, 1, 2, 3].into_iter()); +} diff --git a/src/test/ui/traits/vtable/vtable-non-object-safe.stderr b/src/test/ui/traits/vtable/vtable-non-object-safe.stderr new file mode 100644 index 0000000000..34fe910525 --- /dev/null +++ b/src/test/ui/traits/vtable/vtable-non-object-safe.stderr @@ -0,0 +1,16 @@ +error: vtable entries for ` as A>`: [ + MetadataDropInPlace, + MetadataSize, + MetadataAlign, + Method( as Iterator>::next), + Method( as Iterator>::size_hint), + Method( as Iterator>::advance_by), + Method( as Iterator>::nth), +] + --> $DIR/vtable-non-object-safe.rs:8:1 + | +LL | trait A: Iterator {} + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/traits/vtable/vtable-vacant.rs b/src/test/ui/traits/vtable/vtable-vacant.rs index ebea94171f..a647963583 100644 --- a/src/test/ui/traits/vtable/vtable-vacant.rs +++ b/src/test/ui/traits/vtable/vtable-vacant.rs @@ -1,22 +1,25 @@ // build-fail #![feature(rustc_attrs)] +#![feature(negative_impls)] +#![allow(where_clauses_object_safety)] // B --> A #[rustc_dump_vtable] trait A { fn foo_a1(&self) {} - fn foo_a2(&self) where Self: Sized {} + fn foo_a2(&self) where Self: Send {} } #[rustc_dump_vtable] trait B: A { - //~^ error Vtable + //~^ error vtable fn foo_b1(&self) {} - fn foo_b2() where Self: Sized {} + fn foo_b2(&self) where Self: Send {} } struct S; +impl !Send for S {} impl A for S {} impl B for S {} diff --git a/src/test/ui/traits/vtable/vtable-vacant.stderr b/src/test/ui/traits/vtable/vtable-vacant.stderr index 768cca5268..e3b75e7cf3 100644 --- a/src/test/ui/traits/vtable/vtable-vacant.stderr +++ b/src/test/ui/traits/vtable/vtable-vacant.stderr @@ -1,4 +1,4 @@ -error: Vtable entries for ``: [ +error: vtable entries for ``: [ MetadataDropInPlace, MetadataSize, MetadataAlign, @@ -7,12 +7,12 @@ error: Vtable entries for ``: [ Method(::foo_b1), Vacant, ] - --> $DIR/vtable-vacant.rs:13:1 + --> $DIR/vtable-vacant.rs:15:1 | LL | / trait B: A { LL | | LL | | fn foo_b1(&self) {} -LL | | fn foo_b2() where Self: Sized {} +LL | | fn foo_b2(&self) where Self: Send {} LL | | } | |_^ diff --git a/src/test/ui/traits/wf-object/no-duplicates.stderr b/src/test/ui/traits/wf-object/no-duplicates.stderr index b9506894f8..50dfcf9563 100644 --- a/src/test/ui/traits/wf-object/no-duplicates.stderr +++ b/src/test/ui/traits/wf-object/no-duplicates.stderr @@ -6,7 +6,7 @@ LL | type _0 = dyn Obj + Obj; | | | first non-auto trait | - = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Obj + Obj {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error[E0225]: only auto traits can be used as additional traits in a trait object @@ -17,7 +17,7 @@ LL | type _1 = dyn Send + Obj + Obj; | | | first non-auto trait | - = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Obj + Obj {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error[E0225]: only auto traits can be used as additional traits in a trait object @@ -28,7 +28,7 @@ LL | type _2 = dyn Obj + Send + Obj; | | | first non-auto trait | - = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Obj + Obj {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error[E0225]: only auto traits can be used as additional traits in a trait object @@ -39,7 +39,7 @@ LL | type _4 = dyn for<'a> ObjL<'a> + for<'b> ObjL<'b>; | | | first non-auto trait | - = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: for<'a> ObjL<'a> + for<'b> ObjL<'b> {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: for<'a> ObjL<'a> + for<'b> ObjL<'b> {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error[E0225]: only auto traits can be used as additional traits in a trait object @@ -50,7 +50,7 @@ LL | type _5 = dyn ObjT fn(&'a u8)> + ObjT fn(&'b u8)>; | | | first non-auto trait | - = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: ObjT fn(&'a u8)> + ObjT fn(&'b u8)> {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjT fn(&'a u8)> + ObjT fn(&'b u8)> {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit error: aborting due to 5 previous errors diff --git a/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-copy.stderr b/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-copy.stderr index 7bd951febf..1e26623899 100644 --- a/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-copy.stderr +++ b/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-copy.stderr @@ -1,4 +1,4 @@ -warning: Trait bound String: Copy does not depend on any type or lifetime parameters +warning: trait bound String: Copy does not depend on any type or lifetime parameters --> $DIR/trivial-bounds-inconsistent-copy.rs:5:51 | LL | fn copy_string(t: String) -> String where String: Copy { @@ -6,19 +6,19 @@ LL | fn copy_string(t: String) -> String where String: Copy { | = note: `#[warn(trivial_bounds)]` on by default -warning: Trait bound String: Copy does not depend on any type or lifetime parameters +warning: trait bound String: Copy does not depend on any type or lifetime parameters --> $DIR/trivial-bounds-inconsistent-copy.rs:12:56 | LL | fn copy_out_string(t: &String) -> String where String: Copy { | ^^^^ -warning: Trait bound String: Copy does not depend on any type or lifetime parameters +warning: trait bound String: Copy does not depend on any type or lifetime parameters --> $DIR/trivial-bounds-inconsistent-copy.rs:16:55 | LL | fn copy_string_with_param(x: String) where String: Copy { | ^^^^ -warning: Trait bound for<'b> &'b mut i32: Copy does not depend on any type or lifetime parameters +warning: trait bound for<'b> &'b mut i32: Copy does not depend on any type or lifetime parameters --> $DIR/trivial-bounds-inconsistent-copy.rs:22:76 | LL | fn copy_mut<'a>(t: &&'a mut i32) -> &'a mut i32 where for<'b> &'b mut i32: Copy { diff --git a/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-projection-error.stderr b/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-projection-error.stderr index 6508e6a6e7..26679e7138 100644 --- a/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-projection-error.stderr +++ b/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-projection-error.stderr @@ -10,7 +10,7 @@ LL | B::get_x() help: you can convert an `i32` to a `u8` and panic if the converted value doesn't fit | LL | B::get_x().try_into().unwrap() - | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error: aborting due to previous error diff --git a/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-projection.stderr b/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-projection.stderr index e7835814cb..ddc13c512f 100644 --- a/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-projection.stderr +++ b/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-projection.stderr @@ -1,4 +1,4 @@ -warning: Trait bound B: A does not depend on any type or lifetime parameters +warning: trait bound B: A does not depend on any type or lifetime parameters --> $DIR/trivial-bounds-inconsistent-projection.rs:21:8 | LL | B: A @@ -6,37 +6,37 @@ LL | B: A | = note: `#[warn(trivial_bounds)]` on by default -warning: Trait bound B: A does not depend on any type or lifetime parameters +warning: trait bound B: A does not depend on any type or lifetime parameters --> $DIR/trivial-bounds-inconsistent-projection.rs:28:8 | LL | B: A | ^^^^^^^^^^ -warning: Trait bound B: A does not depend on any type or lifetime parameters +warning: trait bound B: A does not depend on any type or lifetime parameters --> $DIR/trivial-bounds-inconsistent-projection.rs:35:8 | LL | B: A | ^^^^^^^^^ -warning: Trait bound B: A does not depend on any type or lifetime parameters +warning: trait bound B: A does not depend on any type or lifetime parameters --> $DIR/trivial-bounds-inconsistent-projection.rs:42:8 | LL | B: A + A | ^^^^^^^^^^ -warning: Trait bound B: A does not depend on any type or lifetime parameters +warning: trait bound B: A does not depend on any type or lifetime parameters --> $DIR/trivial-bounds-inconsistent-projection.rs:42:21 | LL | B: A + A | ^ -warning: Trait bound B: A does not depend on any type or lifetime parameters +warning: trait bound B: A does not depend on any type or lifetime parameters --> $DIR/trivial-bounds-inconsistent-projection.rs:51:8 | LL | B: A + A | ^^^^^^^^^ -warning: Trait bound B: A does not depend on any type or lifetime parameters +warning: trait bound B: A does not depend on any type or lifetime parameters --> $DIR/trivial-bounds-inconsistent-projection.rs:51:20 | LL | B: A + A diff --git a/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-sized.stderr b/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-sized.stderr index ff254edbd7..cf24d811c0 100644 --- a/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-sized.stderr +++ b/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-sized.stderr @@ -1,4 +1,4 @@ -warning: Trait bound str: Sized does not depend on any type or lifetime parameters +warning: trait bound str: Sized does not depend on any type or lifetime parameters --> $DIR/trivial-bounds-inconsistent-sized.rs:14:31 | LL | struct S(str, str) where str: Sized; @@ -6,13 +6,13 @@ LL | struct S(str, str) where str: Sized; | = note: `#[warn(trivial_bounds)]` on by default -warning: Trait bound for<'a> T<(dyn A + 'a)>: Sized does not depend on any type or lifetime parameters +warning: trait bound for<'a> T<(dyn A + 'a)>: Sized does not depend on any type or lifetime parameters --> $DIR/trivial-bounds-inconsistent-sized.rs:17:49 | LL | fn unsized_local() where for<'a> T: Sized { | ^^^^^ -warning: Trait bound str: Sized does not depend on any type or lifetime parameters +warning: trait bound str: Sized does not depend on any type or lifetime parameters --> $DIR/trivial-bounds-inconsistent-sized.rs:22:35 | LL | fn return_str() -> str where str: Sized { diff --git a/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-well-formed.stderr b/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-well-formed.stderr index a9905052ff..8f58a99a86 100644 --- a/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-well-formed.stderr +++ b/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-well-formed.stderr @@ -1,4 +1,4 @@ -warning: Trait bound Vec: Debug does not depend on any type or lifetime parameters +warning: trait bound Vec: Debug does not depend on any type or lifetime parameters --> $DIR/trivial-bounds-inconsistent-well-formed.rs:7:30 | LL | pub fn foo() where Vec: Debug, str: Copy { @@ -6,7 +6,7 @@ LL | pub fn foo() where Vec: Debug, str: Copy { | = note: `#[warn(trivial_bounds)]` on by default -warning: Trait bound str: Copy does not depend on any type or lifetime parameters +warning: trait bound str: Copy does not depend on any type or lifetime parameters --> $DIR/trivial-bounds-inconsistent-well-formed.rs:7:42 | LL | pub fn foo() where Vec: Debug, str: Copy { diff --git a/src/test/ui/trivial-bounds/trivial-bounds-inconsistent.stderr b/src/test/ui/trivial-bounds/trivial-bounds-inconsistent.stderr index 94c51c5788..16f32e043d 100644 --- a/src/test/ui/trivial-bounds/trivial-bounds-inconsistent.stderr +++ b/src/test/ui/trivial-bounds/trivial-bounds-inconsistent.stderr @@ -1,4 +1,4 @@ -warning: Trait bound i32: Foo does not depend on any type or lifetime parameters +warning: trait bound i32: Foo does not depend on any type or lifetime parameters --> $DIR/trivial-bounds-inconsistent.rs:14:19 | LL | enum E where i32: Foo { V } @@ -6,19 +6,19 @@ LL | enum E where i32: Foo { V } | = note: `#[warn(trivial_bounds)]` on by default -warning: Trait bound i32: Foo does not depend on any type or lifetime parameters +warning: trait bound i32: Foo does not depend on any type or lifetime parameters --> $DIR/trivial-bounds-inconsistent.rs:16:21 | LL | struct S where i32: Foo; | ^^^ -warning: Trait bound i32: Foo does not depend on any type or lifetime parameters +warning: trait bound i32: Foo does not depend on any type or lifetime parameters --> $DIR/trivial-bounds-inconsistent.rs:18:20 | LL | trait T where i32: Foo {} | ^^^ -warning: Trait bound i32: Foo does not depend on any type or lifetime parameters +warning: trait bound i32: Foo does not depend on any type or lifetime parameters --> $DIR/trivial-bounds-inconsistent.rs:20:20 | LL | union U where i32: Foo { f: i32 } @@ -37,55 +37,55 @@ LL - type Y where i32: Foo = (); LL + type Y = (); | -warning: Trait bound i32: Foo does not depend on any type or lifetime parameters +warning: trait bound i32: Foo does not depend on any type or lifetime parameters --> $DIR/trivial-bounds-inconsistent.rs:22:19 | LL | type Y where i32: Foo = (); | ^^^ -warning: Trait bound i32: Foo does not depend on any type or lifetime parameters +warning: trait bound i32: Foo does not depend on any type or lifetime parameters --> $DIR/trivial-bounds-inconsistent.rs:26:28 | LL | impl Foo for () where i32: Foo { | ^^^ -warning: Trait bound i32: Foo does not depend on any type or lifetime parameters +warning: trait bound i32: Foo does not depend on any type or lifetime parameters --> $DIR/trivial-bounds-inconsistent.rs:34:19 | LL | fn f() where i32: Foo { | ^^^ -warning: Trait bound &'static str: Foo does not depend on any type or lifetime parameters +warning: trait bound &'static str: Foo does not depend on any type or lifetime parameters --> $DIR/trivial-bounds-inconsistent.rs:41:28 | LL | fn g() where &'static str: Foo { | ^^^ -warning: Trait bound str: Sized does not depend on any type or lifetime parameters +warning: trait bound str: Sized does not depend on any type or lifetime parameters --> $DIR/trivial-bounds-inconsistent.rs:55:37 | LL | struct TwoStrs(str, str) where str: Sized; | ^^^^^ -warning: Trait bound for<'a> Dst<(dyn A + 'a)>: Sized does not depend on any type or lifetime parameters +warning: trait bound for<'a> Dst<(dyn A + 'a)>: Sized does not depend on any type or lifetime parameters --> $DIR/trivial-bounds-inconsistent.rs:57:51 | LL | fn unsized_local() where for<'a> Dst: Sized { | ^^^^^ -warning: Trait bound str: Sized does not depend on any type or lifetime parameters +warning: trait bound str: Sized does not depend on any type or lifetime parameters --> $DIR/trivial-bounds-inconsistent.rs:61:35 | LL | fn return_str() -> str where str: Sized { | ^^^^^ -warning: Trait bound String: Neg does not depend on any type or lifetime parameters +warning: trait bound String: Neg does not depend on any type or lifetime parameters --> $DIR/trivial-bounds-inconsistent.rs:65:46 | LL | fn use_op(s: String) -> String where String: ::std::ops::Neg { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -warning: Trait bound i32: Iterator does not depend on any type or lifetime parameters +warning: trait bound i32: Iterator does not depend on any type or lifetime parameters --> $DIR/trivial-bounds-inconsistent.rs:70:25 | LL | fn use_for() where i32: Iterator { diff --git a/src/test/ui/trivial-bounds/trivial-bounds-leak.stderr b/src/test/ui/trivial-bounds/trivial-bounds-leak.stderr index 97ef2dd37f..d9e0d21541 100644 --- a/src/test/ui/trivial-bounds/trivial-bounds-leak.stderr +++ b/src/test/ui/trivial-bounds/trivial-bounds-leak.stderr @@ -24,7 +24,9 @@ error[E0277]: the trait bound `i32: Foo` is not satisfied --> $DIR/trivial-bounds-leak.rs:25:15 | LL | Foo::test(&4i32); - | ^^^^^ the trait `Foo` is not implemented for `i32` + | --------- ^^^^^ 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 @@ -36,7 +38,9 @@ error[E0277]: the trait bound `i32: Foo` is not satisfied --> $DIR/trivial-bounds-leak.rs:26:22 | LL | generic_function(5i32); - | ^^^^ the trait `Foo` is not implemented for `i32` + | ---------------- ^^^^ the trait `Foo` is not implemented for `i32` + | | + | required by a bound introduced by this call | note: required by a bound in `generic_function` --> $DIR/trivial-bounds-leak.rs:29:24 diff --git a/src/test/ui/trivial-bounds/trivial-bounds-lint.stderr b/src/test/ui/trivial-bounds/trivial-bounds-lint.stderr index c685d9e740..20e0ddfc29 100644 --- a/src/test/ui/trivial-bounds/trivial-bounds-lint.stderr +++ b/src/test/ui/trivial-bounds/trivial-bounds-lint.stderr @@ -1,4 +1,4 @@ -error: Trait bound i32: Copy does not depend on any type or lifetime parameters +error: trait bound i32: Copy does not depend on any type or lifetime parameters --> $DIR/trivial-bounds-lint.rs:5:21 | LL | struct A where i32: Copy; @@ -10,37 +10,37 @@ note: the lint level is defined here LL | #![deny(trivial_bounds)] | ^^^^^^^^^^^^^^ -error: Trait bound i32: X<()> does not depend on any type or lifetime parameters +error: trait bound i32: X<()> does not depend on any type or lifetime parameters --> $DIR/trivial-bounds-lint.rs:18:30 | LL | fn global_param() where i32: X<()> {} | ^^^^^ -error: Trait bound i32: Z does not depend on any type or lifetime parameters +error: trait bound i32: Z does not depend on any type or lifetime parameters --> $DIR/trivial-bounds-lint.rs:22:35 | LL | fn global_projection() where i32: Z {} | ^^^^^^^^^^ -error: Lifetime bound i32: 'static does not depend on any type or lifetime parameters +error: lifetime bound i32: 'static does not depend on any type or lifetime parameters --> $DIR/trivial-bounds-lint.rs:29:34 | LL | fn global_lifetimes() where i32: 'static, &'static str: 'static {} | ^^^^^^^ -error: Lifetime bound &'static str: 'static does not depend on any type or lifetime parameters +error: lifetime bound &'static str: 'static does not depend on any type or lifetime parameters --> $DIR/trivial-bounds-lint.rs:29:57 | LL | fn global_lifetimes() where i32: 'static, &'static str: 'static {} | ^^^^^^^ -error: Lifetime bound 'static: 'static does not depend on any type or lifetime parameters +error: lifetime bound 'static: 'static does not depend on any type or lifetime parameters --> $DIR/trivial-bounds-lint.rs:35:37 | LL | fn global_outlives() where 'static: 'static {} | ^^^^^^^ -error: Trait bound i32: Copy does not depend on any type or lifetime parameters +error: trait bound i32: Copy does not depend on any type or lifetime parameters --> $DIR/trivial-bounds-lint.rs:38:46 | LL | fn mixed_bounds() where i32: X + Copy {} diff --git a/src/test/ui/try-block/try-block-opt-init.stderr b/src/test/ui/try-block/try-block-opt-init.stderr index 58eb076bba..bd145fd64e 100644 --- a/src/test/ui/try-block/try-block-opt-init.stderr +++ b/src/test/ui/try-block/try-block-opt-init.stderr @@ -2,7 +2,7 @@ error[E0381]: borrow of possibly-uninitialized variable: `cfg_res` --> $DIR/try-block-opt-init.rs:15:5 | LL | assert_eq!(cfg_res, 5); - | ^^^^^^^^^^^^^^^^^^^^^^^ use of possibly-uninitialized `cfg_res` + | ^^^^^^^^^^^^^^^^^^^^^^ use of possibly-uninitialized `cfg_res` | = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/try-block/try-block-unused-delims.stderr b/src/test/ui/try-block/try-block-unused-delims.stderr index c5a2405462..d8dd31645e 100644 --- a/src/test/ui/try-block/try-block-unused-delims.stderr +++ b/src/test/ui/try-block/try-block-unused-delims.stderr @@ -2,43 +2,71 @@ warning: unnecessary parentheses around function argument --> $DIR/try-block-unused-delims.rs:11:13 | LL | consume((try {})); - | ^^^^^^^^ help: remove these parentheses + | ^ ^ | note: the lint level is defined here --> $DIR/try-block-unused-delims.rs:6:9 | LL | #![warn(unused_parens, unused_braces)] | ^^^^^^^^^^^^^ +help: remove these parentheses + | +LL - consume((try {})); +LL + consume(try {}); + | warning: unnecessary braces around function argument --> $DIR/try-block-unused-delims.rs:14:13 | LL | consume({ try {} }); - | ^^^^^^^^^^ help: remove these braces + | ^^ ^^ | note: the lint level is defined here --> $DIR/try-block-unused-delims.rs:6:24 | LL | #![warn(unused_parens, unused_braces)] | ^^^^^^^^^^^^^ +help: remove these braces + | +LL - consume({ try {} }); +LL + consume(try {}); + | warning: unnecessary parentheses around `match` scrutinee expression --> $DIR/try-block-unused-delims.rs:17:11 | LL | match (try {}) { - | ^^^^^^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - match (try {}) { +LL + match try {} { + | warning: unnecessary parentheses around `let` scrutinee expression --> $DIR/try-block-unused-delims.rs:22:22 | LL | if let Err(()) = (try {}) {} - | ^^^^^^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - if let Err(()) = (try {}) {} +LL + if let Err(()) = try {} {} + | warning: unnecessary parentheses around `match` scrutinee expression --> $DIR/try-block-unused-delims.rs:25:11 | LL | match (try {}) { - | ^^^^^^^^ help: remove these parentheses + | ^ ^ + | +help: remove these parentheses + | +LL - match (try {}) { +LL + match try {} { + | warning: 5 warnings emitted diff --git a/src/test/ui/tutorial-suffix-inference-test.stderr b/src/test/ui/tutorial-suffix-inference-test.stderr index ac1027ff34..fbfbffbd24 100644 --- a/src/test/ui/tutorial-suffix-inference-test.stderr +++ b/src/test/ui/tutorial-suffix-inference-test.stderr @@ -2,10 +2,12 @@ error[E0308]: mismatched types --> $DIR/tutorial-suffix-inference-test.rs:9:18 | LL | identity_u16(x); - | ^ - | | - | expected `u16`, found `u8` - | help: you can convert a `u8` to a `u16`: `x.into()` + | ^ expected `u16`, found `u8` + | +help: you can convert a `u8` to a `u16` + | +LL | identity_u16(x.into()); + | +++++++ error[E0308]: mismatched types --> $DIR/tutorial-suffix-inference-test.rs:12:18 @@ -16,7 +18,7 @@ LL | identity_u16(y); help: you can convert an `i32` to a `u16` and panic if the converted value doesn't fit | LL | identity_u16(y.try_into().unwrap()); - | ~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error[E0308]: mismatched types --> $DIR/tutorial-suffix-inference-test.rs:21:18 @@ -27,7 +29,7 @@ LL | identity_u16(a); help: you can convert an `isize` to a `u16` and panic if the converted value doesn't fit | LL | identity_u16(a.try_into().unwrap()); - | ~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error: aborting due to 3 previous errors diff --git a/src/test/ui/type-alias-impl-trait/auto-trait-leakage3.stderr b/src/test/ui/type-alias-impl-trait/auto-trait-leakage3.stderr index 86b3f87d34..c0147e56c9 100644 --- a/src/test/ui/type-alias-impl-trait/auto-trait-leakage3.stderr +++ b/src/test/ui/type-alias-impl-trait/auto-trait-leakage3.stderr @@ -9,7 +9,7 @@ note: ...which requires type-checking `m::bar`... | LL | is_send(foo()); | ^^^^^^^ - = note: ...which requires evaluating trait selection obligation `impl std::fmt::Debug: std::marker::Send`... + = note: ...which requires evaluating trait selection obligation `impl core::fmt::Debug: core::marker::Send`... = note: ...which again requires computing type of `m::Foo::{opaque#0}`, completing the cycle note: cycle used when checking item types in module `m` --> $DIR/auto-trait-leakage3.rs:6:1 diff --git a/src/test/ui/type-alias-impl-trait/bound_reduction2.rs b/src/test/ui/type-alias-impl-trait/bound_reduction2.rs index a15074c359..579067340e 100644 --- a/src/test/ui/type-alias-impl-trait/bound_reduction2.rs +++ b/src/test/ui/type-alias-impl-trait/bound_reduction2.rs @@ -7,6 +7,7 @@ trait TraitWithAssoc { } type Foo = impl Trait; +//~^ ERROR could not find defining uses trait Trait {} @@ -14,5 +15,9 @@ impl Trait for () {} fn foo_desugared(_: T) -> Foo { //~^ ERROR non-defining opaque type use in defining scope + //~| ERROR non-defining opaque type use in defining scope + //~| ERROR non-defining opaque type use in defining scope + //~| ERROR `T` is part of concrete type but not used in parameter list + //~| ERROR `T` is part of concrete type but not used in parameter list () } diff --git a/src/test/ui/type-alias-impl-trait/bound_reduction2.stderr b/src/test/ui/type-alias-impl-trait/bound_reduction2.stderr index c9d6a43b90..a77c0000f1 100644 --- a/src/test/ui/type-alias-impl-trait/bound_reduction2.stderr +++ b/src/test/ui/type-alias-impl-trait/bound_reduction2.stderr @@ -1,8 +1,34 @@ +error: type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias + --> $DIR/bound_reduction2.rs:16:60 + | +LL | fn foo_desugared(_: T) -> Foo { + | ____________________________________________________________^ +LL | | +LL | | +LL | | +... | +LL | | () +LL | | } + | |_^ + +error: type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias + --> $DIR/bound_reduction2.rs:16:60 + | +LL | fn foo_desugared(_: T) -> Foo { + | ____________________________________________________________^ +LL | | +LL | | +LL | | +... | +LL | | () +LL | | } + | |_^ + error: non-defining opaque type use in defining scope - --> $DIR/bound_reduction2.rs:15:46 + --> $DIR/bound_reduction2.rs:16:1 | LL | fn foo_desugared(_: T) -> Foo { - | ^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: used non-generic type `::Assoc` for generic parameter --> $DIR/bound_reduction2.rs:9:10 @@ -10,5 +36,35 @@ note: used non-generic type `::Assoc` for generic parameter LL | type Foo = impl Trait; | ^ -error: aborting due to previous error +error: non-defining opaque type use in defining scope + --> $DIR/bound_reduction2.rs:16:1 + | +LL | fn foo_desugared(_: T) -> Foo { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: used non-generic type `_` for generic parameter + --> $DIR/bound_reduction2.rs:9:10 + | +LL | type Foo = impl Trait; + | ^ + +error: non-defining opaque type use in defining scope + --> $DIR/bound_reduction2.rs:16:1 + | +LL | fn foo_desugared(_: T) -> Foo { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: used non-generic type `_` for generic parameter + --> $DIR/bound_reduction2.rs:9:10 + | +LL | type Foo = impl Trait; + | ^ + +error: could not find defining uses + --> $DIR/bound_reduction2.rs:9:15 + | +LL | type Foo = impl Trait; + | ^^^^^^^^^^^^^ + +error: aborting due to 6 previous errors diff --git a/src/test/ui/type-alias-impl-trait/bounds-are-checked.stderr b/src/test/ui/type-alias-impl-trait/bounds-are-checked.stderr index d5fafe0588..da9f81d6bd 100644 --- a/src/test/ui/type-alias-impl-trait/bounds-are-checked.stderr +++ b/src/test/ui/type-alias-impl-trait/bounds-are-checked.stderr @@ -14,7 +14,7 @@ LL | type X<'a> = impl Into<&'static str> + From<&'a str>; | = note: expected trait `From<&'a str>` found trait `From<&'static str>` -note: the lifetime `'a` as defined on the item at 6:8... +note: the lifetime `'a` as defined here... --> $DIR/bounds-are-checked.rs:6:8 | LL | type X<'a> = impl Into<&'static str> + From<&'a str>; diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.rs b/src/test/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.rs index 31f992976b..885aae619d 100644 --- a/src/test/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.rs +++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.rs @@ -3,6 +3,7 @@ fn main() {} type Two<'a, 'b> = impl std::fmt::Debug; +//~^ ERROR could not find defining uses fn one<'a>(t: &'a ()) -> Two<'a, 'a> { //~^ ERROR non-defining opaque type use diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.stderr b/src/test/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.stderr index 08b26b8fc1..b99c6a51f4 100644 --- a/src/test/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.stderr +++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.stderr @@ -1,5 +1,5 @@ error: non-defining opaque type use in defining scope - --> $DIR/generic_duplicate_lifetime_param.rs:7:26 + --> $DIR/generic_duplicate_lifetime_param.rs:8:26 | LL | fn one<'a>(t: &'a ()) -> Two<'a, 'a> { | ^^^^^^^^^^^ @@ -10,5 +10,11 @@ note: lifetime used multiple times LL | type Two<'a, 'b> = impl std::fmt::Debug; | ^^ ^^ -error: aborting due to previous error +error: could not find defining uses + --> $DIR/generic_duplicate_lifetime_param.rs:5:20 + | +LL | type Two<'a, 'b> = impl std::fmt::Debug; + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use.rs b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use.rs index a4e40f516d..33cd2f6ba0 100644 --- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use.rs +++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use.rs @@ -6,8 +6,11 @@ fn main() {} // test that unused generic parameters are ok type TwoTys = impl Debug; +//~^ ERROR could not find defining uses type TwoLifetimes<'a, 'b> = impl Debug; +//~^ ERROR could not find defining uses type TwoConsts = impl Debug; +//~^ ERROR could not find defining uses fn one_ty(t: T) -> TwoTys { //~^ ERROR non-defining opaque type use in defining scope diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use.stderr b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use.stderr index 641cce26d9..52c60d1777 100644 --- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use.stderr +++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use.stderr @@ -1,5 +1,5 @@ error: non-defining opaque type use in defining scope - --> $DIR/generic_duplicate_param_use.rs:12:30 + --> $DIR/generic_duplicate_param_use.rs:15:30 | LL | fn one_ty(t: T) -> TwoTys { | ^^^^^^^^^^^^ @@ -10,29 +10,47 @@ note: type used multiple times LL | type TwoTys = impl Debug; | ^ ^ +error: could not find defining uses + --> $DIR/generic_duplicate_param_use.rs:8:21 + | +LL | type TwoTys = impl Debug; + | ^^^^^^^^^^ + error: non-defining opaque type use in defining scope - --> $DIR/generic_duplicate_param_use.rs:17:36 + --> $DIR/generic_duplicate_param_use.rs:20:36 | LL | fn one_lifetime<'a>(t: &'a u32) -> TwoLifetimes<'a, 'a> { | ^^^^^^^^^^^^^^^^^^^^ | note: lifetime used multiple times - --> $DIR/generic_duplicate_param_use.rs:9:19 + --> $DIR/generic_duplicate_param_use.rs:10:19 | LL | type TwoLifetimes<'a, 'b> = impl Debug; | ^^ ^^ +error: could not find defining uses + --> $DIR/generic_duplicate_param_use.rs:10:29 + | +LL | type TwoLifetimes<'a, 'b> = impl Debug; + | ^^^^^^^^^^ + error: non-defining opaque type use in defining scope - --> $DIR/generic_duplicate_param_use.rs:22:50 + --> $DIR/generic_duplicate_param_use.rs:25:50 | LL | fn one_const(t: *mut [u8; N]) -> TwoConsts { | ^^^^^^^^^^^^^^^ | note: constant used multiple times - --> $DIR/generic_duplicate_param_use.rs:10:22 + --> $DIR/generic_duplicate_param_use.rs:12:22 | LL | type TwoConsts = impl Debug; | ^ ^ -error: aborting due to 3 previous errors +error: could not find defining uses + --> $DIR/generic_duplicate_param_use.rs:12:50 + | +LL | type TwoConsts = impl Debug; + | ^^^^^^^^^^ + +error: aborting due to 6 previous errors diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use2.rs b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use2.rs index a74731df69..04fb57b39c 100644 --- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use2.rs +++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use2.rs @@ -6,6 +6,7 @@ fn main() {} // test that unused generic parameters are ok type Two = impl Debug; +//~^ ERROR `T` doesn't implement `Debug` fn one(t: T) -> Two { //~^ ERROR non-defining opaque type use in defining scope diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use2.stderr b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use2.stderr index d87e8c5783..fca9b70d18 100644 --- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use2.stderr +++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use2.stderr @@ -1,5 +1,5 @@ error: non-defining opaque type use in defining scope - --> $DIR/generic_duplicate_param_use2.rs:10:27 + --> $DIR/generic_duplicate_param_use2.rs:11:27 | LL | fn one(t: T) -> Two { | ^^^^^^^^^ @@ -10,5 +10,17 @@ note: type used multiple times LL | type Two = impl Debug; | ^ ^ -error: aborting due to previous error +error[E0277]: `T` doesn't implement `Debug` + --> $DIR/generic_duplicate_param_use2.rs:8:18 + | +LL | type Two = impl Debug; + | ^^^^^^^^^^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | +help: consider restricting type parameter `T` + | +LL | type Two = impl Debug; + | +++++++++++++++++ +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use3.rs b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use3.rs index 0597b8385d..1a755d3902 100644 --- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use3.rs +++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use3.rs @@ -6,6 +6,7 @@ fn main() {} // test that unused generic parameters are ok type Two = impl Debug; +//~^ ERROR `T` doesn't implement `Debug` fn one(t: T) -> Two { //~^ ERROR non-defining opaque type use in defining scope @@ -17,5 +18,6 @@ fn two(t: T, _: U) -> Two { } fn three(_: T, u: U) -> Two { + //~^ ERROR concrete type differs from previous defining opaque type use u } diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use3.stderr b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use3.stderr index 711de855f0..90b04c043a 100644 --- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use3.stderr +++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use3.stderr @@ -1,5 +1,5 @@ error: non-defining opaque type use in defining scope - --> $DIR/generic_duplicate_param_use3.rs:10:27 + --> $DIR/generic_duplicate_param_use3.rs:11:27 | LL | fn one(t: T) -> Two { | ^^^^^^^^^ @@ -10,5 +10,29 @@ note: type used multiple times LL | type Two = impl Debug; | ^ ^ -error: aborting due to previous error +error: concrete type differs from previous defining opaque type use + --> $DIR/generic_duplicate_param_use3.rs:20:1 + | +LL | fn three(_: T, u: U) -> Two { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `T`, got `U` + | +note: previous use here + --> $DIR/generic_duplicate_param_use3.rs:16:1 + | +LL | fn two(t: T, _: U) -> Two { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +error[E0277]: `T` doesn't implement `Debug` + --> $DIR/generic_duplicate_param_use3.rs:8:18 + | +LL | type Two = impl Debug; + | ^^^^^^^^^^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | +help: consider restricting type parameter `T` + | +LL | type Two = impl Debug; + | +++++++++++++++++ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use4.rs b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use4.rs index e77c94988f..50d95c83d5 100644 --- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use4.rs +++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use4.rs @@ -6,6 +6,7 @@ fn main() {} // test that unused generic parameters are ok type Two = impl Debug; +//~^ ERROR `U` doesn't implement `Debug` fn one(t: T) -> Two { //~^ ERROR non-defining opaque type use in defining scope diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use4.stderr b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use4.stderr index fcf01f5164..c4be2fa83f 100644 --- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use4.stderr +++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use4.stderr @@ -1,5 +1,5 @@ error: non-defining opaque type use in defining scope - --> $DIR/generic_duplicate_param_use4.rs:10:27 + --> $DIR/generic_duplicate_param_use4.rs:11:27 | LL | fn one(t: T) -> Two { | ^^^^^^^^^ @@ -10,5 +10,17 @@ note: type used multiple times LL | type Two = impl Debug; | ^ ^ -error: aborting due to previous error +error[E0277]: `U` doesn't implement `Debug` + --> $DIR/generic_duplicate_param_use4.rs:8:18 + | +LL | type Two = impl Debug; + | ^^^^^^^^^^ `U` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | +help: consider restricting type parameter `U` + | +LL | type Two = impl Debug; + | +++++++++++++++++ +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/type-alias-impl-trait/generic_nondefining_use.rs b/src/test/ui/type-alias-impl-trait/generic_nondefining_use.rs index 7ee5f7b068..cf43085877 100644 --- a/src/test/ui/type-alias-impl-trait/generic_nondefining_use.rs +++ b/src/test/ui/type-alias-impl-trait/generic_nondefining_use.rs @@ -5,8 +5,11 @@ use std::fmt::Debug; fn main() {} type OneTy = impl Debug; +//~^ ERROR could not find defining uses type OneLifetime<'a> = impl Debug; +//~^ ERROR could not find defining uses type OneConst = impl Debug; +//~^ ERROR could not find defining uses // Not defining uses, because they doesn't define *all* possible generics. diff --git a/src/test/ui/type-alias-impl-trait/generic_nondefining_use.stderr b/src/test/ui/type-alias-impl-trait/generic_nondefining_use.stderr index 5b42f10a6e..3aa42a2548 100644 --- a/src/test/ui/type-alias-impl-trait/generic_nondefining_use.stderr +++ b/src/test/ui/type-alias-impl-trait/generic_nondefining_use.stderr @@ -1,5 +1,5 @@ error: non-defining opaque type use in defining scope - --> $DIR/generic_nondefining_use.rs:13:21 + --> $DIR/generic_nondefining_use.rs:16:21 | LL | fn concrete_ty() -> OneTy { | ^^^^^^^^^^ @@ -10,8 +10,14 @@ note: used non-generic type `u32` for generic parameter LL | type OneTy = impl Debug; | ^ +error: could not find defining uses + --> $DIR/generic_nondefining_use.rs:7:17 + | +LL | type OneTy = impl Debug; + | ^^^^^^^^^^ + error: non-defining opaque type use in defining scope - --> $DIR/generic_nondefining_use.rs:18:27 + --> $DIR/generic_nondefining_use.rs:21:27 | LL | type OneLifetime<'a> = impl Debug; | -- cannot use static lifetime; use a bound lifetime instead or remove the lifetime parameter from the opaque type @@ -19,17 +25,29 @@ LL | type OneLifetime<'a> = impl Debug; LL | fn concrete_lifetime() -> OneLifetime<'static> { | ^^^^^^^^^^^^^^^^^^^^ +error: could not find defining uses + --> $DIR/generic_nondefining_use.rs:9:24 + | +LL | type OneLifetime<'a> = impl Debug; + | ^^^^^^^^^^ + error: non-defining opaque type use in defining scope - --> $DIR/generic_nondefining_use.rs:23:24 + --> $DIR/generic_nondefining_use.rs:26:24 | LL | fn concrete_const() -> OneConst<{ 123 }> { | ^^^^^^^^^^^^^^^^^ | note: used non-generic constant `123_usize` for generic parameter - --> $DIR/generic_nondefining_use.rs:9:21 + --> $DIR/generic_nondefining_use.rs:11:21 | LL | type OneConst = impl Debug; | ^ -error: aborting due to 3 previous errors +error: could not find defining uses + --> $DIR/generic_nondefining_use.rs:11:33 + | +LL | type OneConst = impl Debug; + | ^^^^^^^^^^ + +error: aborting due to 6 previous errors diff --git a/src/test/ui/type-alias-impl-trait/incomplete-inference.rs b/src/test/ui/type-alias-impl-trait/incomplete-inference.rs index 955d1288a4..4c8bf2cfca 100644 --- a/src/test/ui/type-alias-impl-trait/incomplete-inference.rs +++ b/src/test/ui/type-alias-impl-trait/incomplete-inference.rs @@ -8,7 +8,6 @@ fn bar() -> Foo { } fn baz() -> Foo { - //~^ ERROR: concrete type differs from previous defining opaque type use Some(()) } diff --git a/src/test/ui/type-alias-impl-trait/incomplete-inference.stderr b/src/test/ui/type-alias-impl-trait/incomplete-inference.stderr index 53cdf9e5b3..0cdd4cc8dc 100644 --- a/src/test/ui/type-alias-impl-trait/incomplete-inference.stderr +++ b/src/test/ui/type-alias-impl-trait/incomplete-inference.stderr @@ -4,18 +4,6 @@ error[E0282]: type annotations needed LL | None | ^^^^ cannot infer type for type parameter `T` declared on the enum `Option` -error: concrete type differs from previous defining opaque type use - --> $DIR/incomplete-inference.rs:10:1 - | -LL | fn baz() -> Foo { - | ^^^^^^^^^^^^^^^ expected `[type error]`, got `Option<()>` - | -note: previous use here - --> $DIR/incomplete-inference.rs:5:1 - | -LL | fn bar() -> Foo { - | ^^^^^^^^^^^^^^^ - -error: aborting due to 2 previous errors +error: aborting due to previous error For more information about this error, try `rustc --explain E0282`. diff --git a/src/test/ui/type-alias-impl-trait/inference-cycle.stderr b/src/test/ui/type-alias-impl-trait/inference-cycle.stderr index 4c5921c7f6..e121246647 100644 --- a/src/test/ui/type-alias-impl-trait/inference-cycle.stderr +++ b/src/test/ui/type-alias-impl-trait/inference-cycle.stderr @@ -9,7 +9,7 @@ note: ...which requires type-checking `m::bar`... | LL | is_send(foo()); // Today: error | ^^^^^^^ - = note: ...which requires evaluating trait selection obligation `impl std::fmt::Debug: std::marker::Send`... + = note: ...which requires evaluating trait selection obligation `impl core::fmt::Debug: core::marker::Send`... = note: ...which again requires computing type of `m::Foo::{opaque#0}`, completing the cycle note: cycle used when checking item types in module `m` --> $DIR/inference-cycle.rs:4:1 diff --git a/src/test/ui/type-alias-impl-trait/issue-60371.rs b/src/test/ui/type-alias-impl-trait/issue-60371.rs index 37a2f28ce0..9d2ba849c8 100644 --- a/src/test/ui/type-alias-impl-trait/issue-60371.rs +++ b/src/test/ui/type-alias-impl-trait/issue-60371.rs @@ -11,6 +11,7 @@ impl Bug for &() { const FUN: fn() -> Self::Item = || (); //~^ ERROR the trait bound `(): Bug` is not satisfied + //~| ERROR non-defining opaque type use in defining scope } fn main() {} diff --git a/src/test/ui/type-alias-impl-trait/issue-60371.stderr b/src/test/ui/type-alias-impl-trait/issue-60371.stderr index 1710e07644..62ab7eb456 100644 --- a/src/test/ui/type-alias-impl-trait/issue-60371.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-60371.stderr @@ -16,7 +16,16 @@ LL | const FUN: fn() -> Self::Item = || (); = help: the following implementations were found: <&() as Bug> -error: aborting due to 2 previous errors +error: non-defining opaque type use in defining scope + --> $DIR/issue-60371.rs:12:37 + | +LL | impl Bug for &() { + | - cannot use static lifetime; use a bound lifetime instead or remove the lifetime parameter from the opaque type +... +LL | const FUN: fn() -> Self::Item = || (); + | ^^^^^ + +error: aborting due to 3 previous errors Some errors have detailed explanations: E0277, E0658. For more information about an error, try `rustc --explain E0277`. diff --git a/src/test/ui/type-alias-impl-trait/issue-60564.rs b/src/test/ui/type-alias-impl-trait/issue-60564.rs index 78def0d113..44dcec2c3d 100644 --- a/src/test/ui/type-alias-impl-trait/issue-60564.rs +++ b/src/test/ui/type-alias-impl-trait/issue-60564.rs @@ -6,6 +6,7 @@ trait IterBits { } type IterBitsIter = impl std::iter::Iterator; +//~^ ERROR could not find defining uses impl IterBits for T where diff --git a/src/test/ui/type-alias-impl-trait/issue-60564.stderr b/src/test/ui/type-alias-impl-trait/issue-60564.stderr index 66fa862ef9..6b73fbef01 100644 --- a/src/test/ui/type-alias-impl-trait/issue-60564.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-60564.stderr @@ -1,5 +1,5 @@ error: non-defining opaque type use in defining scope - --> $DIR/issue-60564.rs:19:34 + --> $DIR/issue-60564.rs:20:34 | LL | fn iter_bits(self, n: u8) -> Self::BitsIter { | ^^^^^^^^^^^^^^ @@ -10,5 +10,11 @@ note: used non-generic type `u8` for generic parameter LL | type IterBitsIter = impl std::iter::Iterator; | ^ -error: aborting due to previous error +error: could not find defining uses + --> $DIR/issue-60564.rs:8:30 + | +LL | type IterBitsIter = impl std::iter::Iterator; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors diff --git a/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.rs b/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.rs new file mode 100644 index 0000000000..2e6354088a --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.rs @@ -0,0 +1,14 @@ +// Regression test for issue #68368 +// Ensures that we don't ICE when emitting an error +// for a non-defining use when lifetimes are involved + +#![feature(type_alias_impl_trait)] +trait Trait {} +type Alias<'a, U> = impl Trait; +//~^ ERROR could not find defining uses +fn f<'a>() -> Alias<'a, ()> {} +//~^ ERROR non-defining opaque type use in defining scope + +fn main() {} + +impl Trait for () {} diff --git a/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.stderr b/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.stderr new file mode 100644 index 0000000000..721f99a3f0 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.stderr @@ -0,0 +1,20 @@ +error: non-defining opaque type use in defining scope + --> $DIR/issue-68368-non-defining-use-2.rs:9:15 + | +LL | fn f<'a>() -> Alias<'a, ()> {} + | ^^^^^^^^^^^^^ + | +note: used non-generic type `()` for generic parameter + --> $DIR/issue-68368-non-defining-use-2.rs:7:16 + | +LL | type Alias<'a, U> = impl Trait; + | ^ + +error: could not find defining uses + --> $DIR/issue-68368-non-defining-use-2.rs:7:21 + | +LL | type Alias<'a, U> = impl Trait; + | ^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use.rs b/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use.rs index 3b6decbe9c..3addd8dcc4 100644 --- a/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use.rs +++ b/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use.rs @@ -5,6 +5,7 @@ #![feature(type_alias_impl_trait)] trait Trait {} type Alias<'a, U> = impl Trait; +//~^ ERROR could not find defining uses fn f<'a>() -> Alias<'a, ()> {} //~^ ERROR non-defining opaque type use in defining scope diff --git a/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use.stderr b/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use.stderr index c2fa54f50f..f5b8fccf65 100644 --- a/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use.stderr @@ -1,5 +1,5 @@ error: non-defining opaque type use in defining scope - --> $DIR/issue-68368-non-defining-use.rs:8:15 + --> $DIR/issue-68368-non-defining-use.rs:9:15 | LL | fn f<'a>() -> Alias<'a, ()> {} | ^^^^^^^^^^^^^ @@ -10,5 +10,11 @@ note: used non-generic type `()` for generic parameter LL | type Alias<'a, U> = impl Trait; | ^ -error: aborting due to previous error +error: could not find defining uses + --> $DIR/issue-68368-non-defining-use.rs:7:21 + | +LL | type Alias<'a, U> = impl Trait; + | ^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors diff --git a/src/test/ui/type-alias-impl-trait/issue-74761-2.rs b/src/test/ui/type-alias-impl-trait/issue-74761-2.rs index 4345b5d886..d26ca5c3ea 100644 --- a/src/test/ui/type-alias-impl-trait/issue-74761-2.rs +++ b/src/test/ui/type-alias-impl-trait/issue-74761-2.rs @@ -1,4 +1,3 @@ -#![feature(member_constraints)] #![feature(type_alias_impl_trait)] pub trait A { diff --git a/src/test/ui/type-alias-impl-trait/issue-74761-2.stderr b/src/test/ui/type-alias-impl-trait/issue-74761-2.stderr index 7a321458b0..f15d0a069c 100644 --- a/src/test/ui/type-alias-impl-trait/issue-74761-2.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-74761-2.stderr @@ -1,11 +1,11 @@ error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait, self type, or predicates - --> $DIR/issue-74761-2.rs:8:6 + --> $DIR/issue-74761-2.rs:7:6 | LL | impl<'a, 'b> A for () { | ^^ unconstrained lifetime parameter error[E0207]: the lifetime parameter `'b` is not constrained by the impl trait, self type, or predicates - --> $DIR/issue-74761-2.rs:8:10 + --> $DIR/issue-74761-2.rs:7:10 | LL | impl<'a, 'b> A for () { | ^^ unconstrained lifetime parameter diff --git a/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn3.rs b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn3.rs index bcd9aeff6b..11a922443e 100644 --- a/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn3.rs +++ b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn3.rs @@ -11,7 +11,6 @@ fn f(a: A, b: B) -> (X, X) } fn g(a: A, b: B) -> (X, X) { - //~^ ERROR concrete type differs from previous defining opaque type (a, b) //~^ ERROR mismatched types } diff --git a/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn3.stderr b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn3.stderr index 3d943b77af..bbe709dcca 100644 --- a/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn3.stderr +++ b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn3.stderr @@ -1,11 +1,10 @@ error[E0308]: mismatched types - --> $DIR/multiple-def-uses-in-one-fn3.rs:15:9 + --> $DIR/multiple-def-uses-in-one-fn3.rs:14:9 | LL | fn g(a: A, b: B) -> (X, X) { | - - found type parameter | | | expected type parameter -LL | LL | (a, b) | ^ expected type parameter `A`, found type parameter `B` | @@ -14,18 +13,6 @@ LL | (a, b) = note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters -error: concrete type differs from previous defining opaque type use - --> $DIR/multiple-def-uses-in-one-fn3.rs:13:1 - | -LL | fn g(a: A, b: B) -> (X, X) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `A`, got `[type error]` - | -note: previous use here - --> $DIR/multiple-def-uses-in-one-fn3.rs:9:1 - | -LL | fn f(a: A, b: B) -> (X, X) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 2 previous errors +error: aborting due to previous error For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/type-alias-impl-trait/not_a_defining_use.rs b/src/test/ui/type-alias-impl-trait/not_a_defining_use.rs index f29b980dfd..107cd39457 100644 --- a/src/test/ui/type-alias-impl-trait/not_a_defining_use.rs +++ b/src/test/ui/type-alias-impl-trait/not_a_defining_use.rs @@ -5,6 +5,7 @@ use std::fmt::Debug; fn main() {} type Two = impl Debug; +//~^ ERROR `T` doesn't implement `Debug` fn two(t: T) -> Two { //~^ ERROR non-defining opaque type use in defining scope @@ -26,6 +27,7 @@ impl Bar for u32 { } fn four(t: T) -> Two { + //~^ ERROR concrete type differs from previous (t, ::FOO) } diff --git a/src/test/ui/type-alias-impl-trait/not_a_defining_use.stderr b/src/test/ui/type-alias-impl-trait/not_a_defining_use.stderr index 2fa236b373..08e4984552 100644 --- a/src/test/ui/type-alias-impl-trait/not_a_defining_use.stderr +++ b/src/test/ui/type-alias-impl-trait/not_a_defining_use.stderr @@ -1,5 +1,5 @@ error: non-defining opaque type use in defining scope - --> $DIR/not_a_defining_use.rs:9:27 + --> $DIR/not_a_defining_use.rs:10:27 | LL | fn two(t: T) -> Two { | ^^^^^^^^^^^ @@ -10,5 +10,30 @@ note: used non-generic type `u32` for generic parameter LL | type Two = impl Debug; | ^ -error: aborting due to previous error +error: concrete type differs from previous defining opaque type use + --> $DIR/not_a_defining_use.rs:29:1 + | +LL | fn four(t: T) -> Two { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `(T, i8)`, got `(T, ::Blub)` + | +note: previous use here + --> $DIR/not_a_defining_use.rs:15:1 + | +LL | fn three(t: T) -> Two { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +error[E0277]: `T` doesn't implement `Debug` + --> $DIR/not_a_defining_use.rs:7:18 + | +LL | type Two = impl Debug; + | ^^^^^^^^^^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | + = note: required because of the requirements on the impl of `Debug` for `(T, i8)` +help: consider restricting type parameter `T` + | +LL | type Two = impl Debug; + | +++++++++++++++++ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/type-param-constraints.rs b/src/test/ui/type-param-constraints.rs index 4b42fddaf5..3d87a089fc 100644 --- a/src/test/ui/type-param-constraints.rs +++ b/src/test/ui/type-param-constraints.rs @@ -4,8 +4,6 @@ #![allow(dead_code)] // pretty-expanded FIXME #23616 -#![feature(box_syntax)] - fn p_foo(_pinned: T) { } fn s_foo(_shared: T) { } fn u_foo(_unique: T) { } @@ -27,13 +25,13 @@ fn r(i:isize) -> r { pub fn main() { p_foo(r(10)); - p_foo::>(box r(10)); - p_foo::>(box 10); + p_foo::>(Box::new(r(10))); + p_foo::>(Box::new(10)); p_foo(10); - s_foo::>(box 10); + s_foo::>(Box::new(10)); s_foo(10); - u_foo::>(box 10); + u_foo::>(Box::new(10)); u_foo(10); } diff --git a/src/test/ui/type/type-ascription-precedence.stderr b/src/test/ui/type/type-ascription-precedence.stderr index 92d3f18e82..ebce257b27 100644 --- a/src/test/ui/type/type-ascription-precedence.stderr +++ b/src/test/ui/type/type-ascription-precedence.stderr @@ -28,7 +28,22 @@ error[E0600]: cannot apply unary operator `-` to type `Z` LL | -(S: Z); | ^^^^^^^ cannot apply unary operator `-` | - = note: an implementation of `std::ops::Neg` might be missing for `Z` +note: an implementation of `std::ops::Neg` might be missing for `Z` + --> $DIR/type-ascription-precedence.rs:9:1 + | +LL | struct Z; + | ^^^^^^^^^ must implement `std::ops::Neg` +note: the following trait must be implemented + --> $SRC_DIR/core/src/ops/arith.rs:LL:COL + | +LL | / pub trait Neg { +LL | | /// The resulting type after applying the `-` operator. +LL | | #[stable(feature = "rust1", since = "1.0.0")] +LL | | type Output; +... | +LL | | fn neg(self) -> Self::Output; +LL | | } + | |_^ error[E0308]: mismatched types --> $DIR/type-ascription-precedence.rs:45:5 diff --git a/src/test/ui/type/type-check/issue-88577-check-fn-with-more-than-65535-arguments.rs b/src/test/ui/type/type-check/issue-88577-check-fn-with-more-than-65535-arguments.rs new file mode 100644 index 0000000000..e50cc58651 --- /dev/null +++ b/src/test/ui/type/type-check/issue-88577-check-fn-with-more-than-65535-arguments.rs @@ -0,0 +1,12 @@ +macro_rules! many_args { + ([$($t:tt)*]#$($h:tt)*) => { + many_args!{[$($t)*$($t)*]$($h)*} + }; + ([$($t:tt)*]) => { + fn _f($($t: ()),*) {} //~ ERROR function can not have more than 65535 arguments + } +} + +many_args!{[_]########## ######} + +fn main() {} diff --git a/src/test/ui/type/type-check/issue-88577-check-fn-with-more-than-65535-arguments.stderr b/src/test/ui/type/type-check/issue-88577-check-fn-with-more-than-65535-arguments.stderr new file mode 100644 index 0000000000..615fd2ccb0 --- /dev/null +++ b/src/test/ui/type/type-check/issue-88577-check-fn-with-more-than-65535-arguments.stderr @@ -0,0 +1,13 @@ +error: function can not have more than 65535 arguments + --> $DIR/issue-88577-check-fn-with-more-than-65535-arguments.rs:6:24 + | +LL | fn _f($($t: ()),*) {} + | ________________________^ +LL | | } +LL | | } +LL | | +LL | | many_args!{[_]########## ######} + | |____________^ + +error: aborting due to previous error + diff --git a/src/test/ui/type/type-parameter-defaults-referencing-Self-ppaux.stderr b/src/test/ui/type/type-parameter-defaults-referencing-Self-ppaux.stderr index 2de5f6eb0f..8a296dc7ee 100644 --- a/src/test/ui/type/type-parameter-defaults-referencing-Self-ppaux.stderr +++ b/src/test/ui/type/type-parameter-defaults-referencing-Self-ppaux.stderr @@ -16,7 +16,6 @@ error[E0038]: the trait `MyAdd` cannot be made into an object LL | let y = x as dyn MyAdd; | ^^^^^^^^^^^^^^ `MyAdd` cannot be made into an object | - = help: consider moving `add` to another trait note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit --> $DIR/type-parameter-defaults-referencing-Self-ppaux.rs:6:55 | @@ -24,6 +23,7 @@ LL | trait MyAdd { fn add(&self, other: &Rhs) -> Self; } | ----- ^^^^ ...because method `add` references the `Self` type in its return type | | | this trait cannot be made into an object... + = help: consider moving `add` to another trait error: aborting due to 2 previous errors diff --git a/src/test/ui/typeck/call-block.rs b/src/test/ui/typeck/call-block.rs new file mode 100644 index 0000000000..0390d7db04 --- /dev/null +++ b/src/test/ui/typeck/call-block.rs @@ -0,0 +1,3 @@ +fn main() { + let _ = {42}(); //~ ERROR expected function, found `{integer}` +} diff --git a/src/test/ui/typeck/call-block.stderr b/src/test/ui/typeck/call-block.stderr new file mode 100644 index 0000000000..68984bc1c4 --- /dev/null +++ b/src/test/ui/typeck/call-block.stderr @@ -0,0 +1,11 @@ +error[E0618]: expected function, found `{integer}` + --> $DIR/call-block.rs:2:13 + | +LL | let _ = {42}(); + | ^^^^-- + | | + | call expression requires function + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0618`. diff --git a/src/test/ui/typeck/issue-87771-ice-assign-assign-to-bool.rs b/src/test/ui/typeck/issue-87771-ice-assign-assign-to-bool.rs new file mode 100644 index 0000000000..751dc8719c --- /dev/null +++ b/src/test/ui/typeck/issue-87771-ice-assign-assign-to-bool.rs @@ -0,0 +1,4 @@ +fn main() { + let mut a; + a = a = true; //~ ERROR mismatched types +} 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 new file mode 100644 index 0000000000..fe10fa733d --- /dev/null +++ b/src/test/ui/typeck/issue-87771-ice-assign-assign-to-bool.stderr @@ -0,0 +1,9 @@ +error[E0308]: mismatched types + --> $DIR/issue-87771-ice-assign-assign-to-bool.rs:3:9 + | +LL | a = a = true; + | ^^^^^^^^ expected `bool`, found `()` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/typeck/issue-88609.rs b/src/test/ui/typeck/issue-88609.rs new file mode 100644 index 0000000000..dc459c885f --- /dev/null +++ b/src/test/ui/typeck/issue-88609.rs @@ -0,0 +1,19 @@ +// Regression test for #88609: +// The return type for `main` is not normalized while checking if it implements +// the trait `std::process::Termination`. + +// build-pass + +trait Same { + type Output; +} + +impl Same for T { + type Output = T; +} + +type Unit = <() as Same>::Output; + +fn main() -> Result { + unimplemented!() +} diff --git a/src/test/ui/typeck/issue-88803-call-expr-method.fixed b/src/test/ui/typeck/issue-88803-call-expr-method.fixed new file mode 100644 index 0000000000..19b96ecf3f --- /dev/null +++ b/src/test/ui/typeck/issue-88803-call-expr-method.fixed @@ -0,0 +1,9 @@ +// run-rustfix + +fn main() { + let a = Some(42); + println!( + "The value is {}.", + a.unwrap() //~ERROR [E0615] + ); +} diff --git a/src/test/ui/typeck/issue-88803-call-expr-method.rs b/src/test/ui/typeck/issue-88803-call-expr-method.rs new file mode 100644 index 0000000000..a061994663 --- /dev/null +++ b/src/test/ui/typeck/issue-88803-call-expr-method.rs @@ -0,0 +1,9 @@ +// run-rustfix + +fn main() { + let a = Some(42); + println!( + "The value is {}.", + (a.unwrap)() //~ERROR [E0615] + ); +} diff --git a/src/test/ui/typeck/issue-88803-call-expr-method.stderr b/src/test/ui/typeck/issue-88803-call-expr-method.stderr new file mode 100644 index 0000000000..dd717ed941 --- /dev/null +++ b/src/test/ui/typeck/issue-88803-call-expr-method.stderr @@ -0,0 +1,15 @@ +error[E0615]: attempted to take value of method `unwrap` on type `Option<{integer}>` + --> $DIR/issue-88803-call-expr-method.rs:7:12 + | +LL | (a.unwrap)() + | ^^^^^^ method, not a field + | +help: remove wrapping parentheses to call the method + | +LL - (a.unwrap)() +LL + a.unwrap() + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0615`. diff --git a/src/test/ui/typeck/issue-88844.rs b/src/test/ui/typeck/issue-88844.rs new file mode 100644 index 0000000000..116c75aabd --- /dev/null +++ b/src/test/ui/typeck/issue-88844.rs @@ -0,0 +1,14 @@ +// Regression test for #88844. + +struct Struct { value: i32 } +//~^ NOTE: similarly named struct `Struct` defined here + +impl Stuct { +//~^ ERROR: cannot find type `Stuct` in this scope [E0412] +//~| HELP: a struct with a similar name exists + fn new() -> Self { + Self { value: 42 } + } +} + +fn main() {} diff --git a/src/test/ui/typeck/issue-88844.stderr b/src/test/ui/typeck/issue-88844.stderr new file mode 100644 index 0000000000..90bba90be3 --- /dev/null +++ b/src/test/ui/typeck/issue-88844.stderr @@ -0,0 +1,12 @@ +error[E0412]: cannot find type `Stuct` in this scope + --> $DIR/issue-88844.rs:6:6 + | +LL | struct Struct { value: i32 } + | ------------- similarly named struct `Struct` defined here +... +LL | impl Stuct { + | ^^^^^ help: a struct with a similar name exists: `Struct` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0412`. diff --git a/src/test/ui/typeck/issue-89044-wrapped-expr-method.fixed b/src/test/ui/typeck/issue-89044-wrapped-expr-method.fixed new file mode 100644 index 0000000000..0a3086a345 --- /dev/null +++ b/src/test/ui/typeck/issue-89044-wrapped-expr-method.fixed @@ -0,0 +1,9 @@ +// run-rustfix + +fn main() { + let a = Some(42); + println!( + "The value is {}.", + (a.unwrap()) //~ERROR [E0615] + ); +} diff --git a/src/test/ui/typeck/issue-89044-wrapped-expr-method.rs b/src/test/ui/typeck/issue-89044-wrapped-expr-method.rs new file mode 100644 index 0000000000..83617e035e --- /dev/null +++ b/src/test/ui/typeck/issue-89044-wrapped-expr-method.rs @@ -0,0 +1,9 @@ +// run-rustfix + +fn main() { + let a = Some(42); + println!( + "The value is {}.", + (a.unwrap) //~ERROR [E0615] + ); +} diff --git a/src/test/ui/typeck/issue-89044-wrapped-expr-method.stderr b/src/test/ui/typeck/issue-89044-wrapped-expr-method.stderr new file mode 100644 index 0000000000..6fa0915dca --- /dev/null +++ b/src/test/ui/typeck/issue-89044-wrapped-expr-method.stderr @@ -0,0 +1,14 @@ +error[E0615]: attempted to take value of method `unwrap` on type `Option<{integer}>` + --> $DIR/issue-89044-wrapped-expr-method.rs:7:12 + | +LL | (a.unwrap) + | ^^^^^^ method, not a field + | +help: use parentheses to call the method + | +LL | (a.unwrap()) + | ++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0615`. diff --git a/src/test/ui/typeck/issue-89275.rs b/src/test/ui/typeck/issue-89275.rs new file mode 100644 index 0000000000..b91c001754 --- /dev/null +++ b/src/test/ui/typeck/issue-89275.rs @@ -0,0 +1,29 @@ +#![recursion_limit = "5"] // To reduce noise + +//expect mutability error when ambiguous traits are in scope +//and not an overflow error on the span in the main function. + +struct Ratio(T); + +pub trait Pow { + fn pow(self) -> Self; +} + +impl<'a, T> Pow for &'a Ratio +where + &'a T: Pow, +{ + fn pow(self) -> Self { + self + } +} + +fn downcast<'a, W: ?Sized>() -> &'a W { + todo!() +} + +struct Other; + +fn main() { + let other: &mut Other = downcast();//~ERROR 28:29: 28:39: mismatched types [E0308] +} diff --git a/src/test/ui/typeck/issue-89275.stderr b/src/test/ui/typeck/issue-89275.stderr new file mode 100644 index 0000000000..d73e647d21 --- /dev/null +++ b/src/test/ui/typeck/issue-89275.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/issue-89275.rs:28:29 + | +LL | let other: &mut Other = downcast(); + | ---------- ^^^^^^^^^^ types differ in mutability + | | + | expected due to this + | + = note: expected mutable reference `&mut Other` + found reference `&_` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/typeck/issue-89935.rs b/src/test/ui/typeck/issue-89935.rs new file mode 100644 index 0000000000..03f8f09a72 --- /dev/null +++ b/src/test/ui/typeck/issue-89935.rs @@ -0,0 +1,18 @@ +// check-pass + +trait Foo: Baz {} +trait Bar {} +trait Baz: Bar { + fn bar(&self); +} + +impl Bar for T {} +impl Baz for T { + fn bar(&self) {} +} + +fn accept_foo(x: Box) { + x.bar(); +} + +fn main() {} diff --git a/src/test/ui/typeck/issue-90483-inaccessible-field-adjustment.rs b/src/test/ui/typeck/issue-90483-inaccessible-field-adjustment.rs new file mode 100644 index 0000000000..74e50d46e8 --- /dev/null +++ b/src/test/ui/typeck/issue-90483-inaccessible-field-adjustment.rs @@ -0,0 +1,14 @@ +// edition:2021 + +mod m { + pub struct S { foo: i32 } + impl S { + pub fn foo(&self) -> i32 { 42 } + } +} + +fn bar(s: &m::S) { + || s.foo() + s.foo; //~ ERROR E0616 +} + +fn main() {} diff --git a/src/test/ui/typeck/issue-90483-inaccessible-field-adjustment.stderr b/src/test/ui/typeck/issue-90483-inaccessible-field-adjustment.stderr new file mode 100644 index 0000000000..02cdc102c1 --- /dev/null +++ b/src/test/ui/typeck/issue-90483-inaccessible-field-adjustment.stderr @@ -0,0 +1,14 @@ +error[E0616]: field `foo` of struct `S` is private + --> $DIR/issue-90483-inaccessible-field-adjustment.rs:11:18 + | +LL | || s.foo() + s.foo; + | ^^^ private field + | +help: a method `foo` also exists, call it with parentheses + | +LL | || s.foo() + s.foo(); + | ++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0616`. diff --git a/src/test/ui/typeck/typeck-unsafe-always-share.stderr b/src/test/ui/typeck/typeck-unsafe-always-share.stderr index c0f388bd15..4b5804253b 100644 --- a/src/test/ui/typeck/typeck-unsafe-always-share.stderr +++ b/src/test/ui/typeck/typeck-unsafe-always-share.stderr @@ -2,7 +2,9 @@ error[E0277]: `UnsafeCell>` cannot be shared between threads s --> $DIR/typeck-unsafe-always-share.rs:19:10 | LL | test(us); - | ^^ `UnsafeCell>` cannot be shared between threads safely + | ---- ^^ `UnsafeCell>` cannot be shared between threads safely + | | + | required by a bound introduced by this call | = help: the trait `Sync` is not implemented for `UnsafeCell>` note: required by a bound in `test` @@ -15,7 +17,9 @@ error[E0277]: `UnsafeCell` cannot be shared between threads safely --> $DIR/typeck-unsafe-always-share.rs:23:10 | LL | test(uns); - | ^^^ `UnsafeCell` cannot be shared between threads safely + | ---- ^^^ `UnsafeCell` cannot be shared between threads safely + | | + | required by a bound introduced by this call | = help: the trait `Sync` is not implemented for `UnsafeCell` note: required by a bound in `test` @@ -46,7 +50,9 @@ error[E0277]: `NoSync` cannot be shared between threads safely --> $DIR/typeck-unsafe-always-share.rs:30:10 | LL | test(NoSync); - | ^^^^^^ `NoSync` cannot be shared between threads safely + | ---- ^^^^^^ `NoSync` cannot be shared between threads safely + | | + | required by a bound introduced by this call | = help: the trait `Sync` is not implemented for `NoSync` note: required by a bound in `test` diff --git a/src/test/ui/typeclasses-eq-example-static.rs b/src/test/ui/typeclasses-eq-example-static.rs index 282d51a93d..f982ad6a0d 100644 --- a/src/test/ui/typeclasses-eq-example-static.rs +++ b/src/test/ui/typeclasses-eq-example-static.rs @@ -3,7 +3,6 @@ #![allow(non_camel_case_types)] #![allow(non_snake_case)] #![allow(dead_code)] -#![feature(box_syntax)] // Example from lkuper's intern talk, August 2012 -- now with static // methods! @@ -59,11 +58,11 @@ pub fn main() { assert!(Equal::isEq(&leaf(cyan), &leaf(cyan))); assert!(!Equal::isEq(&leaf(cyan), &leaf(yellow))); - assert!(Equal::isEq(&branch(box leaf(magenta), box leaf(cyan)), - &branch(box leaf(magenta), box leaf(cyan)))); + assert!(Equal::isEq(&branch(Box::new(leaf(magenta)), Box::new(leaf(cyan))), + &branch(Box::new(leaf(magenta)), Box::new(leaf(cyan))))); - assert!(!Equal::isEq(&branch(box leaf(magenta), box leaf(cyan)), - &branch(box leaf(magenta), box leaf(magenta)))); + assert!(!Equal::isEq(&branch(Box::new(leaf(magenta)), Box::new(leaf(cyan))), + &branch(Box::new(leaf(magenta)), Box::new(leaf(magenta))))); println!("Assertions all succeeded!"); } diff --git a/src/test/ui/typeclasses-eq-example.rs b/src/test/ui/typeclasses-eq-example.rs index 8d1d22eb82..4400301e61 100644 --- a/src/test/ui/typeclasses-eq-example.rs +++ b/src/test/ui/typeclasses-eq-example.rs @@ -3,7 +3,6 @@ #![allow(non_camel_case_types)] #![allow(non_snake_case)] #![allow(dead_code)] -#![feature(box_syntax)] // Example from lkuper's intern talk, August 2012. use Color::{cyan, magenta, yellow, black}; @@ -55,11 +54,11 @@ pub fn main() { assert!(leaf(cyan).isEq(&leaf(cyan))); assert!(!leaf(cyan).isEq(&leaf(yellow))); - assert!(branch(box leaf(magenta), box leaf(cyan)) - .isEq(&branch(box leaf(magenta), box leaf(cyan)))); + assert!(branch(Box::new(leaf(magenta)), Box::new(leaf(cyan))) + .isEq(&branch(Box::new(leaf(magenta)), Box::new(leaf(cyan))))); - assert!(!branch(box leaf(magenta), box leaf(cyan)) - .isEq(&branch(box leaf(magenta), box leaf(magenta)))); + assert!(!branch(Box::new(leaf(magenta)), Box::new(leaf(cyan))) + .isEq(&branch(Box::new(leaf(magenta)), Box::new(leaf(magenta))))); println!("Assertions all succeeded!"); } diff --git a/src/test/ui/typeof/type_mismatch.stderr b/src/test/ui/typeof/type_mismatch.stderr index 5c58e29fa0..e82b5e4497 100644 --- a/src/test/ui/typeof/type_mismatch.stderr +++ b/src/test/ui/typeof/type_mismatch.stderr @@ -15,7 +15,7 @@ LL | let b: typeof(a) = 1i8; help: change the type of the numeric literal from `i8` to `u8` | LL | let b: typeof(a) = 1u8; - | ~~~ + | ~~ error: aborting due to 2 previous errors diff --git a/src/test/ui/ufcs/ufcs-explicit-self-bad.rs b/src/test/ui/ufcs/ufcs-explicit-self-bad.rs index e836d33976..cb1fac0bae 100644 --- a/src/test/ui/ufcs/ufcs-explicit-self-bad.rs +++ b/src/test/ui/ufcs/ufcs-explicit-self-bad.rs @@ -1,9 +1,9 @@ -#![feature(box_syntax)] - struct Foo { f: isize, } + + impl Foo { fn foo(self: isize, x: isize) -> isize { //~^ ERROR invalid `self` parameter type @@ -48,12 +48,12 @@ impl<'a, T> SomeTrait for &'a Bar { } fn main() { - let foo = box Foo { + let foo = Box::new(Foo { f: 1, - }; + }); println!("{}", foo.foo(2)); - let bar = box Bar { + let bar = Box::new(Bar { f: 1, - }; + }); println!("{} {}", bar.foo(2), bar.bar(2)); } diff --git a/src/test/ui/ufcs/ufcs-explicit-self-bad.stderr b/src/test/ui/ufcs/ufcs-explicit-self-bad.stderr index 133ecab229..f325d1d818 100644 --- a/src/test/ui/ufcs/ufcs-explicit-self-bad.stderr +++ b/src/test/ui/ufcs/ufcs-explicit-self-bad.stderr @@ -33,12 +33,12 @@ LL | fn dummy2(self: &Bar) {} | = note: expected reference `&'a Bar` found reference `&Bar` -note: the anonymous lifetime defined on the method body at 37:21... +note: the anonymous lifetime defined here... --> $DIR/ufcs-explicit-self-bad.rs:37:21 | LL | fn dummy2(self: &Bar) {} | ^^^^^^^ -note: ...does not necessarily outlive the lifetime `'a` as defined on the impl at 35:6 +note: ...does not necessarily outlive the lifetime `'a` as defined here --> $DIR/ufcs-explicit-self-bad.rs:35:6 | LL | impl<'a, T> SomeTrait for &'a Bar { @@ -52,12 +52,12 @@ LL | fn dummy2(self: &Bar) {} | = note: expected reference `&'a Bar` found reference `&Bar` -note: the lifetime `'a` as defined on the impl at 35:6... +note: the lifetime `'a` as defined here... --> $DIR/ufcs-explicit-self-bad.rs:35:6 | LL | impl<'a, T> SomeTrait for &'a Bar { | ^^ -note: ...does not necessarily outlive the anonymous lifetime defined on the method body at 37:21 +note: ...does not necessarily outlive the anonymous lifetime defined here --> $DIR/ufcs-explicit-self-bad.rs:37:21 | LL | fn dummy2(self: &Bar) {} @@ -71,12 +71,12 @@ LL | fn dummy3(self: &&Bar) {} | = note: expected reference `&'a Bar` found reference `&Bar` -note: the anonymous lifetime defined on the method body at 39:22... +note: the anonymous lifetime defined here... --> $DIR/ufcs-explicit-self-bad.rs:39:22 | LL | fn dummy3(self: &&Bar) {} | ^^^^^^^ -note: ...does not necessarily outlive the lifetime `'a` as defined on the impl at 35:6 +note: ...does not necessarily outlive the lifetime `'a` as defined here --> $DIR/ufcs-explicit-self-bad.rs:35:6 | LL | impl<'a, T> SomeTrait for &'a Bar { @@ -90,12 +90,12 @@ LL | fn dummy3(self: &&Bar) {} | = note: expected reference `&'a Bar` found reference `&Bar` -note: the lifetime `'a` as defined on the impl at 35:6... +note: the lifetime `'a` as defined here... --> $DIR/ufcs-explicit-self-bad.rs:35:6 | LL | impl<'a, T> SomeTrait for &'a Bar { | ^^ -note: ...does not necessarily outlive the anonymous lifetime defined on the method body at 39:22 +note: ...does not necessarily outlive the anonymous lifetime defined here --> $DIR/ufcs-explicit-self-bad.rs:39:22 | LL | fn dummy3(self: &&Bar) {} diff --git a/src/test/ui/ufcs/ufcs-qpath-self-mismatch.stderr b/src/test/ui/ufcs/ufcs-qpath-self-mismatch.stderr index 8dc024697d..23b9157375 100644 --- a/src/test/ui/ufcs/ufcs-qpath-self-mismatch.stderr +++ b/src/test/ui/ufcs/ufcs-qpath-self-mismatch.stderr @@ -20,7 +20,7 @@ LL | >::add(1u32, 2); help: change the type of the numeric literal from `u32` to `i32` | LL | >::add(1i32, 2); - | ~~~~ + | ~~~ error[E0308]: mismatched types --> $DIR/ufcs-qpath-self-mismatch.rs:8:31 @@ -31,7 +31,7 @@ LL | >::add(1, 2u32); help: change the type of the numeric literal from `u32` to `i32` | LL | >::add(1, 2i32); - | ~~~~ + | ~~~ error: aborting due to 3 previous errors diff --git a/src/test/ui/unboxed-closures/unboxed-closure-illegal-move.stderr b/src/test/ui/unboxed-closures/unboxed-closure-illegal-move.stderr index f8c90176ff..482d3e44fe 100644 --- a/src/test/ui/unboxed-closures/unboxed-closure-illegal-move.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closure-illegal-move.stderr @@ -4,7 +4,10 @@ error[E0507]: cannot move out of `x`, a captured variable in an `Fn` closure LL | let x = Box::new(0); | - captured outer variable LL | let f = to_fn(|| drop(x)); - | ^ move occurs because `x` has type `Box`, which does not implement the `Copy` trait + | --------^- + | | | + | | move occurs because `x` has type `Box`, which does not implement the `Copy` trait + | captured by this `Fn` closure error[E0507]: cannot move out of `x`, a captured variable in an `FnMut` closure --> $DIR/unboxed-closure-illegal-move.rs:19:35 @@ -12,7 +15,10 @@ error[E0507]: cannot move out of `x`, a captured variable in an `FnMut` closure LL | let x = Box::new(0); | - captured outer variable LL | let f = to_fn_mut(|| drop(x)); - | ^ move occurs because `x` has type `Box`, which does not implement the `Copy` trait + | --------^- + | | | + | | move occurs because `x` has type `Box`, which does not implement the `Copy` trait + | captured by this `FnMut` closure error[E0507]: cannot move out of `x`, a captured variable in an `Fn` closure --> $DIR/unboxed-closure-illegal-move.rs:28:36 @@ -20,7 +26,10 @@ error[E0507]: cannot move out of `x`, a captured variable in an `Fn` closure LL | let x = Box::new(0); | - captured outer variable LL | let f = to_fn(move || drop(x)); - | ^ move occurs because `x` has type `Box`, which does not implement the `Copy` trait + | -------------^- + | | | + | | move occurs because `x` has type `Box`, which does not implement the `Copy` trait + | captured by this `Fn` closure error[E0507]: cannot move out of `x`, a captured variable in an `FnMut` closure --> $DIR/unboxed-closure-illegal-move.rs:32:40 @@ -28,7 +37,10 @@ error[E0507]: cannot move out of `x`, a captured variable in an `FnMut` closure LL | let x = Box::new(0); | - captured outer variable LL | let f = to_fn_mut(move || drop(x)); - | ^ move occurs because `x` has type `Box`, which does not implement the `Copy` trait + | -------------^- + | | | + | | move occurs because `x` has type `Box`, which does not implement the `Copy` trait + | captured by this `FnMut` closure error: aborting due to 4 previous errors diff --git a/src/test/ui/unboxed-closures/unboxed-closures-boxed.rs b/src/test/ui/unboxed-closures/unboxed-closures-boxed.rs index b2596e49aa..3f550fd042 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-boxed.rs +++ b/src/test/ui/unboxed-closures/unboxed-closures-boxed.rs @@ -1,10 +1,9 @@ // run-pass -#![feature(box_syntax)] use std::ops::FnMut; fn make_adder(x: i32) -> Boxi32+'static> { - (box move |y: i32| -> i32 { x + y }) as + Box::new(move |y: i32| -> i32 { x + y }) as Boxi32+'static> } diff --git a/src/test/ui/unboxed-closures/unboxed-closures-fnmut-as-fn.stderr b/src/test/ui/unboxed-closures/unboxed-closures-fnmut-as-fn.stderr index f30bf40983..c8ce3091cf 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-fnmut-as-fn.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closures-fnmut-as-fn.stderr @@ -2,7 +2,9 @@ error[E0277]: expected a `Fn<(isize,)>` closure, found `S` --> $DIR/unboxed-closures-fnmut-as-fn.rs:28:21 | LL | let x = call_it(&S, 22); - | ^^ expected an `Fn<(isize,)>` closure, found `S` + | ------- ^^ expected an `Fn<(isize,)>` closure, found `S` + | | + | required by a bound introduced by this call | = help: the trait `Fn<(isize,)>` is not implemented for `S` note: required by a bound in `call_it` diff --git a/src/test/ui/unboxed-closures/unboxed-closures-infer-argument-types-two-region-pointers.stderr b/src/test/ui/unboxed-closures/unboxed-closures-infer-argument-types-two-region-pointers.stderr index bd20fd2618..d7813338f6 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-infer-argument-types-two-region-pointers.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closures-infer-argument-types-two-region-pointers.stderr @@ -4,7 +4,7 @@ error[E0312]: lifetime of reference outlives lifetime of borrowed content... LL | x.set(y); | ^ | -note: ...the reference is valid for the anonymous lifetime #2 defined on the body at 16:14... +note: ...the reference is valid for the anonymous lifetime #2 defined here... --> $DIR/unboxed-closures-infer-argument-types-two-region-pointers.rs:16:14 | LL | doit(0, &|x, y| { @@ -12,7 +12,7 @@ LL | doit(0, &|x, y| { LL | | x.set(y); LL | | }); | |_____^ -note: ...but the borrowed content is only valid for the anonymous lifetime #3 defined on the body at 16:14 +note: ...but the borrowed content is only valid for the anonymous lifetime #3 defined here --> $DIR/unboxed-closures-infer-argument-types-two-region-pointers.rs:16:14 | LL | doit(0, &|x, y| { diff --git a/src/test/ui/unboxed-closures/unboxed-closures-type-mismatch.stderr b/src/test/ui/unboxed-closures/unboxed-closures-type-mismatch.stderr index 67bf4be54e..f791ea62ce 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-type-mismatch.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closures-type-mismatch.stderr @@ -7,7 +7,7 @@ LL | let z = f(1_usize, 2); help: change the type of the numeric literal from `usize` to `isize` | LL | let z = f(1_isize, 2); - | ~~~~~~~ + | ~~~~~ error: aborting due to previous error diff --git a/src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.stderr b/src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.stderr index 6b21b9246f..c9a20232f3 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.stderr @@ -2,7 +2,9 @@ error[E0277]: expected a `Fn<(&isize,)>` closure, found `for<'r> unsafe fn(&'r i --> $DIR/unboxed-closures-unsafe-extern-fn.rs:20:21 | LL | let x = call_it(&square, 22); - | ^^^^^^^ expected an `Fn<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}` + | ------- ^^^^^^^ expected an `Fn<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}` + | | + | required by a bound introduced by this call | = help: the trait `for<'r> Fn<(&'r isize,)>` is not implemented for `for<'r> unsafe fn(&'r isize) -> isize {square}` note: required by a bound in `call_it` @@ -15,7 +17,9 @@ error[E0277]: expected a `FnMut<(&isize,)>` closure, found `for<'r> unsafe fn(&' --> $DIR/unboxed-closures-unsafe-extern-fn.rs:25:25 | LL | let y = call_it_mut(&mut square, 22); - | ^^^^^^^^^^^ expected an `FnMut<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}` + | ----------- ^^^^^^^^^^^ expected an `FnMut<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}` + | | + | required by a bound introduced by this call | = help: the trait `for<'r> FnMut<(&'r isize,)>` is not implemented for `for<'r> unsafe fn(&'r isize) -> isize {square}` note: required by a bound in `call_it_mut` @@ -28,7 +32,9 @@ error[E0277]: expected a `FnOnce<(&isize,)>` closure, found `for<'r> unsafe fn(& --> $DIR/unboxed-closures-unsafe-extern-fn.rs:30:26 | LL | let z = call_it_once(square, 22); - | ^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}` + | ------------ ^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}` + | | + | required by a bound introduced by this call | = help: the trait `for<'r> FnOnce<(&'r isize,)>` is not implemented for `for<'r> unsafe fn(&'r isize) -> isize {square}` note: required by a bound in `call_it_once` diff --git a/src/test/ui/unboxed-closures/unboxed-closures-wrong-abi.stderr b/src/test/ui/unboxed-closures/unboxed-closures-wrong-abi.stderr index 936cb27759..77c176de62 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-wrong-abi.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closures-wrong-abi.stderr @@ -2,7 +2,9 @@ error[E0277]: expected a `Fn<(&isize,)>` closure, found `for<'r> extern "C" fn(& --> $DIR/unboxed-closures-wrong-abi.rs:20:21 | LL | let x = call_it(&square, 22); - | ^^^^^^^ expected an `Fn<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}` + | ------- ^^^^^^^ expected an `Fn<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}` + | | + | required by a bound introduced by this call | = help: the trait `for<'r> Fn<(&'r isize,)>` is not implemented for `for<'r> extern "C" fn(&'r isize) -> isize {square}` note: required by a bound in `call_it` @@ -15,7 +17,9 @@ error[E0277]: expected a `FnMut<(&isize,)>` closure, found `for<'r> extern "C" f --> $DIR/unboxed-closures-wrong-abi.rs:25:25 | LL | let y = call_it_mut(&mut square, 22); - | ^^^^^^^^^^^ expected an `FnMut<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}` + | ----------- ^^^^^^^^^^^ expected an `FnMut<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}` + | | + | required by a bound introduced by this call | = help: the trait `for<'r> FnMut<(&'r isize,)>` is not implemented for `for<'r> extern "C" fn(&'r isize) -> isize {square}` note: required by a bound in `call_it_mut` @@ -28,7 +32,9 @@ error[E0277]: expected a `FnOnce<(&isize,)>` closure, found `for<'r> extern "C" --> $DIR/unboxed-closures-wrong-abi.rs:30:26 | LL | let z = call_it_once(square, 22); - | ^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}` + | ------------ ^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}` + | | + | required by a bound introduced by this call | = help: the trait `for<'r> FnOnce<(&'r isize,)>` is not implemented for `for<'r> extern "C" fn(&'r isize) -> isize {square}` note: required by a bound in `call_it_once` diff --git a/src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.stderr b/src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.stderr index f9f1182e30..64d57773d7 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.stderr @@ -2,7 +2,9 @@ error[E0277]: expected a `Fn<(&isize,)>` closure, found `unsafe fn(isize) -> isi --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:21:21 | LL | let x = call_it(&square, 22); - | ^^^^^^^ expected an `Fn<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}` + | ------- ^^^^^^^ expected an `Fn<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}` + | | + | required by a bound introduced by this call | = help: the trait `for<'r> Fn<(&'r isize,)>` is not implemented for `unsafe fn(isize) -> isize {square}` note: required by a bound in `call_it` @@ -15,7 +17,9 @@ error[E0277]: expected a `FnMut<(&isize,)>` closure, found `unsafe fn(isize) -> --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:26:25 | LL | let y = call_it_mut(&mut square, 22); - | ^^^^^^^^^^^ expected an `FnMut<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}` + | ----------- ^^^^^^^^^^^ expected an `FnMut<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}` + | | + | required by a bound introduced by this call | = help: the trait `for<'r> FnMut<(&'r isize,)>` is not implemented for `unsafe fn(isize) -> isize {square}` note: required by a bound in `call_it_mut` @@ -28,7 +32,9 @@ error[E0277]: expected a `FnOnce<(&isize,)>` closure, found `unsafe fn(isize) -> --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:31:26 | LL | let z = call_it_once(square, 22); - | ^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}` + | ------------ ^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}` + | | + | required by a bound introduced by this call | = help: the trait `for<'r> FnOnce<(&'r isize,)>` is not implemented for `unsafe fn(isize) -> isize {square}` note: required by a bound in `call_it_once` diff --git a/src/test/ui/underscore-imports/shadow.stderr b/src/test/ui/underscore-imports/shadow.stderr index eb16fa9d56..7faede4e6d 100644 --- a/src/test/ui/underscore-imports/shadow.stderr +++ b/src/test/ui/underscore-imports/shadow.stderr @@ -5,8 +5,10 @@ LL | x.deref(); | ^^^^^ method not found in `&()` | = help: items from traits can only be used if the trait is in scope - = note: the following trait is implemented but not in scope; perhaps add a `use` for it: - `use std::ops::Deref;` +help: the following trait is implemented but not in scope; perhaps add a `use` for it: + | +LL | use std::ops::Deref; + | error: aborting due to previous error diff --git a/src/test/ui/uninhabited/uninhabited-patterns.rs b/src/test/ui/uninhabited/uninhabited-patterns.rs index 58c726d218..f1573b6adf 100644 --- a/src/test/ui/uninhabited/uninhabited-patterns.rs +++ b/src/test/ui/uninhabited/uninhabited-patterns.rs @@ -1,8 +1,8 @@ #![feature(box_patterns)] -#![feature(box_syntax)] #![feature(never_type)] #![feature(exhaustive_patterns)] + #![deny(unreachable_patterns)] mod foo { diff --git a/src/test/ui/union/union-derive-clone.mirunsafeck.stderr b/src/test/ui/union/union-derive-clone.mirunsafeck.stderr index b52117cd19..146a627bcd 100644 --- a/src/test/ui/union/union-derive-clone.mirunsafeck.stderr +++ b/src/test/ui/union/union-derive-clone.mirunsafeck.stderr @@ -16,6 +16,10 @@ LL | let w = u.clone(); = note: the following trait bounds were not satisfied: `CloneNoCopy: Copy` which is required by `U5: Clone` +help: consider annotating `CloneNoCopy` with `#[derive(Copy)]` + | +LL | #[derive(Copy)] + | error[E0277]: the trait bound `U1: Copy` is not satisfied --> $DIR/union-derive-clone.rs:6:10 diff --git a/src/test/ui/union/union-derive-clone.thirunsafeck.stderr b/src/test/ui/union/union-derive-clone.thirunsafeck.stderr index b52117cd19..146a627bcd 100644 --- a/src/test/ui/union/union-derive-clone.thirunsafeck.stderr +++ b/src/test/ui/union/union-derive-clone.thirunsafeck.stderr @@ -16,6 +16,10 @@ LL | let w = u.clone(); = note: the following trait bounds were not satisfied: `CloneNoCopy: Copy` which is required by `U5: Clone` +help: consider annotating `CloneNoCopy` with `#[derive(Copy)]` + | +LL | #[derive(Copy)] + | error[E0277]: the trait bound `U1: Copy` is not satisfied --> $DIR/union-derive-clone.rs:6:10 diff --git a/src/test/ui/unique-object-noncopyable.rs b/src/test/ui/unique-object-noncopyable.rs index d243b8f34d..2c40dfc7a4 100644 --- a/src/test/ui/unique-object-noncopyable.rs +++ b/src/test/ui/unique-object-noncopyable.rs @@ -1,5 +1,3 @@ -#![feature(box_syntax)] - trait Foo { fn f(&self); } @@ -18,8 +16,10 @@ impl Foo for Bar { } } + + fn main() { - let x = box Bar { x: 10 }; + let x = Box::new(Bar { x: 10 }); let y: Box = x as Box; let _z = y.clone(); //~ ERROR the method } diff --git a/src/test/ui/unique-pinned-nocopy.stderr b/src/test/ui/unique-pinned-nocopy.stderr index 8e0804ebf9..02ce371c8d 100644 --- a/src/test/ui/unique-pinned-nocopy.stderr +++ b/src/test/ui/unique-pinned-nocopy.stderr @@ -21,6 +21,10 @@ LL | | >(Unique, A); = 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` +help: consider annotating `R` with `#[derive(Clone)]` + | +LL | #[derive(Clone)] + | error: aborting due to previous error diff --git a/src/test/ui/unique/unique-assign-copy.rs b/src/test/ui/unique/unique-assign-copy.rs index 1946981023..b742973ce3 100644 --- a/src/test/ui/unique/unique-assign-copy.rs +++ b/src/test/ui/unique/unique-assign-copy.rs @@ -1,8 +1,7 @@ // run-pass -#![feature(box_syntax)] pub fn main() { - let mut i: Box<_> = box 1; + let mut i: Box<_> = Box::new(1); // Should be a copy let mut j; j = i.clone(); diff --git a/src/test/ui/unique/unique-assign-drop.rs b/src/test/ui/unique/unique-assign-drop.rs index 32068e79df..e7685b589c 100644 --- a/src/test/ui/unique/unique-assign-drop.rs +++ b/src/test/ui/unique/unique-assign-drop.rs @@ -1,11 +1,9 @@ // run-pass #![allow(unused_assignments)] -#![feature(box_syntax)] - pub fn main() { - let i: Box<_> = box 1; - let mut j: Box<_> = box 2; + let i: Box<_> = Box::new(1); + let mut j: Box<_> = Box::new(2); // Should drop the previous value of j j = i; assert_eq!(*j, 1); diff --git a/src/test/ui/unique/unique-assign-generic.rs b/src/test/ui/unique/unique-assign-generic.rs index 2d62ce59ad..d4932d8333 100644 --- a/src/test/ui/unique/unique-assign-generic.rs +++ b/src/test/ui/unique/unique-assign-generic.rs @@ -1,5 +1,4 @@ // run-pass -#![feature(box_syntax)] fn f(t: T) -> T { let t1 = t; @@ -7,6 +6,6 @@ fn f(t: T) -> T { } pub fn main() { - let t = f::>(box 100); - assert_eq!(t, box 100); + let t = f::>(Box::new(100)); + assert_eq!(t, Box::new(100)); } diff --git a/src/test/ui/unique/unique-assign.rs b/src/test/ui/unique/unique-assign.rs index 5a88df071a..d598744f14 100644 --- a/src/test/ui/unique/unique-assign.rs +++ b/src/test/ui/unique/unique-assign.rs @@ -1,9 +1,8 @@ // run-pass #![allow(unused_mut)] -#![feature(box_syntax)] pub fn main() { let mut i: Box<_>; - i = box 1; + i = Box::new(1); assert_eq!(*i, 1); } diff --git a/src/test/ui/unique/unique-autoderef-field.rs b/src/test/ui/unique/unique-autoderef-field.rs index 0360646f13..64147e11f1 100644 --- a/src/test/ui/unique/unique-autoderef-field.rs +++ b/src/test/ui/unique/unique-autoderef-field.rs @@ -1,11 +1,10 @@ // run-pass -#![feature(box_syntax)] struct J { j: isize } pub fn main() { - let i: Box<_> = box J { + let i: Box<_> = Box::new(J { j: 100 - }; + }); assert_eq!(i.j, 100); } diff --git a/src/test/ui/unique/unique-autoderef-index.rs b/src/test/ui/unique/unique-autoderef-index.rs index 5a3d17a84e..ea6598a7f6 100644 --- a/src/test/ui/unique/unique-autoderef-index.rs +++ b/src/test/ui/unique/unique-autoderef-index.rs @@ -1,7 +1,6 @@ // run-pass -#![feature(box_syntax)] pub fn main() { - let i: Box<_> = box vec![100]; + let i: Box<_> = Box::new(vec![100]); assert_eq!((*i)[0], 100); } diff --git a/src/test/ui/unique/unique-cmp.rs b/src/test/ui/unique/unique-cmp.rs index 7bbc61d25a..ee05dd5a31 100644 --- a/src/test/ui/unique/unique-cmp.rs +++ b/src/test/ui/unique/unique-cmp.rs @@ -1,12 +1,11 @@ // run-pass #![allow(unused_allocation)] -#![feature(box_syntax)] pub fn main() { - let i: Box<_> = box 100; - assert_eq!(i, box 100); - assert!(i < box 101); - assert!(i <= box 100); - assert!(i > box 99); - assert!(i >= box 99); + let i: Box<_> = Box::new(100); + assert_eq!(i, Box::new(100)); + assert!(i < Box::new(101)); + assert!(i <= Box::new(100)); + assert!(i > Box::new(99)); + assert!(i >= Box::new(99)); } diff --git a/src/test/ui/unique/unique-containing-tag.rs b/src/test/ui/unique/unique-containing-tag.rs index f24b3a8645..6c31ae99b8 100644 --- a/src/test/ui/unique/unique-containing-tag.rs +++ b/src/test/ui/unique/unique-containing-tag.rs @@ -4,12 +4,10 @@ // pretty-expanded FIXME #23616 -#![feature(box_syntax)] - pub fn main() { enum t { t1(isize), t2(isize), } - let _x: Box<_> = box t::t1(10); + let _x: Box<_> = Box::new(t::t1(10)); /*alt *x { t1(a) { @@ -19,9 +17,9 @@ pub fn main() { }*/ /*alt x { - box t1(a) { + Box::new(t1(a) { assert_eq!(a, 10); - } + }) _ { panic!(); } }*/ } diff --git a/src/test/ui/unique/unique-create.rs b/src/test/ui/unique/unique-create.rs index 3df0f7d55f..c566e79620 100644 --- a/src/test/ui/unique/unique-create.rs +++ b/src/test/ui/unique/unique-create.rs @@ -2,10 +2,8 @@ #![allow(dead_code)] // pretty-expanded FIXME #23616 -#![feature(box_syntax)] - pub fn main() { - let _: Box<_> = box 100; + let _: Box<_> = Box::new(100); } fn vec() { diff --git a/src/test/ui/unique/unique-decl-init-copy.rs b/src/test/ui/unique/unique-decl-init-copy.rs index 6ae95949e8..5b9576fcc7 100644 --- a/src/test/ui/unique/unique-decl-init-copy.rs +++ b/src/test/ui/unique/unique-decl-init-copy.rs @@ -1,8 +1,7 @@ // run-pass -#![feature(box_syntax)] pub fn main() { - let mut i: Box<_> = box 1; + let mut i: Box<_> = Box::new(1); // Should be a copy let mut j = i.clone(); *i = 2; diff --git a/src/test/ui/unique/unique-decl-init.rs b/src/test/ui/unique/unique-decl-init.rs index 2c7b9d6054..1d70860c7c 100644 --- a/src/test/ui/unique/unique-decl-init.rs +++ b/src/test/ui/unique/unique-decl-init.rs @@ -1,8 +1,7 @@ // run-pass -#![feature(box_syntax)] pub fn main() { - let i: Box<_> = box 1; + let i: Box<_> = Box::new(1); let j = i; assert_eq!(*j, 1); } diff --git a/src/test/ui/unique/unique-decl-move.rs b/src/test/ui/unique/unique-decl-move.rs index 4a5ee56ea9..21187510ff 100644 --- a/src/test/ui/unique/unique-decl-move.rs +++ b/src/test/ui/unique/unique-decl-move.rs @@ -1,8 +1,7 @@ // run-pass -#![feature(box_syntax)] pub fn main() { - let i: Box<_> = box 100; + let i: Box<_> = Box::new(100); let j = i; assert_eq!(*j, 100); } diff --git a/src/test/ui/unique/unique-deref.rs b/src/test/ui/unique/unique-deref.rs index 0c6af0f7f9..33a1e9932b 100644 --- a/src/test/ui/unique/unique-deref.rs +++ b/src/test/ui/unique/unique-deref.rs @@ -1,7 +1,6 @@ // run-pass -#![feature(box_syntax)] pub fn main() { - let i: Box<_> = box 100; + let i: Box<_> = Box::new(100); assert_eq!(*i, 100); } diff --git a/src/test/ui/unique/unique-destructure.rs b/src/test/ui/unique/unique-destructure.rs index 9b9f95dfbc..7207ac9629 100644 --- a/src/test/ui/unique/unique-destructure.rs +++ b/src/test/ui/unique/unique-destructure.rs @@ -1,10 +1,9 @@ // run-pass #![feature(box_patterns)] -#![feature(box_syntax)] struct Foo { a: isize, b: isize } pub fn main() { - let box Foo{a, b} = box Foo{a: 100, b: 200}; + let box Foo{ a, b } = Box::new(Foo { a: 100, b: 200 }); assert_eq!(a + b, 300); } diff --git a/src/test/ui/unique/unique-drop-complex.rs b/src/test/ui/unique/unique-drop-complex.rs index 0b7bda83b3..2324f1e1a6 100644 --- a/src/test/ui/unique/unique-drop-complex.rs +++ b/src/test/ui/unique/unique-drop-complex.rs @@ -1,8 +1,6 @@ // run-pass // pretty-expanded FIXME #23616 -#![feature(box_syntax)] - pub fn main() { - let _x: Box<_> = box vec![0,0,0,0,0]; + let _x: Box<_> = Box::new(vec![0,0,0,0,0]); } diff --git a/src/test/ui/unique/unique-fn-arg-move.rs b/src/test/ui/unique/unique-fn-arg-move.rs index ff33839e57..6d42df218f 100644 --- a/src/test/ui/unique/unique-fn-arg-move.rs +++ b/src/test/ui/unique/unique-fn-arg-move.rs @@ -1,11 +1,10 @@ // run-pass -#![feature(box_syntax)] fn f(i: Box) { assert_eq!(*i, 100); } pub fn main() { - let i = box 100; + let i = Box::new(100); f(i); } diff --git a/src/test/ui/unique/unique-fn-arg-mut.rs b/src/test/ui/unique/unique-fn-arg-mut.rs index e8bb35e4eb..01510200b1 100644 --- a/src/test/ui/unique/unique-fn-arg-mut.rs +++ b/src/test/ui/unique/unique-fn-arg-mut.rs @@ -1,12 +1,11 @@ // run-pass -#![feature(box_syntax)] fn f(i: &mut Box) { - *i = box 200; + *i = Box::new(200); } pub fn main() { - let mut i = box 100; + let mut i = Box::new(100); f(&mut i); assert_eq!(*i, 200); } diff --git a/src/test/ui/unique/unique-fn-arg.rs b/src/test/ui/unique/unique-fn-arg.rs index 75f2a767f5..b4f3bc4b29 100644 --- a/src/test/ui/unique/unique-fn-arg.rs +++ b/src/test/ui/unique/unique-fn-arg.rs @@ -1,12 +1,11 @@ // run-pass -#![feature(box_syntax)] fn f(i: Box) { assert_eq!(*i, 100); } pub fn main() { - f(box 100); - let i = box 100; + f(Box::new(100)); + let i = Box::new(100); f(i); } diff --git a/src/test/ui/unique/unique-fn-ret.rs b/src/test/ui/unique/unique-fn-ret.rs index cd44cfa983..773a9bce1a 100644 --- a/src/test/ui/unique/unique-fn-ret.rs +++ b/src/test/ui/unique/unique-fn-ret.rs @@ -1,10 +1,9 @@ // run-pass -#![feature(box_syntax)] fn f() -> Box { - box 100 + Box::new(100) } pub fn main() { - assert_eq!(f(), box 100); + assert_eq!(f(), Box::new(100)); } diff --git a/src/test/ui/unique/unique-in-tag.rs b/src/test/ui/unique/unique-in-tag.rs index 8d97ebe659..6daa06fb12 100644 --- a/src/test/ui/unique/unique-in-tag.rs +++ b/src/test/ui/unique/unique-in-tag.rs @@ -2,12 +2,10 @@ #![allow(dead_code)] #![allow(non_camel_case_types)] -#![feature(box_syntax)] - fn test1() { enum bar { u(Box), w(isize), } - let x = bar::u(box 10); + let x = bar::u(Box::new(10)); assert!(match x { bar::u(a) => { println!("{}", a); diff --git a/src/test/ui/unique/unique-in-vec-copy.rs b/src/test/ui/unique/unique-in-vec-copy.rs index 8907a8b20a..ce52d15ef1 100644 --- a/src/test/ui/unique/unique-in-vec-copy.rs +++ b/src/test/ui/unique/unique-in-vec-copy.rs @@ -1,8 +1,7 @@ // run-pass -#![feature(box_syntax)] pub fn main() { - let mut a: Vec> = vec![box 10]; + let mut a: Vec> = vec![Box::new(10)]; let b = a.clone(); assert_eq!(*a[0], 10); diff --git a/src/test/ui/unique/unique-in-vec.rs b/src/test/ui/unique/unique-in-vec.rs index 528ea4fb87..1e8d05e3d2 100644 --- a/src/test/ui/unique/unique-in-vec.rs +++ b/src/test/ui/unique/unique-in-vec.rs @@ -1,7 +1,6 @@ // run-pass -#![feature(box_syntax)] pub fn main() { - let vect : Vec> = vec![box 100]; - assert_eq!(vect[0], box 100); + let vect : Vec> = vec![Box::new(100)]; + assert_eq!(vect[0], Box::new(100)); } diff --git a/src/test/ui/unique/unique-init.rs b/src/test/ui/unique/unique-init.rs index c8a150522f..d19605046e 100644 --- a/src/test/ui/unique/unique-init.rs +++ b/src/test/ui/unique/unique-init.rs @@ -1,8 +1,6 @@ // run-pass // pretty-expanded FIXME #23616 -#![feature(box_syntax)] - pub fn main() { - let _i: Box<_> = box 100; + let _i: Box<_> = Box::new(100); } diff --git a/src/test/ui/unique/unique-kinds.rs b/src/test/ui/unique/unique-kinds.rs index f369a1e2a1..f02d0b5076 100644 --- a/src/test/ui/unique/unique-kinds.rs +++ b/src/test/ui/unique/unique-kinds.rs @@ -1,5 +1,4 @@ // run-pass -#![feature(box_syntax)] use std::cmp::PartialEq; use std::fmt::Debug; @@ -14,11 +13,11 @@ fn sendable() { assert!(i != j); } - let i: Box<_> = box 100; - let j: Box<_> = box 100; + let i: Box<_> = Box::new(100); + let j: Box<_> = Box::new(100); f(i, j); - let i: Box<_> = box 100; - let j: Box<_> = box 101; + let i: Box<_> = Box::new(100); + let j: Box<_> = Box::new(101); g(i, j); } @@ -32,11 +31,11 @@ fn copyable() { assert!(i != j); } - let i: Box<_> = box 100; - let j: Box<_> = box 100; + let i: Box<_> = Box::new(100); + let j: Box<_> = Box::new(100); f(i, j); - let i: Box<_> = box 100; - let j: Box<_> = box 101; + let i: Box<_> = Box::new(100); + let j: Box<_> = Box::new(101); g(i, j); } @@ -50,11 +49,11 @@ fn noncopyable() { assert!(i != j); } - let i: Box<_> = box 100; - let j: Box<_> = box 100; + let i: Box<_> = Box::new(100); + let j: Box<_> = Box::new(100); f(i, j); - let i: Box<_> = box 100; - let j: Box<_> = box 101; + let i: Box<_> = Box::new(100); + let j: Box<_> = Box::new(101); g(i, j); } diff --git a/src/test/ui/unique/unique-log.rs b/src/test/ui/unique/unique-log.rs index 2797771770..0715d16628 100644 --- a/src/test/ui/unique/unique-log.rs +++ b/src/test/ui/unique/unique-log.rs @@ -1,7 +1,6 @@ // run-pass -#![feature(box_syntax)] pub fn main() { - let i: Box<_> = box 100; + let i: Box<_> = Box::new(100); println!("{}", i); } diff --git a/src/test/ui/unique/unique-move-drop.rs b/src/test/ui/unique/unique-move-drop.rs index e1ea58b39e..c0f5d8f905 100644 --- a/src/test/ui/unique/unique-move-drop.rs +++ b/src/test/ui/unique/unique-move-drop.rs @@ -1,11 +1,10 @@ // run-pass #![allow(unused_variables)] -#![feature(box_syntax)] pub fn main() { - let i: Box<_> = box 100; - let j: Box<_> = box 200; + let i: Box<_> = Box::new(100); + let j: Box<_> = Box::new(200); let j = i; assert_eq!(*j, 100); } diff --git a/src/test/ui/unique/unique-move-temp.rs b/src/test/ui/unique/unique-move-temp.rs index 4f5de50b72..103af8e1f1 100644 --- a/src/test/ui/unique/unique-move-temp.rs +++ b/src/test/ui/unique/unique-move-temp.rs @@ -1,9 +1,8 @@ // run-pass #![allow(unused_mut)] -#![feature(box_syntax)] pub fn main() { let mut i: Box<_>; - i = box 100; + i = Box::new(100); assert_eq!(*i, 100); } diff --git a/src/test/ui/unique/unique-move.rs b/src/test/ui/unique/unique-move.rs index 0f6bff1432..40a2718e4e 100644 --- a/src/test/ui/unique/unique-move.rs +++ b/src/test/ui/unique/unique-move.rs @@ -1,9 +1,8 @@ // run-pass #![allow(unused_mut)] -#![feature(box_syntax)] pub fn main() { - let i: Box<_> = box 100; + let i: Box<_> = Box::new(100); let mut j; j = i; assert_eq!(*j, 100); diff --git a/src/test/ui/unique/unique-mutable.rs b/src/test/ui/unique/unique-mutable.rs index 176cf33d48..0367c08099 100644 --- a/src/test/ui/unique/unique-mutable.rs +++ b/src/test/ui/unique/unique-mutable.rs @@ -1,8 +1,7 @@ // run-pass -#![feature(box_syntax)] pub fn main() { - let mut i: Box<_> = box 0; + let mut i: Box<_> = Box::new(0); *i = 1; assert_eq!(*i, 1); } diff --git a/src/test/ui/unique/unique-object-move.rs b/src/test/ui/unique/unique-object-move.rs index 84e8cdb32b..bb35a9b2d7 100644 --- a/src/test/ui/unique/unique-object-move.rs +++ b/src/test/ui/unique/unique-object-move.rs @@ -4,8 +4,6 @@ // pretty-expanded FIXME #23616 -#![feature(box_syntax)] - pub trait EventLoop { fn foo(&self) {} } pub struct UvEventLoop { @@ -15,6 +13,6 @@ pub struct UvEventLoop { impl EventLoop for UvEventLoop { } pub fn main() { - let loop_: Box = box UvEventLoop { uvio: 0 } as Box; + let loop_: Box = Box::new(UvEventLoop { uvio: 0 }) as Box; let _loop2_ = loop_; } diff --git a/src/test/ui/unique/unique-pat-2.rs b/src/test/ui/unique/unique-pat-2.rs index c18e029b25..9c73fd2204 100644 --- a/src/test/ui/unique/unique-pat-2.rs +++ b/src/test/ui/unique/unique-pat-2.rs @@ -4,15 +4,15 @@ #![allow(non_shorthand_field_patterns)] #![feature(box_patterns)] -#![feature(box_syntax)] struct Foo {a: isize, b: usize} enum bar { u(Box), w(isize), } pub fn main() { - assert!(match bar::u(box Foo{a: 10, b: 40}) { - bar::u(box Foo{a: a, b: b}) => { a + (b as isize) } - _ => { 66 } - } == 50); + let v = match bar::u(Box::new(Foo{ a: 10, b: 40 })) { + bar::u(box Foo{ a: a, b: b }) => { a + (b as isize) } + _ => { 66 } + }; + assert_eq!(v, 50); } diff --git a/src/test/ui/unique/unique-pat-3.rs b/src/test/ui/unique/unique-pat-3.rs index e17b5a3ddb..2e81f898d0 100644 --- a/src/test/ui/unique/unique-pat-3.rs +++ b/src/test/ui/unique/unique-pat-3.rs @@ -2,16 +2,15 @@ #![allow(dead_code)] #![allow(non_camel_case_types)] -#![feature(box_syntax)] - enum bar { u(Box), w(isize), } pub fn main() { - assert!(match bar::u(box 10) { - bar::u(a) => { - println!("{}", a); - *a - } - _ => { 66 } - } == 10); + let v = match bar::u(10.into()) { + bar::u(a) => { + println!("{}", a); + *a + } + _ => { 66 } + }; + assert_eq!(v, 10); } diff --git a/src/test/ui/unique/unique-pat.rs b/src/test/ui/unique/unique-pat.rs index b32195ac27..c2474d0e77 100644 --- a/src/test/ui/unique/unique-pat.rs +++ b/src/test/ui/unique/unique-pat.rs @@ -1,10 +1,9 @@ // run-pass #![feature(box_patterns)] -#![feature(box_syntax)] fn simple() { - match box true { + match Box::new(true) { box true => { } _ => { panic!(); } } diff --git a/src/test/ui/unique/unique-rec.rs b/src/test/ui/unique/unique-rec.rs index c8bddd246a..9f8ad9bb05 100644 --- a/src/test/ui/unique/unique-rec.rs +++ b/src/test/ui/unique/unique-rec.rs @@ -1,10 +1,9 @@ // run-pass -#![feature(box_syntax)] struct X { x: isize } pub fn main() { - let x: Box<_> = box X {x: 1}; + let x: Box<_> = Box::new(X {x: 1}); let bar = x; assert_eq!(bar.x, 1); } diff --git a/src/test/ui/unique/unique-send-2.rs b/src/test/ui/unique/unique-send-2.rs index 22f0e6c3a4..23ddd2cdca 100644 --- a/src/test/ui/unique/unique-send-2.rs +++ b/src/test/ui/unique/unique-send-2.rs @@ -2,13 +2,11 @@ #![allow(unused_must_use)] // ignore-emscripten no threads support -#![feature(box_syntax)] - use std::sync::mpsc::{channel, Sender}; use std::thread; fn child(tx: &Sender>, i: usize) { - tx.send(box i).unwrap(); + tx.send(Box::new(i)).unwrap(); } pub fn main() { diff --git a/src/test/ui/unique/unique-send.rs b/src/test/ui/unique/unique-send.rs index a5c7561b9a..431cc2be5d 100644 --- a/src/test/ui/unique/unique-send.rs +++ b/src/test/ui/unique/unique-send.rs @@ -1,11 +1,10 @@ // run-pass -#![feature(box_syntax)] use std::sync::mpsc::channel; pub fn main() { let (tx, rx) = channel::>(); - tx.send(box 100).unwrap(); + tx.send(Box::new(100)).unwrap(); let v = rx.recv().unwrap(); - assert_eq!(v, box 100); + assert_eq!(v, Box::new(100)); } diff --git a/src/test/ui/unique/unique-swap.rs b/src/test/ui/unique/unique-swap.rs index 33a6b3b3ed..4f33ff9a8a 100644 --- a/src/test/ui/unique/unique-swap.rs +++ b/src/test/ui/unique/unique-swap.rs @@ -1,12 +1,11 @@ // run-pass -#![feature(box_syntax)] use std::mem::swap; pub fn main() { - let mut i: Box<_> = box 100; - let mut j: Box<_> = box 200; + let mut i: Box<_> = Box::new(100); + let mut j: Box<_> = Box::new(200); swap(&mut i, &mut j); - assert_eq!(i, box 200); - assert_eq!(j, box 100); + assert_eq!(i, Box::new(200)); + assert_eq!(j, Box::new(100)); } diff --git a/src/test/ui/unop-move-semantics.stderr b/src/test/ui/unop-move-semantics.stderr index 95a0f4f5fa..199d5e3727 100644 --- a/src/test/ui/unop-move-semantics.stderr +++ b/src/test/ui/unop-move-semantics.stderr @@ -7,7 +7,7 @@ LL | !x; | -- `x` moved due to usage in operator LL | LL | x.clone(); - | ^ value borrowed here after move + | ^^^^^^^^^ value borrowed here after move | note: calling this operator moves the left-hand side --> $SRC_DIR/core/src/ops/bit.rs:LL:COL diff --git a/src/test/ui/unsafe/inline_asm.mir.stderr b/src/test/ui/unsafe/inline_asm.mir.stderr index 5d9828b559..865d5cc61c 100644 --- a/src/test/ui/unsafe/inline_asm.mir.stderr +++ b/src/test/ui/unsafe/inline_asm.mir.stderr @@ -2,7 +2,7 @@ error[E0133]: use of inline assembly is unsafe and requires unsafe function or b --> $DIR/inline_asm.rs:10:5 | LL | asm!("nop"); - | ^^^^^^^^^^^^ use of inline assembly + | ^^^^^^^^^^^ use of inline assembly | = note: inline assembly is entirely unchecked and can cause undefined behavior @@ -10,7 +10,7 @@ error[E0133]: use of inline assembly is unsafe and requires unsafe function or b --> $DIR/inline_asm.rs:11:5 | LL | llvm_asm!("nop"); - | ^^^^^^^^^^^^^^^^^ use of inline assembly + | ^^^^^^^^^^^^^^^^ use of inline assembly | = note: inline assembly is entirely unchecked and can cause undefined behavior = note: this error originates in the macro `llvm_asm` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/unsafe/inline_asm.thir.stderr b/src/test/ui/unsafe/inline_asm.thir.stderr index 5d9828b559..865d5cc61c 100644 --- a/src/test/ui/unsafe/inline_asm.thir.stderr +++ b/src/test/ui/unsafe/inline_asm.thir.stderr @@ -2,7 +2,7 @@ error[E0133]: use of inline assembly is unsafe and requires unsafe function or b --> $DIR/inline_asm.rs:10:5 | LL | asm!("nop"); - | ^^^^^^^^^^^^ use of inline assembly + | ^^^^^^^^^^^ use of inline assembly | = note: inline assembly is entirely unchecked and can cause undefined behavior @@ -10,7 +10,7 @@ error[E0133]: use of inline assembly is unsafe and requires unsafe function or b --> $DIR/inline_asm.rs:11:5 | LL | llvm_asm!("nop"); - | ^^^^^^^^^^^^^^^^^ use of inline assembly + | ^^^^^^^^^^^^^^^^ use of inline assembly | = note: inline assembly is entirely unchecked and can cause undefined behavior = note: this error originates in the macro `llvm_asm` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/issues/issue-45107-unnecessary-unsafe-in-closure.mir.stderr b/src/test/ui/unsafe/issue-45107-unnecessary-unsafe-in-closure.mir.stderr similarity index 100% rename from src/test/ui/issues/issue-45107-unnecessary-unsafe-in-closure.mir.stderr rename to src/test/ui/unsafe/issue-45107-unnecessary-unsafe-in-closure.mir.stderr diff --git a/src/test/ui/issues/issue-45107-unnecessary-unsafe-in-closure.rs b/src/test/ui/unsafe/issue-45107-unnecessary-unsafe-in-closure.rs similarity index 100% rename from src/test/ui/issues/issue-45107-unnecessary-unsafe-in-closure.rs rename to src/test/ui/unsafe/issue-45107-unnecessary-unsafe-in-closure.rs diff --git a/src/test/ui/issues/issue-45107-unnecessary-unsafe-in-closure.thir.stderr b/src/test/ui/unsafe/issue-45107-unnecessary-unsafe-in-closure.thir.stderr similarity index 100% rename from src/test/ui/issues/issue-45107-unnecessary-unsafe-in-closure.thir.stderr rename to src/test/ui/unsafe/issue-45107-unnecessary-unsafe-in-closure.thir.stderr diff --git a/src/test/ui/unsized-locals/unsized-exprs.stderr b/src/test/ui/unsized-locals/unsized-exprs.stderr index a7f57e3fd1..6686e55130 100644 --- a/src/test/ui/unsized-locals/unsized-exprs.stderr +++ b/src/test/ui/unsized-locals/unsized-exprs.stderr @@ -12,9 +12,11 @@ error[E0277]: the size for values of type `[u8]` cannot be known at compilation --> $DIR/unsized-exprs.rs:24:22 | LL | udrop::>(A { 0: *foo() }); - | ^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | ---------------- ^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | | + | required by a bound introduced by this call | - = help: within `A<[u8]>`, the trait `Sized` is not implemented for `[u8]` + = help: 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/unsized/unsized2.rs b/src/test/ui/unsized/unsized2.rs index be4406399f..bbeb00d5fe 100644 --- a/src/test/ui/unsized/unsized2.rs +++ b/src/test/ui/unsized/unsized2.rs @@ -4,7 +4,6 @@ #![allow(dead_code)] #![allow(unused_variables)] #![allow(unused_imports)] -#![feature(box_syntax)] // Test sized-ness checking in substitution. @@ -36,7 +35,7 @@ trait T2 { struct S; impl T2 for S { fn f() -> Box { - box S + Box::new(S) } } fn f5(x: &X) { @@ -51,7 +50,7 @@ trait T3 { } impl T3 for S { fn f() -> Box { - box S + Box::new(S) } } fn f7(x: &X) { diff --git a/src/test/ui/unsized/unsized3-rpass.rs b/src/test/ui/unsized/unsized3-rpass.rs index c5c5ed26c7..4d5e89575b 100644 --- a/src/test/ui/unsized/unsized3-rpass.rs +++ b/src/test/ui/unsized/unsized3-rpass.rs @@ -2,7 +2,7 @@ // Test structs with always-unsized fields. #![allow(warnings)] -#![feature(box_syntax, unsize, ptr_metadata)] +#![feature(unsize, ptr_metadata)] use std::mem; use std::ptr; @@ -58,7 +58,7 @@ pub fn main() { f: [T; 3], } - let data: Box> = box Foo_ { f: [1, 2, 3] }; + let data: Box> = Box::new(Foo_ { f: [1, 2, 3] }); let x: &Foo = mem::transmute(slice::from_raw_parts(&*data, 3)); assert_eq!(x.f.len(), 3); assert_eq!(x.f[0], 1); @@ -69,7 +69,7 @@ pub fn main() { } let data: Box<_> = - box Baz_ { f1: 42, f2: ['a' as u8, 'b' as u8, 'c' as u8, 'd' as u8, 'e' as u8] }; + Box::new(Baz_ { f1: 42, f2: ['a' as u8, 'b' as u8, 'c' as u8, 'd' as u8, 'e' as u8] }); let x: &Baz = mem::transmute(slice::from_raw_parts(&*data, 5)); assert_eq!(x.f1, 42); let chs: Vec = x.f2.chars().collect(); @@ -84,9 +84,9 @@ pub fn main() { f: St, } - let obj: Box = box St { f: 42 }; + let obj: Box = Box::new(St { f: 42 }); let obj: &Tr = &*obj; - let data: Box<_> = box Qux_ { f: St { f: 234 } }; + let data: Box<_> = Box::new(Qux_ { f: St { f: 234 } }); let x: &Qux = &*ptr::from_raw_parts::((&*data as *const _).cast(), ptr::metadata(obj)); assert_eq!(x.f.foo(), 234); } diff --git a/src/test/ui/unsized/unsized3.rs b/src/test/ui/unsized/unsized3.rs index f5b5d02593..39b6583bc4 100644 --- a/src/test/ui/unsized/unsized3.rs +++ b/src/test/ui/unsized/unsized3.rs @@ -44,8 +44,6 @@ fn f9(x1: Box>) { fn f10(x1: Box>) { f5(&(32, *x1)); //~^ ERROR the size for values of type - //~| ERROR the size for values of type } -pub fn main() { -} +pub fn main() {} diff --git a/src/test/ui/unsized/unsized3.stderr b/src/test/ui/unsized/unsized3.stderr index f7bb6c9c78..ae89f2f997 100644 --- a/src/test/ui/unsized/unsized3.stderr +++ b/src/test/ui/unsized/unsized3.stderr @@ -4,7 +4,9 @@ error[E0277]: the size for values of type `X` cannot be known at compilation tim LL | fn f1(x: &X) { | - this type parameter needs to be `std::marker::Sized` LL | f2::(x); - | ^ doesn't have a size known at compile-time + | ------- ^ doesn't have a size known at compile-time + | | + | required by a bound introduced by this call | note: required by a bound in `f2` --> $DIR/unsized3.rs:10:7 @@ -27,7 +29,9 @@ error[E0277]: the size for values of type `X` cannot be known at compilation tim LL | fn f3(x: &X) { | - this type parameter needs to be `std::marker::Sized` LL | f4::(x); - | ^ doesn't have a size known at compile-time + | ------- ^ doesn't have a size known at compile-time + | | + | required by a bound introduced by this call | note: required by a bound in `f4` --> $DIR/unsized3.rs:21:7 @@ -50,7 +54,9 @@ error[E0277]: the size for values of type `X` cannot be known at compilation tim LL | fn f8(x1: &S, x2: &S) { | - this type parameter needs to be `std::marker::Sized` LL | f5(x1); - | ^^ doesn't have a size known at compile-time + | -- ^^ doesn't have a size known at compile-time + | | + | required by a bound introduced by this call | note: required because it appears within the type `S` --> $DIR/unsized3.rs:28:8 @@ -78,7 +84,9 @@ error[E0277]: the size for values of type `X` cannot be known at compilation tim LL | fn f9(x1: Box>) { | - this type parameter needs to be `std::marker::Sized` LL | f5(&(*x1, 34)); - | ^^^^^^^^^^ doesn't have a size known at compile-time + | -- ^^^^^^^^^^ doesn't have a size known at compile-time + | | + | required by a bound introduced by this call | note: required because it appears within the type `S` --> $DIR/unsized3.rs:28:8 @@ -93,12 +101,14 @@ LL + fn f9(x1: Box>) { | error[E0277]: the size for values of type `X` cannot be known at compilation time - --> $DIR/unsized3.rs:45:9 + --> $DIR/unsized3.rs:45:8 | LL | fn f10(x1: Box>) { | - this type parameter needs to be `std::marker::Sized` LL | f5(&(32, *x1)); - | ^^^^^^^^^ doesn't have a size known at compile-time + | -- ^^^^^^^^^^ doesn't have a size known at compile-time + | | + | required by a bound introduced by this call | note: required because it appears within the type `S` --> $DIR/unsized3.rs:28:8 @@ -113,35 +123,6 @@ LL - fn f10(x1: Box>) { LL + fn f10(x1: Box>) { | -error[E0277]: the size for values of type `X` cannot be known at compilation time - --> $DIR/unsized3.rs:45:8 - | -LL | fn f10(x1: Box>) { - | - this type parameter needs to be `std::marker::Sized` -LL | f5(&(32, *x1)); - | ^^^^^^^^^^ doesn't have a size known at compile-time - | -note: required because it appears within the type `S` - --> $DIR/unsized3.rs:28:8 - | -LL | struct S { - | ^ - = note: required because it appears within the type `({integer}, S)` -note: required by a bound in `f5` - --> $DIR/unsized3.rs:24:7 - | -LL | fn f5(x: &Y) {} - | ^ required by this bound in `f5` -help: consider removing the `?Sized` bound to make the type parameter `Sized` - | -LL - fn f10(x1: Box>) { -LL + fn f10(x1: Box>) { - | -help: consider relaxing the implicit `Sized` restriction - | -LL | fn f5(x: &Y) {} - | ++++++++ - -error: aborting due to 6 previous errors +error: aborting due to 5 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/unused-move-capture.rs b/src/test/ui/unused-move-capture.rs index e9d4684736..efaf10da4a 100644 --- a/src/test/ui/unused-move-capture.rs +++ b/src/test/ui/unused-move-capture.rs @@ -1,10 +1,8 @@ // run-pass // pretty-expanded FIXME #23616 -#![feature(box_syntax)] - pub fn main() { - let _x: Box<_> = box 1; + let _x: Box<_> = Box::new(1); let lam_move = || {}; lam_move(); } diff --git a/src/test/ui/unused-move.rs b/src/test/ui/unused-move.rs index 37aee22f85..697434d47e 100644 --- a/src/test/ui/unused-move.rs +++ b/src/test/ui/unused-move.rs @@ -6,10 +6,8 @@ // pretty-expanded FIXME #23616 #![allow(path_statements)] -#![feature(box_syntax)] -pub fn main() -{ - let y: Box<_> = box 1; +pub fn main() { + let y: Box<_> = Box::new(1); y; } diff --git a/src/test/ui/unwind-unique.rs b/src/test/ui/unwind-unique.rs index ea3089e747..7ca53b664a 100644 --- a/src/test/ui/unwind-unique.rs +++ b/src/test/ui/unwind-unique.rs @@ -1,12 +1,10 @@ // run-pass // ignore-emscripten no threads support -#![feature(box_syntax)] - use std::thread; fn f() { - let _a: Box<_> = box 0; + let _a: Box<_> = Box::new(0); panic!(); } diff --git a/src/test/ui/use/use-after-move-implicity-coerced-object.rs b/src/test/ui/use/use-after-move-implicity-coerced-object.rs index 76487ef1c1..47fbb5bf1c 100644 --- a/src/test/ui/use/use-after-move-implicity-coerced-object.rs +++ b/src/test/ui/use/use-after-move-implicity-coerced-object.rs @@ -1,5 +1,3 @@ -#![feature(box_syntax)] - use std::fmt; struct Number { @@ -22,9 +20,11 @@ impl List { } fn main() { - let n: Box<_> = box Number { n: 42 }; - let mut l: Box<_> = box List { list: Vec::new() }; + + let n: Box<_> = Number { n: 42 }.into(); + let mut l: Box<_> = List { list: Vec::new() }.into(); l.push(n); + let x = n.to_string(); //~^ ERROR: borrow of moved value: `n` } diff --git a/src/test/ui/use/use-after-move-implicity-coerced-object.stderr b/src/test/ui/use/use-after-move-implicity-coerced-object.stderr index b3266562d1..0ad6d6c7c0 100644 --- a/src/test/ui/use/use-after-move-implicity-coerced-object.stderr +++ b/src/test/ui/use/use-after-move-implicity-coerced-object.stderr @@ -1,13 +1,14 @@ error[E0382]: borrow of moved value: `n` --> $DIR/use-after-move-implicity-coerced-object.rs:28:13 | -LL | let n: Box<_> = box Number { n: 42 }; +LL | let n: Box<_> = Number { n: 42 }.into(); | - move occurs because `n` has type `Box`, which does not implement the `Copy` trait -LL | let mut l: Box<_> = box List { list: Vec::new() }; +LL | let mut l: Box<_> = List { list: Vec::new() }.into(); LL | l.push(n); | - value moved here +LL | LL | let x = n.to_string(); - | ^ value borrowed here after move + | ^^^^^^^^^^^^^ value borrowed here after move error: aborting due to previous error diff --git a/src/test/ui/use/use-after-move-self.rs b/src/test/ui/use/use-after-move-self.rs index a6f6c45573..f7a3c0ecce 100644 --- a/src/test/ui/use/use-after-move-self.rs +++ b/src/test/ui/use/use-after-move-self.rs @@ -1,9 +1,9 @@ -#![feature(box_syntax)] - struct S { x: Box, } + + impl S { pub fn foo(self) -> isize { self.bar(); @@ -14,6 +14,6 @@ impl S { } fn main() { - let x = S { x: box 1 }; + let x = S { x: 1.into() }; println!("{}", x.foo()); } diff --git a/src/test/ui/use/use-from-trait-xc.stderr b/src/test/ui/use/use-from-trait-xc.stderr index 37b4e61c80..14523afbda 100644 --- a/src/test/ui/use/use-from-trait-xc.stderr +++ b/src/test/ui/use/use-from-trait-xc.stderr @@ -38,7 +38,7 @@ error[E0432]: unresolved import `use_from_trait_xc::Baz::new` --> $DIR/use-from-trait-xc.rs:23:5 | LL | use use_from_trait_xc::Baz::new as baznew; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no `new` in `Baz` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no `new` in `sub::Baz` error[E0603]: struct `Foo` is private --> $DIR/use-from-trait-xc.rs:14:24 diff --git a/src/test/ui/variance/variance-associated-types2.nll.stderr b/src/test/ui/variance/variance-associated-types2.nll.stderr index 27d1e18441..35871c1236 100644 --- a/src/test/ui/variance/variance-associated-types2.nll.stderr +++ b/src/test/ui/variance/variance-associated-types2.nll.stderr @@ -5,8 +5,6 @@ LL | fn take<'a>(_: &'a u32) { | -- lifetime `'a` defined here LL | let _: Box> = make(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static` - | - = help: consider replacing `'a` with `'static` error: aborting due to previous error diff --git a/src/test/ui/variance/variance-associated-types2.stderr b/src/test/ui/variance/variance-associated-types2.stderr index 52cdd6493b..af4f2a7c2a 100644 --- a/src/test/ui/variance/variance-associated-types2.stderr +++ b/src/test/ui/variance/variance-associated-types2.stderr @@ -6,7 +6,7 @@ LL | let _: Box> = make(); | = note: expected trait object `dyn Foo` found trait object `dyn Foo` -note: the lifetime `'a` as defined on the function body at 12:9... +note: the lifetime `'a` as defined here... --> $DIR/variance-associated-types2.rs:12:9 | LL | fn take<'a>(_: &'a u32) { diff --git a/src/test/ui/variance/variance-btree-invariant-types.nll.stderr b/src/test/ui/variance/variance-btree-invariant-types.nll.stderr index 4b653238aa..1f06949c03 100644 --- a/src/test/ui/variance/variance-btree-invariant-types.nll.stderr +++ b/src/test/ui/variance/variance-btree-invariant-types.nll.stderr @@ -5,8 +5,6 @@ LL | fn iter_cov_key<'a, 'new>(v: IterMut<'a, &'static (), ()>) -> IterMut<'a, & | ---- lifetime `'new` defined here LL | v | ^ returning this value requires that `'new` must outlive `'static` - | - = help: consider replacing `'new` with `'static` error: lifetime may not live long enough --> $DIR/variance-btree-invariant-types.rs:7:5 @@ -15,8 +13,6 @@ LL | fn iter_cov_val<'a, 'new>(v: IterMut<'a, (), &'static ()>) -> IterMut<'a, ( | ---- lifetime `'new` defined here LL | v | ^ returning this value requires that `'new` must outlive `'static` - | - = help: consider replacing `'new` with `'static` error: lifetime may not live long enough --> $DIR/variance-btree-invariant-types.rs:10:5 @@ -25,8 +21,6 @@ LL | fn iter_contra_key<'a, 'new>(v: IterMut<'a, &'new (), ()>) -> IterMut<'a, & | ---- lifetime `'new` defined here LL | v | ^ returning this value requires that `'new` must outlive `'static` - | - = help: consider replacing `'new` with `'static` error: lifetime may not live long enough --> $DIR/variance-btree-invariant-types.rs:13:5 @@ -35,8 +29,6 @@ LL | fn iter_contra_val<'a, 'new>(v: IterMut<'a, (), &'new ()>) -> IterMut<'a, ( | ---- lifetime `'new` defined here LL | v | ^ returning this value requires that `'new` must outlive `'static` - | - = help: consider replacing `'new` with `'static` error: lifetime may not live long enough --> $DIR/variance-btree-invariant-types.rs:17:5 @@ -45,8 +37,6 @@ LL | fn range_cov_key<'a, 'new>(v: RangeMut<'a, &'static (), ()>) -> RangeMut<'a | ---- lifetime `'new` defined here LL | v | ^ returning this value requires that `'new` must outlive `'static` - | - = help: consider replacing `'new` with `'static` error: lifetime may not live long enough --> $DIR/variance-btree-invariant-types.rs:20:5 @@ -55,8 +45,6 @@ LL | fn range_cov_val<'a, 'new>(v: RangeMut<'a, (), &'static ()>) -> RangeMut<'a | ---- lifetime `'new` defined here LL | v | ^ returning this value requires that `'new` must outlive `'static` - | - = help: consider replacing `'new` with `'static` error: lifetime may not live long enough --> $DIR/variance-btree-invariant-types.rs:23:5 @@ -65,8 +53,6 @@ LL | fn range_contra_key<'a, 'new>(v: RangeMut<'a, &'new (), ()>) -> RangeMut<'a | ---- lifetime `'new` defined here LL | v | ^ returning this value requires that `'new` must outlive `'static` - | - = help: consider replacing `'new` with `'static` error: lifetime may not live long enough --> $DIR/variance-btree-invariant-types.rs:26:5 @@ -75,8 +61,6 @@ LL | fn range_contra_val<'a, 'new>(v: RangeMut<'a, (), &'new ()>) -> RangeMut<'a | ---- lifetime `'new` defined here LL | v | ^ returning this value requires that `'new` must outlive `'static` - | - = help: consider replacing `'new` with `'static` error: lifetime may not live long enough --> $DIR/variance-btree-invariant-types.rs:31:5 @@ -86,8 +70,6 @@ LL | fn occ_cov_key<'a, 'new>(v: OccupiedEntry<'a, &'static (), ()>) LL | -> OccupiedEntry<'a, &'new (), ()> { LL | v | ^ returning this value requires that `'new` must outlive `'static` - | - = help: consider replacing `'new` with `'static` error: lifetime may not live long enough --> $DIR/variance-btree-invariant-types.rs:35:5 @@ -97,8 +79,6 @@ LL | fn occ_cov_val<'a, 'new>(v: OccupiedEntry<'a, (), &'static ()>) LL | -> OccupiedEntry<'a, (), &'new ()> { LL | v | ^ returning this value requires that `'new` must outlive `'static` - | - = help: consider replacing `'new` with `'static` error: lifetime may not live long enough --> $DIR/variance-btree-invariant-types.rs:39:5 @@ -108,8 +88,6 @@ LL | fn occ_contra_key<'a, 'new>(v: OccupiedEntry<'a, &'new (), ()>) LL | -> OccupiedEntry<'a, &'static (), ()> { LL | v | ^ returning this value requires that `'new` must outlive `'static` - | - = help: consider replacing `'new` with `'static` error: lifetime may not live long enough --> $DIR/variance-btree-invariant-types.rs:43:5 @@ -119,8 +97,6 @@ LL | fn occ_contra_val<'a, 'new>(v: OccupiedEntry<'a, (), &'new ()>) LL | -> OccupiedEntry<'a, (), &'static ()> { LL | v | ^ returning this value requires that `'new` must outlive `'static` - | - = help: consider replacing `'new` with `'static` error: lifetime may not live long enough --> $DIR/variance-btree-invariant-types.rs:48:5 @@ -130,8 +106,6 @@ LL | fn vac_cov_key<'a, 'new>(v: VacantEntry<'a, &'static (), ()>) LL | -> VacantEntry<'a, &'new (), ()> { LL | v | ^ returning this value requires that `'new` must outlive `'static` - | - = help: consider replacing `'new` with `'static` error: lifetime may not live long enough --> $DIR/variance-btree-invariant-types.rs:52:5 @@ -141,8 +115,6 @@ LL | fn vac_cov_val<'a, 'new>(v: VacantEntry<'a, (), &'static ()>) LL | -> VacantEntry<'a, (), &'new ()> { LL | v | ^ returning this value requires that `'new` must outlive `'static` - | - = help: consider replacing `'new` with `'static` error: lifetime may not live long enough --> $DIR/variance-btree-invariant-types.rs:56:5 @@ -152,8 +124,6 @@ LL | fn vac_contra_key<'a, 'new>(v: VacantEntry<'a, &'new (), ()>) LL | -> VacantEntry<'a, &'static (), ()> { LL | v | ^ returning this value requires that `'new` must outlive `'static` - | - = help: consider replacing `'new` with `'static` error: lifetime may not live long enough --> $DIR/variance-btree-invariant-types.rs:60:5 @@ -163,8 +133,6 @@ LL | fn vac_contra_val<'a, 'new>(v: VacantEntry<'a, (), &'new ()>) LL | -> VacantEntry<'a, (), &'static ()> { LL | v | ^ returning this value requires that `'new` must outlive `'static` - | - = help: consider replacing `'new` with `'static` error: aborting due to 16 previous errors diff --git a/src/test/ui/variance/variance-btree-invariant-types.stderr b/src/test/ui/variance/variance-btree-invariant-types.stderr index ba47bdff28..df519e2564 100644 --- a/src/test/ui/variance/variance-btree-invariant-types.stderr +++ b/src/test/ui/variance/variance-btree-invariant-types.stderr @@ -6,7 +6,7 @@ LL | v | = note: expected struct `std::collections::btree_map::IterMut<'_, &'new (), _>` found struct `std::collections::btree_map::IterMut<'_, &'static (), _>` -note: the lifetime `'new` as defined on the function body at 3:21... +note: the lifetime `'new` as defined here... --> $DIR/variance-btree-invariant-types.rs:3:21 | LL | fn iter_cov_key<'a, 'new>(v: IterMut<'a, &'static (), ()>) -> IterMut<'a, &'new (), ()> { @@ -21,7 +21,7 @@ LL | v | = note: expected struct `std::collections::btree_map::IterMut<'_, _, &'new ()>` found struct `std::collections::btree_map::IterMut<'_, _, &'static ()>` -note: the lifetime `'new` as defined on the function body at 6:21... +note: the lifetime `'new` as defined here... --> $DIR/variance-btree-invariant-types.rs:6:21 | LL | fn iter_cov_val<'a, 'new>(v: IterMut<'a, (), &'static ()>) -> IterMut<'a, (), &'new ()> { @@ -36,7 +36,7 @@ LL | v | = note: expected struct `std::collections::btree_map::IterMut<'_, &'static (), _>` found struct `std::collections::btree_map::IterMut<'_, &'new (), _>` -note: the lifetime `'new` as defined on the function body at 9:24... +note: the lifetime `'new` as defined here... --> $DIR/variance-btree-invariant-types.rs:9:24 | LL | fn iter_contra_key<'a, 'new>(v: IterMut<'a, &'new (), ()>) -> IterMut<'a, &'static (), ()> { @@ -51,7 +51,7 @@ LL | v | = note: expected struct `std::collections::btree_map::IterMut<'_, _, &'static ()>` found struct `std::collections::btree_map::IterMut<'_, _, &'new ()>` -note: the lifetime `'new` as defined on the function body at 12:24... +note: the lifetime `'new` as defined here... --> $DIR/variance-btree-invariant-types.rs:12:24 | LL | fn iter_contra_val<'a, 'new>(v: IterMut<'a, (), &'new ()>) -> IterMut<'a, (), &'static ()> { @@ -66,7 +66,7 @@ LL | v | = note: expected struct `RangeMut<'_, &'new (), _>` found struct `RangeMut<'_, &'static (), _>` -note: the lifetime `'new` as defined on the function body at 16:22... +note: the lifetime `'new` as defined here... --> $DIR/variance-btree-invariant-types.rs:16:22 | LL | fn range_cov_key<'a, 'new>(v: RangeMut<'a, &'static (), ()>) -> RangeMut<'a, &'new (), ()> { @@ -81,7 +81,7 @@ LL | v | = note: expected struct `RangeMut<'_, _, &'new ()>` found struct `RangeMut<'_, _, &'static ()>` -note: the lifetime `'new` as defined on the function body at 19:22... +note: the lifetime `'new` as defined here... --> $DIR/variance-btree-invariant-types.rs:19:22 | LL | fn range_cov_val<'a, 'new>(v: RangeMut<'a, (), &'static ()>) -> RangeMut<'a, (), &'new ()> { @@ -96,7 +96,7 @@ LL | v | = note: expected struct `RangeMut<'_, &'static (), _>` found struct `RangeMut<'_, &'new (), _>` -note: the lifetime `'new` as defined on the function body at 22:25... +note: the lifetime `'new` as defined here... --> $DIR/variance-btree-invariant-types.rs:22:25 | LL | fn range_contra_key<'a, 'new>(v: RangeMut<'a, &'new (), ()>) -> RangeMut<'a, &'static (), ()> { @@ -111,7 +111,7 @@ LL | v | = note: expected struct `RangeMut<'_, _, &'static ()>` found struct `RangeMut<'_, _, &'new ()>` -note: the lifetime `'new` as defined on the function body at 25:25... +note: the lifetime `'new` as defined here... --> $DIR/variance-btree-invariant-types.rs:25:25 | LL | fn range_contra_val<'a, 'new>(v: RangeMut<'a, (), &'new ()>) -> RangeMut<'a, (), &'static ()> { @@ -126,7 +126,7 @@ LL | v | = note: expected struct `std::collections::btree_map::OccupiedEntry<'_, &'new (), _>` found struct `std::collections::btree_map::OccupiedEntry<'_, &'static (), _>` -note: the lifetime `'new` as defined on the function body at 29:20... +note: the lifetime `'new` as defined here... --> $DIR/variance-btree-invariant-types.rs:29:20 | LL | fn occ_cov_key<'a, 'new>(v: OccupiedEntry<'a, &'static (), ()>) @@ -141,7 +141,7 @@ LL | v | = note: expected struct `std::collections::btree_map::OccupiedEntry<'_, _, &'new ()>` found struct `std::collections::btree_map::OccupiedEntry<'_, _, &'static ()>` -note: the lifetime `'new` as defined on the function body at 33:20... +note: the lifetime `'new` as defined here... --> $DIR/variance-btree-invariant-types.rs:33:20 | LL | fn occ_cov_val<'a, 'new>(v: OccupiedEntry<'a, (), &'static ()>) @@ -156,7 +156,7 @@ LL | v | = note: expected struct `std::collections::btree_map::OccupiedEntry<'_, &'static (), _>` found struct `std::collections::btree_map::OccupiedEntry<'_, &'new (), _>` -note: the lifetime `'new` as defined on the function body at 37:23... +note: the lifetime `'new` as defined here... --> $DIR/variance-btree-invariant-types.rs:37:23 | LL | fn occ_contra_key<'a, 'new>(v: OccupiedEntry<'a, &'new (), ()>) @@ -171,7 +171,7 @@ LL | v | = note: expected struct `std::collections::btree_map::OccupiedEntry<'_, _, &'static ()>` found struct `std::collections::btree_map::OccupiedEntry<'_, _, &'new ()>` -note: the lifetime `'new` as defined on the function body at 41:23... +note: the lifetime `'new` as defined here... --> $DIR/variance-btree-invariant-types.rs:41:23 | LL | fn occ_contra_val<'a, 'new>(v: OccupiedEntry<'a, (), &'new ()>) @@ -186,7 +186,7 @@ LL | v | = note: expected struct `std::collections::btree_map::VacantEntry<'_, &'new (), _>` found struct `std::collections::btree_map::VacantEntry<'_, &'static (), _>` -note: the lifetime `'new` as defined on the function body at 46:20... +note: the lifetime `'new` as defined here... --> $DIR/variance-btree-invariant-types.rs:46:20 | LL | fn vac_cov_key<'a, 'new>(v: VacantEntry<'a, &'static (), ()>) @@ -201,7 +201,7 @@ LL | v | = note: expected struct `std::collections::btree_map::VacantEntry<'_, _, &'new ()>` found struct `std::collections::btree_map::VacantEntry<'_, _, &'static ()>` -note: the lifetime `'new` as defined on the function body at 50:20... +note: the lifetime `'new` as defined here... --> $DIR/variance-btree-invariant-types.rs:50:20 | LL | fn vac_cov_val<'a, 'new>(v: VacantEntry<'a, (), &'static ()>) @@ -216,7 +216,7 @@ LL | v | = note: expected struct `std::collections::btree_map::VacantEntry<'_, &'static (), _>` found struct `std::collections::btree_map::VacantEntry<'_, &'new (), _>` -note: the lifetime `'new` as defined on the function body at 54:23... +note: the lifetime `'new` as defined here... --> $DIR/variance-btree-invariant-types.rs:54:23 | LL | fn vac_contra_key<'a, 'new>(v: VacantEntry<'a, &'new (), ()>) @@ -231,7 +231,7 @@ LL | v | = note: expected struct `std::collections::btree_map::VacantEntry<'_, _, &'static ()>` found struct `std::collections::btree_map::VacantEntry<'_, _, &'new ()>` -note: the lifetime `'new` as defined on the function body at 58:23... +note: the lifetime `'new` as defined here... --> $DIR/variance-btree-invariant-types.rs:58:23 | LL | fn vac_contra_val<'a, 'new>(v: VacantEntry<'a, (), &'new ()>) diff --git a/src/test/ui/variance/variance-contravariant-arg-object.stderr b/src/test/ui/variance/variance-contravariant-arg-object.stderr index a512a60aa4..16583fa793 100644 --- a/src/test/ui/variance/variance-contravariant-arg-object.stderr +++ b/src/test/ui/variance/variance-contravariant-arg-object.stderr @@ -6,12 +6,12 @@ LL | v | = note: expected trait object `dyn Get<&'min i32>` found trait object `dyn Get<&'max i32>` -note: the lifetime `'min` as defined on the function body at 10:21... +note: the lifetime `'min` as defined here... --> $DIR/variance-contravariant-arg-object.rs:10:21 | LL | fn get_min_from_max<'min, 'max>(v: Box>) | ^^^^ -note: ...does not necessarily outlive the lifetime `'max` as defined on the function body at 10:27 +note: ...does not necessarily outlive the lifetime `'max` as defined here --> $DIR/variance-contravariant-arg-object.rs:10:27 | LL | fn get_min_from_max<'min, 'max>(v: Box>) @@ -25,12 +25,12 @@ LL | v | = note: expected trait object `dyn Get<&'max i32>` found trait object `dyn Get<&'min i32>` -note: the lifetime `'min` as defined on the function body at 17:21... +note: the lifetime `'min` as defined here... --> $DIR/variance-contravariant-arg-object.rs:17:21 | LL | fn get_max_from_min<'min, 'max, G>(v: Box>) | ^^^^ -note: ...does not necessarily outlive the lifetime `'max` as defined on the function body at 17:27 +note: ...does not necessarily outlive the lifetime `'max` as defined here --> $DIR/variance-contravariant-arg-object.rs:17:27 | LL | fn get_max_from_min<'min, 'max, G>(v: Box>) diff --git a/src/test/ui/variance/variance-contravariant-arg-trait-match.stderr b/src/test/ui/variance/variance-contravariant-arg-trait-match.stderr index 1752b3b36a..370e57f73d 100644 --- a/src/test/ui/variance/variance-contravariant-arg-trait-match.stderr +++ b/src/test/ui/variance/variance-contravariant-arg-trait-match.stderr @@ -6,12 +6,12 @@ LL | impls_get::() | = note: expected type `Get<&'min i32>` found type `Get<&'max i32>` -note: the lifetime `'min` as defined on the function body at 10:21... +note: the lifetime `'min` as defined here... --> $DIR/variance-contravariant-arg-trait-match.rs:10:21 | LL | fn get_min_from_max<'min, 'max, G>() | ^^^^ -note: ...does not necessarily outlive the lifetime `'max` as defined on the function body at 10:27 +note: ...does not necessarily outlive the lifetime `'max` as defined here --> $DIR/variance-contravariant-arg-trait-match.rs:10:27 | LL | fn get_min_from_max<'min, 'max, G>() @@ -25,12 +25,12 @@ LL | impls_get::() | = note: expected type `Get<&'max i32>` found type `Get<&'min i32>` -note: the lifetime `'min` as defined on the function body at 16:21... +note: the lifetime `'min` as defined here... --> $DIR/variance-contravariant-arg-trait-match.rs:16:21 | LL | fn get_max_from_min<'min, 'max, G>() | ^^^^ -note: ...does not necessarily outlive the lifetime `'max` as defined on the function body at 16:27 +note: ...does not necessarily outlive the lifetime `'max` as defined here --> $DIR/variance-contravariant-arg-trait-match.rs:16:27 | LL | fn get_max_from_min<'min, 'max, G>() diff --git a/src/test/ui/variance/variance-contravariant-self-trait-match.stderr b/src/test/ui/variance/variance-contravariant-self-trait-match.stderr index e35aec4c0c..ab14faaa50 100644 --- a/src/test/ui/variance/variance-contravariant-self-trait-match.stderr +++ b/src/test/ui/variance/variance-contravariant-self-trait-match.stderr @@ -4,14 +4,14 @@ error[E0308]: mismatched types LL | impls_get::<&'min G>(); | ^^^^^^^^^^^^^^^^^^^^ lifetime mismatch | - = note: expected type `Get` - found type `Get` -note: the lifetime `'min` as defined on the function body at 10:21... + = note: expected type `<&'min G as Get>` + found type `<&'max G as Get>` +note: the lifetime `'min` as defined here... --> $DIR/variance-contravariant-self-trait-match.rs:10:21 | LL | fn get_min_from_max<'min, 'max, G>() | ^^^^ -note: ...does not necessarily outlive the lifetime `'max` as defined on the function body at 10:27 +note: ...does not necessarily outlive the lifetime `'max` as defined here --> $DIR/variance-contravariant-self-trait-match.rs:10:27 | LL | fn get_min_from_max<'min, 'max, G>() @@ -23,14 +23,14 @@ error[E0308]: mismatched types LL | impls_get::<&'max G>(); | ^^^^^^^^^^^^^^^^^^^^ lifetime mismatch | - = note: expected type `Get` - found type `Get` -note: the lifetime `'min` as defined on the function body at 16:21... + = note: expected type `<&'max G as Get>` + found type `<&'min G as Get>` +note: the lifetime `'min` as defined here... --> $DIR/variance-contravariant-self-trait-match.rs:16:21 | LL | fn get_max_from_min<'min, 'max, G>() | ^^^^ -note: ...does not necessarily outlive the lifetime `'max` as defined on the function body at 16:27 +note: ...does not necessarily outlive the lifetime `'max` as defined here --> $DIR/variance-contravariant-self-trait-match.rs:16:27 | LL | fn get_max_from_min<'min, 'max, G>() diff --git a/src/test/ui/variance/variance-covariant-arg-object.stderr b/src/test/ui/variance/variance-covariant-arg-object.stderr index 75b6d588c1..d590a4dc2d 100644 --- a/src/test/ui/variance/variance-covariant-arg-object.stderr +++ b/src/test/ui/variance/variance-covariant-arg-object.stderr @@ -6,12 +6,12 @@ LL | v | = note: expected trait object `dyn Get<&'min i32>` found trait object `dyn Get<&'max i32>` -note: the lifetime `'min` as defined on the function body at 10:21... +note: the lifetime `'min` as defined here... --> $DIR/variance-covariant-arg-object.rs:10:21 | LL | fn get_min_from_max<'min, 'max>(v: Box>) | ^^^^ -note: ...does not necessarily outlive the lifetime `'max` as defined on the function body at 10:27 +note: ...does not necessarily outlive the lifetime `'max` as defined here --> $DIR/variance-covariant-arg-object.rs:10:27 | LL | fn get_min_from_max<'min, 'max>(v: Box>) @@ -25,12 +25,12 @@ LL | v | = note: expected trait object `dyn Get<&'max i32>` found trait object `dyn Get<&'min i32>` -note: the lifetime `'min` as defined on the function body at 18:21... +note: the lifetime `'min` as defined here... --> $DIR/variance-covariant-arg-object.rs:18:21 | LL | fn get_max_from_min<'min, 'max, G>(v: Box>) | ^^^^ -note: ...does not necessarily outlive the lifetime `'max` as defined on the function body at 18:27 +note: ...does not necessarily outlive the lifetime `'max` as defined here --> $DIR/variance-covariant-arg-object.rs:18:27 | LL | fn get_max_from_min<'min, 'max, G>(v: Box>) diff --git a/src/test/ui/variance/variance-covariant-arg-trait-match.stderr b/src/test/ui/variance/variance-covariant-arg-trait-match.stderr index aa383fcc26..eb1766b096 100644 --- a/src/test/ui/variance/variance-covariant-arg-trait-match.stderr +++ b/src/test/ui/variance/variance-covariant-arg-trait-match.stderr @@ -6,12 +6,12 @@ LL | impls_get::() | = note: expected type `Get<&'min i32>` found type `Get<&'max i32>` -note: the lifetime `'min` as defined on the function body at 10:21... +note: the lifetime `'min` as defined here... --> $DIR/variance-covariant-arg-trait-match.rs:10:21 | LL | fn get_min_from_max<'min, 'max, G>() | ^^^^ -note: ...does not necessarily outlive the lifetime `'max` as defined on the function body at 10:27 +note: ...does not necessarily outlive the lifetime `'max` as defined here --> $DIR/variance-covariant-arg-trait-match.rs:10:27 | LL | fn get_min_from_max<'min, 'max, G>() @@ -25,12 +25,12 @@ LL | impls_get::() | = note: expected type `Get<&'max i32>` found type `Get<&'min i32>` -note: the lifetime `'min` as defined on the function body at 17:21... +note: the lifetime `'min` as defined here... --> $DIR/variance-covariant-arg-trait-match.rs:17:21 | LL | fn get_max_from_min<'min, 'max, G>() | ^^^^ -note: ...does not necessarily outlive the lifetime `'max` as defined on the function body at 17:27 +note: ...does not necessarily outlive the lifetime `'max` as defined here --> $DIR/variance-covariant-arg-trait-match.rs:17:27 | LL | fn get_max_from_min<'min, 'max, G>() diff --git a/src/test/ui/variance/variance-covariant-self-trait-match.stderr b/src/test/ui/variance/variance-covariant-self-trait-match.stderr index a25d1044d4..b0bcb2e842 100644 --- a/src/test/ui/variance/variance-covariant-self-trait-match.stderr +++ b/src/test/ui/variance/variance-covariant-self-trait-match.stderr @@ -4,14 +4,14 @@ error[E0308]: mismatched types LL | impls_get::<&'min G>(); | ^^^^^^^^^^^^^^^^^^^^ lifetime mismatch | - = note: expected type `Get` - found type `Get` -note: the lifetime `'min` as defined on the function body at 10:21... + = note: expected type `<&'min G as Get>` + found type `<&'max G as Get>` +note: the lifetime `'min` as defined here... --> $DIR/variance-covariant-self-trait-match.rs:10:21 | LL | fn get_min_from_max<'min, 'max, G>() | ^^^^ -note: ...does not necessarily outlive the lifetime `'max` as defined on the function body at 10:27 +note: ...does not necessarily outlive the lifetime `'max` as defined here --> $DIR/variance-covariant-self-trait-match.rs:10:27 | LL | fn get_min_from_max<'min, 'max, G>() @@ -23,14 +23,14 @@ error[E0308]: mismatched types LL | impls_get::<&'max G>(); | ^^^^^^^^^^^^^^^^^^^^ lifetime mismatch | - = note: expected type `Get` - found type `Get` -note: the lifetime `'min` as defined on the function body at 17:21... + = note: expected type `<&'max G as Get>` + found type `<&'min G as Get>` +note: the lifetime `'min` as defined here... --> $DIR/variance-covariant-self-trait-match.rs:17:21 | LL | fn get_max_from_min<'min, 'max, G>() | ^^^^ -note: ...does not necessarily outlive the lifetime `'max` as defined on the function body at 17:27 +note: ...does not necessarily outlive the lifetime `'max` as defined here --> $DIR/variance-covariant-self-trait-match.rs:17:27 | LL | fn get_max_from_min<'min, 'max, G>() diff --git a/src/test/ui/variance/variance-invariant-arg-object.stderr b/src/test/ui/variance/variance-invariant-arg-object.stderr index 13ee9b9da3..6c1b07e667 100644 --- a/src/test/ui/variance/variance-invariant-arg-object.stderr +++ b/src/test/ui/variance/variance-invariant-arg-object.stderr @@ -6,12 +6,12 @@ LL | v | = note: expected trait object `dyn Get<&'min i32>` found trait object `dyn Get<&'max i32>` -note: the lifetime `'min` as defined on the function body at 7:21... +note: the lifetime `'min` as defined here... --> $DIR/variance-invariant-arg-object.rs:7:21 | LL | fn get_min_from_max<'min, 'max>(v: Box>) | ^^^^ -note: ...does not necessarily outlive the lifetime `'max` as defined on the function body at 7:27 +note: ...does not necessarily outlive the lifetime `'max` as defined here --> $DIR/variance-invariant-arg-object.rs:7:27 | LL | fn get_min_from_max<'min, 'max>(v: Box>) @@ -25,12 +25,12 @@ LL | v | = note: expected trait object `dyn Get<&'max i32>` found trait object `dyn Get<&'min i32>` -note: the lifetime `'min` as defined on the function body at 14:21... +note: the lifetime `'min` as defined here... --> $DIR/variance-invariant-arg-object.rs:14:21 | LL | fn get_max_from_min<'min, 'max, G>(v: Box>) | ^^^^ -note: ...does not necessarily outlive the lifetime `'max` as defined on the function body at 14:27 +note: ...does not necessarily outlive the lifetime `'max` as defined here --> $DIR/variance-invariant-arg-object.rs:14:27 | LL | fn get_max_from_min<'min, 'max, G>(v: Box>) diff --git a/src/test/ui/variance/variance-invariant-arg-trait-match.stderr b/src/test/ui/variance/variance-invariant-arg-trait-match.stderr index b58993737c..0328496546 100644 --- a/src/test/ui/variance/variance-invariant-arg-trait-match.stderr +++ b/src/test/ui/variance/variance-invariant-arg-trait-match.stderr @@ -6,12 +6,12 @@ LL | impls_get::() | = note: expected type `Get<&'min i32>` found type `Get<&'max i32>` -note: the lifetime `'min` as defined on the function body at 7:21... +note: the lifetime `'min` as defined here... --> $DIR/variance-invariant-arg-trait-match.rs:7:21 | LL | fn get_min_from_max<'min, 'max, G>() | ^^^^ -note: ...does not necessarily outlive the lifetime `'max` as defined on the function body at 7:27 +note: ...does not necessarily outlive the lifetime `'max` as defined here --> $DIR/variance-invariant-arg-trait-match.rs:7:27 | LL | fn get_min_from_max<'min, 'max, G>() @@ -25,12 +25,12 @@ LL | impls_get::() | = note: expected type `Get<&'max i32>` found type `Get<&'min i32>` -note: the lifetime `'min` as defined on the function body at 13:21... +note: the lifetime `'min` as defined here... --> $DIR/variance-invariant-arg-trait-match.rs:13:21 | LL | fn get_max_from_min<'min, 'max, G>() | ^^^^ -note: ...does not necessarily outlive the lifetime `'max` as defined on the function body at 13:27 +note: ...does not necessarily outlive the lifetime `'max` as defined here --> $DIR/variance-invariant-arg-trait-match.rs:13:27 | LL | fn get_max_from_min<'min, 'max, G>() diff --git a/src/test/ui/variance/variance-invariant-self-trait-match.stderr b/src/test/ui/variance/variance-invariant-self-trait-match.stderr index 4a1d4d28b4..c553581b56 100644 --- a/src/test/ui/variance/variance-invariant-self-trait-match.stderr +++ b/src/test/ui/variance/variance-invariant-self-trait-match.stderr @@ -4,14 +4,14 @@ error[E0308]: mismatched types LL | impls_get::<&'min G>(); | ^^^^^^^^^^^^^^^^^^^^ lifetime mismatch | - = note: expected type `Get` - found type `Get` -note: the lifetime `'min` as defined on the function body at 7:21... + = note: expected type `<&'min G as Get>` + found type `<&'max G as Get>` +note: the lifetime `'min` as defined here... --> $DIR/variance-invariant-self-trait-match.rs:7:21 | LL | fn get_min_from_max<'min, 'max, G>() | ^^^^ -note: ...does not necessarily outlive the lifetime `'max` as defined on the function body at 7:27 +note: ...does not necessarily outlive the lifetime `'max` as defined here --> $DIR/variance-invariant-self-trait-match.rs:7:27 | LL | fn get_min_from_max<'min, 'max, G>() @@ -23,14 +23,14 @@ error[E0308]: mismatched types LL | impls_get::<&'max G>(); | ^^^^^^^^^^^^^^^^^^^^ lifetime mismatch | - = note: expected type `Get` - found type `Get` -note: the lifetime `'min` as defined on the function body at 13:21... + = note: expected type `<&'max G as Get>` + found type `<&'min G as Get>` +note: the lifetime `'min` as defined here... --> $DIR/variance-invariant-self-trait-match.rs:13:21 | LL | fn get_max_from_min<'min, 'max, G>() | ^^^^ -note: ...does not necessarily outlive the lifetime `'max` as defined on the function body at 13:27 +note: ...does not necessarily outlive the lifetime `'max` as defined here --> $DIR/variance-invariant-self-trait-match.rs:13:27 | LL | fn get_max_from_min<'min, 'max, G>() diff --git a/src/test/ui/variance/variance-use-contravariant-struct-1.stderr b/src/test/ui/variance/variance-use-contravariant-struct-1.stderr index 423c9a601f..ec0cb22cdb 100644 --- a/src/test/ui/variance/variance-use-contravariant-struct-1.stderr +++ b/src/test/ui/variance/variance-use-contravariant-struct-1.stderr @@ -6,12 +6,12 @@ LL | v | = note: expected struct `SomeStruct<&'min ()>` found struct `SomeStruct<&'max ()>` -note: the lifetime `'min` as defined on the function body at 8:8... +note: the lifetime `'min` as defined here... --> $DIR/variance-use-contravariant-struct-1.rs:8:8 | LL | fn foo<'min,'max>(v: SomeStruct<&'max ()>) | ^^^^ -note: ...does not necessarily outlive the lifetime `'max` as defined on the function body at 8:13 +note: ...does not necessarily outlive the lifetime `'max` as defined here --> $DIR/variance-use-contravariant-struct-1.rs:8:13 | LL | fn foo<'min,'max>(v: SomeStruct<&'max ()>) diff --git a/src/test/ui/variance/variance-use-covariant-struct-1.stderr b/src/test/ui/variance/variance-use-covariant-struct-1.stderr index 3f9224804b..0c0071cf9e 100644 --- a/src/test/ui/variance/variance-use-covariant-struct-1.stderr +++ b/src/test/ui/variance/variance-use-covariant-struct-1.stderr @@ -6,12 +6,12 @@ LL | v | = note: expected struct `SomeStruct<&'max ()>` found struct `SomeStruct<&'min ()>` -note: the lifetime `'min` as defined on the function body at 6:8... +note: the lifetime `'min` as defined here... --> $DIR/variance-use-covariant-struct-1.rs:6:8 | LL | fn foo<'min,'max>(v: SomeStruct<&'min ()>) | ^^^^ -note: ...does not necessarily outlive the lifetime `'max` as defined on the function body at 6:13 +note: ...does not necessarily outlive the lifetime `'max` as defined here --> $DIR/variance-use-covariant-struct-1.rs:6:13 | LL | fn foo<'min,'max>(v: SomeStruct<&'min ()>) diff --git a/src/test/ui/variance/variance-use-invariant-struct-1.stderr b/src/test/ui/variance/variance-use-invariant-struct-1.stderr index 7063f1c9c8..76e4bd76b9 100644 --- a/src/test/ui/variance/variance-use-invariant-struct-1.stderr +++ b/src/test/ui/variance/variance-use-invariant-struct-1.stderr @@ -6,12 +6,12 @@ LL | v | = note: expected struct `SomeStruct<&'min ()>` found struct `SomeStruct<&'max ()>` -note: the lifetime `'min` as defined on the function body at 8:8... +note: the lifetime `'min` as defined here... --> $DIR/variance-use-invariant-struct-1.rs:8:8 | LL | fn foo<'min,'max>(v: SomeStruct<&'max ()>) | ^^^^ -note: ...does not necessarily outlive the lifetime `'max` as defined on the function body at 8:13 +note: ...does not necessarily outlive the lifetime `'max` as defined here --> $DIR/variance-use-invariant-struct-1.rs:8:13 | LL | fn foo<'min,'max>(v: SomeStruct<&'max ()>) @@ -25,12 +25,12 @@ LL | v | = note: expected struct `SomeStruct<&'max ()>` found struct `SomeStruct<&'min ()>` -note: the lifetime `'min` as defined on the function body at 15:8... +note: the lifetime `'min` as defined here... --> $DIR/variance-use-invariant-struct-1.rs:15:8 | LL | fn bar<'min,'max>(v: SomeStruct<&'min ()>) | ^^^^ -note: ...does not necessarily outlive the lifetime `'max` as defined on the function body at 15:13 +note: ...does not necessarily outlive the lifetime `'max` as defined here --> $DIR/variance-use-invariant-struct-1.rs:15:13 | LL | fn bar<'min,'max>(v: SomeStruct<&'min ()>) diff --git a/src/test/ui/vtable-res-trait-param.stderr b/src/test/ui/vtable-res-trait-param.stderr index bff6481326..c5fff622b6 100644 --- a/src/test/ui/vtable-res-trait-param.stderr +++ b/src/test/ui/vtable-res-trait-param.stderr @@ -2,7 +2,9 @@ error[E0277]: the trait bound `{integer}: TraitA` is not satisfied --> $DIR/vtable-res-trait-param.rs:17:18 | LL | b.gimme_an_a(y) - | ^ the trait `TraitA` is not implemented for `{integer}` + | ---------- ^ the trait `TraitA` is not implemented for `{integer}` + | | + | required by a bound introduced by this call error: aborting due to previous error diff --git a/src/test/ui/wasm/simd-to-array-80108.rs b/src/test/ui/wasm/simd-to-array-80108.rs new file mode 100644 index 0000000000..0576c2e6be --- /dev/null +++ b/src/test/ui/wasm/simd-to-array-80108.rs @@ -0,0 +1,15 @@ +// only-wasm32 +// compile-flags: --crate-type=lib -Copt-level=2 +// build-pass +#![feature(repr_simd)] + +// Regression test for #80108 + +#[repr(simd)] +pub struct Vector([i32; 4]); + +impl Vector { + pub const fn to_array(self) -> [i32; 4] { + self.0 + } +} diff --git a/src/test/ui/weak-new-uninhabited-issue-48493.rs b/src/test/ui/weak-new-uninhabited-issue-48493.rs index 644fc8c248..39fbf3c9eb 100644 --- a/src/test/ui/weak-new-uninhabited-issue-48493.rs +++ b/src/test/ui/weak-new-uninhabited-issue-48493.rs @@ -2,6 +2,6 @@ fn main() { enum Void {} - std::rc::Weak::::new(); - std::sync::Weak::::new(); + let _ = std::rc::Weak::::new(); + let _ = std::sync::Weak::::new(); } diff --git a/src/test/ui/wf/hir-wf-check-erase-regions.rs b/src/test/ui/wf/hir-wf-check-erase-regions.rs index bb398e5698..2b4b480df0 100644 --- a/src/test/ui/wf/hir-wf-check-erase-regions.rs +++ b/src/test/ui/wf/hir-wf-check-erase-regions.rs @@ -1,5 +1,5 @@ // Regression test for #87549. -// compile-flags: -C incremental=tmp/wf/hir-wf-check-erase-regions +// incremental pub struct Table([Option; N]); diff --git a/src/test/ui/wf/issue-87495.stderr b/src/test/ui/wf/issue-87495.stderr index 010200b5de..c924cd8799 100644 --- a/src/test/ui/wf/issue-87495.stderr +++ b/src/test/ui/wf/issue-87495.stderr @@ -4,7 +4,6 @@ error[E0038]: the trait `T` cannot be made into an object LL | const CONST: (bool, dyn T); | ^^^^^ `T` cannot be made into an object | - = help: consider moving `CONST` to another trait note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit --> $DIR/issue-87495.rs:4:11 | @@ -12,6 +11,7 @@ LL | trait T { | - this trait cannot be made into an object... LL | const CONST: (bool, dyn T); | ^^^^^ ...because it contains this associated `const` + = help: consider moving `CONST` to another trait error: aborting due to previous error diff --git a/src/test/ui/wf/wf-in-foreign-fn-decls-issue-80468.stderr b/src/test/ui/wf/wf-in-foreign-fn-decls-issue-80468.stderr index 4e927cd983..d3593d8c1e 100644 --- a/src/test/ui/wf/wf-in-foreign-fn-decls-issue-80468.stderr +++ b/src/test/ui/wf/wf-in-foreign-fn-decls-issue-80468.stderr @@ -17,7 +17,7 @@ note: because this has an unmet lifetime requirement | LL | pub struct Wrapper(T); | ^^^^^ introduces a `'static` lifetime requirement -note: the anonymous lifetime #1 defined on the method body at 16:5... +note: the anonymous lifetime #1 defined here... --> $DIR/wf-in-foreign-fn-decls-issue-80468.rs:16:5 | LL | pub fn repro(_: Wrapper); diff --git a/src/test/ui/wf/wf-object-safe.stderr b/src/test/ui/wf/wf-object-safe.stderr index 9b749f88fb..64969fbe32 100644 --- a/src/test/ui/wf/wf-object-safe.stderr +++ b/src/test/ui/wf/wf-object-safe.stderr @@ -4,7 +4,6 @@ error[E0038]: the trait `A` cannot be made into an object LL | let _x: &dyn A; | ^^^^^^ `A` cannot be made into an object | - = help: consider moving `foo` to another trait note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit --> $DIR/wf-object-safe.rs:5:23 | @@ -12,6 +11,7 @@ LL | trait A { | - this trait cannot be made into an object... LL | fn foo(&self, _x: &Self); | ^^^^^ ...because method `foo` references the `Self` type in this parameter + = help: consider moving `foo` to another trait error: aborting due to previous error diff --git a/src/test/ui/wf/wf-static-method.stderr b/src/test/ui/wf/wf-static-method.stderr index c02a8fe4aa..c663931c5d 100644 --- a/src/test/ui/wf/wf-static-method.stderr +++ b/src/test/ui/wf/wf-static-method.stderr @@ -4,12 +4,12 @@ error[E0312]: lifetime of reference outlives lifetime of borrowed content... LL | u | ^ | -note: ...the reference is valid for the lifetime `'a` as defined on the impl at 14:6... +note: ...the reference is valid for the lifetime `'a` as defined here... --> $DIR/wf-static-method.rs:14:6 | LL | impl<'a, 'b> Foo<'a, 'b, Evil<'a, 'b>> for () { | ^^ -note: ...but the borrowed content is only valid for the lifetime `'b` as defined on the impl at 14:10 +note: ...but the borrowed content is only valid for the lifetime `'b` as defined here --> $DIR/wf-static-method.rs:14:10 | LL | impl<'a, 'b> Foo<'a, 'b, Evil<'a, 'b>> for () { @@ -21,12 +21,12 @@ error[E0478]: lifetime bound not satisfied LL | let me = Self::make_me(); | ^^^^ | -note: lifetime parameter instantiated with the lifetime `'b` as defined on the impl at 23:10 +note: lifetime parameter instantiated with the lifetime `'b` as defined here --> $DIR/wf-static-method.rs:23:10 | LL | impl<'a, 'b> Foo<'a, 'b, ()> for IndirectEvil<'a, 'b> { | ^^ -note: but lifetime parameter must outlive the lifetime `'a` as defined on the impl at 23:6 +note: but lifetime parameter must outlive the lifetime `'a` as defined here --> $DIR/wf-static-method.rs:23:6 | LL | impl<'a, 'b> Foo<'a, 'b, ()> for IndirectEvil<'a, 'b> { @@ -38,12 +38,12 @@ error[E0312]: lifetime of reference outlives lifetime of borrowed content... LL | u | ^ | -note: ...the reference is valid for the lifetime `'a` as defined on the impl at 31:6... +note: ...the reference is valid for the lifetime `'a` as defined here... --> $DIR/wf-static-method.rs:31:6 | LL | impl<'a, 'b> Evil<'a, 'b> { | ^^ -note: ...but the borrowed content is only valid for the lifetime `'b` as defined on the impl at 31:10 +note: ...but the borrowed content is only valid for the lifetime `'b` as defined here --> $DIR/wf-static-method.rs:31:10 | LL | impl<'a, 'b> Evil<'a, 'b> { @@ -55,7 +55,7 @@ error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'b` d LL | <()>::static_evil(b) | ^^^^^^^^^^^^^^^^^ | -note: first, the lifetime cannot outlive the lifetime `'b` as defined on the function body at 40:13... +note: first, the lifetime cannot outlive the lifetime `'b` as defined here... --> $DIR/wf-static-method.rs:40:13 | LL | fn evil<'a, 'b>(b: &'b u32) -> &'a u32 { @@ -65,7 +65,7 @@ note: ...so that reference does not outlive borrowed content | LL | <()>::static_evil(b) | ^ -note: but, the lifetime must be valid for the lifetime `'a` as defined on the function body at 40:9... +note: but, the lifetime must be valid for the lifetime `'a` as defined here... --> $DIR/wf-static-method.rs:40:9 | LL | fn evil<'a, 'b>(b: &'b u32) -> &'a u32 { @@ -82,7 +82,7 @@ error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'b` d LL | ::static_evil(b) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: first, the lifetime cannot outlive the lifetime `'b` as defined on the function body at 44:22... +note: first, the lifetime cannot outlive the lifetime `'b` as defined here... --> $DIR/wf-static-method.rs:44:22 | LL | fn indirect_evil<'a, 'b>(b: &'b u32) -> &'a u32 { @@ -92,7 +92,7 @@ note: ...so that reference does not outlive borrowed content | LL | ::static_evil(b) | ^ -note: but, the lifetime must be valid for the lifetime `'a` as defined on the function body at 44:18... +note: but, the lifetime must be valid for the lifetime `'a` as defined here... --> $DIR/wf-static-method.rs:44:18 | LL | fn indirect_evil<'a, 'b>(b: &'b u32) -> &'a u32 { @@ -109,7 +109,7 @@ error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'b` d LL | ::inherent_evil(b) | ^^^^^^^^^^^^^^^^^^^^^ | -note: first, the lifetime cannot outlive the lifetime `'b` as defined on the function body at 49:22... +note: first, the lifetime cannot outlive the lifetime `'b` as defined here... --> $DIR/wf-static-method.rs:49:22 | LL | fn inherent_evil<'a, 'b>(b: &'b u32) -> &'a u32 { @@ -119,7 +119,7 @@ note: ...so that reference does not outlive borrowed content | LL | ::inherent_evil(b) | ^ -note: but, the lifetime must be valid for the lifetime `'a` as defined on the function body at 49:18... +note: but, the lifetime must be valid for the lifetime `'a` as defined here... --> $DIR/wf-static-method.rs:49:18 | LL | fn inherent_evil<'a, 'b>(b: &'b u32) -> &'a u32 { diff --git a/src/test/ui/where-clauses/where-clause-constraints-are-local-for-inherent-impl.stderr b/src/test/ui/where-clauses/where-clause-constraints-are-local-for-inherent-impl.stderr index 0df5f91c8f..43fbc0a906 100644 --- a/src/test/ui/where-clauses/where-clause-constraints-are-local-for-inherent-impl.stderr +++ b/src/test/ui/where-clauses/where-clause-constraints-are-local-for-inherent-impl.stderr @@ -2,7 +2,9 @@ error[E0277]: the trait bound `T: Copy` is not satisfied --> $DIR/where-clause-constraints-are-local-for-inherent-impl.rs:13:22 | LL | require_copy(self.x); - | ^^^^^^ the trait `Copy` is not implemented for `T` + | ------------ ^^^^^^ the trait `Copy` is not implemented for `T` + | | + | required by a bound introduced by this call | note: required by a bound in `require_copy` --> $DIR/where-clause-constraints-are-local-for-inherent-impl.rs:1:20 diff --git a/src/test/ui/where-clauses/where-clause-constraints-are-local-for-trait-impl.stderr b/src/test/ui/where-clauses/where-clause-constraints-are-local-for-trait-impl.stderr index 97d651e0be..f2db8fcc4a 100644 --- a/src/test/ui/where-clauses/where-clause-constraints-are-local-for-trait-impl.stderr +++ b/src/test/ui/where-clauses/where-clause-constraints-are-local-for-trait-impl.stderr @@ -2,7 +2,9 @@ error[E0277]: the trait bound `T: Copy` is not satisfied --> $DIR/where-clause-constraints-are-local-for-trait-impl.rs:18:22 | LL | require_copy(self.x); - | ^^^^^^ the trait `Copy` is not implemented for `T` + | ------------ ^^^^^^ the trait `Copy` is not implemented for `T` + | | + | required by a bound introduced by this call | note: required by a bound in `require_copy` --> $DIR/where-clause-constraints-are-local-for-trait-impl.rs:1:20 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 d7de83104c..3223dca3cd 100644 --- a/src/test/ui/where-clauses/where-clauses-method-unsatisfied.stderr +++ b/src/test/ui/where-clauses/where-clauses-method-unsatisfied.stderr @@ -2,7 +2,9 @@ error[E0277]: the trait bound `Bar: Eq` is not satisfied --> $DIR/where-clauses-method-unsatisfied.rs:18:14 | LL | x.equals(&x); - | ^^ the trait `Eq` is not implemented for `Bar` + | ------ ^^ the trait `Eq` is not implemented for `Bar` + | | + | required by a bound introduced by this call error: aborting due to previous error diff --git a/src/test/ui/while-let.stderr b/src/test/ui/while-let.stderr index 17e8830f63..c5e2fd92f0 100644 --- a/src/test/ui/while-let.stderr +++ b/src/test/ui/while-let.stderr @@ -7,7 +7,7 @@ LL | while let $p = $e $b LL | / foo!(_a, 1, { LL | | println!("irrefutable pattern"); LL | | }); - | |_______- in this macro invocation + | |______- in this macro invocation | = note: `#[warn(irrefutable_let_patterns)]` on by default = note: this pattern will always match, so the loop will never exit @@ -23,7 +23,7 @@ LL | while let $p = $e $b LL | / bar!(_a, 1, { LL | | println!("irrefutable pattern"); LL | | }); - | |_______- in this macro invocation + | |______- in this macro invocation | = note: this pattern will always match, so the loop will never exit = help: consider instead using a `loop { ... }` with a `let` inside it diff --git a/src/test/ui/wrong-ret-type.stderr b/src/test/ui/wrong-ret-type.stderr index 8e240a0e40..c686a0b2f5 100644 --- a/src/test/ui/wrong-ret-type.stderr +++ b/src/test/ui/wrong-ret-type.stderr @@ -9,7 +9,7 @@ LL | fn mk_int() -> usize { let i: isize = 3; return i; } help: you can convert an `isize` to a `usize` and panic if the converted value doesn't fit | LL | fn mk_int() -> usize { let i: isize = 3; return i.try_into().unwrap(); } - | ~~~~~~~~~~~~~~~~~~~~~ + | ++++++++++++++++++++ error: aborting due to previous error diff --git a/src/tools/build-manifest/Cargo.toml b/src/tools/build-manifest/Cargo.toml index 334407c2b2..340acff34f 100644 --- a/src/tools/build-manifest/Cargo.toml +++ b/src/tools/build-manifest/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "build-manifest" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] toml = "0.5" diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs index ab63a9e2df..c1579ae9ac 100644 --- a/src/tools/build-manifest/src/main.rs +++ b/src/tools/build-manifest/src/main.rs @@ -99,6 +99,7 @@ static TARGETS: &[&str] = &[ "i686-unknown-freebsd", "i686-unknown-linux-gnu", "i686-unknown-linux-musl", + "m68k-unknown-linux-gnu", "mips-unknown-linux-gnu", "mips-unknown-linux-musl", "mips64-unknown-linux-gnuabi64", diff --git a/src/tools/bump-stage0/Cargo.toml b/src/tools/bump-stage0/Cargo.toml new file mode 100644 index 0000000000..cf8840ff6e --- /dev/null +++ b/src/tools/bump-stage0/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "bump-stage0" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +anyhow = "1.0.34" +curl = "0.4.38" +indexmap = { version = "1.7.0", features = ["serde"] } +serde = { version = "1.0.125", features = ["derive"] } +serde_json = "1.0.59" +toml = "0.5.7" diff --git a/src/tools/bump-stage0/src/main.rs b/src/tools/bump-stage0/src/main.rs new file mode 100644 index 0000000000..96d3c87384 --- /dev/null +++ b/src/tools/bump-stage0/src/main.rs @@ -0,0 +1,204 @@ +use anyhow::Error; +use curl::easy::Easy; +use indexmap::IndexMap; +use std::collections::HashMap; +use std::convert::TryInto; + +const DIST_SERVER: &str = "https://static.rust-lang.org"; +const COMPILER_COMPONENTS: &[&str] = &["rustc", "rust-std", "cargo"]; +const RUSTFMT_COMPONENTS: &[&str] = &["rustfmt-preview"]; + +struct Tool { + channel: Channel, + version: [u16; 3], + checksums: IndexMap, +} + +impl Tool { + fn new() -> Result { + let channel = match std::fs::read_to_string("src/ci/channel")?.trim() { + "stable" => Channel::Stable, + "beta" => Channel::Beta, + "nightly" => Channel::Nightly, + other => anyhow::bail!("unsupported channel: {}", other), + }; + + // Split "1.42.0" into [1, 42, 0] + let version = std::fs::read_to_string("src/version")? + .trim() + .split('.') + .map(|val| val.parse()) + .collect::, _>>()? + .try_into() + .map_err(|_| anyhow::anyhow!("failed to parse version"))?; + + Ok(Self { channel, version, checksums: IndexMap::new() }) + } + + fn update_json(mut self) -> Result<(), Error> { + std::fs::write( + "src/stage0.json", + format!( + "{}\n", + serde_json::to_string_pretty(&Stage0 { + comment: "Generated by `./x.py run src/tools/bump-stage0`. \ + Run that command again to update the bootstrap compiler.", + dist_server: DIST_SERVER.into(), + compiler: self.detect_compiler()?, + rustfmt: self.detect_rustfmt()?, + checksums_sha256: { + // Keys are sorted here instead of beforehand because values in this map + // are added while filling the other struct fields just above this block. + self.checksums.sort_keys(); + self.checksums + } + })? + ), + )?; + Ok(()) + } + + // Currently Rust always bootstraps from the previous stable release, and in our train model + // this means that the master branch bootstraps from beta, beta bootstraps from current stable, + // and stable bootstraps from the previous stable release. + // + // On the master branch the compiler version is configured to `beta` whereas if you're looking + // at the beta or stable channel you'll likely see `1.x.0` as the version, with the previous + // release's version number. + fn detect_compiler(&mut self) -> Result { + let channel = match self.channel { + Channel::Stable | Channel::Beta => { + // The 1.XX manifest points to the latest point release of that minor release. + format!("{}.{}", self.version[0], self.version[1] - 1) + } + Channel::Nightly => "beta".to_string(), + }; + + let manifest = fetch_manifest(&channel)?; + self.collect_checksums(&manifest, COMPILER_COMPONENTS)?; + Ok(Stage0Toolchain { + date: manifest.date, + version: if self.channel == Channel::Nightly { + "beta".to_string() + } else { + // The version field is like "1.42.0 (abcdef1234 1970-01-01)" + manifest.pkg["rust"] + .version + .split_once(' ') + .expect("invalid version field") + .0 + .to_string() + }, + }) + } + + /// We use a nightly rustfmt to format the source because it solves some bootstrapping issues + /// with use of new syntax in this repo. For the beta/stable channels rustfmt is not provided, + /// as we don't want to depend on rustfmt from nightly there. + fn detect_rustfmt(&mut self) -> Result, Error> { + if self.channel != Channel::Nightly { + return Ok(None); + } + + let manifest = fetch_manifest("nightly")?; + self.collect_checksums(&manifest, RUSTFMT_COMPONENTS)?; + Ok(Some(Stage0Toolchain { date: manifest.date, version: "nightly".into() })) + } + + fn collect_checksums(&mut self, manifest: &Manifest, components: &[&str]) -> Result<(), Error> { + let prefix = format!("{}/", DIST_SERVER); + for component in components { + let pkg = manifest + .pkg + .get(*component) + .ok_or_else(|| anyhow::anyhow!("missing component from manifest: {}", component))?; + for target in pkg.target.values() { + for pair in &[(&target.url, &target.hash), (&target.xz_url, &target.xz_hash)] { + if let (Some(url), Some(sha256)) = pair { + let url = url + .strip_prefix(&prefix) + .ok_or_else(|| { + anyhow::anyhow!("url doesn't start with dist server base: {}", url) + })? + .to_string(); + self.checksums.insert(url, sha256.clone()); + } + } + } + } + Ok(()) + } +} + +fn main() -> Result<(), Error> { + let tool = Tool::new()?; + tool.update_json()?; + Ok(()) +} + +fn fetch_manifest(channel: &str) -> Result { + Ok(toml::from_slice(&http_get(&format!( + "{}/dist/channel-rust-{}.toml", + DIST_SERVER, channel + ))?)?) +} + +fn http_get(url: &str) -> Result, Error> { + let mut data = Vec::new(); + let mut handle = Easy::new(); + handle.fail_on_error(true)?; + handle.url(url)?; + { + let mut transfer = handle.transfer(); + transfer.write_function(|new_data| { + data.extend_from_slice(new_data); + Ok(new_data.len()) + })?; + transfer.perform()?; + } + Ok(data) +} + +#[derive(Debug, PartialEq, Eq)] +enum Channel { + Stable, + Beta, + Nightly, +} + +#[derive(Debug, serde::Serialize)] +struct Stage0 { + #[serde(rename = "__comment")] + comment: &'static str, + dist_server: String, + compiler: Stage0Toolchain, + rustfmt: Option, + checksums_sha256: IndexMap, +} + +#[derive(Debug, serde::Serialize)] +struct Stage0Toolchain { + date: String, + version: String, +} + +#[derive(Debug, serde::Deserialize)] +struct Manifest { + date: String, + pkg: HashMap, +} + +#[derive(Debug, serde::Deserialize)] +struct ManifestPackage { + version: String, + target: HashMap, +} + +#[derive(Debug, serde::Deserialize)] +struct ManifestTargetPackage { + available: bool, + url: Option, + hash: Option, + xz_url: Option, + xz_hash: Option, +} diff --git a/src/tools/cargotest/Cargo.toml b/src/tools/cargotest/Cargo.toml index a88272d234..bfd894e2bd 100644 --- a/src/tools/cargotest/Cargo.toml +++ b/src/tools/cargotest/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "cargotest2" version = "0.1.0" -edition = "2018" +edition = "2021" [[bin]] name = "cargotest" diff --git a/src/tools/clippy/.cargo/config b/src/tools/clippy/.cargo/config index e95ea224cb..688473f2f9 100644 --- a/src/tools/clippy/.cargo/config +++ b/src/tools/clippy/.cargo/config @@ -1,8 +1,10 @@ [alias] uitest = "test --test compile-test" -dev = "run --target-dir clippy_dev/target --package clippy_dev --bin clippy_dev --manifest-path clippy_dev/Cargo.toml --" -lintcheck = "run --target-dir lintcheck/target --package lintcheck --bin lintcheck --manifest-path lintcheck/Cargo.toml -- " +dev = "run --package clippy_dev --bin clippy_dev --manifest-path clippy_dev/Cargo.toml --" +lintcheck = "run --package lintcheck --bin lintcheck --manifest-path lintcheck/Cargo.toml -- " collect-metadata = "test --test dogfood --features metadata-collector-lint -- run_metadata_collection_lint --ignored" [build] -rustflags = ["-Zunstable-options"] +# -Zbinary-dep-depinfo allows us to track which rlib files to use for compiling UI tests +rustflags = ["-Zunstable-options", "-Zbinary-dep-depinfo"] +target-dir = "target" diff --git a/src/tools/clippy/.github/ISSUE_TEMPLATE/blank_issue.md b/src/tools/clippy/.github/ISSUE_TEMPLATE/blank_issue.md index 9aef3ebe63..866303a1f9 100644 --- a/src/tools/clippy/.github/ISSUE_TEMPLATE/blank_issue.md +++ b/src/tools/clippy/.github/ISSUE_TEMPLATE/blank_issue.md @@ -2,3 +2,17 @@ name: Blank Issue about: Create a blank issue. --- + + + diff --git a/src/tools/clippy/.github/ISSUE_TEMPLATE/bug_report.md b/src/tools/clippy/.github/ISSUE_TEMPLATE/bug_report.md index 2bc87db123..119a498fb9 100644 --- a/src/tools/clippy/.github/ISSUE_TEMPLATE/bug_report.md +++ b/src/tools/clippy/.github/ISSUE_TEMPLATE/bug_report.md @@ -20,28 +20,24 @@ Instead, this happened: *explanation* ### Meta -- `cargo clippy -V`: e.g. clippy 0.0.212 (f455e46 2020-06-20) -- `rustc -Vv`: - ``` - rustc 1.46.0-nightly (f455e46ea 2020-06-20) - binary: rustc - commit-hash: f455e46eae1a227d735091091144601b467e1565 - commit-date: 2020-06-20 - host: x86_64-unknown-linux-gnu - release: 1.46.0-nightly - LLVM version: 10.0 - ``` +**Rust version (`rustc -Vv`):** + +``` +rustc 1.46.0-nightly (f455e46ea 2020-06-20) +binary: rustc +commit-hash: f455e46eae1a227d735091091144601b467e1565 +commit-date: 2020-06-20 +host: x86_64-unknown-linux-gnu +release: 1.46.0-nightly +LLVM version: 10.0 +``` -

Backtrace -

- - ``` - - ``` - -

-
diff --git a/src/tools/clippy/.github/ISSUE_TEMPLATE/false_negative.md b/src/tools/clippy/.github/ISSUE_TEMPLATE/false_negative.md index 53341c7a92..d9ea2db34e 100644 --- a/src/tools/clippy/.github/ISSUE_TEMPLATE/false_negative.md +++ b/src/tools/clippy/.github/ISSUE_TEMPLATE/false_negative.md @@ -22,14 +22,14 @@ Instead, this happened: *explanation* ### Meta -- `cargo clippy -V`: e.g. clippy 0.0.212 (f455e46 2020-06-20) -- `rustc -Vv`: - ``` - rustc 1.46.0-nightly (f455e46ea 2020-06-20) - binary: rustc - commit-hash: f455e46eae1a227d735091091144601b467e1565 - commit-date: 2020-06-20 - host: x86_64-unknown-linux-gnu - release: 1.46.0-nightly - LLVM version: 10.0 - ``` +**Rust version (`rustc -Vv`):** + +``` +rustc 1.46.0-nightly (f455e46ea 2020-06-20) +binary: rustc +commit-hash: f455e46eae1a227d735091091144601b467e1565 +commit-date: 2020-06-20 +host: x86_64-unknown-linux-gnu +release: 1.46.0-nightly +LLVM version: 10.0 +``` diff --git a/src/tools/clippy/.github/ISSUE_TEMPLATE/false_positive.md b/src/tools/clippy/.github/ISSUE_TEMPLATE/false_positive.md index 34fd6f4bdb..82158e02f0 100644 --- a/src/tools/clippy/.github/ISSUE_TEMPLATE/false_positive.md +++ b/src/tools/clippy/.github/ISSUE_TEMPLATE/false_positive.md @@ -22,14 +22,23 @@ Instead, this happened: *explanation* ### Meta -- `cargo clippy -V`: e.g. clippy 0.0.212 (f455e46 2020-06-20) -- `rustc -Vv`: - ``` - rustc 1.46.0-nightly (f455e46ea 2020-06-20) - binary: rustc - commit-hash: f455e46eae1a227d735091091144601b467e1565 - commit-date: 2020-06-20 - host: x86_64-unknown-linux-gnu - release: 1.46.0-nightly - LLVM version: 10.0 - ``` +**Rust version (`rustc -Vv`):** +``` +rustc 1.46.0-nightly (f455e46ea 2020-06-20) +binary: rustc +commit-hash: f455e46eae1a227d735091091144601b467e1565 +commit-date: 2020-06-20 +host: x86_64-unknown-linux-gnu +release: 1.46.0-nightly +LLVM version: 10.0 +``` + + diff --git a/src/tools/clippy/.github/ISSUE_TEMPLATE/ice.md b/src/tools/clippy/.github/ISSUE_TEMPLATE/ice.md index 0b7cd1ed0f..6c1bed663c 100644 --- a/src/tools/clippy/.github/ISSUE_TEMPLATE/ice.md +++ b/src/tools/clippy/.github/ISSUE_TEMPLATE/ice.md @@ -20,17 +20,16 @@ http://blog.pnkfx.org/blog/2019/11/18/rust-bug-minimization-patterns/ ### Meta -- `cargo clippy -V`: e.g. clippy 0.0.212 (f455e46 2020-06-20) -- `rustc -Vv`: - ``` - rustc 1.46.0-nightly (f455e46ea 2020-06-20) - binary: rustc - commit-hash: f455e46eae1a227d735091091144601b467e1565 - commit-date: 2020-06-20 - host: x86_64-unknown-linux-gnu - release: 1.46.0-nightly - LLVM version: 10.0 - ``` +**Rust version (`rustc -Vv`):** +``` +rustc 1.46.0-nightly (f455e46ea 2020-06-20) +binary: rustc +commit-hash: f455e46eae1a227d735091091144601b467e1565 +commit-date: 2020-06-20 +host: x86_64-unknown-linux-gnu +release: 1.46.0-nightly +LLVM version: 10.0 +``` ### Error output diff --git a/src/tools/clippy/.github/workflows/clippy_dev.yml b/src/tools/clippy/.github/workflows/clippy_dev.yml index 95da775b7b..9a5416153a 100644 --- a/src/tools/clippy/.github/workflows/clippy_dev.yml +++ b/src/tools/clippy/.github/workflows/clippy_dev.yml @@ -42,9 +42,6 @@ jobs: run: cargo build --features deny-warnings working-directory: clippy_dev - - name: Test limit_stderr_length - run: cargo dev limit_stderr_length - - name: Test update_lints run: cargo dev update_lints --check diff --git a/src/tools/clippy/CHANGELOG.md b/src/tools/clippy/CHANGELOG.md index 2b89170073..dabad5d184 100644 --- a/src/tools/clippy/CHANGELOG.md +++ b/src/tools/clippy/CHANGELOG.md @@ -6,11 +6,81 @@ document. ## Unreleased / In Rust Nightly -[74d1561...master](https://github.com/rust-lang/rust-clippy/compare/74d1561...master) +[7bfc26e...master](https://github.com/rust-lang/rust-clippy/compare/7bfc26e...master) + +## Rust 1.56 + +Current beta, release 2021-10-21 + +[74d1561...7bfc26e](https://github.com/rust-lang/rust-clippy/compare/74d1561...7bfc26e) + +### New Lints + +* [`unwrap_or_else_default`] + [#7516](https://github.com/rust-lang/rust-clippy/pull/7516) + +### Enhancements + +* [`needless_continue`]: Now also lints in `loop { continue; }` case + [#7477](https://github.com/rust-lang/rust-clippy/pull/7477) +* [`disallowed_type`]: Now also primitive types can be disallowed + [#7488](https://github.com/rust-lang/rust-clippy/pull/7488) +* [`manual_swap`]: Now also lints on xor swaps + [#7506](https://github.com/rust-lang/rust-clippy/pull/7506) +* [`map_flatten`]: Now also lints on the `Result` type + [#7522](https://github.com/rust-lang/rust-clippy/pull/7522) +* [`no_effect`]: Now also lints on inclusive ranges + [#7556](https://github.com/rust-lang/rust-clippy/pull/7556) + +### False Positive Fixes + +* [`nonstandard_macro_braces`]: No longer lints on similar named nested macros + [#7478](https://github.com/rust-lang/rust-clippy/pull/7478) +* [`too_many_lines`]: No longer lints in closures to avoid duplicated diagnostics + [#7534](https://github.com/rust-lang/rust-clippy/pull/7534) +* [`similar_names`]: No longer complains about `iter` and `item` being too + similar [#7546](https://github.com/rust-lang/rust-clippy/pull/7546) + +### Suggestion Fixes/Improvements + +* [`similar_names`]: No longer suggests to insert or add an underscore as a fix + [#7221](https://github.com/rust-lang/rust-clippy/pull/7221) +* [`new_without_default`]: No longer shows the full qualified type path when + suggesting adding a `Default` implementation + [#7493](https://github.com/rust-lang/rust-clippy/pull/7493) +* [`while_let_on_iterator`]: Now suggests re-borrowing mutable references + [#7520](https://github.com/rust-lang/rust-clippy/pull/7520) +* [`extend_with_drain`]: Improve code suggestion for mutable and immutable + references [#7533](https://github.com/rust-lang/rust-clippy/pull/7533) +* [`trivially_copy_pass_by_ref`]: Now properly handles `Self` type + [#7535](https://github.com/rust-lang/rust-clippy/pull/7535) +* [`never_loop`]: Now suggests using `if let` instead of a `for` loop when + applicable [#7541](https://github.com/rust-lang/rust-clippy/pull/7541) + +### Documentation Improvements + +* Clippy now uses a lint to generate its lint documentation. [Lints all the way + down](https://en.wikipedia.org/wiki/Turtles_all_the_way_down). + [#7502](https://github.com/rust-lang/rust-clippy/pull/7502) +* Reworked Clippy's website: + [#7172](https://github.com/rust-lang/rust-clippy/issues/7172) + [#7279](https://github.com/rust-lang/rust-clippy/pull/7279) + * Added applicability information about lints + * Added a link to jump into the implementation + * Improved loading times + * Adapted some styling +* `cargo clippy --help` now also explains the `--fix` and `--no-deps` flag + [#7492](https://github.com/rust-lang/rust-clippy/pull/7492) +* [`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 beta, release 2021-09-09 +Current stable, released 2021-09-09 [3ae8faf...74d1561](https://github.com/rust-lang/rust-clippy/compare/3ae8faf...74d1561) @@ -126,21 +196,9 @@ Current beta, release 2021-09-09 * [`use_self`] [#7428](https://github.com/rust-lang/rust-clippy/pull/7428) -### Documentation Improvements - -* Reworked Clippy's website: - [#7279](https://github.com/rust-lang/rust-clippy/pull/7279) - [#7172](https://github.com/rust-lang/rust-clippy/issues/7172) - * Added applicability information about lints - * Added a link to jump into the implementation - * Improved loading times - * Adapted some styling -* Clippy now uses a lint to generate its documentation - [#7298](https://github.com/rust-lang/rust-clippy/pull/7298) - ## Rust 1.54 -Current stable, released 2021-07-29 +Released 2021-07-29 [7c7683c...3ae8faf](https://github.com/rust-lang/rust-clippy/compare/7c7683c...3ae8faf) @@ -964,7 +1022,7 @@ Released 2020-11-19 [#5907](https://github.com/rust-lang/rust-clippy/pull/5907) * [`suspicious_arithmetic_impl`]: extend to implementations of `BitAnd`, `BitOr`, `BitXor`, `Rem`, `Shl`, and `Shr` [#5884](https://github.com/rust-lang/rust-clippy/pull/5884) -* [`invalid_atomic_ordering`]: detect misuse of `compare_exchange`, `compare_exchange_weak`, and `fetch_update` +* `invalid_atomic_ordering`: detect misuse of `compare_exchange`, `compare_exchange_weak`, and `fetch_update` [#6025](https://github.com/rust-lang/rust-clippy/pull/6025) * Avoid [`redundant_pattern_matching`] triggering in macros [#6069](https://github.com/rust-lang/rust-clippy/pull/6069) @@ -1050,7 +1108,7 @@ Released 2020-11-19 [#5913](https://github.com/rust-lang/rust-clippy/pull/5913) * Add example of false positive to [`ptr_arg`] docs. [#5885](https://github.com/rust-lang/rust-clippy/pull/5885) -* [`box_vec`], [`vec_box`] and [`borrowed_box`]: add link to the documentation of `Box` +* [`box_vec`](https://rust-lang.github.io/rust-clippy/master/index.html#box_collection), [`vec_box`] and [`borrowed_box`]: add link to the documentation of `Box` [#6023](https://github.com/rust-lang/rust-clippy/pull/6023) ## Rust 1.47 @@ -1451,7 +1509,7 @@ Released 2020-03-12 * [`option_as_ref_deref`] [#4945](https://github.com/rust-lang/rust-clippy/pull/4945) * [`wildcard_in_or_patterns`] [#4960](https://github.com/rust-lang/rust-clippy/pull/4960) * [`iter_nth_zero`] [#4966](https://github.com/rust-lang/rust-clippy/pull/4966) -* [`invalid_atomic_ordering`] [#4999](https://github.com/rust-lang/rust-clippy/pull/4999) +* `invalid_atomic_ordering` [#4999](https://github.com/rust-lang/rust-clippy/pull/4999) * [`skip_while_next`] [#5067](https://github.com/rust-lang/rust-clippy/pull/5067) ### Moves and Deprecations @@ -1491,7 +1549,7 @@ Released 2020-03-12 * `unknown_clippy_lints` [#4963](https://github.com/rust-lang/rust-clippy/pull/4963) * [`explicit_into_iter_loop`] [#4978](https://github.com/rust-lang/rust-clippy/pull/4978) * [`useless_attribute`] [#5022](https://github.com/rust-lang/rust-clippy/pull/5022) -* [`if_let_some_result`] [#5032](https://github.com/rust-lang/rust-clippy/pull/5032) +* `if_let_some_result` [#5032](https://github.com/rust-lang/rust-clippy/pull/5032) ### ICE fixes @@ -1815,10 +1873,10 @@ Released 2019-01-17 [2e26fdc2...b2601be](https://github.com/rust-lang/rust-clippy/compare/2e26fdc2...b2601be) -* New lints: [`slow_vector_initialization`], [`mem_discriminant_non_enum`], +* New lints: [`slow_vector_initialization`], `mem_discriminant_non_enum`, [`redundant_clone`], [`wildcard_dependencies`], [`into_iter_on_ref`], `into_iter_on_array`, [`deprecated_cfg_attr`], - [`mem_discriminant_non_enum`], [`cargo_common_metadata`] + [`cargo_common_metadata`] * Add support for `u128` and `i128` to integer related lints * Add float support to `mistyped_literal_suffixes` * Fix false positives in `use_self` @@ -2570,7 +2628,7 @@ Released 2018-09-13 [`bool_comparison`]: https://rust-lang.github.io/rust-clippy/master/index.html#bool_comparison [`borrow_interior_mutable_const`]: https://rust-lang.github.io/rust-clippy/master/index.html#borrow_interior_mutable_const [`borrowed_box`]: https://rust-lang.github.io/rust-clippy/master/index.html#borrowed_box -[`box_vec`]: https://rust-lang.github.io/rust-clippy/master/index.html#box_vec +[`box_collection`]: https://rust-lang.github.io/rust-clippy/master/index.html#box_collection [`boxed_local`]: https://rust-lang.github.io/rust-clippy/master/index.html#boxed_local [`branches_sharing_code`]: https://rust-lang.github.io/rust-clippy/master/index.html#branches_sharing_code [`builtin_type_shadow`]: https://rust-lang.github.io/rust-clippy/master/index.html#builtin_type_shadow @@ -2613,6 +2671,7 @@ Released 2018-09-13 [`deprecated_cfg_attr`]: https://rust-lang.github.io/rust-clippy/master/index.html#deprecated_cfg_attr [`deprecated_semver`]: https://rust-lang.github.io/rust-clippy/master/index.html#deprecated_semver [`deref_addrof`]: https://rust-lang.github.io/rust-clippy/master/index.html#deref_addrof +[`derivable_impls`]: https://rust-lang.github.io/rust-clippy/master/index.html#derivable_impls [`derive_hash_xor_eq`]: https://rust-lang.github.io/rust-clippy/master/index.html#derive_hash_xor_eq [`derive_ord_xor_partial_ord`]: https://rust-lang.github.io/rust-clippy/master/index.html#derive_ord_xor_partial_ord [`disallowed_method`]: https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_method @@ -2636,6 +2695,7 @@ Released 2018-09-13 [`enum_glob_use`]: https://rust-lang.github.io/rust-clippy/master/index.html#enum_glob_use [`enum_variant_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#enum_variant_names [`eq_op`]: https://rust-lang.github.io/rust-clippy/master/index.html#eq_op +[`equatable_if_let`]: https://rust-lang.github.io/rust-clippy/master/index.html#equatable_if_let [`erasing_op`]: https://rust-lang.github.io/rust-clippy/master/index.html#erasing_op [`eval_order_dependence`]: https://rust-lang.github.io/rust-clippy/master/index.html#eval_order_dependence [`excessive_precision`]: https://rust-lang.github.io/rust-clippy/master/index.html#excessive_precision @@ -2684,7 +2744,6 @@ Released 2018-09-13 [`identity_op`]: https://rust-lang.github.io/rust-clippy/master/index.html#identity_op [`if_let_mutex`]: https://rust-lang.github.io/rust-clippy/master/index.html#if_let_mutex [`if_let_redundant_pattern_matching`]: https://rust-lang.github.io/rust-clippy/master/index.html#if_let_redundant_pattern_matching -[`if_let_some_result`]: https://rust-lang.github.io/rust-clippy/master/index.html#if_let_some_result [`if_not_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#if_not_else [`if_same_then_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#if_same_then_else [`if_then_some_else_none`]: https://rust-lang.github.io/rust-clippy/master/index.html#if_then_some_else_none @@ -2712,7 +2771,6 @@ Released 2018-09-13 [`integer_arithmetic`]: https://rust-lang.github.io/rust-clippy/master/index.html#integer_arithmetic [`integer_division`]: https://rust-lang.github.io/rust-clippy/master/index.html#integer_division [`into_iter_on_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#into_iter_on_ref -[`invalid_atomic_ordering`]: https://rust-lang.github.io/rust-clippy/master/index.html#invalid_atomic_ordering [`invalid_null_ptr_usage`]: https://rust-lang.github.io/rust-clippy/master/index.html#invalid_null_ptr_usage [`invalid_regex`]: https://rust-lang.github.io/rust-clippy/master/index.html#invalid_regex [`invalid_upcast_comparisons`]: https://rust-lang.github.io/rust-clippy/master/index.html#invalid_upcast_comparisons @@ -2722,6 +2780,7 @@ Released 2018-09-13 [`iter_count`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_count [`iter_next_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_next_loop [`iter_next_slice`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_next_slice +[`iter_not_returning_iterator`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_not_returning_iterator [`iter_nth`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_nth [`iter_nth_zero`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_nth_zero [`iter_skip_next`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_skip_next @@ -2744,6 +2803,7 @@ Released 2018-09-13 [`lossy_float_literal`]: https://rust-lang.github.io/rust-clippy/master/index.html#lossy_float_literal [`macro_use_imports`]: https://rust-lang.github.io/rust-clippy/master/index.html#macro_use_imports [`main_recursion`]: https://rust-lang.github.io/rust-clippy/master/index.html#main_recursion +[`manual_assert`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_assert [`manual_async_fn`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_async_fn [`manual_filter_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_filter_map [`manual_find_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_find_map @@ -2754,6 +2814,7 @@ Released 2018-09-13 [`manual_ok_or`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_ok_or [`manual_range_contains`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_range_contains [`manual_saturating_arithmetic`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_saturating_arithmetic +[`manual_split_once`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_split_once [`manual_str_repeat`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_str_repeat [`manual_strip`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_strip [`manual_swap`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_swap @@ -2772,12 +2833,12 @@ Released 2018-09-13 [`match_on_vec_items`]: https://rust-lang.github.io/rust-clippy/master/index.html#match_on_vec_items [`match_overlapping_arm`]: https://rust-lang.github.io/rust-clippy/master/index.html#match_overlapping_arm [`match_ref_pats`]: https://rust-lang.github.io/rust-clippy/master/index.html#match_ref_pats +[`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_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 -[`mem_discriminant_non_enum`]: https://rust-lang.github.io/rust-clippy/master/index.html#mem_discriminant_non_enum [`mem_forget`]: https://rust-lang.github.io/rust-clippy/master/index.html#mem_forget [`mem_replace_option_with_none`]: https://rust-lang.github.io/rust-clippy/master/index.html#mem_replace_option_with_none [`mem_replace_with_default`]: https://rust-lang.github.io/rust-clippy/master/index.html#mem_replace_with_default @@ -2795,6 +2856,7 @@ Released 2018-09-13 [`missing_safety_doc`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_safety_doc [`mistyped_literal_suffixes`]: https://rust-lang.github.io/rust-clippy/master/index.html#mistyped_literal_suffixes [`mixed_case_hex_literals`]: https://rust-lang.github.io/rust-clippy/master/index.html#mixed_case_hex_literals +[`mod_module_files`]: https://rust-lang.github.io/rust-clippy/master/index.html#mod_module_files [`module_inception`]: https://rust-lang.github.io/rust-clippy/master/index.html#module_inception [`module_name_repetitions`]: https://rust-lang.github.io/rust-clippy/master/index.html#module_name_repetitions [`modulo_arithmetic`]: https://rust-lang.github.io/rust-clippy/master/index.html#modulo_arithmetic @@ -2821,6 +2883,7 @@ Released 2018-09-13 [`needless_doctest_main`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_doctest_main [`needless_for_each`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_for_each [`needless_lifetimes`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes +[`needless_option_as_deref`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_option_as_deref [`needless_pass_by_value`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_value [`needless_question_mark`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_question_mark [`needless_range_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_range_loop @@ -2828,12 +2891,14 @@ Released 2018-09-13 [`needless_update`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_update [`neg_cmp_op_on_partial_ord`]: https://rust-lang.github.io/rust-clippy/master/index.html#neg_cmp_op_on_partial_ord [`neg_multiply`]: https://rust-lang.github.io/rust-clippy/master/index.html#neg_multiply +[`negative_feature_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#negative_feature_names [`never_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#never_loop [`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 [`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 [`nonminimal_bool`]: https://rust-lang.github.io/rust-clippy/master/index.html#nonminimal_bool [`nonsensical_open_options`]: https://rust-lang.github.io/rust-clippy/master/index.html#nonsensical_open_options [`nonstandard_macro_braces`]: https://rust-lang.github.io/rust-clippy/master/index.html#nonstandard_macro_braces @@ -2881,6 +2946,7 @@ Released 2018-09-13 [`redundant_closure_call`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_closure_call [`redundant_closure_for_method_calls`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_closure_for_method_calls [`redundant_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_else +[`redundant_feature_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_feature_names [`redundant_field_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_field_names [`redundant_pattern`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_pattern [`redundant_pattern_matching`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_pattern_matching @@ -2900,9 +2966,11 @@ Released 2018-09-13 [`reversed_empty_ranges`]: https://rust-lang.github.io/rust-clippy/master/index.html#reversed_empty_ranges [`same_functions_in_if_condition`]: https://rust-lang.github.io/rust-clippy/master/index.html#same_functions_in_if_condition [`same_item_push`]: https://rust-lang.github.io/rust-clippy/master/index.html#same_item_push +[`same_name_method`]: https://rust-lang.github.io/rust-clippy/master/index.html#same_name_method [`search_is_some`]: https://rust-lang.github.io/rust-clippy/master/index.html#search_is_some [`self_assignment`]: https://rust-lang.github.io/rust-clippy/master/index.html#self_assignment [`self_named_constructors`]: https://rust-lang.github.io/rust-clippy/master/index.html#self_named_constructors +[`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 [`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 diff --git a/src/tools/clippy/Cargo.toml b/src/tools/clippy/Cargo.toml index 16b6c207a5..ba3ed3053a 100644 --- a/src/tools/clippy/Cargo.toml +++ b/src/tools/clippy/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.1.56" +version = "0.1.57" description = "A bunch of helpful lints to avoid common pitfalls in Rust" repository = "https://github.com/rust-lang/rust-clippy" readme = "README.md" @@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0" keywords = ["clippy", "lint", "plugin"] categories = ["development-tools", "development-tools::cargo-plugins"] build = "build.rs" -edition = "2018" +edition = "2021" publish = false [[bin]] @@ -21,32 +21,35 @@ name = "clippy-driver" path = "src/driver.rs" [dependencies] -# begin automatic update -clippy_lints = { version = "0.1.50", path = "clippy_lints" } -# end automatic update +clippy_lints = { version = "0.1", path = "clippy_lints" } semver = "0.11" -rustc_tools_util = { version = "0.2.0", path = "rustc_tools_util" } -tempfile = { version = "3.1.0", optional = true } +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.6.0", features = ["tmp"] } +compiletest_rs = { version = "0.7", features = ["tmp"] } tester = "0.9" -serde = { version = "1.0", features = ["derive"] } -derive-new = "0.5" -regex = "1.4" -quote = "1" -syn = { version = "1", features = ["full"] } +regex = "1.5" # This is used by the `collect-metadata` alias. filetime = "0.2" # A noop dependency that changes in the Rust repository, it's a bit of a hack. # See the `src/tools/rustc-workspace-hack/README.md` file in `rust-lang/rust` # for more information. -rustc-workspace-hack = "1.0.0" +rustc-workspace-hack = "1.0" + +# UI test dependencies +clippy_utils = { path = "clippy_utils" } +derive-new = "0.5" +if_chain = "1.0" +itertools = "0.10" +quote = "1.0" +serde = { version = "1.0", features = ["derive"] } +syn = { version = "1.0", features = ["full"] } [build-dependencies] -rustc_tools_util = { version = "0.2.0", path = "rustc_tools_util" } +rustc_tools_util = { version = "0.2", path = "rustc_tools_util" } [features] deny-warnings = ["clippy_lints/deny-warnings"] diff --git a/src/tools/clippy/README.md b/src/tools/clippy/README.md index e1c968273c..822335fc65 100644 --- a/src/tools/clippy/README.md +++ b/src/tools/clippy/README.md @@ -18,7 +18,7 @@ You can choose how much Clippy is supposed to ~~annoy~~ help you by changing the | `clippy::style` | code that should be written in a more idiomatic way | **warn** | | `clippy::complexity` | code that does something simple but in a complex way | **warn** | | `clippy::perf` | code that can be written to run faster | **warn** | -| `clippy::pedantic` | lints which are rather strict or might have false positives | allow | +| `clippy::pedantic` | lints which are rather strict or have occasional false positives | allow | | `clippy::nursery` | new lints that are still under development | allow | | `clippy::cargo` | lints for the cargo manifest | allow | @@ -45,13 +45,13 @@ or in Travis CI. One way to use Clippy is by installing Clippy through rustup as a cargo subcommand. -#### Step 1: Install rustup +#### Step 1: Install Rustup -You can install [rustup](https://rustup.rs/) on supported platforms. This will help +You can install [Rustup](https://rustup.rs/) on supported platforms. This will help us install Clippy and its dependencies. -If you already have rustup installed, update to ensure you have the latest -rustup and compiler: +If you already have Rustup installed, update to ensure you have the latest +Rustup and compiler: ```terminal rustup update diff --git a/src/tools/clippy/clippy_dev/Cargo.toml b/src/tools/clippy/clippy_dev/Cargo.toml index 0fae8c7b9a..4a13a45240 100644 --- a/src/tools/clippy/clippy_dev/Cargo.toml +++ b/src/tools/clippy/clippy_dev/Cargo.toml @@ -1,16 +1,16 @@ [package] name = "clippy_dev" version = "0.0.1" -edition = "2018" +edition = "2021" [dependencies] bytecount = "0.6" clap = "2.33" -itertools = "0.9" +itertools = "0.10" opener = "0.5" -regex = "1" +regex = "1.5" shell-escape = "0.1" -walkdir = "2" +walkdir = "2.3" [features] deny-warnings = [] diff --git a/src/tools/clippy/clippy_dev/src/bless.rs b/src/tools/clippy/clippy_dev/src/bless.rs index c4fa0a9aca..daf0fcc993 100644 --- a/src/tools/clippy/clippy_dev/src/bless.rs +++ b/src/tools/clippy/clippy_dev/src/bless.rs @@ -1,7 +1,6 @@ //! `bless` updates the reference files in the repo with changed output files //! from the last test run. -use std::env; use std::ffi::OsStr; use std::fs; use std::lazy::SyncLazy; @@ -10,17 +9,9 @@ use walkdir::WalkDir; use crate::clippy_project_root; -// NOTE: this is duplicated with tests/cargo/mod.rs What to do? -pub static CARGO_TARGET_DIR: SyncLazy = SyncLazy::new(|| match env::var_os("CARGO_TARGET_DIR") { - Some(v) => v.into(), - None => env::current_dir().unwrap().join("target"), -}); - static CLIPPY_BUILD_TIME: SyncLazy> = SyncLazy::new(|| { - let profile = env::var("PROFILE").unwrap_or_else(|_| "debug".to_string()); - let mut path = PathBuf::from(&**CARGO_TARGET_DIR); - path.push(profile); - path.push("cargo-clippy"); + let mut path = std::env::current_exe().unwrap(); + path.set_file_name("cargo-clippy"); fs::metadata(path).ok()?.modified().ok() }); @@ -94,10 +85,7 @@ fn updated_since_clippy_build(path: &Path) -> Option { } fn build_dir() -> PathBuf { - let profile = env::var("PROFILE").unwrap_or_else(|_| "debug".to_string()); - let mut path = PathBuf::new(); - path.push(CARGO_TARGET_DIR.clone()); - path.push(profile); - path.push("test_build_base"); + let mut path = std::env::current_exe().unwrap(); + path.set_file_name("test"); path } diff --git a/src/tools/clippy/clippy_dev/src/lib.rs b/src/tools/clippy/clippy_dev/src/lib.rs index 72bdaf8d59..5538f62c8e 100644 --- a/src/tools/clippy/clippy_dev/src/lib.rs +++ b/src/tools/clippy/clippy_dev/src/lib.rs @@ -3,340 +3,15 @@ // warn on lints, that are included in `rust-lang/rust`s bootstrap #![warn(rust_2018_idioms, unused_lifetimes)] -use itertools::Itertools; -use regex::Regex; -use std::collections::HashMap; -use std::ffi::OsStr; -use std::fs; -use std::lazy::SyncLazy; -use std::path::{Path, PathBuf}; -use walkdir::WalkDir; +use std::path::PathBuf; pub mod bless; pub mod fmt; pub mod new_lint; pub mod serve; pub mod setup; -pub mod stderr_length_check; pub mod update_lints; -static DEC_CLIPPY_LINT_RE: SyncLazy = SyncLazy::new(|| { - Regex::new( - r#"(?x) - declare_clippy_lint!\s*[\{(] - (?:\s+///.*)* - \s+pub\s+(?P[A-Z_][A-Z_0-9]*)\s*,\s* - (?P[a-z_]+)\s*,\s* - "(?P(?:[^"\\]+|\\(?s).(?-s))*)"\s*[})] -"#, - ) - .unwrap() -}); - -static DEC_DEPRECATED_LINT_RE: SyncLazy = SyncLazy::new(|| { - Regex::new( - r#"(?x) - declare_deprecated_lint!\s*[{(]\s* - (?:\s+///.*)* - \s+pub\s+(?P[A-Z_][A-Z_0-9]*)\s*,\s* - "(?P(?:[^"\\]+|\\(?s).(?-s))*)"\s*[})] -"#, - ) - .unwrap() -}); -static NL_ESCAPE_RE: SyncLazy = SyncLazy::new(|| Regex::new(r#"\\\n\s*"#).unwrap()); - -pub static DOCS_LINK: &str = "https://rust-lang.github.io/rust-clippy/master/index.html"; - -/// Lint data parsed from the Clippy source code. -#[derive(Clone, PartialEq, Debug)] -pub struct Lint { - pub name: String, - pub group: String, - pub desc: String, - pub deprecation: Option, - pub module: String, -} - -impl Lint { - #[must_use] - pub fn new(name: &str, group: &str, desc: &str, deprecation: Option<&str>, module: &str) -> Self { - Self { - name: name.to_lowercase(), - group: group.to_string(), - desc: NL_ESCAPE_RE.replace(&desc.replace("\\\"", "\""), "").to_string(), - deprecation: deprecation.map(ToString::to_string), - module: module.to_string(), - } - } - - /// Returns all non-deprecated lints and non-internal lints - #[must_use] - pub fn usable_lints(lints: &[Self]) -> Vec { - lints - .iter() - .filter(|l| l.deprecation.is_none() && !l.group.starts_with("internal")) - .cloned() - .collect() - } - - /// Returns all internal lints (not `internal_warn` lints) - #[must_use] - pub fn internal_lints(lints: &[Self]) -> Vec { - lints.iter().filter(|l| l.group == "internal").cloned().collect() - } - - /// Returns all deprecated lints - #[must_use] - pub fn deprecated_lints(lints: &[Self]) -> Vec { - lints.iter().filter(|l| l.deprecation.is_some()).cloned().collect() - } - - /// Returns the lints in a `HashMap`, grouped by the different lint groups - #[must_use] - pub fn by_lint_group(lints: impl Iterator) -> HashMap> { - lints.map(|lint| (lint.group.to_string(), lint)).into_group_map() - } -} - -/// Generates the Vec items for `register_lint_group` calls in `clippy_lints/src/lib.rs`. -#[must_use] -pub fn gen_lint_group_list<'a>(lints: impl Iterator) -> Vec { - lints - .map(|l| format!(" LintId::of({}::{}),", l.module, l.name.to_uppercase())) - .sorted() - .collect::>() -} - -/// Generates the `pub mod module_name` list in `clippy_lints/src/lib.rs`. -#[must_use] -pub fn gen_modules_list<'a>(lints: impl Iterator) -> Vec { - lints - .map(|l| &l.module) - .unique() - .map(|module| format!("mod {};", module)) - .sorted() - .collect::>() -} - -/// Generates the list of lint links at the bottom of the README -#[must_use] -pub fn gen_changelog_lint_list<'a>(lints: impl Iterator) -> Vec { - lints - .sorted_by_key(|l| &l.name) - .map(|l| format!("[`{}`]: {}#{}", l.name, DOCS_LINK, l.name)) - .collect() -} - -/// Generates the `register_removed` code in `./clippy_lints/src/lib.rs`. -#[must_use] -pub fn gen_deprecated<'a>(lints: impl Iterator) -> Vec { - lints - .flat_map(|l| { - l.deprecation - .clone() - .map(|depr_text| { - vec![ - " store.register_removed(".to_string(), - format!(" \"clippy::{}\",", l.name), - format!(" \"{}\",", depr_text), - " );".to_string(), - ] - }) - .expect("only deprecated lints should be passed") - }) - .collect::>() -} - -#[must_use] -pub fn gen_register_lint_list<'a>( - internal_lints: impl Iterator, - usable_lints: impl Iterator, -) -> Vec { - let header = " store.register_lints(&[".to_string(); - let footer = " ]);".to_string(); - let internal_lints = internal_lints - .sorted_by_key(|l| format!(" {}::{},", l.module, l.name.to_uppercase())) - .map(|l| { - format!( - " #[cfg(feature = \"internal-lints\")]\n {}::{},", - l.module, - l.name.to_uppercase() - ) - }); - let other_lints = usable_lints - .sorted_by_key(|l| format!(" {}::{},", l.module, l.name.to_uppercase())) - .map(|l| format!(" {}::{},", l.module, l.name.to_uppercase())) - .sorted(); - let mut lint_list = vec![header]; - lint_list.extend(internal_lints); - lint_list.extend(other_lints); - lint_list.push(footer); - lint_list -} - -/// Gathers all files in `src/clippy_lints` and gathers all lints inside -pub fn gather_all() -> impl Iterator { - lint_files().flat_map(|f| gather_from_file(&f)) -} - -fn gather_from_file(dir_entry: &walkdir::DirEntry) -> impl Iterator { - let content = fs::read_to_string(dir_entry.path()).unwrap(); - let path = dir_entry.path(); - let filename = path.file_stem().unwrap(); - let path_buf = path.with_file_name(filename); - let mut rel_path = path_buf - .strip_prefix(clippy_project_root().join("clippy_lints/src")) - .expect("only files in `clippy_lints/src` should be looked at"); - // If the lints are stored in mod.rs, we get the module name from - // the containing directory: - if filename == "mod" { - rel_path = rel_path.parent().unwrap(); - } - - let module = rel_path - .components() - .map(|c| c.as_os_str().to_str().unwrap()) - .collect::>() - .join("::"); - - parse_contents(&content, &module) -} - -fn parse_contents(content: &str, module: &str) -> impl Iterator { - let lints = DEC_CLIPPY_LINT_RE - .captures_iter(content) - .map(|m| Lint::new(&m["name"], &m["cat"], &m["desc"], None, module)); - let deprecated = DEC_DEPRECATED_LINT_RE - .captures_iter(content) - .map(|m| Lint::new(&m["name"], "Deprecated", &m["desc"], Some(&m["desc"]), module)); - // Removing the `.collect::>().into_iter()` causes some lifetime issues due to the map - lints.chain(deprecated).collect::>().into_iter() -} - -/// Collects all .rs files in the `clippy_lints/src` directory -fn lint_files() -> impl Iterator { - // We use `WalkDir` instead of `fs::read_dir` here in order to recurse into subdirectories. - // Otherwise we would not collect all the lints, for example in `clippy_lints/src/methods/`. - let path = clippy_project_root().join("clippy_lints/src"); - WalkDir::new(path) - .into_iter() - .filter_map(Result::ok) - .filter(|f| f.path().extension() == Some(OsStr::new("rs"))) -} - -/// Whether a file has had its text changed or not -#[derive(PartialEq, Debug)] -pub struct FileChange { - pub changed: bool, - pub new_lines: String, -} - -/// Replaces a region in a file delimited by two lines matching regexes. -/// -/// `path` is the relative path to the file on which you want to perform the replacement. -/// -/// See `replace_region_in_text` for documentation of the other options. -/// -/// # Panics -/// -/// Panics if the path could not read or then written -pub fn replace_region_in_file( - path: &Path, - start: &str, - end: &str, - replace_start: bool, - write_back: bool, - replacements: F, -) -> FileChange -where - F: FnOnce() -> Vec, -{ - let contents = fs::read_to_string(path).unwrap_or_else(|e| panic!("Cannot read from {}: {}", path.display(), e)); - let file_change = replace_region_in_text(&contents, start, end, replace_start, replacements); - - if write_back { - if let Err(e) = fs::write(path, file_change.new_lines.as_bytes()) { - panic!("Cannot write to {}: {}", path.display(), e); - } - } - file_change -} - -/// Replaces a region in a text delimited by two lines matching regexes. -/// -/// * `text` is the input text on which you want to perform the replacement -/// * `start` is a `&str` that describes the delimiter line before the region you want to replace. -/// As the `&str` will be converted to a `Regex`, this can contain regex syntax, too. -/// * `end` is a `&str` that describes the delimiter line until where the replacement should happen. -/// As the `&str` will be converted to a `Regex`, this can contain regex syntax, too. -/// * If `replace_start` is true, the `start` delimiter line is replaced as well. The `end` -/// delimiter line is never replaced. -/// * `replacements` is a closure that has to return a `Vec` which contains the new text. -/// -/// If you want to perform the replacement on files instead of already parsed text, -/// use `replace_region_in_file`. -/// -/// # Example -/// -/// ``` -/// let the_text = "replace_start\nsome text\nthat will be replaced\nreplace_end"; -/// let result = -/// clippy_dev::replace_region_in_text(the_text, "replace_start", "replace_end", false, || { -/// vec!["a different".to_string(), "text".to_string()] -/// }) -/// .new_lines; -/// assert_eq!("replace_start\na different\ntext\nreplace_end", result); -/// ``` -/// -/// # Panics -/// -/// Panics if start or end is not valid regex -pub fn replace_region_in_text(text: &str, start: &str, end: &str, replace_start: bool, replacements: F) -> FileChange -where - F: FnOnce() -> Vec, -{ - let replace_it = replacements(); - let mut in_old_region = false; - let mut found = false; - let mut new_lines = vec![]; - let start = Regex::new(start).unwrap(); - let end = Regex::new(end).unwrap(); - - for line in text.lines() { - if in_old_region { - if end.is_match(line) { - in_old_region = false; - new_lines.extend(replace_it.clone()); - new_lines.push(line.to_string()); - } - } else if start.is_match(line) { - if !replace_start { - new_lines.push(line.to_string()); - } - in_old_region = true; - found = true; - } else { - new_lines.push(line.to_string()); - } - } - - if !found { - // This happens if the provided regex in `clippy_dev/src/main.rs` does not match in the - // given text or file. Most likely this is an error on the programmer's side and the Regex - // is incorrect. - eprintln!("error: regex \n{:?}\ndoesn't match. You may have to update it.", start); - std::process::exit(1); - } - - let mut new_lines = new_lines.join("\n"); - if text.ends_with('\n') { - new_lines.push('\n'); - } - let changed = new_lines != text; - FileChange { changed, new_lines } -} - /// Returns the path to the Clippy project directory /// /// # Panics @@ -361,200 +36,3 @@ pub fn clippy_project_root() -> PathBuf { } panic!("error: Can't determine root of project. Please run inside a Clippy working dir."); } - -#[test] -fn test_parse_contents() { - let result: Vec = parse_contents( - r#" -declare_clippy_lint! { - pub PTR_ARG, - style, - "really long \ - text" -} - -declare_clippy_lint!{ - pub DOC_MARKDOWN, - pedantic, - "single line" -} - -/// some doc comment -declare_deprecated_lint! { - pub SHOULD_ASSERT_EQ, - "`assert!()` will be more flexible with RFC 2011" -} - "#, - "module_name", - ) - .collect(); - - let expected = vec![ - Lint::new("ptr_arg", "style", "really long text", None, "module_name"), - Lint::new("doc_markdown", "pedantic", "single line", None, "module_name"), - Lint::new( - "should_assert_eq", - "Deprecated", - "`assert!()` will be more flexible with RFC 2011", - Some("`assert!()` will be more flexible with RFC 2011"), - "module_name", - ), - ]; - assert_eq!(expected, result); -} - -#[test] -fn test_replace_region() { - let text = "\nabc\n123\n789\ndef\nghi"; - let expected = FileChange { - changed: true, - new_lines: "\nabc\nhello world\ndef\nghi".to_string(), - }; - let result = replace_region_in_text(text, r#"^\s*abc$"#, r#"^\s*def"#, false, || { - vec!["hello world".to_string()] - }); - assert_eq!(expected, result); -} - -#[test] -fn test_replace_region_with_start() { - let text = "\nabc\n123\n789\ndef\nghi"; - let expected = FileChange { - changed: true, - new_lines: "\nhello world\ndef\nghi".to_string(), - }; - let result = replace_region_in_text(text, r#"^\s*abc$"#, r#"^\s*def"#, true, || { - vec!["hello world".to_string()] - }); - assert_eq!(expected, result); -} - -#[test] -fn test_replace_region_no_changes() { - let text = "123\n456\n789"; - let expected = FileChange { - changed: false, - new_lines: "123\n456\n789".to_string(), - }; - let result = replace_region_in_text(text, r#"^\s*123$"#, r#"^\s*456"#, false, Vec::new); - assert_eq!(expected, result); -} - -#[test] -fn test_usable_lints() { - let lints = vec![ - Lint::new("should_assert_eq", "Deprecated", "abc", Some("Reason"), "module_name"), - Lint::new("should_assert_eq2", "Not Deprecated", "abc", None, "module_name"), - Lint::new("should_assert_eq2", "internal", "abc", None, "module_name"), - Lint::new("should_assert_eq2", "internal_style", "abc", None, "module_name"), - ]; - let expected = vec![Lint::new( - "should_assert_eq2", - "Not Deprecated", - "abc", - None, - "module_name", - )]; - assert_eq!(expected, Lint::usable_lints(&lints)); -} - -#[test] -fn test_by_lint_group() { - let lints = vec![ - Lint::new("should_assert_eq", "group1", "abc", None, "module_name"), - Lint::new("should_assert_eq2", "group2", "abc", None, "module_name"), - Lint::new("incorrect_match", "group1", "abc", None, "module_name"), - ]; - let mut expected: HashMap> = HashMap::new(); - expected.insert( - "group1".to_string(), - vec![ - Lint::new("should_assert_eq", "group1", "abc", None, "module_name"), - Lint::new("incorrect_match", "group1", "abc", None, "module_name"), - ], - ); - expected.insert( - "group2".to_string(), - vec![Lint::new("should_assert_eq2", "group2", "abc", None, "module_name")], - ); - assert_eq!(expected, Lint::by_lint_group(lints.into_iter())); -} - -#[test] -fn test_gen_changelog_lint_list() { - let lints = vec![ - Lint::new("should_assert_eq", "group1", "abc", None, "module_name"), - 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()), - ]; - assert_eq!(expected, gen_changelog_lint_list(lints.iter())); -} - -#[test] -fn test_gen_deprecated() { - let lints = vec![ - Lint::new( - "should_assert_eq", - "group1", - "abc", - Some("has been superseded by should_assert_eq2"), - "module_name", - ), - Lint::new( - "another_deprecated", - "group2", - "abc", - Some("will be removed"), - "module_name", - ), - ]; - let expected: Vec = vec![ - " store.register_removed(", - " \"clippy::should_assert_eq\",", - " \"has been superseded by should_assert_eq2\",", - " );", - " store.register_removed(", - " \"clippy::another_deprecated\",", - " \"will be removed\",", - " );", - ] - .into_iter() - .map(String::from) - .collect(); - assert_eq!(expected, gen_deprecated(lints.iter())); -} - -#[test] -#[should_panic] -fn test_gen_deprecated_fail() { - let lints = vec![Lint::new("should_assert_eq2", "group2", "abc", None, "module_name")]; - let _deprecated_lints = gen_deprecated(lints.iter()); -} - -#[test] -fn test_gen_modules_list() { - let lints = vec![ - Lint::new("should_assert_eq", "group1", "abc", None, "module_name"), - Lint::new("incorrect_stuff", "group3", "abc", None, "another_module"), - ]; - let expected = vec!["mod another_module;".to_string(), "mod module_name;".to_string()]; - assert_eq!(expected, gen_modules_list(lints.iter())); -} - -#[test] -fn test_gen_lint_group_list() { - let lints = vec![ - Lint::new("abc", "group1", "abc", None, "module_name"), - Lint::new("should_assert_eq", "group1", "abc", None, "module_name"), - Lint::new("internal", "internal_style", "abc", None, "module_name"), - ]; - let expected = vec![ - " LintId::of(module_name::ABC),".to_string(), - " LintId::of(module_name::INTERNAL),".to_string(), - " LintId::of(module_name::SHOULD_ASSERT_EQ),".to_string(), - ]; - assert_eq!(expected, gen_lint_group_list(lints.iter())); -} diff --git a/src/tools/clippy/clippy_dev/src/main.rs b/src/tools/clippy/clippy_dev/src/main.rs index ff324ff6ee..8fdeba9842 100644 --- a/src/tools/clippy/clippy_dev/src/main.rs +++ b/src/tools/clippy/clippy_dev/src/main.rs @@ -3,7 +3,7 @@ #![warn(rust_2018_idioms, unused_lifetimes)] use clap::{App, AppSettings, Arg, ArgMatches, SubCommand}; -use clippy_dev::{bless, fmt, new_lint, serve, setup, stderr_length_check, update_lints}; +use clippy_dev::{bless, fmt, new_lint, serve, setup, update_lints}; fn main() { let matches = get_clap_config(); @@ -33,9 +33,6 @@ fn main() { Err(e) => eprintln!("Unable to create lint: {}", e), } }, - ("limit_stderr_length", _) => { - stderr_length_check::check(); - }, ("setup", Some(sub_command)) => match sub_command.subcommand() { ("intellij", Some(matches)) => setup::intellij::setup_rustc_src( matches @@ -152,10 +149,6 @@ fn get_clap_config<'a>() -> ArgMatches<'a> { .takes_value(true), ), ) - .subcommand( - SubCommand::with_name("limit_stderr_length") - .about("Ensures that stderr files do not grow longer than a certain amount of lines."), - ) .subcommand( SubCommand::with_name("setup") .about("Support for setting up your personal development environment") diff --git a/src/tools/clippy/clippy_dev/src/stderr_length_check.rs b/src/tools/clippy/clippy_dev/src/stderr_length_check.rs deleted file mode 100644 index e02b6f7da5..0000000000 --- a/src/tools/clippy/clippy_dev/src/stderr_length_check.rs +++ /dev/null @@ -1,51 +0,0 @@ -use crate::clippy_project_root; -use std::ffi::OsStr; -use std::fs; -use std::path::{Path, PathBuf}; -use walkdir::WalkDir; - -// The maximum length allowed for stderr files. -// -// We limit this because small files are easier to deal with than bigger files. -const LENGTH_LIMIT: usize = 200; - -pub fn check() { - let exceeding_files: Vec<_> = exceeding_stderr_files(); - - if !exceeding_files.is_empty() { - eprintln!("Error: stderr files exceeding limit of {} lines:", LENGTH_LIMIT); - for (path, count) in exceeding_files { - println!("{}: {}", path.display(), count); - } - std::process::exit(1); - } -} - -fn exceeding_stderr_files() -> Vec<(PathBuf, usize)> { - // We use `WalkDir` instead of `fs::read_dir` here in order to recurse into subdirectories. - WalkDir::new(clippy_project_root().join("tests/ui")) - .into_iter() - .filter_map(Result::ok) - .filter(|f| !f.file_type().is_dir()) - .filter_map(|e| { - let p = e.into_path(); - let count = count_linenumbers(&p); - if p.extension() == Some(OsStr::new("stderr")) && count > LENGTH_LIMIT { - Some((p, count)) - } else { - None - } - }) - .collect() -} - -#[must_use] -fn count_linenumbers(filepath: &Path) -> usize { - match fs::read(filepath) { - Ok(content) => bytecount::count(&content, b'\n'), - Err(e) => { - eprintln!("Failed to read file: {}", e); - 0 - }, - } -} diff --git a/src/tools/clippy/clippy_dev/src/update_lints.rs b/src/tools/clippy/clippy_dev/src/update_lints.rs index db467c26f1..10d859988f 100644 --- a/src/tools/clippy/clippy_dev/src/update_lints.rs +++ b/src/tools/clippy/clippy_dev/src/update_lints.rs @@ -1,8 +1,45 @@ -use crate::{ - gather_all, gen_changelog_lint_list, gen_deprecated, gen_lint_group_list, gen_modules_list, gen_register_lint_list, - replace_region_in_file, Lint, DOCS_LINK, -}; +use itertools::Itertools; +use regex::Regex; +use std::collections::HashMap; +use std::ffi::OsStr; +use std::fs; +use std::lazy::SyncLazy; use std::path::Path; +use walkdir::WalkDir; + +use crate::clippy_project_root; + +const GENERATED_FILE_COMMENT: &str = "// This file was generated by `cargo dev update_lints`.\n\ + // Use that command to update this file and do not edit by hand.\n\ + // Manual edits will be overwritten.\n\n"; + +static DEC_CLIPPY_LINT_RE: SyncLazy = SyncLazy::new(|| { + Regex::new( + r#"(?x) + declare_clippy_lint!\s*[\{(] + (?:\s+///.*)* + \s+pub\s+(?P[A-Z_][A-Z_0-9]*)\s*,\s* + (?P[a-z_]+)\s*,\s* + "(?P(?:[^"\\]+|\\(?s).(?-s))*)"\s*[})] +"#, + ) + .unwrap() +}); + +static DEC_DEPRECATED_LINT_RE: SyncLazy = SyncLazy::new(|| { + Regex::new( + r#"(?x) + declare_deprecated_lint!\s*[{(]\s* + (?:\s+///.*)* + \s+pub\s+(?P[A-Z_][A-Z_0-9]*)\s*,\s* + "(?P(?:[^"\\]+|\\(?s).(?-s))*)"\s*[})] +"#, + ) + .unwrap() +}); +static NL_ESCAPE_RE: SyncLazy = SyncLazy::new(|| Regex::new(r#"\\\n\s*"#).unwrap()); + +static DOCS_LINK: &str = "https://rust-lang.github.io/rust-clippy/master/index.html"; #[derive(Clone, Copy, PartialEq)] pub enum UpdateMode { @@ -10,6 +47,15 @@ pub enum UpdateMode { Change, } +/// Runs the `update_lints` command. +/// +/// This updates various generated values from the lint source code. +/// +/// `update_mode` indicates if the files should be updated or if updates should be checked for. +/// +/// # Panics +/// +/// Panics if a file path could not read from or then written to #[allow(clippy::too_many_lines)] pub fn run(update_mode: UpdateMode) { let lint_list: Vec = gather_all().collect(); @@ -52,26 +98,7 @@ pub fn run(update_mode: UpdateMode) { ) .changed; - file_change |= replace_region_in_file( - Path::new("clippy_lints/src/lib.rs"), - "begin deprecated lints", - "end deprecated lints", - false, - update_mode == UpdateMode::Change, - || gen_deprecated(deprecated_lints.iter()), - ) - .changed; - - file_change |= replace_region_in_file( - Path::new("clippy_lints/src/lib.rs"), - "begin register lints", - "end register lints", - false, - update_mode == UpdateMode::Change, - || gen_register_lint_list(internal_lints.iter(), usable_lints.iter()), - ) - .changed; - + // This has to be in lib.rs, otherwise rustfmt doesn't work file_change |= replace_region_in_file( Path::new("clippy_lints/src/lib.rs"), "begin lints modules", @@ -82,46 +109,37 @@ pub fn run(update_mode: UpdateMode) { ) .changed; - // Generate lists of lints in the clippy::all lint group - file_change |= replace_region_in_file( - Path::new("clippy_lints/src/lib.rs"), - r#"store.register_group\(true, "clippy::all""#, - r#"\]\);"#, - false, - update_mode == UpdateMode::Change, - || { - // clippy::all should only include the following lint groups: - let all_group_lints = usable_lints.iter().filter(|l| { - matches!( - &*l.group, - "correctness" | "suspicious" | "style" | "complexity" | "perf" - ) - }); - - gen_lint_group_list(all_group_lints) - }, - ) - .changed; - - // Generate the list of lints for all other lint groups - for (lint_group, lints) in Lint::by_lint_group(usable_lints.into_iter().chain(internal_lints)) { - file_change |= replace_region_in_file( - Path::new("clippy_lints/src/lib.rs"), - &format!("store.register_group\\(true, \"clippy::{}\"", lint_group), - r#"\]\);"#, - false, - update_mode == UpdateMode::Change, - || gen_lint_group_list(lints.iter()), - ) - .changed; + if file_change && update_mode == UpdateMode::Check { + exit_with_failure(); } - if update_mode == UpdateMode::Check && file_change { - println!( - "Not all lints defined properly. \ - Please run `cargo dev update_lints` to make sure all lints are defined properly." + process_file( + "clippy_lints/src/lib.register_lints.rs", + update_mode, + &gen_register_lint_list(internal_lints.iter(), usable_lints.iter()), + ); + process_file( + "clippy_lints/src/lib.deprecated.rs", + update_mode, + &gen_deprecated(deprecated_lints.iter()), + ); + + let all_group_lints = usable_lints.iter().filter(|l| { + matches!( + &*l.group, + "correctness" | "suspicious" | "style" | "complexity" | "perf" + ) + }); + let content = gen_lint_group_list("all", all_group_lints); + process_file("clippy_lints/src/lib.register_all.rs", update_mode, &content); + + for (lint_group, lints) in Lint::by_lint_group(usable_lints.into_iter().chain(internal_lints)) { + let content = gen_lint_group_list(&lint_group, lints.iter()); + process_file( + &format!("clippy_lints/src/lib.register_{}.rs", lint_group), + update_mode, + &content, ); - std::process::exit(1); } } @@ -150,3 +168,538 @@ pub fn print_lints() { fn round_to_fifty(count: usize) -> usize { count / 50 * 50 } + +fn process_file(path: impl AsRef, update_mode: UpdateMode, content: &str) { + if update_mode == UpdateMode::Check { + let old_content = + fs::read_to_string(&path).unwrap_or_else(|e| panic!("Cannot read from {}: {}", path.as_ref().display(), e)); + if content != old_content { + exit_with_failure(); + } + } else { + fs::write(&path, content.as_bytes()) + .unwrap_or_else(|e| panic!("Cannot write to {}: {}", path.as_ref().display(), e)); + } +} + +fn exit_with_failure() { + println!( + "Not all lints defined properly. \ + Please run `cargo dev update_lints` to make sure all lints are defined properly." + ); + std::process::exit(1); +} + +/// Lint data parsed from the Clippy source code. +#[derive(Clone, PartialEq, Debug)] +struct Lint { + name: String, + group: String, + desc: String, + deprecation: Option, + module: String, +} + +impl Lint { + #[must_use] + fn new(name: &str, group: &str, desc: &str, deprecation: Option<&str>, module: &str) -> Self { + Self { + name: name.to_lowercase(), + group: group.to_string(), + desc: NL_ESCAPE_RE.replace(&desc.replace("\\\"", "\""), "").to_string(), + deprecation: deprecation.map(ToString::to_string), + module: module.to_string(), + } + } + + /// Returns all non-deprecated lints and non-internal lints + #[must_use] + fn usable_lints(lints: &[Self]) -> Vec { + lints + .iter() + .filter(|l| l.deprecation.is_none() && !l.group.starts_with("internal")) + .cloned() + .collect() + } + + /// Returns all internal lints (not `internal_warn` lints) + #[must_use] + fn internal_lints(lints: &[Self]) -> Vec { + lints.iter().filter(|l| l.group == "internal").cloned().collect() + } + + /// Returns all deprecated lints + #[must_use] + fn deprecated_lints(lints: &[Self]) -> Vec { + lints.iter().filter(|l| l.deprecation.is_some()).cloned().collect() + } + + /// Returns the lints in a `HashMap`, grouped by the different lint groups + #[must_use] + fn by_lint_group(lints: impl Iterator) -> HashMap> { + lints.map(|lint| (lint.group.to_string(), lint)).into_group_map() + } +} + +/// Generates the code for registering a group +fn gen_lint_group_list<'a>(group_name: &str, lints: impl Iterator) -> String { + let mut details: Vec<_> = lints.map(|l| (&l.module, l.name.to_uppercase())).collect(); + details.sort_unstable(); + + let mut output = GENERATED_FILE_COMMENT.to_string(); + + output.push_str(&format!( + "store.register_group(true, \"clippy::{0}\", Some(\"clippy_{0}\"), vec![\n", + group_name + )); + for (module, name) in details { + output.push_str(&format!(" LintId::of({}::{}),\n", module, name)); + } + output.push_str("])\n"); + + output +} + +/// Generates the module declarations for `lints` +#[must_use] +fn gen_modules_list<'a>(lints: impl Iterator) -> Vec { + lints + .map(|l| &l.module) + .unique() + .map(|module| format!("mod {};", module)) + .sorted() + .collect::>() +} + +/// Generates the list of lint links at the bottom of the CHANGELOG +#[must_use] +fn gen_changelog_lint_list<'a>(lints: impl Iterator) -> Vec { + lints + .sorted_by_key(|l| &l.name) + .map(|l| format!("[`{}`]: {}#{}", l.name, DOCS_LINK, l.name)) + .collect() +} + +/// Generates the `register_removed` code +#[must_use] +fn gen_deprecated<'a>(lints: impl Iterator) -> String { + let mut output = GENERATED_FILE_COMMENT.to_string(); + output.push_str("{\n"); + for Lint { name, deprecation, .. } in lints { + output.push_str(&format!( + concat!( + " store.register_removed(\n", + " \"clippy::{}\",\n", + " \"{}\",\n", + " );\n" + ), + name, + deprecation.as_ref().expect("`lints` are deprecated") + )); + } + output.push_str("}\n"); + + output +} + +/// Generates the code for registering lints +#[must_use] +fn gen_register_lint_list<'a>( + internal_lints: impl Iterator, + usable_lints: impl Iterator, +) -> String { + let mut details: Vec<_> = internal_lints + .map(|l| (false, &l.module, l.name.to_uppercase())) + .chain(usable_lints.map(|l| (true, &l.module, l.name.to_uppercase()))) + .collect(); + details.sort_unstable(); + + let mut output = GENERATED_FILE_COMMENT.to_string(); + output.push_str("store.register_lints(&[\n"); + + for (is_public, module_name, lint_name) in details { + if !is_public { + output.push_str(" #[cfg(feature = \"internal-lints\")]\n"); + } + output.push_str(&format!(" {}::{},\n", module_name, lint_name)); + } + output.push_str("])\n"); + + output +} + +/// Gathers all files in `src/clippy_lints` and gathers all lints inside +fn gather_all() -> impl Iterator { + lint_files().flat_map(|f| gather_from_file(&f)) +} + +fn gather_from_file(dir_entry: &walkdir::DirEntry) -> impl Iterator { + let content = fs::read_to_string(dir_entry.path()).unwrap(); + let path = dir_entry.path(); + let filename = path.file_stem().unwrap(); + let path_buf = path.with_file_name(filename); + let mut rel_path = path_buf + .strip_prefix(clippy_project_root().join("clippy_lints/src")) + .expect("only files in `clippy_lints/src` should be looked at"); + // If the lints are stored in mod.rs, we get the module name from + // the containing directory: + if filename == "mod" { + rel_path = rel_path.parent().unwrap(); + } + + let module = rel_path + .components() + .map(|c| c.as_os_str().to_str().unwrap()) + .collect::>() + .join("::"); + + parse_contents(&content, &module) +} + +fn parse_contents(content: &str, module: &str) -> impl Iterator { + let lints = DEC_CLIPPY_LINT_RE + .captures_iter(content) + .map(|m| Lint::new(&m["name"], &m["cat"], &m["desc"], None, module)); + let deprecated = DEC_DEPRECATED_LINT_RE + .captures_iter(content) + .map(|m| Lint::new(&m["name"], "Deprecated", &m["desc"], Some(&m["desc"]), module)); + // Removing the `.collect::>().into_iter()` causes some lifetime issues due to the map + lints.chain(deprecated).collect::>().into_iter() +} + +/// Collects all .rs files in the `clippy_lints/src` directory +fn lint_files() -> impl Iterator { + // We use `WalkDir` instead of `fs::read_dir` here in order to recurse into subdirectories. + // Otherwise we would not collect all the lints, for example in `clippy_lints/src/methods/`. + let path = clippy_project_root().join("clippy_lints/src"); + WalkDir::new(path) + .into_iter() + .filter_map(Result::ok) + .filter(|f| f.path().extension() == Some(OsStr::new("rs"))) +} + +/// Whether a file has had its text changed or not +#[derive(PartialEq, Debug)] +struct FileChange { + changed: bool, + new_lines: String, +} + +/// Replaces a region in a file delimited by two lines matching regexes. +/// +/// `path` is the relative path to the file on which you want to perform the replacement. +/// +/// See `replace_region_in_text` for documentation of the other options. +/// +/// # Panics +/// +/// Panics if the path could not read or then written +fn replace_region_in_file( + path: &Path, + start: &str, + end: &str, + replace_start: bool, + write_back: bool, + replacements: F, +) -> FileChange +where + F: FnOnce() -> Vec, +{ + let contents = fs::read_to_string(path).unwrap_or_else(|e| panic!("Cannot read from {}: {}", path.display(), e)); + let file_change = replace_region_in_text(&contents, start, end, replace_start, replacements); + + if write_back { + if let Err(e) = fs::write(path, file_change.new_lines.as_bytes()) { + panic!("Cannot write to {}: {}", path.display(), e); + } + } + file_change +} + +/// Replaces a region in a text delimited by two lines matching regexes. +/// +/// * `text` is the input text on which you want to perform the replacement +/// * `start` is a `&str` that describes the delimiter line before the region you want to replace. +/// As the `&str` will be converted to a `Regex`, this can contain regex syntax, too. +/// * `end` is a `&str` that describes the delimiter line until where the replacement should happen. +/// As the `&str` will be converted to a `Regex`, this can contain regex syntax, too. +/// * If `replace_start` is true, the `start` delimiter line is replaced as well. The `end` +/// delimiter line is never replaced. +/// * `replacements` is a closure that has to return a `Vec` which contains the new text. +/// +/// If you want to perform the replacement on files instead of already parsed text, +/// use `replace_region_in_file`. +/// +/// # Example +/// +/// ```ignore +/// let the_text = "replace_start\nsome text\nthat will be replaced\nreplace_end"; +/// let result = +/// replace_region_in_text(the_text, "replace_start", "replace_end", false, || { +/// vec!["a different".to_string(), "text".to_string()] +/// }) +/// .new_lines; +/// assert_eq!("replace_start\na different\ntext\nreplace_end", result); +/// ``` +/// +/// # Panics +/// +/// Panics if start or end is not valid regex +fn replace_region_in_text(text: &str, start: &str, end: &str, replace_start: bool, replacements: F) -> FileChange +where + F: FnOnce() -> Vec, +{ + let replace_it = replacements(); + let mut in_old_region = false; + let mut found = false; + let mut new_lines = vec![]; + let start = Regex::new(start).unwrap(); + let end = Regex::new(end).unwrap(); + + for line in text.lines() { + if in_old_region { + if end.is_match(line) { + in_old_region = false; + new_lines.extend(replace_it.clone()); + new_lines.push(line.to_string()); + } + } else if start.is_match(line) { + if !replace_start { + new_lines.push(line.to_string()); + } + in_old_region = true; + found = true; + } else { + new_lines.push(line.to_string()); + } + } + + if !found { + // This happens if the provided regex in `clippy_dev/src/main.rs` does not match in the + // given text or file. Most likely this is an error on the programmer's side and the Regex + // is incorrect. + eprintln!("error: regex \n{:?}\ndoesn't match. You may have to update it.", start); + std::process::exit(1); + } + + let mut new_lines = new_lines.join("\n"); + if text.ends_with('\n') { + new_lines.push('\n'); + } + let changed = new_lines != text; + FileChange { changed, new_lines } +} + +#[test] +fn test_parse_contents() { + let result: Vec = parse_contents( + r#" +declare_clippy_lint! { + pub PTR_ARG, + style, + "really long \ + text" +} + +declare_clippy_lint!{ + pub DOC_MARKDOWN, + pedantic, + "single line" +} + +/// some doc comment +declare_deprecated_lint! { + pub SHOULD_ASSERT_EQ, + "`assert!()` will be more flexible with RFC 2011" +} + "#, + "module_name", + ) + .collect(); + + let expected = vec![ + Lint::new("ptr_arg", "style", "really long text", None, "module_name"), + Lint::new("doc_markdown", "pedantic", "single line", None, "module_name"), + Lint::new( + "should_assert_eq", + "Deprecated", + "`assert!()` will be more flexible with RFC 2011", + Some("`assert!()` will be more flexible with RFC 2011"), + "module_name", + ), + ]; + assert_eq!(expected, result); +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_replace_region() { + let text = "\nabc\n123\n789\ndef\nghi"; + let expected = FileChange { + changed: true, + new_lines: "\nabc\nhello world\ndef\nghi".to_string(), + }; + let result = replace_region_in_text(text, r#"^\s*abc$"#, r#"^\s*def"#, false, || { + vec!["hello world".to_string()] + }); + assert_eq!(expected, result); + } + + #[test] + fn test_replace_region_with_start() { + let text = "\nabc\n123\n789\ndef\nghi"; + let expected = FileChange { + changed: true, + new_lines: "\nhello world\ndef\nghi".to_string(), + }; + let result = replace_region_in_text(text, r#"^\s*abc$"#, r#"^\s*def"#, true, || { + vec!["hello world".to_string()] + }); + assert_eq!(expected, result); + } + + #[test] + fn test_replace_region_no_changes() { + let text = "123\n456\n789"; + let expected = FileChange { + changed: false, + new_lines: "123\n456\n789".to_string(), + }; + let result = replace_region_in_text(text, r#"^\s*123$"#, r#"^\s*456"#, false, Vec::new); + assert_eq!(expected, result); + } + + #[test] + fn test_usable_lints() { + let lints = vec![ + Lint::new("should_assert_eq", "Deprecated", "abc", Some("Reason"), "module_name"), + Lint::new("should_assert_eq2", "Not Deprecated", "abc", None, "module_name"), + Lint::new("should_assert_eq2", "internal", "abc", None, "module_name"), + Lint::new("should_assert_eq2", "internal_style", "abc", None, "module_name"), + ]; + let expected = vec![Lint::new( + "should_assert_eq2", + "Not Deprecated", + "abc", + None, + "module_name", + )]; + assert_eq!(expected, Lint::usable_lints(&lints)); + } + + #[test] + fn test_by_lint_group() { + let lints = vec![ + Lint::new("should_assert_eq", "group1", "abc", None, "module_name"), + Lint::new("should_assert_eq2", "group2", "abc", None, "module_name"), + Lint::new("incorrect_match", "group1", "abc", None, "module_name"), + ]; + let mut expected: HashMap> = HashMap::new(); + expected.insert( + "group1".to_string(), + vec![ + Lint::new("should_assert_eq", "group1", "abc", None, "module_name"), + Lint::new("incorrect_match", "group1", "abc", None, "module_name"), + ], + ); + expected.insert( + "group2".to_string(), + vec![Lint::new("should_assert_eq2", "group2", "abc", None, "module_name")], + ); + assert_eq!(expected, Lint::by_lint_group(lints.into_iter())); + } + + #[test] + fn test_gen_changelog_lint_list() { + let lints = vec![ + Lint::new("should_assert_eq", "group1", "abc", None, "module_name"), + 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()), + ]; + assert_eq!(expected, gen_changelog_lint_list(lints.iter())); + } + + #[test] + fn test_gen_deprecated() { + let lints = vec![ + Lint::new( + "should_assert_eq", + "group1", + "abc", + Some("has been superseded by should_assert_eq2"), + "module_name", + ), + Lint::new( + "another_deprecated", + "group2", + "abc", + Some("will be removed"), + "module_name", + ), + ]; + + let expected = GENERATED_FILE_COMMENT.to_string() + + &[ + "{", + " store.register_removed(", + " \"clippy::should_assert_eq\",", + " \"has been superseded by should_assert_eq2\",", + " );", + " store.register_removed(", + " \"clippy::another_deprecated\",", + " \"will be removed\",", + " );", + "}", + ] + .join("\n") + + "\n"; + + assert_eq!(expected, gen_deprecated(lints.iter())); + } + + #[test] + #[should_panic] + fn test_gen_deprecated_fail() { + let lints = vec![Lint::new("should_assert_eq2", "group2", "abc", None, "module_name")]; + let _deprecated_lints = gen_deprecated(lints.iter()); + } + + #[test] + fn test_gen_modules_list() { + let lints = vec![ + Lint::new("should_assert_eq", "group1", "abc", None, "module_name"), + Lint::new("incorrect_stuff", "group3", "abc", None, "another_module"), + ]; + let expected = vec!["mod another_module;".to_string(), "mod module_name;".to_string()]; + assert_eq!(expected, gen_modules_list(lints.iter())); + } + + #[test] + fn test_gen_lint_group_list() { + let lints = vec![ + Lint::new("abc", "group1", "abc", None, "module_name"), + Lint::new("should_assert_eq", "group1", "abc", None, "module_name"), + Lint::new("internal", "internal_style", "abc", None, "module_name"), + ]; + let expected = GENERATED_FILE_COMMENT.to_string() + + &[ + "store.register_group(true, \"clippy::group1\", Some(\"clippy_group1\"), vec![", + " LintId::of(module_name::ABC),", + " LintId::of(module_name::INTERNAL),", + " LintId::of(module_name::SHOULD_ASSERT_EQ),", + "])", + ] + .join("\n") + + "\n"; + + let result = gen_lint_group_list("group1", lints.iter()); + + assert_eq!(expected, result); + } +} diff --git a/src/tools/clippy/clippy_dummy/Cargo.toml b/src/tools/clippy/clippy_dummy/Cargo.toml index a1707bad5c..c206a1eb07 100644 --- a/src/tools/clippy/clippy_dummy/Cargo.toml +++ b/src/tools/clippy/clippy_dummy/Cargo.toml @@ -13,4 +13,4 @@ keywords = ["clippy", "lint", "plugin"] categories = ["development-tools", "development-tools::cargo-plugins"] [build-dependencies] -term = "0.6" +term = "0.7" diff --git a/src/tools/clippy/clippy_lints/Cargo.toml b/src/tools/clippy/clippy_lints/Cargo.toml index a3b92e1faa..7900dc6d04 100644 --- a/src/tools/clippy/clippy_lints/Cargo.toml +++ b/src/tools/clippy/clippy_lints/Cargo.toml @@ -1,33 +1,31 @@ [package] name = "clippy_lints" -# begin automatic update -version = "0.1.56" -# end automatic update +version = "0.1.57" description = "A bunch of helpful lints to avoid common pitfalls in Rust" repository = "https://github.com/rust-lang/rust-clippy" readme = "README.md" license = "MIT OR Apache-2.0" keywords = ["clippy", "lint", "plugin"] -edition = "2018" +edition = "2021" [dependencies] cargo_metadata = "0.12" clippy_utils = { path = "../clippy_utils" } -if_chain = "1.0.0" -itertools = "0.9" +if_chain = "1.0" +itertools = "0.10" pulldown-cmark = { version = "0.8", default-features = false } -quine-mc_cluskey = "0.2.2" +quine-mc_cluskey = "0.2" regex-syntax = "0.6" serde = { version = "1.0", features = ["derive"] } serde_json = { version = "1.0", optional = true } -toml = "0.5.3" +toml = "0.5" unicode-normalization = "0.1" -unicode-script = { version = "0.5.3", default-features = false } +unicode-script = { version = "0.5", default-features = false } semver = "0.11" -rustc-semver = "1.1.0" +rustc-semver = "1.1" # NOTE: cargo requires serde feat in its url dep # see -url = { version = "2.1.0", features = ["serde"] } +url = { version = "2.2", features = ["serde"] } [features] deny-warnings = ["clippy_utils/deny-warnings"] diff --git a/src/tools/clippy/clippy_lints/src/approx_const.rs b/src/tools/clippy/clippy_lints/src/approx_const.rs index 6100f4e435..fb54ac1ec5 100644 --- a/src/tools/clippy/clippy_lints/src/approx_const.rs +++ b/src/tools/clippy/clippy_lints/src/approx_const.rs @@ -1,8 +1,10 @@ -use clippy_utils::diagnostics::span_lint; +use clippy_utils::diagnostics::span_lint_and_help; +use clippy_utils::{meets_msrv, msrvs}; use rustc_ast::ast::{FloatTy, LitFloatType, LitKind}; use rustc_hir::{Expr, ExprKind}; -use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_lint::{LateContext, LateLintPass, LintContext}; +use rustc_semver::RustcVersion; +use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::symbol; use std::f64::consts as f64; @@ -36,68 +38,82 @@ declare_clippy_lint! { "the approximate of a known float constant (in `std::fXX::consts`)" } -// Tuples are of the form (constant, name, min_digits) -const KNOWN_CONSTS: [(f64, &str, usize); 18] = [ - (f64::E, "E", 4), - (f64::FRAC_1_PI, "FRAC_1_PI", 4), - (f64::FRAC_1_SQRT_2, "FRAC_1_SQRT_2", 5), - (f64::FRAC_2_PI, "FRAC_2_PI", 5), - (f64::FRAC_2_SQRT_PI, "FRAC_2_SQRT_PI", 5), - (f64::FRAC_PI_2, "FRAC_PI_2", 5), - (f64::FRAC_PI_3, "FRAC_PI_3", 5), - (f64::FRAC_PI_4, "FRAC_PI_4", 5), - (f64::FRAC_PI_6, "FRAC_PI_6", 5), - (f64::FRAC_PI_8, "FRAC_PI_8", 5), - (f64::LN_10, "LN_10", 5), - (f64::LN_2, "LN_2", 5), - (f64::LOG10_E, "LOG10_E", 5), - (f64::LOG2_E, "LOG2_E", 5), - (f64::LOG2_10, "LOG2_10", 5), - (f64::LOG10_2, "LOG10_2", 5), - (f64::PI, "PI", 3), - (f64::SQRT_2, "SQRT_2", 5), +// Tuples are of the form (constant, name, min_digits, msrv) +const KNOWN_CONSTS: [(f64, &str, usize, Option); 19] = [ + (f64::E, "E", 4, None), + (f64::FRAC_1_PI, "FRAC_1_PI", 4, None), + (f64::FRAC_1_SQRT_2, "FRAC_1_SQRT_2", 5, None), + (f64::FRAC_2_PI, "FRAC_2_PI", 5, None), + (f64::FRAC_2_SQRT_PI, "FRAC_2_SQRT_PI", 5, None), + (f64::FRAC_PI_2, "FRAC_PI_2", 5, None), + (f64::FRAC_PI_3, "FRAC_PI_3", 5, None), + (f64::FRAC_PI_4, "FRAC_PI_4", 5, None), + (f64::FRAC_PI_6, "FRAC_PI_6", 5, None), + (f64::FRAC_PI_8, "FRAC_PI_8", 5, None), + (f64::LN_2, "LN_2", 5, None), + (f64::LN_10, "LN_10", 5, None), + (f64::LOG2_10, "LOG2_10", 5, Some(msrvs::LOG2_10)), + (f64::LOG2_E, "LOG2_E", 5, None), + (f64::LOG10_2, "LOG10_2", 5, Some(msrvs::LOG10_2)), + (f64::LOG10_E, "LOG10_E", 5, None), + (f64::PI, "PI", 3, None), + (f64::SQRT_2, "SQRT_2", 5, None), + (f64::TAU, "TAU", 3, Some(msrvs::TAU)), ]; -declare_lint_pass!(ApproxConstant => [APPROX_CONSTANT]); +pub struct ApproxConstant { + msrv: Option, +} + +impl ApproxConstant { + #[must_use] + pub fn new(msrv: Option) -> Self { + Self { msrv } + } + + fn check_lit(&self, cx: &LateContext<'_>, lit: &LitKind, e: &Expr<'_>) { + match *lit { + LitKind::Float(s, LitFloatType::Suffixed(fty)) => match fty { + FloatTy::F32 => self.check_known_consts(cx, e, s, "f32"), + FloatTy::F64 => self.check_known_consts(cx, e, s, "f64"), + }, + LitKind::Float(s, LitFloatType::Unsuffixed) => self.check_known_consts(cx, e, s, "f{32, 64}"), + _ => (), + } + } + + fn check_known_consts(&self, cx: &LateContext<'_>, e: &Expr<'_>, s: symbol::Symbol, module: &str) { + let s = s.as_str(); + if s.parse::().is_ok() { + for &(constant, name, min_digits, msrv) in &KNOWN_CONSTS { + if is_approx_const(constant, &s, min_digits) + && msrv.as_ref().map_or(true, |msrv| meets_msrv(self.msrv.as_ref(), msrv)) + { + span_lint_and_help( + cx, + APPROX_CONSTANT, + e.span, + &format!("approximate value of `{}::consts::{}` found", module, &name), + None, + "consider using the constant directly", + ); + return; + } + } + } + } +} + +impl_lint_pass!(ApproxConstant => [APPROX_CONSTANT]); impl<'tcx> LateLintPass<'tcx> for ApproxConstant { fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) { if let ExprKind::Lit(lit) = &e.kind { - check_lit(cx, &lit.node, e); + self.check_lit(cx, &lit.node, e); } } -} -fn check_lit(cx: &LateContext<'_>, lit: &LitKind, e: &Expr<'_>) { - match *lit { - LitKind::Float(s, LitFloatType::Suffixed(fty)) => match fty { - FloatTy::F32 => check_known_consts(cx, e, s, "f32"), - FloatTy::F64 => check_known_consts(cx, e, s, "f64"), - }, - LitKind::Float(s, LitFloatType::Unsuffixed) => check_known_consts(cx, e, s, "f{32, 64}"), - _ => (), - } -} - -fn check_known_consts(cx: &LateContext<'_>, e: &Expr<'_>, s: symbol::Symbol, module: &str) { - let s = s.as_str(); - if s.parse::().is_ok() { - for &(constant, name, min_digits) in &KNOWN_CONSTS { - if is_approx_const(constant, &s, min_digits) { - span_lint( - cx, - APPROX_CONSTANT, - e.span, - &format!( - "approximate value of `{}::consts::{}` found. \ - Consider using it directly", - module, &name - ), - ); - return; - } - } - } + extract_msrv_attr!(LateContext); } /// Returns `false` if the number of significant figures in `value` are diff --git a/src/tools/clippy/clippy_lints/src/assertions_on_constants.rs b/src/tools/clippy/clippy_lints/src/assertions_on_constants.rs index 891e865b24..d834a1d317 100644 --- a/src/tools/clippy/clippy_lints/src/assertions_on_constants.rs +++ b/src/tools/clippy/clippy_lints/src/assertions_on_constants.rs @@ -118,7 +118,7 @@ enum AssertKind { fn match_assert_with_message<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option { if_chain! { if let Some(higher::If { cond, then, .. }) = higher::If::hir(expr); - if let ExprKind::Unary(UnOp::Not, ref expr) = cond.kind; + if let ExprKind::Unary(UnOp::Not, expr) = cond.kind; // bind the first argument of the `assert!` macro if let Some((Constant::Bool(is_true), _)) = constant(cx, cx.typeck_results(), expr); // block diff --git a/src/tools/clippy/clippy_lints/src/attrs.rs b/src/tools/clippy/clippy_lints/src/attrs.rs index c9ff468874..6f8b645dd7 100644 --- a/src/tools/clippy/clippy_lints/src/attrs.rs +++ b/src/tools/clippy/clippy_lints/src/attrs.rs @@ -527,8 +527,8 @@ fn check_empty_line_after_outer_attr(cx: &EarlyContext<'_>, item: &rustc_ast::It return; } - let begin_of_attr_to_item = Span::new(attr.span.lo(), item.span.lo(), item.span.ctxt()); - let end_of_attr_to_item = Span::new(attr.span.hi(), item.span.lo(), item.span.ctxt()); + let begin_of_attr_to_item = Span::new(attr.span.lo(), item.span.lo(), item.span.ctxt(), item.span.parent()); + let end_of_attr_to_item = Span::new(attr.span.hi(), item.span.lo(), item.span.ctxt(), item.span.parent()); if let Some(snippet) = snippet_opt(cx, end_of_attr_to_item) { let lines = snippet.split('\n').collect::>(); @@ -563,7 +563,7 @@ fn check_deprecated_cfg_attr(cx: &EarlyContext<'_>, attr: &Attribute) { skip_item.path.segments.last().expect("empty path in attribute").ident.name == sym::skip; // Only lint outer attributes, because custom inner attributes are unstable // Tracking issue: https://github.com/rust-lang/rust/issues/54726 - if let AttrStyle::Outer = attr.style; + if attr.style == AttrStyle::Outer; then { span_lint_and_sugg( cx, diff --git a/src/tools/clippy/clippy_lints/src/await_holding_invalid.rs b/src/tools/clippy/clippy_lints/src/await_holding_invalid.rs index 0cc79c8b6e..28615b9217 100644 --- a/src/tools/clippy/clippy_lints/src/await_holding_invalid.rs +++ b/src/tools/clippy/clippy_lints/src/await_holding_invalid.rs @@ -16,7 +16,7 @@ declare_clippy_lint! { /// The Mutex types found in std::sync and parking_lot /// are not designed to operate in an async context across await points. /// - /// There are two potential solutions. One is to use an asynx-aware Mutex + /// There are two potential solutions. One is to use an async-aware Mutex /// type. Many asynchronous foundation crates provide such a Mutex type. The /// other solution is to ensure the mutex is unlocked before calling await, /// either by introducing a scope or an explicit call to Drop::drop. diff --git a/src/tools/clippy/clippy_lints/src/blocks_in_if_conditions.rs b/src/tools/clippy/clippy_lints/src/blocks_in_if_conditions.rs index 51d95cc6f0..47e5b0d583 100644 --- a/src/tools/clippy/clippy_lints/src/blocks_in_if_conditions.rs +++ b/src/tools/clippy/clippy_lints/src/blocks_in_if_conditions.rs @@ -61,8 +61,8 @@ impl<'a, 'tcx> Visitor<'tcx> for ExVisitor<'a, 'tcx> { // do not lint if the closure is called using an iterator (see #1141) if_chain! { if let Some(parent) = get_parent_expr(self.cx, expr); - if let ExprKind::MethodCall(_, _, args, _) = parent.kind; - let caller = self.cx.typeck_results().expr_ty(&args[0]); + if let ExprKind::MethodCall(_, _, [self_arg, ..], _) = &parent.kind; + let caller = self.cx.typeck_results().expr_ty(self_arg); if let Some(iter_id) = self.cx.tcx.get_diagnostic_item(sym::Iterator); if implements_trait(self.cx, caller, iter_id, &[]); then { diff --git a/src/tools/clippy/clippy_lints/src/bool_assert_comparison.rs b/src/tools/clippy/clippy_lints/src/bool_assert_comparison.rs index 8d3f68565b..cdc192a47e 100644 --- a/src/tools/clippy/clippy_lints/src/bool_assert_comparison.rs +++ b/src/tools/clippy/clippy_lints/src/bool_assert_comparison.rs @@ -1,9 +1,11 @@ -use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::{ast_utils, is_direct_expn_of}; -use rustc_ast::ast::{Expr, ExprKind, Lit, LitKind}; +use clippy_utils::{diagnostics::span_lint_and_sugg, higher, is_direct_expn_of, ty::implements_trait}; +use rustc_ast::ast::LitKind; use rustc_errors::Applicability; -use rustc_lint::{EarlyContext, EarlyLintPass}; +use rustc_hir::{Expr, ExprKind, Lit}; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::ty; use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_span::symbol::Ident; declare_clippy_lint! { /// ### What it does @@ -28,45 +30,77 @@ declare_clippy_lint! { declare_lint_pass!(BoolAssertComparison => [BOOL_ASSERT_COMPARISON]); -fn is_bool_lit(e: &Expr) -> bool { +fn is_bool_lit(e: &Expr<'_>) -> bool { matches!( e.kind, ExprKind::Lit(Lit { - kind: LitKind::Bool(_), + node: LitKind::Bool(_), .. }) ) && !e.span.from_expansion() } -impl EarlyLintPass for BoolAssertComparison { - fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &Expr) { +fn is_impl_not_trait_with_bool_out(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> bool { + let ty = cx.typeck_results().expr_ty(e); + + cx.tcx + .lang_items() + .not_trait() + .filter(|trait_id| implements_trait(cx, ty, *trait_id, &[])) + .and_then(|trait_id| { + cx.tcx.associated_items(trait_id).find_by_name_and_kind( + cx.tcx, + Ident::from_str("Output"), + ty::AssocKind::Type, + trait_id, + ) + }) + .map_or(false, |assoc_item| { + let proj = cx.tcx.mk_projection(assoc_item.def_id, cx.tcx.mk_substs_trait(ty, &[])); + let nty = cx.tcx.normalize_erasing_regions(cx.param_env, proj); + + nty.is_bool() + }) +} + +impl<'tcx> LateLintPass<'tcx> for BoolAssertComparison { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { let macros = ["assert_eq", "debug_assert_eq"]; let inverted_macros = ["assert_ne", "debug_assert_ne"]; for mac in macros.iter().chain(inverted_macros.iter()) { - if let Some(span) = is_direct_expn_of(e.span, mac) { - if let Some([a, b]) = ast_utils::extract_assert_macro_args(e) { - let nb_bool_args = is_bool_lit(a) as usize + is_bool_lit(b) as usize; + if let Some(span) = is_direct_expn_of(expr.span, mac) { + if let Some(args) = higher::extract_assert_macro_args(expr) { + if let [a, b, ..] = args[..] { + let nb_bool_args = is_bool_lit(a) as usize + is_bool_lit(b) as usize; - if nb_bool_args != 1 { - // If there are two boolean arguments, we definitely don't understand - // what's going on, so better leave things as is... - // - // Or there is simply no boolean and then we can leave things as is! + if nb_bool_args != 1 { + // If there are two boolean arguments, we definitely don't understand + // what's going on, so better leave things as is... + // + // Or there is simply no boolean and then we can leave things as is! + return; + } + + if !is_impl_not_trait_with_bool_out(cx, a) || !is_impl_not_trait_with_bool_out(cx, b) { + // At this point the expression which is not a boolean + // literal does not implement Not trait with a bool output, + // so we cannot suggest to rewrite our code + return; + } + + let non_eq_mac = &mac[..mac.len() - 3]; + span_lint_and_sugg( + cx, + BOOL_ASSERT_COMPARISON, + span, + &format!("used `{}!` with a literal bool", mac), + "replace it with", + format!("{}!(..)", non_eq_mac), + Applicability::MaybeIncorrect, + ); return; } - - let non_eq_mac = &mac[..mac.len() - 3]; - span_lint_and_sugg( - cx, - BOOL_ASSERT_COMPARISON, - span, - &format!("used `{}!` with a literal bool", mac), - "replace it with", - format!("{}!(..)", non_eq_mac), - Applicability::MaybeIncorrect, - ); - return; } } } diff --git a/src/tools/clippy/clippy_lints/src/booleans.rs b/src/tools/clippy/clippy_lints/src/booleans.rs index 6f12d34e66..8282800c81 100644 --- a/src/tools/clippy/clippy_lints/src/booleans.rs +++ b/src/tools/clippy/clippy_lints/src/booleans.rs @@ -260,8 +260,8 @@ fn simplify_not(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option { }, ExprKind::MethodCall(path, _, args, _) if args.len() == 1 => { let type_of_receiver = cx.typeck_results().expr_ty(&args[0]); - if !is_type_diagnostic_item(cx, type_of_receiver, sym::option_type) - && !is_type_diagnostic_item(cx, type_of_receiver, sym::result_type) + if !is_type_diagnostic_item(cx, type_of_receiver, sym::Option) + && !is_type_diagnostic_item(cx, type_of_receiver, sym::Result) { return None; } diff --git a/src/tools/clippy/clippy_lints/src/bytecount.rs b/src/tools/clippy/clippy_lints/src/bytecount.rs index c444984bc1..a07cd5e5f4 100644 --- a/src/tools/clippy/clippy_lints/src/bytecount.rs +++ b/src/tools/clippy/clippy_lints/src/bytecount.rs @@ -1,7 +1,7 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet_with_applicability; use clippy_utils::ty::match_type; -use clippy_utils::visitors::LocalUsedVisitor; +use clippy_utils::visitors::is_local_used; use clippy_utils::{path_to_local_id, paths, peel_ref_operators, remove_blocks, strip_pat_refs}; use if_chain::if_chain; use rustc_errors::Applicability; @@ -65,7 +65,7 @@ impl<'tcx> LateLintPass<'tcx> for ByteCount { return; }; if ty::Uint(UintTy::U8) == *cx.typeck_results().expr_ty(needle).peel_refs().kind(); - if !LocalUsedVisitor::new(cx, arg_id).check_expr(needle); + if !is_local_used(cx, needle, arg_id); then { let haystack = if let ExprKind::MethodCall(path, _, args, _) = filter_recv.kind { diff --git a/src/tools/clippy/clippy_lints/src/cargo_common_metadata.rs b/src/tools/clippy/clippy_lints/src/cargo_common_metadata.rs index bd5426ba70..ff619c59b6 100644 --- a/src/tools/clippy/clippy_lints/src/cargo_common_metadata.rs +++ b/src/tools/clippy/clippy_lints/src/cargo_common_metadata.rs @@ -1,9 +1,7 @@ //! lint on missing cargo common metadata -use std::path::PathBuf; - use clippy_utils::{diagnostics::span_lint, is_lint_allowed}; -use rustc_hir::{hir_id::CRATE_HIR_ID, Crate}; +use rustc_hir::hir_id::CRATE_HIR_ID; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::source_map::DUMMY_SP; @@ -69,12 +67,8 @@ fn missing_warning(cx: &LateContext<'_>, package: &cargo_metadata::Package, fiel span_lint(cx, CARGO_COMMON_METADATA, DUMMY_SP, &message); } -fn is_empty_str(value: &Option) -> bool { - value.as_ref().map_or(true, String::is_empty) -} - -fn is_empty_path(value: &Option) -> bool { - value.as_ref().and_then(|x| x.to_str()).map_or(true, str::is_empty) +fn is_empty_str>(value: &Option) -> bool { + value.as_ref().map_or(true, |s| s.as_ref().is_empty()) } fn is_empty_vec(value: &[String]) -> bool { @@ -83,7 +77,7 @@ fn is_empty_vec(value: &[String]) -> bool { } impl LateLintPass<'_> for CargoCommonMetadata { - fn check_crate(&mut self, cx: &LateContext<'_>, _: &Crate<'_>) { + fn check_crate(&mut self, cx: &LateContext<'_>) { if is_lint_allowed(cx, CARGO_COMMON_METADATA, CRATE_HIR_ID) { return; } @@ -98,7 +92,7 @@ impl LateLintPass<'_> for CargoCommonMetadata { missing_warning(cx, &package, "package.description"); } - if is_empty_str(&package.license) && is_empty_path(&package.license_file) { + if is_empty_str(&package.license) && is_empty_str(&package.license_file) { missing_warning(cx, &package, "either package.license or package.license_file"); } @@ -106,7 +100,7 @@ impl LateLintPass<'_> for CargoCommonMetadata { missing_warning(cx, &package, "package.repository"); } - if is_empty_path(&package.readme) { + if is_empty_str(&package.readme) { missing_warning(cx, &package, "package.readme"); } diff --git a/src/tools/clippy/clippy_lints/src/case_sensitive_file_extension_comparisons.rs b/src/tools/clippy/clippy_lints/src/case_sensitive_file_extension_comparisons.rs index 86b32475ce..c876553c16 100644 --- a/src/tools/clippy/clippy_lints/src/case_sensitive_file_extension_comparisons.rs +++ b/src/tools/clippy/clippy_lints/src/case_sensitive_file_extension_comparisons.rs @@ -55,7 +55,7 @@ fn check_case_sensitive_file_extension_comparison(ctx: &LateContext<'_>, expr: & return Some(span); }, ty::Adt(&ty::AdtDef { did, .. }, _) => { - if ctx.tcx.is_diagnostic_item(sym::string_type, did) { + if ctx.tcx.is_diagnostic_item(sym::String, did) { return Some(span); } }, diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_precision_loss.rs b/src/tools/clippy/clippy_lints/src/casts/cast_precision_loss.rs index 63ac8fd2dd..334e1646cd 100644 --- a/src/tools/clippy/clippy_lints/src/casts/cast_precision_loss.rs +++ b/src/tools/clippy/clippy_lints/src/casts/cast_precision_loss.rs @@ -12,7 +12,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_from: Ty<'_>, ca } let from_nbits = utils::int_ty_to_nbits(cast_from, cx.tcx); - let to_nbits = if let ty::Float(FloatTy::F32) = cast_to.kind() { + let to_nbits = if cast_to.kind() == &ty::Float(FloatTy::F32) { 32 } else { 64 diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_ptr_alignment.rs b/src/tools/clippy/clippy_lints/src/casts/cast_ptr_alignment.rs index 62a119d662..248b35b024 100644 --- a/src/tools/clippy/clippy_lints/src/casts/cast_ptr_alignment.rs +++ b/src/tools/clippy/clippy_lints/src/casts/cast_ptr_alignment.rs @@ -3,9 +3,9 @@ use clippy_utils::is_hir_ty_cfg_dependant; use if_chain::if_chain; use rustc_hir::{Expr, ExprKind, GenericArg}; use rustc_lint::LateContext; +use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::{self, Ty}; use rustc_span::symbol::sym; -use rustc_target::abi::LayoutOf; use super::CAST_PTR_ALIGNMENT; @@ -19,7 +19,7 @@ pub(super) fn check(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { cx.typeck_results().expr_ty(expr), ); lint_cast_ptr_alignment(cx, expr, cast_from, cast_to); - } else if let ExprKind::MethodCall(method_path, _, args, _) = expr.kind { + } else if let ExprKind::MethodCall(method_path, _, [self_arg, ..], _) = &expr.kind { if_chain! { if method_path.ident.name == sym!(cast); if let Some(generic_args) = method_path.args; @@ -28,7 +28,7 @@ pub(super) fn check(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { if !is_hir_ty_cfg_dependant(cx, cast_to); then { let (cast_from, cast_to) = - (cx.typeck_results().expr_ty(&args[0]), cx.typeck_results().expr_ty(expr)); + (cx.typeck_results().expr_ty(self_arg), cx.typeck_results().expr_ty(expr)); lint_cast_ptr_alignment(cx, expr, cast_from, cast_to); } } diff --git a/src/tools/clippy/clippy_lints/src/cognitive_complexity.rs b/src/tools/clippy/clippy_lints/src/cognitive_complexity.rs index 96c30d57ee..1ccb8c5d88 100644 --- a/src/tools/clippy/clippy_lints/src/cognitive_complexity.rs +++ b/src/tools/clippy/clippy_lints/src/cognitive_complexity.rs @@ -67,7 +67,7 @@ impl CognitiveComplexity { helper.visit_expr(expr); let CcHelper { cc, returns } = helper; let ret_ty = cx.typeck_results().node_type(expr.hir_id); - let ret_adjust = if is_type_diagnostic_item(cx, ret_ty, sym::result_type) { + let ret_adjust = if is_type_diagnostic_item(cx, ret_ty, sym::Result) { returns } else { #[allow(clippy::integer_division)] @@ -95,7 +95,7 @@ impl CognitiveComplexity { }); if let Some((low, high)) = pos { - Span::new(low, high, header_span.ctxt()) + Span::new(low, high, header_span.ctxt(), header_span.parent()) } else { return; } diff --git a/src/tools/clippy/clippy_lints/src/collapsible_match.rs b/src/tools/clippy/clippy_lints/src/collapsible_match.rs index a42eee5345..a4693fa213 100644 --- a/src/tools/clippy/clippy_lints/src/collapsible_match.rs +++ b/src/tools/clippy/clippy_lints/src/collapsible_match.rs @@ -1,9 +1,10 @@ use clippy_utils::diagnostics::span_lint_and_then; -use clippy_utils::visitors::LocalUsedVisitor; -use clippy_utils::{higher, is_lang_ctor, is_unit_expr, path_to_local, peel_ref_operators, SpanlessEq}; +use clippy_utils::higher::IfLetOrMatch; +use clippy_utils::visitors::is_local_used; +use clippy_utils::{is_lang_ctor, is_unit_expr, path_to_local, peel_ref_operators, SpanlessEq}; use if_chain::if_chain; use rustc_hir::LangItem::OptionNone; -use rustc_hir::{Arm, Expr, ExprKind, Guard, HirId, MatchSource, Pat, PatKind, StmtKind}; +use rustc_hir::{Arm, Expr, ExprKind, Guard, HirId, Pat, PatKind, StmtKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::{MultiSpan, Span}; @@ -56,11 +57,11 @@ impl<'tcx> LateLintPass<'tcx> for CollapsibleMatch { check_arm(cx, true, arm.pat, arm.body, arm.guard.as_ref(), Some(els_arm.body)); } } - } + }, Some(IfLetOrMatch::IfLet(_, pat, body, els)) => { check_arm(cx, false, pat, body, None, els); - } - None => {} + }, + None => {}, } } } @@ -71,7 +72,7 @@ fn check_arm<'tcx>( outer_pat: &'tcx Pat<'tcx>, outer_then_body: &'tcx Expr<'tcx>, outer_guard: Option<&'tcx Guard<'tcx>>, - outer_else_body: Option<&'tcx Expr<'tcx>> + outer_else_body: Option<&'tcx Expr<'tcx>>, ) { let inner_expr = strip_singleton_blocks(outer_then_body); if_chain! { @@ -106,14 +107,13 @@ fn check_arm<'tcx>( (Some(a), Some(b)) => SpanlessEq::new(cx).eq_expr(a, b), }; // the binding must not be used in the if guard - let mut used_visitor = LocalUsedVisitor::new(cx, binding_id); - if outer_guard.map_or(true, |(Guard::If(e) | Guard::IfLet(_, e))| !used_visitor.check_expr(e)); + if outer_guard.map_or(true, |(Guard::If(e) | Guard::IfLet(_, e))| !is_local_used(cx, *e, binding_id)); // ...or anywhere in the inner expression if match inner { IfLetOrMatch::IfLet(_, _, body, els) => { - !used_visitor.check_expr(body) && els.map_or(true, |e| !used_visitor.check_expr(e)) + !is_local_used(cx, body, binding_id) && els.map_or(true, |e| !is_local_used(cx, e, binding_id)) }, - IfLetOrMatch::Match(_, arms, ..) => !arms.iter().any(|arm| used_visitor.check_arm(arm)), + IfLetOrMatch::Match(_, arms, ..) => !arms.iter().any(|arm| is_local_used(cx, arm, binding_id)), }; then { let msg = format!( @@ -151,23 +151,6 @@ fn strip_singleton_blocks<'hir>(mut expr: &'hir Expr<'hir>) -> &'hir Expr<'hir> expr } -enum IfLetOrMatch<'hir> { - Match(&'hir Expr<'hir>, &'hir [Arm<'hir>], MatchSource), - /// scrutinee, pattern, then block, else block - IfLet(&'hir Expr<'hir>, &'hir Pat<'hir>, &'hir Expr<'hir>, Option<&'hir Expr<'hir>>), -} - -impl<'hir> IfLetOrMatch<'hir> { - fn parse(cx: &LateContext<'_>, expr: &Expr<'hir>) -> Option { - match expr.kind { - ExprKind::Match(expr, arms, source) => Some(Self::Match(expr, arms, source)), - _ => higher::IfLet::hir(cx, expr).map(|higher::IfLet { let_expr, let_pat, if_then, if_else }| { - Self::IfLet(let_expr, let_pat, if_then, if_else) - }) - } - } -} - /// A "wild-like" arm has a wild (`_`) or `None` pattern and no guard. Such arms can be "collapsed" /// into a single wild arm without any significant loss in semantics or readability. fn arm_is_wild_like(cx: &LateContext<'_>, arm: &Arm<'_>) -> bool { diff --git a/src/tools/clippy/clippy_lints/src/copies.rs b/src/tools/clippy/clippy_lints/src/copies.rs index 5eb99cfe24..b7385dcfbc 100644 --- a/src/tools/clippy/clippy_lints/src/copies.rs +++ b/src/tools/clippy/clippy_lints/src/copies.rs @@ -9,7 +9,7 @@ use rustc_data_structures::fx::FxHashSet; use rustc_errors::{Applicability, DiagnosticBuilder}; use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc_hir::{Block, Expr, ExprKind, HirId}; -use rustc_lint::{LateContext, LateLintPass}; +use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::hir::map::Map; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::{source_map::Span, symbol::Symbol, BytePos}; @@ -148,7 +148,7 @@ declare_clippy_lint! { /// }; /// ``` pub BRANCHES_SHARING_CODE, - complexity, + nursery, "`if` statement with shared code in all blocks" } @@ -432,10 +432,11 @@ fn emit_branches_sharing_code_lint( let mut add_expr_note = false; // Construct suggestions + let sm = cx.sess().source_map(); if start_stmts > 0 { let block = blocks[0]; let span_start = first_line_of_span(cx, if_expr.span).shrink_to_lo(); - let span_end = block.stmts[start_stmts - 1].span.source_callsite(); + let span_end = sm.stmt_span(block.stmts[start_stmts - 1].span, block.span); let cond_span = first_line_of_span(cx, if_expr.span).until(block.span); let cond_snippet = reindent_multiline(snippet(cx, cond_span, "_"), false, None); @@ -454,15 +455,16 @@ fn emit_branches_sharing_code_lint( let span_end = block.span.shrink_to_hi(); let moved_start = if end_stmts == 0 && block.expr.is_some() { - block.expr.unwrap().span + block.expr.unwrap().span.source_callsite() } else { - block.stmts[block.stmts.len() - end_stmts].span - } - .source_callsite(); + sm.stmt_span(block.stmts[block.stmts.len() - end_stmts].span, block.span) + }; let moved_end = block .expr - .map_or_else(|| block.stmts[block.stmts.len() - 1].span, |expr| expr.span) - .source_callsite(); + .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); @@ -472,7 +474,7 @@ fn emit_branches_sharing_code_lint( let mut span = moved_start.to(span_end); // Improve formatting if the inner block has indention (i.e. normal Rust formatting) - let test_span = Span::new(span.lo() - BytePos(4), span.lo(), span.ctxt()); + let test_span = Span::new(span.lo() - BytePos(4), span.lo(), span.ctxt(), span.parent()); if snippet_opt(cx, test_span) .map(|snip| snip == " ") .unwrap_or_default() diff --git a/src/tools/clippy/clippy_lints/src/dereference.rs b/src/tools/clippy/clippy_lints/src/dereference.rs index 7825e5f6ed..ce59311c4a 100644 --- a/src/tools/clippy/clippy_lints/src/dereference.rs +++ b/src/tools/clippy/clippy_lints/src/dereference.rs @@ -126,7 +126,7 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing { target_mut, }, )); - } + }, _ => (), } }, diff --git a/src/tools/clippy/clippy_lints/src/derivable_impls.rs b/src/tools/clippy/clippy_lints/src/derivable_impls.rs new file mode 100644 index 0000000000..fdef0abe97 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/derivable_impls.rs @@ -0,0 +1,118 @@ +use clippy_utils::diagnostics::span_lint_and_help; +use clippy_utils::{in_macro, is_automatically_derived, is_default_equivalent, remove_blocks}; +use rustc_hir::{ + def::{DefKind, Res}, + Body, Expr, ExprKind, GenericArg, Impl, ImplItemKind, Item, ItemKind, Node, PathSegment, QPath, TyKind, +}; +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 manual `std::default::Default` implementations that are identical to a derived implementation. + /// + /// ### Why is this bad? + /// It is less concise. + /// + /// ### Example + /// ```rust + /// struct Foo { + /// bar: bool + /// } + /// + /// impl std::default::Default for Foo { + /// fn default() -> Self { + /// Self { + /// bar: false + /// } + /// } + /// } + /// ``` + /// + /// Could be written as: + /// + /// ```rust + /// #[derive(Default)] + /// struct Foo { + /// bar: bool + /// } + /// ``` + /// + /// ### Known problems + /// Derive macros [sometimes use incorrect bounds](https://github.com/rust-lang/rust/issues/26925) + /// in generic types and the user defined `impl` maybe is more generalized or + /// specialized than what derive will produce. This lint can't detect the manual `impl` + /// has exactly equal bounds, and therefore this lint is disabled for types with + /// generic parameters. + /// + pub DERIVABLE_IMPLS, + complexity, + "manual implementation of the `Default` trait which is equal to a derive" +} + +declare_lint_pass!(DerivableImpls => [DERIVABLE_IMPLS]); + +fn is_path_self(e: &Expr<'_>) -> bool { + if let ExprKind::Path(QPath::Resolved(_, p)) = e.kind { + matches!(p.res, Res::SelfCtor(..) | Res::Def(DefKind::Ctor(..), _)) + } else { + false + } +} + +impl<'tcx> LateLintPass<'tcx> for DerivableImpls { + fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) { + if_chain! { + if let ItemKind::Impl(Impl { + of_trait: Some(ref trait_ref), + items: [child], + self_ty, + .. + }) = item.kind; + if let attrs = cx.tcx.hir().attrs(item.hir_id()); + if !is_automatically_derived(attrs); + if !in_macro(item.span); + if let Some(def_id) = trait_ref.trait_def_id(); + if cx.tcx.is_diagnostic_item(sym::Default, def_id); + if let impl_item_hir = child.id.hir_id(); + if let Some(Node::ImplItem(impl_item)) = cx.tcx.hir().find(impl_item_hir); + if let ImplItemKind::Fn(_, b) = &impl_item.kind; + if let Body { value: func_expr, .. } = cx.tcx.hir().body(*b); + if let Some(adt_def) = cx.tcx.type_of(item.def_id).ty_adt_def(); + if !attrs.iter().any(|attr| attr.doc_str().is_some()); + if let child_attrs = cx.tcx.hir().attrs(impl_item_hir); + if !child_attrs.iter().any(|attr| attr.doc_str().is_some()); + if adt_def.is_struct(); + then { + if let TyKind::Path(QPath::Resolved(_, p)) = self_ty.kind { + if let Some(PathSegment { args: Some(a), .. }) = p.segments.last() { + for arg in a.args { + if !matches!(arg, GenericArg::Lifetime(_)) { + return; + } + } + } + } + let should_emit = match remove_blocks(func_expr).kind { + ExprKind::Tup(fields) => fields.iter().all(|e| is_default_equivalent(cx, e)), + ExprKind::Call(callee, args) + if is_path_self(callee) => args.iter().all(|e| is_default_equivalent(cx, e)), + ExprKind::Struct(_, fields, _) => fields.iter().all(|ef| is_default_equivalent(cx, ef.expr)), + _ => false, + }; + if should_emit { + let path_string = cx.tcx.def_path_str(adt_def.did); + span_lint_and_help( + cx, + DERIVABLE_IMPLS, + item.span, + "this `impl` can be derived", + None, + &format!("try annotating `{}` with `#[derive(Default)]`", path_string), + ); + } + } + } + } +} diff --git a/src/tools/clippy/clippy_lints/src/derive.rs b/src/tools/clippy/clippy_lints/src/derive.rs index dcfa5253f8..24ac5917dc 100644 --- a/src/tools/clippy/clippy_lints/src/derive.rs +++ b/src/tools/clippy/clippy_lints/src/derive.rs @@ -105,9 +105,6 @@ declare_clippy_lint! { /// nothing more than copy the object, which is what `#[derive(Copy, Clone)]` /// gets you. /// - /// ### Known problems - /// Bounds of generic types are sometimes wrong: https://github.com/rust-lang/rust/issues/26925 - /// /// ### Example /// ```rust,ignore /// #[derive(Copy)] @@ -396,7 +393,7 @@ impl<'tcx> Visitor<'tcx> for UnsafeVisitor<'_, 'tcx> { if_chain! { if let Some(header) = kind.header(); - if let Unsafety::Unsafe = header.unsafety; + if header.unsafety == Unsafety::Unsafe; then { self.has_unsafe = true; } @@ -411,7 +408,7 @@ impl<'tcx> Visitor<'tcx> for UnsafeVisitor<'_, 'tcx> { } if let ExprKind::Block(block, _) = expr.kind { - if let BlockCheckMode::UnsafeBlock(UnsafeSource::UserProvided) = block.rules { + if block.rules == BlockCheckMode::UnsafeBlock(UnsafeSource::UserProvided) { self.has_unsafe = true; } } diff --git a/src/tools/clippy/clippy_lints/src/disallowed_method.rs b/src/tools/clippy/clippy_lints/src/disallowed_method.rs index 7069cb4198..22d726cdcb 100644 --- a/src/tools/clippy/clippy_lints/src/disallowed_method.rs +++ b/src/tools/clippy/clippy_lints/src/disallowed_method.rs @@ -1,33 +1,44 @@ -use clippy_utils::diagnostics::span_lint; +use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::fn_def_id; -use rustc_data_structures::fx::FxHashSet; -use rustc_hir::{def::Res, def_id::DefId, Crate, Expr}; +use rustc_hir::{def::Res, def_id::DefIdMap, Expr}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_tool_lint, impl_lint_pass}; -use rustc_span::Symbol; + +use crate::utils::conf; declare_clippy_lint! { /// ### What it does /// Denies the configured methods and functions in clippy.toml /// /// ### Why is this bad? - /// Some methods are undesirable in certain contexts, - /// and it's beneficial to lint for them as needed. + /// Some methods are undesirable in certain contexts, and it's beneficial to + /// lint for them as needed. /// /// ### Example /// An example clippy.toml configuration: /// ```toml /// # clippy.toml - /// disallowed-methods = ["std::vec::Vec::leak", "std::time::Instant::now"] + /// disallowed-methods = [ + /// # Can use a string as the path of the disallowed method. + /// "std::boxed::Box::new", + /// # Can also use an inline table with a `path` key. + /// { path = "std::time::Instant::now" }, + /// # When using an inline table, can add a `reason` for why the method + /// # is disallowed. + /// { path = "std::vec::Vec::leak", reason = "no leaking memory" }, + /// ] /// ``` /// /// ```rust,ignore /// // Example code where clippy issues a warning /// let xs = vec![1, 2, 3, 4]; /// xs.leak(); // Vec::leak is disallowed in the config. + /// // The diagnostic contains the message "no leaking memory". /// /// let _now = Instant::now(); // Instant::now is disallowed in the config. + /// + /// let _box = Box::new(3); // Box::new is disallowed in the config. /// ``` /// /// Use instead: @@ -43,18 +54,15 @@ declare_clippy_lint! { #[derive(Clone, Debug)] pub struct DisallowedMethod { - disallowed: FxHashSet>, - def_ids: FxHashSet<(DefId, Vec)>, + conf_disallowed: Vec, + disallowed: DefIdMap>, } impl DisallowedMethod { - pub fn new(disallowed: &FxHashSet) -> Self { + pub fn new(conf_disallowed: Vec) -> Self { Self { - disallowed: disallowed - .iter() - .map(|s| s.split("::").map(|seg| Symbol::intern(seg)).collect::>()) - .collect(), - def_ids: FxHashSet::default(), + conf_disallowed, + disallowed: DefIdMap::default(), } } } @@ -62,33 +70,37 @@ impl DisallowedMethod { impl_lint_pass!(DisallowedMethod => [DISALLOWED_METHOD]); impl<'tcx> LateLintPass<'tcx> for DisallowedMethod { - fn check_crate(&mut self, cx: &LateContext<'_>, _: &Crate<'_>) { - for path in &self.disallowed { - let segs = path.iter().map(ToString::to_string).collect::>(); - if let Res::Def(_, id) = clippy_utils::path_to_res(cx, &segs.iter().map(String::as_str).collect::>()) - { - self.def_ids.insert((id, path.clone())); + fn check_crate(&mut self, cx: &LateContext<'_>) { + for conf in &self.conf_disallowed { + let (path, reason) = match conf { + conf::DisallowedMethod::Simple(path) => (path, None), + conf::DisallowedMethod::WithReason { path, reason } => ( + path, + reason.as_ref().map(|reason| format!("{} (from clippy.toml)", reason)), + ), + }; + let segs: Vec<_> = path.split("::").collect(); + if let Res::Def(_, id) = clippy_utils::path_to_res(cx, &segs) { + self.disallowed.insert(id, reason); } } } fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { - if let Some(def_id) = fn_def_id(cx, expr) { - if self.def_ids.iter().any(|(id, _)| def_id == *id) { - let func_path = cx.get_def_path(def_id); - let func_path_string = func_path - .into_iter() - .map(Symbol::to_ident_string) - .collect::>() - .join("::"); - - span_lint( - cx, - DISALLOWED_METHOD, - expr.span, - &format!("use of a disallowed method `{}`", func_path_string), - ); + let def_id = match fn_def_id(cx, expr) { + Some(def_id) => def_id, + None => return, + }; + let reason = match self.disallowed.get(&def_id) { + Some(reason) => reason, + None => return, + }; + let func_path = cx.tcx.def_path_str(def_id); + let msg = format!("use of a disallowed method `{}`", func_path); + span_lint_and_then(cx, DISALLOWED_METHOD, expr.span, &msg, |diag| { + if let Some(reason) = reason { + diag.note(reason); } - } + }); } } diff --git a/src/tools/clippy/clippy_lints/src/disallowed_type.rs b/src/tools/clippy/clippy_lints/src/disallowed_type.rs index e627168b93..87124f093a 100644 --- a/src/tools/clippy/clippy_lints/src/disallowed_type.rs +++ b/src/tools/clippy/clippy_lints/src/disallowed_type.rs @@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint; use rustc_data_structures::fx::FxHashSet; use rustc_hir::{ - def::Res, def_id::DefId, Crate, Item, ItemKind, PolyTraitRef, PrimTy, TraitBoundModifier, Ty, TyKind, UseKind, + 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}; @@ -48,7 +48,7 @@ impl DisallowedType { Self { disallowed: disallowed .iter() - .map(|s| s.split("::").map(|seg| Symbol::intern(seg)).collect::>()) + .map(|s| s.split("::").map(Symbol::intern).collect::>()) .collect(), def_ids: FxHashSet::default(), prim_tys: FxHashSet::default(), @@ -75,7 +75,7 @@ impl DisallowedType { impl_lint_pass!(DisallowedType => [DISALLOWED_TYPE]); impl<'tcx> LateLintPass<'tcx> for DisallowedType { - fn check_crate(&mut self, cx: &LateContext<'_>, _: &Crate<'_>) { + fn check_crate(&mut self, cx: &LateContext<'_>) { for path in &self.disallowed { let segs = path.iter().map(ToString::to_string).collect::>(); match clippy_utils::path_to_res(cx, &segs.iter().map(String::as_str).collect::>()) { diff --git a/src/tools/clippy/clippy_lints/src/doc.rs b/src/tools/clippy/clippy_lints/src/doc.rs index cb2b7f5be7..9840affbf6 100644 --- a/src/tools/clippy/clippy_lints/src/doc.rs +++ b/src/tools/clippy/clippy_lints/src/doc.rs @@ -212,7 +212,7 @@ impl_lint_pass!(DocMarkdown => ); impl<'tcx> LateLintPass<'tcx> for DocMarkdown { - fn check_crate(&mut self, cx: &LateContext<'tcx>, _: &'tcx hir::Crate<'_>) { + fn check_crate(&mut self, cx: &LateContext<'tcx>) { let attrs = cx.tcx.hir().attrs(hir::CRATE_HIR_ID); check_attrs(cx, &self.valid_idents, attrs); } @@ -236,7 +236,17 @@ impl<'tcx> LateLintPass<'tcx> for DocMarkdown { hir::ItemKind::Impl(ref impl_) => { self.in_trait_impl = impl_.of_trait.is_some(); }, - _ => {}, + hir::ItemKind::Trait(_, unsafety, ..) => { + if !headers.safety && unsafety == hir::Unsafety::Unsafe { + span_lint( + cx, + MISSING_SAFETY_DOC, + item.span, + "docs for unsafe trait missing `# Safety` section", + ); + } + }, + _ => (), } } @@ -307,7 +317,7 @@ fn lint_for_missing_headers<'tcx>( } if !headers.errors { let hir_id = cx.tcx.hir().local_def_id_to_hir_id(def_id); - if is_type_diagnostic_item(cx, return_ty(cx, hir_id), sym::result_type) { + if is_type_diagnostic_item(cx, return_ty(cx, hir_id), sym::Result) { span_lint( cx, MISSING_ERRORS_DOC, @@ -325,7 +335,7 @@ fn lint_for_missing_headers<'tcx>( if let ty::Opaque(_, subs) = ret_ty.kind(); if let Some(gen) = subs.types().next(); if let ty::Generator(_, subs, _) = gen.kind(); - if is_type_diagnostic_item(cx, subs.as_generator().return_ty(), sym::result_type); + if is_type_diagnostic_item(cx, subs.as_generator().return_ty(), sym::Result); then { span_lint( cx, @@ -396,6 +406,15 @@ struct DocHeaders { } fn check_attrs<'a>(cx: &LateContext<'_>, valid_idents: &FxHashSet, attrs: &'a [Attribute]) -> DocHeaders { + use pulldown_cmark::{BrokenLink, CowStr, Options}; + /// We don't want the parser to choke on intra doc links. Since we don't + /// actually care about rendering them, just pretend that all broken links are + /// point to a fake address. + #[allow(clippy::unnecessary_wraps)] // we're following a type signature + fn fake_broken_link_callback<'a>(_: BrokenLink<'_>) -> Option<(CowStr<'a>, CowStr<'a>)> { + Some(("fake".into(), "fake".into())) + } + let mut doc = String::new(); let mut spans = vec![]; @@ -430,7 +449,10 @@ fn check_attrs<'a>(cx: &LateContext<'_>, valid_idents: &FxHashSet, attrs }; } - let parser = pulldown_cmark::Parser::new(&doc).into_offset_iter(); + let mut cb = fake_broken_link_callback; + + let parser = + pulldown_cmark::Parser::new_with_broken_link_callback(&doc, Options::empty(), Some(&mut cb)).into_offset_iter(); // Iterate over all `Events` and combine consecutive events into one let events = parser.coalesce(|previous, current| { use pulldown_cmark::Event::Text; @@ -665,6 +687,7 @@ fn check_text(cx: &LateContext<'_>, valid_idents: &FxHashSet, text: &str span.lo() + BytePos::from_usize(offset), span.lo() + BytePos::from_usize(offset + word.len()), span.ctxt(), + span.parent(), ); check_word(cx, word, span); @@ -759,8 +782,8 @@ 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_type) - || is_type_diagnostic_item(self.cx, reciever_ty, sym::result_type) + if is_type_diagnostic_item(self.cx, reciever_ty, sym::Option) + || is_type_diagnostic_item(self.cx, reciever_ty, sym::Result) { self.panic_span = Some(expr.span); } diff --git a/src/tools/clippy/clippy_lints/src/entry.rs b/src/tools/clippy/clippy_lints/src/entry.rs index 627f746ec9..57fd24bd4f 100644 --- a/src/tools/clippy/clippy_lints/src/entry.rs +++ b/src/tools/clippy/clippy_lints/src/entry.rs @@ -9,8 +9,9 @@ use clippy_utils::{ use core::fmt::Write; use rustc_errors::Applicability; use rustc_hir::{ + hir_id::HirIdSet, intravisit::{walk_expr, ErasedMap, NestedVisitorMap, Visitor}, - Block, Expr, ExprKind, Guard, HirId, Local, Stmt, StmtKind, UnOp, + Block, Expr, ExprKind, Guard, HirId, Pat, Stmt, StmtKind, UnOp, }; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; @@ -244,11 +245,14 @@ fn try_parse_contains(cx: &LateContext<'_>, expr: &'tcx Expr<'_>) -> Option<(Map ExprKind::MethodCall( _, _, - [map, Expr { - kind: ExprKind::AddrOf(_, _, key), - span: key_span, - .. - }], + [ + map, + Expr { + kind: ExprKind::AddrOf(_, _, key), + span: key_span, + .. + }, + ], _, ) if key_span.ctxt() == expr.span.ctxt() => { let id = cx.typeck_results().type_dependent_def_id(expr.hir_id)?; @@ -338,6 +342,8 @@ struct InsertSearcher<'cx, 'tcx> { edits: Vec>, /// A stack of loops the visitor is currently in. loops: Vec, + /// Local variables created in the expression. These don't need to be captured. + locals: HirIdSet, } impl<'tcx> InsertSearcher<'_, 'tcx> { /// Visit the expression as a branch in control flow. Multiple insert calls can be used, but @@ -385,13 +391,16 @@ impl<'tcx> Visitor<'tcx> for InsertSearcher<'_, 'tcx> { } }, StmtKind::Expr(e) => self.visit_expr(e), - StmtKind::Local(Local { init: Some(e), .. }) => { - self.allow_insert_closure &= !self.in_tail_pos; - self.in_tail_pos = false; - self.is_single_insert = false; - self.visit_expr(e); + StmtKind::Local(l) => { + self.visit_pat(l.pat); + if let Some(e) = l.init { + self.allow_insert_closure &= !self.in_tail_pos; + self.in_tail_pos = false; + self.is_single_insert = false; + self.visit_expr(e); + } }, - _ => { + StmtKind::Item(_) => { self.allow_insert_closure &= !self.in_tail_pos; self.is_single_insert = false; }, @@ -473,6 +482,7 @@ impl<'tcx> Visitor<'tcx> for InsertSearcher<'_, 'tcx> { // Each branch may contain it's own insert expression. let mut is_map_used = self.is_map_used; for arm in arms { + self.visit_pat(arm.pat); if let Some(Guard::If(guard) | Guard::IfLet(_, guard)) = arm.guard { self.visit_non_tail_expr(guard); } @@ -498,7 +508,8 @@ impl<'tcx> Visitor<'tcx> for InsertSearcher<'_, 'tcx> { }, _ => { self.allow_insert_closure &= !self.in_tail_pos; - self.allow_insert_closure &= can_move_expr_to_closure_no_visit(self.cx, expr, &self.loops); + self.allow_insert_closure &= + can_move_expr_to_closure_no_visit(self.cx, expr, &self.loops, &self.locals); // Sub expressions are no longer in the tail position. self.is_single_insert = false; self.in_tail_pos = false; @@ -507,6 +518,12 @@ impl<'tcx> Visitor<'tcx> for InsertSearcher<'_, 'tcx> { }, } } + + fn visit_pat(&mut self, p: &'tcx Pat<'tcx>) { + p.each_binding_or_first(&mut |_, id, _, _| { + self.locals.insert(id); + }); + } } struct InsertSearchResults<'tcx> { @@ -632,6 +649,7 @@ fn find_insert_calls( in_tail_pos: true, is_single_insert: true, loops: Vec::new(), + locals: HirIdSet::default(), }; s.visit_expr(expr); let allow_insert_closure = s.allow_insert_closure; diff --git a/src/tools/clippy/clippy_lints/src/equatable_if_let.rs b/src/tools/clippy/clippy_lints/src/equatable_if_let.rs new file mode 100644 index 0000000000..0c6ba91c94 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/equatable_if_let.rs @@ -0,0 +1,100 @@ +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::source::snippet_with_applicability; +use clippy_utils::ty::implements_trait; +use if_chain::if_chain; +use rustc_errors::Applicability; +use rustc_hir::{Expr, ExprKind, Pat, PatKind}; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::ty::Ty; +use rustc_session::{declare_lint_pass, declare_tool_lint}; + +declare_clippy_lint! { + /// ### What it does + /// Checks for pattern matchings that can be expressed using equality. + /// + /// ### Why is this bad? + /// + /// * It reads better and has less cognitive load because equality won't cause binding. + /// * It is a [Yoda condition](https://en.wikipedia.org/wiki/Yoda_conditions). Yoda conditions are widely + /// criticized for increasing the cognitive load of reading the code. + /// * Equality is a simple bool expression and can be merged with `&&` and `||` and + /// reuse if blocks + /// + /// ### Example + /// ```rust,ignore + /// if let Some(2) = x { + /// do_thing(); + /// } + /// ``` + /// Should be written + /// ```rust,ignore + /// if x == Some(2) { + /// do_thing(); + /// } + /// ``` + pub EQUATABLE_IF_LET, + nursery, + "using pattern matching instead of equality" +} + +declare_lint_pass!(PatternEquality => [EQUATABLE_IF_LET]); + +/// detects if pattern matches just one thing +fn unary_pattern(pat: &Pat<'_>) -> bool { + fn array_rec(pats: &[Pat<'_>]) -> bool { + pats.iter().all(unary_pattern) + } + match &pat.kind { + PatKind::Slice(_, _, _) | PatKind::Range(_, _, _) | PatKind::Binding(..) | PatKind::Wild | PatKind::Or(_) => { + false + }, + PatKind::Struct(_, a, etc) => !etc && a.iter().all(|x| unary_pattern(x.pat)), + PatKind::Tuple(a, etc) | PatKind::TupleStruct(_, a, etc) => !etc.is_some() && array_rec(a), + PatKind::Ref(x, _) | PatKind::Box(x) => unary_pattern(x), + PatKind::Path(_) | PatKind::Lit(_) => true, + } +} + +fn is_structural_partial_eq(cx: &LateContext<'tcx>, ty: Ty<'tcx>, other: Ty<'tcx>) -> bool { + if let Some(def_id) = cx.tcx.lang_items().eq_trait() { + implements_trait(cx, ty, def_id, &[other.into()]) + } else { + false + } +} + +impl<'tcx> LateLintPass<'tcx> for PatternEquality { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { + if_chain! { + if let ExprKind::Let(pat, exp, _) = expr.kind; + if unary_pattern(pat); + let exp_ty = cx.typeck_results().expr_ty(exp); + let pat_ty = cx.typeck_results().pat_ty(pat); + if is_structural_partial_eq(cx, exp_ty, pat_ty); + then { + + let mut applicability = Applicability::MachineApplicable; + let pat_str = match pat.kind { + PatKind::Struct(..) => format!( + "({})", + snippet_with_applicability(cx, pat.span, "..", &mut applicability), + ), + _ => snippet_with_applicability(cx, pat.span, "..", &mut applicability).to_string(), + }; + span_lint_and_sugg( + cx, + EQUATABLE_IF_LET, + expr.span, + "this pattern matching can be expressed using equality", + "try", + format!( + "{} == {}", + snippet_with_applicability(cx, exp.span, "..", &mut applicability), + pat_str, + ), + applicability, + ); + } + } + } +} diff --git a/src/tools/clippy/clippy_lints/src/erasing_op.rs b/src/tools/clippy/clippy_lints/src/erasing_op.rs index 026d14d0ea..d0944c37cf 100644 --- a/src/tools/clippy/clippy_lints/src/erasing_op.rs +++ b/src/tools/clippy/clippy_lints/src/erasing_op.rs @@ -47,7 +47,7 @@ impl<'tcx> LateLintPass<'tcx> for ErasingOp { } fn check(cx: &LateContext<'_>, e: &Expr<'_>, span: Span) { - if let Some(Constant::Int(0)) = constant_simple(cx, cx.typeck_results(), e) { + if constant_simple(cx, cx.typeck_results(), e) == Some(Constant::Int(0)) { span_lint( cx, ERASING_OP, diff --git a/src/tools/clippy/clippy_lints/src/escape.rs b/src/tools/clippy/clippy_lints/src/escape.rs index 685dbf2625..75b1c882c2 100644 --- a/src/tools/clippy/clippy_lints/src/escape.rs +++ b/src/tools/clippy/clippy_lints/src/escape.rs @@ -5,11 +5,11 @@ use rustc_hir::{self, AssocItemKind, Body, FnDecl, HirId, HirIdSet, Impl, ItemKi use rustc_infer::infer::TyCtxtInferExt; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::mir::FakeReadCause; +use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::{self, TraitRef, Ty}; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::source_map::Span; use rustc_span::symbol::kw; -use rustc_target::abi::LayoutOf; use rustc_target::spec::abi::Abi; use rustc_typeck::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId}; @@ -90,9 +90,12 @@ impl<'tcx> LateLintPass<'tcx> for BoxedLocal { for trait_item in items { if trait_item.id.hir_id() == hir_id { // be sure we have `self` parameter in this function - if let AssocItemKind::Fn { has_self: true } = trait_item.kind { - trait_self_ty = - Some(TraitRef::identity(cx.tcx, trait_item.id.def_id.to_def_id()).self_ty()); + if trait_item.kind == (AssocItemKind::Fn { has_self: true }) { + trait_self_ty = Some( + TraitRef::identity(cx.tcx, trait_item.id.def_id.to_def_id()) + .self_ty() + .skip_binder(), + ); } } } @@ -171,7 +174,8 @@ impl<'a, 'tcx> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> { // skip if there is a `self` parameter binding to a type // that contains `Self` (i.e.: `self: Box`), see #4804 if let Some(trait_self_ty) = self.trait_self_ty { - if map.name(cmt.hir_id) == kw::SelfLower && contains_ty(self.cx.tcx, cmt.place.ty(), trait_self_ty) { + if map.name(cmt.hir_id) == kw::SelfLower && contains_ty(self.cx.tcx, cmt.place.ty(), trait_self_ty) + { return; } } diff --git a/src/tools/clippy/clippy_lints/src/eta_reduction.rs b/src/tools/clippy/clippy_lints/src/eta_reduction.rs index f6a64a8ca6..9247343b52 100644 --- a/src/tools/clippy/clippy_lints/src/eta_reduction.rs +++ b/src/tools/clippy/clippy_lints/src/eta_reduction.rs @@ -1,16 +1,16 @@ use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then}; use clippy_utils::higher::VecArgs; use clippy_utils::source::snippet_opt; -use clippy_utils::ty::{implements_trait, type_is_unsafe_function}; use clippy_utils::usage::UsedAfterExprVisitor; -use clippy_utils::{get_enclosing_loop_or_closure, higher}; -use clippy_utils::{is_adjusted, iter_input_pats}; +use clippy_utils::{get_enclosing_loop_or_closure, higher, path_to_local_id}; use if_chain::if_chain; use rustc_errors::Applicability; -use rustc_hir::{def_id, Expr, ExprKind, Param, PatKind, QPath}; -use rustc_lint::{LateContext, LateLintPass, LintContext}; -use rustc_middle::lint::in_external_macro; -use rustc_middle::ty::{self, ClosureKind, Ty}; +use rustc_hir::def_id::DefId; +use rustc_hir::{Expr, ExprKind, Param, PatKind, Unsafety}; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow}; +use rustc_middle::ty::subst::Subst; +use rustc_middle::ty::{self, ClosureKind, Ty, TypeFoldable}; use rustc_session::{declare_lint_pass, declare_tool_lint}; declare_clippy_lint! { @@ -52,12 +52,6 @@ declare_clippy_lint! { /// ### Why is this bad? /// It's unnecessary to create the closure. /// - /// ### Known problems - /// [#3071](https://github.com/rust-lang/rust-clippy/issues/3071), - /// [#3942](https://github.com/rust-lang/rust-clippy/issues/3942), - /// [#4002](https://github.com/rust-lang/rust-clippy/issues/4002) - /// - /// /// ### Example /// ```rust,ignore /// Some('a').map(|s| s.to_uppercase()); @@ -75,32 +69,16 @@ declare_lint_pass!(EtaReduction => [REDUNDANT_CLOSURE, REDUNDANT_CLOSURE_FOR_MET impl<'tcx> LateLintPass<'tcx> for EtaReduction { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { - if in_external_macro(cx.sess(), expr.span) { + if expr.span.from_expansion() { return; } - - match expr.kind { - ExprKind::Call(_, args) | ExprKind::MethodCall(_, _, args, _) => { - for arg in args { - // skip `foo(macro!())` - if arg.span.ctxt() == expr.span.ctxt() { - check_closure(cx, arg); - } - } - }, - _ => (), - } - } -} - -fn check_closure<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { - if let ExprKind::Closure(_, decl, eid, _, _) = expr.kind { - let body = cx.tcx.hir().body(eid); - let ex = &body.value; - - if ex.span.ctxt() != expr.span.ctxt() { - if decl.inputs.is_empty() { - if let Some(VecArgs::Vec(&[])) = higher::VecArgs::hir(cx, ex) { + let body = match expr.kind { + ExprKind::Closure(_, _, id, _, _) => cx.tcx.hir().body(id), + _ => return, + }; + if body.value.span.from_expansion() { + if body.params.is_empty() { + if let Some(VecArgs::Vec(&[])) = higher::VecArgs::hir(cx, &body.value) { // replace `|| vec![]` with `Vec::new` span_lint_and_sugg( cx, @@ -117,33 +95,30 @@ fn check_closure<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { return; } + let closure_ty = cx.typeck_results().expr_ty(expr); + if_chain!( - if let ExprKind::Call(caller, args) = ex.kind; - - if let ExprKind::Path(_) = caller.kind; - - // Not the same number of arguments, there is no way the closure is the same as the function return; - if args.len() == decl.inputs.len(); - - // Are the expression or the arguments type-adjusted? Then we need the closure - if !(is_adjusted(cx, ex) || args.iter().any(|arg| is_adjusted(cx, arg))); - - let fn_ty = cx.typeck_results().expr_ty(caller); - - if matches!(fn_ty.kind(), ty::FnDef(_, _) | ty::FnPtr(_) | ty::Closure(_, _)); - - if !type_is_unsafe_function(cx, fn_ty); - - if compare_inputs(&mut iter_input_pats(decl, body), &mut args.iter()); - + if let ExprKind::Call(callee, args) = body.value.kind; + if let ExprKind::Path(_) = callee.kind; + if check_inputs(cx, body.params, args); + let callee_ty = cx.typeck_results().expr_ty_adjusted(callee); + let call_ty = cx.typeck_results().type_dependent_def_id(body.value.hir_id) + .map_or(callee_ty, |id| cx.tcx.type_of(id)); + if check_sig(cx, closure_ty, call_ty); + let substs = cx.typeck_results().node_substs(callee.hir_id); + // This fixes some false positives that I don't entirely understand + if substs.is_empty() || !cx.typeck_results().expr_ty(expr).has_late_bound_regions(); + // A type param function ref like `T::f` is not 'static, however + // it is if cast like `T::f as fn()`. This seems like a rustc bug. + if !substs.types().any(|t| matches!(t.kind(), ty::Param(_))); then { span_lint_and_then(cx, REDUNDANT_CLOSURE, expr.span, "redundant closure", |diag| { - if let Some(mut snippet) = snippet_opt(cx, caller.span) { + if let Some(mut snippet) = snippet_opt(cx, callee.span) { if_chain! { - if let ty::Closure(_, substs) = fn_ty.kind(); - if let ClosureKind::FnMut = substs.as_closure().kind(); - if UsedAfterExprVisitor::is_found(cx, caller) - || get_enclosing_loop_or_closure(cx.tcx, expr).is_some(); + if let ty::Closure(_, substs) = callee_ty.peel_refs().kind(); + if substs.as_closure().kind() == ClosureKind::FnMut; + if get_enclosing_loop_or_closure(cx.tcx, expr).is_some() + || UsedAfterExprVisitor::is_found(cx, callee); then { // Mutable closure is used after current expr; we cannot consume it. @@ -162,110 +137,82 @@ fn check_closure<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { ); if_chain!( - if let ExprKind::MethodCall(path, _, args, _) = ex.kind; - - // Not the same number of arguments, there is no way the closure is the same as the function return; - if args.len() == decl.inputs.len(); - - // Are the expression or the arguments type-adjusted? Then we need the closure - if !(is_adjusted(cx, ex) || args.iter().skip(1).any(|arg| is_adjusted(cx, arg))); - - let method_def_id = cx.typeck_results().type_dependent_def_id(ex.hir_id).unwrap(); - if !type_is_unsafe_function(cx, cx.tcx.type_of(method_def_id)); - - if compare_inputs(&mut iter_input_pats(decl, body), &mut args.iter()); - - if let Some(name) = get_ufcs_type_name(cx, method_def_id, &args[0]); - + if let ExprKind::MethodCall(path, _, args, _) = body.value.kind; + if check_inputs(cx, body.params, args); + let method_def_id = cx.typeck_results().type_dependent_def_id(body.value.hir_id).unwrap(); + let substs = cx.typeck_results().node_substs(body.value.hir_id); + let call_ty = cx.tcx.type_of(method_def_id).subst(cx.tcx, substs); + if check_sig(cx, closure_ty, call_ty); then { - span_lint_and_sugg( - cx, - REDUNDANT_CLOSURE_FOR_METHOD_CALLS, - expr.span, - "redundant closure", - "replace the closure with the method itself", - format!("{}::{}", name, path.ident.name), - Applicability::MachineApplicable, - ); + span_lint_and_then(cx, REDUNDANT_CLOSURE_FOR_METHOD_CALLS, expr.span, "redundant closure", |diag| { + let name = get_ufcs_type_name(cx, method_def_id); + diag.span_suggestion( + expr.span, + "replace the closure with the method itself", + format!("{}::{}", name, path.ident.name), + Applicability::MachineApplicable, + ); + }) } ); } } -/// Tries to determine the type for universal function call to be used instead of the closure -fn get_ufcs_type_name(cx: &LateContext<'_>, method_def_id: def_id::DefId, self_arg: &Expr<'_>) -> Option { - let expected_type_of_self = &cx.tcx.fn_sig(method_def_id).inputs_and_output().skip_binder()[0]; - let actual_type_of_self = &cx.typeck_results().node_type(self_arg.hir_id); - - if let Some(trait_id) = cx.tcx.trait_of_item(method_def_id) { - if match_borrow_depth(expected_type_of_self, actual_type_of_self) - && implements_trait(cx, actual_type_of_self, trait_id, &[]) - { - return Some(cx.tcx.def_path_str(trait_id)); - } +fn check_inputs(cx: &LateContext<'_>, params: &[Param<'_>], call_args: &[Expr<'_>]) -> bool { + if params.len() != call_args.len() { + return false; } - - cx.tcx.impl_of_method(method_def_id).and_then(|_| { - //a type may implicitly implement other type's methods (e.g. Deref) - if match_types(expected_type_of_self, actual_type_of_self) { - Some(get_type_name(cx, actual_type_of_self)) - } else { - None + std::iter::zip(params, call_args).all(|(param, arg)| { + match param.pat.kind { + PatKind::Binding(_, id, ..) if path_to_local_id(arg, id) => {}, + _ => return false, + } + match *cx.typeck_results().expr_adjustments(arg) { + [] => true, + [ + Adjustment { + kind: Adjust::Deref(None), + .. + }, + Adjustment { + kind: Adjust::Borrow(AutoBorrow::Ref(_, mu2)), + .. + }, + ] => { + // re-borrow with the same mutability is allowed + let ty = cx.typeck_results().expr_ty(arg); + matches!(*ty.kind(), ty::Ref(.., mu1) if mu1 == mu2.into()) + }, + _ => false, } }) } -fn match_borrow_depth(lhs: Ty<'_>, rhs: Ty<'_>) -> bool { - match (&lhs.kind(), &rhs.kind()) { - (ty::Ref(_, t1, mut1), ty::Ref(_, t2, mut2)) => mut1 == mut2 && match_borrow_depth(t1, t2), - (l, r) => !matches!((l, r), (ty::Ref(_, _, _), _) | (_, ty::Ref(_, _, _))), +fn check_sig<'tcx>(cx: &LateContext<'tcx>, closure_ty: Ty<'tcx>, call_ty: Ty<'tcx>) -> bool { + let call_sig = call_ty.fn_sig(cx.tcx); + if call_sig.unsafety() == Unsafety::Unsafe { + return false; } + if !closure_ty.has_late_bound_regions() { + return true; + } + let substs = match closure_ty.kind() { + ty::Closure(_, substs) => substs, + _ => return false, + }; + let closure_sig = cx.tcx.signature_unclosure(substs.as_closure().sig(), Unsafety::Normal); + cx.tcx.erase_late_bound_regions(closure_sig) == cx.tcx.erase_late_bound_regions(call_sig) } -fn match_types(lhs: Ty<'_>, rhs: Ty<'_>) -> bool { - match (&lhs.kind(), &rhs.kind()) { - (ty::Bool, ty::Bool) - | (ty::Char, ty::Char) - | (ty::Int(_), ty::Int(_)) - | (ty::Uint(_), ty::Uint(_)) - | (ty::Str, ty::Str) => true, - (ty::Ref(_, t1, mut1), ty::Ref(_, t2, mut2)) => mut1 == mut2 && match_types(t1, t2), - (ty::Array(t1, _), ty::Array(t2, _)) | (ty::Slice(t1), ty::Slice(t2)) => match_types(t1, t2), - (ty::Adt(def1, _), ty::Adt(def2, _)) => def1 == def2, - (_, _) => false, - } -} - -fn get_type_name(cx: &LateContext<'_>, ty: Ty<'_>) -> String { - match ty.kind() { - ty::Adt(t, _) => cx.tcx.def_path_str(t.did), - ty::Ref(_, r, _) => get_type_name(cx, r), - _ => ty.to_string(), - } -} - -fn compare_inputs( - closure_inputs: &mut dyn Iterator>, - call_args: &mut dyn Iterator>, -) -> bool { - for (closure_input, function_arg) in closure_inputs.zip(call_args) { - if let PatKind::Binding(_, _, ident, _) = closure_input.pat.kind { - // XXXManishearth Should I be checking the binding mode here? - if let ExprKind::Path(QPath::Resolved(None, p)) = function_arg.kind { - if p.segments.len() != 1 { - // If it's a proper path, it can't be a local variable - return false; - } - if p.segments[0].ident.name != ident.name { - // The two idents should be the same - return false; - } - } else { - return false; +fn get_ufcs_type_name(cx: &LateContext<'_>, method_def_id: DefId) -> String { + match cx.tcx.associated_item(method_def_id).container { + ty::TraitContainer(def_id) => cx.tcx.def_path_str(def_id), + ty::ImplContainer(def_id) => { + let ty = cx.tcx.type_of(def_id); + match ty.kind() { + ty::Adt(adt, _) => cx.tcx.def_path_str(adt.did), + _ => ty.to_string(), } - } else { - return false; - } + }, } - true } diff --git a/src/tools/clippy/clippy_lints/src/eval_order_dependence.rs b/src/tools/clippy/clippy_lints/src/eval_order_dependence.rs index f72a1e446d..1b56dd4b08 100644 --- a/src/tools/clippy/clippy_lints/src/eval_order_dependence.rs +++ b/src/tools/clippy/clippy_lints/src/eval_order_dependence.rs @@ -15,8 +15,8 @@ declare_clippy_lint! { /// order of sub-expressions. /// /// ### Why is this bad? - /// It is often confusing to read. In addition, the - /// sub-expression evaluation order for Rust is not well documented. + /// It is often confusing to read. As described [here](https://doc.rust-lang.org/reference/expressions.html?highlight=subexpression#evaluation-order-of-operands), + /// the operands of these expressions are evaluated before applying the effects of the expression. /// /// ### Known problems /// Code which intentionally depends on the evaluation @@ -141,7 +141,7 @@ impl<'a, 'tcx> Visitor<'tcx> for DivergenceVisitor<'a, 'tcx> { match typ.kind() { ty::FnDef(..) | ty::FnPtr(_) => { let sig = typ.fn_sig(self.cx.tcx); - if let ty::Never = self.cx.tcx.erase_late_bound_regions(sig).output().kind() { + if self.cx.tcx.erase_late_bound_regions(sig).output().kind() == &ty::Never { self.report_diverging_sub_expr(e); } }, diff --git a/src/tools/clippy/clippy_lints/src/fallible_impl_from.rs b/src/tools/clippy/clippy_lints/src/fallible_impl_from.rs index 7e4d1b3ef9..70337f5bbe 100644 --- a/src/tools/clippy/clippy_lints/src/fallible_impl_from.rs +++ b/src/tools/clippy/clippy_lints/src/fallible_impl_from.rs @@ -57,7 +57,7 @@ impl<'tcx> LateLintPass<'tcx> for FallibleImplFrom { if_chain! { if let hir::ItemKind::Impl(impl_) = &item.kind; if let Some(impl_trait_ref) = cx.tcx.impl_trait_ref(item.def_id); - if cx.tcx.is_diagnostic_item(sym::from_trait, impl_trait_ref.def_id); + if cx.tcx.is_diagnostic_item(sym::From, impl_trait_ref.def_id); then { lint_impl_body(cx, item.span, impl_.items); } @@ -65,7 +65,7 @@ impl<'tcx> LateLintPass<'tcx> for FallibleImplFrom { } } -fn lint_impl_body<'tcx>(cx: &LateContext<'tcx>, impl_span: Span, impl_items: &[hir::ImplItemRef<'_>]) { +fn lint_impl_body<'tcx>(cx: &LateContext<'tcx>, impl_span: Span, impl_items: &[hir::ImplItemRef]) { use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc_hir::{Expr, ExprKind, ImplItemKind, QPath}; @@ -94,8 +94,8 @@ fn lint_impl_body<'tcx>(cx: &LateContext<'tcx>, impl_span: Span, impl_items: &[h // 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.lcx, reciever_ty, sym::option_type) - || is_type_diagnostic_item(self.lcx, reciever_ty, sym::result_type) + if is_type_diagnostic_item(self.lcx, reciever_ty, sym::Option) + || is_type_diagnostic_item(self.lcx, reciever_ty, sym::Result) { self.result.push(expr.span); } diff --git a/src/tools/clippy/clippy_lints/src/feature_name.rs b/src/tools/clippy/clippy_lints/src/feature_name.rs new file mode 100644 index 0000000000..f534327f7a --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/feature_name.rs @@ -0,0 +1,164 @@ +use clippy_utils::diagnostics::span_lint_and_help; +use clippy_utils::{diagnostics::span_lint, is_lint_allowed}; +use rustc_hir::CRATE_HIR_ID; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_span::source_map::DUMMY_SP; + +declare_clippy_lint! { + /// ### What it does + /// Checks for feature names with prefix `use-`, `with-` or suffix `-support` + /// + /// ### Why is this bad? + /// These prefixes and suffixes have no significant meaning. + /// + /// ### Example + /// ```toml + /// # The `Cargo.toml` with feature name redundancy + /// [features] + /// default = ["use-abc", "with-def", "ghi-support"] + /// use-abc = [] // redundant + /// with-def = [] // redundant + /// ghi-support = [] // redundant + /// ``` + /// + /// Use instead: + /// ```toml + /// [features] + /// default = ["abc", "def", "ghi"] + /// abc = [] + /// def = [] + /// ghi = [] + /// ``` + /// + pub REDUNDANT_FEATURE_NAMES, + cargo, + "usage of a redundant feature name" +} + +declare_clippy_lint! { + /// ### What it does + /// Checks for negative feature names with prefix `no-` or `not-` + /// + /// ### Why is this bad? + /// Features are supposed to be additive, and negatively-named features violate it. + /// + /// ### Example + /// ```toml + /// # The `Cargo.toml` with negative feature names + /// [features] + /// default = [] + /// no-abc = [] + /// not-def = [] + /// + /// ``` + /// Use instead: + /// ```toml + /// [features] + /// default = ["abc", "def"] + /// abc = [] + /// def = [] + /// + /// ``` + pub NEGATIVE_FEATURE_NAMES, + cargo, + "usage of a negative feature name" +} + +declare_lint_pass!(FeatureName => [REDUNDANT_FEATURE_NAMES, NEGATIVE_FEATURE_NAMES]); + +static PREFIXES: [&str; 8] = ["no-", "no_", "not-", "not_", "use-", "use_", "with-", "with_"]; +static SUFFIXES: [&str; 2] = ["-support", "_support"]; + +fn is_negative_prefix(s: &str) -> bool { + s.starts_with("no") +} + +fn lint(cx: &LateContext<'_>, feature: &str, substring: &str, is_prefix: bool) { + let is_negative = is_prefix && is_negative_prefix(substring); + span_lint_and_help( + cx, + if is_negative { + NEGATIVE_FEATURE_NAMES + } else { + REDUNDANT_FEATURE_NAMES + }, + DUMMY_SP, + &format!( + "the \"{}\" {} in the feature name \"{}\" is {}", + substring, + if is_prefix { "prefix" } else { "suffix" }, + feature, + if is_negative { "negative" } else { "redundant" } + ), + None, + &format!( + "consider renaming the feature to \"{}\"{}", + if is_prefix { + feature.strip_prefix(substring) + } else { + feature.strip_suffix(substring) + } + .unwrap(), + if is_negative { + ", but make sure the feature adds functionality" + } else { + "" + } + ), + ); +} + +impl LateLintPass<'_> for FeatureName { + fn check_crate(&mut self, cx: &LateContext<'_>) { + if is_lint_allowed(cx, REDUNDANT_FEATURE_NAMES, CRATE_HIR_ID) + && is_lint_allowed(cx, NEGATIVE_FEATURE_NAMES, CRATE_HIR_ID) + { + return; + } + + let metadata = unwrap_cargo_metadata!(cx, REDUNDANT_FEATURE_NAMES, false); + + for package in metadata.packages { + let mut features: Vec<&String> = package.features.keys().collect(); + features.sort(); + for feature in features { + let prefix_opt = { + let i = PREFIXES.partition_point(|prefix| prefix < &feature.as_str()); + if i > 0 && feature.starts_with(PREFIXES[i - 1]) { + Some(PREFIXES[i - 1]) + } else { + None + } + }; + if let Some(prefix) = prefix_opt { + lint(cx, feature, prefix, true); + } + + let suffix_opt: Option<&str> = { + let i = SUFFIXES.partition_point(|suffix| { + suffix.bytes().rev().cmp(feature.bytes().rev()) == std::cmp::Ordering::Less + }); + if i > 0 && feature.ends_with(SUFFIXES[i - 1]) { + Some(SUFFIXES[i - 1]) + } else { + None + } + }; + if let Some(suffix) = suffix_opt { + lint(cx, feature, suffix, false); + } + } + } + } +} + +#[test] +fn test_prefixes_sorted() { + let mut sorted_prefixes = PREFIXES; + sorted_prefixes.sort_unstable(); + assert_eq!(PREFIXES, sorted_prefixes); + let mut sorted_suffixes = SUFFIXES; + sorted_suffixes.sort_by(|a, b| a.bytes().rev().cmp(b.bytes().rev())); + assert_eq!(SUFFIXES, sorted_suffixes); +} diff --git a/src/tools/clippy/clippy_lints/src/float_literal.rs b/src/tools/clippy/clippy_lints/src/float_literal.rs index a3d70f31f0..1e8a5bd7d3 100644 --- a/src/tools/clippy/clippy_lints/src/float_literal.rs +++ b/src/tools/clippy/clippy_lints/src/float_literal.rs @@ -111,7 +111,7 @@ impl<'tcx> LateLintPass<'tcx> for FloatLiteral { Applicability::MachineApplicable, ); } - } else if digits > max as usize && sym_str != float_str { + } else if digits > max as usize && float_str.len() < sym_str.len() { span_lint_and_sugg( cx, EXCESSIVE_PRECISION, diff --git a/src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs b/src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs index d12482e7b7..eda611117b 100644 --- a/src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs +++ b/src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs @@ -332,8 +332,6 @@ fn check_powi(cx: &LateContext<'_>, expr: &Expr<'_>, args: &[Expr<'_>]) { ), Applicability::MachineApplicable, ); - - return; } } } @@ -364,22 +362,22 @@ fn detect_hypot(cx: &LateContext<'_>, args: &[Expr<'_>]) -> Option { if_chain! { if let ExprKind::MethodCall( PathSegment { ident: lmethod_name, .. }, - ref _lspan, - largs, + _lspan, + [largs_0, largs_1, ..], _ - ) = add_lhs.kind; + ) = &add_lhs.kind; if let ExprKind::MethodCall( PathSegment { ident: rmethod_name, .. }, - ref _rspan, - rargs, + _rspan, + [rargs_0, rargs_1, ..], _ - ) = add_rhs.kind; + ) = &add_rhs.kind; if lmethod_name.as_str() == "powi" && rmethod_name.as_str() == "powi"; - if let Some((lvalue, _)) = constant(cx, cx.typeck_results(), &largs[1]); - if let Some((rvalue, _)) = constant(cx, cx.typeck_results(), &rargs[1]); + if let Some((lvalue, _)) = constant(cx, cx.typeck_results(), largs_1); + if let Some((rvalue, _)) = constant(cx, cx.typeck_results(), rargs_1); if Int(2) == lvalue && Int(2) == rvalue; then { - return Some(format!("{}.hypot({})", Sugg::hir(cx, &largs[0], ".."), Sugg::hir(cx, &rargs[0], ".."))); + return Some(format!("{}.hypot({})", Sugg::hir(cx, largs_0, ".."), Sugg::hir(cx, rargs_0, ".."))); } } } @@ -409,8 +407,8 @@ fn check_expm1(cx: &LateContext<'_>, expr: &Expr<'_>) { if cx.typeck_results().expr_ty(lhs).is_floating_point(); if let Some((value, _)) = constant(cx, cx.typeck_results(), rhs); if F32(1.0) == value || F64(1.0) == value; - if let ExprKind::MethodCall(path, _, method_args, _) = lhs.kind; - if cx.typeck_results().expr_ty(&method_args[0]).is_floating_point(); + if let ExprKind::MethodCall(path, _, [self_arg, ..], _) = &lhs.kind; + if cx.typeck_results().expr_ty(self_arg).is_floating_point(); if path.ident.name.as_str() == "exp"; then { span_lint_and_sugg( @@ -421,7 +419,7 @@ fn check_expm1(cx: &LateContext<'_>, expr: &Expr<'_>) { "consider using", format!( "{}.exp_m1()", - Sugg::hir(cx, &method_args[0], "..") + Sugg::hir(cx, self_arg, "..") ), Applicability::MachineApplicable, ); @@ -619,8 +617,8 @@ fn check_log_division(cx: &LateContext<'_>, expr: &Expr<'_>) { rhs, ) = &expr.kind; if are_same_base_logs(cx, lhs, rhs); - if let ExprKind::MethodCall(_, _, largs, _) = lhs.kind; - if let ExprKind::MethodCall(_, _, rargs, _) = rhs.kind; + if let ExprKind::MethodCall(_, _, [largs_self, ..], _) = &lhs.kind; + if let ExprKind::MethodCall(_, _, [rargs_self, ..], _) = &rhs.kind; then { span_lint_and_sugg( cx, @@ -628,7 +626,7 @@ fn check_log_division(cx: &LateContext<'_>, expr: &Expr<'_>) { expr.span, "log base can be expressed more clearly", "consider using", - format!("{}.log({})", Sugg::hir(cx, &largs[0], ".."), Sugg::hir(cx, &rargs[0], ".."),), + format!("{}.log({})", Sugg::hir(cx, largs_self, ".."), Sugg::hir(cx, rargs_self, ".."),), Applicability::MachineApplicable, ); } diff --git a/src/tools/clippy/clippy_lints/src/format.rs b/src/tools/clippy/clippy_lints/src/format.rs index 863c606f5a..37d9ea3bdc 100644 --- a/src/tools/clippy/clippy_lints/src/format.rs +++ b/src/tools/clippy/clippy_lints/src/format.rs @@ -65,12 +65,12 @@ impl<'tcx> LateLintPass<'tcx> for UselessFormat { if_chain! { if format_args.format_string_symbols == [kw::Empty]; if match cx.typeck_results().expr_ty(value).peel_refs().kind() { - ty::Adt(adt, _) => cx.tcx.is_diagnostic_item(sym::string_type, adt.did), + ty::Adt(adt, _) => cx.tcx.is_diagnostic_item(sym::String, adt.did), ty::Str => true, _ => false, }; - if format_args.args.iter().all(|e| is_display_arg(e)); - if format_args.fmt_expr.map_or(true, |e| check_unformatted(e)); + if format_args.args.iter().all(is_display_arg); + if format_args.fmt_expr.map_or(true, check_unformatted); then { let is_new_string = match value.kind { ExprKind::Binary(..) => true, @@ -90,12 +90,7 @@ impl<'tcx> LateLintPass<'tcx> for UselessFormat { } } -fn span_useless_format(cx: &LateContext<'_>, span: Span, mut sugg: String, mut applicability: Applicability) { - // The callsite span contains the statement semicolon for some reason. - if snippet_with_applicability(cx, span, "..", &mut applicability).ends_with(';') { - sugg.push(';'); - } - +fn span_useless_format(cx: &LateContext<'_>, span: Span, sugg: String, applicability: Applicability) { span_lint_and_sugg( cx, USELESS_FORMAT, @@ -112,7 +107,7 @@ fn is_display_arg(expr: &Expr<'_>) -> bool { if let ExprKind::Call(_, [_, fmt]) = expr.kind; if let ExprKind::Path(QPath::Resolved(_, path)) = fmt.kind; if let [.., t, _] = path.segments; - if t.ident.name.as_str() == "Display"; + if t.ident.name == sym::Display; then { true } else { false } } } diff --git a/src/tools/clippy/clippy_lints/src/formatting.rs b/src/tools/clippy/clippy_lints/src/formatting.rs index 4dd0ffe77e..b4f186525c 100644 --- a/src/tools/clippy/clippy_lints/src/formatting.rs +++ b/src/tools/clippy/clippy_lints/src/formatting.rs @@ -286,34 +286,39 @@ fn check_array(cx: &EarlyContext<'_>, expr: &Expr) { } fn check_missing_else(cx: &EarlyContext<'_>, first: &Expr, second: &Expr) { - if !differing_macro_contexts(first.span, second.span) - && !first.span.from_expansion() - && is_if(first) - && (is_block(second) || is_if(second)) - { - // where the else would be + if_chain! { + if !differing_macro_contexts(first.span, second.span); + if !first.span.from_expansion(); + if let ExprKind::If(cond_expr, ..) = &first.kind; + if is_block(second) || is_if(second); + + // Proc-macros can give weird spans. Make sure this is actually an `if`. + if let Some(if_snip) = snippet_opt(cx, first.span.until(cond_expr.span)); + if if_snip.starts_with("if"); + + // If there is a line break between the two expressions, don't lint. + // If there is a non-whitespace character, this span came from a proc-macro. let else_span = first.span.between(second.span); + if let Some(else_snippet) = snippet_opt(cx, else_span); + if !else_snippet.chars().any(|c| c == '\n' || !c.is_whitespace()); + then { + let (looks_like, next_thing) = if is_if(second) { + ("an `else if`", "the second `if`") + } else { + ("an `else {..}`", "the next block") + }; - if let Some(else_snippet) = snippet_opt(cx, else_span) { - if !else_snippet.contains('\n') { - let (looks_like, next_thing) = if is_if(second) { - ("an `else if`", "the second `if`") - } else { - ("an `else {..}`", "the next block") - }; - - span_lint_and_note( - cx, - SUSPICIOUS_ELSE_FORMATTING, - else_span, - &format!("this looks like {} but the `else` is missing", looks_like), - None, - &format!( - "to remove this lint, add the missing `else` or add a new line before {}", - next_thing, - ), - ); - } + span_lint_and_note( + cx, + SUSPICIOUS_ELSE_FORMATTING, + else_span, + &format!("this looks like {} but the `else` is missing", looks_like), + None, + &format!( + "to remove this lint, add the missing `else` or add a new line before {}", + next_thing, + ), + ); } } } diff --git a/src/tools/clippy/clippy_lints/src/from_over_into.rs b/src/tools/clippy/clippy_lints/src/from_over_into.rs index 623546cd1d..347c6eb12c 100644 --- a/src/tools/clippy/clippy_lints/src/from_over_into.rs +++ b/src/tools/clippy/clippy_lints/src/from_over_into.rs @@ -61,7 +61,7 @@ impl LateLintPass<'_> for FromOverInto { if_chain! { if let hir::ItemKind::Impl{ .. } = &item.kind; if let Some(impl_trait_ref) = cx.tcx.impl_trait_ref(item.def_id); - if cx.tcx.is_diagnostic_item(sym::into_trait, impl_trait_ref.def_id); + if cx.tcx.is_diagnostic_item(sym::Into, impl_trait_ref.def_id); then { span_lint_and_help( diff --git a/src/tools/clippy/clippy_lints/src/from_str_radix_10.rs b/src/tools/clippy/clippy_lints/src/from_str_radix_10.rs index cc4bb85c50..98ce3db025 100644 --- a/src/tools/clippy/clippy_lints/src/from_str_radix_10.rs +++ b/src/tools/clippy/clippy_lints/src/from_str_radix_10.rs @@ -98,5 +98,5 @@ impl LateLintPass<'tcx> for FromStrRadix10 { /// Checks if a Ty is `String` or `&str` fn is_ty_stringish(cx: &LateContext<'_>, ty: Ty<'_>) -> bool { - is_type_diagnostic_item(cx, ty, sym::string_type) || is_type_diagnostic_item(cx, ty, sym::str) + is_type_diagnostic_item(cx, ty, sym::String) || is_type_diagnostic_item(cx, ty, sym::str) } diff --git a/src/tools/clippy/clippy_lints/src/functions/must_use.rs b/src/tools/clippy/clippy_lints/src/functions/must_use.rs index ea6193acbe..77d08081c0 100644 --- a/src/tools/clippy/clippy_lints/src/functions/must_use.rs +++ b/src/tools/clippy/clippy_lints/src/functions/must_use.rs @@ -26,7 +26,6 @@ pub(super) fn check_item(cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) { let fn_header_span = item.span.with_hi(sig.decl.output.span().hi()); if let Some(attr) = attr { check_needless_must_use(cx, sig.decl, item.hir_id(), item.span, fn_header_span, attr); - return; } else if is_public && !is_proc_macro(cx.sess(), attrs) && !attrs.iter().any(|a| a.has_name(sym::no_mangle)) { check_must_use_candidate( cx, diff --git a/src/tools/clippy/clippy_lints/src/functions/result_unit_err.rs b/src/tools/clippy/clippy_lints/src/functions/result_unit_err.rs index 13863ec838..71f6f87ae6 100644 --- a/src/tools/clippy/clippy_lints/src/functions/result_unit_err.rs +++ b/src/tools/clippy/clippy_lints/src/functions/result_unit_err.rs @@ -48,7 +48,7 @@ fn check_result_unit_err(cx: &LateContext<'_>, decl: &hir::FnDecl<'_>, item_span if !in_external_macro(cx.sess(), item_span); if let hir::FnRetTy::Return(ty) = decl.output; let ty = hir_ty_to_ty(cx.tcx, ty); - if is_type_diagnostic_item(cx, ty, sym::result_type); + if is_type_diagnostic_item(cx, ty, sym::Result); if let ty::Adt(_, substs) = ty.kind(); let err_ty = substs.type_at(1); if err_ty.is_unit(); 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 3e35ada7b2..e18442515b 100644 --- a/src/tools/clippy/clippy_lints/src/future_not_send.rs +++ b/src/tools/clippy/clippy_lints/src/future_not_send.rs @@ -75,7 +75,7 @@ impl<'tcx> LateLintPass<'tcx> for FutureNotSend { } } if is_future { - let send_trait = cx.tcx.get_diagnostic_item(sym::send_trait).unwrap(); + 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 cause = traits::ObligationCause::misc(span, hir_id); diff --git a/src/tools/clippy/clippy_lints/src/get_last_with_len.rs b/src/tools/clippy/clippy_lints/src/get_last_with_len.rs index ced35030de..f3929b0f1e 100644 --- a/src/tools/clippy/clippy_lints/src/get_last_with_len.rs +++ b/src/tools/clippy/clippy_lints/src/get_last_with_len.rs @@ -58,7 +58,7 @@ impl<'tcx> LateLintPass<'tcx> for GetLastWithLen { // Argument 0 (the struct we're calling the method on) is a vector if let Some(struct_calling_on) = args.get(0); let struct_ty = cx.typeck_results().expr_ty(struct_calling_on); - if is_type_diagnostic_item(cx, struct_ty, sym::vec_type); + if is_type_diagnostic_item(cx, struct_ty, sym::Vec); // Argument to "get" is a subtraction if let Some(get_index_arg) = args.get(1); diff --git a/src/tools/clippy/clippy_lints/src/identity_op.rs b/src/tools/clippy/clippy_lints/src/identity_op.rs index 5feb0ce8de..73bdd67ff5 100644 --- a/src/tools/clippy/clippy_lints/src/identity_op.rs +++ b/src/tools/clippy/clippy_lints/src/identity_op.rs @@ -1,5 +1,4 @@ use clippy_utils::source::snippet; -use if_chain::if_chain; use rustc_hir::{BinOp, BinOpKind, Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty; @@ -62,16 +61,9 @@ impl<'tcx> LateLintPass<'tcx> for IdentityOp { fn is_allowed(cx: &LateContext<'_>, cmp: BinOp, left: &Expr<'_>, right: &Expr<'_>) -> bool { // `1 << 0` is a common pattern in bit manipulation code - if_chain! { - if let BinOpKind::Shl = cmp.node; - if let Some(Constant::Int(0)) = constant_simple(cx, cx.typeck_results(), right); - if let Some(Constant::Int(1)) = constant_simple(cx, cx.typeck_results(), left); - then { - return true; - } - } - - false + cmp.node == BinOpKind::Shl + && constant_simple(cx, cx.typeck_results(), right) == Some(Constant::Int(0)) + && constant_simple(cx, cx.typeck_results(), left) == Some(Constant::Int(1)) } #[allow(clippy::cast_possible_wrap)] diff --git a/src/tools/clippy/clippy_lints/src/if_let_mutex.rs b/src/tools/clippy/clippy_lints/src/if_let_mutex.rs index 7dad1c3115..a4118bf54b 100644 --- a/src/tools/clippy/clippy_lints/src/if_let_mutex.rs +++ b/src/tools/clippy/clippy_lints/src/if_let_mutex.rs @@ -8,6 +8,7 @@ use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::hir::map::Map; use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_span::sym; declare_clippy_lint! { /// ### What it does @@ -138,12 +139,12 @@ impl<'tcx, 'l> ArmVisitor<'tcx, 'l> { fn is_mutex_lock_call<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<&'tcx Expr<'tcx>> { if_chain! { - if let ExprKind::MethodCall(path, _span, args, _) = &expr.kind; + if let ExprKind::MethodCall(path, _span, [self_arg, ..], _) = &expr.kind; if path.ident.as_str() == "lock"; - let ty = cx.typeck_results().expr_ty(&args[0]); - if is_type_diagnostic_item(cx, ty, sym!(mutex_type)); + let ty = cx.typeck_results().expr_ty(self_arg); + if is_type_diagnostic_item(cx, ty, sym::Mutex); then { - Some(&args[0]) + Some(self_arg) } else { None } diff --git a/src/tools/clippy/clippy_lints/src/implicit_hasher.rs b/src/tools/clippy/clippy_lints/src/implicit_hasher.rs index 6b407c7bb6..81eb51e6f7 100644 --- a/src/tools/clippy/clippy_lints/src/implicit_hasher.rs +++ b/src/tools/clippy/clippy_lints/src/implicit_hasher.rs @@ -130,7 +130,7 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitHasher { let pos = snippet_opt(cx, item.span.until(target.span())) .and_then(|snip| Some(item.span.lo() + BytePos(snip.find("impl")? as u32 + 4))); if let Some(pos) = pos { - Span::new(pos, pos, item.span.data().ctxt) + Span::new(pos, pos, item.span.ctxt(), item.span.parent()) } else { return; } @@ -167,13 +167,21 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitHasher { continue; } let generics_suggestion_span = generics.span.substitute_dummy({ - let pos = snippet_opt(cx, item.span.until(body.params[0].pat.span)) - .and_then(|snip| { - let i = snip.find("fn")?; - Some(item.span.lo() + BytePos((i + (&snip[i..]).find('(')?) as u32)) - }) - .expect("failed to create span for type parameters"); - Span::new(pos, pos, item.span.data().ctxt) + let pos = snippet_opt( + cx, + Span::new( + item.span.lo(), + body.params[0].pat.span.lo(), + item.span.ctxt(), + item.span.parent(), + ), + ) + .and_then(|snip| { + let i = snip.find("fn")?; + Some(item.span.lo() + BytePos((i + (&snip[i..]).find('(')?) as u32)) + }) + .expect("failed to create span for type parameters"); + Span::new(pos, pos, item.span.ctxt(), item.span.parent()) }); let mut ctr_vis = ImplicitHasherConstructorVisitor::new(cx, target); @@ -225,14 +233,14 @@ impl<'tcx> ImplicitHasherType<'tcx> { let ty = hir_ty_to_ty(cx.tcx, hir_ty); - if is_type_diagnostic_item(cx, ty, sym::hashmap_type) && params_len == 2 { + if is_type_diagnostic_item(cx, ty, sym::HashMap) && params_len == 2 { Some(ImplicitHasherType::HashMap( hir_ty.span, ty, snippet(cx, params[0].span, "K"), snippet(cx, params[1].span, "V"), )) - } else if is_type_diagnostic_item(cx, ty, sym::hashset_type) && params_len == 1 { + } else if is_type_diagnostic_item(cx, ty, sym::HashSet) && params_len == 1 { Some(ImplicitHasherType::HashSet( hir_ty.span, ty, @@ -347,7 +355,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for ImplicitHasherConstructorVisitor<'a, 'b, 't return; } - if self.cx.tcx.is_diagnostic_item(sym::hashmap_type, ty_did) { + if self.cx.tcx.is_diagnostic_item(sym::HashMap, ty_did) { if method.ident.name == sym::new { self.suggestions .insert(e.span, "HashMap::default()".to_string()); @@ -360,7 +368,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for ImplicitHasherConstructorVisitor<'a, 'b, 't ), ); } - } else if self.cx.tcx.is_diagnostic_item(sym::hashset_type, ty_did) { + } else if self.cx.tcx.is_diagnostic_item(sym::HashSet, ty_did) { if method.ident.name == sym::new { self.suggestions .insert(e.span, "HashSet::default()".to_string()); diff --git a/src/tools/clippy/clippy_lints/src/infinite_iter.rs b/src/tools/clippy/clippy_lints/src/infinite_iter.rs index 58646385de..68c1fa35fc 100644 --- a/src/tools/clippy/clippy_lints/src/infinite_iter.rs +++ b/src/tools/clippy/clippy_lints/src/infinite_iter.rs @@ -210,11 +210,11 @@ const INFINITE_COLLECTORS: &[Symbol] = &[ sym::BinaryHeap, sym::BTreeMap, sym::BTreeSet, - sym::hashmap_type, - sym::hashset_type, + sym::HashMap, + sym::HashSet, sym::LinkedList, - sym::vec_type, - sym::vecdeque_type, + sym::Vec, + sym::VecDeque, ]; fn complete_infinite_iter(cx: &LateContext<'_>, expr: &Expr<'_>) -> Finiteness { diff --git a/src/tools/clippy/clippy_lints/src/inherent_impl.rs b/src/tools/clippy/clippy_lints/src/inherent_impl.rs index d87055c842..0d23bec27a 100644 --- a/src/tools/clippy/clippy_lints/src/inherent_impl.rs +++ b/src/tools/clippy/clippy_lints/src/inherent_impl.rs @@ -3,7 +3,7 @@ use clippy_utils::diagnostics::span_lint_and_note; use clippy_utils::{in_macro, is_lint_allowed}; use rustc_data_structures::fx::FxHashMap; -use rustc_hir::{def_id::LocalDefId, Crate, Item, ItemKind, Node}; +use rustc_hir::{def_id::LocalDefId, Item, ItemKind, Node}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::Span; @@ -44,7 +44,7 @@ declare_clippy_lint! { declare_lint_pass!(MultipleInherentImpl => [MULTIPLE_INHERENT_IMPL]); impl<'tcx> LateLintPass<'tcx> for MultipleInherentImpl { - fn check_crate_post(&mut self, cx: &LateContext<'tcx>, _: &'tcx Crate<'_>) { + fn check_crate_post(&mut self, cx: &LateContext<'tcx>) { // Map from a type to it's first impl block. Needed to distinguish generic arguments. // e.g. `Foo` and `Foo` let mut type_map = FxHashMap::default(); 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 b62fad4bd3..3c40ca50a0 100644 --- a/src/tools/clippy/clippy_lints/src/inherent_to_string.rs +++ b/src/tools/clippy/clippy_lints/src/inherent_to_string.rs @@ -111,7 +111,7 @@ impl<'tcx> LateLintPass<'tcx> for InherentToString { if impl_item.generics.params.is_empty(); // Check if return type is String - if is_type_diagnostic_item(cx, return_ty(cx, impl_item.hir_id()), sym::string_type); + if is_type_diagnostic_item(cx, return_ty(cx, impl_item.hir_id()), sym::String); // Filters instances of to_string which are required by a trait if trait_ref_of_method(cx, impl_item.hir_id()).is_none(); diff --git a/src/tools/clippy/clippy_lints/src/int_plus_one.rs b/src/tools/clippy/clippy_lints/src/int_plus_one.rs index 49b69dd072..6850e0c347 100644 --- a/src/tools/clippy/clippy_lints/src/int_plus_one.rs +++ b/src/tools/clippy/clippy_lints/src/int_plus_one.rs @@ -89,7 +89,7 @@ impl IntPlusOne { }, _ => None, } - } + }, // case where `x + 1 <= ...` or `1 + x <= ...` (BinOpKind::Le, &ExprKind::Binary(ref lhskind, ref lhslhs, ref lhsrhs), _) if lhskind.node == BinOpKind::Add => @@ -104,7 +104,7 @@ impl IntPlusOne { }, _ => None, } - } + }, // case where `... >= y - 1` or `... >= -1 + y` (BinOpKind::Le, _, &ExprKind::Binary(ref rhskind, ref rhslhs, ref rhsrhs)) => { match (rhskind.node, &rhslhs.kind, &rhsrhs.kind) { diff --git a/src/tools/clippy/clippy_lints/src/integer_division.rs b/src/tools/clippy/clippy_lints/src/integer_division.rs index a0e6f12b81..c962e814fa 100644 --- a/src/tools/clippy/clippy_lints/src/integer_division.rs +++ b/src/tools/clippy/clippy_lints/src/integer_division.rs @@ -48,7 +48,7 @@ impl<'tcx> LateLintPass<'tcx> for IntegerDivision { fn is_integer_division<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) -> bool { if_chain! { if let hir::ExprKind::Binary(binop, left, right) = &expr.kind; - if let hir::BinOpKind::Div = &binop.node; + if binop.node == hir::BinOpKind::Div; then { let (left_ty, right_ty) = (cx.typeck_results().expr_ty(left), cx.typeck_results().expr_ty(right)); return left_ty.is_integral() && right_ty.is_integral(); 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 3b28b12120..b1f70b30c1 100644 --- a/src/tools/clippy/clippy_lints/src/invalid_upcast_comparisons.rs +++ b/src/tools/clippy/clippy_lints/src/invalid_upcast_comparisons.rs @@ -2,10 +2,10 @@ use std::cmp::Ordering; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::{self, IntTy, UintTy}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::Span; -use rustc_target::abi::LayoutOf; use clippy_utils::comparisons::Rel; use clippy_utils::consts::{constant, Constant}; diff --git a/src/tools/clippy/clippy_lints/src/iter_not_returning_iterator.rs b/src/tools/clippy/clippy_lints/src/iter_not_returning_iterator.rs new file mode 100644 index 0000000000..6c779348ca --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/iter_not_returning_iterator.rs @@ -0,0 +1,64 @@ +use clippy_utils::{diagnostics::span_lint, return_ty, ty::implements_trait}; +use rustc_hir::{ImplItem, ImplItemKind}; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_span::symbol::kw; +use rustc_span::symbol::sym; + +declare_clippy_lint! { + /// ### What it does + /// Detects methods named `iter` or `iter_mut` that do not have a return type that implements `Iterator`. + /// + /// ### Why is this bad? + /// Methods named `iter` or `iter_mut` conventionally return an `Iterator`. + /// + /// ### Example + /// ```rust + /// // `String` does not implement `Iterator` + /// struct Data {} + /// impl Data { + /// fn iter(&self) -> String { + /// todo!() + /// } + /// } + /// ``` + /// Use instead: + /// ```rust + /// use std::str::Chars; + /// struct Data {} + /// impl Data { + /// fn iter(&self) -> Chars<'static> { + /// todo!() + /// } + /// } + /// ``` + pub ITER_NOT_RETURNING_ITERATOR, + pedantic, + "methods named `iter` or `iter_mut` that do not return an `Iterator`" +} + +declare_lint_pass!(IterNotReturningIterator => [ITER_NOT_RETURNING_ITERATOR]); + +impl LateLintPass<'_> for IterNotReturningIterator { + fn check_impl_item(&mut self, cx: &LateContext<'tcx>, impl_item: &'tcx ImplItem<'tcx>) { + let name: &str = &impl_item.ident.name.as_str(); + if_chain! { + if let ImplItemKind::Fn(fn_sig, _) = &impl_item.kind; + let ret_ty = return_ty(cx, impl_item.hir_id()); + if matches!(name, "iter" | "iter_mut"); + if let [param] = cx.tcx.fn_arg_names(impl_item.def_id); + if param.name == kw::SelfLower; + if let Some(iter_trait_id) = cx.tcx.get_diagnostic_item(sym::Iterator); + if !implements_trait(cx, ret_ty, iter_trait_id, &[]); + + then { + span_lint( + cx, + ITER_NOT_RETURNING_ITERATOR, + fn_sig.span, + &format!("this method is named `{}` but its return type does not implement `Iterator`", name), + ); + } + } + } +} diff --git a/src/tools/clippy/clippy_lints/src/large_const_arrays.rs b/src/tools/clippy/clippy_lints/src/large_const_arrays.rs index 5d4e06c2af..fe6814e35d 100644 --- a/src/tools/clippy/clippy_lints/src/large_const_arrays.rs +++ b/src/tools/clippy/clippy_lints/src/large_const_arrays.rs @@ -1,10 +1,10 @@ -use crate::rustc_target::abi::LayoutOf; use clippy_utils::diagnostics::span_lint_and_then; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::{Item, ItemKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::mir::interpret::ConstValue; +use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::{self, ConstKind}; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::{BytePos, Pos, Span}; @@ -63,6 +63,7 @@ impl<'tcx> LateLintPass<'tcx> for LargeConstArrays { hi_pos - BytePos::from_usize("const".len()), hi_pos, item.span.ctxt(), + item.span.parent(), ); span_lint_and_then( cx, diff --git a/src/tools/clippy/clippy_lints/src/large_enum_variant.rs b/src/tools/clippy/clippy_lints/src/large_enum_variant.rs index cde2336b69..392166237b 100644 --- a/src/tools/clippy/clippy_lints/src/large_enum_variant.rs +++ b/src/tools/clippy/clippy_lints/src/large_enum_variant.rs @@ -1,13 +1,14 @@ //! lint when there is a large size difference between variants on an enum use clippy_utils::diagnostics::span_lint_and_then; -use clippy_utils::source::snippet_opt; +use clippy_utils::source::snippet_with_applicability; use rustc_errors::Applicability; -use rustc_hir::{Item, ItemKind, VariantData}; +use rustc_hir::{Item, ItemKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::lint::in_external_macro; +use rustc_middle::ty::layout::LayoutOf; use rustc_session::{declare_tool_lint, impl_lint_pass}; -use rustc_target::abi::LayoutOf; +use rustc_span::source_map::Span; declare_clippy_lint! { /// ### What it does @@ -58,6 +59,17 @@ impl LargeEnumVariant { } } +struct FieldInfo { + ind: usize, + size: u64, +} + +struct VariantInfo { + ind: usize, + size: u64, + fields_size: Vec, +} + impl_lint_pass!(LargeEnumVariant => [LARGE_ENUM_VARIANT]); impl<'tcx> LateLintPass<'tcx> for LargeEnumVariant { @@ -68,72 +80,95 @@ impl<'tcx> LateLintPass<'tcx> for LargeEnumVariant { if let ItemKind::Enum(ref def, _) = item.kind { let ty = cx.tcx.type_of(item.def_id); let adt = ty.ty_adt_def().expect("already checked whether this is an enum"); - - let mut largest_variant: Option<(_, _)> = None; - let mut second_variant: Option<(_, _)> = None; - - for (i, variant) in adt.variants.iter().enumerate() { - let size: u64 = variant - .fields - .iter() - .filter_map(|f| { - let ty = cx.tcx.type_of(f.did); - // don't count generics by filtering out everything - // that does not have a layout - cx.layout_of(ty).ok().map(|l| l.size.bytes()) - }) - .sum(); - - let grouped = (size, (i, variant)); - - if grouped.0 >= largest_variant.map_or(0, |x| x.0) { - second_variant = largest_variant; - largest_variant = Some(grouped); - } + if adt.variants.len() <= 1 { + return; } + let mut variants_size: Vec = adt + .variants + .iter() + .enumerate() + .map(|(i, variant)| { + let mut fields_size = Vec::new(); + let size: u64 = variant + .fields + .iter() + .enumerate() + .filter_map(|(i, f)| { + let ty = cx.tcx.type_of(f.did); + // don't count generics by filtering out everything + // that does not have a layout + cx.layout_of(ty).ok().map(|l| { + let size = l.size.bytes(); + fields_size.push(FieldInfo { ind: i, size }); + size + }) + }) + .sum(); + VariantInfo { + ind: i, + size, + fields_size, + } + }) + .collect(); - if let (Some(largest), Some(second)) = (largest_variant, second_variant) { - let difference = largest.0 - second.0; + variants_size.sort_by(|a, b| (b.size.cmp(&a.size))); - if difference > self.maximum_size_difference_allowed { - let (i, variant) = largest.1; + let mut difference = variants_size[0].size - variants_size[1].size; + if difference > self.maximum_size_difference_allowed { + let help_text = "consider boxing the large fields to reduce the total size of the enum"; + span_lint_and_then( + cx, + LARGE_ENUM_VARIANT, + def.variants[variants_size[0].ind].span, + "large size difference between variants", + |diag| { + diag.span_label( + def.variants[variants_size[0].ind].span, + &format!("this variant is {} bytes", variants_size[0].size), + ); + diag.span_note( + def.variants[variants_size[1].ind].span, + &format!("and the second-largest variant is {} bytes:", variants_size[1].size), + ); - let help_text = "consider boxing the large fields to reduce the total size of the enum"; - span_lint_and_then( - cx, - LARGE_ENUM_VARIANT, - def.variants[i].span, - "large size difference between variants", - |diag| { - diag.span_label( - def.variants[(largest.1).0].span, - &format!("this variant is {} bytes", largest.0), - ); - diag.span_note( - def.variants[(second.1).0].span, - &format!("and the second-largest variant is {} bytes:", second.0), - ); - if variant.fields.len() == 1 { - let span = match def.variants[i].data { - VariantData::Struct(fields, ..) | VariantData::Tuple(fields, ..) => { - fields[0].ty.span - }, - VariantData::Unit(..) => unreachable!(), - }; - if let Some(snip) = snippet_opt(cx, span) { - diag.span_suggestion( - span, - help_text, - format!("Box<{}>", snip), - Applicability::MaybeIncorrect, - ); - return; + let fields = def.variants[variants_size[0].ind].data.fields(); + variants_size[0].fields_size.sort_by(|a, b| (a.size.cmp(&b.size))); + let mut applicability = Applicability::MaybeIncorrect; + let sugg: Vec<(Span, String)> = variants_size[0] + .fields_size + .iter() + .rev() + .map_while(|val| { + if difference > self.maximum_size_difference_allowed { + difference = difference.saturating_sub(val.size); + Some(( + fields[val.ind].ty.span, + format!( + "Box<{}>", + snippet_with_applicability( + cx, + fields[val.ind].ty.span, + "..", + &mut applicability + ) + .into_owned() + ), + )) + } else { + None } - } - diag.span_help(def.variants[i].span, help_text); - }, - ); - } + }) + .collect(); + + if !sugg.is_empty() { + diag.multipart_suggestion(help_text, sugg, Applicability::MaybeIncorrect); + return; + } + + diag.span_help(def.variants[variants_size[0].ind].span, help_text); + }, + ); } } } diff --git a/src/tools/clippy/clippy_lints/src/large_stack_arrays.rs b/src/tools/clippy/clippy_lints/src/large_stack_arrays.rs index 7088630bfd..bbb6c1f902 100644 --- a/src/tools/clippy/clippy_lints/src/large_stack_arrays.rs +++ b/src/tools/clippy/clippy_lints/src/large_stack_arrays.rs @@ -4,11 +4,10 @@ use if_chain::if_chain; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::mir::interpret::ConstValue; +use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::{self, ConstKind}; use rustc_session::{declare_tool_lint, impl_lint_pass}; -use crate::rustc_target::abi::LayoutOf; - declare_clippy_lint! { /// ### What it does /// Checks for local arrays that may be too large. diff --git a/src/tools/clippy/clippy_lints/src/len_zero.rs b/src/tools/clippy/clippy_lints/src/len_zero.rs index a519ad90df..f336fb9d42 100644 --- a/src/tools/clippy/clippy_lints/src/len_zero.rs +++ b/src/tools/clippy/clippy_lints/src/len_zero.rs @@ -245,10 +245,10 @@ enum LenOutput<'tcx> { fn parse_len_output(cx: &LateContext<'_>, sig: FnSig<'tcx>) -> Option> { match *sig.output().kind() { ty::Int(_) | ty::Uint(_) => Some(LenOutput::Integral), - ty::Adt(adt, subs) if cx.tcx.is_diagnostic_item(sym::option_type, adt.did) => { + ty::Adt(adt, subs) if cx.tcx.is_diagnostic_item(sym::Option, adt.did) => { subs.type_at(0).is_integral().then(|| LenOutput::Option(adt.did)) }, - ty::Adt(adt, subs) if cx.tcx.is_diagnostic_item(sym::result_type, adt.did) => subs + ty::Adt(adt, subs) if cx.tcx.is_diagnostic_item(sym::Result, adt.did) => subs .type_at(0) .is_integral() .then(|| LenOutput::Result(adt.did, subs.type_at(1))), @@ -455,14 +455,10 @@ fn is_empty_array(expr: &Expr<'_>) -> bool { fn has_is_empty(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { /// Gets an `AssocItem` and return true if it matches `is_empty(self)`. fn is_is_empty(cx: &LateContext<'_>, item: &ty::AssocItem) -> bool { - if let ty::AssocKind::Fn = item.kind { - if item.ident.name.as_str() == "is_empty" { - let sig = cx.tcx.fn_sig(item.def_id); - let ty = sig.skip_binder(); - ty.inputs().len() == 1 - } else { - false - } + if item.kind == ty::AssocKind::Fn && item.ident.name.as_str() == "is_empty" { + let sig = cx.tcx.fn_sig(item.def_id); + let ty = sig.skip_binder(); + ty.inputs().len() == 1 } else { false } diff --git a/src/tools/clippy/clippy_lints/src/let_if_seq.rs b/src/tools/clippy/clippy_lints/src/let_if_seq.rs index 0594b73dd3..7f2c7b707f 100644 --- a/src/tools/clippy/clippy_lints/src/let_if_seq.rs +++ b/src/tools/clippy/clippy_lints/src/let_if_seq.rs @@ -1,6 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::source::snippet; -use clippy_utils::{path_to_local_id, visitors::LocalUsedVisitor}; +use clippy_utils::{path_to_local_id, visitors::is_local_used}; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir as hir; @@ -65,11 +65,10 @@ impl<'tcx> LateLintPass<'tcx> for LetIfSeq { if let hir::PatKind::Binding(mode, canonical_id, ident, None) = local.pat.kind; if let hir::StmtKind::Expr(if_) = expr.kind; if let hir::ExprKind::If(hir::Expr { kind: hir::ExprKind::DropTemps(cond), ..}, then, else_) = if_.kind; - let mut used_visitor = LocalUsedVisitor::new(cx, canonical_id); - if !used_visitor.check_expr(cond); + if !is_local_used(cx, *cond, canonical_id); if let hir::ExprKind::Block(then, _) = then.kind; if let Some(value) = check_assign(cx, canonical_id, &*then); - if !used_visitor.check_expr(value); + if !is_local_used(cx, value, canonical_id); then { let span = stmt.span.to(if_.span); @@ -148,15 +147,13 @@ fn check_assign<'tcx>( if let hir::ExprKind::Assign(var, value, _) = expr.kind; if path_to_local_id(var, decl); then { - let mut v = LocalUsedVisitor::new(cx, decl); - - if block.stmts.iter().take(block.stmts.len()-1).any(|stmt| v.check_stmt(stmt)) { - return None; + if block.stmts.iter().take(block.stmts.len()-1).any(|stmt| is_local_used(cx, stmt, decl)) { + None + } else { + Some(value) } - - return Some(value); + } else { + None } } - - None } diff --git a/src/tools/clippy/clippy_lints/src/lib.deprecated.rs b/src/tools/clippy/clippy_lints/src/lib.deprecated.rs new file mode 100644 index 0000000000..80bde1b113 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/lib.deprecated.rs @@ -0,0 +1,70 @@ +// This file was generated by `cargo dev update_lints`. +// Use that command to update this file and do not edit by hand. +// Manual edits will be overwritten. + +{ + store.register_removed( + "clippy::should_assert_eq", + "`assert!()` will be more flexible with RFC 2011", + ); + store.register_removed( + "clippy::extend_from_slice", + "`.extend_from_slice(_)` is a faster way to extend a Vec by a slice", + ); + store.register_removed( + "clippy::range_step_by_zero", + "`iterator.step_by(0)` panics nowadays", + ); + store.register_removed( + "clippy::unstable_as_slice", + "`Vec::as_slice` has been stabilized in 1.7", + ); + store.register_removed( + "clippy::unstable_as_mut_slice", + "`Vec::as_mut_slice` has been stabilized in 1.7", + ); + store.register_removed( + "clippy::misaligned_transmute", + "this lint has been split into cast_ptr_alignment and transmute_ptr_to_ptr", + ); + store.register_removed( + "clippy::assign_ops", + "using compound assignment operators (e.g., `+=`) is harmless", + ); + store.register_removed( + "clippy::if_let_redundant_pattern_matching", + "this lint has been changed to redundant_pattern_matching", + ); + store.register_removed( + "clippy::unsafe_vector_initialization", + "the replacement suggested by this lint had substantially different behavior", + ); + store.register_removed( + "clippy::unused_collect", + "`collect` has been marked as #[must_use] in rustc and that covers all cases of this lint", + ); + store.register_removed( + "clippy::replace_consts", + "associated-constants `MIN`/`MAX` of integers are preferred to `{min,max}_value()` and module constants", + ); + store.register_removed( + "clippy::regex_macro", + "the regex! macro has been removed from the regex crate in 2018", + ); + store.register_removed( + "clippy::find_map", + "this lint has been replaced by `manual_find_map`, a more specific lint", + ); + store.register_removed( + "clippy::filter_map", + "this lint has been replaced by `manual_filter_map`, a more specific lint", + ); + store.register_removed( + "clippy::pub_enum_variant_names", + "set the `avoid-breaking-exported-api` config option to `false` to enable the `enum_variant_names` lint for public items", + ); + store.register_removed( + "clippy::wrong_pub_self_convention", + "set the `avoid-breaking-exported-api` config option to `false` to enable the `wrong_self_convention` lint for public items", + ); +} diff --git a/src/tools/clippy/clippy_lints/src/lib.register_all.rs b/src/tools/clippy/clippy_lints/src/lib.register_all.rs new file mode 100644 index 0000000000..e67d73c3c6 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/lib.register_all.rs @@ -0,0 +1,302 @@ +// This file was generated by `cargo dev update_lints`. +// Use that command to update this file and do not edit by hand. +// Manual edits will be overwritten. + +store.register_group(true, "clippy::all", Some("clippy_all"), vec![ + LintId::of(absurd_extreme_comparisons::ABSURD_EXTREME_COMPARISONS), + LintId::of(approx_const::APPROX_CONSTANT), + LintId::of(assertions_on_constants::ASSERTIONS_ON_CONSTANTS), + LintId::of(assign_ops::ASSIGN_OP_PATTERN), + LintId::of(assign_ops::MISREFACTORED_ASSIGN_OP), + LintId::of(async_yields_async::ASYNC_YIELDS_ASYNC), + LintId::of(attrs::BLANKET_CLIPPY_RESTRICTION_LINTS), + LintId::of(attrs::DEPRECATED_CFG_ATTR), + LintId::of(attrs::DEPRECATED_SEMVER), + LintId::of(attrs::MISMATCHED_TARGET_OS), + LintId::of(attrs::USELESS_ATTRIBUTE), + LintId::of(bit_mask::BAD_BIT_MASK), + LintId::of(bit_mask::INEFFECTIVE_BIT_MASK), + LintId::of(blacklisted_name::BLACKLISTED_NAME), + LintId::of(blocks_in_if_conditions::BLOCKS_IN_IF_CONDITIONS), + LintId::of(bool_assert_comparison::BOOL_ASSERT_COMPARISON), + LintId::of(booleans::LOGIC_BUG), + LintId::of(booleans::NONMINIMAL_BOOL), + LintId::of(casts::CAST_REF_TO_MUT), + LintId::of(casts::CHAR_LIT_AS_U8), + LintId::of(casts::FN_TO_NUMERIC_CAST), + LintId::of(casts::FN_TO_NUMERIC_CAST_WITH_TRUNCATION), + LintId::of(casts::UNNECESSARY_CAST), + LintId::of(collapsible_if::COLLAPSIBLE_ELSE_IF), + LintId::of(collapsible_if::COLLAPSIBLE_IF), + LintId::of(collapsible_match::COLLAPSIBLE_MATCH), + LintId::of(comparison_chain::COMPARISON_CHAIN), + LintId::of(copies::IFS_SAME_COND), + LintId::of(copies::IF_SAME_THEN_ELSE), + LintId::of(default::FIELD_REASSIGN_WITH_DEFAULT), + LintId::of(derivable_impls::DERIVABLE_IMPLS), + LintId::of(derive::DERIVE_HASH_XOR_EQ), + LintId::of(derive::DERIVE_ORD_XOR_PARTIAL_ORD), + LintId::of(doc::MISSING_SAFETY_DOC), + LintId::of(doc::NEEDLESS_DOCTEST_MAIN), + LintId::of(double_comparison::DOUBLE_COMPARISONS), + LintId::of(double_parens::DOUBLE_PARENS), + LintId::of(drop_forget_ref::DROP_COPY), + LintId::of(drop_forget_ref::DROP_REF), + LintId::of(drop_forget_ref::FORGET_COPY), + LintId::of(drop_forget_ref::FORGET_REF), + LintId::of(duration_subsec::DURATION_SUBSEC), + LintId::of(entry::MAP_ENTRY), + LintId::of(enum_clike::ENUM_CLIKE_UNPORTABLE_VARIANT), + LintId::of(enum_variants::ENUM_VARIANT_NAMES), + LintId::of(enum_variants::MODULE_INCEPTION), + LintId::of(eq_op::EQ_OP), + LintId::of(eq_op::OP_REF), + LintId::of(erasing_op::ERASING_OP), + LintId::of(escape::BOXED_LOCAL), + LintId::of(eta_reduction::REDUNDANT_CLOSURE), + LintId::of(eval_order_dependence::DIVERGING_SUB_EXPRESSION), + LintId::of(eval_order_dependence::EVAL_ORDER_DEPENDENCE), + LintId::of(explicit_write::EXPLICIT_WRITE), + LintId::of(float_equality_without_abs::FLOAT_EQUALITY_WITHOUT_ABS), + LintId::of(float_literal::EXCESSIVE_PRECISION), + LintId::of(format::USELESS_FORMAT), + LintId::of(formatting::POSSIBLE_MISSING_COMMA), + LintId::of(formatting::SUSPICIOUS_ASSIGNMENT_FORMATTING), + LintId::of(formatting::SUSPICIOUS_ELSE_FORMATTING), + LintId::of(formatting::SUSPICIOUS_UNARY_OP_FORMATTING), + LintId::of(from_over_into::FROM_OVER_INTO), + LintId::of(from_str_radix_10::FROM_STR_RADIX_10), + LintId::of(functions::DOUBLE_MUST_USE), + LintId::of(functions::MUST_USE_UNIT), + LintId::of(functions::NOT_UNSAFE_PTR_ARG_DEREF), + LintId::of(functions::RESULT_UNIT_ERR), + LintId::of(functions::TOO_MANY_ARGUMENTS), + LintId::of(get_last_with_len::GET_LAST_WITH_LEN), + LintId::of(identity_op::IDENTITY_OP), + LintId::of(if_let_mutex::IF_LET_MUTEX), + LintId::of(indexing_slicing::OUT_OF_BOUNDS_INDEXING), + LintId::of(infinite_iter::INFINITE_ITER), + LintId::of(inherent_to_string::INHERENT_TO_STRING), + LintId::of(inherent_to_string::INHERENT_TO_STRING_SHADOW_DISPLAY), + LintId::of(inline_fn_without_body::INLINE_FN_WITHOUT_BODY), + LintId::of(int_plus_one::INT_PLUS_ONE), + LintId::of(large_const_arrays::LARGE_CONST_ARRAYS), + LintId::of(large_enum_variant::LARGE_ENUM_VARIANT), + LintId::of(len_zero::COMPARISON_TO_EMPTY), + LintId::of(len_zero::LEN_WITHOUT_IS_EMPTY), + LintId::of(len_zero::LEN_ZERO), + LintId::of(let_underscore::LET_UNDERSCORE_LOCK), + LintId::of(lifetimes::EXTRA_UNUSED_LIFETIMES), + LintId::of(lifetimes::NEEDLESS_LIFETIMES), + LintId::of(literal_representation::INCONSISTENT_DIGIT_GROUPING), + LintId::of(literal_representation::MISTYPED_LITERAL_SUFFIXES), + LintId::of(literal_representation::UNUSUAL_BYTE_GROUPINGS), + LintId::of(loops::EMPTY_LOOP), + LintId::of(loops::EXPLICIT_COUNTER_LOOP), + LintId::of(loops::FOR_KV_MAP), + LintId::of(loops::FOR_LOOPS_OVER_FALLIBLES), + LintId::of(loops::ITER_NEXT_LOOP), + LintId::of(loops::MANUAL_FLATTEN), + LintId::of(loops::MANUAL_MEMCPY), + LintId::of(loops::MUT_RANGE_BOUND), + LintId::of(loops::NEEDLESS_COLLECT), + LintId::of(loops::NEEDLESS_RANGE_LOOP), + LintId::of(loops::NEVER_LOOP), + LintId::of(loops::SAME_ITEM_PUSH), + LintId::of(loops::SINGLE_ELEMENT_LOOP), + LintId::of(loops::WHILE_IMMUTABLE_CONDITION), + LintId::of(loops::WHILE_LET_LOOP), + LintId::of(loops::WHILE_LET_ON_ITERATOR), + LintId::of(main_recursion::MAIN_RECURSION), + LintId::of(manual_async_fn::MANUAL_ASYNC_FN), + LintId::of(manual_map::MANUAL_MAP), + LintId::of(manual_non_exhaustive::MANUAL_NON_EXHAUSTIVE), + LintId::of(manual_strip::MANUAL_STRIP), + LintId::of(manual_unwrap_or::MANUAL_UNWRAP_OR), + LintId::of(map_clone::MAP_CLONE), + LintId::of(map_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(matches::INFALLIBLE_DESTRUCTURING_MATCH), + LintId::of(matches::MATCH_AS_REF), + LintId::of(matches::MATCH_LIKE_MATCHES_MACRO), + LintId::of(matches::MATCH_OVERLAPPING_ARM), + LintId::of(matches::MATCH_REF_PATS), + LintId::of(matches::MATCH_SINGLE_BINDING), + LintId::of(matches::REDUNDANT_PATTERN_MATCHING), + LintId::of(matches::SINGLE_MATCH), + LintId::of(matches::WILDCARD_IN_OR_PATTERNS), + LintId::of(mem_replace::MEM_REPLACE_OPTION_WITH_NONE), + LintId::of(mem_replace::MEM_REPLACE_WITH_DEFAULT), + LintId::of(mem_replace::MEM_REPLACE_WITH_UNINIT), + LintId::of(methods::BIND_INSTEAD_OF_MAP), + LintId::of(methods::BYTES_NTH), + LintId::of(methods::CHARS_LAST_CMP), + LintId::of(methods::CHARS_NEXT_CMP), + LintId::of(methods::CLONE_DOUBLE_REF), + LintId::of(methods::CLONE_ON_COPY), + LintId::of(methods::EXPECT_FUN_CALL), + LintId::of(methods::EXTEND_WITH_DRAIN), + LintId::of(methods::FILTER_MAP_IDENTITY), + LintId::of(methods::FILTER_NEXT), + LintId::of(methods::FLAT_MAP_IDENTITY), + LintId::of(methods::INSPECT_FOR_EACH), + LintId::of(methods::INTO_ITER_ON_REF), + LintId::of(methods::ITERATOR_STEP_BY_ZERO), + LintId::of(methods::ITER_CLONED_COLLECT), + LintId::of(methods::ITER_COUNT), + LintId::of(methods::ITER_NEXT_SLICE), + LintId::of(methods::ITER_NTH), + LintId::of(methods::ITER_NTH_ZERO), + LintId::of(methods::ITER_SKIP_NEXT), + LintId::of(methods::MANUAL_FILTER_MAP), + LintId::of(methods::MANUAL_FIND_MAP), + LintId::of(methods::MANUAL_SATURATING_ARITHMETIC), + LintId::of(methods::MANUAL_SPLIT_ONCE), + LintId::of(methods::MANUAL_STR_REPEAT), + LintId::of(methods::MAP_COLLECT_RESULT_UNIT), + LintId::of(methods::MAP_IDENTITY), + LintId::of(methods::NEW_RET_NO_SELF), + LintId::of(methods::OK_EXPECT), + LintId::of(methods::OPTION_AS_REF_DEREF), + LintId::of(methods::OPTION_FILTER_MAP), + LintId::of(methods::OPTION_MAP_OR_NONE), + LintId::of(methods::OR_FUN_CALL), + LintId::of(methods::RESULT_MAP_OR_INTO_OPTION), + LintId::of(methods::SEARCH_IS_SOME), + LintId::of(methods::SHOULD_IMPLEMENT_TRAIT), + LintId::of(methods::SINGLE_CHAR_ADD_STR), + LintId::of(methods::SINGLE_CHAR_PATTERN), + LintId::of(methods::SKIP_WHILE_NEXT), + LintId::of(methods::STRING_EXTEND_CHARS), + LintId::of(methods::SUSPICIOUS_MAP), + LintId::of(methods::SUSPICIOUS_SPLITN), + LintId::of(methods::UNINIT_ASSUMED_INIT), + LintId::of(methods::UNNECESSARY_FILTER_MAP), + LintId::of(methods::UNNECESSARY_FOLD), + LintId::of(methods::UNNECESSARY_LAZY_EVALUATIONS), + LintId::of(methods::UNWRAP_OR_ELSE_DEFAULT), + LintId::of(methods::USELESS_ASREF), + LintId::of(methods::WRONG_SELF_CONVENTION), + LintId::of(methods::ZST_OFFSET), + LintId::of(minmax::MIN_MAX), + LintId::of(misc::CMP_NAN), + LintId::of(misc::CMP_OWNED), + LintId::of(misc::MODULO_ONE), + LintId::of(misc::SHORT_CIRCUIT_STATEMENT), + LintId::of(misc::TOPLEVEL_REF_ARG), + LintId::of(misc::ZERO_PTR), + LintId::of(misc_early::BUILTIN_TYPE_SHADOW), + LintId::of(misc_early::DOUBLE_NEG), + LintId::of(misc_early::DUPLICATE_UNDERSCORE_ARGUMENT), + LintId::of(misc_early::MIXED_CASE_HEX_LITERALS), + LintId::of(misc_early::REDUNDANT_PATTERN), + LintId::of(misc_early::UNNEEDED_WILDCARD_PATTERN), + LintId::of(misc_early::ZERO_PREFIXED_LITERAL), + LintId::of(mut_key::MUTABLE_KEY_TYPE), + LintId::of(mut_mutex_lock::MUT_MUTEX_LOCK), + LintId::of(mut_reference::UNNECESSARY_MUT_PASSED), + LintId::of(mutex_atomic::MUTEX_ATOMIC), + LintId::of(needless_arbitrary_self_type::NEEDLESS_ARBITRARY_SELF_TYPE), + LintId::of(needless_bool::BOOL_COMPARISON), + LintId::of(needless_bool::NEEDLESS_BOOL), + LintId::of(needless_borrow::NEEDLESS_BORROW), + LintId::of(needless_borrowed_ref::NEEDLESS_BORROWED_REFERENCE), + LintId::of(needless_option_as_deref::NEEDLESS_OPTION_AS_DEREF), + LintId::of(needless_question_mark::NEEDLESS_QUESTION_MARK), + LintId::of(needless_update::NEEDLESS_UPDATE), + LintId::of(neg_cmp_op_on_partial_ord::NEG_CMP_OP_ON_PARTIAL_ORD), + LintId::of(neg_multiply::NEG_MULTIPLY), + LintId::of(new_without_default::NEW_WITHOUT_DEFAULT), + LintId::of(no_effect::NO_EFFECT), + LintId::of(no_effect::UNNECESSARY_OPERATION), + LintId::of(non_copy_const::BORROW_INTERIOR_MUTABLE_CONST), + LintId::of(non_copy_const::DECLARE_INTERIOR_MUTABLE_CONST), + LintId::of(non_expressive_names::JUST_UNDERSCORES_AND_DIGITS), + LintId::of(non_octal_unix_permissions::NON_OCTAL_UNIX_PERMISSIONS), + LintId::of(open_options::NONSENSICAL_OPEN_OPTIONS), + LintId::of(option_env_unwrap::OPTION_ENV_UNWRAP), + LintId::of(overflow_check_conditional::OVERFLOW_CHECK_CONDITIONAL), + LintId::of(partialeq_ne_impl::PARTIALEQ_NE_IMPL), + LintId::of(precedence::PRECEDENCE), + LintId::of(ptr::CMP_NULL), + LintId::of(ptr::INVALID_NULL_PTR_USAGE), + LintId::of(ptr::MUT_FROM_REF), + LintId::of(ptr::PTR_ARG), + LintId::of(ptr_eq::PTR_EQ), + LintId::of(ptr_offset_with_cast::PTR_OFFSET_WITH_CAST), + LintId::of(question_mark::QUESTION_MARK), + LintId::of(ranges::MANUAL_RANGE_CONTAINS), + LintId::of(ranges::RANGE_ZIP_WITH_LEN), + LintId::of(ranges::REVERSED_EMPTY_RANGES), + LintId::of(redundant_clone::REDUNDANT_CLONE), + LintId::of(redundant_closure_call::REDUNDANT_CLOSURE_CALL), + LintId::of(redundant_field_names::REDUNDANT_FIELD_NAMES), + LintId::of(redundant_slicing::REDUNDANT_SLICING), + LintId::of(redundant_static_lifetimes::REDUNDANT_STATIC_LIFETIMES), + LintId::of(reference::DEREF_ADDROF), + LintId::of(reference::REF_IN_DEREF), + LintId::of(regex::INVALID_REGEX), + LintId::of(repeat_once::REPEAT_ONCE), + LintId::of(returns::LET_AND_RETURN), + LintId::of(returns::NEEDLESS_RETURN), + LintId::of(self_assignment::SELF_ASSIGNMENT), + LintId::of(self_named_constructors::SELF_NAMED_CONSTRUCTORS), + LintId::of(serde_api::SERDE_API_MISUSE), + LintId::of(single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS), + LintId::of(size_of_in_element_count::SIZE_OF_IN_ELEMENT_COUNT), + LintId::of(slow_vector_initialization::SLOW_VECTOR_INITIALIZATION), + LintId::of(stable_sort_primitive::STABLE_SORT_PRIMITIVE), + LintId::of(strings::STRING_FROM_UTF8_AS_BYTES), + LintId::of(strlen_on_c_strings::STRLEN_ON_C_STRINGS), + LintId::of(suspicious_trait_impl::SUSPICIOUS_ARITHMETIC_IMPL), + LintId::of(suspicious_trait_impl::SUSPICIOUS_OP_ASSIGN_IMPL), + LintId::of(swap::ALMOST_SWAPPED), + LintId::of(swap::MANUAL_SWAP), + LintId::of(tabs_in_doc_comments::TABS_IN_DOC_COMMENTS), + LintId::of(temporary_assignment::TEMPORARY_ASSIGNMENT), + LintId::of(to_digit_is_some::TO_DIGIT_IS_SOME), + LintId::of(to_string_in_display::TO_STRING_IN_DISPLAY), + LintId::of(transmute::CROSSPOINTER_TRANSMUTE), + LintId::of(transmute::TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS), + LintId::of(transmute::TRANSMUTE_BYTES_TO_STR), + LintId::of(transmute::TRANSMUTE_FLOAT_TO_INT), + LintId::of(transmute::TRANSMUTE_INT_TO_BOOL), + LintId::of(transmute::TRANSMUTE_INT_TO_CHAR), + LintId::of(transmute::TRANSMUTE_INT_TO_FLOAT), + LintId::of(transmute::TRANSMUTE_PTR_TO_REF), + LintId::of(transmute::UNSOUND_COLLECTION_TRANSMUTE), + LintId::of(transmute::WRONG_TRANSMUTE), + LintId::of(transmuting_null::TRANSMUTING_NULL), + LintId::of(try_err::TRY_ERR), + LintId::of(types::BORROWED_BOX), + LintId::of(types::BOX_COLLECTION), + LintId::of(types::REDUNDANT_ALLOCATION), + LintId::of(types::TYPE_COMPLEXITY), + LintId::of(types::VEC_BOX), + LintId::of(undropped_manually_drops::UNDROPPED_MANUALLY_DROPS), + LintId::of(unicode::INVISIBLE_CHARACTERS), + LintId::of(unit_return_expecting_ord::UNIT_RETURN_EXPECTING_ORD), + LintId::of(unit_types::UNIT_ARG), + LintId::of(unit_types::UNIT_CMP), + LintId::of(unnamed_address::FN_ADDRESS_COMPARISONS), + LintId::of(unnamed_address::VTABLE_ADDRESS_COMPARISONS), + LintId::of(unnecessary_sort_by::UNNECESSARY_SORT_BY), + LintId::of(unsafe_removed_from_name::UNSAFE_REMOVED_FROM_NAME), + LintId::of(unused_io_amount::UNUSED_IO_AMOUNT), + LintId::of(unused_unit::UNUSED_UNIT), + LintId::of(unwrap::PANICKING_UNWRAP), + LintId::of(unwrap::UNNECESSARY_UNWRAP), + LintId::of(upper_case_acronyms::UPPER_CASE_ACRONYMS), + LintId::of(useless_conversion::USELESS_CONVERSION), + LintId::of(vec::USELESS_VEC), + LintId::of(vec_init_then_push::VEC_INIT_THEN_PUSH), + LintId::of(vec_resize_to_zero::VEC_RESIZE_TO_ZERO), + LintId::of(write::PRINTLN_EMPTY_STRING), + LintId::of(write::PRINT_LITERAL), + LintId::of(write::PRINT_WITH_NEWLINE), + LintId::of(write::WRITELN_EMPTY_STRING), + LintId::of(write::WRITE_LITERAL), + LintId::of(write::WRITE_WITH_NEWLINE), + LintId::of(zero_div_zero::ZERO_DIVIDED_BY_ZERO), +]) diff --git a/src/tools/clippy/clippy_lints/src/lib.register_cargo.rs b/src/tools/clippy/clippy_lints/src/lib.register_cargo.rs new file mode 100644 index 0000000000..1809f2cc7d --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/lib.register_cargo.rs @@ -0,0 +1,11 @@ +// This file was generated by `cargo dev update_lints`. +// Use that command to update this file and do not edit by hand. +// Manual edits will be overwritten. + +store.register_group(true, "clippy::cargo", Some("clippy_cargo"), vec![ + LintId::of(cargo_common_metadata::CARGO_COMMON_METADATA), + LintId::of(feature_name::NEGATIVE_FEATURE_NAMES), + LintId::of(feature_name::REDUNDANT_FEATURE_NAMES), + LintId::of(multiple_crate_versions::MULTIPLE_CRATE_VERSIONS), + LintId::of(wildcard_dependencies::WILDCARD_DEPENDENCIES), +]) diff --git a/src/tools/clippy/clippy_lints/src/lib.register_complexity.rs b/src/tools/clippy/clippy_lints/src/lib.register_complexity.rs new file mode 100644 index 0000000000..64b82fc0fa --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/lib.register_complexity.rs @@ -0,0 +1,94 @@ +// This file was generated by `cargo dev update_lints`. +// Use that command to update this file and do not edit by hand. +// Manual edits will be overwritten. + +store.register_group(true, "clippy::complexity", Some("clippy_complexity"), vec![ + LintId::of(attrs::DEPRECATED_CFG_ATTR), + LintId::of(booleans::NONMINIMAL_BOOL), + LintId::of(casts::CHAR_LIT_AS_U8), + LintId::of(casts::UNNECESSARY_CAST), + LintId::of(derivable_impls::DERIVABLE_IMPLS), + LintId::of(double_comparison::DOUBLE_COMPARISONS), + LintId::of(double_parens::DOUBLE_PARENS), + LintId::of(duration_subsec::DURATION_SUBSEC), + LintId::of(eval_order_dependence::DIVERGING_SUB_EXPRESSION), + LintId::of(explicit_write::EXPLICIT_WRITE), + LintId::of(format::USELESS_FORMAT), + LintId::of(functions::TOO_MANY_ARGUMENTS), + LintId::of(get_last_with_len::GET_LAST_WITH_LEN), + LintId::of(identity_op::IDENTITY_OP), + LintId::of(int_plus_one::INT_PLUS_ONE), + LintId::of(lifetimes::EXTRA_UNUSED_LIFETIMES), + LintId::of(lifetimes::NEEDLESS_LIFETIMES), + LintId::of(loops::EXPLICIT_COUNTER_LOOP), + LintId::of(loops::MANUAL_FLATTEN), + LintId::of(loops::SINGLE_ELEMENT_LOOP), + LintId::of(loops::WHILE_LET_LOOP), + LintId::of(manual_strip::MANUAL_STRIP), + LintId::of(manual_unwrap_or::MANUAL_UNWRAP_OR), + LintId::of(map_unit_fn::OPTION_MAP_UNIT_FN), + LintId::of(map_unit_fn::RESULT_MAP_UNIT_FN), + LintId::of(matches::MATCH_AS_REF), + LintId::of(matches::MATCH_SINGLE_BINDING), + LintId::of(matches::WILDCARD_IN_OR_PATTERNS), + LintId::of(methods::BIND_INSTEAD_OF_MAP), + LintId::of(methods::CLONE_ON_COPY), + LintId::of(methods::FILTER_MAP_IDENTITY), + LintId::of(methods::FILTER_NEXT), + LintId::of(methods::FLAT_MAP_IDENTITY), + LintId::of(methods::INSPECT_FOR_EACH), + LintId::of(methods::ITER_COUNT), + LintId::of(methods::MANUAL_FILTER_MAP), + LintId::of(methods::MANUAL_FIND_MAP), + LintId::of(methods::MANUAL_SPLIT_ONCE), + LintId::of(methods::MAP_IDENTITY), + LintId::of(methods::OPTION_AS_REF_DEREF), + LintId::of(methods::OPTION_FILTER_MAP), + LintId::of(methods::SEARCH_IS_SOME), + LintId::of(methods::SKIP_WHILE_NEXT), + LintId::of(methods::UNNECESSARY_FILTER_MAP), + LintId::of(methods::USELESS_ASREF), + LintId::of(misc::SHORT_CIRCUIT_STATEMENT), + LintId::of(misc_early::UNNEEDED_WILDCARD_PATTERN), + LintId::of(misc_early::ZERO_PREFIXED_LITERAL), + LintId::of(needless_arbitrary_self_type::NEEDLESS_ARBITRARY_SELF_TYPE), + LintId::of(needless_bool::BOOL_COMPARISON), + LintId::of(needless_bool::NEEDLESS_BOOL), + LintId::of(needless_borrowed_ref::NEEDLESS_BORROWED_REFERENCE), + LintId::of(needless_option_as_deref::NEEDLESS_OPTION_AS_DEREF), + LintId::of(needless_question_mark::NEEDLESS_QUESTION_MARK), + LintId::of(needless_update::NEEDLESS_UPDATE), + LintId::of(neg_cmp_op_on_partial_ord::NEG_CMP_OP_ON_PARTIAL_ORD), + LintId::of(no_effect::NO_EFFECT), + LintId::of(no_effect::UNNECESSARY_OPERATION), + LintId::of(overflow_check_conditional::OVERFLOW_CHECK_CONDITIONAL), + LintId::of(partialeq_ne_impl::PARTIALEQ_NE_IMPL), + LintId::of(precedence::PRECEDENCE), + LintId::of(ptr_offset_with_cast::PTR_OFFSET_WITH_CAST), + LintId::of(ranges::RANGE_ZIP_WITH_LEN), + LintId::of(redundant_closure_call::REDUNDANT_CLOSURE_CALL), + LintId::of(redundant_slicing::REDUNDANT_SLICING), + LintId::of(reference::DEREF_ADDROF), + LintId::of(reference::REF_IN_DEREF), + LintId::of(repeat_once::REPEAT_ONCE), + LintId::of(strings::STRING_FROM_UTF8_AS_BYTES), + LintId::of(strlen_on_c_strings::STRLEN_ON_C_STRINGS), + LintId::of(swap::MANUAL_SWAP), + LintId::of(temporary_assignment::TEMPORARY_ASSIGNMENT), + LintId::of(transmute::CROSSPOINTER_TRANSMUTE), + LintId::of(transmute::TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS), + LintId::of(transmute::TRANSMUTE_BYTES_TO_STR), + LintId::of(transmute::TRANSMUTE_FLOAT_TO_INT), + LintId::of(transmute::TRANSMUTE_INT_TO_BOOL), + LintId::of(transmute::TRANSMUTE_INT_TO_CHAR), + LintId::of(transmute::TRANSMUTE_INT_TO_FLOAT), + LintId::of(transmute::TRANSMUTE_PTR_TO_REF), + LintId::of(types::BORROWED_BOX), + LintId::of(types::TYPE_COMPLEXITY), + LintId::of(types::VEC_BOX), + LintId::of(unit_types::UNIT_ARG), + LintId::of(unnecessary_sort_by::UNNECESSARY_SORT_BY), + LintId::of(unwrap::UNNECESSARY_UNWRAP), + LintId::of(useless_conversion::USELESS_CONVERSION), + LintId::of(zero_div_zero::ZERO_DIVIDED_BY_ZERO), +]) diff --git a/src/tools/clippy/clippy_lints/src/lib.register_correctness.rs b/src/tools/clippy/clippy_lints/src/lib.register_correctness.rs new file mode 100644 index 0000000000..bbe47a0e77 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/lib.register_correctness.rs @@ -0,0 +1,72 @@ +// This file was generated by `cargo dev update_lints`. +// Use that command to update this file and do not edit by hand. +// Manual edits will be overwritten. + +store.register_group(true, "clippy::correctness", Some("clippy_correctness"), vec![ + LintId::of(absurd_extreme_comparisons::ABSURD_EXTREME_COMPARISONS), + LintId::of(approx_const::APPROX_CONSTANT), + LintId::of(async_yields_async::ASYNC_YIELDS_ASYNC), + LintId::of(attrs::DEPRECATED_SEMVER), + LintId::of(attrs::MISMATCHED_TARGET_OS), + LintId::of(attrs::USELESS_ATTRIBUTE), + LintId::of(bit_mask::BAD_BIT_MASK), + LintId::of(bit_mask::INEFFECTIVE_BIT_MASK), + LintId::of(booleans::LOGIC_BUG), + LintId::of(casts::CAST_REF_TO_MUT), + LintId::of(copies::IFS_SAME_COND), + LintId::of(copies::IF_SAME_THEN_ELSE), + LintId::of(derive::DERIVE_HASH_XOR_EQ), + LintId::of(derive::DERIVE_ORD_XOR_PARTIAL_ORD), + LintId::of(drop_forget_ref::DROP_COPY), + LintId::of(drop_forget_ref::DROP_REF), + LintId::of(drop_forget_ref::FORGET_COPY), + LintId::of(drop_forget_ref::FORGET_REF), + LintId::of(enum_clike::ENUM_CLIKE_UNPORTABLE_VARIANT), + LintId::of(eq_op::EQ_OP), + LintId::of(erasing_op::ERASING_OP), + LintId::of(formatting::POSSIBLE_MISSING_COMMA), + LintId::of(functions::NOT_UNSAFE_PTR_ARG_DEREF), + LintId::of(if_let_mutex::IF_LET_MUTEX), + LintId::of(indexing_slicing::OUT_OF_BOUNDS_INDEXING), + LintId::of(infinite_iter::INFINITE_ITER), + LintId::of(inherent_to_string::INHERENT_TO_STRING_SHADOW_DISPLAY), + LintId::of(inline_fn_without_body::INLINE_FN_WITHOUT_BODY), + LintId::of(let_underscore::LET_UNDERSCORE_LOCK), + LintId::of(literal_representation::MISTYPED_LITERAL_SUFFIXES), + LintId::of(loops::ITER_NEXT_LOOP), + LintId::of(loops::NEVER_LOOP), + LintId::of(loops::WHILE_IMMUTABLE_CONDITION), + LintId::of(mem_replace::MEM_REPLACE_WITH_UNINIT), + LintId::of(methods::CLONE_DOUBLE_REF), + LintId::of(methods::ITERATOR_STEP_BY_ZERO), + LintId::of(methods::SUSPICIOUS_SPLITN), + LintId::of(methods::UNINIT_ASSUMED_INIT), + LintId::of(methods::ZST_OFFSET), + LintId::of(minmax::MIN_MAX), + LintId::of(misc::CMP_NAN), + LintId::of(misc::MODULO_ONE), + LintId::of(non_octal_unix_permissions::NON_OCTAL_UNIX_PERMISSIONS), + LintId::of(open_options::NONSENSICAL_OPEN_OPTIONS), + LintId::of(option_env_unwrap::OPTION_ENV_UNWRAP), + LintId::of(ptr::INVALID_NULL_PTR_USAGE), + LintId::of(ptr::MUT_FROM_REF), + LintId::of(ranges::REVERSED_EMPTY_RANGES), + LintId::of(regex::INVALID_REGEX), + LintId::of(self_assignment::SELF_ASSIGNMENT), + LintId::of(serde_api::SERDE_API_MISUSE), + LintId::of(size_of_in_element_count::SIZE_OF_IN_ELEMENT_COUNT), + LintId::of(swap::ALMOST_SWAPPED), + LintId::of(to_string_in_display::TO_STRING_IN_DISPLAY), + LintId::of(transmute::UNSOUND_COLLECTION_TRANSMUTE), + LintId::of(transmute::WRONG_TRANSMUTE), + LintId::of(transmuting_null::TRANSMUTING_NULL), + LintId::of(undropped_manually_drops::UNDROPPED_MANUALLY_DROPS), + LintId::of(unicode::INVISIBLE_CHARACTERS), + LintId::of(unit_return_expecting_ord::UNIT_RETURN_EXPECTING_ORD), + LintId::of(unit_types::UNIT_CMP), + LintId::of(unnamed_address::FN_ADDRESS_COMPARISONS), + LintId::of(unnamed_address::VTABLE_ADDRESS_COMPARISONS), + LintId::of(unused_io_amount::UNUSED_IO_AMOUNT), + LintId::of(unwrap::PANICKING_UNWRAP), + LintId::of(vec_resize_to_zero::VEC_RESIZE_TO_ZERO), +]) diff --git a/src/tools/clippy/clippy_lints/src/lib.register_internal.rs b/src/tools/clippy/clippy_lints/src/lib.register_internal.rs new file mode 100644 index 0000000000..c8c1e0262a --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/lib.register_internal.rs @@ -0,0 +1,18 @@ +// This file was generated by `cargo dev update_lints`. +// Use that command to update this file and do not edit by hand. +// Manual edits will be overwritten. + +store.register_group(true, "clippy::internal", Some("clippy_internal"), vec![ + LintId::of(utils::internal_lints::CLIPPY_LINTS_INTERNAL), + LintId::of(utils::internal_lints::COLLAPSIBLE_SPAN_LINT_CALLS), + LintId::of(utils::internal_lints::COMPILER_LINT_FUNCTIONS), + LintId::of(utils::internal_lints::DEFAULT_LINT), + LintId::of(utils::internal_lints::IF_CHAIN_STYLE), + LintId::of(utils::internal_lints::INTERNING_DEFINED_SYMBOL), + LintId::of(utils::internal_lints::INVALID_PATHS), + LintId::of(utils::internal_lints::LINT_WITHOUT_LINT_PASS), + LintId::of(utils::internal_lints::MATCH_TYPE_ON_DIAGNOSTIC_ITEM), + LintId::of(utils::internal_lints::OUTER_EXPN_EXPN_DATA), + LintId::of(utils::internal_lints::PRODUCE_ICE), + LintId::of(utils::internal_lints::UNNECESSARY_SYMBOL_STR), +]) diff --git a/src/tools/clippy/clippy_lints/src/lib.register_lints.rs b/src/tools/clippy/clippy_lints/src/lib.register_lints.rs new file mode 100644 index 0000000000..d5a3734737 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/lib.register_lints.rs @@ -0,0 +1,509 @@ +// This file was generated by `cargo dev update_lints`. +// Use that command to update this file and do not edit by hand. +// Manual edits will be overwritten. + +store.register_lints(&[ + #[cfg(feature = "internal-lints")] + utils::internal_lints::CLIPPY_LINTS_INTERNAL, + #[cfg(feature = "internal-lints")] + utils::internal_lints::COLLAPSIBLE_SPAN_LINT_CALLS, + #[cfg(feature = "internal-lints")] + utils::internal_lints::COMPILER_LINT_FUNCTIONS, + #[cfg(feature = "internal-lints")] + utils::internal_lints::DEFAULT_LINT, + #[cfg(feature = "internal-lints")] + utils::internal_lints::IF_CHAIN_STYLE, + #[cfg(feature = "internal-lints")] + utils::internal_lints::INTERNING_DEFINED_SYMBOL, + #[cfg(feature = "internal-lints")] + utils::internal_lints::INVALID_PATHS, + #[cfg(feature = "internal-lints")] + utils::internal_lints::LINT_WITHOUT_LINT_PASS, + #[cfg(feature = "internal-lints")] + utils::internal_lints::MATCH_TYPE_ON_DIAGNOSTIC_ITEM, + #[cfg(feature = "internal-lints")] + utils::internal_lints::OUTER_EXPN_EXPN_DATA, + #[cfg(feature = "internal-lints")] + utils::internal_lints::PRODUCE_ICE, + #[cfg(feature = "internal-lints")] + utils::internal_lints::UNNECESSARY_SYMBOL_STR, + absurd_extreme_comparisons::ABSURD_EXTREME_COMPARISONS, + approx_const::APPROX_CONSTANT, + arithmetic::FLOAT_ARITHMETIC, + arithmetic::INTEGER_ARITHMETIC, + as_conversions::AS_CONVERSIONS, + asm_syntax::INLINE_ASM_X86_ATT_SYNTAX, + asm_syntax::INLINE_ASM_X86_INTEL_SYNTAX, + assertions_on_constants::ASSERTIONS_ON_CONSTANTS, + assign_ops::ASSIGN_OP_PATTERN, + assign_ops::MISREFACTORED_ASSIGN_OP, + async_yields_async::ASYNC_YIELDS_ASYNC, + attrs::BLANKET_CLIPPY_RESTRICTION_LINTS, + attrs::DEPRECATED_CFG_ATTR, + attrs::DEPRECATED_SEMVER, + attrs::EMPTY_LINE_AFTER_OUTER_ATTR, + attrs::INLINE_ALWAYS, + attrs::MISMATCHED_TARGET_OS, + attrs::USELESS_ATTRIBUTE, + await_holding_invalid::AWAIT_HOLDING_LOCK, + await_holding_invalid::AWAIT_HOLDING_REFCELL_REF, + bit_mask::BAD_BIT_MASK, + bit_mask::INEFFECTIVE_BIT_MASK, + bit_mask::VERBOSE_BIT_MASK, + blacklisted_name::BLACKLISTED_NAME, + blocks_in_if_conditions::BLOCKS_IN_IF_CONDITIONS, + bool_assert_comparison::BOOL_ASSERT_COMPARISON, + booleans::LOGIC_BUG, + booleans::NONMINIMAL_BOOL, + bytecount::NAIVE_BYTECOUNT, + cargo_common_metadata::CARGO_COMMON_METADATA, + case_sensitive_file_extension_comparisons::CASE_SENSITIVE_FILE_EXTENSION_COMPARISONS, + casts::CAST_LOSSLESS, + casts::CAST_POSSIBLE_TRUNCATION, + casts::CAST_POSSIBLE_WRAP, + casts::CAST_PRECISION_LOSS, + casts::CAST_PTR_ALIGNMENT, + casts::CAST_REF_TO_MUT, + casts::CAST_SIGN_LOSS, + casts::CHAR_LIT_AS_U8, + casts::FN_TO_NUMERIC_CAST, + casts::FN_TO_NUMERIC_CAST_WITH_TRUNCATION, + casts::PTR_AS_PTR, + casts::UNNECESSARY_CAST, + checked_conversions::CHECKED_CONVERSIONS, + cognitive_complexity::COGNITIVE_COMPLEXITY, + collapsible_if::COLLAPSIBLE_ELSE_IF, + collapsible_if::COLLAPSIBLE_IF, + collapsible_match::COLLAPSIBLE_MATCH, + comparison_chain::COMPARISON_CHAIN, + copies::BRANCHES_SHARING_CODE, + copies::IFS_SAME_COND, + copies::IF_SAME_THEN_ELSE, + copies::SAME_FUNCTIONS_IN_IF_CONDITION, + copy_iterator::COPY_ITERATOR, + create_dir::CREATE_DIR, + dbg_macro::DBG_MACRO, + default::DEFAULT_TRAIT_ACCESS, + default::FIELD_REASSIGN_WITH_DEFAULT, + default_numeric_fallback::DEFAULT_NUMERIC_FALLBACK, + dereference::EXPLICIT_DEREF_METHODS, + derivable_impls::DERIVABLE_IMPLS, + derive::DERIVE_HASH_XOR_EQ, + derive::DERIVE_ORD_XOR_PARTIAL_ORD, + derive::EXPL_IMPL_CLONE_ON_COPY, + derive::UNSAFE_DERIVE_DESERIALIZE, + disallowed_method::DISALLOWED_METHOD, + disallowed_script_idents::DISALLOWED_SCRIPT_IDENTS, + disallowed_type::DISALLOWED_TYPE, + doc::DOC_MARKDOWN, + doc::MISSING_ERRORS_DOC, + doc::MISSING_PANICS_DOC, + doc::MISSING_SAFETY_DOC, + doc::NEEDLESS_DOCTEST_MAIN, + double_comparison::DOUBLE_COMPARISONS, + double_parens::DOUBLE_PARENS, + drop_forget_ref::DROP_COPY, + drop_forget_ref::DROP_REF, + drop_forget_ref::FORGET_COPY, + drop_forget_ref::FORGET_REF, + duration_subsec::DURATION_SUBSEC, + else_if_without_else::ELSE_IF_WITHOUT_ELSE, + empty_enum::EMPTY_ENUM, + entry::MAP_ENTRY, + enum_clike::ENUM_CLIKE_UNPORTABLE_VARIANT, + enum_variants::ENUM_VARIANT_NAMES, + enum_variants::MODULE_INCEPTION, + enum_variants::MODULE_NAME_REPETITIONS, + eq_op::EQ_OP, + eq_op::OP_REF, + equatable_if_let::EQUATABLE_IF_LET, + erasing_op::ERASING_OP, + escape::BOXED_LOCAL, + eta_reduction::REDUNDANT_CLOSURE, + eta_reduction::REDUNDANT_CLOSURE_FOR_METHOD_CALLS, + eval_order_dependence::DIVERGING_SUB_EXPRESSION, + eval_order_dependence::EVAL_ORDER_DEPENDENCE, + excessive_bools::FN_PARAMS_EXCESSIVE_BOOLS, + excessive_bools::STRUCT_EXCESSIVE_BOOLS, + exhaustive_items::EXHAUSTIVE_ENUMS, + exhaustive_items::EXHAUSTIVE_STRUCTS, + exit::EXIT, + explicit_write::EXPLICIT_WRITE, + fallible_impl_from::FALLIBLE_IMPL_FROM, + feature_name::NEGATIVE_FEATURE_NAMES, + feature_name::REDUNDANT_FEATURE_NAMES, + float_equality_without_abs::FLOAT_EQUALITY_WITHOUT_ABS, + float_literal::EXCESSIVE_PRECISION, + float_literal::LOSSY_FLOAT_LITERAL, + floating_point_arithmetic::IMPRECISE_FLOPS, + floating_point_arithmetic::SUBOPTIMAL_FLOPS, + format::USELESS_FORMAT, + formatting::POSSIBLE_MISSING_COMMA, + formatting::SUSPICIOUS_ASSIGNMENT_FORMATTING, + formatting::SUSPICIOUS_ELSE_FORMATTING, + formatting::SUSPICIOUS_UNARY_OP_FORMATTING, + from_over_into::FROM_OVER_INTO, + from_str_radix_10::FROM_STR_RADIX_10, + functions::DOUBLE_MUST_USE, + functions::MUST_USE_CANDIDATE, + functions::MUST_USE_UNIT, + functions::NOT_UNSAFE_PTR_ARG_DEREF, + functions::RESULT_UNIT_ERR, + functions::TOO_MANY_ARGUMENTS, + functions::TOO_MANY_LINES, + future_not_send::FUTURE_NOT_SEND, + get_last_with_len::GET_LAST_WITH_LEN, + identity_op::IDENTITY_OP, + if_let_mutex::IF_LET_MUTEX, + if_not_else::IF_NOT_ELSE, + if_then_some_else_none::IF_THEN_SOME_ELSE_NONE, + implicit_hasher::IMPLICIT_HASHER, + implicit_return::IMPLICIT_RETURN, + implicit_saturating_sub::IMPLICIT_SATURATING_SUB, + inconsistent_struct_constructor::INCONSISTENT_STRUCT_CONSTRUCTOR, + indexing_slicing::INDEXING_SLICING, + indexing_slicing::OUT_OF_BOUNDS_INDEXING, + infinite_iter::INFINITE_ITER, + infinite_iter::MAYBE_INFINITE_ITER, + inherent_impl::MULTIPLE_INHERENT_IMPL, + inherent_to_string::INHERENT_TO_STRING, + inherent_to_string::INHERENT_TO_STRING_SHADOW_DISPLAY, + inline_fn_without_body::INLINE_FN_WITHOUT_BODY, + int_plus_one::INT_PLUS_ONE, + integer_division::INTEGER_DIVISION, + invalid_upcast_comparisons::INVALID_UPCAST_COMPARISONS, + items_after_statements::ITEMS_AFTER_STATEMENTS, + iter_not_returning_iterator::ITER_NOT_RETURNING_ITERATOR, + large_const_arrays::LARGE_CONST_ARRAYS, + large_enum_variant::LARGE_ENUM_VARIANT, + large_stack_arrays::LARGE_STACK_ARRAYS, + len_zero::COMPARISON_TO_EMPTY, + len_zero::LEN_WITHOUT_IS_EMPTY, + len_zero::LEN_ZERO, + let_if_seq::USELESS_LET_IF_SEQ, + let_underscore::LET_UNDERSCORE_DROP, + let_underscore::LET_UNDERSCORE_LOCK, + let_underscore::LET_UNDERSCORE_MUST_USE, + lifetimes::EXTRA_UNUSED_LIFETIMES, + lifetimes::NEEDLESS_LIFETIMES, + literal_representation::DECIMAL_LITERAL_REPRESENTATION, + literal_representation::INCONSISTENT_DIGIT_GROUPING, + literal_representation::LARGE_DIGIT_GROUPS, + literal_representation::MISTYPED_LITERAL_SUFFIXES, + literal_representation::UNREADABLE_LITERAL, + literal_representation::UNUSUAL_BYTE_GROUPINGS, + loops::EMPTY_LOOP, + loops::EXPLICIT_COUNTER_LOOP, + loops::EXPLICIT_INTO_ITER_LOOP, + loops::EXPLICIT_ITER_LOOP, + loops::FOR_KV_MAP, + loops::FOR_LOOPS_OVER_FALLIBLES, + loops::ITER_NEXT_LOOP, + loops::MANUAL_FLATTEN, + loops::MANUAL_MEMCPY, + loops::MUT_RANGE_BOUND, + loops::NEEDLESS_COLLECT, + loops::NEEDLESS_RANGE_LOOP, + loops::NEVER_LOOP, + loops::SAME_ITEM_PUSH, + loops::SINGLE_ELEMENT_LOOP, + loops::WHILE_IMMUTABLE_CONDITION, + loops::WHILE_LET_LOOP, + loops::WHILE_LET_ON_ITERATOR, + macro_use::MACRO_USE_IMPORTS, + main_recursion::MAIN_RECURSION, + manual_assert::MANUAL_ASSERT, + manual_async_fn::MANUAL_ASYNC_FN, + manual_map::MANUAL_MAP, + manual_non_exhaustive::MANUAL_NON_EXHAUSTIVE, + manual_ok_or::MANUAL_OK_OR, + manual_strip::MANUAL_STRIP, + manual_unwrap_or::MANUAL_UNWRAP_OR, + map_clone::MAP_CLONE, + map_err_ignore::MAP_ERR_IGNORE, + map_unit_fn::OPTION_MAP_UNIT_FN, + map_unit_fn::RESULT_MAP_UNIT_FN, + match_on_vec_items::MATCH_ON_VEC_ITEMS, + match_result_ok::MATCH_RESULT_OK, + matches::INFALLIBLE_DESTRUCTURING_MATCH, + matches::MATCH_AS_REF, + matches::MATCH_BOOL, + matches::MATCH_LIKE_MATCHES_MACRO, + matches::MATCH_OVERLAPPING_ARM, + matches::MATCH_REF_PATS, + matches::MATCH_SAME_ARMS, + matches::MATCH_SINGLE_BINDING, + matches::MATCH_WILDCARD_FOR_SINGLE_VARIANTS, + matches::MATCH_WILD_ERR_ARM, + matches::REDUNDANT_PATTERN_MATCHING, + matches::REST_PAT_IN_FULLY_BOUND_STRUCTS, + matches::SINGLE_MATCH, + matches::SINGLE_MATCH_ELSE, + matches::WILDCARD_ENUM_MATCH_ARM, + matches::WILDCARD_IN_OR_PATTERNS, + mem_forget::MEM_FORGET, + mem_replace::MEM_REPLACE_OPTION_WITH_NONE, + mem_replace::MEM_REPLACE_WITH_DEFAULT, + mem_replace::MEM_REPLACE_WITH_UNINIT, + methods::BIND_INSTEAD_OF_MAP, + methods::BYTES_NTH, + methods::CHARS_LAST_CMP, + methods::CHARS_NEXT_CMP, + methods::CLONED_INSTEAD_OF_COPIED, + methods::CLONE_DOUBLE_REF, + methods::CLONE_ON_COPY, + methods::CLONE_ON_REF_PTR, + methods::EXPECT_FUN_CALL, + methods::EXPECT_USED, + methods::EXTEND_WITH_DRAIN, + methods::FILETYPE_IS_FILE, + methods::FILTER_MAP_IDENTITY, + methods::FILTER_MAP_NEXT, + methods::FILTER_NEXT, + methods::FLAT_MAP_IDENTITY, + methods::FLAT_MAP_OPTION, + methods::FROM_ITER_INSTEAD_OF_COLLECT, + methods::GET_UNWRAP, + methods::IMPLICIT_CLONE, + methods::INEFFICIENT_TO_STRING, + methods::INSPECT_FOR_EACH, + methods::INTO_ITER_ON_REF, + methods::ITERATOR_STEP_BY_ZERO, + methods::ITER_CLONED_COLLECT, + methods::ITER_COUNT, + methods::ITER_NEXT_SLICE, + methods::ITER_NTH, + methods::ITER_NTH_ZERO, + methods::ITER_SKIP_NEXT, + methods::MANUAL_FILTER_MAP, + methods::MANUAL_FIND_MAP, + methods::MANUAL_SATURATING_ARITHMETIC, + methods::MANUAL_SPLIT_ONCE, + methods::MANUAL_STR_REPEAT, + methods::MAP_COLLECT_RESULT_UNIT, + methods::MAP_FLATTEN, + methods::MAP_IDENTITY, + methods::MAP_UNWRAP_OR, + methods::NEW_RET_NO_SELF, + methods::OK_EXPECT, + methods::OPTION_AS_REF_DEREF, + methods::OPTION_FILTER_MAP, + methods::OPTION_MAP_OR_NONE, + methods::OR_FUN_CALL, + methods::RESULT_MAP_OR_INTO_OPTION, + methods::SEARCH_IS_SOME, + methods::SHOULD_IMPLEMENT_TRAIT, + methods::SINGLE_CHAR_ADD_STR, + methods::SINGLE_CHAR_PATTERN, + methods::SKIP_WHILE_NEXT, + methods::STRING_EXTEND_CHARS, + methods::SUSPICIOUS_MAP, + methods::SUSPICIOUS_SPLITN, + methods::UNINIT_ASSUMED_INIT, + methods::UNNECESSARY_FILTER_MAP, + methods::UNNECESSARY_FOLD, + methods::UNNECESSARY_LAZY_EVALUATIONS, + methods::UNWRAP_OR_ELSE_DEFAULT, + methods::UNWRAP_USED, + methods::USELESS_ASREF, + methods::WRONG_SELF_CONVENTION, + methods::ZST_OFFSET, + minmax::MIN_MAX, + misc::CMP_NAN, + misc::CMP_OWNED, + misc::FLOAT_CMP, + misc::FLOAT_CMP_CONST, + misc::MODULO_ONE, + misc::SHORT_CIRCUIT_STATEMENT, + misc::TOPLEVEL_REF_ARG, + misc::USED_UNDERSCORE_BINDING, + misc::ZERO_PTR, + misc_early::BUILTIN_TYPE_SHADOW, + misc_early::DOUBLE_NEG, + misc_early::DUPLICATE_UNDERSCORE_ARGUMENT, + misc_early::MIXED_CASE_HEX_LITERALS, + misc_early::REDUNDANT_PATTERN, + misc_early::UNNEEDED_FIELD_PATTERN, + misc_early::UNNEEDED_WILDCARD_PATTERN, + misc_early::UNSEPARATED_LITERAL_SUFFIX, + misc_early::ZERO_PREFIXED_LITERAL, + missing_const_for_fn::MISSING_CONST_FOR_FN, + missing_doc::MISSING_DOCS_IN_PRIVATE_ITEMS, + missing_enforced_import_rename::MISSING_ENFORCED_IMPORT_RENAMES, + missing_inline::MISSING_INLINE_IN_PUBLIC_ITEMS, + module_style::MOD_MODULE_FILES, + module_style::SELF_NAMED_MODULE_FILES, + modulo_arithmetic::MODULO_ARITHMETIC, + multiple_crate_versions::MULTIPLE_CRATE_VERSIONS, + mut_key::MUTABLE_KEY_TYPE, + mut_mut::MUT_MUT, + mut_mutex_lock::MUT_MUTEX_LOCK, + mut_reference::UNNECESSARY_MUT_PASSED, + mutable_debug_assertion::DEBUG_ASSERT_WITH_MUT_CALL, + mutex_atomic::MUTEX_ATOMIC, + mutex_atomic::MUTEX_INTEGER, + needless_arbitrary_self_type::NEEDLESS_ARBITRARY_SELF_TYPE, + needless_bitwise_bool::NEEDLESS_BITWISE_BOOL, + needless_bool::BOOL_COMPARISON, + needless_bool::NEEDLESS_BOOL, + needless_borrow::NEEDLESS_BORROW, + needless_borrow::REF_BINDING_TO_REFERENCE, + needless_borrowed_ref::NEEDLESS_BORROWED_REFERENCE, + needless_continue::NEEDLESS_CONTINUE, + needless_for_each::NEEDLESS_FOR_EACH, + needless_option_as_deref::NEEDLESS_OPTION_AS_DEREF, + needless_pass_by_value::NEEDLESS_PASS_BY_VALUE, + needless_question_mark::NEEDLESS_QUESTION_MARK, + needless_update::NEEDLESS_UPDATE, + neg_cmp_op_on_partial_ord::NEG_CMP_OP_ON_PARTIAL_ORD, + neg_multiply::NEG_MULTIPLY, + new_without_default::NEW_WITHOUT_DEFAULT, + no_effect::NO_EFFECT, + no_effect::UNNECESSARY_OPERATION, + non_copy_const::BORROW_INTERIOR_MUTABLE_CONST, + non_copy_const::DECLARE_INTERIOR_MUTABLE_CONST, + non_expressive_names::JUST_UNDERSCORES_AND_DIGITS, + non_expressive_names::MANY_SINGLE_CHAR_NAMES, + non_expressive_names::SIMILAR_NAMES, + non_octal_unix_permissions::NON_OCTAL_UNIX_PERMISSIONS, + non_send_fields_in_send_ty::NON_SEND_FIELDS_IN_SEND_TY, + nonstandard_macro_braces::NONSTANDARD_MACRO_BRACES, + open_options::NONSENSICAL_OPEN_OPTIONS, + option_env_unwrap::OPTION_ENV_UNWRAP, + option_if_let_else::OPTION_IF_LET_ELSE, + overflow_check_conditional::OVERFLOW_CHECK_CONDITIONAL, + panic_in_result_fn::PANIC_IN_RESULT_FN, + panic_unimplemented::PANIC, + panic_unimplemented::TODO, + panic_unimplemented::UNIMPLEMENTED, + panic_unimplemented::UNREACHABLE, + partialeq_ne_impl::PARTIALEQ_NE_IMPL, + pass_by_ref_or_value::LARGE_TYPES_PASSED_BY_VALUE, + pass_by_ref_or_value::TRIVIALLY_COPY_PASS_BY_REF, + path_buf_push_overwrite::PATH_BUF_PUSH_OVERWRITE, + pattern_type_mismatch::PATTERN_TYPE_MISMATCH, + precedence::PRECEDENCE, + ptr::CMP_NULL, + ptr::INVALID_NULL_PTR_USAGE, + ptr::MUT_FROM_REF, + ptr::PTR_ARG, + ptr_eq::PTR_EQ, + ptr_offset_with_cast::PTR_OFFSET_WITH_CAST, + question_mark::QUESTION_MARK, + ranges::MANUAL_RANGE_CONTAINS, + ranges::RANGE_MINUS_ONE, + ranges::RANGE_PLUS_ONE, + ranges::RANGE_ZIP_WITH_LEN, + ranges::REVERSED_EMPTY_RANGES, + redundant_clone::REDUNDANT_CLONE, + redundant_closure_call::REDUNDANT_CLOSURE_CALL, + redundant_else::REDUNDANT_ELSE, + redundant_field_names::REDUNDANT_FIELD_NAMES, + redundant_pub_crate::REDUNDANT_PUB_CRATE, + redundant_slicing::REDUNDANT_SLICING, + redundant_static_lifetimes::REDUNDANT_STATIC_LIFETIMES, + ref_option_ref::REF_OPTION_REF, + reference::DEREF_ADDROF, + reference::REF_IN_DEREF, + regex::INVALID_REGEX, + regex::TRIVIAL_REGEX, + repeat_once::REPEAT_ONCE, + returns::LET_AND_RETURN, + returns::NEEDLESS_RETURN, + same_name_method::SAME_NAME_METHOD, + self_assignment::SELF_ASSIGNMENT, + self_named_constructors::SELF_NAMED_CONSTRUCTORS, + semicolon_if_nothing_returned::SEMICOLON_IF_NOTHING_RETURNED, + serde_api::SERDE_API_MISUSE, + shadow::SHADOW_REUSE, + shadow::SHADOW_SAME, + shadow::SHADOW_UNRELATED, + single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS, + size_of_in_element_count::SIZE_OF_IN_ELEMENT_COUNT, + slow_vector_initialization::SLOW_VECTOR_INITIALIZATION, + stable_sort_primitive::STABLE_SORT_PRIMITIVE, + strings::STRING_ADD, + strings::STRING_ADD_ASSIGN, + strings::STRING_FROM_UTF8_AS_BYTES, + strings::STRING_LIT_AS_BYTES, + strings::STRING_TO_STRING, + strings::STR_TO_STRING, + strlen_on_c_strings::STRLEN_ON_C_STRINGS, + suspicious_operation_groupings::SUSPICIOUS_OPERATION_GROUPINGS, + suspicious_trait_impl::SUSPICIOUS_ARITHMETIC_IMPL, + suspicious_trait_impl::SUSPICIOUS_OP_ASSIGN_IMPL, + swap::ALMOST_SWAPPED, + swap::MANUAL_SWAP, + tabs_in_doc_comments::TABS_IN_DOC_COMMENTS, + temporary_assignment::TEMPORARY_ASSIGNMENT, + to_digit_is_some::TO_DIGIT_IS_SOME, + to_string_in_display::TO_STRING_IN_DISPLAY, + trait_bounds::TRAIT_DUPLICATION_IN_BOUNDS, + trait_bounds::TYPE_REPETITION_IN_BOUNDS, + transmute::CROSSPOINTER_TRANSMUTE, + transmute::TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS, + transmute::TRANSMUTE_BYTES_TO_STR, + transmute::TRANSMUTE_FLOAT_TO_INT, + transmute::TRANSMUTE_INT_TO_BOOL, + transmute::TRANSMUTE_INT_TO_CHAR, + transmute::TRANSMUTE_INT_TO_FLOAT, + transmute::TRANSMUTE_PTR_TO_PTR, + transmute::TRANSMUTE_PTR_TO_REF, + transmute::UNSOUND_COLLECTION_TRANSMUTE, + transmute::USELESS_TRANSMUTE, + transmute::WRONG_TRANSMUTE, + transmuting_null::TRANSMUTING_NULL, + try_err::TRY_ERR, + types::BORROWED_BOX, + types::BOX_COLLECTION, + types::LINKEDLIST, + types::OPTION_OPTION, + types::RC_BUFFER, + types::RC_MUTEX, + types::REDUNDANT_ALLOCATION, + types::TYPE_COMPLEXITY, + types::VEC_BOX, + undropped_manually_drops::UNDROPPED_MANUALLY_DROPS, + unicode::INVISIBLE_CHARACTERS, + unicode::NON_ASCII_LITERAL, + unicode::UNICODE_NOT_NFC, + unit_return_expecting_ord::UNIT_RETURN_EXPECTING_ORD, + unit_types::LET_UNIT_VALUE, + unit_types::UNIT_ARG, + unit_types::UNIT_CMP, + unnamed_address::FN_ADDRESS_COMPARISONS, + unnamed_address::VTABLE_ADDRESS_COMPARISONS, + unnecessary_self_imports::UNNECESSARY_SELF_IMPORTS, + unnecessary_sort_by::UNNECESSARY_SORT_BY, + unnecessary_wraps::UNNECESSARY_WRAPS, + unnested_or_patterns::UNNESTED_OR_PATTERNS, + unsafe_removed_from_name::UNSAFE_REMOVED_FROM_NAME, + unused_async::UNUSED_ASYNC, + unused_io_amount::UNUSED_IO_AMOUNT, + unused_self::UNUSED_SELF, + unused_unit::UNUSED_UNIT, + unwrap::PANICKING_UNWRAP, + unwrap::UNNECESSARY_UNWRAP, + unwrap_in_result::UNWRAP_IN_RESULT, + upper_case_acronyms::UPPER_CASE_ACRONYMS, + use_self::USE_SELF, + useless_conversion::USELESS_CONVERSION, + vec::USELESS_VEC, + vec_init_then_push::VEC_INIT_THEN_PUSH, + vec_resize_to_zero::VEC_RESIZE_TO_ZERO, + verbose_file_reads::VERBOSE_FILE_READS, + wildcard_dependencies::WILDCARD_DEPENDENCIES, + wildcard_imports::ENUM_GLOB_USE, + wildcard_imports::WILDCARD_IMPORTS, + write::PRINTLN_EMPTY_STRING, + write::PRINT_LITERAL, + write::PRINT_STDERR, + write::PRINT_STDOUT, + write::PRINT_WITH_NEWLINE, + write::USE_DEBUG, + write::WRITELN_EMPTY_STRING, + write::WRITE_LITERAL, + write::WRITE_WITH_NEWLINE, + zero_div_zero::ZERO_DIVIDED_BY_ZERO, + zero_sized_map_values::ZERO_SIZED_MAP_VALUES, +]) diff --git a/src/tools/clippy/clippy_lints/src/lib.register_nursery.rs b/src/tools/clippy/clippy_lints/src/lib.register_nursery.rs new file mode 100644 index 0000000000..96e0b42109 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/lib.register_nursery.rs @@ -0,0 +1,30 @@ +// This file was generated by `cargo dev update_lints`. +// Use that command to update this file and do not edit by hand. +// Manual edits will be overwritten. + +store.register_group(true, "clippy::nursery", Some("clippy_nursery"), vec![ + LintId::of(attrs::EMPTY_LINE_AFTER_OUTER_ATTR), + LintId::of(cognitive_complexity::COGNITIVE_COMPLEXITY), + LintId::of(copies::BRANCHES_SHARING_CODE), + LintId::of(disallowed_method::DISALLOWED_METHOD), + LintId::of(disallowed_type::DISALLOWED_TYPE), + LintId::of(equatable_if_let::EQUATABLE_IF_LET), + LintId::of(fallible_impl_from::FALLIBLE_IMPL_FROM), + LintId::of(floating_point_arithmetic::IMPRECISE_FLOPS), + LintId::of(floating_point_arithmetic::SUBOPTIMAL_FLOPS), + LintId::of(future_not_send::FUTURE_NOT_SEND), + LintId::of(let_if_seq::USELESS_LET_IF_SEQ), + LintId::of(missing_const_for_fn::MISSING_CONST_FOR_FN), + LintId::of(mutable_debug_assertion::DEBUG_ASSERT_WITH_MUT_CALL), + LintId::of(mutex_atomic::MUTEX_INTEGER), + LintId::of(non_send_fields_in_send_ty::NON_SEND_FIELDS_IN_SEND_TY), + LintId::of(nonstandard_macro_braces::NONSTANDARD_MACRO_BRACES), + LintId::of(option_if_let_else::OPTION_IF_LET_ELSE), + LintId::of(path_buf_push_overwrite::PATH_BUF_PUSH_OVERWRITE), + LintId::of(redundant_pub_crate::REDUNDANT_PUB_CRATE), + LintId::of(regex::TRIVIAL_REGEX), + LintId::of(strings::STRING_LIT_AS_BYTES), + LintId::of(suspicious_operation_groupings::SUSPICIOUS_OPERATION_GROUPINGS), + 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 new file mode 100644 index 0000000000..a4b8109a35 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/lib.register_pedantic.rs @@ -0,0 +1,101 @@ +// This file was generated by `cargo dev update_lints`. +// Use that command to update this file and do not edit by hand. +// Manual edits will be overwritten. + +store.register_group(true, "clippy::pedantic", Some("clippy_pedantic"), vec![ + LintId::of(attrs::INLINE_ALWAYS), + LintId::of(await_holding_invalid::AWAIT_HOLDING_LOCK), + LintId::of(await_holding_invalid::AWAIT_HOLDING_REFCELL_REF), + LintId::of(bit_mask::VERBOSE_BIT_MASK), + LintId::of(bytecount::NAIVE_BYTECOUNT), + LintId::of(case_sensitive_file_extension_comparisons::CASE_SENSITIVE_FILE_EXTENSION_COMPARISONS), + LintId::of(casts::CAST_LOSSLESS), + LintId::of(casts::CAST_POSSIBLE_TRUNCATION), + LintId::of(casts::CAST_POSSIBLE_WRAP), + LintId::of(casts::CAST_PRECISION_LOSS), + LintId::of(casts::CAST_PTR_ALIGNMENT), + LintId::of(casts::CAST_SIGN_LOSS), + LintId::of(casts::PTR_AS_PTR), + LintId::of(checked_conversions::CHECKED_CONVERSIONS), + LintId::of(copies::SAME_FUNCTIONS_IN_IF_CONDITION), + LintId::of(copy_iterator::COPY_ITERATOR), + LintId::of(default::DEFAULT_TRAIT_ACCESS), + LintId::of(dereference::EXPLICIT_DEREF_METHODS), + LintId::of(derive::EXPL_IMPL_CLONE_ON_COPY), + LintId::of(derive::UNSAFE_DERIVE_DESERIALIZE), + LintId::of(doc::DOC_MARKDOWN), + LintId::of(doc::MISSING_ERRORS_DOC), + LintId::of(doc::MISSING_PANICS_DOC), + LintId::of(empty_enum::EMPTY_ENUM), + LintId::of(enum_variants::MODULE_NAME_REPETITIONS), + LintId::of(eta_reduction::REDUNDANT_CLOSURE_FOR_METHOD_CALLS), + LintId::of(excessive_bools::FN_PARAMS_EXCESSIVE_BOOLS), + LintId::of(excessive_bools::STRUCT_EXCESSIVE_BOOLS), + LintId::of(functions::MUST_USE_CANDIDATE), + LintId::of(functions::TOO_MANY_LINES), + LintId::of(if_not_else::IF_NOT_ELSE), + LintId::of(implicit_hasher::IMPLICIT_HASHER), + LintId::of(implicit_saturating_sub::IMPLICIT_SATURATING_SUB), + LintId::of(inconsistent_struct_constructor::INCONSISTENT_STRUCT_CONSTRUCTOR), + LintId::of(infinite_iter::MAYBE_INFINITE_ITER), + LintId::of(invalid_upcast_comparisons::INVALID_UPCAST_COMPARISONS), + LintId::of(items_after_statements::ITEMS_AFTER_STATEMENTS), + LintId::of(iter_not_returning_iterator::ITER_NOT_RETURNING_ITERATOR), + LintId::of(large_stack_arrays::LARGE_STACK_ARRAYS), + LintId::of(let_underscore::LET_UNDERSCORE_DROP), + LintId::of(literal_representation::LARGE_DIGIT_GROUPS), + LintId::of(literal_representation::UNREADABLE_LITERAL), + LintId::of(loops::EXPLICIT_INTO_ITER_LOOP), + LintId::of(loops::EXPLICIT_ITER_LOOP), + LintId::of(macro_use::MACRO_USE_IMPORTS), + LintId::of(manual_assert::MANUAL_ASSERT), + LintId::of(manual_ok_or::MANUAL_OK_OR), + LintId::of(match_on_vec_items::MATCH_ON_VEC_ITEMS), + LintId::of(matches::MATCH_BOOL), + LintId::of(matches::MATCH_SAME_ARMS), + LintId::of(matches::MATCH_WILDCARD_FOR_SINGLE_VARIANTS), + LintId::of(matches::MATCH_WILD_ERR_ARM), + LintId::of(matches::SINGLE_MATCH_ELSE), + LintId::of(methods::CLONED_INSTEAD_OF_COPIED), + LintId::of(methods::FILTER_MAP_NEXT), + LintId::of(methods::FLAT_MAP_OPTION), + LintId::of(methods::FROM_ITER_INSTEAD_OF_COLLECT), + LintId::of(methods::IMPLICIT_CLONE), + LintId::of(methods::INEFFICIENT_TO_STRING), + LintId::of(methods::MAP_FLATTEN), + LintId::of(methods::MAP_UNWRAP_OR), + LintId::of(misc::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(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), + LintId::of(pass_by_ref_or_value::TRIVIALLY_COPY_PASS_BY_REF), + LintId::of(ranges::RANGE_MINUS_ONE), + LintId::of(ranges::RANGE_PLUS_ONE), + LintId::of(redundant_else::REDUNDANT_ELSE), + LintId::of(ref_option_ref::REF_OPTION_REF), + LintId::of(semicolon_if_nothing_returned::SEMICOLON_IF_NOTHING_RETURNED), + LintId::of(strings::STRING_ADD_ASSIGN), + LintId::of(trait_bounds::TRAIT_DUPLICATION_IN_BOUNDS), + LintId::of(trait_bounds::TYPE_REPETITION_IN_BOUNDS), + LintId::of(transmute::TRANSMUTE_PTR_TO_PTR), + LintId::of(types::LINKEDLIST), + LintId::of(types::OPTION_OPTION), + LintId::of(unicode::NON_ASCII_LITERAL), + LintId::of(unicode::UNICODE_NOT_NFC), + LintId::of(unit_types::LET_UNIT_VALUE), + LintId::of(unnecessary_wraps::UNNECESSARY_WRAPS), + LintId::of(unnested_or_patterns::UNNESTED_OR_PATTERNS), + LintId::of(unused_async::UNUSED_ASYNC), + LintId::of(unused_self::UNUSED_SELF), + LintId::of(wildcard_imports::ENUM_GLOB_USE), + LintId::of(wildcard_imports::WILDCARD_IMPORTS), + LintId::of(zero_sized_map_values::ZERO_SIZED_MAP_VALUES), +]) diff --git a/src/tools/clippy/clippy_lints/src/lib.register_perf.rs b/src/tools/clippy/clippy_lints/src/lib.register_perf.rs new file mode 100644 index 0000000000..5432345760 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/lib.register_perf.rs @@ -0,0 +1,27 @@ +// This file was generated by `cargo dev update_lints`. +// Use that command to update this file and do not edit by hand. +// Manual edits will be overwritten. + +store.register_group(true, "clippy::perf", Some("clippy_perf"), vec![ + LintId::of(entry::MAP_ENTRY), + LintId::of(escape::BOXED_LOCAL), + LintId::of(large_const_arrays::LARGE_CONST_ARRAYS), + LintId::of(large_enum_variant::LARGE_ENUM_VARIANT), + LintId::of(loops::MANUAL_MEMCPY), + LintId::of(loops::NEEDLESS_COLLECT), + LintId::of(methods::EXPECT_FUN_CALL), + LintId::of(methods::EXTEND_WITH_DRAIN), + LintId::of(methods::ITER_NTH), + LintId::of(methods::MANUAL_STR_REPEAT), + LintId::of(methods::OR_FUN_CALL), + LintId::of(methods::SINGLE_CHAR_PATTERN), + LintId::of(misc::CMP_OWNED), + LintId::of(mutex_atomic::MUTEX_ATOMIC), + LintId::of(redundant_clone::REDUNDANT_CLONE), + LintId::of(slow_vector_initialization::SLOW_VECTOR_INITIALIZATION), + LintId::of(stable_sort_primitive::STABLE_SORT_PRIMITIVE), + LintId::of(types::BOX_COLLECTION), + LintId::of(types::REDUNDANT_ALLOCATION), + LintId::of(vec::USELESS_VEC), + LintId::of(vec_init_then_push::VEC_INIT_THEN_PUSH), +]) diff --git a/src/tools/clippy/clippy_lints/src/lib.register_restriction.rs b/src/tools/clippy/clippy_lints/src/lib.register_restriction.rs new file mode 100644 index 0000000000..4463dea5fc --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/lib.register_restriction.rs @@ -0,0 +1,65 @@ +// This file was generated by `cargo dev update_lints`. +// Use that command to update this file and do not edit by hand. +// Manual edits will be overwritten. + +store.register_group(true, "clippy::restriction", Some("clippy_restriction"), vec![ + LintId::of(arithmetic::FLOAT_ARITHMETIC), + LintId::of(arithmetic::INTEGER_ARITHMETIC), + LintId::of(as_conversions::AS_CONVERSIONS), + LintId::of(asm_syntax::INLINE_ASM_X86_ATT_SYNTAX), + LintId::of(asm_syntax::INLINE_ASM_X86_INTEL_SYNTAX), + LintId::of(create_dir::CREATE_DIR), + LintId::of(dbg_macro::DBG_MACRO), + LintId::of(default_numeric_fallback::DEFAULT_NUMERIC_FALLBACK), + LintId::of(disallowed_script_idents::DISALLOWED_SCRIPT_IDENTS), + LintId::of(else_if_without_else::ELSE_IF_WITHOUT_ELSE), + LintId::of(exhaustive_items::EXHAUSTIVE_ENUMS), + LintId::of(exhaustive_items::EXHAUSTIVE_STRUCTS), + LintId::of(exit::EXIT), + LintId::of(float_literal::LOSSY_FLOAT_LITERAL), + LintId::of(if_then_some_else_none::IF_THEN_SOME_ELSE_NONE), + LintId::of(implicit_return::IMPLICIT_RETURN), + LintId::of(indexing_slicing::INDEXING_SLICING), + LintId::of(inherent_impl::MULTIPLE_INHERENT_IMPL), + LintId::of(integer_division::INTEGER_DIVISION), + LintId::of(let_underscore::LET_UNDERSCORE_MUST_USE), + LintId::of(literal_representation::DECIMAL_LITERAL_REPRESENTATION), + LintId::of(map_err_ignore::MAP_ERR_IGNORE), + LintId::of(matches::REST_PAT_IN_FULLY_BOUND_STRUCTS), + LintId::of(matches::WILDCARD_ENUM_MATCH_ARM), + LintId::of(mem_forget::MEM_FORGET), + LintId::of(methods::CLONE_ON_REF_PTR), + LintId::of(methods::EXPECT_USED), + LintId::of(methods::FILETYPE_IS_FILE), + LintId::of(methods::GET_UNWRAP), + LintId::of(methods::UNWRAP_USED), + LintId::of(misc::FLOAT_CMP_CONST), + LintId::of(misc_early::UNNEEDED_FIELD_PATTERN), + LintId::of(missing_doc::MISSING_DOCS_IN_PRIVATE_ITEMS), + LintId::of(missing_enforced_import_rename::MISSING_ENFORCED_IMPORT_RENAMES), + LintId::of(missing_inline::MISSING_INLINE_IN_PUBLIC_ITEMS), + LintId::of(module_style::MOD_MODULE_FILES), + LintId::of(module_style::SELF_NAMED_MODULE_FILES), + LintId::of(modulo_arithmetic::MODULO_ARITHMETIC), + LintId::of(panic_in_result_fn::PANIC_IN_RESULT_FN), + LintId::of(panic_unimplemented::PANIC), + LintId::of(panic_unimplemented::TODO), + LintId::of(panic_unimplemented::UNIMPLEMENTED), + LintId::of(panic_unimplemented::UNREACHABLE), + LintId::of(pattern_type_mismatch::PATTERN_TYPE_MISMATCH), + LintId::of(same_name_method::SAME_NAME_METHOD), + LintId::of(shadow::SHADOW_REUSE), + LintId::of(shadow::SHADOW_SAME), + LintId::of(shadow::SHADOW_UNRELATED), + LintId::of(strings::STRING_ADD), + LintId::of(strings::STRING_TO_STRING), + LintId::of(strings::STR_TO_STRING), + LintId::of(types::RC_BUFFER), + LintId::of(types::RC_MUTEX), + LintId::of(unnecessary_self_imports::UNNECESSARY_SELF_IMPORTS), + LintId::of(unwrap_in_result::UNWRAP_IN_RESULT), + LintId::of(verbose_file_reads::VERBOSE_FILE_READS), + LintId::of(write::PRINT_STDERR), + LintId::of(write::PRINT_STDOUT), + LintId::of(write::USE_DEBUG), +]) diff --git a/src/tools/clippy/clippy_lints/src/lib.register_style.rs b/src/tools/clippy/clippy_lints/src/lib.register_style.rs new file mode 100644 index 0000000000..744880bda3 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/lib.register_style.rs @@ -0,0 +1,113 @@ +// This file was generated by `cargo dev update_lints`. +// Use that command to update this file and do not edit by hand. +// Manual edits will be overwritten. + +store.register_group(true, "clippy::style", Some("clippy_style"), vec![ + LintId::of(assertions_on_constants::ASSERTIONS_ON_CONSTANTS), + LintId::of(assign_ops::ASSIGN_OP_PATTERN), + LintId::of(blacklisted_name::BLACKLISTED_NAME), + LintId::of(blocks_in_if_conditions::BLOCKS_IN_IF_CONDITIONS), + LintId::of(bool_assert_comparison::BOOL_ASSERT_COMPARISON), + LintId::of(casts::FN_TO_NUMERIC_CAST), + LintId::of(casts::FN_TO_NUMERIC_CAST_WITH_TRUNCATION), + LintId::of(collapsible_if::COLLAPSIBLE_ELSE_IF), + LintId::of(collapsible_if::COLLAPSIBLE_IF), + LintId::of(collapsible_match::COLLAPSIBLE_MATCH), + LintId::of(comparison_chain::COMPARISON_CHAIN), + LintId::of(default::FIELD_REASSIGN_WITH_DEFAULT), + LintId::of(doc::MISSING_SAFETY_DOC), + LintId::of(doc::NEEDLESS_DOCTEST_MAIN), + LintId::of(enum_variants::ENUM_VARIANT_NAMES), + LintId::of(enum_variants::MODULE_INCEPTION), + LintId::of(eq_op::OP_REF), + LintId::of(eta_reduction::REDUNDANT_CLOSURE), + LintId::of(float_literal::EXCESSIVE_PRECISION), + LintId::of(from_over_into::FROM_OVER_INTO), + LintId::of(from_str_radix_10::FROM_STR_RADIX_10), + LintId::of(functions::DOUBLE_MUST_USE), + LintId::of(functions::MUST_USE_UNIT), + LintId::of(functions::RESULT_UNIT_ERR), + LintId::of(inherent_to_string::INHERENT_TO_STRING), + LintId::of(len_zero::COMPARISON_TO_EMPTY), + LintId::of(len_zero::LEN_WITHOUT_IS_EMPTY), + LintId::of(len_zero::LEN_ZERO), + LintId::of(literal_representation::INCONSISTENT_DIGIT_GROUPING), + LintId::of(literal_representation::UNUSUAL_BYTE_GROUPINGS), + LintId::of(loops::FOR_KV_MAP), + LintId::of(loops::NEEDLESS_RANGE_LOOP), + LintId::of(loops::SAME_ITEM_PUSH), + LintId::of(loops::WHILE_LET_ON_ITERATOR), + LintId::of(main_recursion::MAIN_RECURSION), + LintId::of(manual_async_fn::MANUAL_ASYNC_FN), + LintId::of(manual_map::MANUAL_MAP), + LintId::of(manual_non_exhaustive::MANUAL_NON_EXHAUSTIVE), + LintId::of(map_clone::MAP_CLONE), + LintId::of(match_result_ok::MATCH_RESULT_OK), + LintId::of(matches::INFALLIBLE_DESTRUCTURING_MATCH), + LintId::of(matches::MATCH_LIKE_MATCHES_MACRO), + LintId::of(matches::MATCH_OVERLAPPING_ARM), + LintId::of(matches::MATCH_REF_PATS), + LintId::of(matches::REDUNDANT_PATTERN_MATCHING), + LintId::of(matches::SINGLE_MATCH), + LintId::of(mem_replace::MEM_REPLACE_OPTION_WITH_NONE), + LintId::of(mem_replace::MEM_REPLACE_WITH_DEFAULT), + LintId::of(methods::BYTES_NTH), + LintId::of(methods::CHARS_LAST_CMP), + LintId::of(methods::CHARS_NEXT_CMP), + LintId::of(methods::INTO_ITER_ON_REF), + LintId::of(methods::ITER_CLONED_COLLECT), + LintId::of(methods::ITER_NEXT_SLICE), + LintId::of(methods::ITER_NTH_ZERO), + LintId::of(methods::ITER_SKIP_NEXT), + LintId::of(methods::MANUAL_SATURATING_ARITHMETIC), + LintId::of(methods::MAP_COLLECT_RESULT_UNIT), + LintId::of(methods::NEW_RET_NO_SELF), + LintId::of(methods::OK_EXPECT), + LintId::of(methods::OPTION_MAP_OR_NONE), + LintId::of(methods::RESULT_MAP_OR_INTO_OPTION), + LintId::of(methods::SHOULD_IMPLEMENT_TRAIT), + LintId::of(methods::SINGLE_CHAR_ADD_STR), + LintId::of(methods::STRING_EXTEND_CHARS), + LintId::of(methods::UNNECESSARY_FOLD), + LintId::of(methods::UNNECESSARY_LAZY_EVALUATIONS), + LintId::of(methods::UNWRAP_OR_ELSE_DEFAULT), + LintId::of(methods::WRONG_SELF_CONVENTION), + LintId::of(misc::TOPLEVEL_REF_ARG), + LintId::of(misc::ZERO_PTR), + LintId::of(misc_early::BUILTIN_TYPE_SHADOW), + LintId::of(misc_early::DOUBLE_NEG), + LintId::of(misc_early::DUPLICATE_UNDERSCORE_ARGUMENT), + LintId::of(misc_early::MIXED_CASE_HEX_LITERALS), + LintId::of(misc_early::REDUNDANT_PATTERN), + LintId::of(mut_mutex_lock::MUT_MUTEX_LOCK), + LintId::of(mut_reference::UNNECESSARY_MUT_PASSED), + LintId::of(needless_borrow::NEEDLESS_BORROW), + LintId::of(neg_multiply::NEG_MULTIPLY), + LintId::of(new_without_default::NEW_WITHOUT_DEFAULT), + LintId::of(non_copy_const::BORROW_INTERIOR_MUTABLE_CONST), + LintId::of(non_copy_const::DECLARE_INTERIOR_MUTABLE_CONST), + LintId::of(non_expressive_names::JUST_UNDERSCORES_AND_DIGITS), + LintId::of(ptr::CMP_NULL), + LintId::of(ptr::PTR_ARG), + LintId::of(ptr_eq::PTR_EQ), + LintId::of(question_mark::QUESTION_MARK), + LintId::of(ranges::MANUAL_RANGE_CONTAINS), + LintId::of(redundant_field_names::REDUNDANT_FIELD_NAMES), + LintId::of(redundant_static_lifetimes::REDUNDANT_STATIC_LIFETIMES), + LintId::of(returns::LET_AND_RETURN), + LintId::of(returns::NEEDLESS_RETURN), + LintId::of(self_named_constructors::SELF_NAMED_CONSTRUCTORS), + LintId::of(single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS), + LintId::of(tabs_in_doc_comments::TABS_IN_DOC_COMMENTS), + LintId::of(to_digit_is_some::TO_DIGIT_IS_SOME), + LintId::of(try_err::TRY_ERR), + LintId::of(unsafe_removed_from_name::UNSAFE_REMOVED_FROM_NAME), + LintId::of(unused_unit::UNUSED_UNIT), + LintId::of(upper_case_acronyms::UPPER_CASE_ACRONYMS), + LintId::of(write::PRINTLN_EMPTY_STRING), + LintId::of(write::PRINT_LITERAL), + LintId::of(write::PRINT_WITH_NEWLINE), + LintId::of(write::WRITELN_EMPTY_STRING), + LintId::of(write::WRITE_LITERAL), + LintId::of(write::WRITE_WITH_NEWLINE), +]) diff --git a/src/tools/clippy/clippy_lints/src/lib.register_suspicious.rs b/src/tools/clippy/clippy_lints/src/lib.register_suspicious.rs new file mode 100644 index 0000000000..8859787fbc --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/lib.register_suspicious.rs @@ -0,0 +1,20 @@ +// This file was generated by `cargo dev update_lints`. +// Use that command to update this file and do not edit by hand. +// Manual edits will be overwritten. + +store.register_group(true, "clippy::suspicious", Some("clippy_suspicious"), vec![ + LintId::of(assign_ops::MISREFACTORED_ASSIGN_OP), + LintId::of(attrs::BLANKET_CLIPPY_RESTRICTION_LINTS), + LintId::of(eval_order_dependence::EVAL_ORDER_DEPENDENCE), + LintId::of(float_equality_without_abs::FLOAT_EQUALITY_WITHOUT_ABS), + LintId::of(formatting::SUSPICIOUS_ASSIGNMENT_FORMATTING), + LintId::of(formatting::SUSPICIOUS_ELSE_FORMATTING), + LintId::of(formatting::SUSPICIOUS_UNARY_OP_FORMATTING), + LintId::of(loops::EMPTY_LOOP), + LintId::of(loops::FOR_LOOPS_OVER_FALLIBLES), + LintId::of(loops::MUT_RANGE_BOUND), + LintId::of(methods::SUSPICIOUS_MAP), + LintId::of(mut_key::MUTABLE_KEY_TYPE), + LintId::of(suspicious_trait_impl::SUSPICIOUS_ARITHMETIC_IMPL), + LintId::of(suspicious_trait_impl::SUSPICIOUS_OP_ASSIGN_IMPL), +]) diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs index 1971950287..78ecdb99be 100644 --- a/src/tools/clippy/clippy_lints/src/lib.rs +++ b/src/tools/clippy/clippy_lints/src/lib.rs @@ -31,7 +31,7 @@ extern crate rustc_infer; extern crate rustc_lexer; extern crate rustc_lint; extern crate rustc_middle; -extern crate rustc_mir; +extern crate rustc_mir_dataflow; extern crate rustc_parse; extern crate rustc_parse_format; extern crate rustc_session; @@ -187,6 +187,7 @@ mod dbg_macro; mod default; mod default_numeric_fallback; mod dereference; +mod derivable_impls; mod derive; mod disallowed_method; mod disallowed_script_idents; @@ -202,6 +203,7 @@ mod entry; mod enum_clike; mod enum_variants; mod eq_op; +mod equatable_if_let; mod erasing_op; mod escape; mod eta_reduction; @@ -211,6 +213,7 @@ mod exhaustive_items; mod exit; mod explicit_write; mod fallible_impl_from; +mod feature_name; mod float_equality_without_abs; mod float_literal; mod floating_point_arithmetic; @@ -223,7 +226,6 @@ mod future_not_send; mod get_last_with_len; mod identity_op; mod if_let_mutex; -mod if_let_some_result; mod if_not_else; mod if_then_some_else_none; mod implicit_hasher; @@ -239,6 +241,7 @@ mod int_plus_one; mod integer_division; mod invalid_upcast_comparisons; mod items_after_statements; +mod iter_not_returning_iterator; mod large_const_arrays; mod large_enum_variant; mod large_stack_arrays; @@ -250,6 +253,7 @@ mod literal_representation; mod loops; mod macro_use; mod main_recursion; +mod manual_assert; mod manual_async_fn; mod manual_map; mod manual_non_exhaustive; @@ -260,8 +264,8 @@ mod map_clone; mod map_err_ignore; mod map_unit_fn; mod match_on_vec_items; +mod match_result_ok; mod matches; -mod mem_discriminant; mod mem_forget; mod mem_replace; mod methods; @@ -272,6 +276,7 @@ mod missing_const_for_fn; mod missing_doc; mod missing_enforced_import_rename; mod missing_inline; +mod module_style; mod modulo_arithmetic; mod multiple_crate_versions; mod mut_key; @@ -287,6 +292,7 @@ mod needless_borrow; mod needless_borrowed_ref; mod needless_continue; mod needless_for_each; +mod needless_option_as_deref; mod needless_pass_by_value; mod needless_question_mark; mod needless_update; @@ -297,6 +303,7 @@ mod no_effect; mod non_copy_const; mod non_expressive_names; mod non_octal_unix_permissions; +mod non_send_fields_in_send_ty; mod nonstandard_macro_braces; mod open_options; mod option_env_unwrap; @@ -326,6 +333,7 @@ mod reference; mod regex; mod repeat_once; mod returns; +mod same_name_method; mod self_assignment; mod self_named_constructors; mod semicolon_if_nothing_returned; @@ -431,1380 +439,23 @@ pub fn read_conf(sess: &Session) -> Conf { pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &Conf) { register_removed_non_tool_lints(store); - // begin deprecated lints, do not remove this comment, it’s used in `update_lints` - store.register_removed( - "clippy::should_assert_eq", - "`assert!()` will be more flexible with RFC 2011", - ); - store.register_removed( - "clippy::extend_from_slice", - "`.extend_from_slice(_)` is a faster way to extend a Vec by a slice", - ); - store.register_removed( - "clippy::range_step_by_zero", - "`iterator.step_by(0)` panics nowadays", - ); - store.register_removed( - "clippy::unstable_as_slice", - "`Vec::as_slice` has been stabilized in 1.7", - ); - store.register_removed( - "clippy::unstable_as_mut_slice", - "`Vec::as_mut_slice` has been stabilized in 1.7", - ); - store.register_removed( - "clippy::misaligned_transmute", - "this lint has been split into cast_ptr_alignment and transmute_ptr_to_ptr", - ); - store.register_removed( - "clippy::assign_ops", - "using compound assignment operators (e.g., `+=`) is harmless", - ); - store.register_removed( - "clippy::if_let_redundant_pattern_matching", - "this lint has been changed to redundant_pattern_matching", - ); - store.register_removed( - "clippy::unsafe_vector_initialization", - "the replacement suggested by this lint had substantially different behavior", - ); - store.register_removed( - "clippy::unused_collect", - "`collect` has been marked as #[must_use] in rustc and that covers all cases of this lint", - ); - store.register_removed( - "clippy::replace_consts", - "associated-constants `MIN`/`MAX` of integers are preferred to `{min,max}_value()` and module constants", - ); - store.register_removed( - "clippy::regex_macro", - "the regex! macro has been removed from the regex crate in 2018", - ); - store.register_removed( - "clippy::find_map", - "this lint has been replaced by `manual_find_map`, a more specific lint", - ); - store.register_removed( - "clippy::filter_map", - "this lint has been replaced by `manual_filter_map`, a more specific lint", - ); - store.register_removed( - "clippy::pub_enum_variant_names", - "set the `avoid-breaking-exported-api` config option to `false` to enable the `enum_variant_names` lint for public items", - ); - store.register_removed( - "clippy::wrong_pub_self_convention", - "set the `avoid-breaking-exported-api` config option to `false` to enable the `wrong_self_convention` lint for public items", - ); - // end deprecated lints, do not remove this comment, it’s used in `update_lints` + include!("lib.deprecated.rs"); - // begin register lints, do not remove this comment, it’s used in `update_lints` - store.register_lints(&[ - #[cfg(feature = "internal-lints")] - utils::internal_lints::CLIPPY_LINTS_INTERNAL, - #[cfg(feature = "internal-lints")] - utils::internal_lints::COLLAPSIBLE_SPAN_LINT_CALLS, - #[cfg(feature = "internal-lints")] - utils::internal_lints::COMPILER_LINT_FUNCTIONS, - #[cfg(feature = "internal-lints")] - utils::internal_lints::DEFAULT_LINT, - #[cfg(feature = "internal-lints")] - utils::internal_lints::IF_CHAIN_STYLE, - #[cfg(feature = "internal-lints")] - utils::internal_lints::INTERNING_DEFINED_SYMBOL, - #[cfg(feature = "internal-lints")] - utils::internal_lints::INVALID_PATHS, - #[cfg(feature = "internal-lints")] - utils::internal_lints::LINT_WITHOUT_LINT_PASS, - #[cfg(feature = "internal-lints")] - utils::internal_lints::MATCH_TYPE_ON_DIAGNOSTIC_ITEM, - #[cfg(feature = "internal-lints")] - utils::internal_lints::OUTER_EXPN_EXPN_DATA, - #[cfg(feature = "internal-lints")] - utils::internal_lints::PRODUCE_ICE, - #[cfg(feature = "internal-lints")] - utils::internal_lints::UNNECESSARY_SYMBOL_STR, - absurd_extreme_comparisons::ABSURD_EXTREME_COMPARISONS, - approx_const::APPROX_CONSTANT, - arithmetic::FLOAT_ARITHMETIC, - arithmetic::INTEGER_ARITHMETIC, - as_conversions::AS_CONVERSIONS, - asm_syntax::INLINE_ASM_X86_ATT_SYNTAX, - asm_syntax::INLINE_ASM_X86_INTEL_SYNTAX, - assertions_on_constants::ASSERTIONS_ON_CONSTANTS, - assign_ops::ASSIGN_OP_PATTERN, - assign_ops::MISREFACTORED_ASSIGN_OP, - async_yields_async::ASYNC_YIELDS_ASYNC, - attrs::BLANKET_CLIPPY_RESTRICTION_LINTS, - attrs::DEPRECATED_CFG_ATTR, - attrs::DEPRECATED_SEMVER, - attrs::EMPTY_LINE_AFTER_OUTER_ATTR, - attrs::INLINE_ALWAYS, - attrs::MISMATCHED_TARGET_OS, - attrs::USELESS_ATTRIBUTE, - await_holding_invalid::AWAIT_HOLDING_LOCK, - await_holding_invalid::AWAIT_HOLDING_REFCELL_REF, - bit_mask::BAD_BIT_MASK, - bit_mask::INEFFECTIVE_BIT_MASK, - bit_mask::VERBOSE_BIT_MASK, - blacklisted_name::BLACKLISTED_NAME, - blocks_in_if_conditions::BLOCKS_IN_IF_CONDITIONS, - bool_assert_comparison::BOOL_ASSERT_COMPARISON, - booleans::LOGIC_BUG, - booleans::NONMINIMAL_BOOL, - bytecount::NAIVE_BYTECOUNT, - cargo_common_metadata::CARGO_COMMON_METADATA, - case_sensitive_file_extension_comparisons::CASE_SENSITIVE_FILE_EXTENSION_COMPARISONS, - casts::CAST_LOSSLESS, - casts::CAST_POSSIBLE_TRUNCATION, - casts::CAST_POSSIBLE_WRAP, - casts::CAST_PRECISION_LOSS, - casts::CAST_PTR_ALIGNMENT, - casts::CAST_REF_TO_MUT, - casts::CAST_SIGN_LOSS, - casts::CHAR_LIT_AS_U8, - casts::FN_TO_NUMERIC_CAST, - casts::FN_TO_NUMERIC_CAST_WITH_TRUNCATION, - casts::PTR_AS_PTR, - casts::UNNECESSARY_CAST, - checked_conversions::CHECKED_CONVERSIONS, - cognitive_complexity::COGNITIVE_COMPLEXITY, - collapsible_if::COLLAPSIBLE_ELSE_IF, - collapsible_if::COLLAPSIBLE_IF, - collapsible_match::COLLAPSIBLE_MATCH, - comparison_chain::COMPARISON_CHAIN, - copies::BRANCHES_SHARING_CODE, - copies::IFS_SAME_COND, - copies::IF_SAME_THEN_ELSE, - copies::SAME_FUNCTIONS_IN_IF_CONDITION, - copy_iterator::COPY_ITERATOR, - create_dir::CREATE_DIR, - dbg_macro::DBG_MACRO, - default::DEFAULT_TRAIT_ACCESS, - default::FIELD_REASSIGN_WITH_DEFAULT, - default_numeric_fallback::DEFAULT_NUMERIC_FALLBACK, - dereference::EXPLICIT_DEREF_METHODS, - derive::DERIVE_HASH_XOR_EQ, - derive::DERIVE_ORD_XOR_PARTIAL_ORD, - derive::EXPL_IMPL_CLONE_ON_COPY, - derive::UNSAFE_DERIVE_DESERIALIZE, - disallowed_method::DISALLOWED_METHOD, - disallowed_script_idents::DISALLOWED_SCRIPT_IDENTS, - disallowed_type::DISALLOWED_TYPE, - doc::DOC_MARKDOWN, - doc::MISSING_ERRORS_DOC, - doc::MISSING_PANICS_DOC, - doc::MISSING_SAFETY_DOC, - doc::NEEDLESS_DOCTEST_MAIN, - double_comparison::DOUBLE_COMPARISONS, - double_parens::DOUBLE_PARENS, - drop_forget_ref::DROP_COPY, - drop_forget_ref::DROP_REF, - drop_forget_ref::FORGET_COPY, - drop_forget_ref::FORGET_REF, - duration_subsec::DURATION_SUBSEC, - else_if_without_else::ELSE_IF_WITHOUT_ELSE, - empty_enum::EMPTY_ENUM, - entry::MAP_ENTRY, - enum_clike::ENUM_CLIKE_UNPORTABLE_VARIANT, - enum_variants::ENUM_VARIANT_NAMES, - enum_variants::MODULE_INCEPTION, - enum_variants::MODULE_NAME_REPETITIONS, - eq_op::EQ_OP, - eq_op::OP_REF, - erasing_op::ERASING_OP, - escape::BOXED_LOCAL, - eta_reduction::REDUNDANT_CLOSURE, - eta_reduction::REDUNDANT_CLOSURE_FOR_METHOD_CALLS, - eval_order_dependence::DIVERGING_SUB_EXPRESSION, - eval_order_dependence::EVAL_ORDER_DEPENDENCE, - excessive_bools::FN_PARAMS_EXCESSIVE_BOOLS, - excessive_bools::STRUCT_EXCESSIVE_BOOLS, - exhaustive_items::EXHAUSTIVE_ENUMS, - exhaustive_items::EXHAUSTIVE_STRUCTS, - exit::EXIT, - explicit_write::EXPLICIT_WRITE, - fallible_impl_from::FALLIBLE_IMPL_FROM, - float_equality_without_abs::FLOAT_EQUALITY_WITHOUT_ABS, - float_literal::EXCESSIVE_PRECISION, - float_literal::LOSSY_FLOAT_LITERAL, - floating_point_arithmetic::IMPRECISE_FLOPS, - floating_point_arithmetic::SUBOPTIMAL_FLOPS, - format::USELESS_FORMAT, - formatting::POSSIBLE_MISSING_COMMA, - formatting::SUSPICIOUS_ASSIGNMENT_FORMATTING, - formatting::SUSPICIOUS_ELSE_FORMATTING, - formatting::SUSPICIOUS_UNARY_OP_FORMATTING, - from_over_into::FROM_OVER_INTO, - from_str_radix_10::FROM_STR_RADIX_10, - functions::DOUBLE_MUST_USE, - functions::MUST_USE_CANDIDATE, - functions::MUST_USE_UNIT, - functions::NOT_UNSAFE_PTR_ARG_DEREF, - functions::RESULT_UNIT_ERR, - functions::TOO_MANY_ARGUMENTS, - functions::TOO_MANY_LINES, - future_not_send::FUTURE_NOT_SEND, - get_last_with_len::GET_LAST_WITH_LEN, - identity_op::IDENTITY_OP, - if_let_mutex::IF_LET_MUTEX, - if_let_some_result::IF_LET_SOME_RESULT, - if_not_else::IF_NOT_ELSE, - if_then_some_else_none::IF_THEN_SOME_ELSE_NONE, - implicit_hasher::IMPLICIT_HASHER, - implicit_return::IMPLICIT_RETURN, - implicit_saturating_sub::IMPLICIT_SATURATING_SUB, - inconsistent_struct_constructor::INCONSISTENT_STRUCT_CONSTRUCTOR, - indexing_slicing::INDEXING_SLICING, - indexing_slicing::OUT_OF_BOUNDS_INDEXING, - infinite_iter::INFINITE_ITER, - infinite_iter::MAYBE_INFINITE_ITER, - inherent_impl::MULTIPLE_INHERENT_IMPL, - inherent_to_string::INHERENT_TO_STRING, - inherent_to_string::INHERENT_TO_STRING_SHADOW_DISPLAY, - inline_fn_without_body::INLINE_FN_WITHOUT_BODY, - int_plus_one::INT_PLUS_ONE, - integer_division::INTEGER_DIVISION, - invalid_upcast_comparisons::INVALID_UPCAST_COMPARISONS, - items_after_statements::ITEMS_AFTER_STATEMENTS, - large_const_arrays::LARGE_CONST_ARRAYS, - large_enum_variant::LARGE_ENUM_VARIANT, - large_stack_arrays::LARGE_STACK_ARRAYS, - len_zero::COMPARISON_TO_EMPTY, - len_zero::LEN_WITHOUT_IS_EMPTY, - len_zero::LEN_ZERO, - let_if_seq::USELESS_LET_IF_SEQ, - let_underscore::LET_UNDERSCORE_DROP, - let_underscore::LET_UNDERSCORE_LOCK, - let_underscore::LET_UNDERSCORE_MUST_USE, - lifetimes::EXTRA_UNUSED_LIFETIMES, - lifetimes::NEEDLESS_LIFETIMES, - literal_representation::DECIMAL_LITERAL_REPRESENTATION, - literal_representation::INCONSISTENT_DIGIT_GROUPING, - literal_representation::LARGE_DIGIT_GROUPS, - literal_representation::MISTYPED_LITERAL_SUFFIXES, - literal_representation::UNREADABLE_LITERAL, - literal_representation::UNUSUAL_BYTE_GROUPINGS, - loops::EMPTY_LOOP, - loops::EXPLICIT_COUNTER_LOOP, - loops::EXPLICIT_INTO_ITER_LOOP, - loops::EXPLICIT_ITER_LOOP, - loops::FOR_KV_MAP, - loops::FOR_LOOPS_OVER_FALLIBLES, - loops::ITER_NEXT_LOOP, - loops::MANUAL_FLATTEN, - loops::MANUAL_MEMCPY, - loops::MUT_RANGE_BOUND, - loops::NEEDLESS_COLLECT, - loops::NEEDLESS_RANGE_LOOP, - loops::NEVER_LOOP, - loops::SAME_ITEM_PUSH, - loops::SINGLE_ELEMENT_LOOP, - loops::WHILE_IMMUTABLE_CONDITION, - loops::WHILE_LET_LOOP, - loops::WHILE_LET_ON_ITERATOR, - macro_use::MACRO_USE_IMPORTS, - main_recursion::MAIN_RECURSION, - manual_async_fn::MANUAL_ASYNC_FN, - manual_map::MANUAL_MAP, - manual_non_exhaustive::MANUAL_NON_EXHAUSTIVE, - manual_ok_or::MANUAL_OK_OR, - manual_strip::MANUAL_STRIP, - manual_unwrap_or::MANUAL_UNWRAP_OR, - map_clone::MAP_CLONE, - map_err_ignore::MAP_ERR_IGNORE, - map_unit_fn::OPTION_MAP_UNIT_FN, - map_unit_fn::RESULT_MAP_UNIT_FN, - match_on_vec_items::MATCH_ON_VEC_ITEMS, - matches::INFALLIBLE_DESTRUCTURING_MATCH, - matches::MATCH_AS_REF, - matches::MATCH_BOOL, - matches::MATCH_LIKE_MATCHES_MACRO, - matches::MATCH_OVERLAPPING_ARM, - matches::MATCH_REF_PATS, - matches::MATCH_SAME_ARMS, - matches::MATCH_SINGLE_BINDING, - matches::MATCH_WILDCARD_FOR_SINGLE_VARIANTS, - matches::MATCH_WILD_ERR_ARM, - matches::REDUNDANT_PATTERN_MATCHING, - matches::REST_PAT_IN_FULLY_BOUND_STRUCTS, - matches::SINGLE_MATCH, - matches::SINGLE_MATCH_ELSE, - matches::WILDCARD_ENUM_MATCH_ARM, - matches::WILDCARD_IN_OR_PATTERNS, - mem_discriminant::MEM_DISCRIMINANT_NON_ENUM, - mem_forget::MEM_FORGET, - mem_replace::MEM_REPLACE_OPTION_WITH_NONE, - mem_replace::MEM_REPLACE_WITH_DEFAULT, - mem_replace::MEM_REPLACE_WITH_UNINIT, - methods::BIND_INSTEAD_OF_MAP, - methods::BYTES_NTH, - methods::CHARS_LAST_CMP, - methods::CHARS_NEXT_CMP, - methods::CLONED_INSTEAD_OF_COPIED, - methods::CLONE_DOUBLE_REF, - methods::CLONE_ON_COPY, - methods::CLONE_ON_REF_PTR, - methods::EXPECT_FUN_CALL, - methods::EXPECT_USED, - methods::EXTEND_WITH_DRAIN, - methods::FILETYPE_IS_FILE, - methods::FILTER_MAP_IDENTITY, - methods::FILTER_MAP_NEXT, - methods::FILTER_NEXT, - methods::FLAT_MAP_IDENTITY, - methods::FLAT_MAP_OPTION, - methods::FROM_ITER_INSTEAD_OF_COLLECT, - methods::GET_UNWRAP, - methods::IMPLICIT_CLONE, - methods::INEFFICIENT_TO_STRING, - methods::INSPECT_FOR_EACH, - methods::INTO_ITER_ON_REF, - methods::ITERATOR_STEP_BY_ZERO, - methods::ITER_CLONED_COLLECT, - methods::ITER_COUNT, - methods::ITER_NEXT_SLICE, - methods::ITER_NTH, - methods::ITER_NTH_ZERO, - methods::ITER_SKIP_NEXT, - methods::MANUAL_FILTER_MAP, - methods::MANUAL_FIND_MAP, - methods::MANUAL_SATURATING_ARITHMETIC, - methods::MANUAL_STR_REPEAT, - methods::MAP_COLLECT_RESULT_UNIT, - methods::MAP_FLATTEN, - methods::MAP_IDENTITY, - methods::MAP_UNWRAP_OR, - methods::NEW_RET_NO_SELF, - methods::OK_EXPECT, - methods::OPTION_AS_REF_DEREF, - methods::OPTION_FILTER_MAP, - methods::OPTION_MAP_OR_NONE, - methods::OR_FUN_CALL, - methods::RESULT_MAP_OR_INTO_OPTION, - methods::SEARCH_IS_SOME, - methods::SHOULD_IMPLEMENT_TRAIT, - methods::SINGLE_CHAR_ADD_STR, - methods::SINGLE_CHAR_PATTERN, - methods::SKIP_WHILE_NEXT, - methods::STRING_EXTEND_CHARS, - methods::SUSPICIOUS_MAP, - methods::SUSPICIOUS_SPLITN, - methods::UNINIT_ASSUMED_INIT, - methods::UNNECESSARY_FILTER_MAP, - methods::UNNECESSARY_FOLD, - methods::UNNECESSARY_LAZY_EVALUATIONS, - methods::UNWRAP_OR_ELSE_DEFAULT, - methods::UNWRAP_USED, - methods::USELESS_ASREF, - methods::WRONG_SELF_CONVENTION, - methods::ZST_OFFSET, - minmax::MIN_MAX, - misc::CMP_NAN, - misc::CMP_OWNED, - misc::FLOAT_CMP, - misc::FLOAT_CMP_CONST, - misc::MODULO_ONE, - misc::SHORT_CIRCUIT_STATEMENT, - misc::TOPLEVEL_REF_ARG, - misc::USED_UNDERSCORE_BINDING, - misc::ZERO_PTR, - misc_early::BUILTIN_TYPE_SHADOW, - misc_early::DOUBLE_NEG, - misc_early::DUPLICATE_UNDERSCORE_ARGUMENT, - misc_early::MIXED_CASE_HEX_LITERALS, - misc_early::REDUNDANT_PATTERN, - misc_early::UNNEEDED_FIELD_PATTERN, - misc_early::UNNEEDED_WILDCARD_PATTERN, - misc_early::UNSEPARATED_LITERAL_SUFFIX, - misc_early::ZERO_PREFIXED_LITERAL, - missing_const_for_fn::MISSING_CONST_FOR_FN, - missing_doc::MISSING_DOCS_IN_PRIVATE_ITEMS, - missing_enforced_import_rename::MISSING_ENFORCED_IMPORT_RENAMES, - missing_inline::MISSING_INLINE_IN_PUBLIC_ITEMS, - modulo_arithmetic::MODULO_ARITHMETIC, - multiple_crate_versions::MULTIPLE_CRATE_VERSIONS, - mut_key::MUTABLE_KEY_TYPE, - mut_mut::MUT_MUT, - mut_mutex_lock::MUT_MUTEX_LOCK, - mut_reference::UNNECESSARY_MUT_PASSED, - mutable_debug_assertion::DEBUG_ASSERT_WITH_MUT_CALL, - mutex_atomic::MUTEX_ATOMIC, - mutex_atomic::MUTEX_INTEGER, - needless_arbitrary_self_type::NEEDLESS_ARBITRARY_SELF_TYPE, - needless_bitwise_bool::NEEDLESS_BITWISE_BOOL, - needless_bool::BOOL_COMPARISON, - needless_bool::NEEDLESS_BOOL, - needless_borrow::NEEDLESS_BORROW, - needless_borrow::REF_BINDING_TO_REFERENCE, - needless_borrowed_ref::NEEDLESS_BORROWED_REFERENCE, - needless_continue::NEEDLESS_CONTINUE, - needless_for_each::NEEDLESS_FOR_EACH, - needless_pass_by_value::NEEDLESS_PASS_BY_VALUE, - needless_question_mark::NEEDLESS_QUESTION_MARK, - needless_update::NEEDLESS_UPDATE, - neg_cmp_op_on_partial_ord::NEG_CMP_OP_ON_PARTIAL_ORD, - neg_multiply::NEG_MULTIPLY, - new_without_default::NEW_WITHOUT_DEFAULT, - no_effect::NO_EFFECT, - no_effect::UNNECESSARY_OPERATION, - non_copy_const::BORROW_INTERIOR_MUTABLE_CONST, - non_copy_const::DECLARE_INTERIOR_MUTABLE_CONST, - non_expressive_names::JUST_UNDERSCORES_AND_DIGITS, - non_expressive_names::MANY_SINGLE_CHAR_NAMES, - non_expressive_names::SIMILAR_NAMES, - non_octal_unix_permissions::NON_OCTAL_UNIX_PERMISSIONS, - nonstandard_macro_braces::NONSTANDARD_MACRO_BRACES, - open_options::NONSENSICAL_OPEN_OPTIONS, - option_env_unwrap::OPTION_ENV_UNWRAP, - option_if_let_else::OPTION_IF_LET_ELSE, - overflow_check_conditional::OVERFLOW_CHECK_CONDITIONAL, - panic_in_result_fn::PANIC_IN_RESULT_FN, - panic_unimplemented::PANIC, - panic_unimplemented::TODO, - panic_unimplemented::UNIMPLEMENTED, - panic_unimplemented::UNREACHABLE, - partialeq_ne_impl::PARTIALEQ_NE_IMPL, - pass_by_ref_or_value::LARGE_TYPES_PASSED_BY_VALUE, - pass_by_ref_or_value::TRIVIALLY_COPY_PASS_BY_REF, - path_buf_push_overwrite::PATH_BUF_PUSH_OVERWRITE, - pattern_type_mismatch::PATTERN_TYPE_MISMATCH, - precedence::PRECEDENCE, - ptr::CMP_NULL, - ptr::INVALID_NULL_PTR_USAGE, - ptr::MUT_FROM_REF, - ptr::PTR_ARG, - ptr_eq::PTR_EQ, - ptr_offset_with_cast::PTR_OFFSET_WITH_CAST, - question_mark::QUESTION_MARK, - ranges::MANUAL_RANGE_CONTAINS, - ranges::RANGE_MINUS_ONE, - ranges::RANGE_PLUS_ONE, - ranges::RANGE_ZIP_WITH_LEN, - ranges::REVERSED_EMPTY_RANGES, - redundant_clone::REDUNDANT_CLONE, - redundant_closure_call::REDUNDANT_CLOSURE_CALL, - redundant_else::REDUNDANT_ELSE, - redundant_field_names::REDUNDANT_FIELD_NAMES, - redundant_pub_crate::REDUNDANT_PUB_CRATE, - redundant_slicing::REDUNDANT_SLICING, - redundant_static_lifetimes::REDUNDANT_STATIC_LIFETIMES, - ref_option_ref::REF_OPTION_REF, - reference::DEREF_ADDROF, - reference::REF_IN_DEREF, - regex::INVALID_REGEX, - regex::TRIVIAL_REGEX, - repeat_once::REPEAT_ONCE, - returns::LET_AND_RETURN, - returns::NEEDLESS_RETURN, - self_assignment::SELF_ASSIGNMENT, - self_named_constructors::SELF_NAMED_CONSTRUCTORS, - semicolon_if_nothing_returned::SEMICOLON_IF_NOTHING_RETURNED, - serde_api::SERDE_API_MISUSE, - shadow::SHADOW_REUSE, - shadow::SHADOW_SAME, - shadow::SHADOW_UNRELATED, - single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS, - size_of_in_element_count::SIZE_OF_IN_ELEMENT_COUNT, - slow_vector_initialization::SLOW_VECTOR_INITIALIZATION, - stable_sort_primitive::STABLE_SORT_PRIMITIVE, - strings::STRING_ADD, - strings::STRING_ADD_ASSIGN, - strings::STRING_FROM_UTF8_AS_BYTES, - strings::STRING_LIT_AS_BYTES, - strings::STRING_TO_STRING, - strings::STR_TO_STRING, - strlen_on_c_strings::STRLEN_ON_C_STRINGS, - suspicious_operation_groupings::SUSPICIOUS_OPERATION_GROUPINGS, - suspicious_trait_impl::SUSPICIOUS_ARITHMETIC_IMPL, - suspicious_trait_impl::SUSPICIOUS_OP_ASSIGN_IMPL, - swap::ALMOST_SWAPPED, - swap::MANUAL_SWAP, - tabs_in_doc_comments::TABS_IN_DOC_COMMENTS, - temporary_assignment::TEMPORARY_ASSIGNMENT, - to_digit_is_some::TO_DIGIT_IS_SOME, - to_string_in_display::TO_STRING_IN_DISPLAY, - trait_bounds::TRAIT_DUPLICATION_IN_BOUNDS, - trait_bounds::TYPE_REPETITION_IN_BOUNDS, - transmute::CROSSPOINTER_TRANSMUTE, - transmute::TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS, - transmute::TRANSMUTE_BYTES_TO_STR, - transmute::TRANSMUTE_FLOAT_TO_INT, - transmute::TRANSMUTE_INT_TO_BOOL, - transmute::TRANSMUTE_INT_TO_CHAR, - transmute::TRANSMUTE_INT_TO_FLOAT, - transmute::TRANSMUTE_PTR_TO_PTR, - transmute::TRANSMUTE_PTR_TO_REF, - transmute::UNSOUND_COLLECTION_TRANSMUTE, - transmute::USELESS_TRANSMUTE, - transmute::WRONG_TRANSMUTE, - transmuting_null::TRANSMUTING_NULL, - try_err::TRY_ERR, - types::BORROWED_BOX, - types::BOX_VEC, - types::LINKEDLIST, - types::OPTION_OPTION, - types::RC_BUFFER, - types::RC_MUTEX, - types::REDUNDANT_ALLOCATION, - types::TYPE_COMPLEXITY, - types::VEC_BOX, - undropped_manually_drops::UNDROPPED_MANUALLY_DROPS, - unicode::INVISIBLE_CHARACTERS, - unicode::NON_ASCII_LITERAL, - unicode::UNICODE_NOT_NFC, - unit_return_expecting_ord::UNIT_RETURN_EXPECTING_ORD, - unit_types::LET_UNIT_VALUE, - unit_types::UNIT_ARG, - unit_types::UNIT_CMP, - unnamed_address::FN_ADDRESS_COMPARISONS, - unnamed_address::VTABLE_ADDRESS_COMPARISONS, - unnecessary_self_imports::UNNECESSARY_SELF_IMPORTS, - unnecessary_sort_by::UNNECESSARY_SORT_BY, - unnecessary_wraps::UNNECESSARY_WRAPS, - unnested_or_patterns::UNNESTED_OR_PATTERNS, - unsafe_removed_from_name::UNSAFE_REMOVED_FROM_NAME, - unused_async::UNUSED_ASYNC, - unused_io_amount::UNUSED_IO_AMOUNT, - unused_self::UNUSED_SELF, - unused_unit::UNUSED_UNIT, - unwrap::PANICKING_UNWRAP, - unwrap::UNNECESSARY_UNWRAP, - unwrap_in_result::UNWRAP_IN_RESULT, - upper_case_acronyms::UPPER_CASE_ACRONYMS, - use_self::USE_SELF, - useless_conversion::USELESS_CONVERSION, - vec::USELESS_VEC, - vec_init_then_push::VEC_INIT_THEN_PUSH, - vec_resize_to_zero::VEC_RESIZE_TO_ZERO, - verbose_file_reads::VERBOSE_FILE_READS, - wildcard_dependencies::WILDCARD_DEPENDENCIES, - wildcard_imports::ENUM_GLOB_USE, - wildcard_imports::WILDCARD_IMPORTS, - write::PRINTLN_EMPTY_STRING, - write::PRINT_LITERAL, - write::PRINT_STDERR, - write::PRINT_STDOUT, - write::PRINT_WITH_NEWLINE, - write::USE_DEBUG, - write::WRITELN_EMPTY_STRING, - write::WRITE_LITERAL, - write::WRITE_WITH_NEWLINE, - zero_div_zero::ZERO_DIVIDED_BY_ZERO, - zero_sized_map_values::ZERO_SIZED_MAP_VALUES, - ]); - // end register lints, do not remove this comment, it’s used in `update_lints` - - store.register_group(true, "clippy::restriction", Some("clippy_restriction"), vec![ - LintId::of(arithmetic::FLOAT_ARITHMETIC), - LintId::of(arithmetic::INTEGER_ARITHMETIC), - LintId::of(as_conversions::AS_CONVERSIONS), - LintId::of(asm_syntax::INLINE_ASM_X86_ATT_SYNTAX), - LintId::of(asm_syntax::INLINE_ASM_X86_INTEL_SYNTAX), - LintId::of(create_dir::CREATE_DIR), - LintId::of(dbg_macro::DBG_MACRO), - LintId::of(default_numeric_fallback::DEFAULT_NUMERIC_FALLBACK), - LintId::of(disallowed_script_idents::DISALLOWED_SCRIPT_IDENTS), - LintId::of(else_if_without_else::ELSE_IF_WITHOUT_ELSE), - LintId::of(exhaustive_items::EXHAUSTIVE_ENUMS), - LintId::of(exhaustive_items::EXHAUSTIVE_STRUCTS), - LintId::of(exit::EXIT), - LintId::of(float_literal::LOSSY_FLOAT_LITERAL), - LintId::of(if_then_some_else_none::IF_THEN_SOME_ELSE_NONE), - LintId::of(implicit_return::IMPLICIT_RETURN), - LintId::of(indexing_slicing::INDEXING_SLICING), - LintId::of(inherent_impl::MULTIPLE_INHERENT_IMPL), - LintId::of(integer_division::INTEGER_DIVISION), - LintId::of(let_underscore::LET_UNDERSCORE_MUST_USE), - LintId::of(literal_representation::DECIMAL_LITERAL_REPRESENTATION), - LintId::of(map_err_ignore::MAP_ERR_IGNORE), - LintId::of(matches::REST_PAT_IN_FULLY_BOUND_STRUCTS), - LintId::of(matches::WILDCARD_ENUM_MATCH_ARM), - LintId::of(mem_forget::MEM_FORGET), - LintId::of(methods::CLONE_ON_REF_PTR), - LintId::of(methods::EXPECT_USED), - LintId::of(methods::FILETYPE_IS_FILE), - LintId::of(methods::GET_UNWRAP), - LintId::of(methods::UNWRAP_USED), - LintId::of(misc::FLOAT_CMP_CONST), - LintId::of(misc_early::UNNEEDED_FIELD_PATTERN), - LintId::of(missing_doc::MISSING_DOCS_IN_PRIVATE_ITEMS), - LintId::of(missing_enforced_import_rename::MISSING_ENFORCED_IMPORT_RENAMES), - LintId::of(missing_inline::MISSING_INLINE_IN_PUBLIC_ITEMS), - LintId::of(modulo_arithmetic::MODULO_ARITHMETIC), - LintId::of(panic_in_result_fn::PANIC_IN_RESULT_FN), - LintId::of(panic_unimplemented::PANIC), - LintId::of(panic_unimplemented::TODO), - LintId::of(panic_unimplemented::UNIMPLEMENTED), - LintId::of(panic_unimplemented::UNREACHABLE), - LintId::of(pattern_type_mismatch::PATTERN_TYPE_MISMATCH), - LintId::of(shadow::SHADOW_REUSE), - LintId::of(shadow::SHADOW_SAME), - LintId::of(strings::STRING_ADD), - LintId::of(strings::STRING_TO_STRING), - LintId::of(strings::STR_TO_STRING), - LintId::of(types::RC_BUFFER), - LintId::of(types::RC_MUTEX), - LintId::of(unnecessary_self_imports::UNNECESSARY_SELF_IMPORTS), - LintId::of(unwrap_in_result::UNWRAP_IN_RESULT), - LintId::of(verbose_file_reads::VERBOSE_FILE_READS), - LintId::of(write::PRINT_STDERR), - LintId::of(write::PRINT_STDOUT), - LintId::of(write::USE_DEBUG), - ]); - - store.register_group(true, "clippy::pedantic", Some("clippy_pedantic"), vec![ - LintId::of(attrs::INLINE_ALWAYS), - LintId::of(await_holding_invalid::AWAIT_HOLDING_LOCK), - LintId::of(await_holding_invalid::AWAIT_HOLDING_REFCELL_REF), - LintId::of(bit_mask::VERBOSE_BIT_MASK), - LintId::of(bytecount::NAIVE_BYTECOUNT), - LintId::of(case_sensitive_file_extension_comparisons::CASE_SENSITIVE_FILE_EXTENSION_COMPARISONS), - LintId::of(casts::CAST_LOSSLESS), - LintId::of(casts::CAST_POSSIBLE_TRUNCATION), - LintId::of(casts::CAST_POSSIBLE_WRAP), - LintId::of(casts::CAST_PRECISION_LOSS), - LintId::of(casts::CAST_PTR_ALIGNMENT), - LintId::of(casts::CAST_SIGN_LOSS), - LintId::of(casts::PTR_AS_PTR), - LintId::of(checked_conversions::CHECKED_CONVERSIONS), - LintId::of(copies::SAME_FUNCTIONS_IN_IF_CONDITION), - LintId::of(copy_iterator::COPY_ITERATOR), - LintId::of(default::DEFAULT_TRAIT_ACCESS), - LintId::of(dereference::EXPLICIT_DEREF_METHODS), - LintId::of(derive::EXPL_IMPL_CLONE_ON_COPY), - LintId::of(derive::UNSAFE_DERIVE_DESERIALIZE), - LintId::of(doc::DOC_MARKDOWN), - LintId::of(doc::MISSING_ERRORS_DOC), - LintId::of(doc::MISSING_PANICS_DOC), - LintId::of(empty_enum::EMPTY_ENUM), - LintId::of(enum_variants::MODULE_NAME_REPETITIONS), - LintId::of(eta_reduction::REDUNDANT_CLOSURE_FOR_METHOD_CALLS), - LintId::of(excessive_bools::FN_PARAMS_EXCESSIVE_BOOLS), - LintId::of(excessive_bools::STRUCT_EXCESSIVE_BOOLS), - LintId::of(functions::MUST_USE_CANDIDATE), - LintId::of(functions::TOO_MANY_LINES), - LintId::of(if_not_else::IF_NOT_ELSE), - LintId::of(implicit_hasher::IMPLICIT_HASHER), - LintId::of(implicit_saturating_sub::IMPLICIT_SATURATING_SUB), - LintId::of(inconsistent_struct_constructor::INCONSISTENT_STRUCT_CONSTRUCTOR), - LintId::of(infinite_iter::MAYBE_INFINITE_ITER), - LintId::of(invalid_upcast_comparisons::INVALID_UPCAST_COMPARISONS), - LintId::of(items_after_statements::ITEMS_AFTER_STATEMENTS), - LintId::of(large_stack_arrays::LARGE_STACK_ARRAYS), - LintId::of(let_underscore::LET_UNDERSCORE_DROP), - LintId::of(literal_representation::LARGE_DIGIT_GROUPS), - LintId::of(literal_representation::UNREADABLE_LITERAL), - LintId::of(loops::EXPLICIT_INTO_ITER_LOOP), - LintId::of(loops::EXPLICIT_ITER_LOOP), - LintId::of(macro_use::MACRO_USE_IMPORTS), - LintId::of(manual_ok_or::MANUAL_OK_OR), - LintId::of(match_on_vec_items::MATCH_ON_VEC_ITEMS), - LintId::of(matches::MATCH_BOOL), - LintId::of(matches::MATCH_SAME_ARMS), - LintId::of(matches::MATCH_WILDCARD_FOR_SINGLE_VARIANTS), - LintId::of(matches::MATCH_WILD_ERR_ARM), - LintId::of(matches::SINGLE_MATCH_ELSE), - LintId::of(methods::CLONED_INSTEAD_OF_COPIED), - LintId::of(methods::FILTER_MAP_NEXT), - LintId::of(methods::FLAT_MAP_OPTION), - LintId::of(methods::FROM_ITER_INSTEAD_OF_COLLECT), - LintId::of(methods::IMPLICIT_CLONE), - LintId::of(methods::INEFFICIENT_TO_STRING), - LintId::of(methods::MAP_FLATTEN), - LintId::of(methods::MAP_UNWRAP_OR), - LintId::of(misc::USED_UNDERSCORE_BINDING), - LintId::of(misc_early::UNSEPARATED_LITERAL_SUFFIX), - LintId::of(mut_mut::MUT_MUT), - LintId::of(needless_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(non_expressive_names::SIMILAR_NAMES), - LintId::of(option_if_let_else::OPTION_IF_LET_ELSE), - LintId::of(pass_by_ref_or_value::LARGE_TYPES_PASSED_BY_VALUE), - LintId::of(pass_by_ref_or_value::TRIVIALLY_COPY_PASS_BY_REF), - LintId::of(ranges::RANGE_MINUS_ONE), - LintId::of(ranges::RANGE_PLUS_ONE), - LintId::of(redundant_else::REDUNDANT_ELSE), - LintId::of(ref_option_ref::REF_OPTION_REF), - LintId::of(semicolon_if_nothing_returned::SEMICOLON_IF_NOTHING_RETURNED), - LintId::of(shadow::SHADOW_UNRELATED), - LintId::of(strings::STRING_ADD_ASSIGN), - LintId::of(trait_bounds::TRAIT_DUPLICATION_IN_BOUNDS), - LintId::of(trait_bounds::TYPE_REPETITION_IN_BOUNDS), - LintId::of(transmute::TRANSMUTE_PTR_TO_PTR), - LintId::of(types::LINKEDLIST), - LintId::of(types::OPTION_OPTION), - LintId::of(unicode::NON_ASCII_LITERAL), - LintId::of(unicode::UNICODE_NOT_NFC), - LintId::of(unit_types::LET_UNIT_VALUE), - LintId::of(unnecessary_wraps::UNNECESSARY_WRAPS), - LintId::of(unnested_or_patterns::UNNESTED_OR_PATTERNS), - LintId::of(unused_async::UNUSED_ASYNC), - LintId::of(unused_self::UNUSED_SELF), - LintId::of(wildcard_imports::ENUM_GLOB_USE), - LintId::of(wildcard_imports::WILDCARD_IMPORTS), - LintId::of(zero_sized_map_values::ZERO_SIZED_MAP_VALUES), - ]); + include!("lib.register_lints.rs"); + include!("lib.register_restriction.rs"); + include!("lib.register_pedantic.rs"); #[cfg(feature = "internal-lints")] - store.register_group(true, "clippy::internal", Some("clippy_internal"), vec![ - LintId::of(utils::internal_lints::CLIPPY_LINTS_INTERNAL), - LintId::of(utils::internal_lints::COLLAPSIBLE_SPAN_LINT_CALLS), - LintId::of(utils::internal_lints::COMPILER_LINT_FUNCTIONS), - LintId::of(utils::internal_lints::DEFAULT_LINT), - LintId::of(utils::internal_lints::IF_CHAIN_STYLE), - LintId::of(utils::internal_lints::INTERNING_DEFINED_SYMBOL), - LintId::of(utils::internal_lints::INVALID_PATHS), - LintId::of(utils::internal_lints::LINT_WITHOUT_LINT_PASS), - LintId::of(utils::internal_lints::MATCH_TYPE_ON_DIAGNOSTIC_ITEM), - LintId::of(utils::internal_lints::OUTER_EXPN_EXPN_DATA), - LintId::of(utils::internal_lints::PRODUCE_ICE), - LintId::of(utils::internal_lints::UNNECESSARY_SYMBOL_STR), - ]); + include!("lib.register_internal.rs"); - store.register_group(true, "clippy::all", Some("clippy"), vec![ - LintId::of(absurd_extreme_comparisons::ABSURD_EXTREME_COMPARISONS), - LintId::of(approx_const::APPROX_CONSTANT), - LintId::of(assertions_on_constants::ASSERTIONS_ON_CONSTANTS), - LintId::of(assign_ops::ASSIGN_OP_PATTERN), - LintId::of(assign_ops::MISREFACTORED_ASSIGN_OP), - LintId::of(async_yields_async::ASYNC_YIELDS_ASYNC), - LintId::of(attrs::BLANKET_CLIPPY_RESTRICTION_LINTS), - LintId::of(attrs::DEPRECATED_CFG_ATTR), - LintId::of(attrs::DEPRECATED_SEMVER), - LintId::of(attrs::MISMATCHED_TARGET_OS), - LintId::of(attrs::USELESS_ATTRIBUTE), - LintId::of(bit_mask::BAD_BIT_MASK), - LintId::of(bit_mask::INEFFECTIVE_BIT_MASK), - LintId::of(blacklisted_name::BLACKLISTED_NAME), - LintId::of(blocks_in_if_conditions::BLOCKS_IN_IF_CONDITIONS), - LintId::of(bool_assert_comparison::BOOL_ASSERT_COMPARISON), - LintId::of(booleans::LOGIC_BUG), - LintId::of(booleans::NONMINIMAL_BOOL), - LintId::of(casts::CAST_REF_TO_MUT), - LintId::of(casts::CHAR_LIT_AS_U8), - LintId::of(casts::FN_TO_NUMERIC_CAST), - LintId::of(casts::FN_TO_NUMERIC_CAST_WITH_TRUNCATION), - LintId::of(casts::UNNECESSARY_CAST), - LintId::of(collapsible_if::COLLAPSIBLE_ELSE_IF), - LintId::of(collapsible_if::COLLAPSIBLE_IF), - LintId::of(collapsible_match::COLLAPSIBLE_MATCH), - LintId::of(comparison_chain::COMPARISON_CHAIN), - LintId::of(copies::BRANCHES_SHARING_CODE), - LintId::of(copies::IFS_SAME_COND), - LintId::of(copies::IF_SAME_THEN_ELSE), - LintId::of(default::FIELD_REASSIGN_WITH_DEFAULT), - LintId::of(derive::DERIVE_HASH_XOR_EQ), - LintId::of(derive::DERIVE_ORD_XOR_PARTIAL_ORD), - LintId::of(doc::MISSING_SAFETY_DOC), - LintId::of(doc::NEEDLESS_DOCTEST_MAIN), - LintId::of(double_comparison::DOUBLE_COMPARISONS), - LintId::of(double_parens::DOUBLE_PARENS), - LintId::of(drop_forget_ref::DROP_COPY), - LintId::of(drop_forget_ref::DROP_REF), - LintId::of(drop_forget_ref::FORGET_COPY), - LintId::of(drop_forget_ref::FORGET_REF), - LintId::of(duration_subsec::DURATION_SUBSEC), - LintId::of(entry::MAP_ENTRY), - LintId::of(enum_clike::ENUM_CLIKE_UNPORTABLE_VARIANT), - LintId::of(enum_variants::ENUM_VARIANT_NAMES), - LintId::of(enum_variants::MODULE_INCEPTION), - LintId::of(eq_op::EQ_OP), - LintId::of(eq_op::OP_REF), - LintId::of(erasing_op::ERASING_OP), - LintId::of(escape::BOXED_LOCAL), - LintId::of(eta_reduction::REDUNDANT_CLOSURE), - LintId::of(eval_order_dependence::DIVERGING_SUB_EXPRESSION), - LintId::of(eval_order_dependence::EVAL_ORDER_DEPENDENCE), - LintId::of(explicit_write::EXPLICIT_WRITE), - LintId::of(float_equality_without_abs::FLOAT_EQUALITY_WITHOUT_ABS), - LintId::of(float_literal::EXCESSIVE_PRECISION), - LintId::of(format::USELESS_FORMAT), - LintId::of(formatting::POSSIBLE_MISSING_COMMA), - LintId::of(formatting::SUSPICIOUS_ASSIGNMENT_FORMATTING), - LintId::of(formatting::SUSPICIOUS_ELSE_FORMATTING), - LintId::of(formatting::SUSPICIOUS_UNARY_OP_FORMATTING), - LintId::of(from_over_into::FROM_OVER_INTO), - LintId::of(from_str_radix_10::FROM_STR_RADIX_10), - LintId::of(functions::DOUBLE_MUST_USE), - LintId::of(functions::MUST_USE_UNIT), - LintId::of(functions::NOT_UNSAFE_PTR_ARG_DEREF), - LintId::of(functions::RESULT_UNIT_ERR), - LintId::of(functions::TOO_MANY_ARGUMENTS), - LintId::of(get_last_with_len::GET_LAST_WITH_LEN), - LintId::of(identity_op::IDENTITY_OP), - LintId::of(if_let_mutex::IF_LET_MUTEX), - LintId::of(if_let_some_result::IF_LET_SOME_RESULT), - LintId::of(indexing_slicing::OUT_OF_BOUNDS_INDEXING), - LintId::of(infinite_iter::INFINITE_ITER), - LintId::of(inherent_to_string::INHERENT_TO_STRING), - LintId::of(inherent_to_string::INHERENT_TO_STRING_SHADOW_DISPLAY), - LintId::of(inline_fn_without_body::INLINE_FN_WITHOUT_BODY), - LintId::of(int_plus_one::INT_PLUS_ONE), - LintId::of(large_const_arrays::LARGE_CONST_ARRAYS), - LintId::of(large_enum_variant::LARGE_ENUM_VARIANT), - LintId::of(len_zero::COMPARISON_TO_EMPTY), - LintId::of(len_zero::LEN_WITHOUT_IS_EMPTY), - LintId::of(len_zero::LEN_ZERO), - LintId::of(let_underscore::LET_UNDERSCORE_LOCK), - LintId::of(lifetimes::EXTRA_UNUSED_LIFETIMES), - LintId::of(lifetimes::NEEDLESS_LIFETIMES), - LintId::of(literal_representation::INCONSISTENT_DIGIT_GROUPING), - LintId::of(literal_representation::MISTYPED_LITERAL_SUFFIXES), - LintId::of(literal_representation::UNUSUAL_BYTE_GROUPINGS), - LintId::of(loops::EMPTY_LOOP), - LintId::of(loops::EXPLICIT_COUNTER_LOOP), - LintId::of(loops::FOR_KV_MAP), - LintId::of(loops::FOR_LOOPS_OVER_FALLIBLES), - LintId::of(loops::ITER_NEXT_LOOP), - LintId::of(loops::MANUAL_FLATTEN), - LintId::of(loops::MANUAL_MEMCPY), - LintId::of(loops::MUT_RANGE_BOUND), - LintId::of(loops::NEEDLESS_COLLECT), - LintId::of(loops::NEEDLESS_RANGE_LOOP), - LintId::of(loops::NEVER_LOOP), - LintId::of(loops::SAME_ITEM_PUSH), - LintId::of(loops::SINGLE_ELEMENT_LOOP), - LintId::of(loops::WHILE_IMMUTABLE_CONDITION), - LintId::of(loops::WHILE_LET_LOOP), - LintId::of(loops::WHILE_LET_ON_ITERATOR), - LintId::of(main_recursion::MAIN_RECURSION), - LintId::of(manual_async_fn::MANUAL_ASYNC_FN), - LintId::of(manual_map::MANUAL_MAP), - LintId::of(manual_non_exhaustive::MANUAL_NON_EXHAUSTIVE), - LintId::of(manual_strip::MANUAL_STRIP), - LintId::of(manual_unwrap_or::MANUAL_UNWRAP_OR), - LintId::of(map_clone::MAP_CLONE), - LintId::of(map_unit_fn::OPTION_MAP_UNIT_FN), - LintId::of(map_unit_fn::RESULT_MAP_UNIT_FN), - LintId::of(matches::INFALLIBLE_DESTRUCTURING_MATCH), - LintId::of(matches::MATCH_AS_REF), - LintId::of(matches::MATCH_LIKE_MATCHES_MACRO), - LintId::of(matches::MATCH_OVERLAPPING_ARM), - LintId::of(matches::MATCH_REF_PATS), - LintId::of(matches::MATCH_SINGLE_BINDING), - LintId::of(matches::REDUNDANT_PATTERN_MATCHING), - LintId::of(matches::SINGLE_MATCH), - LintId::of(matches::WILDCARD_IN_OR_PATTERNS), - LintId::of(mem_discriminant::MEM_DISCRIMINANT_NON_ENUM), - LintId::of(mem_replace::MEM_REPLACE_OPTION_WITH_NONE), - LintId::of(mem_replace::MEM_REPLACE_WITH_DEFAULT), - LintId::of(mem_replace::MEM_REPLACE_WITH_UNINIT), - LintId::of(methods::BIND_INSTEAD_OF_MAP), - LintId::of(methods::BYTES_NTH), - LintId::of(methods::CHARS_LAST_CMP), - LintId::of(methods::CHARS_NEXT_CMP), - LintId::of(methods::CLONE_DOUBLE_REF), - LintId::of(methods::CLONE_ON_COPY), - LintId::of(methods::EXPECT_FUN_CALL), - LintId::of(methods::EXTEND_WITH_DRAIN), - LintId::of(methods::FILTER_MAP_IDENTITY), - LintId::of(methods::FILTER_NEXT), - LintId::of(methods::FLAT_MAP_IDENTITY), - LintId::of(methods::INSPECT_FOR_EACH), - LintId::of(methods::INTO_ITER_ON_REF), - LintId::of(methods::ITERATOR_STEP_BY_ZERO), - LintId::of(methods::ITER_CLONED_COLLECT), - LintId::of(methods::ITER_COUNT), - LintId::of(methods::ITER_NEXT_SLICE), - LintId::of(methods::ITER_NTH), - LintId::of(methods::ITER_NTH_ZERO), - LintId::of(methods::ITER_SKIP_NEXT), - LintId::of(methods::MANUAL_FILTER_MAP), - LintId::of(methods::MANUAL_FIND_MAP), - LintId::of(methods::MANUAL_SATURATING_ARITHMETIC), - LintId::of(methods::MANUAL_STR_REPEAT), - LintId::of(methods::MAP_COLLECT_RESULT_UNIT), - LintId::of(methods::MAP_IDENTITY), - LintId::of(methods::NEW_RET_NO_SELF), - LintId::of(methods::OK_EXPECT), - LintId::of(methods::OPTION_AS_REF_DEREF), - LintId::of(methods::OPTION_FILTER_MAP), - LintId::of(methods::OPTION_MAP_OR_NONE), - LintId::of(methods::OR_FUN_CALL), - LintId::of(methods::RESULT_MAP_OR_INTO_OPTION), - LintId::of(methods::SEARCH_IS_SOME), - LintId::of(methods::SHOULD_IMPLEMENT_TRAIT), - LintId::of(methods::SINGLE_CHAR_ADD_STR), - LintId::of(methods::SINGLE_CHAR_PATTERN), - LintId::of(methods::SKIP_WHILE_NEXT), - LintId::of(methods::STRING_EXTEND_CHARS), - LintId::of(methods::SUSPICIOUS_MAP), - LintId::of(methods::SUSPICIOUS_SPLITN), - LintId::of(methods::UNINIT_ASSUMED_INIT), - LintId::of(methods::UNNECESSARY_FILTER_MAP), - LintId::of(methods::UNNECESSARY_FOLD), - LintId::of(methods::UNNECESSARY_LAZY_EVALUATIONS), - LintId::of(methods::UNWRAP_OR_ELSE_DEFAULT), - LintId::of(methods::USELESS_ASREF), - LintId::of(methods::WRONG_SELF_CONVENTION), - LintId::of(methods::ZST_OFFSET), - LintId::of(minmax::MIN_MAX), - LintId::of(misc::CMP_NAN), - LintId::of(misc::CMP_OWNED), - LintId::of(misc::FLOAT_CMP), - LintId::of(misc::MODULO_ONE), - LintId::of(misc::SHORT_CIRCUIT_STATEMENT), - LintId::of(misc::TOPLEVEL_REF_ARG), - LintId::of(misc::ZERO_PTR), - LintId::of(misc_early::BUILTIN_TYPE_SHADOW), - LintId::of(misc_early::DOUBLE_NEG), - LintId::of(misc_early::DUPLICATE_UNDERSCORE_ARGUMENT), - LintId::of(misc_early::MIXED_CASE_HEX_LITERALS), - LintId::of(misc_early::REDUNDANT_PATTERN), - LintId::of(misc_early::UNNEEDED_WILDCARD_PATTERN), - LintId::of(misc_early::ZERO_PREFIXED_LITERAL), - LintId::of(mut_key::MUTABLE_KEY_TYPE), - LintId::of(mut_mutex_lock::MUT_MUTEX_LOCK), - LintId::of(mut_reference::UNNECESSARY_MUT_PASSED), - LintId::of(mutex_atomic::MUTEX_ATOMIC), - LintId::of(needless_arbitrary_self_type::NEEDLESS_ARBITRARY_SELF_TYPE), - LintId::of(needless_bool::BOOL_COMPARISON), - LintId::of(needless_bool::NEEDLESS_BOOL), - LintId::of(needless_borrow::NEEDLESS_BORROW), - LintId::of(needless_borrowed_ref::NEEDLESS_BORROWED_REFERENCE), - LintId::of(needless_question_mark::NEEDLESS_QUESTION_MARK), - LintId::of(needless_update::NEEDLESS_UPDATE), - LintId::of(neg_cmp_op_on_partial_ord::NEG_CMP_OP_ON_PARTIAL_ORD), - LintId::of(neg_multiply::NEG_MULTIPLY), - LintId::of(new_without_default::NEW_WITHOUT_DEFAULT), - LintId::of(no_effect::NO_EFFECT), - LintId::of(no_effect::UNNECESSARY_OPERATION), - LintId::of(non_copy_const::BORROW_INTERIOR_MUTABLE_CONST), - LintId::of(non_copy_const::DECLARE_INTERIOR_MUTABLE_CONST), - LintId::of(non_expressive_names::JUST_UNDERSCORES_AND_DIGITS), - LintId::of(non_expressive_names::MANY_SINGLE_CHAR_NAMES), - LintId::of(non_octal_unix_permissions::NON_OCTAL_UNIX_PERMISSIONS), - LintId::of(open_options::NONSENSICAL_OPEN_OPTIONS), - LintId::of(option_env_unwrap::OPTION_ENV_UNWRAP), - LintId::of(overflow_check_conditional::OVERFLOW_CHECK_CONDITIONAL), - LintId::of(partialeq_ne_impl::PARTIALEQ_NE_IMPL), - LintId::of(precedence::PRECEDENCE), - LintId::of(ptr::CMP_NULL), - LintId::of(ptr::INVALID_NULL_PTR_USAGE), - LintId::of(ptr::MUT_FROM_REF), - LintId::of(ptr::PTR_ARG), - LintId::of(ptr_eq::PTR_EQ), - LintId::of(ptr_offset_with_cast::PTR_OFFSET_WITH_CAST), - LintId::of(question_mark::QUESTION_MARK), - LintId::of(ranges::MANUAL_RANGE_CONTAINS), - LintId::of(ranges::RANGE_ZIP_WITH_LEN), - LintId::of(ranges::REVERSED_EMPTY_RANGES), - LintId::of(redundant_clone::REDUNDANT_CLONE), - LintId::of(redundant_closure_call::REDUNDANT_CLOSURE_CALL), - LintId::of(redundant_field_names::REDUNDANT_FIELD_NAMES), - LintId::of(redundant_slicing::REDUNDANT_SLICING), - LintId::of(redundant_static_lifetimes::REDUNDANT_STATIC_LIFETIMES), - LintId::of(reference::DEREF_ADDROF), - LintId::of(reference::REF_IN_DEREF), - LintId::of(regex::INVALID_REGEX), - LintId::of(repeat_once::REPEAT_ONCE), - LintId::of(returns::LET_AND_RETURN), - LintId::of(returns::NEEDLESS_RETURN), - LintId::of(self_assignment::SELF_ASSIGNMENT), - LintId::of(self_named_constructors::SELF_NAMED_CONSTRUCTORS), - LintId::of(serde_api::SERDE_API_MISUSE), - LintId::of(single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS), - LintId::of(size_of_in_element_count::SIZE_OF_IN_ELEMENT_COUNT), - LintId::of(slow_vector_initialization::SLOW_VECTOR_INITIALIZATION), - LintId::of(stable_sort_primitive::STABLE_SORT_PRIMITIVE), - LintId::of(strings::STRING_FROM_UTF8_AS_BYTES), - LintId::of(strlen_on_c_strings::STRLEN_ON_C_STRINGS), - LintId::of(suspicious_trait_impl::SUSPICIOUS_ARITHMETIC_IMPL), - LintId::of(suspicious_trait_impl::SUSPICIOUS_OP_ASSIGN_IMPL), - LintId::of(swap::ALMOST_SWAPPED), - LintId::of(swap::MANUAL_SWAP), - LintId::of(tabs_in_doc_comments::TABS_IN_DOC_COMMENTS), - LintId::of(temporary_assignment::TEMPORARY_ASSIGNMENT), - LintId::of(to_digit_is_some::TO_DIGIT_IS_SOME), - LintId::of(to_string_in_display::TO_STRING_IN_DISPLAY), - LintId::of(transmute::CROSSPOINTER_TRANSMUTE), - LintId::of(transmute::TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS), - LintId::of(transmute::TRANSMUTE_BYTES_TO_STR), - LintId::of(transmute::TRANSMUTE_FLOAT_TO_INT), - LintId::of(transmute::TRANSMUTE_INT_TO_BOOL), - LintId::of(transmute::TRANSMUTE_INT_TO_CHAR), - LintId::of(transmute::TRANSMUTE_INT_TO_FLOAT), - LintId::of(transmute::TRANSMUTE_PTR_TO_REF), - LintId::of(transmute::UNSOUND_COLLECTION_TRANSMUTE), - LintId::of(transmute::WRONG_TRANSMUTE), - LintId::of(transmuting_null::TRANSMUTING_NULL), - LintId::of(try_err::TRY_ERR), - LintId::of(types::BORROWED_BOX), - LintId::of(types::BOX_VEC), - LintId::of(types::REDUNDANT_ALLOCATION), - LintId::of(types::TYPE_COMPLEXITY), - LintId::of(types::VEC_BOX), - LintId::of(undropped_manually_drops::UNDROPPED_MANUALLY_DROPS), - LintId::of(unicode::INVISIBLE_CHARACTERS), - LintId::of(unit_return_expecting_ord::UNIT_RETURN_EXPECTING_ORD), - LintId::of(unit_types::UNIT_ARG), - LintId::of(unit_types::UNIT_CMP), - LintId::of(unnamed_address::FN_ADDRESS_COMPARISONS), - LintId::of(unnamed_address::VTABLE_ADDRESS_COMPARISONS), - LintId::of(unnecessary_sort_by::UNNECESSARY_SORT_BY), - LintId::of(unsafe_removed_from_name::UNSAFE_REMOVED_FROM_NAME), - LintId::of(unused_io_amount::UNUSED_IO_AMOUNT), - LintId::of(unused_unit::UNUSED_UNIT), - LintId::of(unwrap::PANICKING_UNWRAP), - LintId::of(unwrap::UNNECESSARY_UNWRAP), - LintId::of(upper_case_acronyms::UPPER_CASE_ACRONYMS), - LintId::of(useless_conversion::USELESS_CONVERSION), - LintId::of(vec::USELESS_VEC), - LintId::of(vec_init_then_push::VEC_INIT_THEN_PUSH), - LintId::of(vec_resize_to_zero::VEC_RESIZE_TO_ZERO), - LintId::of(write::PRINTLN_EMPTY_STRING), - LintId::of(write::PRINT_LITERAL), - LintId::of(write::PRINT_WITH_NEWLINE), - LintId::of(write::WRITELN_EMPTY_STRING), - LintId::of(write::WRITE_LITERAL), - LintId::of(write::WRITE_WITH_NEWLINE), - LintId::of(zero_div_zero::ZERO_DIVIDED_BY_ZERO), - ]); - - store.register_group(true, "clippy::style", Some("clippy_style"), vec![ - LintId::of(assertions_on_constants::ASSERTIONS_ON_CONSTANTS), - LintId::of(assign_ops::ASSIGN_OP_PATTERN), - LintId::of(blacklisted_name::BLACKLISTED_NAME), - LintId::of(blocks_in_if_conditions::BLOCKS_IN_IF_CONDITIONS), - LintId::of(bool_assert_comparison::BOOL_ASSERT_COMPARISON), - LintId::of(casts::FN_TO_NUMERIC_CAST), - LintId::of(casts::FN_TO_NUMERIC_CAST_WITH_TRUNCATION), - LintId::of(collapsible_if::COLLAPSIBLE_ELSE_IF), - LintId::of(collapsible_if::COLLAPSIBLE_IF), - LintId::of(collapsible_match::COLLAPSIBLE_MATCH), - LintId::of(comparison_chain::COMPARISON_CHAIN), - LintId::of(default::FIELD_REASSIGN_WITH_DEFAULT), - LintId::of(doc::MISSING_SAFETY_DOC), - LintId::of(doc::NEEDLESS_DOCTEST_MAIN), - LintId::of(enum_variants::ENUM_VARIANT_NAMES), - LintId::of(enum_variants::MODULE_INCEPTION), - LintId::of(eq_op::OP_REF), - LintId::of(eta_reduction::REDUNDANT_CLOSURE), - LintId::of(float_literal::EXCESSIVE_PRECISION), - LintId::of(from_over_into::FROM_OVER_INTO), - LintId::of(from_str_radix_10::FROM_STR_RADIX_10), - LintId::of(functions::DOUBLE_MUST_USE), - LintId::of(functions::MUST_USE_UNIT), - LintId::of(functions::RESULT_UNIT_ERR), - LintId::of(if_let_some_result::IF_LET_SOME_RESULT), - LintId::of(inherent_to_string::INHERENT_TO_STRING), - LintId::of(len_zero::COMPARISON_TO_EMPTY), - LintId::of(len_zero::LEN_WITHOUT_IS_EMPTY), - LintId::of(len_zero::LEN_ZERO), - LintId::of(literal_representation::INCONSISTENT_DIGIT_GROUPING), - LintId::of(literal_representation::UNUSUAL_BYTE_GROUPINGS), - LintId::of(loops::FOR_KV_MAP), - LintId::of(loops::NEEDLESS_RANGE_LOOP), - LintId::of(loops::SAME_ITEM_PUSH), - LintId::of(loops::WHILE_LET_ON_ITERATOR), - LintId::of(main_recursion::MAIN_RECURSION), - LintId::of(manual_async_fn::MANUAL_ASYNC_FN), - LintId::of(manual_map::MANUAL_MAP), - LintId::of(manual_non_exhaustive::MANUAL_NON_EXHAUSTIVE), - LintId::of(map_clone::MAP_CLONE), - LintId::of(matches::INFALLIBLE_DESTRUCTURING_MATCH), - LintId::of(matches::MATCH_LIKE_MATCHES_MACRO), - LintId::of(matches::MATCH_OVERLAPPING_ARM), - LintId::of(matches::MATCH_REF_PATS), - LintId::of(matches::REDUNDANT_PATTERN_MATCHING), - LintId::of(matches::SINGLE_MATCH), - LintId::of(mem_replace::MEM_REPLACE_OPTION_WITH_NONE), - LintId::of(mem_replace::MEM_REPLACE_WITH_DEFAULT), - LintId::of(methods::BYTES_NTH), - LintId::of(methods::CHARS_LAST_CMP), - LintId::of(methods::CHARS_NEXT_CMP), - LintId::of(methods::INTO_ITER_ON_REF), - LintId::of(methods::ITER_CLONED_COLLECT), - LintId::of(methods::ITER_NEXT_SLICE), - LintId::of(methods::ITER_NTH_ZERO), - LintId::of(methods::ITER_SKIP_NEXT), - LintId::of(methods::MANUAL_SATURATING_ARITHMETIC), - LintId::of(methods::MAP_COLLECT_RESULT_UNIT), - LintId::of(methods::NEW_RET_NO_SELF), - LintId::of(methods::OK_EXPECT), - LintId::of(methods::OPTION_MAP_OR_NONE), - LintId::of(methods::RESULT_MAP_OR_INTO_OPTION), - LintId::of(methods::SHOULD_IMPLEMENT_TRAIT), - LintId::of(methods::SINGLE_CHAR_ADD_STR), - LintId::of(methods::STRING_EXTEND_CHARS), - LintId::of(methods::UNNECESSARY_FOLD), - LintId::of(methods::UNNECESSARY_LAZY_EVALUATIONS), - LintId::of(methods::UNWRAP_OR_ELSE_DEFAULT), - LintId::of(methods::WRONG_SELF_CONVENTION), - LintId::of(misc::TOPLEVEL_REF_ARG), - LintId::of(misc::ZERO_PTR), - LintId::of(misc_early::BUILTIN_TYPE_SHADOW), - LintId::of(misc_early::DOUBLE_NEG), - LintId::of(misc_early::DUPLICATE_UNDERSCORE_ARGUMENT), - LintId::of(misc_early::MIXED_CASE_HEX_LITERALS), - LintId::of(misc_early::REDUNDANT_PATTERN), - LintId::of(mut_mutex_lock::MUT_MUTEX_LOCK), - LintId::of(mut_reference::UNNECESSARY_MUT_PASSED), - LintId::of(needless_borrow::NEEDLESS_BORROW), - LintId::of(neg_multiply::NEG_MULTIPLY), - LintId::of(new_without_default::NEW_WITHOUT_DEFAULT), - LintId::of(non_copy_const::BORROW_INTERIOR_MUTABLE_CONST), - LintId::of(non_copy_const::DECLARE_INTERIOR_MUTABLE_CONST), - LintId::of(non_expressive_names::JUST_UNDERSCORES_AND_DIGITS), - LintId::of(non_expressive_names::MANY_SINGLE_CHAR_NAMES), - LintId::of(ptr::CMP_NULL), - LintId::of(ptr::PTR_ARG), - LintId::of(ptr_eq::PTR_EQ), - LintId::of(question_mark::QUESTION_MARK), - LintId::of(ranges::MANUAL_RANGE_CONTAINS), - LintId::of(redundant_field_names::REDUNDANT_FIELD_NAMES), - LintId::of(redundant_static_lifetimes::REDUNDANT_STATIC_LIFETIMES), - LintId::of(returns::LET_AND_RETURN), - LintId::of(returns::NEEDLESS_RETURN), - LintId::of(self_named_constructors::SELF_NAMED_CONSTRUCTORS), - LintId::of(single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS), - LintId::of(tabs_in_doc_comments::TABS_IN_DOC_COMMENTS), - LintId::of(to_digit_is_some::TO_DIGIT_IS_SOME), - LintId::of(try_err::TRY_ERR), - LintId::of(unsafe_removed_from_name::UNSAFE_REMOVED_FROM_NAME), - LintId::of(unused_unit::UNUSED_UNIT), - LintId::of(upper_case_acronyms::UPPER_CASE_ACRONYMS), - LintId::of(write::PRINTLN_EMPTY_STRING), - LintId::of(write::PRINT_LITERAL), - LintId::of(write::PRINT_WITH_NEWLINE), - LintId::of(write::WRITELN_EMPTY_STRING), - LintId::of(write::WRITE_LITERAL), - LintId::of(write::WRITE_WITH_NEWLINE), - ]); - - store.register_group(true, "clippy::complexity", Some("clippy_complexity"), vec![ - LintId::of(attrs::DEPRECATED_CFG_ATTR), - LintId::of(booleans::NONMINIMAL_BOOL), - LintId::of(casts::CHAR_LIT_AS_U8), - LintId::of(casts::UNNECESSARY_CAST), - LintId::of(copies::BRANCHES_SHARING_CODE), - LintId::of(double_comparison::DOUBLE_COMPARISONS), - LintId::of(double_parens::DOUBLE_PARENS), - LintId::of(duration_subsec::DURATION_SUBSEC), - LintId::of(eval_order_dependence::DIVERGING_SUB_EXPRESSION), - LintId::of(explicit_write::EXPLICIT_WRITE), - LintId::of(format::USELESS_FORMAT), - LintId::of(functions::TOO_MANY_ARGUMENTS), - LintId::of(get_last_with_len::GET_LAST_WITH_LEN), - LintId::of(identity_op::IDENTITY_OP), - LintId::of(int_plus_one::INT_PLUS_ONE), - LintId::of(lifetimes::EXTRA_UNUSED_LIFETIMES), - LintId::of(lifetimes::NEEDLESS_LIFETIMES), - LintId::of(loops::EXPLICIT_COUNTER_LOOP), - LintId::of(loops::MANUAL_FLATTEN), - LintId::of(loops::SINGLE_ELEMENT_LOOP), - LintId::of(loops::WHILE_LET_LOOP), - LintId::of(manual_strip::MANUAL_STRIP), - LintId::of(manual_unwrap_or::MANUAL_UNWRAP_OR), - LintId::of(map_unit_fn::OPTION_MAP_UNIT_FN), - LintId::of(map_unit_fn::RESULT_MAP_UNIT_FN), - LintId::of(matches::MATCH_AS_REF), - LintId::of(matches::MATCH_SINGLE_BINDING), - LintId::of(matches::WILDCARD_IN_OR_PATTERNS), - LintId::of(methods::BIND_INSTEAD_OF_MAP), - LintId::of(methods::CLONE_ON_COPY), - LintId::of(methods::FILTER_MAP_IDENTITY), - LintId::of(methods::FILTER_NEXT), - LintId::of(methods::FLAT_MAP_IDENTITY), - LintId::of(methods::INSPECT_FOR_EACH), - LintId::of(methods::ITER_COUNT), - LintId::of(methods::MANUAL_FILTER_MAP), - LintId::of(methods::MANUAL_FIND_MAP), - LintId::of(methods::MAP_IDENTITY), - LintId::of(methods::OPTION_AS_REF_DEREF), - LintId::of(methods::OPTION_FILTER_MAP), - LintId::of(methods::SEARCH_IS_SOME), - LintId::of(methods::SKIP_WHILE_NEXT), - LintId::of(methods::UNNECESSARY_FILTER_MAP), - LintId::of(methods::USELESS_ASREF), - LintId::of(misc::SHORT_CIRCUIT_STATEMENT), - LintId::of(misc_early::UNNEEDED_WILDCARD_PATTERN), - LintId::of(misc_early::ZERO_PREFIXED_LITERAL), - LintId::of(needless_arbitrary_self_type::NEEDLESS_ARBITRARY_SELF_TYPE), - LintId::of(needless_bool::BOOL_COMPARISON), - LintId::of(needless_bool::NEEDLESS_BOOL), - LintId::of(needless_borrowed_ref::NEEDLESS_BORROWED_REFERENCE), - LintId::of(needless_question_mark::NEEDLESS_QUESTION_MARK), - LintId::of(needless_update::NEEDLESS_UPDATE), - LintId::of(neg_cmp_op_on_partial_ord::NEG_CMP_OP_ON_PARTIAL_ORD), - LintId::of(no_effect::NO_EFFECT), - LintId::of(no_effect::UNNECESSARY_OPERATION), - LintId::of(overflow_check_conditional::OVERFLOW_CHECK_CONDITIONAL), - LintId::of(partialeq_ne_impl::PARTIALEQ_NE_IMPL), - LintId::of(precedence::PRECEDENCE), - LintId::of(ptr_offset_with_cast::PTR_OFFSET_WITH_CAST), - LintId::of(ranges::RANGE_ZIP_WITH_LEN), - LintId::of(redundant_closure_call::REDUNDANT_CLOSURE_CALL), - LintId::of(redundant_slicing::REDUNDANT_SLICING), - LintId::of(reference::DEREF_ADDROF), - LintId::of(reference::REF_IN_DEREF), - LintId::of(repeat_once::REPEAT_ONCE), - LintId::of(strings::STRING_FROM_UTF8_AS_BYTES), - LintId::of(strlen_on_c_strings::STRLEN_ON_C_STRINGS), - LintId::of(swap::MANUAL_SWAP), - LintId::of(temporary_assignment::TEMPORARY_ASSIGNMENT), - LintId::of(transmute::CROSSPOINTER_TRANSMUTE), - LintId::of(transmute::TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS), - LintId::of(transmute::TRANSMUTE_BYTES_TO_STR), - LintId::of(transmute::TRANSMUTE_FLOAT_TO_INT), - LintId::of(transmute::TRANSMUTE_INT_TO_BOOL), - LintId::of(transmute::TRANSMUTE_INT_TO_CHAR), - LintId::of(transmute::TRANSMUTE_INT_TO_FLOAT), - LintId::of(transmute::TRANSMUTE_PTR_TO_REF), - LintId::of(types::BORROWED_BOX), - LintId::of(types::TYPE_COMPLEXITY), - LintId::of(types::VEC_BOX), - LintId::of(unit_types::UNIT_ARG), - LintId::of(unnecessary_sort_by::UNNECESSARY_SORT_BY), - LintId::of(unwrap::UNNECESSARY_UNWRAP), - LintId::of(useless_conversion::USELESS_CONVERSION), - LintId::of(zero_div_zero::ZERO_DIVIDED_BY_ZERO), - ]); - - store.register_group(true, "clippy::correctness", Some("clippy_correctness"), vec![ - LintId::of(absurd_extreme_comparisons::ABSURD_EXTREME_COMPARISONS), - LintId::of(approx_const::APPROX_CONSTANT), - LintId::of(async_yields_async::ASYNC_YIELDS_ASYNC), - LintId::of(attrs::DEPRECATED_SEMVER), - LintId::of(attrs::MISMATCHED_TARGET_OS), - LintId::of(attrs::USELESS_ATTRIBUTE), - LintId::of(bit_mask::BAD_BIT_MASK), - LintId::of(bit_mask::INEFFECTIVE_BIT_MASK), - LintId::of(booleans::LOGIC_BUG), - LintId::of(casts::CAST_REF_TO_MUT), - LintId::of(copies::IFS_SAME_COND), - LintId::of(copies::IF_SAME_THEN_ELSE), - LintId::of(derive::DERIVE_HASH_XOR_EQ), - LintId::of(derive::DERIVE_ORD_XOR_PARTIAL_ORD), - LintId::of(drop_forget_ref::DROP_COPY), - LintId::of(drop_forget_ref::DROP_REF), - LintId::of(drop_forget_ref::FORGET_COPY), - LintId::of(drop_forget_ref::FORGET_REF), - LintId::of(enum_clike::ENUM_CLIKE_UNPORTABLE_VARIANT), - LintId::of(eq_op::EQ_OP), - LintId::of(erasing_op::ERASING_OP), - LintId::of(formatting::POSSIBLE_MISSING_COMMA), - LintId::of(functions::NOT_UNSAFE_PTR_ARG_DEREF), - LintId::of(if_let_mutex::IF_LET_MUTEX), - LintId::of(indexing_slicing::OUT_OF_BOUNDS_INDEXING), - LintId::of(infinite_iter::INFINITE_ITER), - LintId::of(inherent_to_string::INHERENT_TO_STRING_SHADOW_DISPLAY), - LintId::of(inline_fn_without_body::INLINE_FN_WITHOUT_BODY), - LintId::of(let_underscore::LET_UNDERSCORE_LOCK), - LintId::of(literal_representation::MISTYPED_LITERAL_SUFFIXES), - LintId::of(loops::ITER_NEXT_LOOP), - LintId::of(loops::NEVER_LOOP), - LintId::of(loops::WHILE_IMMUTABLE_CONDITION), - LintId::of(mem_discriminant::MEM_DISCRIMINANT_NON_ENUM), - LintId::of(mem_replace::MEM_REPLACE_WITH_UNINIT), - LintId::of(methods::CLONE_DOUBLE_REF), - LintId::of(methods::ITERATOR_STEP_BY_ZERO), - LintId::of(methods::SUSPICIOUS_SPLITN), - LintId::of(methods::UNINIT_ASSUMED_INIT), - LintId::of(methods::ZST_OFFSET), - LintId::of(minmax::MIN_MAX), - LintId::of(misc::CMP_NAN), - LintId::of(misc::FLOAT_CMP), - LintId::of(misc::MODULO_ONE), - LintId::of(non_octal_unix_permissions::NON_OCTAL_UNIX_PERMISSIONS), - LintId::of(open_options::NONSENSICAL_OPEN_OPTIONS), - LintId::of(option_env_unwrap::OPTION_ENV_UNWRAP), - LintId::of(ptr::INVALID_NULL_PTR_USAGE), - LintId::of(ptr::MUT_FROM_REF), - LintId::of(ranges::REVERSED_EMPTY_RANGES), - LintId::of(regex::INVALID_REGEX), - LintId::of(self_assignment::SELF_ASSIGNMENT), - LintId::of(serde_api::SERDE_API_MISUSE), - LintId::of(size_of_in_element_count::SIZE_OF_IN_ELEMENT_COUNT), - LintId::of(swap::ALMOST_SWAPPED), - LintId::of(to_string_in_display::TO_STRING_IN_DISPLAY), - LintId::of(transmute::UNSOUND_COLLECTION_TRANSMUTE), - LintId::of(transmute::WRONG_TRANSMUTE), - LintId::of(transmuting_null::TRANSMUTING_NULL), - LintId::of(undropped_manually_drops::UNDROPPED_MANUALLY_DROPS), - LintId::of(unicode::INVISIBLE_CHARACTERS), - LintId::of(unit_return_expecting_ord::UNIT_RETURN_EXPECTING_ORD), - LintId::of(unit_types::UNIT_CMP), - LintId::of(unnamed_address::FN_ADDRESS_COMPARISONS), - LintId::of(unnamed_address::VTABLE_ADDRESS_COMPARISONS), - LintId::of(unused_io_amount::UNUSED_IO_AMOUNT), - LintId::of(unwrap::PANICKING_UNWRAP), - LintId::of(vec_resize_to_zero::VEC_RESIZE_TO_ZERO), - ]); - - store.register_group(true, "clippy::suspicious", None, vec![ - LintId::of(assign_ops::MISREFACTORED_ASSIGN_OP), - LintId::of(attrs::BLANKET_CLIPPY_RESTRICTION_LINTS), - LintId::of(eval_order_dependence::EVAL_ORDER_DEPENDENCE), - LintId::of(float_equality_without_abs::FLOAT_EQUALITY_WITHOUT_ABS), - LintId::of(formatting::SUSPICIOUS_ASSIGNMENT_FORMATTING), - LintId::of(formatting::SUSPICIOUS_ELSE_FORMATTING), - LintId::of(formatting::SUSPICIOUS_UNARY_OP_FORMATTING), - LintId::of(loops::EMPTY_LOOP), - LintId::of(loops::FOR_LOOPS_OVER_FALLIBLES), - LintId::of(loops::MUT_RANGE_BOUND), - LintId::of(methods::SUSPICIOUS_MAP), - LintId::of(mut_key::MUTABLE_KEY_TYPE), - LintId::of(suspicious_trait_impl::SUSPICIOUS_ARITHMETIC_IMPL), - LintId::of(suspicious_trait_impl::SUSPICIOUS_OP_ASSIGN_IMPL), - ]); - - store.register_group(true, "clippy::perf", Some("clippy_perf"), vec![ - LintId::of(entry::MAP_ENTRY), - LintId::of(escape::BOXED_LOCAL), - LintId::of(large_const_arrays::LARGE_CONST_ARRAYS), - LintId::of(large_enum_variant::LARGE_ENUM_VARIANT), - LintId::of(loops::MANUAL_MEMCPY), - LintId::of(loops::NEEDLESS_COLLECT), - LintId::of(methods::EXPECT_FUN_CALL), - LintId::of(methods::EXTEND_WITH_DRAIN), - LintId::of(methods::ITER_NTH), - LintId::of(methods::MANUAL_STR_REPEAT), - LintId::of(methods::OR_FUN_CALL), - LintId::of(methods::SINGLE_CHAR_PATTERN), - LintId::of(misc::CMP_OWNED), - LintId::of(mutex_atomic::MUTEX_ATOMIC), - LintId::of(redundant_clone::REDUNDANT_CLONE), - LintId::of(slow_vector_initialization::SLOW_VECTOR_INITIALIZATION), - LintId::of(stable_sort_primitive::STABLE_SORT_PRIMITIVE), - LintId::of(types::BOX_VEC), - LintId::of(types::REDUNDANT_ALLOCATION), - LintId::of(vec::USELESS_VEC), - LintId::of(vec_init_then_push::VEC_INIT_THEN_PUSH), - ]); - - store.register_group(true, "clippy::cargo", Some("clippy_cargo"), vec![ - LintId::of(cargo_common_metadata::CARGO_COMMON_METADATA), - LintId::of(multiple_crate_versions::MULTIPLE_CRATE_VERSIONS), - LintId::of(wildcard_dependencies::WILDCARD_DEPENDENCIES), - ]); - - store.register_group(true, "clippy::nursery", Some("clippy_nursery"), vec![ - LintId::of(attrs::EMPTY_LINE_AFTER_OUTER_ATTR), - LintId::of(cognitive_complexity::COGNITIVE_COMPLEXITY), - LintId::of(disallowed_method::DISALLOWED_METHOD), - LintId::of(disallowed_type::DISALLOWED_TYPE), - LintId::of(fallible_impl_from::FALLIBLE_IMPL_FROM), - LintId::of(floating_point_arithmetic::IMPRECISE_FLOPS), - LintId::of(floating_point_arithmetic::SUBOPTIMAL_FLOPS), - LintId::of(future_not_send::FUTURE_NOT_SEND), - LintId::of(let_if_seq::USELESS_LET_IF_SEQ), - LintId::of(missing_const_for_fn::MISSING_CONST_FOR_FN), - LintId::of(mutable_debug_assertion::DEBUG_ASSERT_WITH_MUT_CALL), - LintId::of(mutex_atomic::MUTEX_INTEGER), - LintId::of(nonstandard_macro_braces::NONSTANDARD_MACRO_BRACES), - LintId::of(path_buf_push_overwrite::PATH_BUF_PUSH_OVERWRITE), - LintId::of(redundant_pub_crate::REDUNDANT_PUB_CRATE), - LintId::of(regex::TRIVIAL_REGEX), - LintId::of(strings::STRING_LIT_AS_BYTES), - LintId::of(suspicious_operation_groupings::SUSPICIOUS_OPERATION_GROUPINGS), - LintId::of(transmute::USELESS_TRANSMUTE), - LintId::of(use_self::USE_SELF), - ]); + include!("lib.register_all.rs"); + include!("lib.register_style.rs"); + include!("lib.register_complexity.rs"); + include!("lib.register_correctness.rs"); + include!("lib.register_suspicious.rs"); + include!("lib.register_perf.rs"); + include!("lib.register_cargo.rs"); + include!("lib.register_nursery.rs"); #[cfg(feature = "metadata-collector-lint")] { @@ -1835,7 +486,12 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|| Box::new(serde_api::SerdeApi)); let vec_box_size_threshold = conf.vec_box_size_threshold; let type_complexity_threshold = conf.type_complexity_threshold; - store.register_late_pass(move || Box::new(types::Types::new(vec_box_size_threshold, type_complexity_threshold))); + let avoid_breaking_exported_api = conf.avoid_breaking_exported_api; + store.register_late_pass(move || Box::new(types::Types::new( + vec_box_size_threshold, + type_complexity_threshold, + avoid_breaking_exported_api, + ))); store.register_late_pass(|| Box::new(booleans::NonminimalBool)); store.register_late_pass(|| Box::new(needless_bitwise_bool::NeedlessBitwiseBool)); store.register_late_pass(|| Box::new(eq_op::EqOp)); @@ -1846,9 +502,9 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|| Box::new(ptr::Ptr)); store.register_late_pass(|| Box::new(ptr_eq::PtrEq)); store.register_late_pass(|| Box::new(needless_bool::NeedlessBool)); + store.register_late_pass(|| Box::new(needless_option_as_deref::OptionNeedlessDeref)); store.register_late_pass(|| Box::new(needless_bool::BoolComparison)); store.register_late_pass(|| Box::new(needless_for_each::NeedlessForEach)); - store.register_late_pass(|| Box::new(approx_const::ApproxConstant)); store.register_late_pass(|| Box::new(misc::MiscLints)); store.register_late_pass(|| Box::new(eta_reduction::EtaReduction)); store.register_late_pass(|| Box::new(identity_op::IdentityOp)); @@ -1877,6 +533,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: }); let avoid_breaking_exported_api = conf.avoid_breaking_exported_api; + store.register_late_pass(move || Box::new(approx_const::ApproxConstant::new(msrv))); store.register_late_pass(move || Box::new(methods::Methods::new(avoid_breaking_exported_api, msrv))); store.register_late_pass(move || Box::new(matches::Matches::new(msrv))); store.register_early_pass(move || Box::new(manual_non_exhaustive::ManualNonExhaustive::new(msrv))); @@ -1894,9 +551,10 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_early_pass(move || Box::new(unnested_or_patterns::UnnestedOrPatterns::new(msrv))); store.register_late_pass(|| Box::new(size_of_in_element_count::SizeOfInElementCount)); + store.register_late_pass(|| Box::new(same_name_method::SameNameMethod)); store.register_late_pass(|| Box::new(map_clone::MapClone)); store.register_late_pass(|| Box::new(map_err_ignore::MapErrIgnore)); - store.register_late_pass(|| Box::new(shadow::Shadow)); + store.register_late_pass(|| Box::new(shadow::Shadow::default())); store.register_late_pass(|| Box::new(unit_types::UnitTypes)); store.register_late_pass(|| Box::new(loops::Loops)); store.register_late_pass(|| Box::new(main_recursion::MainRecursion::default())); @@ -1920,12 +578,13 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|| Box::new(panic_unimplemented::PanicUnimplemented)); store.register_late_pass(|| Box::new(strings::StringLitAsBytes)); store.register_late_pass(|| Box::new(derive::Derive)); + store.register_late_pass(|| Box::new(derivable_impls::DerivableImpls)); store.register_late_pass(|| Box::new(get_last_with_len::GetLastWithLen)); store.register_late_pass(|| Box::new(drop_forget_ref::DropForgetRef)); store.register_late_pass(|| Box::new(empty_enum::EmptyEnum)); store.register_late_pass(|| Box::new(absurd_extreme_comparisons::AbsurdExtremeComparisons)); store.register_late_pass(|| Box::new(invalid_upcast_comparisons::InvalidUpcastComparisons)); - store.register_late_pass(|| Box::new(regex::Regex::default())); + store.register_late_pass(|| Box::new(regex::Regex)); store.register_late_pass(|| Box::new(copies::CopyAndPaste)); store.register_late_pass(|| Box::new(copy_iterator::CopyIterator)); store.register_late_pass(|| Box::new(format::UselessFormat)); @@ -1940,7 +599,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: let doc_valid_idents = conf.doc_valid_idents.iter().cloned().collect::>(); store.register_late_pass(move || Box::new(doc::DocMarkdown::new(doc_valid_idents.clone()))); store.register_late_pass(|| Box::new(neg_multiply::NegMultiply)); - store.register_late_pass(|| Box::new(mem_discriminant::MemDiscriminant)); store.register_late_pass(|| Box::new(mem_forget::MemForget)); store.register_late_pass(|| Box::new(arithmetic::Arithmetic::default())); store.register_late_pass(|| Box::new(assign_ops::AssignOps)); @@ -1949,7 +607,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|| Box::new(missing_doc::MissingDoc::new())); store.register_late_pass(|| Box::new(missing_inline::MissingInline)); store.register_late_pass(move || Box::new(exhaustive_items::ExhaustiveItems)); - store.register_late_pass(|| Box::new(if_let_some_result::OkIfLet)); + store.register_late_pass(|| Box::new(match_result_ok::MatchResultOk)); store.register_late_pass(|| Box::new(partialeq_ne_impl::PartialEqNeImpl)); store.register_late_pass(|| Box::new(unused_io_amount::UnusedIoAmount)); let enum_variant_size_threshold = conf.enum_variant_size_threshold; @@ -2056,6 +714,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(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)); store.register_late_pass(|| Box::new(manual_async_fn::ManualAsyncFn)); @@ -2078,8 +737,8 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|| Box::new(float_equality_without_abs::FloatEqualityWithoutAbs)); store.register_late_pass(|| Box::new(semicolon_if_nothing_returned::SemicolonIfNothingReturned)); store.register_late_pass(|| Box::new(async_yields_async::AsyncYieldsAsync)); - let disallowed_methods = conf.disallowed_methods.iter().cloned().collect::>(); - store.register_late_pass(move || Box::new(disallowed_method::DisallowedMethod::new(&disallowed_methods))); + let disallowed_methods = conf.disallowed_methods.clone(); + store.register_late_pass(move || Box::new(disallowed_method::DisallowedMethod::new(disallowed_methods.clone()))); store.register_early_pass(|| Box::new(asm_syntax::InlineAsmX86AttSyntax)); store.register_early_pass(|| Box::new(asm_syntax::InlineAsmX86IntelSyntax)); store.register_late_pass(|| Box::new(undropped_manually_drops::UndroppedManuallyDrops)); @@ -2092,7 +751,8 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|| Box::new(from_str_radix_10::FromStrRadix10)); store.register_late_pass(|| Box::new(manual_map::ManualMap)); store.register_late_pass(move || Box::new(if_then_some_else_none::IfThenSomeElseNone::new(msrv))); - store.register_early_pass(|| Box::new(bool_assert_comparison::BoolAssertComparison)); + 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::>(); store.register_late_pass(move || Box::new(disallowed_type::DisallowedType::new(&disallowed_types))); @@ -2102,6 +762,11 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_early_pass(move || Box::new(disallowed_script_idents::DisallowedScriptIdents::new(&scripts))); store.register_late_pass(|| Box::new(strlen_on_c_strings::StrlenOnCStrings)); store.register_late_pass(move || Box::new(self_named_constructors::SelfNamedConstructors)); + store.register_late_pass(move || Box::new(feature_name::FeatureName)); + store.register_late_pass(move || Box::new(iter_not_returning_iterator::IterNotReturningIterator)); + 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))); } #[rustfmt::skip] @@ -2157,6 +822,7 @@ pub fn register_renamed(ls: &mut rustc_lint::LintStore) { ls.register_renamed("clippy::cyclomatic_complexity", "clippy::cognitive_complexity"); ls.register_renamed("clippy::const_static_lifetime", "clippy::redundant_static_lifetimes"); ls.register_renamed("clippy::option_and_then_some", "clippy::bind_instead_of_map"); + ls.register_renamed("clippy::box_vec", "clippy::box_collection"); ls.register_renamed("clippy::block_in_if_condition_expr", "clippy::blocks_in_if_conditions"); ls.register_renamed("clippy::block_in_if_condition_stmt", "clippy::blocks_in_if_conditions"); ls.register_renamed("clippy::option_map_unwrap_or", "clippy::map_unwrap_or"); @@ -2171,6 +837,7 @@ pub fn register_renamed(ls: &mut rustc_lint::LintStore) { ls.register_renamed("clippy::identity_conversion", "clippy::useless_conversion"); ls.register_renamed("clippy::zero_width_space", "clippy::invisible_characters"); ls.register_renamed("clippy::single_char_push_str", "clippy::single_char_add_str"); + ls.register_renamed("clippy::if_let_some_result", "clippy::match_result_ok"); // uplifted lints ls.register_renamed("clippy::invalid_ref", "invalid_value"); @@ -2181,6 +848,7 @@ pub fn register_renamed(ls: &mut rustc_lint::LintStore) { ls.register_renamed("clippy::panic_params", "non_fmt_panics"); ls.register_renamed("clippy::unknown_clippy_lints", "unknown_lints"); ls.register_renamed("clippy::invalid_atomic_ordering", "invalid_atomic_ordering"); + ls.register_renamed("clippy::mem_discriminant_non_enum", "enum_intrinsics_non_enums"); } // only exists to let the dogfood integration test works. diff --git a/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs b/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs index 50bc096ba2..5ac69d106c 100644 --- a/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs +++ b/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs @@ -54,11 +54,11 @@ fn is_ref_iterable_type(cx: &LateContext<'_>, e: &Expr<'_>) -> bool { // will allow further borrows afterwards let ty = cx.typeck_results().expr_ty(e); is_iterable_array(ty, cx) || - is_type_diagnostic_item(cx, ty, sym::vec_type) || + is_type_diagnostic_item(cx, ty, sym::Vec) || is_type_diagnostic_item(cx, ty, sym::LinkedList) || - is_type_diagnostic_item(cx, ty, sym::hashmap_type) || - is_type_diagnostic_item(cx, ty, sym::hashset_type) || - is_type_diagnostic_item(cx, ty, sym::vecdeque_type) || + is_type_diagnostic_item(cx, ty, sym::HashMap) || + is_type_diagnostic_item(cx, ty, sym::HashSet) || + is_type_diagnostic_item(cx, ty, sym::VecDeque) || is_type_diagnostic_item(cx, ty, sym::BinaryHeap) || is_type_diagnostic_item(cx, ty, sym::BTreeMap) || is_type_diagnostic_item(cx, ty, sym::BTreeSet) diff --git a/src/tools/clippy/clippy_lints/src/loops/for_kv_map.rs b/src/tools/clippy/clippy_lints/src/loops/for_kv_map.rs index 82bf49f5b4..bee0e1d768 100644 --- a/src/tools/clippy/clippy_lints/src/loops/for_kv_map.rs +++ b/src/tools/clippy/clippy_lints/src/loops/for_kv_map.rs @@ -3,20 +3,14 @@ use clippy_utils::diagnostics::{multispan_sugg, span_lint_and_then}; use clippy_utils::source::snippet; use clippy_utils::sugg; use clippy_utils::ty::is_type_diagnostic_item; -use clippy_utils::visitors::LocalUsedVisitor; +use clippy_utils::visitors::is_local_used; use rustc_hir::{BorrowKind, Expr, ExprKind, Mutability, Pat, PatKind}; use rustc_lint::LateContext; use rustc_middle::ty; use rustc_span::sym; /// Checks for the `FOR_KV_MAP` lint. -pub(super) fn check<'tcx>( - cx: &LateContext<'tcx>, - pat: &'tcx Pat<'_>, - arg: &'tcx Expr<'_>, - body: &'tcx Expr<'_>, - expr: &'tcx Expr<'_>, -) { +pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, pat: &'tcx Pat<'_>, arg: &'tcx Expr<'_>, body: &'tcx Expr<'_>) { let pat_span = pat.span; if let PatKind::Tuple(pat, _) = pat.kind { @@ -39,11 +33,11 @@ pub(super) fn check<'tcx>( _ => arg, }; - if is_type_diagnostic_item(cx, ty, sym::hashmap_type) || is_type_diagnostic_item(cx, ty, sym::BTreeMap) { + if is_type_diagnostic_item(cx, ty, sym::HashMap) || is_type_diagnostic_item(cx, ty, sym::BTreeMap) { span_lint_and_then( cx, FOR_KV_MAP, - expr.span, + arg_span, &format!("you seem to want to iterate on a map's {}s", kind), |diag| { let map = sugg::Sugg::hir(cx, arg, "map"); @@ -66,9 +60,7 @@ pub(super) fn check<'tcx>( fn pat_is_wild<'tcx>(cx: &LateContext<'tcx>, pat: &'tcx PatKind<'_>, body: &'tcx Expr<'_>) -> bool { match *pat { PatKind::Wild => true, - PatKind::Binding(_, id, ident, None) if ident.as_str().starts_with('_') => { - !LocalUsedVisitor::new(cx, id).check_expr(body) - }, + PatKind::Binding(_, id, ident, None) if ident.as_str().starts_with('_') => !is_local_used(cx, body, id), _ => false, } } diff --git a/src/tools/clippy/clippy_lints/src/loops/for_loops_over_fallibles.rs b/src/tools/clippy/clippy_lints/src/loops/for_loops_over_fallibles.rs index d49b0517dc..90530ebf00 100644 --- a/src/tools/clippy/clippy_lints/src/loops/for_loops_over_fallibles.rs +++ b/src/tools/clippy/clippy_lints/src/loops/for_loops_over_fallibles.rs @@ -9,7 +9,7 @@ use rustc_span::symbol::sym; /// Checks for `for` loops over `Option`s and `Result`s. pub(super) fn check(cx: &LateContext<'_>, pat: &Pat<'_>, arg: &Expr<'_>) { let ty = cx.typeck_results().expr_ty(arg); - if is_type_diagnostic_item(cx, ty, sym::option_type) { + if is_type_diagnostic_item(cx, ty, sym::Option) { span_lint_and_help( cx, FOR_LOOPS_OVER_FALLIBLES, @@ -26,7 +26,7 @@ pub(super) fn check(cx: &LateContext<'_>, pat: &Pat<'_>, arg: &Expr<'_>) { snippet(cx, arg.span, "_") ), ); - } else if is_type_diagnostic_item(cx, ty, sym::result_type) { + } else if is_type_diagnostic_item(cx, ty, sym::Result) { span_lint_and_help( cx, FOR_LOOPS_OVER_FALLIBLES, diff --git a/src/tools/clippy/clippy_lints/src/loops/iter_next_loop.rs b/src/tools/clippy/clippy_lints/src/loops/iter_next_loop.rs index 9148fbfd49..e640c62ebd 100644 --- a/src/tools/clippy/clippy_lints/src/loops/iter_next_loop.rs +++ b/src/tools/clippy/clippy_lints/src/loops/iter_next_loop.rs @@ -5,12 +5,12 @@ use rustc_hir::Expr; use rustc_lint::LateContext; use rustc_span::sym; -pub(super) fn check(cx: &LateContext<'_>, arg: &Expr<'_>, expr: &Expr<'_>) -> bool { +pub(super) fn check(cx: &LateContext<'_>, arg: &Expr<'_>) -> bool { if is_trait_method(cx, arg, sym::Iterator) { span_lint( cx, ITER_NEXT_LOOP, - expr.span, + arg.span, "you are iterating over `Iterator::next()` which is an Option; this will compile but is \ probably not what you want", ); diff --git a/src/tools/clippy/clippy_lints/src/loops/manual_flatten.rs b/src/tools/clippy/clippy_lints/src/loops/manual_flatten.rs index 5852674da5..5b6e27085d 100644 --- a/src/tools/clippy/clippy_lints/src/loops/manual_flatten.rs +++ b/src/tools/clippy/clippy_lints/src/loops/manual_flatten.rs @@ -2,6 +2,7 @@ use super::utils::make_iterator_snippet; use super::MANUAL_FLATTEN; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::higher; +use clippy_utils::visitors::is_local_used; use clippy_utils::{is_lang_ctor, path_to_local_id}; use if_chain::if_chain; use rustc_errors::Applicability; @@ -37,7 +38,8 @@ pub(super) fn check<'tcx>( if_chain! { if let Some(inner_expr) = inner_expr; - if let Some(higher::IfLet { let_pat, let_expr, if_else: None, .. }) = higher::IfLet::hir(cx, inner_expr); + if let Some(higher::IfLet { let_pat, let_expr, if_then, if_else: None }) + = higher::IfLet::hir(cx, inner_expr); // Ensure match_expr in `if let` statement is the same as the pat from the for-loop if let PatKind::Binding(_, pat_hir_id, _, _) = pat.kind; if path_to_local_id(let_expr, pat_hir_id); @@ -46,6 +48,8 @@ pub(super) fn check<'tcx>( let some_ctor = is_lang_ctor(cx, qpath, OptionSome); let ok_ctor = is_lang_ctor(cx, qpath, ResultOk); if some_ctor || ok_ctor; + // Ensure epxr in `if let` is not used afterwards + if !is_local_used(cx, if_then, pat_hir_id); then { let if_let_type = if some_ctor { "Some" } else { "Ok" }; // Prepare the error message 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 2296842e86..72027a163a 100644 --- a/src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs +++ b/src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs @@ -332,7 +332,7 @@ fn is_slice_like<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'_>) -> bool { _ => false, }; - is_slice || is_type_diagnostic_item(cx, ty, sym::vec_type) || is_type_diagnostic_item(cx, ty, sym::vecdeque_type) + is_slice || is_type_diagnostic_item(cx, ty, sym::Vec) || is_type_diagnostic_item(cx, ty, sym::VecDeque) } fn fetch_cloned_expr<'tcx>(expr: &'tcx Expr<'tcx>) -> &'tcx Expr<'tcx> { diff --git a/src/tools/clippy/clippy_lints/src/loops/mod.rs b/src/tools/clippy/clippy_lints/src/loops/mod.rs index bd9de5e08d..5df1b79640 100644 --- a/src/tools/clippy/clippy_lints/src/loops/mod.rs +++ b/src/tools/clippy/clippy_lints/src/loops/mod.rs @@ -397,6 +397,21 @@ declare_clippy_lint! { /// ### Why is this bad? /// One might think that modifying the mutable variable changes the loop bounds /// + /// ### Known problems + /// False positive when mutation is followed by a `break`, but the `break` is not immediately + /// after the mutation: + /// + /// ```rust + /// let mut x = 5; + /// for _ in 0..x { + /// x += 1; // x is a range bound that is mutated + /// ..; // some other expression + /// break; // leaves the loop, so mutation is not an issue + /// } + /// ``` + /// + /// False positive on nested loops ([#6072](https://github.com/rust-lang/rust-clippy/issues/6072)) + /// /// ### Example /// ```rust /// let mut foo = 42; @@ -580,8 +595,8 @@ impl<'tcx> LateLintPass<'tcx> for Loops { while_let_on_iterator::check(cx, expr); - if let Some(higher::While { if_cond, if_then, .. }) = higher::While::hir(&expr) { - while_immutable_condition::check(cx, if_cond, if_then); + if let Some(higher::While { condition, body }) = higher::While::hir(expr) { + while_immutable_condition::check(cx, condition, body); } needless_collect::check(expr, cx); @@ -601,15 +616,15 @@ fn check_for_loop<'tcx>( needless_range_loop::check(cx, pat, arg, body, expr); explicit_counter_loop::check(cx, pat, arg, body, expr); } - check_for_loop_arg(cx, pat, arg, expr); - for_kv_map::check(cx, pat, arg, body, expr); + check_for_loop_arg(cx, pat, arg); + for_kv_map::check(cx, pat, arg, body); mut_range_bound::check(cx, arg, body); single_element_loop::check(cx, pat, arg, body, expr); same_item_push::check(cx, pat, arg, body, expr); manual_flatten::check(cx, pat, arg, body, span); } -fn check_for_loop_arg(cx: &LateContext<'_>, pat: &Pat<'_>, arg: &Expr<'_>, expr: &Expr<'_>) { +fn check_for_loop_arg(cx: &LateContext<'_>, pat: &Pat<'_>, arg: &Expr<'_>) { let mut next_loop_linted = false; // whether or not ITER_NEXT_LOOP lint was used if let ExprKind::MethodCall(method, _, [self_arg], _) = arg.kind { @@ -622,7 +637,7 @@ fn check_for_loop_arg(cx: &LateContext<'_>, pat: &Pat<'_>, arg: &Expr<'_>, expr: explicit_into_iter_loop::check(cx, self_arg, arg); }, "next" => { - next_loop_linted = iter_next_loop::check(cx, arg, expr); + next_loop_linted = iter_next_loop::check(cx, arg); }, _ => {}, } diff --git a/src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs b/src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs index 344dc5074d..aedf084493 100644 --- a/src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs +++ b/src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs @@ -1,24 +1,27 @@ use super::MUT_RANGE_BOUND; -use clippy_utils::diagnostics::span_lint; -use clippy_utils::{higher, path_to_local}; +use clippy_utils::diagnostics::span_lint_and_note; +use clippy_utils::{get_enclosing_block, higher, path_to_local}; use if_chain::if_chain; -use rustc_hir::{BindingAnnotation, Expr, HirId, Node, PatKind}; +use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; +use rustc_hir::{BindingAnnotation, Expr, ExprKind, HirId, Node, PatKind}; use rustc_infer::infer::TyCtxtInferExt; use rustc_lint::LateContext; +use rustc_middle::hir::map::Map; use rustc_middle::{mir::FakeReadCause, ty}; use rustc_span::source_map::Span; use rustc_typeck::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId}; pub(super) fn check(cx: &LateContext<'_>, arg: &Expr<'_>, body: &Expr<'_>) { - if let Some(higher::Range { - start: Some(start), - end: Some(end), - .. - }) = higher::Range::hir(arg) - { - let mut_ids = vec![check_for_mutability(cx, start), check_for_mutability(cx, end)]; - if mut_ids[0].is_some() || mut_ids[1].is_some() { - let (span_low, span_high) = check_for_mutation(cx, body, &mut_ids); + if_chain! { + if let Some(higher::Range { + start: Some(start), + end: Some(end), + .. + }) = higher::Range::hir(arg); + let (mut_id_start, mut_id_end) = (check_for_mutability(cx, start), check_for_mutability(cx, end)); + if mut_id_start.is_some() || mut_id_end.is_some(); + then { + let (span_low, span_high) = check_for_mutation(cx, body, mut_id_start, mut_id_end); mut_warn_with_span(cx, span_low); mut_warn_with_span(cx, span_high); } @@ -27,11 +30,13 @@ pub(super) fn check(cx: &LateContext<'_>, arg: &Expr<'_>, body: &Expr<'_>) { fn mut_warn_with_span(cx: &LateContext<'_>, span: Option) { if let Some(sp) = span { - span_lint( + span_lint_and_note( cx, MUT_RANGE_BOUND, sp, - "attempt to mutate range bound within loop; note that the range of the loop is unchanged", + "attempt to mutate range bound within loop", + None, + "the range of the loop is unchanged", ); } } @@ -51,12 +56,13 @@ fn check_for_mutability(cx: &LateContext<'_>, bound: &Expr<'_>) -> Option fn check_for_mutation<'tcx>( cx: &LateContext<'tcx>, body: &Expr<'_>, - bound_ids: &[Option], + bound_id_start: Option, + bound_id_end: Option, ) -> (Option, Option) { let mut delegate = MutatePairDelegate { cx, - hir_id_low: bound_ids[0], - hir_id_high: bound_ids[1], + hir_id_low: bound_id_start, + hir_id_high: bound_id_end, span_low: None, span_high: None, }; @@ -70,6 +76,7 @@ fn check_for_mutation<'tcx>( ) .walk_expr(body); }); + delegate.mutation_span() } @@ -85,12 +92,12 @@ impl<'tcx> Delegate<'tcx> for MutatePairDelegate<'_, 'tcx> { fn consume(&mut self, _: &PlaceWithHirId<'tcx>, _: HirId) {} fn borrow(&mut self, cmt: &PlaceWithHirId<'tcx>, diag_expr_id: HirId, bk: ty::BorrowKind) { - if let ty::BorrowKind::MutBorrow = bk { + if bk == ty::BorrowKind::MutBorrow { if let PlaceBase::Local(id) = cmt.place.base { - if Some(id) == self.hir_id_low { + if Some(id) == self.hir_id_low && !BreakAfterExprVisitor::is_found(self.cx, diag_expr_id) { self.span_low = Some(self.cx.tcx.hir().span(diag_expr_id)); } - if Some(id) == self.hir_id_high { + if Some(id) == self.hir_id_high && !BreakAfterExprVisitor::is_found(self.cx, diag_expr_id) { self.span_high = Some(self.cx.tcx.hir().span(diag_expr_id)); } } @@ -99,10 +106,10 @@ impl<'tcx> Delegate<'tcx> for MutatePairDelegate<'_, 'tcx> { fn mutate(&mut self, cmt: &PlaceWithHirId<'tcx>, diag_expr_id: HirId) { if let PlaceBase::Local(id) = cmt.place.base { - if Some(id) == self.hir_id_low { + if Some(id) == self.hir_id_low && !BreakAfterExprVisitor::is_found(self.cx, diag_expr_id) { self.span_low = Some(self.cx.tcx.hir().span(diag_expr_id)); } - if Some(id) == self.hir_id_high { + if Some(id) == self.hir_id_high && !BreakAfterExprVisitor::is_found(self.cx, diag_expr_id) { self.span_high = Some(self.cx.tcx.hir().span(diag_expr_id)); } } @@ -116,3 +123,52 @@ impl MutatePairDelegate<'_, '_> { (self.span_low, self.span_high) } } + +struct BreakAfterExprVisitor { + hir_id: HirId, + past_expr: bool, + past_candidate: bool, + break_after_expr: bool, +} + +impl BreakAfterExprVisitor { + pub fn is_found(cx: &LateContext<'_>, hir_id: HirId) -> bool { + let mut visitor = BreakAfterExprVisitor { + hir_id, + past_expr: false, + past_candidate: false, + break_after_expr: false, + }; + + get_enclosing_block(cx, hir_id).map_or(false, |block| { + visitor.visit_block(block); + visitor.break_after_expr + }) + } +} + +impl intravisit::Visitor<'tcx> for BreakAfterExprVisitor { + type Map = Map<'tcx>; + + fn nested_visit_map(&mut self) -> NestedVisitorMap { + NestedVisitorMap::None + } + + fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) { + if self.past_candidate { + return; + } + + if expr.hir_id == self.hir_id { + self.past_expr = true; + } else if self.past_expr { + if matches!(&expr.kind, ExprKind::Break(..)) { + self.break_after_expr = true; + } + + self.past_candidate = true; + } else { + intravisit::walk_expr(self, expr); + } + } +} diff --git a/src/tools/clippy/clippy_lints/src/loops/needless_collect.rs b/src/tools/clippy/clippy_lints/src/loops/needless_collect.rs index 51d7def137..e87f4b6691 100644 --- a/src/tools/clippy/clippy_lints/src/loops/needless_collect.rs +++ b/src/tools/clippy/clippy_lints/src/loops/needless_collect.rs @@ -26,11 +26,11 @@ fn check_needless_collect_direct_usage<'tcx>(expr: &'tcx Expr<'_>, cx: &LateCont if chain_method.ident.name == sym!(collect) && is_trait_method(cx, &args[0], sym::Iterator); then { let ty = cx.typeck_results().expr_ty(&args[0]); - let mut applicability = Applicability::MachineApplicable; + let mut applicability = Applicability::MaybeIncorrect; let is_empty_sugg = "next().is_none()".to_string(); let method_name = &*method.ident.name.as_str(); - let sugg = if is_type_diagnostic_item(cx, ty, sym::vec_type) || - is_type_diagnostic_item(cx, ty, sym::vecdeque_type) || + let sugg = if is_type_diagnostic_item(cx, ty, sym::Vec) || + is_type_diagnostic_item(cx, ty, sym::VecDeque) || is_type_diagnostic_item(cx, ty, sym::LinkedList) || is_type_diagnostic_item(cx, ty, sym::BinaryHeap) { match method_name { @@ -47,7 +47,7 @@ fn check_needless_collect_direct_usage<'tcx>(expr: &'tcx Expr<'_>, cx: &LateCont } } else if is_type_diagnostic_item(cx, ty, sym::BTreeMap) || - is_type_diagnostic_item(cx, ty, sym::hashmap_type) { + is_type_diagnostic_item(cx, ty, sym::HashMap) { match method_name { "is_empty" => is_empty_sugg, _ => return, @@ -79,8 +79,8 @@ fn check_needless_collect_indirect_usage<'tcx>(expr: &'tcx Expr<'_>, cx: &LateCo if let ExprKind::MethodCall(method_name, collect_span, &[ref iter_source], ..) = init_expr.kind; if method_name.ident.name == sym!(collect) && is_trait_method(cx, init_expr, sym::Iterator); let ty = cx.typeck_results().expr_ty(init_expr); - if is_type_diagnostic_item(cx, ty, sym::vec_type) || - is_type_diagnostic_item(cx, ty, sym::vecdeque_type) || + if is_type_diagnostic_item(cx, ty, sym::Vec) || + is_type_diagnostic_item(cx, ty, sym::VecDeque) || is_type_diagnostic_item(cx, ty, sym::BinaryHeap) || is_type_diagnostic_item(cx, ty, sym::LinkedList); if let Some(iter_calls) = detect_iter_and_into_iters(block, id); @@ -113,7 +113,7 @@ fn check_needless_collect_indirect_usage<'tcx>(expr: &'tcx Expr<'_>, cx: &LateCo (stmt.span, String::new()), (iter_call.span, iter_replacement) ], - Applicability::MachineApplicable,// MaybeIncorrect, + Applicability::MaybeIncorrect, ); }, ); diff --git a/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs b/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs index 3f77e7af92..172d9fc39a 100644 --- a/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs +++ b/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs @@ -2,10 +2,8 @@ use super::NEEDLESS_RANGE_LOOP; use clippy_utils::diagnostics::{multispan_sugg, span_lint_and_then}; use clippy_utils::source::snippet; use clippy_utils::ty::has_iter_method; -use clippy_utils::visitors::LocalUsedVisitor; -use clippy_utils::{ - contains_name, higher, is_integer_const, match_trait_method, path_to_local_id, paths, sugg, SpanlessEq, -}; +use clippy_utils::visitors::is_local_used; +use clippy_utils::{contains_name, higher, is_integer_const, match_trait_method, paths, sugg, SpanlessEq}; use if_chain::if_chain; use rustc_ast::ast; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; @@ -97,7 +95,7 @@ pub(super) fn check<'tcx>( let mut take_expr = end; if let ExprKind::Binary(ref op, left, right) = end.kind { - if let BinOpKind::Add = op.node { + if op.node == BinOpKind::Add { let start_equal_left = SpanlessEq::new(cx).eq_expr(start, left); let start_equal_right = SpanlessEq::new(cx).eq_expr(start, right); @@ -146,7 +144,7 @@ pub(super) fn check<'tcx>( span_lint_and_then( cx, NEEDLESS_RANGE_LOOP, - expr.span, + arg.span, &format!("the loop variable `{}` is used to index `{}`", ident.name, indexed), |diag| { multispan_sugg( @@ -172,7 +170,7 @@ pub(super) fn check<'tcx>( span_lint_and_then( cx, NEEDLESS_RANGE_LOOP, - expr.span, + arg.span, &format!("the loop variable `{}` is only used to index `{}`", ident.name, indexed), |diag| { multispan_sugg( @@ -256,43 +254,36 @@ impl<'a, 'tcx> VarVisitor<'a, 'tcx> { if let ExprKind::Path(ref seqpath) = seqexpr.kind; if let QPath::Resolved(None, seqvar) = *seqpath; if seqvar.segments.len() == 1; - let index_used_directly = path_to_local_id(idx, self.var); - let indexed_indirectly = { - let mut used_visitor = LocalUsedVisitor::new(self.cx, self.var); - walk_expr(&mut used_visitor, idx); - used_visitor.used - }; - if indexed_indirectly || index_used_directly; + if is_local_used(self.cx, idx, self.var); then { if self.prefer_mutable { self.indexed_mut.insert(seqvar.segments[0].ident.name); } + let index_used_directly = matches!(idx.kind, ExprKind::Path(_)); let res = self.cx.qpath_res(seqpath, seqexpr.hir_id); match res { Res::Local(hir_id) => { let parent_id = self.cx.tcx.hir().get_parent_item(expr.hir_id); let parent_def_id = self.cx.tcx.hir().local_def_id(parent_id); let extent = self.cx.tcx.region_scope_tree(parent_def_id).var_scope(hir_id.local_id); - if indexed_indirectly { - self.indexed_indirectly.insert(seqvar.segments[0].ident.name, Some(extent)); - } if index_used_directly { self.indexed_directly.insert( seqvar.segments[0].ident.name, (Some(extent), self.cx.typeck_results().node_type(seqexpr.hir_id)), ); + } else { + self.indexed_indirectly.insert(seqvar.segments[0].ident.name, Some(extent)); } return false; // no need to walk further *on the variable* } Res::Def(DefKind::Static | DefKind::Const, ..) => { - if indexed_indirectly { - self.indexed_indirectly.insert(seqvar.segments[0].ident.name, None); - } if index_used_directly { self.indexed_directly.insert( seqvar.segments[0].ident.name, (None, self.cx.typeck_results().node_type(seqexpr.hir_id)), ); + } else { + self.indexed_indirectly.insert(seqvar.segments[0].ident.name, None); } return false; // no need to walk further *on the variable* } @@ -310,10 +301,10 @@ impl<'a, 'tcx> Visitor<'tcx> for VarVisitor<'a, 'tcx> { fn visit_expr(&mut self, expr: &'tcx Expr<'_>) { if_chain! { // a range index op - if let ExprKind::MethodCall(meth, _, args, _) = expr.kind; + if let ExprKind::MethodCall(meth, _, [args_0, args_1, ..], _) = &expr.kind; if (meth.ident.name == sym::index && match_trait_method(self.cx, expr, &paths::INDEX)) || (meth.ident.name == sym::index_mut && match_trait_method(self.cx, expr, &paths::INDEX_MUT)); - if !self.check(&args[1], &args[0], expr); + if !self.check(args_1, args_0, expr); then { return } } 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 2c46971d5f..c0fde5e516 100644 --- a/src/tools/clippy/clippy_lints/src/loops/never_loop.rs +++ b/src/tools/clippy/clippy_lints/src/loops/never_loop.rs @@ -14,7 +14,7 @@ pub(super) fn check(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { NeverLoopResult::AlwaysBreak => { span_lint_and_then(cx, NEVER_LOOP, expr.span, "this loop never actually loops", |diag| { if_chain! { - if let LoopSource::ForLoop = source; + 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 { @@ -87,7 +87,7 @@ fn combine_branches(b1: NeverLoopResult, b2: NeverLoopResult) -> NeverLoopResult fn never_loop_block(block: &Block<'_>, main_loop_id: HirId) -> NeverLoopResult { let stmts = block.stmts.iter().map(stmt_to_expr); - let expr = once(block.expr.as_deref()); + let expr = once(block.expr); let mut iter = stmts.chain(expr).flatten(); never_loop_expr_seq(&mut iter, main_loop_id) } @@ -100,7 +100,7 @@ fn never_loop_expr_seq<'a, T: Iterator>>(es: &mut T, main_lo fn stmt_to_expr<'tcx>(stmt: &Stmt<'tcx>) -> Option<&'tcx Expr<'tcx>> { match stmt.kind { StmtKind::Semi(e, ..) | StmtKind::Expr(e, ..) => Some(e), - StmtKind::Local(local) => local.init.as_deref(), + StmtKind::Local(local) => local.init, StmtKind::Item(..) => None, } } diff --git a/src/tools/clippy/clippy_lints/src/loops/same_item_push.rs b/src/tools/clippy/clippy_lints/src/loops/same_item_push.rs index 545498a104..2eb247de9f 100644 --- a/src/tools/clippy/clippy_lints/src/loops/same_item_push.rs +++ b/src/tools/clippy/clippy_lints/src/loops/same_item_push.rs @@ -192,7 +192,7 @@ fn get_vec_push<'tcx>(cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) -> Option<(& if let Some(self_expr) = args.get(0); if let Some(pushed_item) = args.get(1); // Check that the method being called is push() on a Vec - if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(self_expr), sym::vec_type); + if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(self_expr), sym::Vec); if path.ident.name.as_str() == "push"; then { return Some((self_expr, pushed_item)) diff --git a/src/tools/clippy/clippy_lints/src/loops/utils.rs b/src/tools/clippy/clippy_lints/src/loops/utils.rs index 2f7360210b..f9f515cc40 100644 --- a/src/tools/clippy/clippy_lints/src/loops/utils.rs +++ b/src/tools/clippy/clippy_lints/src/loops/utils.rs @@ -338,7 +338,7 @@ pub(super) fn make_iterator_snippet(cx: &LateContext<'_>, arg: &Expr<'_>, applic sugg::Sugg::hir_with_applicability(cx, arg_inner, "_", applic_ref).maybe_par(), meth_name, ) - } + }, _ => format!( "{}.into_iter()", sugg::Sugg::hir_with_applicability(cx, arg, "_", applic_ref).maybe_par() diff --git a/src/tools/clippy/clippy_lints/src/loops/while_let_loop.rs b/src/tools/clippy/clippy_lints/src/loops/while_let_loop.rs index d6d3315e0a..4dcd5c8772 100644 --- a/src/tools/clippy/clippy_lints/src/loops/while_let_loop.rs +++ b/src/tools/clippy/clippy_lints/src/loops/while_let_loop.rs @@ -24,13 +24,13 @@ pub(super) fn check(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, loop_block: &' } } - if let ExprKind::Match(ref matchexpr, ref arms, MatchSource::Normal) = inner.kind { + if let ExprKind::Match(matchexpr, arms, MatchSource::Normal) = inner.kind { if arms.len() == 2 && arms[0].guard.is_none() && arms[1].guard.is_none() - && is_simple_break_expr(&arms[1].body) + && is_simple_break_expr(arms[1].body) { - could_be_while_let(cx, expr, &arms[0].pat, matchexpr); + could_be_while_let(cx, expr, arms[0].pat, matchexpr); } } } @@ -65,7 +65,7 @@ fn extract_first_expr<'tcx>(block: &Block<'tcx>) -> Option<&'tcx Expr<'tcx>> { fn is_simple_break_expr(expr: &Expr<'_>) -> bool { match expr.kind { ExprKind::Break(dest, ref passed_expr) if dest.label.is_none() && passed_expr.is_none() => true, - ExprKind::Block(b, _) => extract_first_expr(b).map_or(false, |subexpr| is_simple_break_expr(subexpr)), + ExprKind::Block(b, _) => extract_first_expr(b).map_or(false, is_simple_break_expr), _ => false, } } diff --git a/src/tools/clippy/clippy_lints/src/loops/while_let_on_iterator.rs b/src/tools/clippy/clippy_lints/src/loops/while_let_on_iterator.rs index 0757d32912..b390476a66 100644 --- a/src/tools/clippy/clippy_lints/src/loops/while_let_on_iterator.rs +++ b/src/tools/clippy/clippy_lints/src/loops/while_let_on_iterator.rs @@ -8,18 +8,13 @@ use clippy_utils::{ use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::intravisit::{walk_expr, ErasedMap, NestedVisitorMap, Visitor}; -use rustc_hir::{def::Res, Expr, ExprKind, HirId, Local, Mutability, PatKind, QPath, UnOp}; +use rustc_hir::{def::Res, Expr, ExprKind, HirId, Local, PatKind, QPath, UnOp}; use rustc_lint::LateContext; use rustc_span::{symbol::sym, Span, Symbol}; pub(super) fn check(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { let (scrutinee_expr, iter_expr, some_pat, loop_expr) = if_chain! { - if let Some(higher::WhileLet { - if_then, - let_pat, - let_expr, - .. - }) = higher::WhileLet::hir(expr); + if let Some(higher::WhileLet { if_then, let_pat, let_expr }) = higher::WhileLet::hir(expr); // check for `Some(..)` pattern if let PatKind::TupleStruct(QPath::Resolved(None, pat_path), some_pat, _) = let_pat.kind; if let Res::Def(_, pat_did) = pat_path.res; @@ -52,13 +47,8 @@ pub(super) fn check(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { // If the iterator is a field or the iterator is accessed after the loop is complete it needs to be // borrowed mutably. TODO: If the struct can be partially moved from and the struct isn't used // afterwards a mutable borrow of a field isn't necessary. - let ref_mut = if !iter_expr.fields.is_empty() || needs_mutable_borrow(cx, &iter_expr, loop_expr) { - if cx.typeck_results().node_type(iter_expr.hir_id).ref_mutability() == Some(Mutability::Mut) { - // Reborrow for mutable references. It may not be possible to get a mutable reference here. - "&mut *" - } else { - "&mut " - } + let by_ref = if !iter_expr.fields.is_empty() || needs_mutable_borrow(cx, &iter_expr, loop_expr) { + ".by_ref()" } else { "" }; @@ -70,7 +60,7 @@ pub(super) fn check(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { expr.span.with_hi(scrutinee_expr.span.hi()), "this loop could be written as a `for` loop", "try", - format!("for {} in {}{}", loop_var, ref_mut, iterator), + format!("for {} in {}{}", loop_var, iterator, by_ref), applicability, ); } @@ -79,8 +69,6 @@ pub(super) fn check(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { struct IterExpr { /// The span of the whole expression, not just the path and fields stored here. span: Span, - /// The HIR id of the whole expression, not just the path and fields stored here. - hir_id: HirId, /// The fields used, in order of child to parent. fields: Vec, /// The path being used. @@ -91,14 +79,12 @@ struct IterExpr { /// the expression might have side effects. fn try_parse_iter_expr(cx: &LateContext<'_>, mut e: &Expr<'_>) -> Option { let span = e.span; - let hir_id = e.hir_id; let mut fields = Vec::new(); loop { match e.kind { ExprKind::Path(ref path) => { break Some(IterExpr { span, - hir_id, fields, path: cx.qpath_res(path, e.hir_id), }); diff --git a/src/tools/clippy/clippy_lints/src/macro_use.rs b/src/tools/clippy/clippy_lints/src/macro_use.rs index 39f7ade3f8..c38162743a 100644 --- a/src/tools/clippy/clippy_lints/src/macro_use.rs +++ b/src/tools/clippy/clippy_lints/src/macro_use.rs @@ -29,37 +29,21 @@ declare_clippy_lint! { "#[macro_use] is no longer needed" } -const BRACKETS: &[char] = &['<', '>']; - #[derive(Clone, Debug, PartialEq, Eq)] struct PathAndSpan { path: String, span: Span, } -/// `MacroRefData` includes the name of the macro -/// and the path from `SourceMap::span_to_filename`. +/// `MacroRefData` includes the name of the macro. #[derive(Debug, Clone)] pub struct MacroRefData { name: String, - path: String, } impl MacroRefData { - pub fn new(name: String, callee: Span, cx: &LateContext<'_>) -> Self { - let sm = cx.sess().source_map(); - let mut path = sm.filename_for_diagnostics(&sm.span_to_filename(callee)) - .to_string(); - - // std lib paths are <::std::module::file type> - // so remove brackets, space and type. - if path.contains('<') { - path = path.replace(BRACKETS, ""); - } - if path.contains(' ') { - path = path.split(' ').next().unwrap().to_string(); - } - Self { name, path } + pub fn new(name: String) -> Self { + Self { name } } } @@ -79,29 +63,24 @@ impl MacroUseImports { fn push_unique_macro(&mut self, cx: &LateContext<'_>, span: Span) { let call_site = span.source_callsite(); let name = snippet(cx, cx.sess().source_map().span_until_char(call_site, '!'), "_"); - if let Some(callee) = span.source_callee() { - if !self.collected.contains(&call_site) { - let name = if name.contains("::") { - name.split("::").last().unwrap().to_string() - } else { - name.to_string() - }; + if span.source_callee().is_some() && !self.collected.contains(&call_site) { + let name = if name.contains("::") { + name.split("::").last().unwrap().to_string() + } else { + name.to_string() + }; - self.mac_refs.push(MacroRefData::new(name, callee.def_site, cx)); - self.collected.insert(call_site); - } + self.mac_refs.push(MacroRefData::new(name)); + self.collected.insert(call_site); } } fn push_unique_macro_pat_ty(&mut self, cx: &LateContext<'_>, span: Span) { let call_site = span.source_callsite(); let name = snippet(cx, cx.sess().source_map().span_until_char(call_site, '!'), "_"); - if let Some(callee) = span.source_callee() { - if !self.collected.contains(&call_site) { - self.mac_refs - .push(MacroRefData::new(name.to_string(), callee.def_site, cx)); - self.collected.insert(call_site); - } + if span.source_callee().is_some() && !self.collected.contains(&call_site) { + self.mac_refs.push(MacroRefData::new(name.to_string())); + self.collected.insert(call_site); } } } @@ -156,7 +135,7 @@ impl<'tcx> LateLintPass<'tcx> for MacroUseImports { } } #[allow(clippy::too_many_lines)] - fn check_crate_post(&mut self, cx: &LateContext<'_>, _krate: &hir::Crate<'_>) { + fn check_crate_post(&mut self, cx: &LateContext<'_>) { let mut used = FxHashMap::default(); let mut check_dup = vec![]; for (import, span) in &self.imports { diff --git a/src/tools/clippy/clippy_lints/src/main_recursion.rs b/src/tools/clippy/clippy_lints/src/main_recursion.rs index 776e4b3fe7..23b3ba2296 100644 --- a/src/tools/clippy/clippy_lints/src/main_recursion.rs +++ b/src/tools/clippy/clippy_lints/src/main_recursion.rs @@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint_and_help; use clippy_utils::source::snippet; use clippy_utils::{is_entrypoint_fn, is_no_std_crate}; use if_chain::if_chain; -use rustc_hir::{Crate, Expr, ExprKind, QPath}; +use rustc_hir::{Expr, ExprKind, QPath}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_tool_lint, impl_lint_pass}; @@ -33,7 +33,7 @@ pub struct MainRecursion { impl_lint_pass!(MainRecursion => [MAIN_RECURSION]); impl LateLintPass<'_> for MainRecursion { - fn check_crate(&mut self, cx: &LateContext<'_>, _: &Crate<'_>) { + fn check_crate(&mut self, cx: &LateContext<'_>) { self.has_no_std_attr = is_no_std_crate(cx); } diff --git a/src/tools/clippy/clippy_lints/src/manual_assert.rs b/src/tools/clippy/clippy_lints/src/manual_assert.rs new file mode 100644 index 0000000000..42c679e364 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/manual_assert.rs @@ -0,0 +1,99 @@ +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::higher::PanicExpn; +use clippy_utils::source::snippet_with_applicability; +use clippy_utils::{is_expn_of, sugg}; +use rustc_errors::Applicability; +use rustc_hir::{Block, Expr, ExprKind, StmtKind, UnOp}; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_session::{declare_lint_pass, declare_tool_lint}; + +declare_clippy_lint! { + /// ### What it does + /// Detects `if`-then-`panic!` that can be replaced with `assert!`. + /// + /// ### Why is this bad? + /// `assert!` is simpler than `if`-then-`panic!`. + /// + /// ### Example + /// ```rust + /// let sad_people: Vec<&str> = vec![]; + /// if !sad_people.is_empty() { + /// panic!("there are sad people: {:?}", sad_people); + /// } + /// ``` + /// Use instead: + /// ```rust + /// let sad_people: Vec<&str> = vec![]; + /// assert!(sad_people.is_empty(), "there are sad people: {:?}", sad_people); + /// ``` + pub MANUAL_ASSERT, + pedantic, + "`panic!` and only a `panic!` in `if`-then statement" +} + +declare_lint_pass!(ManualAssert => [MANUAL_ASSERT]); + +impl LateLintPass<'_> for ManualAssert { + fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) { + if_chain! { + if let Expr { + kind: ExprKind:: If(cond, Expr { + kind: ExprKind::Block( + Block { + stmts: [stmt], + .. + }, + _), + .. + }, None), + .. + } = &expr; + if is_expn_of(stmt.span, "panic").is_some(); + if !matches!(cond.kind, ExprKind::Let(_, _, _)); + if let StmtKind::Semi(semi) = stmt.kind; + if !cx.tcx.sess.source_map().is_multiline(cond.span); + + then { + let span = if let Some(panic_expn) = PanicExpn::parse(semi) { + 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_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 + } + } + }; + let mut applicability = Applicability::MachineApplicable; + let sugg = snippet_with_applicability(cx, span, "..", &mut applicability); + let cond_sugg = if let ExprKind::DropTemps(e, ..) = cond.kind { + 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()) + } + } else { + format!("!{}", sugg::Sugg::hir_with_applicability(cx, cond, "..", &mut applicability).maybe_par().to_string()) + }; + + span_lint_and_sugg( + cx, + MANUAL_ASSERT, + expr.span, + "only a `panic!` in `if`-then statement", + "try", + format!("assert!({}, {});", cond_sugg, sugg), + Applicability::MachineApplicable, + ); + } + } + } +} diff --git a/src/tools/clippy/clippy_lints/src/manual_async_fn.rs b/src/tools/clippy/clippy_lints/src/manual_async_fn.rs index 8e1385fb83..b632af455f 100644 --- a/src/tools/clippy/clippy_lints/src/manual_async_fn.rs +++ b/src/tools/clippy/clippy_lints/src/manual_async_fn.rs @@ -49,7 +49,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualAsyncFn { ) { if_chain! { if let Some(header) = kind.header(); - if let IsAsync::NotAsync = header.asyncness; + if header.asyncness == IsAsync::NotAsync; // Check that this function returns `impl Future` if let FnRetTy::Return(ret_ty) = decl.output; if let Some((trait_ref, output_lifetimes)) = future_trait_ref(cx, ret_ty); @@ -178,7 +178,7 @@ fn desugared_async_block<'tcx>(cx: &LateContext<'tcx>, block: &'tcx Block<'tcx>) if args.len() == 1; if let Expr{kind: ExprKind::Closure(_, _, body_id, ..), ..} = args[0]; let closure_body = cx.tcx.hir().body(body_id); - if let Some(GeneratorKind::Async(AsyncGeneratorKind::Block)) = closure_body.generator_kind; + if closure_body.generator_kind == Some(GeneratorKind::Async(AsyncGeneratorKind::Block)); then { return Some(closure_body); } diff --git a/src/tools/clippy/clippy_lints/src/manual_map.rs b/src/tools/clippy/clippy_lints/src/manual_map.rs index 161d884149..96df3d0a49 100644 --- a/src/tools/clippy/clippy_lints/src/manual_map.rs +++ b/src/tools/clippy/clippy_lints/src/manual_map.rs @@ -1,16 +1,18 @@ use crate::{map_unit_fn::OPTION_MAP_UNIT_FN, matches::MATCH_AS_REF}; use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::higher; +use clippy_utils::higher::IfLetOrMatch; use clippy_utils::source::{snippet_with_applicability, snippet_with_context}; use clippy_utils::ty::{is_type_diagnostic_item, peel_mid_ty_refs_is_mutable}; use clippy_utils::{ can_move_expr_to_closure, in_constant, is_else_clause, is_lang_ctor, is_lint_allowed, path_to_local_id, - peel_hir_expr_refs, + peel_hir_expr_refs, peel_hir_expr_while, CaptureKind, }; use rustc_ast::util::parser::PREC_POSTFIX; use rustc_errors::Applicability; use rustc_hir::LangItem::{OptionNone, OptionSome}; -use rustc_hir::{Arm, BindingAnnotation, Block, Expr, ExprKind, HirId, Mutability, Pat, PatKind}; +use rustc_hir::{ + def::Res, Arm, BindingAnnotation, Block, Expr, ExprKind, HirId, Mutability, Pat, PatKind, Path, QPath, +}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; use rustc_session::{declare_lint_pass, declare_tool_lint}; @@ -44,168 +46,169 @@ declare_lint_pass!(ManualMap => [MANUAL_MAP]); impl LateLintPass<'_> for ManualMap { #[allow(clippy::too_many_lines)] fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { - if let Some(higher::IfLet { - let_pat, - let_expr, - if_then, - if_else: Some(if_else), - }) = higher::IfLet::hir(cx, expr) - { - manage_lint(cx, expr, (&let_pat.kind, if_then), (&PatKind::Wild, if_else), let_expr); - } - - if let ExprKind::Match(scrutinee, [then @ Arm { guard: None, .. }, r#else @ Arm { guard: None, .. }], _) = - expr.kind - { - manage_lint( - cx, - expr, - (&then.pat.kind, then.body), - (&r#else.pat.kind, r#else.body), + let (scrutinee, then_pat, then_body, else_pat, else_body) = match IfLetOrMatch::parse(cx, expr) { + Some(IfLetOrMatch::IfLet(scrutinee, pat, body, Some(r#else))) => (scrutinee, pat, body, None, r#else), + Some(IfLetOrMatch::Match( scrutinee, - ); + [arm1 @ Arm { guard: None, .. }, arm2 @ Arm { guard: None, .. }], + _, + )) => (scrutinee, arm1.pat, arm1.body, Some(arm2.pat), arm2.body), + _ => return, + }; + if in_external_macro(cx.sess(), expr.span) || in_constant(cx, expr.hir_id) { + return; } - } -} -fn manage_lint<'tcx>( - cx: &LateContext<'tcx>, - expr: &'tcx Expr<'_>, - then: (&'tcx PatKind<'_>, &'tcx Expr<'_>), - r#else: (&'tcx PatKind<'_>, &'tcx Expr<'_>), - scrut: &'tcx Expr<'_>, -) { - if in_external_macro(cx.sess(), expr.span) || in_constant(cx, expr.hir_id) { - return; - } + let (scrutinee_ty, ty_ref_count, ty_mutability) = + peel_mid_ty_refs_is_mutable(cx.typeck_results().expr_ty(scrutinee)); + if !(is_type_diagnostic_item(cx, scrutinee_ty, sym::Option) + && is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(expr), sym::Option)) + { + return; + } - let (scrutinee_ty, ty_ref_count, ty_mutability) = peel_mid_ty_refs_is_mutable(cx.typeck_results().expr_ty(scrut)); - if !(is_type_diagnostic_item(cx, scrutinee_ty, sym::option_type) - && is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(expr), sym::option_type)) - { - return; - } - - let (then_pat, then_expr) = then; - let (else_pat, else_expr) = r#else; - - let expr_ctxt = expr.span.ctxt(); - let (some_expr, some_pat, pat_ref_count, is_wild_none) = match ( - try_parse_pattern(cx, then_pat, expr_ctxt), - try_parse_pattern(cx, else_pat, expr_ctxt), - ) { - (Some(OptionPat::Wild), Some(OptionPat::Some { pattern, ref_count })) if is_none_expr(cx, then_expr) => { - (else_expr, pattern, ref_count, true) - }, - (Some(OptionPat::None), Some(OptionPat::Some { pattern, ref_count })) if is_none_expr(cx, then_expr) => { - (else_expr, pattern, ref_count, false) - }, - (Some(OptionPat::Some { pattern, ref_count }), Some(OptionPat::Wild)) if is_none_expr(cx, else_expr) => { - (then_expr, pattern, ref_count, true) - }, - (Some(OptionPat::Some { pattern, ref_count }), Some(OptionPat::None)) if is_none_expr(cx, else_expr) => { - (then_expr, pattern, ref_count, false) - }, - _ => return, - }; - - // Top level or patterns aren't allowed in closures. - if matches!(some_pat.kind, PatKind::Or(_)) { - return; - } - - let some_expr = match get_some_expr(cx, some_expr, expr_ctxt) { - Some(expr) => expr, - None => return, - }; - - if cx.typeck_results().expr_ty(some_expr) == cx.tcx.types.unit && !is_lint_allowed(cx, OPTION_MAP_UNIT_FN, expr.hir_id) { - return; - } - - // `map` won't perform any adjustments. - if !cx.typeck_results().expr_adjustments(some_expr).is_empty() { - return; - } - - if !can_move_expr_to_closure(cx, some_expr) { - return; - } - - // Determine which binding mode to use. - let explicit_ref = some_pat.contains_explicit_ref_binding(); - let binding_ref = explicit_ref.or_else(|| (ty_ref_count != pat_ref_count).then(|| ty_mutability)); - - let as_ref_str = match binding_ref { - Some(Mutability::Mut) => ".as_mut()", - Some(Mutability::Not) => ".as_ref()", - None => "", - }; - - let mut app = Applicability::MachineApplicable; - - // Remove address-of expressions from the scrutinee. Either `as_ref` will be called, or - // it's being passed by value. - let scrutinee = peel_hir_expr_refs(scrut).0; - let (scrutinee_str, _) = snippet_with_context(cx, scrutinee.span, expr_ctxt, "..", &mut app); - let scrutinee_str = if scrutinee.span.ctxt() == expr.span.ctxt() && scrutinee.precedence().order() < PREC_POSTFIX { - format!("({})", scrutinee_str) - } else { - scrutinee_str.into() - }; - - let body_str = if let PatKind::Binding(annotation, id, some_binding, None) = some_pat.kind { - match can_pass_as_func(cx, id, some_expr) { - Some(func) if func.span.ctxt() == some_expr.span.ctxt() => { - snippet_with_applicability(cx, func.span, "..", &mut app).into_owned() + let expr_ctxt = expr.span.ctxt(); + let (some_expr, some_pat, pat_ref_count, is_wild_none) = match ( + try_parse_pattern(cx, then_pat, expr_ctxt), + else_pat.map_or(Some(OptionPat::Wild), |p| try_parse_pattern(cx, p, expr_ctxt)), + ) { + (Some(OptionPat::Wild), Some(OptionPat::Some { pattern, ref_count })) if is_none_expr(cx, then_body) => { + (else_body, pattern, ref_count, true) }, - _ => { - if path_to_local_id(some_expr, id) - && !is_lint_allowed(cx, MATCH_AS_REF, expr.hir_id) - && binding_ref.is_some() - { - return; + (Some(OptionPat::None), Some(OptionPat::Some { pattern, ref_count })) if is_none_expr(cx, then_body) => { + (else_body, pattern, ref_count, false) + }, + (Some(OptionPat::Some { pattern, ref_count }), Some(OptionPat::Wild)) if is_none_expr(cx, else_body) => { + (then_body, pattern, ref_count, true) + }, + (Some(OptionPat::Some { pattern, ref_count }), Some(OptionPat::None)) if is_none_expr(cx, else_body) => { + (then_body, pattern, ref_count, false) + }, + _ => return, + }; + + // Top level or patterns aren't allowed in closures. + if matches!(some_pat.kind, PatKind::Or(_)) { + return; + } + + let some_expr = match get_some_expr(cx, some_expr, expr_ctxt) { + Some(expr) => expr, + None => return, + }; + + // These two lints will go back and forth with each other. + if cx.typeck_results().expr_ty(some_expr) == cx.tcx.types.unit + && !is_lint_allowed(cx, OPTION_MAP_UNIT_FN, expr.hir_id) + { + return; + } + + // `map` won't perform any adjustments. + if !cx.typeck_results().expr_adjustments(some_expr).is_empty() { + return; + } + + // Determine which binding mode to use. + let explicit_ref = some_pat.contains_explicit_ref_binding(); + let binding_ref = explicit_ref.or_else(|| (ty_ref_count != pat_ref_count).then(|| ty_mutability)); + + let as_ref_str = match binding_ref { + Some(Mutability::Mut) => ".as_mut()", + Some(Mutability::Not) => ".as_ref()", + None => "", + }; + + match can_move_expr_to_closure(cx, some_expr) { + Some(captures) => { + // Check if captures the closure will need conflict with borrows made in the scrutinee. + // TODO: check all the references made in the scrutinee expression. This will require interacting + // with the borrow checker. Currently only `[.]*` is checked for. + if let Some(binding_ref_mutability) = binding_ref { + let e = peel_hir_expr_while(scrutinee, |e| match e.kind { + ExprKind::Field(e, _) | ExprKind::AddrOf(_, _, e) => Some(e), + _ => None, + }); + if let ExprKind::Path(QPath::Resolved(None, Path { res: Res::Local(l), .. })) = e.kind { + match captures.get(l) { + Some(CaptureKind::Value | CaptureKind::Ref(Mutability::Mut)) => return, + Some(CaptureKind::Ref(Mutability::Not)) if binding_ref_mutability == Mutability::Mut => { + return; + }, + Some(CaptureKind::Ref(Mutability::Not)) | None => (), + } + } } - - // `ref` and `ref mut` annotations were handled earlier. - let annotation = if matches!(annotation, BindingAnnotation::Mutable) { - "mut " - } else { - "" - }; - format!( - "|{}{}| {}", - annotation, - some_binding, - snippet_with_context(cx, some_expr.span, expr_ctxt, "..", &mut app).0 - ) }, - } - } else if !is_wild_none && explicit_ref.is_none() { - // TODO: handle explicit reference annotations. - format!( - "|{}| {}", - snippet_with_context(cx, some_pat.span, expr_ctxt, "..", &mut app).0, - snippet_with_context(cx, some_expr.span, expr_ctxt, "..", &mut app).0 - ) - } else { - // Refutable bindings and mixed reference annotations can't be handled by `map`. - return; - }; + None => return, + }; - span_lint_and_sugg( - cx, - MANUAL_MAP, - expr.span, - "manual implementation of `Option::map`", - "try this", - if is_else_clause(cx.tcx, expr) { - format!("{{ {}{}.map({}) }}", scrutinee_str, as_ref_str, body_str) + let mut app = Applicability::MachineApplicable; + + // Remove address-of expressions from the scrutinee. Either `as_ref` will be called, or + // it's being passed by value. + let scrutinee = peel_hir_expr_refs(scrutinee).0; + let (scrutinee_str, _) = snippet_with_context(cx, scrutinee.span, expr_ctxt, "..", &mut app); + let scrutinee_str = + if scrutinee.span.ctxt() == expr.span.ctxt() && scrutinee.precedence().order() < PREC_POSTFIX { + format!("({})", scrutinee_str) + } else { + scrutinee_str.into() + }; + + let body_str = if let PatKind::Binding(annotation, id, some_binding, None) = some_pat.kind { + match can_pass_as_func(cx, id, some_expr) { + Some(func) if func.span.ctxt() == some_expr.span.ctxt() => { + snippet_with_applicability(cx, func.span, "..", &mut app).into_owned() + }, + _ => { + if path_to_local_id(some_expr, id) + && !is_lint_allowed(cx, MATCH_AS_REF, expr.hir_id) + && binding_ref.is_some() + { + return; + } + + // `ref` and `ref mut` annotations were handled earlier. + let annotation = if matches!(annotation, BindingAnnotation::Mutable) { + "mut " + } else { + "" + }; + format!( + "|{}{}| {}", + annotation, + some_binding, + snippet_with_context(cx, some_expr.span, expr_ctxt, "..", &mut app).0 + ) + }, + } + } else if !is_wild_none && explicit_ref.is_none() { + // TODO: handle explicit reference annotations. + format!( + "|{}| {}", + snippet_with_context(cx, some_pat.span, expr_ctxt, "..", &mut app).0, + snippet_with_context(cx, some_expr.span, expr_ctxt, "..", &mut app).0 + ) } else { - format!("{}{}.map({})", scrutinee_str, as_ref_str, body_str) - }, - app, - ); + // Refutable bindings and mixed reference annotations can't be handled by `map`. + return; + }; + + span_lint_and_sugg( + cx, + MANUAL_MAP, + expr.span, + "manual implementation of `Option::map`", + "try this", + if else_pat.is_none() && is_else_clause(cx.tcx, expr) { + format!("{{ {}{}.map({}) }}", scrutinee_str, as_ref_str, body_str) + } else { + format!("{}{}.map({})", scrutinee_str, as_ref_str, body_str) + }, + app, + ); + } } // Checks whether the expression could be passed as a function, or whether a closure is needed. @@ -213,7 +216,7 @@ fn manage_lint<'tcx>( fn can_pass_as_func(cx: &LateContext<'tcx>, binding: HirId, expr: &'tcx Expr<'_>) -> Option<&'tcx Expr<'tcx>> { match expr.kind { ExprKind::Call(func, [arg]) - if path_to_local_id (arg, binding) && cx.typeck_results().expr_adjustments(arg).is_empty() => + if path_to_local_id(arg, binding) && cx.typeck_results().expr_adjustments(arg).is_empty() => { Some(func) }, @@ -235,28 +238,21 @@ enum OptionPat<'a> { // Try to parse into a recognized `Option` pattern. // i.e. `_`, `None`, `Some(..)`, or a reference to any of those. -fn try_parse_pattern( - cx: &LateContext<'tcx>, - pat_kind: &'tcx PatKind<'_>, - ctxt: SyntaxContext, -) -> Option> { - fn f( - cx: &LateContext<'tcx>, - pat_kind: &'tcx PatKind<'_>, - ref_count: usize, - ctxt: SyntaxContext, - ) -> Option> { - match pat_kind { +fn try_parse_pattern(cx: &LateContext<'tcx>, pat: &'tcx Pat<'_>, ctxt: SyntaxContext) -> Option> { + fn f(cx: &LateContext<'tcx>, pat: &'tcx Pat<'_>, ref_count: usize, ctxt: SyntaxContext) -> Option> { + match pat.kind { PatKind::Wild => Some(OptionPat::Wild), - PatKind::Ref(ref_pat, _) => f(cx, &ref_pat.kind, ref_count + 1, ctxt), + PatKind::Ref(pat, _) => f(cx, pat, ref_count + 1, ctxt), PatKind::Path(ref qpath) if is_lang_ctor(cx, qpath, OptionNone) => Some(OptionPat::None), - PatKind::TupleStruct(ref qpath, [pattern], _) if is_lang_ctor(cx, qpath, OptionSome) => { + PatKind::TupleStruct(ref qpath, [pattern], _) + if is_lang_ctor(cx, qpath, OptionSome) && pat.span.ctxt() == ctxt => + { Some(OptionPat::Some { pattern, ref_count }) }, _ => None, } } - f(cx, pat_kind, 0, ctxt) + f(cx, pat, 0, ctxt) } // Checks for an expression wrapped by the `Some` constructor. Returns the contained expression. diff --git a/src/tools/clippy/clippy_lints/src/manual_ok_or.rs b/src/tools/clippy/clippy_lints/src/manual_ok_or.rs index b2f287af69..cf641d0ce8 100644 --- a/src/tools/clippy/clippy_lints/src/manual_ok_or.rs +++ b/src/tools/clippy/clippy_lints/src/manual_ok_or.rs @@ -51,7 +51,7 @@ impl LateLintPass<'_> for ManualOkOr { if args.len() == 3; let method_receiver = &args[0]; let ty = cx.typeck_results().expr_ty(method_receiver); - if is_type_diagnostic_item(cx, ty, sym::option_type); + if is_type_diagnostic_item(cx, ty, sym::Option); let or_expr = &args[1]; if is_ok_wrapping(cx, &args[2]); if let ExprKind::Call(Expr { kind: ExprKind::Path(err_path), .. }, &[ref err_arg]) = or_expr.kind; 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 426789742d..2ae9cb4f9c 100644 --- a/src/tools/clippy/clippy_lints/src/manual_unwrap_or.rs +++ b/src/tools/clippy/clippy_lints/src/manual_unwrap_or.rs @@ -82,9 +82,9 @@ fn lint_manual_unwrap_or<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { if_chain! { if let ExprKind::Match(scrutinee, match_arms, _) = expr.kind; let ty = cx.typeck_results().expr_ty(scrutinee); - if let Some(ty_name) = if is_type_diagnostic_item(cx, ty, sym::option_type) { + if let Some(ty_name) = if is_type_diagnostic_item(cx, ty, sym::Option) { Some("Option") - } else if is_type_diagnostic_item(cx, ty, sym::result_type) { + } else if is_type_diagnostic_item(cx, ty, sym::Result) { Some("Result") } else { None diff --git a/src/tools/clippy/clippy_lints/src/map_clone.rs b/src/tools/clippy/clippy_lints/src/map_clone.rs index 394606200b..7db5c7e52e 100644 --- a/src/tools/clippy/clippy_lints/src/map_clone.rs +++ b/src/tools/clippy/clippy_lints/src/map_clone.rs @@ -55,7 +55,7 @@ impl<'tcx> LateLintPass<'tcx> for MapClone { if args.len() == 2; if method.ident.name == sym::map; let ty = cx.typeck_results().expr_ty(&args[0]); - if is_type_diagnostic_item(cx, ty, sym::option_type) || is_trait_method(cx, e, sym::Iterator); + if is_type_diagnostic_item(cx, ty, sym::Option) || is_trait_method(cx, e, sym::Iterator); if let hir::ExprKind::Closure(_, _, body_id, _, _) = args[1].kind; then { let closure_body = cx.tcx.hir().body(body_id); diff --git a/src/tools/clippy/clippy_lints/src/map_unit_fn.rs b/src/tools/clippy/clippy_lints/src/map_unit_fn.rs index fd40590d07..40de9ffcd4 100644 --- a/src/tools/clippy/clippy_lints/src/map_unit_fn.rs +++ b/src/tools/clippy/clippy_lints/src/map_unit_fn.rs @@ -205,14 +205,13 @@ fn suggestion_msg(function_type: &str, map_type: &str) -> String { fn lint_map_unit_fn(cx: &LateContext<'_>, stmt: &hir::Stmt<'_>, expr: &hir::Expr<'_>, map_args: &[hir::Expr<'_>]) { let var_arg = &map_args[0]; - let (map_type, variant, lint) = - if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(var_arg), sym::option_type) { - ("Option", "Some", OPTION_MAP_UNIT_FN) - } else if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(var_arg), sym::result_type) { - ("Result", "Ok", RESULT_MAP_UNIT_FN) - } else { - return; - }; + let (map_type, variant, lint) = if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(var_arg), sym::Option) { + ("Option", "Some", OPTION_MAP_UNIT_FN) + } else if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(var_arg), sym::Result) { + ("Result", "Ok", RESULT_MAP_UNIT_FN) + } else { + return; + }; let fn_arg = &map_args[1]; if is_unit_function(cx, fn_arg) { diff --git a/src/tools/clippy/clippy_lints/src/match_on_vec_items.rs b/src/tools/clippy/clippy_lints/src/match_on_vec_items.rs index e66a35452f..552c9a5889 100644 --- a/src/tools/clippy/clippy_lints/src/match_on_vec_items.rs +++ b/src/tools/clippy/clippy_lints/src/match_on_vec_items.rs @@ -93,7 +93,7 @@ fn is_vec_indexing<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> Opti fn is_vector(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { let ty = cx.typeck_results().expr_ty(expr); let ty = ty.peel_refs(); - is_type_diagnostic_item(cx, ty, sym::vec_type) + is_type_diagnostic_item(cx, ty, sym::Vec) } fn is_full_range(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { diff --git a/src/tools/clippy/clippy_lints/src/if_let_some_result.rs b/src/tools/clippy/clippy_lints/src/match_result_ok.rs similarity index 58% rename from src/tools/clippy/clippy_lints/src/if_let_some_result.rs rename to src/tools/clippy/clippy_lints/src/match_result_ok.rs index fb5637fcec..3db1f0421e 100644 --- a/src/tools/clippy/clippy_lints/src/if_let_some_result.rs +++ b/src/tools/clippy/clippy_lints/src/match_result_ok.rs @@ -12,58 +12,71 @@ use rustc_span::sym; declare_clippy_lint! { /// ### What it does - ///* Checks for unnecessary `ok()` in if let. + /// Checks for unnecessary `ok()` in `while let`. /// /// ### Why is this bad? - /// Calling `ok()` in if let is unnecessary, instead match + /// Calling `ok()` in `while let` is unnecessary, instead match /// on `Ok(pat)` /// /// ### Example /// ```ignore - /// for i in iter { - /// if let Some(value) = i.parse().ok() { - /// vec.push(value) - /// } + /// while let Some(value) = iter.next().ok() { + /// vec.push(value) /// } - /// ``` - /// Could be written: /// - /// ```ignore - /// for i in iter { - /// if let Ok(value) = i.parse() { - /// vec.push(value) - /// } + /// if let Some(valie) = iter.next().ok() { + /// vec.push(value) /// } /// ``` - pub IF_LET_SOME_RESULT, + /// Use instead: + /// ```ignore + /// while let Ok(value) = iter.next() { + /// vec.push(value) + /// } + /// + /// if let Ok(value) = iter.next() { + /// vec.push_value) + /// } + /// ``` + pub MATCH_RESULT_OK, style, - "usage of `ok()` in `if let Some(pat)` statements is unnecessary, match on `Ok(pat)` instead" + "usage of `ok()` in `let Some(pat)` statements is unnecessary, match on `Ok(pat)` instead" } -declare_lint_pass!(OkIfLet => [IF_LET_SOME_RESULT]); +declare_lint_pass!(MatchResultOk => [MATCH_RESULT_OK]); -impl<'tcx> LateLintPass<'tcx> for OkIfLet { +impl<'tcx> LateLintPass<'tcx> for MatchResultOk { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { - if_chain! { //begin checking variables - if let Some(higher::IfLet { let_pat, let_expr, .. }) = higher::IfLet::hir(cx, expr); - if let ExprKind::MethodCall(_, ok_span, ref result_types, _) = let_expr.kind; //check is expr.ok() has type Result.ok(, _) - if let PatKind::TupleStruct(QPath::Resolved(_, ref x), ref y, _) = let_pat.kind; //get operation + let (let_pat, let_expr, ifwhile) = + if let Some(higher::IfLet { let_pat, let_expr, .. }) = higher::IfLet::hir(cx, expr) { + (let_pat, let_expr, "if") + } else if let Some(higher::WhileLet { let_pat, let_expr, .. }) = higher::WhileLet::hir(expr) { + (let_pat, let_expr, "while") + } else { + return; + }; + + if_chain! { + if let ExprKind::MethodCall(_, ok_span, [ref result_types_0, ..], _) = let_expr.kind; //check is expr.ok() has type Result.ok(, _) + if let PatKind::TupleStruct(QPath::Resolved(_, x), y, _) = let_pat.kind; //get operation if method_chain_args(let_expr, &["ok"]).is_some(); //test to see if using ok() methoduse std::marker::Sized; - if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(&result_types[0]), sym::result_type); + if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(result_types_0), sym::Result); if rustc_hir_pretty::to_string(rustc_hir_pretty::NO_ANN, |s| s.print_path(x, false)) == "Some"; then { + let mut applicability = Applicability::MachineApplicable; let some_expr_string = snippet_with_applicability(cx, y[0].span, "", &mut applicability); let trimmed_ok = snippet_with_applicability(cx, let_expr.span.until(ok_span), "", &mut applicability); let sugg = format!( - "if let Ok({}) = {}", + "{} let Ok({}) = {}", + ifwhile, some_expr_string, trimmed_ok.trim().trim_end_matches('.'), ); span_lint_and_sugg( cx, - IF_LET_SOME_RESULT, + MATCH_RESULT_OK, expr.span.with_hi(let_expr.span.hi()), "matching on `Some` with `ok()` is redundant", &format!("consider matching on `Ok({})` and removing the call to `ok` instead", some_expr_string), diff --git a/src/tools/clippy/clippy_lints/src/matches.rs b/src/tools/clippy/clippy_lints/src/matches.rs index 3d0da472dd..56d4163a6b 100644 --- a/src/tools/clippy/clippy_lints/src/matches.rs +++ b/src/tools/clippy/clippy_lints/src/matches.rs @@ -6,7 +6,7 @@ use clippy_utils::higher; use clippy_utils::source::{expr_block, indent_of, snippet, snippet_block, snippet_opt, snippet_with_applicability}; use clippy_utils::sugg::Sugg; use clippy_utils::ty::{implements_trait, is_type_diagnostic_item, match_type, peel_mid_ty_refs}; -use clippy_utils::visitors::LocalUsedVisitor; +use clippy_utils::visitors::is_local_used; use clippy_utils::{ get_parent_expr, in_macro, is_expn_of, is_lang_ctor, is_lint_allowed, is_refutable, is_unit_expr, is_wild, meets_msrv, msrvs, path_to_local, path_to_local_id, peel_hir_pat_refs, peel_n_hir_expr_refs, recurse_or_patterns, @@ -183,8 +183,8 @@ declare_clippy_lint! { /// ```rust /// let x = 5; /// match x { - /// 1...10 => println!("1 ... 10"), - /// 5...15 => println!("5 ... 15"), + /// 1..=10 => println!("1 ... 10"), + /// 5..=15 => println!("5 ... 15"), /// _ => (), /// } /// ``` @@ -631,7 +631,7 @@ impl<'tcx> LateLintPass<'tcx> for Matches { check_match_single_binding(cx, ex, arms, expr); } } - if let ExprKind::Match(ref ex, ref arms, _) = expr.kind { + if let ExprKind::Match(ex, arms, _) = expr.kind { check_match_ref_pats(cx, ex, arms.iter().map(|el| el.pat), expr); } if let Some(higher::IfLet { let_pat, let_expr, .. }) = higher::IfLet::hir(cx, expr) { @@ -948,7 +948,7 @@ fn check_overlapping_arms<'tcx>(cx: &LateContext<'tcx>, ex: &'tcx Expr<'_>, arms fn check_wild_err_arm<'tcx>(cx: &LateContext<'tcx>, ex: &Expr<'tcx>, arms: &[Arm<'tcx>]) { let ex_ty = cx.typeck_results().expr_ty(ex).peel_refs(); - if is_type_diagnostic_item(cx, ex_ty, sym::result_type) { + if is_type_diagnostic_item(cx, ex_ty, sym::Result) { for arm in arms { if let PatKind::TupleStruct(ref path, inner, _) = arm.pat.kind { let path_str = rustc_hir_pretty::to_string(rustc_hir_pretty::NO_ANN, |s| s.print_qpath(path, false)); @@ -959,9 +959,7 @@ fn check_wild_err_arm<'tcx>(cx: &LateContext<'tcx>, ex: &Expr<'tcx>, arms: &[Arm // Looking for unused bindings (i.e.: `_e`) for pat in inner.iter() { if let PatKind::Binding(_, id, ident, None) = pat.kind { - if ident.as_str().starts_with('_') - && !LocalUsedVisitor::new(cx, id).check_expr(arm.body) - { + if ident.as_str().starts_with('_') && !is_local_used(cx, arm.body, id) { ident_bind_name = (&ident.name.as_str()).to_string(); matching_wild = true; } @@ -1027,8 +1025,7 @@ fn check_wild_enum_match(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>]) let adt_def = match ty.kind() { ty::Adt(adt_def, _) if adt_def.is_enum() - && !(is_type_diagnostic_item(cx, ty, sym::option_type) - || is_type_diagnostic_item(cx, ty, sym::result_type)) => + && !(is_type_diagnostic_item(cx, ty, sym::Option) || is_type_diagnostic_item(cx, ty, sym::Result)) => { adt_def }, @@ -1196,7 +1193,7 @@ where let (first_sugg, msg, title); let span = ex.span.source_callsite(); - if let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, ref inner) = ex.kind { + if let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, inner) = ex.kind { first_sugg = once((span, Sugg::hir_with_macro_callsite(cx, inner, "..").to_string())); msg = "try"; title = "you don't need to add `&` to both the expression and the patterns"; @@ -1207,7 +1204,7 @@ where } let remaining_suggs = pats.filter_map(|pat| { - if let PatKind::Ref(ref refp, _) = pat.kind { + if let PatKind::Ref(refp, _) = pat.kind { Some((pat.span, snippet(cx, refp.span, "..").to_string())) } else { None @@ -1367,7 +1364,7 @@ where find_bool_lit(&arm.2.kind, is_if_let).map_or(false, |b| b == b0) && arm.3.is_none() && arm.0.is_empty() }); then { - if let Some(ref last_pat) = last_pat_opt { + if let Some(last_pat) = last_pat_opt { if !is_wild(last_pat) { return false; } @@ -1829,13 +1826,13 @@ mod redundant_pattern_match { .. }) = higher::IfLet::hir(cx, expr) { - find_sugg_for_if_let(cx, expr, let_pat, let_expr, "if", if_else.is_some()) + find_sugg_for_if_let(cx, expr, let_pat, let_expr, "if", if_else.is_some()); } if let ExprKind::Match(op, arms, MatchSource::Normal) = &expr.kind { - find_sugg_for_match(cx, expr, op, arms) + find_sugg_for_match(cx, expr, op, arms); } if let Some(higher::WhileLet { let_pat, let_expr, .. }) = higher::WhileLet::hir(expr) { - find_sugg_for_if_let(cx, expr, let_pat, let_expr, "while", false) + find_sugg_for_if_let(cx, expr, let_pat, let_expr, "while", false); } } @@ -1871,7 +1868,7 @@ mod redundant_pattern_match { } } // Check for std types which implement drop, but only for memory allocation. - else if is_type_diagnostic_item(cx, ty, sym::vec_type) + else if is_type_diagnostic_item(cx, ty, sym::Vec) || is_type_lang_item(cx, ty, LangItem::OwnedBox) || is_type_diagnostic_item(cx, ty, sym::Rc) || is_type_diagnostic_item(cx, ty, sym::Arc) diff --git a/src/tools/clippy/clippy_lints/src/mem_discriminant.rs b/src/tools/clippy/clippy_lints/src/mem_discriminant.rs deleted file mode 100644 index 59176c4b84..0000000000 --- a/src/tools/clippy/clippy_lints/src/mem_discriminant.rs +++ /dev/null @@ -1,82 +0,0 @@ -use clippy_utils::diagnostics::span_lint_and_then; -use clippy_utils::source::snippet; -use clippy_utils::ty::walk_ptrs_ty_depth; -use clippy_utils::{match_def_path, paths}; -use if_chain::if_chain; -use rustc_errors::Applicability; -use rustc_hir::{BorrowKind, Expr, ExprKind}; -use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; - -declare_clippy_lint! { - /// ### What it does - /// Checks for calls of `mem::discriminant()` on a non-enum type. - /// - /// ### Why is this bad? - /// The value of `mem::discriminant()` on non-enum types - /// is unspecified. - /// - /// ### Example - /// ```rust - /// use std::mem; - /// - /// mem::discriminant(&"hello"); - /// mem::discriminant(&&Some(2)); - /// ``` - pub MEM_DISCRIMINANT_NON_ENUM, - correctness, - "calling `mem::descriminant` on non-enum type" -} - -declare_lint_pass!(MemDiscriminant => [MEM_DISCRIMINANT_NON_ENUM]); - -impl<'tcx> LateLintPass<'tcx> for MemDiscriminant { - fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { - if_chain! { - if let ExprKind::Call(func, func_args) = expr.kind; - // is `mem::discriminant` - if let ExprKind::Path(ref func_qpath) = func.kind; - if let Some(def_id) = cx.qpath_res(func_qpath, func.hir_id).opt_def_id(); - if match_def_path(cx, def_id, &paths::MEM_DISCRIMINANT); - // type is non-enum - let ty_param = cx.typeck_results().node_substs(func.hir_id).type_at(0); - if !ty_param.is_enum(); - - then { - span_lint_and_then( - cx, - MEM_DISCRIMINANT_NON_ENUM, - expr.span, - &format!("calling `mem::discriminant` on non-enum type `{}`", ty_param), - |diag| { - // if this is a reference to an enum, suggest dereferencing - let (base_ty, ptr_depth) = walk_ptrs_ty_depth(ty_param); - if ptr_depth >= 1 && base_ty.is_enum() { - let param = &func_args[0]; - - // cancel out '&'s first - let mut derefs_needed = ptr_depth; - let mut cur_expr = param; - while derefs_needed > 0 { - if let ExprKind::AddrOf(BorrowKind::Ref, _, inner_expr) = cur_expr.kind { - derefs_needed -= 1; - cur_expr = inner_expr; - } else { - break; - } - } - - let derefs = "*".repeat(derefs_needed); - diag.span_suggestion( - param.span, - "try dereferencing", - format!("{}{}", derefs, snippet(cx, cur_expr.span, "")), - Applicability::MachineApplicable, - ); - } - }, - ) - } - } - } -} diff --git a/src/tools/clippy/clippy_lints/src/mem_forget.rs b/src/tools/clippy/clippy_lints/src/mem_forget.rs index 07202a59c4..eb437dc47a 100644 --- a/src/tools/clippy/clippy_lints/src/mem_forget.rs +++ b/src/tools/clippy/clippy_lints/src/mem_forget.rs @@ -28,11 +28,11 @@ declare_lint_pass!(MemForget => [MEM_FORGET]); impl<'tcx> LateLintPass<'tcx> for MemForget { fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) { - if let ExprKind::Call(path_expr, args) = e.kind { + if let ExprKind::Call(path_expr, [ref first_arg, ..]) = e.kind { if let ExprKind::Path(ref qpath) = path_expr.kind { if let Some(def_id) = cx.qpath_res(qpath, path_expr.hir_id).opt_def_id() { if match_def_path(cx, def_id, &paths::MEM_FORGET) { - let forgot_ty = cx.typeck_results().expr_ty(&args[0]); + let forgot_ty = cx.typeck_results().expr_ty(first_arg); if forgot_ty.ty_adt_def().map_or(false, |def| def.has_dtor(cx.tcx)) { span_lint(cx, MEM_FORGET, e.span, "usage of `mem::forget` on `Drop` type"); diff --git a/src/tools/clippy/clippy_lints/src/mem_replace.rs b/src/tools/clippy/clippy_lints/src/mem_replace.rs index 3d071c9081..1e6057a8fe 100644 --- a/src/tools/clippy/clippy_lints/src/mem_replace.rs +++ b/src/tools/clippy/clippy_lints/src/mem_replace.rs @@ -1,9 +1,9 @@ use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg, span_lint_and_then}; use clippy_utils::source::{snippet, snippet_with_applicability}; -use clippy_utils::{in_macro, is_diag_trait_item, is_lang_ctor, match_def_path, meets_msrv, msrvs, paths}; +use clippy_utils::ty::is_non_aggregate_primitive_type; +use clippy_utils::{in_macro, is_default_equivalent, is_lang_ctor, match_def_path, meets_msrv, msrvs, paths}; use if_chain::if_chain; use rustc_errors::Applicability; -use rustc_hir::def_id::DefId; use rustc_hir::LangItem::OptionNone; use rustc_hir::{BorrowKind, Expr, ExprKind, Mutability, QPath}; use rustc_lint::{LateContext, LateLintPass, LintContext}; @@ -194,64 +194,37 @@ fn check_replace_with_uninit(cx: &LateContext<'_>, src: &Expr<'_>, dest: &Expr<' } } -/// Returns true if the `def_id` associated with the `path` is recognized as a "default-equivalent" -/// constructor from the std library -fn is_default_equivalent_ctor(cx: &LateContext<'_>, def_id: DefId, path: &QPath<'_>) -> bool { - let std_types_symbols = &[ - sym::string_type, - sym::vec_type, - sym::vecdeque_type, - sym::LinkedList, - sym::hashmap_type, - sym::BTreeMap, - sym::hashset_type, - sym::BTreeSet, - sym::BinaryHeap, - ]; - - if let QPath::TypeRelative(_, method) = path { - if method.ident.name == sym::new { - if let Some(impl_did) = cx.tcx.impl_of_method(def_id) { - if let Some(adt) = cx.tcx.type_of(impl_did).ty_adt_def() { - return std_types_symbols - .iter() - .any(|&symbol| cx.tcx.is_diagnostic_item(symbol, adt.did)); - } - } +fn check_replace_with_default(cx: &LateContext<'_>, src: &Expr<'_>, dest: &Expr<'_>, expr_span: Span) { + // disable lint for primitives + let expr_type = cx.typeck_results().expr_ty_adjusted(src); + if is_non_aggregate_primitive_type(expr_type) { + return; + } + // disable lint for Option since it is covered in another lint + if let ExprKind::Path(q) = &src.kind { + if is_lang_ctor(cx, q, OptionNone) { + return; } } - false -} + if is_default_equivalent(cx, src) && !in_external_macro(cx.tcx.sess, expr_span) { + span_lint_and_then( + cx, + MEM_REPLACE_WITH_DEFAULT, + expr_span, + "replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take`", + |diag| { + if !in_macro(expr_span) { + let suggestion = format!("std::mem::take({})", snippet(cx, dest.span, "")); -fn check_replace_with_default(cx: &LateContext<'_>, src: &Expr<'_>, dest: &Expr<'_>, expr_span: Span) { - if_chain! { - if let ExprKind::Call(repl_func, _) = src.kind; - if !in_external_macro(cx.tcx.sess, expr_span); - if let ExprKind::Path(ref repl_func_qpath) = repl_func.kind; - if let Some(repl_def_id) = cx.qpath_res(repl_func_qpath, repl_func.hir_id).opt_def_id(); - if is_diag_trait_item(cx, repl_def_id, sym::Default) - || is_default_equivalent_ctor(cx, repl_def_id, repl_func_qpath); - - then { - span_lint_and_then( - cx, - MEM_REPLACE_WITH_DEFAULT, - expr_span, - "replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take`", - |diag| { - if !in_macro(expr_span) { - let suggestion = format!("std::mem::take({})", snippet(cx, dest.span, "")); - - diag.span_suggestion( - expr_span, - "consider using", - suggestion, - Applicability::MachineApplicable - ); - } + diag.span_suggestion( + expr_span, + "consider using", + suggestion, + Applicability::MachineApplicable, + ); } - ); - } + }, + ); } } diff --git a/src/tools/clippy/clippy_lints/src/methods/bytes_nth.rs b/src/tools/clippy/clippy_lints/src/methods/bytes_nth.rs index 2ad3e673c5..76eaedea8a 100644 --- a/src/tools/clippy/clippy_lints/src/methods/bytes_nth.rs +++ b/src/tools/clippy/clippy_lints/src/methods/bytes_nth.rs @@ -12,7 +12,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>, recv: &'tcx E let ty = cx.typeck_results().expr_ty(recv).peel_refs(); let caller_type = if ty.is_str() { "str" - } else if is_type_diagnostic_item(cx, ty, sym::string_type) { + } else if is_type_diagnostic_item(cx, ty, sym::String) { "String" } else { return; diff --git a/src/tools/clippy/clippy_lints/src/methods/clone_on_copy.rs b/src/tools/clippy/clippy_lints/src/methods/clone_on_copy.rs index 1a32af5dc7..b4dacb2580 100644 --- a/src/tools/clippy/clippy_lints/src/methods/clone_on_copy.rs +++ b/src/tools/clippy/clippy_lints/src/methods/clone_on_copy.rs @@ -85,7 +85,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, method_name: Symbol, if expr.hir_id == self_arg.hir_id && ty != cx.typeck_results().expr_ty_adjusted(expr) => { return; - } + }, ExprKind::MethodCall(_, _, [self_arg, ..], _) if expr.hir_id == self_arg.hir_id => true, ExprKind::Match(_, _, MatchSource::TryDesugar | MatchSource::AwaitDesugar) | ExprKind::Field(..) @@ -100,7 +100,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, method_name: Symbol, ) => { return; - } + }, _ => false, }; diff --git a/src/tools/clippy/clippy_lints/src/methods/cloned_instead_of_copied.rs b/src/tools/clippy/clippy_lints/src/methods/cloned_instead_of_copied.rs index f5b4b6bf8e..6fe69b8f01 100644 --- a/src/tools/clippy/clippy_lints/src/methods/cloned_instead_of_copied.rs +++ b/src/tools/clippy/clippy_lints/src/methods/cloned_instead_of_copied.rs @@ -15,7 +15,7 @@ pub fn check(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, span: Span, let inner_ty = match recv_ty.kind() { // `Option` -> `T` ty::Adt(adt, subst) - if cx.tcx.is_diagnostic_item(sym::option_type, adt.did) && meets_msrv(msrv, &msrvs::OPTION_COPIED) => + if cx.tcx.is_diagnostic_item(sym::Option, adt.did) && meets_msrv(msrv, &msrvs::OPTION_COPIED) => { subst.type_at(0) }, diff --git a/src/tools/clippy/clippy_lints/src/methods/expect_fun_call.rs b/src/tools/clippy/clippy_lints/src/methods/expect_fun_call.rs index f8ee31a00d..0ec9387f9c 100644 --- a/src/tools/clippy/clippy_lints/src/methods/expect_fun_call.rs +++ b/src/tools/clippy/clippy_lints/src/methods/expect_fun_call.rs @@ -28,7 +28,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, method_span: Spa && { let arg_type = cx.typeck_results().expr_ty(&call_args[0]); let base_type = arg_type.peel_refs(); - *base_type.kind() == ty::Str || is_type_diagnostic_item(cx, base_type, sym::string_type) + *base_type.kind() == ty::Str || is_type_diagnostic_item(cx, base_type, sym::String) } { &call_args[0] @@ -46,7 +46,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, method_span: Spa // converted to string. fn requires_to_string(cx: &LateContext<'_>, arg: &hir::Expr<'_>) -> bool { let arg_ty = cx.typeck_results().expr_ty(arg); - if is_type_diagnostic_item(cx, arg_ty, sym::string_type) { + if is_type_diagnostic_item(cx, arg_ty, sym::String) { return false; } if let ty::Ref(_, ty, ..) = arg_ty.kind() { @@ -113,9 +113,9 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, method_span: Spa } let receiver_type = cx.typeck_results().expr_ty_adjusted(&args[0]); - let closure_args = if is_type_diagnostic_item(cx, receiver_type, sym::option_type) { + let closure_args = if is_type_diagnostic_item(cx, receiver_type, sym::Option) { "||" - } else if is_type_diagnostic_item(cx, receiver_type, sym::result_type) { + } else if is_type_diagnostic_item(cx, receiver_type, sym::Result) { "|_|" } else { return; diff --git a/src/tools/clippy/clippy_lints/src/methods/expect_used.rs b/src/tools/clippy/clippy_lints/src/methods/expect_used.rs index 63a834fdce..55be513c5b 100644 --- a/src/tools/clippy/clippy_lints/src/methods/expect_used.rs +++ b/src/tools/clippy/clippy_lints/src/methods/expect_used.rs @@ -10,9 +10,9 @@ use super::EXPECT_USED; pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr<'_>) { let obj_ty = cx.typeck_results().expr_ty(recv).peel_refs(); - let mess = if is_type_diagnostic_item(cx, obj_ty, sym::option_type) { + let mess = if is_type_diagnostic_item(cx, obj_ty, sym::Option) { Some((EXPECT_USED, "an Option", "None")) - } else if is_type_diagnostic_item(cx, obj_ty, sym::result_type) { + } else if is_type_diagnostic_item(cx, obj_ty, sym::Result) { Some((EXPECT_USED, "a Result", "Err")) } else { None diff --git a/src/tools/clippy/clippy_lints/src/methods/extend_with_drain.rs b/src/tools/clippy/clippy_lints/src/methods/extend_with_drain.rs index 8829b8c5f4..687636f823 100644 --- a/src/tools/clippy/clippy_lints/src/methods/extend_with_drain.rs +++ b/src/tools/clippy/clippy_lints/src/methods/extend_with_drain.rs @@ -12,7 +12,7 @@ use super::EXTEND_WITH_DRAIN; pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, arg: &Expr<'_>) { let ty = cx.typeck_results().expr_ty(recv).peel_refs(); if_chain! { - if is_type_diagnostic_item(cx, ty, sym::vec_type); + if is_type_diagnostic_item(cx, ty, sym::Vec); //check source object if let ExprKind::MethodCall(src_method, _, [drain_vec, drain_arg], _) = &arg.kind; if src_method.ident.as_str() == "drain"; @@ -20,7 +20,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, arg: //check if actual src type is mutable for code suggestion let immutable = src_ty.is_mutable_ptr(); let src_ty = src_ty.peel_refs(); - if is_type_diagnostic_item(cx, src_ty, sym::vec_type); + if is_type_diagnostic_item(cx, src_ty, sym::Vec); //check drain range if let src_ty_range = cx.typeck_results().expr_ty(drain_arg).peel_refs(); if is_type_lang_item(cx, src_ty_range, LangItem::RangeFull); diff --git a/src/tools/clippy/clippy_lints/src/methods/filter_map.rs b/src/tools/clippy/clippy_lints/src/methods/filter_map.rs index 35fae450ee..c96c817bb8 100644 --- a/src/tools/clippy/clippy_lints/src/methods/filter_map.rs +++ b/src/tools/clippy/clippy_lints/src/methods/filter_map.rs @@ -61,7 +61,7 @@ fn lint_filter_some_map_unwrap( methods_span: Span, ) { let iterator = is_trait_method(cx, expr, sym::Iterator); - let option = is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(filter_recv), sym::option_type); + let option = is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(filter_recv), sym::Option); if (iterator || option) && is_option_filter_map(cx, filter_arg, map_arg) { let msg = "`filter` for `Some` followed by `unwrap`"; let help = "consider using `flatten` instead"; @@ -120,9 +120,9 @@ pub(super) fn check<'tcx>( if let PatKind::Binding(_, filter_param_id, _, None) = filter_pat.kind; if let ExprKind::MethodCall(path, _, [filter_arg], _) = filter_body.value.kind; if let Some(opt_ty) = cx.typeck_results().expr_ty(filter_arg).ty_adt_def(); - if let Some(is_result) = if cx.tcx.is_diagnostic_item(sym::option_type, opt_ty.did) { + if let Some(is_result) = if cx.tcx.is_diagnostic_item(sym::Option, opt_ty.did) { Some(false) - } else if cx.tcx.is_diagnostic_item(sym::result_type, opt_ty.did) { + } else if cx.tcx.is_diagnostic_item(sym::Result, opt_ty.did) { Some(true) } else { None diff --git a/src/tools/clippy/clippy_lints/src/methods/filter_next.rs b/src/tools/clippy/clippy_lints/src/methods/filter_next.rs index 172714f6b0..bcf8d93b60 100644 --- a/src/tools/clippy/clippy_lints/src/methods/filter_next.rs +++ b/src/tools/clippy/clippy_lints/src/methods/filter_next.rs @@ -1,6 +1,6 @@ use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg}; -use clippy_utils::is_trait_method; use clippy_utils::source::snippet; +use clippy_utils::ty::implements_trait; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::LateContext; @@ -16,7 +16,10 @@ pub(super) fn check<'tcx>( filter_arg: &'tcx hir::Expr<'_>, ) { // lint if caller of `.filter().next()` is an Iterator - if is_trait_method(cx, expr, sym::Iterator) { + let recv_impls_iterator = cx.tcx.get_diagnostic_item(sym::Iterator).map_or(false, |id| { + implements_trait(cx, cx.typeck_results().expr_ty(recv), id, &[]) + }); + if recv_impls_iterator { let msg = "called `filter(..).next()` on an `Iterator`. This is more succinctly expressed by calling \ `.find(..)` instead"; let filter_snippet = snippet(cx, filter_arg.span, ".."); diff --git a/src/tools/clippy/clippy_lints/src/methods/flat_map_option.rs b/src/tools/clippy/clippy_lints/src/methods/flat_map_option.rs index 32d40d97bf..615bde9413 100644 --- a/src/tools/clippy/clippy_lints/src/methods/flat_map_option.rs +++ b/src/tools/clippy/clippy_lints/src/methods/flat_map_option.rs @@ -19,7 +19,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, arg _ if arg_ty.is_fn() => arg_ty.fn_sig(cx.tcx), _ => return, }; - if !is_type_diagnostic_item(cx, sig.output().skip_binder(), sym::option_type) { + if !is_type_diagnostic_item(cx, sig.output().skip_binder(), sym::Option) { return; } span_lint_and_sugg( diff --git a/src/tools/clippy/clippy_lints/src/methods/get_unwrap.rs b/src/tools/clippy/clippy_lints/src/methods/get_unwrap.rs index 66fb85deae..18e08d6ee2 100644 --- a/src/tools/clippy/clippy_lints/src/methods/get_unwrap.rs +++ b/src/tools/clippy/clippy_lints/src/methods/get_unwrap.rs @@ -27,13 +27,13 @@ pub(super) fn check<'tcx>( let caller_type = if derefs_to_slice(cx, recv, expr_ty).is_some() { needs_ref = get_args_str.parse::().is_ok(); "slice" - } else if is_type_diagnostic_item(cx, expr_ty, sym::vec_type) { + } else if is_type_diagnostic_item(cx, expr_ty, sym::Vec) { needs_ref = get_args_str.parse::().is_ok(); "Vec" - } else if is_type_diagnostic_item(cx, expr_ty, sym::vecdeque_type) { + } else if is_type_diagnostic_item(cx, expr_ty, sym::VecDeque) { needs_ref = get_args_str.parse::().is_ok(); "VecDeque" - } else if !is_mut && is_type_diagnostic_item(cx, expr_ty, sym::hashmap_type) { + } else if !is_mut && is_type_diagnostic_item(cx, expr_ty, sym::HashMap) { needs_ref = true; "HashMap" } else if !is_mut && is_type_diagnostic_item(cx, expr_ty, sym::BTreeMap) { diff --git a/src/tools/clippy/clippy_lints/src/methods/inefficient_to_string.rs b/src/tools/clippy/clippy_lints/src/methods/inefficient_to_string.rs index 950ec62c9f..c0f66feb48 100644 --- a/src/tools/clippy/clippy_lints/src/methods/inefficient_to_string.rs +++ b/src/tools/clippy/clippy_lints/src/methods/inefficient_to_string.rs @@ -55,7 +55,7 @@ fn specializes_tostring(cx: &LateContext<'_>, ty: Ty<'_>) -> bool { return true; } - if is_type_diagnostic_item(cx, ty, sym::string_type) { + if is_type_diagnostic_item(cx, ty, sym::String) { return true; } diff --git a/src/tools/clippy/clippy_lints/src/methods/iter_cloned_collect.rs b/src/tools/clippy/clippy_lints/src/methods/iter_cloned_collect.rs index 739f313716..dd4ef6e4b5 100644 --- a/src/tools/clippy/clippy_lints/src/methods/iter_cloned_collect.rs +++ b/src/tools/clippy/clippy_lints/src/methods/iter_cloned_collect.rs @@ -11,7 +11,7 @@ use super::ITER_CLONED_COLLECT; pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &hir::Expr<'_>, recv: &'tcx hir::Expr<'_>) { if_chain! { - if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(expr), sym::vec_type); + if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(expr), sym::Vec); if let Some(slice) = derefs_to_slice(cx, recv, cx.typeck_results().expr_ty(recv)); if let Some(to_replace) = expr.span.trim_start(slice.span.source_callsite()); diff --git a/src/tools/clippy/clippy_lints/src/methods/iter_count.rs b/src/tools/clippy/clippy_lints/src/methods/iter_count.rs index b69f57f50e..052be3d8ee 100644 --- a/src/tools/clippy/clippy_lints/src/methods/iter_count.rs +++ b/src/tools/clippy/clippy_lints/src/methods/iter_count.rs @@ -13,13 +13,13 @@ pub(crate) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>, recv: &'tcx E let ty = cx.typeck_results().expr_ty(recv); let caller_type = if derefs_to_slice(cx, recv, ty).is_some() { "slice" - } else if is_type_diagnostic_item(cx, ty, sym::vec_type) { + } else if is_type_diagnostic_item(cx, ty, sym::Vec) { "Vec" - } else if is_type_diagnostic_item(cx, ty, sym::vecdeque_type) { + } else if is_type_diagnostic_item(cx, ty, sym::VecDeque) { "VecDeque" - } else if is_type_diagnostic_item(cx, ty, sym::hashset_type) { + } else if is_type_diagnostic_item(cx, ty, sym::HashSet) { "HashSet" - } else if is_type_diagnostic_item(cx, ty, sym::hashmap_type) { + } else if is_type_diagnostic_item(cx, ty, sym::HashMap) { "HashMap" } else if is_type_diagnostic_item(cx, ty, sym::BTreeMap) { "BTreeMap" diff --git a/src/tools/clippy/clippy_lints/src/methods/iter_next_slice.rs b/src/tools/clippy/clippy_lints/src/methods/iter_next_slice.rs index 6954da67e3..d053ff5675 100644 --- a/src/tools/clippy/clippy_lints/src/methods/iter_next_slice.rs +++ b/src/tools/clippy/clippy_lints/src/methods/iter_next_slice.rs @@ -64,6 +64,6 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, cal } fn is_vec_or_array<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) -> bool { - is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(expr), sym::vec_type) + is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(expr), sym::Vec) || matches!(&cx.typeck_results().expr_ty(expr).peel_refs().kind(), ty::Array(_, _)) } diff --git a/src/tools/clippy/clippy_lints/src/methods/iter_nth.rs b/src/tools/clippy/clippy_lints/src/methods/iter_nth.rs index c2232239fe..80ca4c9421 100644 --- a/src/tools/clippy/clippy_lints/src/methods/iter_nth.rs +++ b/src/tools/clippy/clippy_lints/src/methods/iter_nth.rs @@ -19,9 +19,9 @@ pub(super) fn check<'tcx>( let mut_str = if is_mut { "_mut" } else { "" }; let caller_type = if derefs_to_slice(cx, iter_recv, cx.typeck_results().expr_ty(iter_recv)).is_some() { "slice" - } else if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(iter_recv), sym::vec_type) { + } else if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(iter_recv), sym::Vec) { "Vec" - } else if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(iter_recv), sym::vecdeque_type) { + } else if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(iter_recv), sym::VecDeque) { "VecDeque" } else { iter_nth_zero::check(cx, expr, nth_recv, nth_arg); diff --git a/src/tools/clippy/clippy_lints/src/methods/manual_saturating_arithmetic.rs b/src/tools/clippy/clippy_lints/src/methods/manual_saturating_arithmetic.rs index 2fddea7068..7ecafa1f3b 100644 --- a/src/tools/clippy/clippy_lints/src/methods/manual_saturating_arithmetic.rs +++ b/src/tools/clippy/clippy_lints/src/methods/manual_saturating_arithmetic.rs @@ -6,7 +6,7 @@ use rustc_ast::ast; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::LateContext; -use rustc_target::abi::LayoutOf; +use rustc_middle::ty::layout::LayoutOf; pub fn check( cx: &LateContext<'_>, diff --git a/src/tools/clippy/clippy_lints/src/methods/manual_split_once.rs b/src/tools/clippy/clippy_lints/src/methods/manual_split_once.rs new file mode 100644 index 0000000000..13eb72251b --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/methods/manual_split_once.rs @@ -0,0 +1,211 @@ +use clippy_utils::consts::{constant, Constant}; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::source::snippet_with_context; +use clippy_utils::{is_diag_item_method, match_def_path, paths}; +use if_chain::if_chain; +use rustc_errors::Applicability; +use rustc_hir::{Expr, ExprKind, HirId, LangItem, Node, QPath}; +use rustc_lint::LateContext; +use rustc_middle::ty::{self, adjustment::Adjust}; +use rustc_span::{symbol::sym, Span, SyntaxContext}; + +use super::MANUAL_SPLIT_ONCE; + +pub(super) fn check(cx: &LateContext<'_>, method_name: &str, expr: &Expr<'_>, self_arg: &Expr<'_>, pat_arg: &Expr<'_>) { + if !cx.typeck_results().expr_ty_adjusted(self_arg).peel_refs().is_str() { + return; + } + + let ctxt = expr.span.ctxt(); + let (method_name, msg, reverse) = if method_name == "splitn" { + ("split_once", "manual implementation of `split_once`", false) + } else { + ("rsplit_once", "manual implementation of `rsplit_once`", true) + }; + let usage = match parse_iter_usage(cx, ctxt, cx.tcx.hir().parent_iter(expr.hir_id), reverse) { + Some(x) => x, + None => return, + }; + + let mut app = Applicability::MachineApplicable; + let self_snip = snippet_with_context(cx, self_arg.span, ctxt, "..", &mut app).0; + let pat_snip = snippet_with_context(cx, pat_arg.span, ctxt, "..", &mut app).0; + + let sugg = match usage.kind { + IterUsageKind::NextTuple => { + format!("{}.{}({})", self_snip, method_name, pat_snip) + }, + IterUsageKind::RNextTuple => format!("{}.{}({}).map(|(x, y)| (y, x))", self_snip, method_name, pat_snip), + IterUsageKind::Next => { + let self_deref = { + let adjust = cx.typeck_results().expr_adjustments(self_arg); + if adjust.is_empty() { + String::new() + } else if cx.typeck_results().expr_ty(self_arg).is_box() + || adjust + .iter() + .any(|a| matches!(a.kind, Adjust::Deref(Some(_))) || a.target.is_box()) + { + format!("&{}", "*".repeat(adjust.len() - 1)) + } else { + "*".repeat(adjust.len() - 2) + } + }; + if usage.unwrap_kind.is_some() { + format!( + "{}.{}({}).map_or({}{}, |x| x.0)", + &self_snip, method_name, pat_snip, self_deref, &self_snip + ) + } else { + format!( + "Some({}.{}({}).map_or({}{}, |x| x.0))", + &self_snip, method_name, pat_snip, self_deref, &self_snip + ) + } + }, + IterUsageKind::Second => { + let access_str = match usage.unwrap_kind { + Some(UnwrapKind::Unwrap) => ".unwrap().1", + Some(UnwrapKind::QuestionMark) => "?.1", + None => ".map(|x| x.1)", + }; + format!("{}.{}({}){}", self_snip, method_name, pat_snip, access_str) + }, + }; + + span_lint_and_sugg(cx, MANUAL_SPLIT_ONCE, usage.span, msg, "try this", sugg, app); +} + +enum IterUsageKind { + Next, + Second, + NextTuple, + RNextTuple, +} + +enum UnwrapKind { + Unwrap, + QuestionMark, +} + +struct IterUsage { + kind: IterUsageKind, + unwrap_kind: Option, + span: Span, +} + +#[allow(clippy::too_many_lines)] +fn parse_iter_usage( + cx: &LateContext<'tcx>, + ctxt: SyntaxContext, + mut iter: impl Iterator)>, + reverse: bool, +) -> Option { + let (kind, span) = match iter.next() { + Some((_, Node::Expr(e))) if e.span.ctxt() == ctxt => { + let (name, args) = if let ExprKind::MethodCall(name, _, [_, args @ ..], _) = e.kind { + (name, args) + } else { + return None; + }; + let did = cx.typeck_results().type_dependent_def_id(e.hir_id)?; + let iter_id = cx.tcx.get_diagnostic_item(sym::Iterator)?; + + match (&*name.ident.as_str(), args) { + ("next", []) if cx.tcx.trait_of_item(did) == Some(iter_id) => { + if reverse { + (IterUsageKind::Second, e.span) + } else { + (IterUsageKind::Next, e.span) + } + }, + ("next_tuple", []) => { + return if_chain! { + if match_def_path(cx, did, &paths::ITERTOOLS_NEXT_TUPLE); + if let ty::Adt(adt_def, subs) = cx.typeck_results().expr_ty(e).kind(); + if cx.tcx.is_diagnostic_item(sym::Option, adt_def.did); + if let ty::Tuple(subs) = subs.type_at(0).kind(); + if subs.len() == 2; + then { + Some(IterUsage { + kind: if reverse { IterUsageKind::RNextTuple } else { IterUsageKind::NextTuple }, + span: e.span, + unwrap_kind: None + }) + } else { + None + } + }; + }, + ("nth" | "skip", [idx_expr]) if cx.tcx.trait_of_item(did) == Some(iter_id) => { + if let Some((Constant::Int(idx), _)) = constant(cx, cx.typeck_results(), idx_expr) { + let span = if name.ident.as_str() == "nth" { + e.span + } else { + if_chain! { + if let Some((_, Node::Expr(next_expr))) = iter.next(); + if let ExprKind::MethodCall(next_name, _, [_], _) = next_expr.kind; + if next_name.ident.name == sym::next; + if next_expr.span.ctxt() == ctxt; + if let Some(next_id) = cx.typeck_results().type_dependent_def_id(next_expr.hir_id); + if cx.tcx.trait_of_item(next_id) == Some(iter_id); + then { + next_expr.span + } else { + return None; + } + } + }; + match if reverse { idx ^ 1 } else { idx } { + 0 => (IterUsageKind::Next, span), + 1 => (IterUsageKind::Second, span), + _ => return None, + } + } else { + return None; + } + }, + _ => return None, + } + }, + _ => return None, + }; + + let (unwrap_kind, span) = if let Some((_, Node::Expr(e))) = iter.next() { + match e.kind { + ExprKind::Call( + Expr { + kind: ExprKind::Path(QPath::LangItem(LangItem::TryTraitBranch, _)), + .. + }, + _, + ) => { + let parent_span = e.span.parent_callsite().unwrap(); + if parent_span.ctxt() == ctxt { + (Some(UnwrapKind::QuestionMark), parent_span) + } else { + (None, span) + } + }, + _ if e.span.ctxt() != ctxt => (None, span), + ExprKind::MethodCall(name, _, [_], _) + if name.ident.name == sym::unwrap + && cx + .typeck_results() + .type_dependent_def_id(e.hir_id) + .map_or(false, |id| is_diag_item_method(cx, id, sym::Option)) => + { + (Some(UnwrapKind::Unwrap), e.span) + }, + _ => (None, span), + } + } else { + (None, span) + }; + + Some(IterUsage { + kind, + unwrap_kind, + span, + }) +} diff --git a/src/tools/clippy/clippy_lints/src/methods/manual_str_repeat.rs b/src/tools/clippy/clippy_lints/src/methods/manual_str_repeat.rs index 919e2628c5..d74c910b67 100644 --- a/src/tools/clippy/clippy_lints/src/methods/manual_str_repeat.rs +++ b/src/tools/clippy/clippy_lints/src/methods/manual_str_repeat.rs @@ -36,14 +36,14 @@ fn parse_repeat_arg(cx: &LateContext<'_>, e: &Expr<'_>) -> Option { } } else { let ty = cx.typeck_results().expr_ty(e); - if is_type_diagnostic_item(cx, ty, sym::string_type) + if is_type_diagnostic_item(cx, ty, sym::String) || (is_type_lang_item(cx, ty, LangItem::OwnedBox) && get_ty_param(ty).map_or(false, TyS::is_str)) || (match_type(cx, ty, &paths::COW) && get_ty_param(ty).map_or(false, TyS::is_str)) { Some(RepeatKind::String) } else { let ty = ty.peel_refs(); - (ty.is_str() || is_type_diagnostic_item(cx, ty, sym::string_type)).then(|| RepeatKind::String) + (ty.is_str() || is_type_diagnostic_item(cx, ty, sym::String)).then(|| RepeatKind::String) } } } @@ -58,7 +58,7 @@ pub(super) fn check( if_chain! { if let ExprKind::Call(repeat_fn, [repeat_arg]) = take_self_arg.kind; if is_expr_path_def_path(cx, repeat_fn, &paths::ITER_REPEAT); - if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(collect_expr), sym::string_type); + if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(collect_expr), sym::String); if let Some(collect_id) = cx.typeck_results().type_dependent_def_id(collect_expr.hir_id); if let Some(take_id) = cx.typeck_results().type_dependent_def_id(take_expr.hir_id); if let Some(iter_trait_id) = cx.tcx.get_diagnostic_item(sym::Iterator); diff --git a/src/tools/clippy/clippy_lints/src/methods/map_collect_result_unit.rs b/src/tools/clippy/clippy_lints/src/methods/map_collect_result_unit.rs index 82063ad70b..d420f144ee 100644 --- a/src/tools/clippy/clippy_lints/src/methods/map_collect_result_unit.rs +++ b/src/tools/clippy/clippy_lints/src/methods/map_collect_result_unit.rs @@ -23,7 +23,7 @@ pub(super) fn check( if is_trait_method(cx, collect_recv, sym::Iterator); // return of collect `Result<(),_>` let collect_ret_ty = cx.typeck_results().expr_ty(expr); - if is_type_diagnostic_item(cx, collect_ret_ty, sym::result_type); + if is_type_diagnostic_item(cx, collect_ret_ty, sym::Result); if let ty::Adt(_, substs) = collect_ret_ty.kind(); if let Some(result_t) = substs.types().next(); if result_t.is_unit(); diff --git a/src/tools/clippy/clippy_lints/src/methods/map_flatten.rs b/src/tools/clippy/clippy_lints/src/methods/map_flatten.rs index 08d3a7ce92..6782f64f2c 100644 --- a/src/tools/clippy/clippy_lints/src/methods/map_flatten.rs +++ b/src/tools/clippy/clippy_lints/src/methods/map_flatten.rs @@ -27,7 +27,7 @@ pub(super) fn check<'tcx>( _ => map_closure_ty.fn_sig(cx.tcx), }; let map_closure_return_ty = cx.tcx.erase_late_bound_regions(map_closure_sig.output()); - is_type_diagnostic_item(cx, map_closure_return_ty, sym::option_type) + is_type_diagnostic_item(cx, map_closure_return_ty, sym::Option) }, _ => false, }; @@ -55,9 +55,9 @@ pub(super) fn check<'tcx>( // lint if caller of `.map().flatten()` is an Option or Result let caller_type = match cx.typeck_results().expr_ty(recv).kind() { ty::Adt(adt, _) => { - if cx.tcx.is_diagnostic_item(sym::option_type, adt.did) { + if cx.tcx.is_diagnostic_item(sym::Option, adt.did) { "Option" - } else if cx.tcx.is_diagnostic_item(sym::result_type, adt.did) { + } else if cx.tcx.is_diagnostic_item(sym::Result, adt.did) { "Result" } else { return; diff --git a/src/tools/clippy/clippy_lints/src/methods/map_identity.rs b/src/tools/clippy/clippy_lints/src/methods/map_identity.rs index 538a12566e..f112b500d3 100644 --- a/src/tools/clippy/clippy_lints/src/methods/map_identity.rs +++ b/src/tools/clippy/clippy_lints/src/methods/map_identity.rs @@ -19,8 +19,8 @@ pub(super) fn check( if_chain! { if is_trait_method(cx, expr, sym::Iterator) - || is_type_diagnostic_item(cx, caller_ty, sym::result_type) - || is_type_diagnostic_item(cx, caller_ty, sym::option_type); + || is_type_diagnostic_item(cx, caller_ty, sym::Result) + || is_type_diagnostic_item(cx, caller_ty, sym::Option); if is_expr_identity_function(cx, map_arg); if let Some(sugg_span) = expr.span.trim_start(caller.span); then { diff --git a/src/tools/clippy/clippy_lints/src/methods/map_unwrap_or.rs b/src/tools/clippy/clippy_lints/src/methods/map_unwrap_or.rs index 4d8365fcda..9ec84e7651 100644 --- a/src/tools/clippy/clippy_lints/src/methods/map_unwrap_or.rs +++ b/src/tools/clippy/clippy_lints/src/methods/map_unwrap_or.rs @@ -22,8 +22,8 @@ pub(super) fn check<'tcx>( msrv: Option<&RustcVersion>, ) -> bool { // lint if the caller of `map()` is an `Option` - let is_option = is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::option_type); - let is_result = is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::result_type); + let is_option = is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::Option); + let is_result = is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::Result); if is_result && !meets_msrv(msrv, &msrvs::RESULT_MAP_OR_ELSE) { return false; diff --git a/src/tools/clippy/clippy_lints/src/methods/mod.rs b/src/tools/clippy/clippy_lints/src/methods/mod.rs index 9626cf79dc..b26d11c0d6 100644 --- a/src/tools/clippy/clippy_lints/src/methods/mod.rs +++ b/src/tools/clippy/clippy_lints/src/methods/mod.rs @@ -33,6 +33,7 @@ mod iter_nth_zero; mod iter_skip_next; mod iterator_step_by_zero; mod manual_saturating_arithmetic; +mod manual_split_once; mod manual_str_repeat; mod map_collect_result_unit; mod map_flatten; @@ -64,6 +65,7 @@ mod wrong_self_convention; mod zst_offset; use bind_instead_of_map::BindInsteadOfMap; +use clippy_utils::consts::{constant, Constant}; use clippy_utils::diagnostics::{span_lint, span_lint_and_help}; use clippy_utils::ty::{contains_adt_constructor, contains_ty, implements_trait, is_copy, is_type_diagnostic_item}; use clippy_utils::{contains_return, get_trait_def_id, in_macro, iter_input_pats, meets_msrv, msrvs, paths, return_ty}; @@ -262,6 +264,8 @@ declare_clippy_lint! { /// The method signature is controlled by the trait and often `&self` is required for all types that implement the trait /// (see e.g. the `std::string::ToString` trait). /// + /// Clippy allows `Pin<&Self>` and `Pin<&mut Self>` if `&self` and `&mut self` is required. + /// /// Please find more info here: /// https://rust-lang.github.io/api-guidelines/naming.html#ad-hoc-conversions-follow-as_-to_-into_-conventions-c-conv /// @@ -993,7 +997,7 @@ declare_clippy_lint! { declare_clippy_lint! { /// ### What it does /// Checks for use of `.iter().nth()` (and the related - /// `.iter_mut().nth()`) on standard library types with O(1) element access. + /// `.iter_mut().nth()`) on standard library types with *O*(1) element access. /// /// ### Why is this bad? /// `.get()` and `.get_mut()` are more efficient and more @@ -1280,8 +1284,9 @@ declare_clippy_lint! { /// /// ### Why is this bad? /// It looks suspicious. Maybe `map` was confused with `filter`. - /// If the `map` call is intentional, this should be rewritten. Or, if you intend to - /// drive the iterator to completion, you can just use `for_each` instead. + /// If the `map` call is intentional, this should be rewritten + /// using `inspect`. Or, if you intend to drive the iterator to + /// completion, you can just use `for_each` instead. /// /// ### Example /// ```rust @@ -1771,6 +1776,29 @@ declare_clippy_lint! { "manual implementation of `str::repeat`" } +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. + /// + /// **Example:** + /// + /// ```rust,ignore + /// // Bad + /// let (key, value) = _.splitn(2, '=').next_tuple()?; + /// let value = _.splitn(2, '=').nth(1)?; + /// + /// // Good + /// let (key, value) = _.split_once('=')?; + /// let value = _.split_once('=')?.1; + /// ``` + pub MANUAL_SPLIT_ONCE, + complexity, + "replace `.splitn(2, pat)` with `.split_once(pat)`" +} + pub struct Methods { avoid_breaking_exported_api: bool, msrv: Option, @@ -1848,7 +1876,8 @@ impl_lint_pass!(Methods => [ IMPLICIT_CLONE, SUSPICIOUS_SPLITN, MANUAL_STR_REPEAT, - EXTEND_WITH_DRAIN + EXTEND_WITH_DRAIN, + MANUAL_SPLIT_ONCE ]); /// Extracts a method call name, args, and `Span` of the method name. @@ -2035,7 +2064,7 @@ impl<'tcx> LateLintPass<'tcx> for Methods { then { let first_arg_span = first_arg_ty.span; let first_arg_ty = hir_ty_to_ty(cx.tcx, first_arg_ty); - let self_ty = TraitRef::identity(cx.tcx, item.def_id.to_def_id()).self_ty(); + let self_ty = TraitRef::identity(cx.tcx, item.def_id.to_def_id()).self_ty().skip_binder(); wrong_self_convention::check( cx, &item.ident.name.as_str(), @@ -2052,7 +2081,7 @@ impl<'tcx> LateLintPass<'tcx> for Methods { if item.ident.name == sym::new; if let TraitItemKind::Fn(_, _) = item.kind; let ret_ty = return_ty(cx, item.hir_id()); - let self_ty = TraitRef::identity(cx.tcx, item.def_id.to_def_id()).self_ty(); + let self_ty = TraitRef::identity(cx.tcx, item.def_id.to_def_id()).self_ty().skip_binder(); if !contains_ty(cx.tcx, ret_ty, self_ty); then { @@ -2176,8 +2205,18 @@ fn check_methods<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, msrv: Optio unnecessary_lazy_eval::check(cx, expr, recv, arg, "or"); } }, - ("splitn" | "splitn_mut" | "rsplitn" | "rsplitn_mut", [count_arg, _]) => { - suspicious_splitn::check(cx, name, expr, recv, count_arg); + ("splitn" | "rsplitn", [count_arg, pat_arg]) => { + if let Some((Constant::Int(count), _)) = constant(cx, cx.typeck_results(), count_arg) { + suspicious_splitn::check(cx, name, expr, recv, count); + if count == 2 && meets_msrv(msrv, &msrvs::STR_SPLIT_ONCE) { + manual_split_once::check(cx, name, expr, recv, pat_arg); + } + } + }, + ("splitn_mut" | "rsplitn_mut", [count_arg, _]) => { + if let Some((Constant::Int(count), _)) = constant(cx, cx.typeck_results(), count_arg) { + suspicious_splitn::check(cx, name, expr, recv, count); + } }, ("step_by", [arg]) => iterator_step_by_zero::check(cx, expr, arg), ("to_os_string" | "to_owned" | "to_path_buf" | "to_vec", []) => { diff --git a/src/tools/clippy/clippy_lints/src/methods/ok_expect.rs b/src/tools/clippy/clippy_lints/src/methods/ok_expect.rs index d0b1b4b84b..d64a9f320d 100644 --- a/src/tools/clippy/clippy_lints/src/methods/ok_expect.rs +++ b/src/tools/clippy/clippy_lints/src/methods/ok_expect.rs @@ -12,7 +12,7 @@ use super::OK_EXPECT; pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr<'_>) { if_chain! { // lint if the caller of `ok()` is a `Result` - if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::result_type); + if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::Result); let result_type = cx.typeck_results().expr_ty(recv); if let Some(error_type) = get_error_type(cx, result_type); if has_debug_impl(error_type, cx); @@ -33,7 +33,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr /// Given a `Result` type, return its error type (`E`). fn get_error_type<'a>(cx: &LateContext<'_>, ty: Ty<'a>) -> Option> { match ty.kind() { - ty::Adt(_, substs) if is_type_diagnostic_item(cx, ty, sym::result_type) => substs.types().nth(1), + ty::Adt(_, substs) if is_type_diagnostic_item(cx, ty, sym::Result) => substs.types().nth(1), _ => None, } } @@ -41,6 +41,6 @@ fn get_error_type<'a>(cx: &LateContext<'_>, ty: Ty<'a>) -> Option> { /// This checks whether a given type is known to implement Debug. fn has_debug_impl<'tcx>(ty: Ty<'tcx>, cx: &LateContext<'tcx>) -> bool { cx.tcx - .get_diagnostic_item(sym::debug_trait) + .get_diagnostic_item(sym::Debug) .map_or(false, |debug| implements_trait(cx, ty, debug, &[])) } diff --git a/src/tools/clippy/clippy_lints/src/methods/option_as_ref_deref.rs b/src/tools/clippy/clippy_lints/src/methods/option_as_ref_deref.rs index 5a57135038..d3f40d2620 100644 --- a/src/tools/clippy/clippy_lints/src/methods/option_as_ref_deref.rs +++ b/src/tools/clippy/clippy_lints/src/methods/option_as_ref_deref.rs @@ -28,7 +28,7 @@ pub(super) fn check<'tcx>( let same_mutability = |m| (is_mut && m == &hir::Mutability::Mut) || (!is_mut && m == &hir::Mutability::Not); let option_ty = cx.typeck_results().expr_ty(as_ref_recv); - if !is_type_diagnostic_item(cx, option_ty, sym::option_type) { + if !is_type_diagnostic_item(cx, option_ty, sym::Option) { return; } diff --git a/src/tools/clippy/clippy_lints/src/methods/option_map_or_none.rs b/src/tools/clippy/clippy_lints/src/methods/option_map_or_none.rs index 36a1c13d5b..e99b6b07d1 100644 --- a/src/tools/clippy/clippy_lints/src/methods/option_map_or_none.rs +++ b/src/tools/clippy/clippy_lints/src/methods/option_map_or_none.rs @@ -19,8 +19,8 @@ pub(super) fn check<'tcx>( def_arg: &'tcx hir::Expr<'_>, map_arg: &'tcx hir::Expr<'_>, ) { - let is_option = is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::option_type); - let is_result = is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::result_type); + let is_option = is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::Option); + let is_result = is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::Result); // There are two variants of this `map_or` lint: // (1) using `map_or` as an adapter from `Result` to `Option` diff --git a/src/tools/clippy/clippy_lints/src/methods/option_map_unwrap_or.rs b/src/tools/clippy/clippy_lints/src/methods/option_map_unwrap_or.rs index 5bca49dec2..2faa6a69f8 100644 --- a/src/tools/clippy/clippy_lints/src/methods/option_map_unwrap_or.rs +++ b/src/tools/clippy/clippy_lints/src/methods/option_map_unwrap_or.rs @@ -25,7 +25,7 @@ pub(super) fn check<'tcx>( map_span: Span, ) { // lint if the caller of `map()` is an `Option` - if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::option_type) { + if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::Option) { if !is_copy(cx, cx.typeck_results().expr_ty(unwrap_arg)) { // Do not lint if the `map` argument uses identifiers in the `map` // argument that are also used in the `unwrap_or` argument diff --git a/src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs b/src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs index c1d22e5d72..fe9ffde0d3 100644 --- a/src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs +++ b/src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs @@ -96,16 +96,16 @@ pub(super) fn check<'tcx>( (&paths::RESULT, true, &["or", "unwrap_or"], "else"), ]; - if let hir::ExprKind::MethodCall(path, _, args, _) = &arg.kind { + if let hir::ExprKind::MethodCall(path, _, [self_arg, ..], _) = &arg.kind { if path.ident.name == sym::len { - let ty = cx.typeck_results().expr_ty(&args[0]).peel_refs(); + let ty = cx.typeck_results().expr_ty(self_arg).peel_refs(); match ty.kind() { ty::Slice(_) | ty::Array(_, _) | ty::Str => return, _ => (), } - if is_type_diagnostic_item(cx, ty, sym::vec_type) { + if is_type_diagnostic_item(cx, ty, sym::Vec) { return; } } @@ -178,12 +178,12 @@ pub(super) fn check<'tcx>( hir::ExprKind::Index(..) | hir::ExprKind::MethodCall(..) => { check_general_case(cx, name, method_span, &args[0], &args[1], expr.span, None); }, - hir::ExprKind::Block(block, _) => { - if let BlockCheckMode::UnsafeBlock(UnsafeSource::UserProvided) = block.rules { - if let Some(block_expr) = block.expr { - if let hir::ExprKind::MethodCall(..) = block_expr.kind { - check_general_case(cx, name, method_span, &args[0], &args[1], expr.span, None); - } + hir::ExprKind::Block(block, _) + if block.rules == BlockCheckMode::UnsafeBlock(UnsafeSource::UserProvided) => + { + if let Some(block_expr) = block.expr { + if let hir::ExprKind::MethodCall(..) = block_expr.kind { + check_general_case(cx, name, method_span, &args[0], &args[1], expr.span, None); } } }, diff --git a/src/tools/clippy/clippy_lints/src/methods/search_is_some.rs b/src/tools/clippy/clippy_lints/src/methods/search_is_some.rs index ecec6fc3bb..0f2e58d898 100644 --- a/src/tools/clippy/clippy_lints/src/methods/search_is_some.rs +++ b/src/tools/clippy/clippy_lints/src/methods/search_is_some.rs @@ -101,7 +101,7 @@ pub(super) fn check<'tcx>( else if search_method == "find" { let is_string_or_str_slice = |e| { let self_ty = cx.typeck_results().expr_ty(e).peel_refs(); - if is_type_diagnostic_item(cx, self_ty, sym::string_type) { + if is_type_diagnostic_item(cx, self_ty, sym::String) { true } else { *self_ty.kind() == ty::Str diff --git a/src/tools/clippy/clippy_lints/src/methods/string_extend_chars.rs b/src/tools/clippy/clippy_lints/src/methods/string_extend_chars.rs index 6e7890a308..d06658f2a5 100644 --- a/src/tools/clippy/clippy_lints/src/methods/string_extend_chars.rs +++ b/src/tools/clippy/clippy_lints/src/methods/string_extend_chars.rs @@ -12,7 +12,7 @@ use super::STRING_EXTEND_CHARS; pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr<'_>, arg: &hir::Expr<'_>) { let obj_ty = cx.typeck_results().expr_ty(recv).peel_refs(); - if !is_type_diagnostic_item(cx, obj_ty, sym::string_type) { + if !is_type_diagnostic_item(cx, obj_ty, sym::String) { return; } if let Some(arglists) = method_chain_args(arg, &["chars"]) { @@ -20,7 +20,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr let self_ty = cx.typeck_results().expr_ty(target).peel_refs(); let ref_str = if *self_ty.kind() == ty::Str { "" - } else if is_type_diagnostic_item(cx, self_ty, sym::string_type) { + } else if is_type_diagnostic_item(cx, self_ty, sym::String) { "&" } else { return; diff --git a/src/tools/clippy/clippy_lints/src/methods/suspicious_map.rs b/src/tools/clippy/clippy_lints/src/methods/suspicious_map.rs index 0fd0668c73..18ded29191 100644 --- a/src/tools/clippy/clippy_lints/src/methods/suspicious_map.rs +++ b/src/tools/clippy/clippy_lints/src/methods/suspicious_map.rs @@ -28,7 +28,7 @@ pub fn check<'tcx>(cx: &LateContext<'tcx>, expr: &hir::Expr<'_>, count_recv: &hi expr.span, "this call to `map()` won't have an effect on the call to `count()`", None, - "make sure you did not confuse `map` with `filter` or `for_each`", + "make sure you did not confuse `map` with `filter`, `for_each` or `inspect`", ); } } diff --git a/src/tools/clippy/clippy_lints/src/methods/suspicious_splitn.rs b/src/tools/clippy/clippy_lints/src/methods/suspicious_splitn.rs index a271df6057..1c546a15bf 100644 --- a/src/tools/clippy/clippy_lints/src/methods/suspicious_splitn.rs +++ b/src/tools/clippy/clippy_lints/src/methods/suspicious_splitn.rs @@ -1,4 +1,3 @@ -use clippy_utils::consts::{constant, Constant}; use clippy_utils::diagnostics::span_lint_and_note; use if_chain::if_chain; use rustc_ast::LitKind; @@ -8,15 +7,8 @@ use rustc_span::source_map::Spanned; use super::SUSPICIOUS_SPLITN; -pub(super) fn check( - cx: &LateContext<'_>, - method_name: &str, - expr: &Expr<'_>, - self_arg: &Expr<'_>, - count_arg: &Expr<'_>, -) { +pub(super) fn check(cx: &LateContext<'_>, method_name: &str, expr: &Expr<'_>, self_arg: &Expr<'_>, count: u128) { if_chain! { - if let Some((Constant::Int(count), _)) = constant(cx, cx.typeck_results(), count_arg); if count <= 1; if let Some(call_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id); if let Some(impl_id) = cx.tcx.impl_of_method(call_id); @@ -24,9 +16,9 @@ pub(super) fn check( if lang_items.slice_impl() == Some(impl_id) || lang_items.str_impl() == Some(impl_id); then { // Ignore empty slice and string literals when used with a literal count. - if (matches!(self_arg.kind, ExprKind::Array([])) + if matches!(self_arg.kind, ExprKind::Array([])) || matches!(self_arg.kind, ExprKind::Lit(Spanned { node: LitKind::Str(s, _), .. }) if s.is_empty()) - ) && matches!(count_arg.kind, ExprKind::Lit(_)) + { return; } diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_filter_map.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_filter_map.rs index 8b66587bfd..59bdfb923e 100644 --- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_filter_map.rs +++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_filter_map.rs @@ -35,8 +35,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, arg: &hir::Expr< let in_ty = cx.typeck_results().node_type(body.params[0].hir_id); match cx.typeck_results().expr_ty(&body.value).kind() { ty::Adt(adt, subst) - if cx.tcx.is_diagnostic_item(sym::option_type, adt.did) - && TyS::same_type(in_ty, subst.type_at(0)) => + if cx.tcx.is_diagnostic_item(sym::Option, adt.did) && TyS::same_type(in_ty, subst.type_at(0)) => { "filter" }, diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_lazy_eval.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_lazy_eval.rs index b7380883a5..740af750b4 100644 --- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_lazy_eval.rs +++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_lazy_eval.rs @@ -18,8 +18,8 @@ pub(super) fn check<'tcx>( arg: &'tcx hir::Expr<'_>, simplify_using: &str, ) { - let is_option = is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::option_type); - let is_result = is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::result_type); + let is_option = is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::Option); + let is_result = is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::Result); if is_option || is_result { if let hir::ExprKind::Closure(_, _, eid, _, _) = arg.kind { diff --git a/src/tools/clippy/clippy_lints/src/methods/unwrap_or_else_default.rs b/src/tools/clippy/clippy_lints/src/methods/unwrap_or_else_default.rs index 677aa80e1b..276467b1df 100644 --- a/src/tools/clippy/clippy_lints/src/methods/unwrap_or_else_default.rs +++ b/src/tools/clippy/clippy_lints/src/methods/unwrap_or_else_default.rs @@ -19,8 +19,8 @@ pub(super) fn check<'tcx>( // ^^^^^^^^^- recv ^^^^^^^^^^^^^^^^- u_arg // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- expr let recv_ty = cx.typeck_results().expr_ty(recv); - let is_option = is_type_diagnostic_item(cx, recv_ty, sym::option_type); - let is_result = is_type_diagnostic_item(cx, recv_ty, sym::result_type); + let is_option = is_type_diagnostic_item(cx, recv_ty, sym::Option); + let is_result = is_type_diagnostic_item(cx, recv_ty, sym::Result); if_chain! { if is_option || is_result; diff --git a/src/tools/clippy/clippy_lints/src/methods/unwrap_used.rs b/src/tools/clippy/clippy_lints/src/methods/unwrap_used.rs index 7fd1948594..44676d78c6 100644 --- a/src/tools/clippy/clippy_lints/src/methods/unwrap_used.rs +++ b/src/tools/clippy/clippy_lints/src/methods/unwrap_used.rs @@ -10,9 +10,9 @@ use super::UNWRAP_USED; pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr<'_>) { let obj_ty = cx.typeck_results().expr_ty(recv).peel_refs(); - let mess = if is_type_diagnostic_item(cx, obj_ty, sym::option_type) { + let mess = if is_type_diagnostic_item(cx, obj_ty, sym::Option) { Some((UNWRAP_USED, "an Option", "None")) - } else if is_type_diagnostic_item(cx, obj_ty, sym::result_type) { + } else if is_type_diagnostic_item(cx, obj_ty, sym::Result) { Some((UNWRAP_USED, "a Result", "Err")) } else { None diff --git a/src/tools/clippy/clippy_lints/src/methods/utils.rs b/src/tools/clippy/clippy_lints/src/methods/utils.rs index 0daea47816..ba2ce73a11 100644 --- a/src/tools/clippy/clippy_lints/src/methods/utils.rs +++ b/src/tools/clippy/clippy_lints/src/methods/utils.rs @@ -17,16 +17,16 @@ pub(super) fn derefs_to_slice<'tcx>( match ty.kind() { ty::Slice(_) => true, ty::Adt(def, _) if def.is_box() => may_slice(cx, ty.boxed_ty()), - ty::Adt(..) => is_type_diagnostic_item(cx, ty, sym::vec_type), + ty::Adt(..) => is_type_diagnostic_item(cx, ty, sym::Vec), ty::Array(_, size) => size.try_eval_usize(cx.tcx, cx.param_env).is_some(), ty::Ref(_, inner, _) => may_slice(cx, inner), _ => false, } } - if let hir::ExprKind::MethodCall(path, _, args, _) = expr.kind { - if path.ident.name == sym::iter && may_slice(cx, cx.typeck_results().expr_ty(&args[0])) { - Some(&args[0]) + if let hir::ExprKind::MethodCall(path, _, [self_arg, ..], _) = &expr.kind { + if path.ident.name == sym::iter && may_slice(cx, cx.typeck_results().expr_ty(self_arg)) { + Some(self_arg) } else { None } diff --git a/src/tools/clippy/clippy_lints/src/misc.rs b/src/tools/clippy/clippy_lints/src/misc.rs index c796abe981..0f32cd9164 100644 --- a/src/tools/clippy/clippy_lints/src/misc.rs +++ b/src/tools/clippy/clippy_lints/src/misc.rs @@ -113,7 +113,7 @@ declare_clippy_lint! { /// if (y - x).abs() > error_margin { } /// ``` pub FLOAT_CMP, - correctness, + pedantic, "using `==` or `!=` on float values instead of comparing difference with an epsilon" } @@ -513,12 +513,12 @@ fn is_signum(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { } if_chain! { - if let ExprKind::MethodCall(method_name, _, expressions, _) = expr.kind; + if let ExprKind::MethodCall(method_name, _, [ref self_arg, ..], _) = expr.kind; if sym!(signum) == method_name.ident.name; // Check that the receiver of the signum() is a float (expressions[0] is the receiver of // the method call) then { - return is_float(cx, &expressions[0]); + return is_float(cx, self_arg); } } false diff --git a/src/tools/clippy/clippy_lints/src/missing_doc.rs b/src/tools/clippy/clippy_lints/src/missing_doc.rs index 940eee7a78..564f021268 100644 --- a/src/tools/clippy/clippy_lints/src/missing_doc.rs +++ b/src/tools/clippy/clippy_lints/src/missing_doc.rs @@ -12,6 +12,7 @@ use rustc_hir as hir; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::ty; use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_span::def_id::CRATE_DEF_ID; use rustc_span::source_map::Span; use rustc_span::sym; @@ -78,9 +79,7 @@ impl MissingDoc { return; } - let has_doc = attrs - .iter() - .any(|a| a.doc_str().is_some()); + let has_doc = attrs.iter().any(|a| a.doc_str().is_some()); if !has_doc { span_lint( cx, @@ -104,9 +103,9 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc { self.doc_hidden_stack.pop().expect("empty doc_hidden_stack"); } - fn check_crate(&mut self, cx: &LateContext<'tcx>, krate: &'tcx hir::Crate<'_>) { + fn check_crate(&mut self, cx: &LateContext<'tcx>) { let attrs = cx.tcx.hir().attrs(hir::CRATE_HIR_ID); - self.check_missing_docs_attrs(cx, attrs, krate.module().inner, "the", "crate"); + self.check_missing_docs_attrs(cx, attrs, cx.tcx.def_span(CRATE_DEF_ID), "the", "crate"); } fn check_item(&mut self, cx: &LateContext<'tcx>, it: &'tcx hir::Item<'_>) { diff --git a/src/tools/clippy/clippy_lints/src/missing_enforced_import_rename.rs b/src/tools/clippy/clippy_lints/src/missing_enforced_import_rename.rs index 9d27870321..448bfc2fdd 100644 --- a/src/tools/clippy/clippy_lints/src/missing_enforced_import_rename.rs +++ b/src/tools/clippy/clippy_lints/src/missing_enforced_import_rename.rs @@ -2,7 +2,7 @@ use clippy_utils::{diagnostics::span_lint_and_sugg, source::snippet_opt}; use rustc_data_structures::fx::FxHashMap; use rustc_errors::Applicability; -use rustc_hir::{def::Res, def_id::DefId, Crate, Item, ItemKind, UseKind}; +use rustc_hir::{def::Res, def_id::DefId, Item, ItemKind, UseKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::Symbol; @@ -55,7 +55,7 @@ impl ImportRename { impl_lint_pass!(ImportRename => [MISSING_ENFORCED_IMPORT_RENAMES]); impl LateLintPass<'_> for ImportRename { - fn check_crate(&mut self, cx: &LateContext<'_>, _: &Crate<'_>) { + fn check_crate(&mut self, cx: &LateContext<'_>) { for Rename { path, rename } in &self.conf_renames { if let Res::Def(_, id) = clippy_utils::path_to_res(cx, &path.split("::").collect::>()) { self.renames.insert(id, Symbol::intern(rename)); diff --git a/src/tools/clippy/clippy_lints/src/module_style.rs b/src/tools/clippy/clippy_lints/src/module_style.rs new file mode 100644 index 0000000000..d41b547456 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/module_style.rs @@ -0,0 +1,178 @@ +use std::{ + ffi::OsString, + path::{Component, Path}, +}; + +use rustc_ast::ast; +use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_lint::{EarlyContext, EarlyLintPass, Level, LintContext}; +use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_span::{FileName, RealFileName, SourceFile, Span, SyntaxContext}; + +declare_clippy_lint! { + /// ### What it does + /// Checks that module layout uses only self named module files, bans mod.rs files. + /// + /// ### Why is this bad? + /// Having multiple module layout styles in a project can be confusing. + /// + /// ### Example + /// ```text + /// src/ + /// stuff/ + /// stuff_files.rs + /// mod.rs + /// lib.rs + /// ``` + /// Use instead: + /// ```text + /// src/ + /// stuff/ + /// stuff_files.rs + /// stuff.rs + /// lib.rs + /// ``` + pub MOD_MODULE_FILES, + restriction, + "checks that module layout is consistent" +} + +declare_clippy_lint! { + /// ### What it does + /// Checks that module layout uses only mod.rs files. + /// + /// ### Why is this bad? + /// Having multiple module layout styles in a project can be confusing. + /// + /// ### Example + /// ```text + /// src/ + /// stuff/ + /// stuff_files.rs + /// stuff.rs + /// lib.rs + /// ``` + /// Use instead: + /// ```text + /// src/ + /// stuff/ + /// stuff_files.rs + /// mod.rs + /// lib.rs + /// ``` + + pub SELF_NAMED_MODULE_FILES, + restriction, + "checks that module layout is consistent" +} + +pub struct ModStyle; + +impl_lint_pass!(ModStyle => [MOD_MODULE_FILES, SELF_NAMED_MODULE_FILES]); + +impl EarlyLintPass for ModStyle { + fn check_crate(&mut self, cx: &EarlyContext<'_>, _: &ast::Crate) { + if cx.builder.lint_level(MOD_MODULE_FILES).0 == Level::Allow + && cx.builder.lint_level(SELF_NAMED_MODULE_FILES).0 == Level::Allow + { + return; + } + + let files = cx.sess.source_map().files(); + + let trim_to_src = if let RealFileName::LocalPath(p) = &cx.sess.opts.working_dir { + p.to_string_lossy() + } else { + return; + }; + + // `folder_segments` is all unique folder path segments `path/to/foo.rs` gives + // `[path, to]` but not foo + let mut folder_segments = FxHashSet::default(); + // `mod_folders` is all the unique folder names that contain a mod.rs file + let mut mod_folders = FxHashSet::default(); + // `file_map` maps file names to the full path including the file name + // `{ foo => path/to/foo.rs, .. } + let mut file_map = FxHashMap::default(); + for file in files.iter() { + match &file.name { + FileName::Real(RealFileName::LocalPath(lp)) + if lp.to_string_lossy().starts_with(trim_to_src.as_ref()) => + { + let p = lp.to_string_lossy(); + let path = Path::new(p.trim_start_matches(trim_to_src.as_ref())); + if let Some(stem) = path.file_stem() { + file_map.insert(stem.to_os_string(), (file, path.to_owned())); + } + process_paths_for_mod_files(path, &mut folder_segments, &mut mod_folders); + check_self_named_mod_exists(cx, path, file); + }, + _ => {}, + } + } + + for folder in &folder_segments { + if !mod_folders.contains(folder) { + if let Some((file, path)) = file_map.get(folder) { + let mut correct = path.clone(); + correct.pop(); + correct.push(folder); + correct.push("mod.rs"); + cx.struct_span_lint( + SELF_NAMED_MODULE_FILES, + Span::new(file.start_pos, file.start_pos, SyntaxContext::root(), None), + |build| { + let mut lint = + build.build(&format!("`mod.rs` files are required, found `{}`", path.display())); + lint.help(&format!("move `{}` to `{}`", path.display(), correct.display(),)); + lint.emit(); + }, + ); + } + } + } + } +} + +/// For each `path` we add each folder component to `folder_segments` and if the file name +/// is `mod.rs` we add it's parent folder to `mod_folders`. +fn process_paths_for_mod_files( + path: &Path, + folder_segments: &mut FxHashSet, + mod_folders: &mut FxHashSet, +) { + let mut comp = path.components().rev().peekable(); + let _ = comp.next(); + if path.ends_with("mod.rs") { + mod_folders.insert(comp.peek().map(|c| c.as_os_str().to_owned()).unwrap_or_default()); + } + let folders = comp + .filter_map(|c| { + if let Component::Normal(s) = c { + Some(s.to_os_string()) + } else { + None + } + }) + .collect::>(); + folder_segments.extend(folders); +} + +/// Checks every path for the presence of `mod.rs` files and emits the lint if found. +fn check_self_named_mod_exists(cx: &EarlyContext<'_>, path: &Path, file: &SourceFile) { + if path.ends_with("mod.rs") { + let mut mod_file = path.to_path_buf(); + mod_file.pop(); + mod_file.set_extension("rs"); + + cx.struct_span_lint( + MOD_MODULE_FILES, + Span::new(file.start_pos, file.start_pos, SyntaxContext::root(), None), + |build| { + let mut lint = build.build(&format!("`mod.rs` files are not allowed, found `{}`", path.display())); + lint.help(&format!("move `{}` to `{}`", path.display(), mod_file.display(),)); + lint.emit(); + }, + ); + } +} diff --git a/src/tools/clippy/clippy_lints/src/modulo_arithmetic.rs b/src/tools/clippy/clippy_lints/src/modulo_arithmetic.rs index 2d14943b56..f45e68233a 100644 --- a/src/tools/clippy/clippy_lints/src/modulo_arithmetic.rs +++ b/src/tools/clippy/clippy_lints/src/modulo_arithmetic.rs @@ -128,7 +128,7 @@ impl<'tcx> LateLintPass<'tcx> for ModuloArithmetic { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { match &expr.kind { ExprKind::Binary(op, lhs, rhs) | ExprKind::AssignOp(op, lhs, rhs) => { - if let BinOpKind::Rem = op.node { + if op.node == BinOpKind::Rem { let lhs_operand = analyze_operand(lhs, cx, expr); let rhs_operand = analyze_operand(rhs, cx, expr); if_chain! { diff --git a/src/tools/clippy/clippy_lints/src/multiple_crate_versions.rs b/src/tools/clippy/clippy_lints/src/multiple_crate_versions.rs index 1c61970fdc..816b2f275f 100644 --- a/src/tools/clippy/clippy_lints/src/multiple_crate_versions.rs +++ b/src/tools/clippy/clippy_lints/src/multiple_crate_versions.rs @@ -3,7 +3,7 @@ use clippy_utils::diagnostics::span_lint; use clippy_utils::is_lint_allowed; use rustc_hir::def_id::LOCAL_CRATE; -use rustc_hir::{Crate, CRATE_HIR_ID}; +use rustc_hir::CRATE_HIR_ID; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::DUMMY_SP; @@ -41,7 +41,7 @@ declare_clippy_lint! { declare_lint_pass!(MultipleCrateVersions => [MULTIPLE_CRATE_VERSIONS]); impl LateLintPass<'_> for MultipleCrateVersions { - fn check_crate(&mut self, cx: &LateContext<'_>, _: &Crate<'_>) { + fn check_crate(&mut self, cx: &LateContext<'_>) { if is_lint_allowed(cx, MULTIPLE_CRATE_VERSIONS, CRATE_HIR_ID) { return; } diff --git a/src/tools/clippy/clippy_lints/src/mut_key.rs b/src/tools/clippy/clippy_lints/src/mut_key.rs index 2c7681c45a..8476257f08 100644 --- a/src/tools/clippy/clippy_lints/src/mut_key.rs +++ b/src/tools/clippy/clippy_lints/src/mut_key.rs @@ -3,7 +3,7 @@ use clippy_utils::trait_ref_of_method; use rustc_hir as hir; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::TypeFoldable; -use rustc_middle::ty::{Adt, Array, RawPtr, Ref, Slice, Tuple, Ty, TypeAndMut}; +use rustc_middle::ty::{Adt, Array, Ref, Slice, Tuple, Ty}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; use rustc_span::symbol::sym; @@ -19,10 +19,29 @@ declare_clippy_lint! { /// so having types with interior mutability is a bad idea. /// /// ### Known problems - /// It's correct to use a struct, that contains interior mutability - /// as a key, when its `Hash` implementation doesn't access any of the interior mutable types. - /// However, this lint is unable to recognize this, so it causes a false positive in theses cases. - /// The `bytes` crate is a great example of this. + /// + /// #### False Positives + /// It's correct to use a struct that contains interior mutability as a key, when its + /// implementation of `Hash` or `Ord` doesn't access any of the interior mutable types. + /// However, this lint is unable to recognize this, so it will often cause false positives in + /// theses cases. The `bytes` crate is a great example of this. + /// + /// #### False Negatives + /// For custom `struct`s/`enum`s, this lint is unable to check for interior mutability behind + /// indirection. For example, `struct BadKey<'a>(&'a Cell)` will be seen as immutable + /// and cause a false negative if its implementation of `Hash`/`Ord` accesses the `Cell`. + /// + /// This lint does check a few cases for indirection. Firstly, using some standard library + /// types (`Option`, `Result`, `Box`, `Rc`, `Arc`, `Vec`, `VecDeque`, `BTreeMap` and + /// `BTreeSet`) directly as keys (e.g. in `HashMap>, ()>`) **will** trigger the + /// lint, because the impls of `Hash`/`Ord` for these types directly call `Hash`/`Ord` on their + /// contained type. + /// + /// Secondly, the implementations of `Hash` and `Ord` for raw pointers (`*const T` or `*mut T`) + /// apply only to the **address** of the contained value. Therefore, interior mutability + /// behind raw pointers (e.g. in `HashSet<*mut Cell>`) can't impact the value of `Hash` + /// or `Ord`, and therefore will not trigger this link. For more info, see issue + /// [#6745](https://github.com/rust-lang/rust-clippy/issues/6745). /// /// ### Example /// ```rust @@ -103,30 +122,52 @@ fn check_sig<'tcx>(cx: &LateContext<'tcx>, item_hir_id: hir::HirId, decl: &hir:: fn check_ty<'tcx>(cx: &LateContext<'tcx>, span: Span, ty: Ty<'tcx>) { let ty = ty.peel_refs(); if let Adt(def, substs) = ty.kind() { - if [sym::hashmap_type, sym::BTreeMap, sym::hashset_type, sym::BTreeMap] + let is_keyed_type = [sym::HashMap, sym::BTreeMap, sym::HashSet, sym::BTreeSet] .iter() - .any(|diag_item| cx.tcx.is_diagnostic_item(*diag_item, def.did)) - && is_mutable_type(cx, substs.type_at(0), span) - { + .any(|diag_item| cx.tcx.is_diagnostic_item(*diag_item, def.did)); + if is_keyed_type && is_interior_mutable_type(cx, substs.type_at(0), span) { span_lint(cx, MUTABLE_KEY_TYPE, span, "mutable key type"); } } } -fn is_mutable_type<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, span: Span) -> bool { +/// Determines if a type contains interior mutability which would affect its implementation of +/// [`Hash`] or [`Ord`]. +fn is_interior_mutable_type<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, span: Span) -> bool { match *ty.kind() { - RawPtr(TypeAndMut { ty: inner_ty, mutbl }) | Ref(_, inner_ty, mutbl) => { - mutbl == hir::Mutability::Mut || is_mutable_type(cx, inner_ty, span) - }, - Slice(inner_ty) => is_mutable_type(cx, inner_ty, span), + Ref(_, inner_ty, mutbl) => mutbl == hir::Mutability::Mut || is_interior_mutable_type(cx, inner_ty, span), + Slice(inner_ty) => is_interior_mutable_type(cx, inner_ty, span), Array(inner_ty, size) => { - size.try_eval_usize(cx.tcx, cx.param_env).map_or(true, |u| u != 0) && is_mutable_type(cx, inner_ty, span) + size.try_eval_usize(cx.tcx, cx.param_env).map_or(true, |u| u != 0) + && is_interior_mutable_type(cx, inner_ty, span) }, - Tuple(..) => ty.tuple_fields().any(|ty| is_mutable_type(cx, ty, span)), - Adt(..) => { - !ty.has_escaping_bound_vars() - && cx.tcx.layout_of(cx.param_env.and(ty)).is_ok() - && !ty.is_freeze(cx.tcx.at(span), cx.param_env) + Tuple(..) => ty.tuple_fields().any(|ty| is_interior_mutable_type(cx, ty, span)), + Adt(def, substs) => { + // Special case for collections in `std` who's impl of `Hash` or `Ord` delegates to + // that of their type parameters. Note: we don't include `HashSet` and `HashMap` + // because they have no impl for `Hash` or `Ord`. + let is_std_collection = [ + sym::Option, + sym::Result, + sym::LinkedList, + sym::Vec, + sym::VecDeque, + sym::BTreeMap, + sym::BTreeSet, + sym::Rc, + sym::Arc, + ] + .iter() + .any(|diag_item| cx.tcx.is_diagnostic_item(*diag_item, def.did)); + let is_box = Some(def.did) == cx.tcx.lang_items().owned_box(); + if is_std_collection || is_box { + // The type is mutable if any of its type parameters are + substs.types().any(|ty| is_interior_mutable_type(cx, ty, span)) + } else { + !ty.has_escaping_bound_vars() + && cx.tcx.layout_of(cx.param_env.and(ty)).is_ok() + && !ty.is_freeze(cx.tcx.at(span), cx.param_env) + } }, _ => false, } diff --git a/src/tools/clippy/clippy_lints/src/mut_mutex_lock.rs b/src/tools/clippy/clippy_lints/src/mut_mutex_lock.rs index 85e870632a..b96fa4774c 100644 --- a/src/tools/clippy/clippy_lints/src/mut_mutex_lock.rs +++ b/src/tools/clippy/clippy_lints/src/mut_mutex_lock.rs @@ -6,6 +6,7 @@ use rustc_hir::{Expr, ExprKind, Mutability}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty; use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_span::sym; declare_clippy_lint! { /// ### What it does @@ -47,11 +48,11 @@ declare_lint_pass!(MutMutexLock => [MUT_MUTEX_LOCK]); impl<'tcx> LateLintPass<'tcx> for MutMutexLock { fn check_expr(&mut self, cx: &LateContext<'tcx>, ex: &'tcx Expr<'tcx>) { if_chain! { - if let ExprKind::MethodCall(path, method_span, args, _) = &ex.kind; + if let ExprKind::MethodCall(path, method_span, [self_arg, ..], _) = &ex.kind; if path.ident.name == sym!(lock); - let ty = cx.typeck_results().expr_ty(&args[0]); + let ty = cx.typeck_results().expr_ty(self_arg); if let ty::Ref(_, inner_ty, Mutability::Mut) = ty.kind(); - if is_type_diagnostic_item(cx, inner_ty, sym!(mutex_type)); + if is_type_diagnostic_item(cx, inner_ty, sym::Mutex); then { span_lint_and_sugg( cx, diff --git a/src/tools/clippy/clippy_lints/src/mutex_atomic.rs b/src/tools/clippy/clippy_lints/src/mutex_atomic.rs index 436ceec6cf..5feddcbfc6 100644 --- a/src/tools/clippy/clippy_lints/src/mutex_atomic.rs +++ b/src/tools/clippy/clippy_lints/src/mutex_atomic.rs @@ -8,6 +8,7 @@ use rustc_hir::Expr; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::{self, Ty}; use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_span::sym; declare_clippy_lint! { /// ### What it does @@ -74,7 +75,7 @@ impl<'tcx> LateLintPass<'tcx> for Mutex { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { let ty = cx.typeck_results().expr_ty(expr); if let ty::Adt(_, subst) = ty.kind() { - if is_type_diagnostic_item(cx, ty, sym!(mutex_type)) { + if is_type_diagnostic_item(cx, ty, sym::Mutex) { let mutex_param = subst.type_at(0); if let Some(atomic_name) = get_atomic_name(mutex_param) { let msg = format!( diff --git a/src/tools/clippy/clippy_lints/src/needless_bool.rs b/src/tools/clippy/clippy_lints/src/needless_bool.rs index c9dd94400e..9194465350 100644 --- a/src/tools/clippy/clippy_lints/src/needless_bool.rs +++ b/src/tools/clippy/clippy_lints/src/needless_bool.rs @@ -248,7 +248,7 @@ fn check_comparison<'a, 'tcx>( if l_ty.is_bool() && r_ty.is_bool() { let mut applicability = Applicability::MachineApplicable; - if let BinOpKind::Eq = op.node { + if op.node == BinOpKind::Eq { let expression_info = one_side_is_unary_not(left_side, right_side); if expression_info.one_side_is_unary_not { span_lint_and_sugg( diff --git a/src/tools/clippy/clippy_lints/src/needless_borrow.rs b/src/tools/clippy/clippy_lints/src/needless_borrow.rs index ba8f9446af..f1be90c44f 100644 --- a/src/tools/clippy/clippy_lints/src/needless_borrow.rs +++ b/src/tools/clippy/clippy_lints/src/needless_borrow.rs @@ -104,26 +104,36 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessBorrow { if e.span.from_expansion() { return; } - if let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, inner) = e.kind { + if let ExprKind::AddrOf(BorrowKind::Ref, mutability, inner) = e.kind { if let ty::Ref(_, ty, _) = cx.typeck_results().expr_ty(inner).kind() { for adj3 in cx.typeck_results().expr_adjustments(e).windows(3) { - if let [Adjustment { - kind: Adjust::Deref(_), .. - }, Adjustment { - kind: Adjust::Deref(_), .. - }, Adjustment { - kind: Adjust::Borrow(_), - .. - }] = *adj3 + if let [ + Adjustment { + kind: Adjust::Deref(_), .. + }, + Adjustment { + kind: Adjust::Deref(_), .. + }, + Adjustment { + kind: Adjust::Borrow(_), + .. + }, + ] = *adj3 { + let help_msg_ty = if matches!(mutability, Mutability::Not) { + format!("&{}", ty) + } else { + format!("&mut {}", ty) + }; + span_lint_and_then( cx, NEEDLESS_BORROW, e.span, &format!( - "this expression borrows a reference (`&{}`) that is immediately dereferenced \ + "this expression borrows a reference (`{}`) that is immediately dereferenced \ by the compiler", - ty + help_msg_ty ), |diag| { if let Some(snippet) = snippet_opt(cx, inner.span) { diff --git a/src/tools/clippy/clippy_lints/src/needless_continue.rs b/src/tools/clippy/clippy_lints/src/needless_continue.rs index 5a50cc48d6..7aa93ed783 100644 --- a/src/tools/clippy/clippy_lints/src/needless_continue.rs +++ b/src/tools/clippy/clippy_lints/src/needless_continue.rs @@ -36,9 +36,8 @@ use clippy_utils::diagnostics::span_lint_and_help; use clippy_utils::source::{indent_of, snippet, snippet_block}; use rustc_ast::ast; -use rustc_lint::{EarlyContext, EarlyLintPass}; +use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use rustc_span::source_map::{original_sp, DUMMY_SP}; use rustc_span::Span; declare_clippy_lint! { @@ -270,7 +269,7 @@ struct LintData<'a> { /// The 0-based index of the `if` statement in the containing loop block. stmt_idx: usize, /// The statements of the loop block. - block_stmts: &'a [ast::Stmt], + loop_block: &'a ast::Block, } const MSG_REDUNDANT_CONTINUE_EXPRESSION: &str = "this `continue` expression is redundant"; @@ -343,10 +342,10 @@ fn suggestion_snippet_for_continue_inside_else<'a>(cx: &EarlyContext<'_>, data: let indent = span_of_first_expr_in_block(data.if_block) .and_then(|span| indent_of(cx, span)) .unwrap_or(0); - let to_annex = data.block_stmts[data.stmt_idx + 1..] + let to_annex = data.loop_block.stmts[data.stmt_idx + 1..] .iter() - .map(|stmt| original_sp(stmt.span, DUMMY_SP)) - .map(|span| { + .map(|stmt| { + let span = cx.sess().source_map().stmt_span(stmt.span, data.loop_block.span); let snip = snippet_block(cx, span, "..", None).into_owned(); snip.lines() .map(|line| format!("{}{}", " ".repeat(indent), line)) @@ -393,7 +392,7 @@ fn check_and_warn<'a>(cx: &EarlyContext<'_>, expr: &'a ast::Expr) { if_cond: cond, if_block: then_block, else_expr, - block_stmts: &loop_block.stmts, + loop_block, }; if needless_continue_in_else(else_expr, label) { emit_warning( diff --git a/src/tools/clippy/clippy_lints/src/needless_option_as_deref.rs b/src/tools/clippy/clippy_lints/src/needless_option_as_deref.rs new file mode 100644 index 0000000000..fbdaaf51f7 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/needless_option_as_deref.rs @@ -0,0 +1,66 @@ +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::in_macro; +use clippy_utils::source::snippet_opt; +use clippy_utils::ty::is_type_diagnostic_item; +use rustc_errors::Applicability; +use rustc_hir::{Expr, ExprKind}; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::ty::TyS; +use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_span::symbol::sym; + +declare_clippy_lint! { + /// ### What it does + /// Checks for no-op uses of Option::{as_deref,as_deref_mut}, + /// for example, `Option<&T>::as_deref()` returns the same type. + /// + /// ### Why is this bad? + /// Redundant code and improving readability. + /// + /// ### Example + /// ```rust + /// let a = Some(&1); + /// let b = a.as_deref(); // goes from Option<&i32> to Option<&i32> + /// ``` + /// Could be written as: + /// ```rust + /// let a = Some(&1); + /// let b = a; + /// ``` + pub NEEDLESS_OPTION_AS_DEREF, + complexity, + "no-op use of `deref` or `deref_mut` method to `Option`." +} + +declare_lint_pass!(OptionNeedlessDeref=> [ + NEEDLESS_OPTION_AS_DEREF, +]); + +impl<'tcx> LateLintPass<'tcx> for OptionNeedlessDeref { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { + if expr.span.from_expansion() || in_macro(expr.span) { + return; + } + let typeck = cx.typeck_results(); + let outer_ty = typeck.expr_ty(expr); + + if_chain! { + if is_type_diagnostic_item(cx,outer_ty,sym::Option); + if let ExprKind::MethodCall(path, _, [sub_expr], _) = expr.kind; + let symbol = path.ident.as_str(); + if symbol=="as_deref" || symbol=="as_deref_mut"; + if TyS::same_type( outer_ty, typeck.expr_ty(sub_expr) ); + then{ + span_lint_and_sugg( + cx, + NEEDLESS_OPTION_AS_DEREF, + expr.span, + "derefed type is same as origin", + "try this", + snippet_opt(cx,sub_expr.span).unwrap(), + Applicability::MachineApplicable + ); + } + } + } +} diff --git a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs index 90b2aa1689..352dc6f8be 100644 --- a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs +++ b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs @@ -206,7 +206,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue { let deref_span = spans_need_deref.get(&canonical_id); if_chain! { - if is_type_diagnostic_item(cx, ty, sym::vec_type); + if is_type_diagnostic_item(cx, ty, sym::Vec); if let Some(clone_spans) = get_spans(cx, Some(body.id()), idx, &[("clone", ".to_owned()")]); if let TyKind::Path(QPath::Resolved(_, path)) = input.kind; @@ -245,7 +245,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue { } } - if is_type_diagnostic_item(cx, ty, sym::string_type) { + if is_type_diagnostic_item(cx, ty, sym::String) { if let Some(clone_spans) = get_spans(cx, Some(body.id()), idx, &[("clone", ".to_string()"), ("as_str", "")]) { diag.span_suggestion( diff --git a/src/tools/clippy/clippy_lints/src/neg_multiply.rs b/src/tools/clippy/clippy_lints/src/neg_multiply.rs index fa36d8fb1b..1b15d29439 100644 --- a/src/tools/clippy/clippy_lints/src/neg_multiply.rs +++ b/src/tools/clippy/clippy_lints/src/neg_multiply.rs @@ -46,7 +46,7 @@ impl<'tcx> LateLintPass<'tcx> for NegMultiply { fn check_mul(cx: &LateContext<'_>, span: Span, lit: &Expr<'_>, exp: &Expr<'_>) { if_chain! { if let ExprKind::Lit(ref l) = lit.kind; - if let Constant::Int(1) = consts::lit_to_constant(&l.node, cx.typeck_results().expr_ty_opt(lit)); + if consts::lit_to_constant(&l.node, cx.typeck_results().expr_ty_opt(lit)) == Constant::Int(1); if cx.typeck_results().expr_ty(exp).is_integral(); then { span_lint(cx, NEG_MULTIPLY, span, "negation by multiplying with `-1`"); diff --git a/src/tools/clippy/clippy_lints/src/new_without_default.rs b/src/tools/clippy/clippy_lints/src/new_without_default.rs index 0ad616a39d..0ac27f1cba 100644 --- a/src/tools/clippy/clippy_lints/src/new_without_default.rs +++ b/src/tools/clippy/clippy_lints/src/new_without_default.rs @@ -69,7 +69,7 @@ impl<'tcx> LateLintPass<'tcx> for NewWithoutDefault { }) = item.kind { for assoc_item in items { - if let hir::AssocItemKind::Fn { has_self: false } = assoc_item.kind { + if assoc_item.kind == (hir::AssocItemKind::Fn { has_self: false }) { let impl_item = cx.tcx.hir().impl_item(assoc_item.id); if in_external_macro(cx.sess(), impl_item.span) { return; diff --git a/src/tools/clippy/clippy_lints/src/no_effect.rs b/src/tools/clippy/clippy_lints/src/no_effect.rs index 28e9e6f438..c5a5cde4b1 100644 --- a/src/tools/clippy/clippy_lints/src/no_effect.rs +++ b/src/tools/clippy/clippy_lints/src/no_effect.rs @@ -96,28 +96,63 @@ impl<'tcx> LateLintPass<'tcx> for NoEffect { 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) { - let mut snippet = String::new(); - for e in reduced { + for e in &reduced { if e.span.from_expansion() { return; } - 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, - "statement can be reduced", - |diag| { - diag.span_suggestion(stmt.span, "replace it with", snippet, Applicability::MachineApplicable); - }, - ); + 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, + ); + }, + ); + } 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, + ); + }, + ); + } } } } 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 2ffc00b449..5b254bc813 100644 --- a/src/tools/clippy/clippy_lints/src/non_expressive_names.rs +++ b/src/tools/clippy/clippy_lints/src/non_expressive_names.rs @@ -43,7 +43,7 @@ declare_clippy_lint! { /// let (a, b, c, d, e, f, g) = (...); /// ``` pub MANY_SINGLE_CHAR_NAMES, - style, + pedantic, "too many single character bindings" } diff --git a/src/tools/clippy/clippy_lints/src/non_send_fields_in_send_ty.rs b/src/tools/clippy/clippy_lints/src/non_send_fields_in_send_ty.rs new file mode 100644 index 0000000000..374b7bd596 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/non_send_fields_in_send_ty.rs @@ -0,0 +1,238 @@ +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::is_lint_allowed; +use clippy_utils::source::snippet; +use clippy_utils::ty::{implements_trait, is_copy}; +use rustc_ast::ImplPolarity; +use rustc_hir::def_id::DefId; +use rustc_hir::{FieldDef, Item, ItemKind, Node}; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::ty::{self, subst::GenericArgKind, Ty}; +use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_span::sym; + +declare_clippy_lint! { + /// ### What it does + /// Warns about fields in struct implementing `Send` that are neither `Send` nor `Copy`. + /// + /// ### Why is this bad? + /// Sending the struct to another thread will transfer the ownership to + /// the new thread by dropping in the current thread during the transfer. + /// This causes soundness issues for non-`Send` fields, as they are also + /// dropped and might not be set up to handle this. + /// + /// See: + /// * [*The Rustonomicon* about *Send and Sync*](https://doc.rust-lang.org/nomicon/send-and-sync.html) + /// * [The documentation of `Send`](https://doc.rust-lang.org/std/marker/trait.Send.html) + /// + /// ### Known Problems + /// Data structures that contain raw pointers may cause false positives. + /// They are sometimes safe to be sent across threads but do not implement + /// the `Send` trait. This lint has a heuristic to filter out basic cases + /// such as `Vec<*const T>`, but it's not perfect. Feel free to create an + /// issue if you have a suggestion on how this heuristic can be improved. + /// + /// ### Example + /// ```rust,ignore + /// struct ExampleStruct { + /// rc_is_not_send: Rc, + /// unbounded_generic_field: T, + /// } + /// + /// // This impl is unsound because it allows sending `!Send` types through `ExampleStruct` + /// unsafe impl Send for ExampleStruct {} + /// ``` + /// Use thread-safe types like [`std::sync::Arc`](https://doc.rust-lang.org/std/sync/struct.Arc.html) + /// or specify correct bounds on generic type parameters (`T: Send`). + pub NON_SEND_FIELDS_IN_SEND_TY, + nursery, + "there is field that does not implement `Send` in a `Send` struct" +} + +#[derive(Copy, Clone)] +pub struct NonSendFieldInSendTy { + enable_raw_pointer_heuristic: bool, +} + +impl NonSendFieldInSendTy { + pub fn new(enable_raw_pointer_heuristic: bool) -> Self { + Self { + enable_raw_pointer_heuristic, + } + } +} + +impl_lint_pass!(NonSendFieldInSendTy => [NON_SEND_FIELDS_IN_SEND_TY]); + +impl<'tcx> LateLintPass<'tcx> for NonSendFieldInSendTy { + fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) { + let ty_allowed_in_send = if self.enable_raw_pointer_heuristic { + ty_allowed_with_raw_pointer_heuristic + } else { + ty_allowed_without_raw_pointer_heuristic + }; + + // Checks if we are in `Send` impl item. + // We start from `Send` impl instead of `check_field_def()` because + // single `AdtDef` may have multiple `Send` impls due to generic + // parameters, and the lint is much easier to implement in this way. + if_chain! { + if let Some(send_trait) = cx.tcx.get_diagnostic_item(sym::Send); + if let ItemKind::Impl(hir_impl) = &item.kind; + if let Some(trait_ref) = &hir_impl.of_trait; + if let Some(trait_id) = trait_ref.trait_def_id(); + if send_trait == trait_id; + if hir_impl.polarity == ImplPolarity::Positive; + if let Some(ty_trait_ref) = cx.tcx.impl_trait_ref(item.def_id); + if let self_ty = ty_trait_ref.self_ty(); + if let ty::Adt(adt_def, impl_trait_substs) = self_ty.kind(); + then { + let mut non_send_fields = Vec::new(); + + let hir_map = cx.tcx.hir(); + for variant in &adt_def.variants { + for field in &variant.fields { + if_chain! { + if let Some(field_hir_id) = field + .did + .as_local() + .map(|local_def_id| hir_map.local_def_id_to_hir_id(local_def_id)); + if !is_lint_allowed(cx, NON_SEND_FIELDS_IN_SEND_TY, field_hir_id); + if let field_ty = field.ty(cx.tcx, impl_trait_substs); + if !ty_allowed_in_send(cx, field_ty, send_trait); + if let Node::Field(field_def) = hir_map.get(field_hir_id); + then { + non_send_fields.push(NonSendField { + def: field_def, + ty: field_ty, + generic_params: collect_generic_params(cx, field_ty), + }) + } + } + } + } + + if !non_send_fields.is_empty() { + span_lint_and_then( + cx, + NON_SEND_FIELDS_IN_SEND_TY, + item.span, + &format!( + "this implementation is unsound, as some fields in `{}` are `!Send`", + snippet(cx, hir_impl.self_ty.span, "Unknown") + ), + |diag| { + for field in non_send_fields { + diag.span_note( + field.def.span, + &format!("the type of field `{}` is `!Send`", field.def.ident.name), + ); + + match field.generic_params.len() { + 0 => diag.help("use a thread-safe type that implements `Send`"), + 1 if is_ty_param(field.ty) => diag.help(&format!("add `{}: Send` bound in `Send` impl", field.ty)), + _ => diag.help(&format!( + "add bounds on type parameter{} `{}` that satisfy `{}: Send`", + if field.generic_params.len() > 1 { "s" } else { "" }, + field.generic_params_string(), + snippet(cx, field.def.ty.span, "Unknown"), + )), + }; + } + }, + ); + } + } + } + } +} + +struct NonSendField<'tcx> { + def: &'tcx FieldDef<'tcx>, + ty: Ty<'tcx>, + generic_params: Vec>, +} + +impl<'tcx> NonSendField<'tcx> { + fn generic_params_string(&self) -> String { + self.generic_params + .iter() + .map(ToString::to_string) + .collect::>() + .join(", ") + } +} + +/// Given a type, collect all of its generic parameters. +/// Example: `MyStruct>` => `vec![P, Q, R]` +fn collect_generic_params<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Vec> { + ty.walk(cx.tcx) + .filter_map(|inner| match inner.unpack() { + GenericArgKind::Type(inner_ty) => Some(inner_ty), + _ => None, + }) + .filter(|&inner_ty| is_ty_param(inner_ty)) + .collect() +} + +/// Be more strict when the heuristic is disabled +fn ty_allowed_without_raw_pointer_heuristic<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, send_trait: DefId) -> bool { + if implements_trait(cx, ty, send_trait, &[]) { + return true; + } + + if is_copy(cx, ty) && !contains_raw_pointer(cx, ty) { + return true; + } + + false +} + +/// Heuristic to allow cases like `Vec<*const u8>` +fn ty_allowed_with_raw_pointer_heuristic<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, send_trait: DefId) -> bool { + if implements_trait(cx, ty, send_trait, &[]) || is_copy(cx, ty) { + return true; + } + + // The type is known to be `!Send` and `!Copy` + match ty.kind() { + ty::Tuple(_) => ty + .tuple_fields() + .all(|ty| ty_allowed_with_raw_pointer_heuristic(cx, ty, send_trait)), + ty::Array(ty, _) | ty::Slice(ty) => ty_allowed_with_raw_pointer_heuristic(cx, ty, send_trait), + ty::Adt(_, substs) => { + if contains_raw_pointer(cx, ty) { + // descends only if ADT contains any raw pointers + substs.iter().all(|generic_arg| match generic_arg.unpack() { + GenericArgKind::Type(ty) => ty_allowed_with_raw_pointer_heuristic(cx, ty, send_trait), + // Lifetimes and const generics are not solid part of ADT and ignored + GenericArgKind::Lifetime(_) | GenericArgKind::Const(_) => true, + }) + } else { + false + } + }, + // Raw pointers are `!Send` but allowed by the heuristic + ty::RawPtr(_) => true, + _ => false, + } +} + +/// Checks if the type contains any raw pointers in substs (including nested ones). +fn contains_raw_pointer<'tcx>(cx: &LateContext<'tcx>, target_ty: Ty<'tcx>) -> bool { + for ty_node in target_ty.walk(cx.tcx) { + if_chain! { + if let GenericArgKind::Type(inner_ty) = ty_node.unpack(); + if let ty::RawPtr(_) = inner_ty.kind(); + then { + return true; + } + } + } + + false +} + +/// Returns `true` if the type is a type parameter such as `T`. +fn is_ty_param(target_ty: Ty<'_>) -> bool { + matches!(target_ty.kind(), ty::Param(_)) +} diff --git a/src/tools/clippy/clippy_lints/src/open_options.rs b/src/tools/clippy/clippy_lints/src/open_options.rs index 4064d94da2..5752342cf6 100644 --- a/src/tools/clippy/clippy_lints/src/open_options.rs +++ b/src/tools/clippy/clippy_lints/src/open_options.rs @@ -31,11 +31,11 @@ declare_lint_pass!(OpenOptions => [NONSENSICAL_OPEN_OPTIONS]); impl<'tcx> LateLintPass<'tcx> for OpenOptions { fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) { - if let ExprKind::MethodCall(path, _, arguments, _) = e.kind { - let obj_ty = cx.typeck_results().expr_ty(&arguments[0]).peel_refs(); + if let ExprKind::MethodCall(path, _, [self_arg, ..], _) = &e.kind { + let obj_ty = cx.typeck_results().expr_ty(self_arg).peel_refs(); if path.ident.name == sym!(open) && match_type(cx, obj_ty, &paths::OPEN_OPTIONS) { let mut options = Vec::new(); - get_open_options(cx, &arguments[0], &mut options); + get_open_options(cx, self_arg, &mut options); check_open_options(cx, &options, e.span); } } 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 eff3d3abff..a62eb06998 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 @@ -2,12 +2,14 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::higher; use clippy_utils::sugg::Sugg; use clippy_utils::ty::is_type_diagnostic_item; -use clippy_utils::usage::contains_return_break_continue_macro; -use clippy_utils::{eager_or_lazy, in_macro, is_else_clause, is_lang_ctor}; +use clippy_utils::{ + can_move_expr_to_closure, eager_or_lazy, in_constant, in_macro, is_else_clause, is_lang_ctor, peel_hir_expr_while, + CaptureKind, +}; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::LangItem::OptionSome; -use rustc_hir::{BindingAnnotation, Block, Expr, ExprKind, Mutability, PatKind, UnOp}; +use rustc_hir::{def::Res, BindingAnnotation, Block, Expr, ExprKind, Mutability, PatKind, Path, QPath, UnOp}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::sym; @@ -58,7 +60,7 @@ declare_clippy_lint! { /// }, |foo| foo); /// ``` pub OPTION_IF_LET_ELSE, - pedantic, + nursery, "reimplementation of Option::map_or" } @@ -68,7 +70,7 @@ declare_lint_pass!(OptionIfLetElse => [OPTION_IF_LET_ELSE]); fn is_result_ok(cx: &LateContext<'_>, expr: &'_ Expr<'_>) -> bool { if let ExprKind::MethodCall(path, _, &[ref receiver], _) = &expr.kind { path.ident.name.as_str() == "ok" - && is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(receiver), sym::result_type) + && is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(receiver), sym::Result) } else { false } @@ -125,20 +127,30 @@ fn format_option_in_sugg(cx: &LateContext<'_>, cond_expr: &Expr<'_>, as_ref: boo fn detect_option_if_let_else<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>) -> Option { if_chain! { if !in_macro(expr.span); // Don't lint macros, because it behaves weirdly - if let Some(higher::IfLet { let_pat, let_expr, if_then, if_else: Some(if_else) }) = higher::IfLet::hir(cx, expr); + if !in_constant(cx, expr.hir_id); + if let Some(higher::IfLet { let_pat, let_expr, if_then, if_else: Some(if_else) }) + = higher::IfLet::hir(cx, expr); if !is_else_clause(cx.tcx, expr); if !is_result_ok(cx, let_expr); // Don't lint on Result::ok because a different lint does it already if let PatKind::TupleStruct(struct_qpath, [inner_pat], _) = &let_pat.kind; if is_lang_ctor(cx, struct_qpath, OptionSome); if let PatKind::Binding(bind_annotation, _, id, _) = &inner_pat.kind; - if !contains_return_break_continue_macro(if_then); - if !contains_return_break_continue_macro(if_else); + if let Some(some_captures) = can_move_expr_to_closure(cx, if_then); + if let Some(none_captures) = can_move_expr_to_closure(cx, if_else); + if some_captures + .iter() + .filter_map(|(id, &c)| none_captures.get(id).map(|&c2| (c, c2))) + .all(|(x, y)| x.is_imm_ref() && y.is_imm_ref()); then { let capture_mut = if bind_annotation == &BindingAnnotation::Mutable { "mut " } else { "" }; let some_body = extract_body_from_expr(if_then)?; let none_body = extract_body_from_expr(if_else)?; - let method_sugg = if eager_or_lazy::is_eagerness_candidate(cx, none_body) { "map_or" } else { "map_or_else" }; + let method_sugg = if eager_or_lazy::is_eagerness_candidate(cx, none_body) { + "map_or" + } else { + "map_or_else" + }; let capture_name = id.name.to_ident_string(); let (as_ref, as_mut) = match &let_expr.kind { ExprKind::AddrOf(_, Mutability::Not, _) => (true, false), @@ -150,6 +162,24 @@ fn detect_option_if_let_else<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>) -> ExprKind::Unary(UnOp::Deref, expr) | ExprKind::AddrOf(_, _, expr) => expr, _ => let_expr, }; + // Check if captures the closure will need conflict with borrows made in the scrutinee. + // TODO: check all the references made in the scrutinee expression. This will require interacting + // with the borrow checker. Currently only `[.]*` is checked for. + if as_ref || as_mut { + let e = peel_hir_expr_while(cond_expr, |e| match e.kind { + ExprKind::Field(e, _) | ExprKind::AddrOf(_, _, e) => Some(e), + _ => None, + }); + if let ExprKind::Path(QPath::Resolved(None, Path { res: Res::Local(local_id), .. })) = e.kind { + match some_captures.get(local_id) + .or_else(|| (method_sugg == "map_or_else").then(|| ()).and_then(|_| none_captures.get(local_id))) + { + Some(CaptureKind::Value | CaptureKind::Ref(Mutability::Mut)) => return None, + Some(CaptureKind::Ref(Mutability::Not)) if as_mut => return None, + Some(CaptureKind::Ref(Mutability::Not)) | None => (), + } + } + } Some(OptionIfLetElseOccurence { option: format_option_in_sugg(cx, cond_expr, as_ref, as_mut), method_sugg: method_sugg.to_string(), diff --git a/src/tools/clippy/clippy_lints/src/overflow_check_conditional.rs b/src/tools/clippy/clippy_lints/src/overflow_check_conditional.rs index 34755afdb7..0f9e5ada3a 100644 --- a/src/tools/clippy/clippy_lints/src/overflow_check_conditional.rs +++ b/src/tools/clippy/clippy_lints/src/overflow_check_conditional.rs @@ -26,6 +26,9 @@ declare_clippy_lint! { declare_lint_pass!(OverflowCheckConditional => [OVERFLOW_CHECK_CONDITIONAL]); +const OVERFLOW_MSG: &str = "you are trying to use classic C overflow conditions that will fail in Rust"; +const UNDERFLOW_MSG: &str = "you are trying to use classic C underflow conditions that will fail in Rust"; + impl<'tcx> LateLintPass<'tcx> for OverflowCheckConditional { // a + b < a, a > a + b, a < a - b, a - b > a fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { @@ -40,17 +43,11 @@ impl<'tcx> LateLintPass<'tcx> for OverflowCheckConditional { if cx.typeck_results().expr_ty(ident1).is_integral(); if cx.typeck_results().expr_ty(ident2).is_integral(); then { - if let BinOpKind::Lt = op.node { - if let BinOpKind::Add = op2.node { - span_lint(cx, OVERFLOW_CHECK_CONDITIONAL, expr.span, - "you are trying to use classic C overflow conditions that will fail in Rust"); - } + if op.node == BinOpKind::Lt && op2.node == BinOpKind::Add { + span_lint(cx, OVERFLOW_CHECK_CONDITIONAL, expr.span, OVERFLOW_MSG); } - if let BinOpKind::Gt = op.node { - if let BinOpKind::Sub = op2.node { - span_lint(cx, OVERFLOW_CHECK_CONDITIONAL, expr.span, - "you are trying to use classic C underflow conditions that will fail in Rust"); - } + if op.node == BinOpKind::Gt && op2.node == BinOpKind::Sub { + span_lint(cx, OVERFLOW_CHECK_CONDITIONAL, expr.span, UNDERFLOW_MSG); } } } @@ -65,17 +62,11 @@ impl<'tcx> LateLintPass<'tcx> for OverflowCheckConditional { if cx.typeck_results().expr_ty(ident1).is_integral(); if cx.typeck_results().expr_ty(ident2).is_integral(); then { - if let BinOpKind::Gt = op.node { - if let BinOpKind::Add = op2.node { - span_lint(cx, OVERFLOW_CHECK_CONDITIONAL, expr.span, - "you are trying to use classic C overflow conditions that will fail in Rust"); - } + if op.node == BinOpKind::Gt && op2.node == BinOpKind::Add { + span_lint(cx, OVERFLOW_CHECK_CONDITIONAL, expr.span, OVERFLOW_MSG); } - if let BinOpKind::Lt = op.node { - if let BinOpKind::Sub = op2.node { - span_lint(cx, OVERFLOW_CHECK_CONDITIONAL, expr.span, - "you are trying to use classic C underflow conditions that will fail in Rust"); - } + if op.node == BinOpKind::Lt && op2.node == BinOpKind::Sub { + span_lint(cx, OVERFLOW_CHECK_CONDITIONAL, expr.span, UNDERFLOW_MSG); } } } diff --git a/src/tools/clippy/clippy_lints/src/panic_in_result_fn.rs b/src/tools/clippy/clippy_lints/src/panic_in_result_fn.rs index e2b6ba8e2d..583c42b656 100644 --- a/src/tools/clippy/clippy_lints/src/panic_in_result_fn.rs +++ b/src/tools/clippy/clippy_lints/src/panic_in_result_fn.rs @@ -47,7 +47,7 @@ impl<'tcx> LateLintPass<'tcx> for PanicInResultFn { span: Span, hir_id: hir::HirId, ) { - if !matches!(fn_kind, FnKind::Closure) && is_type_diagnostic_item(cx, return_ty(cx, hir_id), sym::result_type) { + if !matches!(fn_kind, FnKind::Closure) && is_type_diagnostic_item(cx, return_ty(cx, hir_id), sym::Result) { lint_impl_body(cx, span, body); } } diff --git a/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs b/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs index 157b18c1f6..6229b9608b 100644 --- a/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs +++ b/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs @@ -13,10 +13,10 @@ use rustc_hir::intravisit::FnKind; use rustc_hir::{BindingAnnotation, Body, FnDecl, HirId, Impl, ItemKind, MutTy, Mutability, Node, PatKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty; +use rustc_middle::ty::layout::LayoutOf; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::def_id::LocalDefId; use rustc_span::{sym, Span}; -use rustc_target::abi::LayoutOf; use rustc_target::spec::abi::Abi; use rustc_target::spec::Target; 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 35cff4141a..e7bc244659 100644 --- a/src/tools/clippy/clippy_lints/src/pattern_type_mismatch.rs +++ b/src/tools/clippy/clippy_lints/src/pattern_type_mismatch.rs @@ -118,7 +118,7 @@ impl<'tcx> LateLintPass<'tcx> for PatternTypeMismatch { } } if let ExprKind::Let(let_pat, let_expr, _) = expr.kind { - if let Some(ref expr_ty) = cx.typeck_results().node_type_opt(let_expr.hir_id) { + 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; } diff --git a/src/tools/clippy/clippy_lints/src/ptr.rs b/src/tools/clippy/clippy_lints/src/ptr.rs index c0d1f1eb6e..d180d6f922 100644 --- a/src/tools/clippy/clippy_lints/src/ptr.rs +++ b/src/tools/clippy/clippy_lints/src/ptr.rs @@ -258,7 +258,7 @@ 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_type) { + if is_type_diagnostic_item(cx, ty, sym::Vec) { if let Some(spans) = get_spans(cx, opt_body_id, idx, &[("clone", ".to_owned()")]) { span_lint_and_then( cx, @@ -288,7 +288,7 @@ fn check_fn(cx: &LateContext<'_>, decl: &FnDecl<'_>, fn_id: HirId, opt_body_id: }, ); } - } else if is_type_diagnostic_item(cx, ty, sym::string_type) { + } else if is_type_diagnostic_item(cx, ty, sym::String) { if let Some(spans) = get_spans(cx, opt_body_id, idx, &[("clone", ".to_string()"), ("as_str", "")]) { span_lint_and_then( cx, @@ -372,7 +372,7 @@ fn check_fn(cx: &LateContext<'_>, decl: &FnDecl<'_>, fn_id: HirId, opt_body_id: for (_, ref mutbl, ref argspan) in decl .inputs .iter() - .filter_map(|ty| get_rptr_lm(ty)) + .filter_map(get_rptr_lm) .filter(|&(lt, _, _)| lt.name == out.name) { if *mutbl == Mutability::Mut { diff --git a/src/tools/clippy/clippy_lints/src/ptr_offset_with_cast.rs b/src/tools/clippy/clippy_lints/src/ptr_offset_with_cast.rs index f1975056dd..cfb5287c66 100644 --- a/src/tools/clippy/clippy_lints/src/ptr_offset_with_cast.rs +++ b/src/tools/clippy/clippy_lints/src/ptr_offset_with_cast.rs @@ -92,13 +92,13 @@ fn expr_as_ptr_offset_call<'tcx>( cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, ) -> Option<(&'tcx Expr<'tcx>, &'tcx Expr<'tcx>, Method)> { - if let ExprKind::MethodCall(path_segment, _, args, _) = expr.kind { - if is_expr_ty_raw_ptr(cx, &args[0]) { + if let ExprKind::MethodCall(path_segment, _, [arg_0, arg_1, ..], _) = &expr.kind { + if is_expr_ty_raw_ptr(cx, arg_0) { if path_segment.ident.name == sym::offset { - return Some((&args[0], &args[1], Method::Offset)); + return Some((arg_0, arg_1, Method::Offset)); } if path_segment.ident.name == sym!(wrapping_offset) { - return Some((&args[0], &args[1], Method::WrappingOffset)); + return Some((arg_0, arg_1, Method::WrappingOffset)); } } } diff --git a/src/tools/clippy/clippy_lints/src/question_mark.rs b/src/tools/clippy/clippy_lints/src/question_mark.rs index 7b6a0894e6..aa6d254e7a 100644 --- a/src/tools/clippy/clippy_lints/src/question_mark.rs +++ b/src/tools/clippy/clippy_lints/src/question_mark.rs @@ -97,7 +97,8 @@ impl QuestionMark { fn check_if_let_some_and_early_return_none(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 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; @@ -105,7 +106,7 @@ impl QuestionMark { if let PatKind::Binding(annot, bind_id, _, _) = fields[0].kind; let by_ref = matches!(annot, BindingAnnotation::Ref | BindingAnnotation::RefMut); - if let ExprKind::Block(ref block, None) = if_then.kind; + 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); @@ -142,7 +143,7 @@ impl QuestionMark { fn is_option(cx: &LateContext<'_>, expression: &Expr<'_>) -> bool { let expr_ty = cx.typeck_results().expr_ty(expression); - is_type_diagnostic_item(cx, expr_ty, sym::option_type) + is_type_diagnostic_item(cx, expr_ty, sym::Option) } fn expression_returns_none(cx: &LateContext<'_>, expression: &Expr<'_>) -> bool { diff --git a/src/tools/clippy/clippy_lints/src/redundant_clone.rs b/src/tools/clippy/clippy_lints/src/redundant_clone.rs index f5e43264a5..f7711b6fe9 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_clone.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_clone.rs @@ -15,7 +15,7 @@ use rustc_middle::mir::{ Mutability, }; use rustc_middle::ty::{self, fold::TypeVisitor, Ty, TyCtxt}; -use rustc_mir::dataflow::{Analysis, AnalysisDomain, GenKill, GenKillAnalysis, ResultsCursor}; +use rustc_mir_dataflow::{Analysis, AnalysisDomain, GenKill, GenKillAnalysis, ResultsCursor}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::{BytePos, Span}; use rustc_span::sym; @@ -123,7 +123,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClone { let from_borrow = match_def_path(cx, fn_def_id, &paths::CLONE_TRAIT_METHOD) || match_def_path(cx, fn_def_id, &paths::TO_OWNED_METHOD) || (match_def_path(cx, fn_def_id, &paths::TO_STRING_METHOD) - && is_type_diagnostic_item(cx, arg_ty, sym::string_type)); + && is_type_diagnostic_item(cx, arg_ty, sym::String)); let from_deref = !from_borrow && (match_def_path(cx, fn_def_id, &paths::PATH_TO_PATH_BUF) @@ -625,7 +625,10 @@ impl<'a, 'tcx> mir::visit::Visitor<'tcx> for PossibleBorrowerVisitor<'a, 'tcx> { .flat_map(HybridBitSet::iter) .collect(); - if ContainsRegion(self.cx.tcx).visit_ty(self.body.local_decls[*dest].ty).is_break() { + if ContainsRegion(self.cx.tcx) + .visit_ty(self.body.local_decls[*dest].ty) + .is_break() + { mutable_variables.push(*dest); } diff --git a/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs b/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs index 7314bce83e..90e3c3f4b3 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs @@ -51,9 +51,7 @@ impl ReturnVisitor { impl<'ast> ast_visit::Visitor<'ast> for ReturnVisitor { fn visit_expr(&mut self, ex: &'ast ast::Expr) { - if let ast::ExprKind::Ret(_) = ex.kind { - self.found_return = true; - } else if let ast::ExprKind::Try(_) = ex.kind { + if let ast::ExprKind::Ret(_) | ast::ExprKind::Try(_) = ex.kind { self.found_return = true; } diff --git a/src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs b/src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs index ed2e1f90fa..919d4e11e5 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs @@ -41,25 +41,23 @@ impl_lint_pass!(RedundantPubCrate => [REDUNDANT_PUB_CRATE]); impl<'tcx> LateLintPass<'tcx> for RedundantPubCrate { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) { if let VisibilityKind::Crate { .. } = item.vis.node { - if !cx.access_levels.is_exported(item.def_id) { - if let Some(false) = self.is_exported.last() { - let span = item.span.with_hi(item.ident.span.hi()); - let descr = cx.tcx.def_kind(item.def_id).descr(item.def_id.to_def_id()); - span_lint_and_then( - cx, - REDUNDANT_PUB_CRATE, - span, - &format!("pub(crate) {} inside private module", descr), - |diag| { - diag.span_suggestion( - item.vis.span, - "consider using", - "pub".to_string(), - Applicability::MachineApplicable, - ); - }, - ); - } + if !cx.access_levels.is_exported(item.def_id) && self.is_exported.last() == Some(&false) { + let span = item.span.with_hi(item.ident.span.hi()); + let descr = cx.tcx.def_kind(item.def_id).descr(item.def_id.to_def_id()); + span_lint_and_then( + cx, + REDUNDANT_PUB_CRATE, + span, + &format!("pub(crate) {} inside private module", descr), + |diag| { + diag.span_suggestion( + item.vis.span, + "consider using", + "pub".to_string(), + Applicability::MachineApplicable, + ); + }, + ); } } diff --git a/src/tools/clippy/clippy_lints/src/ref_option_ref.rs b/src/tools/clippy/clippy_lints/src/ref_option_ref.rs index 65ab6cac44..d543832e31 100644 --- a/src/tools/clippy/clippy_lints/src/ref_option_ref.rs +++ b/src/tools/clippy/clippy_lints/src/ref_option_ref.rs @@ -45,7 +45,7 @@ impl<'tcx> LateLintPass<'tcx> for RefOptionRef { if let Some(res) = last.res; if let Some(def_id) = res.opt_def_id(); - if cx.tcx.is_diagnostic_item(sym::option_type, def_id); + if cx.tcx.is_diagnostic_item(sym::Option, def_id); if let Some(params) = last_path_segment(qpath).args ; if !params.parenthesized; if let Some(inner_ty) = params.args.iter().find_map(|arg| match arg { diff --git a/src/tools/clippy/clippy_lints/src/regex.rs b/src/tools/clippy/clippy_lints/src/regex.rs index eab0973373..5d08aee1e5 100644 --- a/src/tools/clippy/clippy_lints/src/regex.rs +++ b/src/tools/clippy/clippy_lints/src/regex.rs @@ -3,10 +3,9 @@ use clippy_utils::diagnostics::{span_lint, span_lint_and_help}; use clippy_utils::{match_def_path, paths}; use if_chain::if_chain; use rustc_ast::ast::{LitKind, StrStyle}; -use rustc_data_structures::fx::FxHashSet; -use rustc_hir::{BorrowKind, Expr, ExprKind, HirId}; +use rustc_hir::{BorrowKind, Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::{BytePos, Span}; use std::convert::TryFrom; @@ -52,13 +51,7 @@ declare_clippy_lint! { "trivial regular expressions" } -#[derive(Clone, Default)] -pub struct Regex { - spans: FxHashSet, - last: Option, -} - -impl_lint_pass!(Regex => [INVALID_REGEX, TRIVIAL_REGEX]); +declare_lint_pass!(Regex => [INVALID_REGEX, TRIVIAL_REGEX]); impl<'tcx> LateLintPass<'tcx> for Regex { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { @@ -91,7 +84,7 @@ fn str_span(base: Span, c: regex_syntax::ast::Span, offset: u16) -> Span { let end = base.lo() + BytePos(u32::try_from(c.end.offset).expect("offset too large") + offset); let start = base.lo() + BytePos(u32::try_from(c.start.offset).expect("offset too large") + offset); assert!(start <= end); - Span::new(start, end, base.ctxt()) + Span::new(start, end, base.ctxt(), base.parent()) } fn const_str<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> Option { diff --git a/src/tools/clippy/clippy_lints/src/repeat_once.rs b/src/tools/clippy/clippy_lints/src/repeat_once.rs index 54b9c8b327..cf94c0e97d 100644 --- a/src/tools/clippy/clippy_lints/src/repeat_once.rs +++ b/src/tools/clippy/clippy_lints/src/repeat_once.rs @@ -48,7 +48,7 @@ impl<'tcx> LateLintPass<'tcx> for RepeatOnce { if_chain! { if let ExprKind::MethodCall(path, _, [receiver, count], _) = &expr.kind; if path.ident.name == sym!(repeat); - if let Some(Constant::Int(1)) = constant_context(cx, cx.typeck_results()).expr(count); + if constant_context(cx, cx.typeck_results()).expr(count) == Some(Constant::Int(1)); if !in_macro(receiver.span); then { let ty = cx.typeck_results().expr_ty(receiver).peel_refs(); @@ -72,7 +72,7 @@ impl<'tcx> LateLintPass<'tcx> for RepeatOnce { format!("{}.to_vec()", snippet(cx, receiver.span, r#""...""#)), Applicability::MachineApplicable, ); - } else if is_type_diagnostic_item(cx, ty, sym::string_type) { + } else if is_type_diagnostic_item(cx, ty, sym::String) { span_lint_and_sugg( cx, REPEAT_ONCE, diff --git a/src/tools/clippy/clippy_lints/src/returns.rs b/src/tools/clippy/clippy_lints/src/returns.rs index 681baed8c3..ae85b7087e 100644 --- a/src/tools/clippy/clippy_lints/src/returns.rs +++ b/src/tools/clippy/clippy_lints/src/returns.rs @@ -11,6 +11,7 @@ use rustc_middle::hir::map::Map; use rustc_middle::lint::in_external_macro; use rustc_middle::ty::subst::GenericArgKind; use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_span::hygiene::DesugaringKind; use rustc_span::source_map::Span; use rustc_span::sym; @@ -199,20 +200,19 @@ fn check_final_expr<'tcx>( check_block_return(cx, ifblock); } if let Some(else_clause) = else_clause_opt { - check_final_expr(cx, else_clause, None, RetReplacement::Empty); + if expr.span.desugaring_kind() != Some(DesugaringKind::LetElse) { + check_final_expr(cx, else_clause, None, RetReplacement::Empty); + } } }, // a match expr, check all arms // an if/if let expr, check both exprs // note, if without else is going to be a type checking error anyways // (except for unit type functions) so we don't match it - ExprKind::Match(_, arms, source) => match source { - MatchSource::Normal => { - for arm in arms.iter() { - check_final_expr(cx, arm.body, Some(arm.body.span), RetReplacement::Block); - } - }, - _ => (), + ExprKind::Match(_, arms, MatchSource::Normal) => { + for arm in arms.iter() { + check_final_expr(cx, arm.body, Some(arm.body.span), RetReplacement::Block); + } }, ExprKind::DropTemps(expr) => check_final_expr(cx, expr, None, RetReplacement::Empty), _ => (), diff --git a/src/tools/clippy/clippy_lints/src/same_name_method.rs b/src/tools/clippy/clippy_lints/src/same_name_method.rs new file mode 100644 index 0000000000..737ff634e4 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/same_name_method.rs @@ -0,0 +1,160 @@ +use clippy_utils::diagnostics::span_lint_and_then; +use rustc_data_structures::fx::FxHashMap; +use rustc_hir::def::{DefKind, Res}; +use rustc_hir::{Impl, ItemKind, Node, Path, QPath, TraitRef, TyKind}; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::ty::AssocKind; +use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_span::symbol::Symbol; +use rustc_span::Span; +use std::collections::{BTreeMap, BTreeSet}; + +declare_clippy_lint! { + /// ### What it does + /// It lints if a struct has two method with same time: + /// one from a trait, another not from trait. + /// + /// ### Why is this bad? + /// Confusing. + /// + /// ### Example + /// ```rust + /// trait T { + /// fn foo(&self) {} + /// } + /// + /// struct S; + /// + /// impl T for S { + /// fn foo(&self) {} + /// } + /// + /// impl S { + /// fn foo(&self) {} + /// } + /// ``` + pub SAME_NAME_METHOD, + restriction, + "two method with same name" +} + +declare_lint_pass!(SameNameMethod => [SAME_NAME_METHOD]); + +struct ExistingName { + impl_methods: BTreeMap, + trait_methods: BTreeMap>, +} + +impl<'tcx> LateLintPass<'tcx> for SameNameMethod { + fn check_crate_post(&mut self, cx: &LateContext<'tcx>) { + let mut map = FxHashMap::::default(); + + for item in cx.tcx.hir().items() { + if let ItemKind::Impl(Impl { + items, + of_trait, + self_ty, + .. + }) = &item.kind + { + if let TyKind::Path(QPath::Resolved(_, Path { res, .. })) = self_ty.kind { + if !map.contains_key(res) { + map.insert( + *res, + ExistingName { + impl_methods: BTreeMap::new(), + trait_methods: BTreeMap::new(), + }, + ); + } + let existing_name = map.get_mut(res).unwrap(); + + match of_trait { + Some(trait_ref) => { + let mut methods_in_trait: BTreeSet = if_chain! { + if let Some(Node::TraitRef(TraitRef { path, .. })) = + cx.tcx.hir().find(trait_ref.hir_ref_id); + if let Res::Def(DefKind::Trait, did) = path.res; + then{ + // FIXME: if + // `rustc_middle::ty::assoc::AssocItems::items` is public, + // we can iterate its keys instead of `in_definition_order`, + // which's more efficient + cx.tcx + .associated_items(did) + .in_definition_order() + .filter(|assoc_item| { + matches!(assoc_item.kind, AssocKind::Fn) + }) + .map(|assoc_item| assoc_item.ident.name) + .collect() + }else{ + BTreeSet::new() + } + }; + + let mut check_trait_method = |method_name: Symbol, trait_method_span: Span| { + if let Some(impl_span) = existing_name.impl_methods.get(&method_name) { + span_lint_and_then( + cx, + SAME_NAME_METHOD, + *impl_span, + "method's name is same to an existing method in a trait", + |diag| { + diag.span_note( + trait_method_span, + &format!("existing `{}` defined here", method_name), + ); + }, + ); + } + if let Some(v) = existing_name.trait_methods.get_mut(&method_name) { + v.push(trait_method_span); + } else { + existing_name.trait_methods.insert(method_name, vec![trait_method_span]); + } + }; + + for impl_item_ref in (*items).iter().filter(|impl_item_ref| { + matches!(impl_item_ref.kind, rustc_hir::AssocItemKind::Fn { .. }) + }) { + let method_name = impl_item_ref.ident.name; + methods_in_trait.remove(&method_name); + check_trait_method(method_name, impl_item_ref.span); + } + + for method_name in methods_in_trait { + check_trait_method(method_name, item.span); + } + }, + None => { + for impl_item_ref in (*items).iter().filter(|impl_item_ref| { + matches!(impl_item_ref.kind, rustc_hir::AssocItemKind::Fn { .. }) + }) { + let method_name = impl_item_ref.ident.name; + let impl_span = impl_item_ref.span; + if let Some(trait_spans) = existing_name.trait_methods.get(&method_name) { + span_lint_and_then( + cx, + SAME_NAME_METHOD, + impl_span, + "method's name is same to an existing method in a trait", + |diag| { + // TODO should we `span_note` on every trait? + // iterate on trait_spans? + diag.span_note( + trait_spans[0], + &format!("existing `{}` defined here", method_name), + ); + }, + ); + } + existing_name.impl_methods.insert(method_name, impl_span); + } + }, + } + } + } + } + } +} diff --git a/src/tools/clippy/clippy_lints/src/shadow.rs b/src/tools/clippy/clippy_lints/src/shadow.rs index b9e317a3cf..2ca7c18800 100644 --- a/src/tools/clippy/clippy_lints/src/shadow.rs +++ b/src/tools/clippy/clippy_lints/src/shadow.rs @@ -1,17 +1,14 @@ -use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::diagnostics::span_lint_and_note; use clippy_utils::source::snippet; -use clippy_utils::{contains_name, higher, iter_input_pats}; -use rustc_hir::intravisit::FnKind; -use rustc_hir::{ - Block, Body, Expr, ExprKind, FnDecl, Guard, HirId, Local, MutTy, Pat, PatKind, Path, QPath, StmtKind, Ty, TyKind, - UnOp, -}; -use rustc_lint::{LateContext, LateLintPass, LintContext}; -use rustc_middle::lint::in_external_macro; -use rustc_middle::ty; -use rustc_session::{declare_lint_pass, declare_tool_lint}; -use rustc_span::source_map::Span; -use rustc_span::symbol::Symbol; +use clippy_utils::visitors::is_local_used; +use rustc_data_structures::fx::FxHashMap; +use rustc_hir::def::Res; +use rustc_hir::def_id::LocalDefId; +use rustc_hir::hir_id::ItemLocalId; +use rustc_hir::{Block, Body, BodyOwnerKind, Expr, ExprKind, HirId, Node, Pat, PatKind, QPath, UnOp}; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_span::{Span, Symbol}; declare_clippy_lint! { /// ### What it does @@ -23,10 +20,6 @@ declare_clippy_lint! { /// code. Still, some may opt to avoid it in their code base, they can set this /// lint to `Warn`. /// - /// ### Known problems - /// This lint, as the other shadowing related lints, - /// currently only catches very simple patterns. - /// /// ### Example /// ```rust /// # let x = 1; @@ -52,10 +45,6 @@ declare_clippy_lint! { /// because a value may be bound to different things depending on position in /// the code. /// - /// ### Known problems - /// This lint, as the other shadowing related lints, - /// currently only catches very simple patterns. - /// /// ### Example /// ```rust /// let x = 2; @@ -83,12 +72,6 @@ declare_clippy_lint! { /// any place in the code. This can be alleviated by either giving more specific /// names to bindings or introducing more scopes to contain the bindings. /// - /// ### Known problems - /// This lint, as the other shadowing related lints, - /// currently only catches very simple patterns. Note that - /// `allow`/`warn`/`deny`/`forbid` attributes only work on the function level - /// for this lint. - /// /// ### Example /// ```rust /// # let y = 1; @@ -102,307 +85,151 @@ declare_clippy_lint! { /// let w = z; // use different variable name /// ``` pub SHADOW_UNRELATED, - pedantic, + restriction, "rebinding a name without even using the original value" } -declare_lint_pass!(Shadow => [SHADOW_SAME, SHADOW_REUSE, SHADOW_UNRELATED]); +#[derive(Default)] +pub(crate) struct Shadow { + bindings: Vec>>, +} + +impl_lint_pass!(Shadow => [SHADOW_SAME, SHADOW_REUSE, SHADOW_UNRELATED]); impl<'tcx> LateLintPass<'tcx> for Shadow { - fn check_fn( - &mut self, - cx: &LateContext<'tcx>, - _: FnKind<'tcx>, - decl: &'tcx FnDecl<'_>, - body: &'tcx Body<'_>, - _: Span, - _: HirId, - ) { - if in_external_macro(cx.sess(), body.value.span) { + fn check_pat(&mut self, cx: &LateContext<'tcx>, pat: &'tcx Pat<'_>) { + let (id, ident) = match pat.kind { + PatKind::Binding(_, hir_id, ident, _) => (hir_id, ident), + _ => return, + }; + if ident.span.from_expansion() || ident.span.is_dummy() { return; } - check_fn(cx, decl, body); - } -} + let HirId { owner, local_id } = id; -fn check_fn<'tcx>(cx: &LateContext<'tcx>, decl: &'tcx FnDecl<'_>, body: &'tcx Body<'_>) { - let mut bindings = Vec::with_capacity(decl.inputs.len()); - for arg in iter_input_pats(decl, body) { - if let PatKind::Binding(.., ident, _) = arg.pat.kind { - bindings.push((ident.name, ident.span)); + // get (or insert) the list of items for this owner and symbol + let data = self.bindings.last_mut().unwrap(); + let items_with_name = data.entry(ident.name).or_default(); + + // check other bindings with the same name, most recently seen first + for &prev in items_with_name.iter().rev() { + if prev == local_id { + // repeated binding in an `Or` pattern + return; + } + + if is_shadow(cx, owner, prev, local_id) { + let prev_hir_id = HirId { owner, local_id: prev }; + lint_shadow(cx, pat, prev_hir_id, ident.span); + // only lint against the "nearest" shadowed binding + break; + } + } + // store the binding + items_with_name.push(local_id); + } + + fn check_body(&mut self, cx: &LateContext<'_>, body: &Body<'_>) { + let hir = cx.tcx.hir(); + if !matches!(hir.body_owner_kind(hir.body_owner(body.id())), BodyOwnerKind::Closure) { + self.bindings.push(FxHashMap::default()); } } - check_expr(cx, &body.value, &mut bindings); -} -fn check_block<'tcx>(cx: &LateContext<'tcx>, block: &'tcx Block<'_>, bindings: &mut Vec<(Symbol, Span)>) { - let len = bindings.len(); - for stmt in block.stmts { - match stmt.kind { - StmtKind::Local(local) => check_local(cx, local, bindings), - StmtKind::Expr(e) | StmtKind::Semi(e) => check_expr(cx, e, bindings), - StmtKind::Item(..) => {}, + fn check_body_post(&mut self, cx: &LateContext<'_>, body: &Body<'_>) { + let hir = cx.tcx.hir(); + if !matches!(hir.body_owner_kind(hir.body_owner(body.id())), BodyOwnerKind::Closure) { + self.bindings.pop(); } } - if let Some(o) = block.expr { - check_expr(cx, o, bindings); - } - bindings.truncate(len); } -fn check_local<'tcx>(cx: &LateContext<'tcx>, local: &'tcx Local<'_>, bindings: &mut Vec<(Symbol, Span)>) { - if in_external_macro(cx.sess(), local.span) { - return; - } - if higher::is_from_for_desugar(local) { - return; - } - let Local { - pat, - ref ty, - ref init, +fn is_shadow(cx: &LateContext<'_>, owner: LocalDefId, first: ItemLocalId, second: ItemLocalId) -> bool { + let scope_tree = cx.tcx.region_scope_tree(owner.to_def_id()); + let first_scope = scope_tree.var_scope(first); + let second_scope = scope_tree.var_scope(second); + scope_tree.is_subscope_of(second_scope, first_scope) +} + +fn lint_shadow(cx: &LateContext<'_>, pat: &Pat<'_>, shadowed: HirId, span: Span) { + let (lint, msg) = match find_init(cx, pat.hir_id) { + Some(expr) if is_self_shadow(cx, pat, expr, shadowed) => { + let msg = format!( + "`{}` is shadowed by itself in `{}`", + snippet(cx, pat.span, "_"), + snippet(cx, expr.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, "..") + ); + (SHADOW_REUSE, msg) + }, + _ => { + let msg = format!("`{}` shadows a previous, unrelated binding", snippet(cx, pat.span, "_")); + (SHADOW_UNRELATED, msg) + }, + }; + span_lint_and_note( + cx, + lint, span, - .. - } = *local; - if let Some(t) = *ty { - check_ty(cx, t, bindings); - } - if let Some(o) = *init { - check_expr(cx, o, bindings); - check_pat(cx, pat, Some(o), span, bindings); - } else { - check_pat(cx, pat, None, span, bindings); - } + &msg, + Some(cx.tcx.hir().span(shadowed)), + "previous binding is here", + ); } -fn is_binding(cx: &LateContext<'_>, pat_id: HirId) -> bool { - let var_ty = cx.typeck_results().node_type_opt(pat_id); - var_ty.map_or(false, |var_ty| !matches!(var_ty.kind(), ty::Adt(..))) -} - -fn check_pat<'tcx>( - cx: &LateContext<'tcx>, - pat: &'tcx Pat<'_>, - init: Option<&'tcx Expr<'_>>, - span: Span, - bindings: &mut Vec<(Symbol, Span)>, -) { - // TODO: match more stuff / destructuring - match pat.kind { - PatKind::Binding(.., ident, ref inner) => { - let name = ident.name; - if is_binding(cx, pat.hir_id) { - let mut new_binding = true; - for tup in bindings.iter_mut() { - if tup.0 == name { - lint_shadow(cx, name, span, pat.span, init, tup.1); - tup.1 = ident.span; - new_binding = false; - break; - } - } - if new_binding { - bindings.push((name, ident.span)); - } - } - if let Some(p) = *inner { - check_pat(cx, p, init, span, bindings); - } - }, - PatKind::Struct(_, pfields, _) => { - if let Some(init_struct) = init { - if let ExprKind::Struct(_, efields, _) = init_struct.kind { - for field in pfields { - let name = field.ident.name; - let efield = efields - .iter() - .find_map(|f| if f.ident.name == name { Some(&*f.expr) } else { None }); - check_pat(cx, field.pat, efield, span, bindings); - } - } else { - for field in pfields { - check_pat(cx, field.pat, init, span, bindings); - } - } - } else { - for field in pfields { - check_pat(cx, field.pat, None, span, bindings); - } - } - }, - PatKind::Tuple(inner, _) => { - if let Some(init_tup) = init { - if let ExprKind::Tup(tup) = init_tup.kind { - for (i, p) in inner.iter().enumerate() { - check_pat(cx, p, Some(&tup[i]), p.span, bindings); - } - } else { - for p in inner { - check_pat(cx, p, init, span, bindings); - } - } - } else { - for p in inner { - check_pat(cx, p, None, span, bindings); - } - } - }, - PatKind::Box(inner) => { - if let Some(initp) = init { - if let ExprKind::Box(inner_init) = initp.kind { - check_pat(cx, inner, Some(inner_init), span, bindings); - } else { - check_pat(cx, inner, init, span, bindings); - } - } else { - check_pat(cx, inner, init, span, bindings); - } - }, - PatKind::Ref(inner, _) => check_pat(cx, inner, init, span, bindings), - // PatVec(Vec>, Option>, Vec>), - _ => (), +/// Returns true if the expression is a simple transformation of a local binding such as `&x` +fn is_self_shadow(cx: &LateContext<'_>, pat: &Pat<'_>, mut expr: &Expr<'_>, hir_id: HirId) -> bool { + let hir = cx.tcx.hir(); + let is_direct_binding = hir + .parent_iter(pat.hir_id) + .map_while(|(_id, node)| match node { + Node::Pat(pat) => Some(pat), + _ => None, + }) + .all(|pat| matches!(pat.kind, PatKind::Ref(..) | PatKind::Or(_))); + if !is_direct_binding { + return false; } -} - -fn lint_shadow<'tcx>( - cx: &LateContext<'tcx>, - name: Symbol, - span: Span, - pattern_span: Span, - init: Option<&'tcx Expr<'_>>, - prev_span: Span, -) { - if let Some(expr) = init { - if is_self_shadow(name, expr) { - span_lint_and_then( - cx, - SHADOW_SAME, - span, - &format!( - "`{}` is shadowed by itself in `{}`", - snippet(cx, pattern_span, "_"), - snippet(cx, expr.span, "..") - ), - |diag| { - diag.span_note(prev_span, "previous binding is here"); + loop { + expr = match expr.kind { + ExprKind::Box(e) + | ExprKind::AddrOf(_, _, e) + | ExprKind::Block( + &Block { + stmts: [], + expr: Some(e), + .. }, - ); - } else if contains_name(name, expr) { - span_lint_and_then( - cx, - SHADOW_REUSE, - pattern_span, - &format!( - "`{}` is shadowed by `{}` which reuses the original value", - snippet(cx, pattern_span, "_"), - snippet(cx, expr.span, "..") - ), - |diag| { - diag.span_note(expr.span, "initialization happens here"); - diag.span_note(prev_span, "previous binding is here"); - }, - ); - } else { - span_lint_and_then( - cx, - SHADOW_UNRELATED, - pattern_span, - &format!("`{}` is being shadowed", snippet(cx, pattern_span, "_")), - |diag| { - diag.span_note(expr.span, "initialization happens here"); - diag.span_note(prev_span, "previous binding is here"); - }, - ); + _, + ) + | ExprKind::Unary(UnOp::Deref, e) => e, + ExprKind::Path(QPath::Resolved(None, path)) => break path.res == Res::Local(hir_id), + _ => break false, } - } else { - span_lint_and_then( - cx, - SHADOW_UNRELATED, - span, - &format!("`{}` shadows a previous declaration", snippet(cx, pattern_span, "_")), - |diag| { - diag.span_note(prev_span, "previous binding is here"); + } +} + +/// Finds the "init" expression for a pattern: `let = ;` or +/// `match { .., => .., .. }` +fn find_init<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId) -> Option<&'tcx Expr<'tcx>> { + for (_, node) in cx.tcx.hir().parent_iter(hir_id) { + let init = match node { + Node::Arm(_) | Node::Pat(_) => continue, + Node::Expr(expr) => match expr.kind { + ExprKind::Match(e, _, _) => Some(e), + _ => None, }, - ); + Node::Local(local) => local.init, + _ => None, + }; + return init; } -} - -fn check_expr<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, bindings: &mut Vec<(Symbol, Span)>) { - if in_external_macro(cx.sess(), expr.span) { - return; - } - match expr.kind { - ExprKind::Unary(_, e) | ExprKind::Field(e, _) | ExprKind::AddrOf(_, _, e) | ExprKind::Box(e) => { - check_expr(cx, e, bindings); - }, - ExprKind::Block(block, _) | ExprKind::Loop(block, ..) => check_block(cx, block, bindings), - // ExprKind::Call - // ExprKind::MethodCall - ExprKind::Array(v) | ExprKind::Tup(v) => { - for e in v { - check_expr(cx, e, bindings); - } - }, - ExprKind::If(cond, then, ref otherwise) => { - check_expr(cx, cond, bindings); - check_expr(cx, then, bindings); - if let Some(o) = *otherwise { - check_expr(cx, o, bindings); - } - }, - ExprKind::Match(init, arms, _) => { - check_expr(cx, init, bindings); - let len = bindings.len(); - for arm in arms { - check_pat(cx, arm.pat, Some(init), arm.pat.span, bindings); - // This is ugly, but needed to get the right type - if let Some(ref guard) = arm.guard { - match guard { - Guard::If(if_expr) => check_expr(cx, if_expr, bindings), - Guard::IfLet(guard_pat, guard_expr) => { - check_pat(cx, guard_pat, Some(*guard_expr), guard_pat.span, bindings); - check_expr(cx, guard_expr, bindings); - }, - } - } - check_expr(cx, arm.body, bindings); - bindings.truncate(len); - } - }, - _ => (), - } -} - -fn check_ty<'tcx>(cx: &LateContext<'tcx>, ty: &'tcx Ty<'_>, bindings: &mut Vec<(Symbol, Span)>) { - match ty.kind { - TyKind::Slice(sty) => check_ty(cx, sty, bindings), - TyKind::Array(fty, ref anon_const) => { - check_ty(cx, fty, bindings); - check_expr(cx, &cx.tcx.hir().body(anon_const.body).value, bindings); - }, - TyKind::Ptr(MutTy { ty: mty, .. }) | TyKind::Rptr(_, MutTy { ty: mty, .. }) => check_ty(cx, mty, bindings), - TyKind::Tup(tup) => { - for t in tup { - check_ty(cx, t, bindings); - } - }, - TyKind::Typeof(ref anon_const) => check_expr(cx, &cx.tcx.hir().body(anon_const.body).value, bindings), - _ => (), - } -} - -fn is_self_shadow(name: Symbol, expr: &Expr<'_>) -> bool { - match expr.kind { - ExprKind::Box(inner) | ExprKind::AddrOf(_, _, inner) => is_self_shadow(name, inner), - ExprKind::Block(block, _) => { - block.stmts.is_empty() && block.expr.as_ref().map_or(false, |e| is_self_shadow(name, e)) - }, - ExprKind::Unary(op, inner) => (UnOp::Deref == op) && is_self_shadow(name, inner), - ExprKind::Path(QPath::Resolved(_, path)) => path_eq_name(name, path), - _ => false, - } -} - -fn path_eq_name(name: Symbol, path: &Path<'_>) -> bool { - !path.is_global() && path.segments.len() == 1 && path.segments[0].ident.name == name + None } diff --git a/src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs b/src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs index 3d039e1306..3608fe1472 100644 --- a/src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs +++ b/src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs @@ -120,7 +120,7 @@ impl SlowVectorInit { if let ExprKind::Call(func, [arg]) = expr.kind; if let ExprKind::Path(QPath::TypeRelative(ty, name)) = func.kind; if name.ident.as_str() == "with_capacity"; - if is_type_diagnostic_item(cx, cx.typeck_results().node_type(ty.hir_id), sym::vec_type); + if is_type_diagnostic_item(cx, cx.typeck_results().node_type(ty.hir_id), sym::Vec); then { Some(arg) } else { diff --git a/src/tools/clippy/clippy_lints/src/strings.rs b/src/tools/clippy/clippy_lints/src/strings.rs index 1a78a4968e..35b6bde569 100644 --- a/src/tools/clippy/clippy_lints/src/strings.rs +++ b/src/tools/clippy/clippy_lints/src/strings.rs @@ -157,7 +157,7 @@ impl<'tcx> LateLintPass<'tcx> for StringAdd { } fn is_string(cx: &LateContext<'_>, e: &Expr<'_>) -> bool { - is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(e).peel_refs(), sym::string_type) + is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(e).peel_refs(), sym::String) } fn is_add(cx: &LateContext<'_>, src: &Expr<'_>, target: &Expr<'_>) -> bool { @@ -345,9 +345,9 @@ declare_lint_pass!(StrToString => [STR_TO_STRING]); impl LateLintPass<'_> for StrToString { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'_>) { if_chain! { - if let ExprKind::MethodCall(path, _, args, _) = &expr.kind; + if let ExprKind::MethodCall(path, _, [self_arg, ..], _) = &expr.kind; if path.ident.name == sym!(to_string); - let ty = cx.typeck_results().expr_ty(&args[0]); + let ty = cx.typeck_results().expr_ty(self_arg); if let ty::Ref(_, ty, ..) = ty.kind(); if *ty.kind() == ty::Str; then { @@ -394,10 +394,10 @@ declare_lint_pass!(StringToString => [STRING_TO_STRING]); impl LateLintPass<'_> for StringToString { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'_>) { if_chain! { - if let ExprKind::MethodCall(path, _, args, _) = &expr.kind; + if let ExprKind::MethodCall(path, _, [self_arg, ..], _) = &expr.kind; if path.ident.name == sym!(to_string); - let ty = cx.typeck_results().expr_ty(&args[0]); - if is_type_diagnostic_item(cx, ty, sym::string_type); + let ty = cx.typeck_results().expr_ty(self_arg); + if is_type_diagnostic_item(cx, ty, sym::String); then { span_lint_and_help( cx, diff --git a/src/tools/clippy/clippy_lints/src/swap.rs b/src/tools/clippy/clippy_lints/src/swap.rs index f126908e84..ef26de5b6b 100644 --- a/src/tools/clippy/clippy_lints/src/swap.rs +++ b/src/tools/clippy/clippy_lints/src/swap.rs @@ -86,8 +86,8 @@ fn generate_swap_warning(cx: &LateContext<'_>, e1: &Expr<'_>, e2: &Expr<'_>, spa if matches!(ty.kind(), ty::Slice(_)) || matches!(ty.kind(), ty::Array(_, _)) - || is_type_diagnostic_item(cx, ty, sym::vec_type) - || is_type_diagnostic_item(cx, ty, sym::vecdeque_type) + || is_type_diagnostic_item(cx, ty, sym::Vec) + || is_type_diagnostic_item(cx, ty, sym::VecDeque) { let slice = Sugg::hir_with_applicability(cx, lhs1, "", &mut applicability); span_lint_and_sugg( @@ -231,7 +231,7 @@ fn check_xor_swap(cx: &LateContext<'_>, block: &Block<'_>) { } } -/// Returns the lhs and rhs of an xor assignment statement. +/// Returns the lhs and rhs of an xor assignment statement. fn extract_sides_of_xor_assign<'a, 'hir>(stmt: &'a Stmt<'hir>) -> Option<(&'a Expr<'hir>, &'a Expr<'hir>)> { if let StmtKind::Semi(expr) = stmt.kind { if let ExprKind::AssignOp( diff --git a/src/tools/clippy/clippy_lints/src/tabs_in_doc_comments.rs b/src/tools/clippy/clippy_lints/src/tabs_in_doc_comments.rs index 6a73b94d87..4a67cabf32 100644 --- a/src/tools/clippy/clippy_lints/src/tabs_in_doc_comments.rs +++ b/src/tools/clippy/clippy_lints/src/tabs_in_doc_comments.rs @@ -69,6 +69,7 @@ impl TabsInDocComments { attr.span.lo() + BytePos(3 + lo), attr.span.lo() + BytePos(3 + hi), attr.span.ctxt(), + attr.span.parent(), ); span_lint_and_sugg( cx, diff --git a/src/tools/clippy/clippy_lints/src/to_string_in_display.rs b/src/tools/clippy/clippy_lints/src/to_string_in_display.rs index b036ed9a3d..b7414cec87 100644 --- a/src/tools/clippy/clippy_lints/src/to_string_in_display.rs +++ b/src/tools/clippy/clippy_lints/src/to_string_in_display.rs @@ -92,11 +92,11 @@ impl LateLintPass<'_> for ToStringInDisplay { if_chain! { if self.in_display_impl; if let Some(self_hir_id) = self.self_hir_id; - if let ExprKind::MethodCall(path, _, args, _) = expr.kind; + if let ExprKind::MethodCall(path, _, [ref self_arg, ..], _) = expr.kind; if path.ident.name == sym!(to_string); if let Some(expr_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id); if is_diag_trait_item(cx, expr_def_id, sym::ToString); - if path_to_local_id(&args[0], self_hir_id); + if path_to_local_id(self_arg, self_hir_id); then { span_lint( cx, diff --git a/src/tools/clippy/clippy_lints/src/transmute/unsound_collection_transmute.rs b/src/tools/clippy/clippy_lints/src/transmute/unsound_collection_transmute.rs index 868c41aab4..2ce8d4031d 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/unsound_collection_transmute.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/unsound_collection_transmute.rs @@ -9,13 +9,13 @@ use rustc_span::symbol::{sym, Symbol}; // used to check for UNSOUND_COLLECTION_TRANSMUTE static COLLECTIONS: &[Symbol] = &[ - sym::vec_type, - sym::vecdeque_type, + sym::Vec, + sym::VecDeque, sym::BinaryHeap, sym::BTreeSet, sym::BTreeMap, - sym::hashset_type, - sym::hashmap_type, + sym::HashSet, + sym::HashMap, ]; /// Checks for `unsound_collection_transmute` lint. diff --git a/src/tools/clippy/clippy_lints/src/transmuting_null.rs b/src/tools/clippy/clippy_lints/src/transmuting_null.rs index a67fa79220..ef80663d1d 100644 --- a/src/tools/clippy/clippy_lints/src/transmuting_null.rs +++ b/src/tools/clippy/clippy_lints/src/transmuting_null.rs @@ -49,8 +49,8 @@ impl<'tcx> LateLintPass<'tcx> for TransmutingNull { let mut const_eval_context = constant_context(cx, cx.typeck_results()); if_chain! { if let ExprKind::Path(ref _qpath) = arg.kind; - let x = const_eval_context.expr(arg); - if let Some(Constant::RawPtr(0)) = x; + if let Some(Constant::RawPtr(x)) = const_eval_context.expr(arg); + if x == 0; then { span_lint(cx, TRANSMUTING_NULL, expr.span, LINT_MSG) } diff --git a/src/tools/clippy/clippy_lints/src/try_err.rs b/src/tools/clippy/clippy_lints/src/try_err.rs index 1196271d5d..e9ec120a7f 100644 --- a/src/tools/clippy/clippy_lints/src/try_err.rs +++ b/src/tools/clippy/clippy_lints/src/try_err.rs @@ -143,7 +143,7 @@ fn find_return_type<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx ExprKind<'_>) -> O fn result_error_type<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option> { if_chain! { if let ty::Adt(_, subst) = ty.kind(); - if is_type_diagnostic_item(cx, ty, sym::result_type); + if is_type_diagnostic_item(cx, ty, sym::Result); then { Some(subst.type_at(1)) } else { @@ -160,7 +160,7 @@ fn poll_result_error_type<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option< let ready_ty = subst.type_at(0); if let ty::Adt(ready_def, ready_subst) = ready_ty.kind(); - if cx.tcx.is_diagnostic_item(sym::result_type, ready_def.did); + if cx.tcx.is_diagnostic_item(sym::Result, ready_def.did); then { Some(ready_subst.type_at(1)) } else { @@ -177,11 +177,11 @@ fn poll_option_result_error_type<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> let ready_ty = subst.type_at(0); if let ty::Adt(ready_def, ready_subst) = ready_ty.kind(); - if cx.tcx.is_diagnostic_item(sym::option_type, ready_def.did); + if cx.tcx.is_diagnostic_item(sym::Option, ready_def.did); let some_ty = ready_subst.type_at(0); if let ty::Adt(some_def, some_subst) = some_ty.kind(); - if cx.tcx.is_diagnostic_item(sym::result_type, some_def.did); + if cx.tcx.is_diagnostic_item(sym::Result, some_def.did); then { Some(some_subst.type_at(1)) } else { diff --git a/src/tools/clippy/clippy_lints/src/types/box_collection.rs b/src/tools/clippy/clippy_lints/src/types/box_collection.rs new file mode 100644 index 0000000000..538c10a5b2 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/types/box_collection.rs @@ -0,0 +1,50 @@ +use clippy_utils::diagnostics::span_lint_and_help; +use clippy_utils::is_ty_param_diagnostic_item; +use rustc_hir::{self as hir, def_id::DefId, QPath}; +use rustc_lint::LateContext; +use rustc_span::symbol::sym; + +use super::BOX_COLLECTION; + +pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_>, def_id: DefId) -> bool { + if_chain! { + if Some(def_id) == cx.tcx.lang_items().owned_box(); + if let Some(item_type) = get_std_collection(cx, qpath); + then { + let generic = if item_type == "String" { + "" + } else { + "<..>" + }; + span_lint_and_help( + cx, + BOX_COLLECTION, + hir_ty.span, + &format!( + "you seem to be trying to use `Box<{outer}{generic}>`. Consider using just `{outer}{generic}`", + outer=item_type, + generic = generic), + None, + &format!( + "`{outer}{generic}` is already on the heap, `Box<{outer}{generic}>` makes an extra allocation", + outer=item_type, + generic = generic) + ); + true + } else { + false + } + } +} + +fn get_std_collection(cx: &LateContext<'_>, qpath: &QPath<'_>) -> Option<&'static str> { + if is_ty_param_diagnostic_item(cx, qpath, sym::Vec).is_some() { + Some("Vec") + } else if is_ty_param_diagnostic_item(cx, qpath, sym::String).is_some() { + Some("String") + } else if is_ty_param_diagnostic_item(cx, qpath, sym::HashMap).is_some() { + Some("HashMap") + } else { + None + } +} diff --git a/src/tools/clippy/clippy_lints/src/types/box_vec.rs b/src/tools/clippy/clippy_lints/src/types/box_vec.rs deleted file mode 100644 index d8b1953457..0000000000 --- a/src/tools/clippy/clippy_lints/src/types/box_vec.rs +++ /dev/null @@ -1,25 +0,0 @@ -use clippy_utils::diagnostics::span_lint_and_help; -use clippy_utils::is_ty_param_diagnostic_item; -use rustc_hir::{self as hir, def_id::DefId, QPath}; -use rustc_lint::LateContext; -use rustc_span::symbol::sym; - -use super::BOX_VEC; - -pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_>, def_id: DefId) -> bool { - if Some(def_id) == cx.tcx.lang_items().owned_box() - && is_ty_param_diagnostic_item(cx, qpath, sym::vec_type).is_some() - { - span_lint_and_help( - cx, - BOX_VEC, - hir_ty.span, - "you seem to be trying to use `Box>`. Consider using just `Vec`", - None, - "`Vec` is already on the heap, `Box>` makes an extra allocation", - ); - true - } else { - false - } -} diff --git a/src/tools/clippy/clippy_lints/src/types/mod.rs b/src/tools/clippy/clippy_lints/src/types/mod.rs index 371bb8b445..bbe07db535 100644 --- a/src/tools/clippy/clippy_lints/src/types/mod.rs +++ b/src/tools/clippy/clippy_lints/src/types/mod.rs @@ -1,5 +1,5 @@ mod borrowed_box; -mod box_vec; +mod box_collection; mod linked_list; mod option_option; mod rc_buffer; @@ -21,12 +21,12 @@ use rustc_span::source_map::Span; declare_clippy_lint! { /// ### What it does - /// Checks for use of `Box>` anywhere in the code. + /// Checks for use of `Box` where T is a collection such as Vec anywhere in the code. /// Check the [Box documentation](https://doc.rust-lang.org/std/boxed/index.html) for more information. /// /// ### Why is this bad? - /// `Vec` already keeps its contents in a separate area on - /// the heap. So if you `Box` it, you just add another level of indirection + /// Collections already keeps their contents in a separate area on + /// the heap. So if you `Box` them, you just add another level of indirection /// without any benefit whatsoever. /// /// ### Example @@ -43,7 +43,7 @@ declare_clippy_lint! { /// values: Vec, /// } /// ``` - pub BOX_VEC, + pub BOX_COLLECTION, perf, "usage of `Box>`, vector elements are already on the heap" } @@ -295,9 +295,10 @@ declare_clippy_lint! { pub struct Types { vec_box_size_threshold: u64, type_complexity_threshold: u64, + avoid_breaking_exported_api: bool, } -impl_lint_pass!(Types => [BOX_VEC, VEC_BOX, OPTION_OPTION, LINKEDLIST, BORROWED_BOX, REDUNDANT_ALLOCATION, RC_BUFFER, RC_MUTEX, TYPE_COMPLEXITY]); +impl_lint_pass!(Types => [BOX_COLLECTION, VEC_BOX, OPTION_OPTION, LINKEDLIST, BORROWED_BOX, REDUNDANT_ALLOCATION, RC_BUFFER, RC_MUTEX, TYPE_COMPLEXITY]); impl<'tcx> LateLintPass<'tcx> for Types { fn check_fn(&mut self, cx: &LateContext<'_>, _: FnKind<'_>, decl: &FnDecl<'_>, _: &Body<'_>, _: Span, id: HirId) { @@ -308,19 +309,31 @@ impl<'tcx> LateLintPass<'tcx> for Types { false }; + let is_exported = cx.access_levels.is_exported(cx.tcx.hir().local_def_id(id)); + self.check_fn_decl( cx, decl, CheckTyContext { is_in_trait_impl, + is_exported, ..CheckTyContext::default() }, ); } fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) { + let is_exported = cx.access_levels.is_exported(item.def_id); + match item.kind { - ItemKind::Static(ty, _, _) | ItemKind::Const(ty, _) => self.check_ty(cx, ty, CheckTyContext::default()), + ItemKind::Static(ty, _, _) | ItemKind::Const(ty, _) => self.check_ty( + cx, + ty, + CheckTyContext { + is_exported, + ..CheckTyContext::default() + }, + ), // functions, enums, structs, impls and traits are covered _ => (), } @@ -342,15 +355,31 @@ impl<'tcx> LateLintPass<'tcx> for Types { } fn check_field_def(&mut self, cx: &LateContext<'_>, field: &hir::FieldDef<'_>) { - self.check_ty(cx, field.ty, CheckTyContext::default()); + let is_exported = cx.access_levels.is_exported(cx.tcx.hir().local_def_id(field.hir_id)); + + self.check_ty( + cx, + field.ty, + CheckTyContext { + is_exported, + ..CheckTyContext::default() + }, + ); } - fn check_trait_item(&mut self, cx: &LateContext<'_>, item: &TraitItem<'_>) { + fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &TraitItem<'_>) { + let is_exported = cx.access_levels.is_exported(item.def_id); + + let context = CheckTyContext { + is_exported, + ..CheckTyContext::default() + }; + match item.kind { TraitItemKind::Const(ty, _) | TraitItemKind::Type(_, Some(ty)) => { - self.check_ty(cx, ty, CheckTyContext::default()); + self.check_ty(cx, ty, context); }, - TraitItemKind::Fn(ref sig, _) => self.check_fn_decl(cx, sig.decl, CheckTyContext::default()), + TraitItemKind::Fn(ref sig, _) => self.check_fn_decl(cx, sig.decl, context), TraitItemKind::Type(..) => (), } } @@ -370,10 +399,11 @@ impl<'tcx> LateLintPass<'tcx> for Types { } impl Types { - pub fn new(vec_box_size_threshold: u64, type_complexity_threshold: u64) -> Self { + pub fn new(vec_box_size_threshold: u64, type_complexity_threshold: u64, avoid_breaking_exported_api: bool) -> Self { Self { vec_box_size_threshold, type_complexity_threshold, + avoid_breaking_exported_api, } } @@ -410,17 +440,24 @@ impl Types { let hir_id = hir_ty.hir_id; let res = cx.qpath_res(qpath, hir_id); if let Some(def_id) = res.opt_def_id() { - let mut triggered = false; - triggered |= box_vec::check(cx, hir_ty, qpath, def_id); - triggered |= redundant_allocation::check(cx, hir_ty, qpath, def_id); - triggered |= rc_buffer::check(cx, hir_ty, qpath, def_id); - triggered |= vec_box::check(cx, hir_ty, qpath, def_id, self.vec_box_size_threshold); - triggered |= option_option::check(cx, hir_ty, qpath, def_id); - triggered |= linked_list::check(cx, hir_ty, def_id); - triggered |= rc_mutex::check(cx, hir_ty, qpath, def_id); + if self.is_type_change_allowed(context) { + // All lints that are being checked in this block are guarded by + // the `avoid_breaking_exported_api` configuration. When adding a + // new lint, please also add the name to the configuration documentation + // in `clippy_lints::utils::conf.rs` - if triggered { - return; + let mut triggered = false; + triggered |= box_collection::check(cx, hir_ty, qpath, def_id); + triggered |= redundant_allocation::check(cx, hir_ty, qpath, def_id); + triggered |= rc_buffer::check(cx, hir_ty, qpath, def_id); + triggered |= vec_box::check(cx, hir_ty, qpath, def_id, self.vec_box_size_threshold); + triggered |= option_option::check(cx, hir_ty, qpath, def_id); + triggered |= linked_list::check(cx, hir_ty, def_id); + triggered |= rc_mutex::check(cx, hir_ty, qpath, def_id); + + if triggered { + return; + } } } match *qpath { @@ -487,11 +524,21 @@ impl Types { _ => {}, } } + + /// This function checks if the type is allowed to change in the current context + /// based on the `avoid_breaking_exported_api` configuration + fn is_type_change_allowed(&self, context: CheckTyContext) -> bool { + !(context.is_exported && self.avoid_breaking_exported_api) + } } +#[allow(clippy::struct_excessive_bools)] #[derive(Clone, Copy, Default)] struct CheckTyContext { is_in_trait_impl: bool, + /// `true` for types on local variables. is_local: bool, + /// `true` for types that are part of the public API. + is_exported: bool, is_nested_call: bool, } diff --git a/src/tools/clippy/clippy_lints/src/types/option_option.rs b/src/tools/clippy/clippy_lints/src/types/option_option.rs index b2692c4807..903e62995c 100644 --- a/src/tools/clippy/clippy_lints/src/types/option_option.rs +++ b/src/tools/clippy/clippy_lints/src/types/option_option.rs @@ -7,9 +7,7 @@ use rustc_span::symbol::sym; use super::OPTION_OPTION; pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_>, def_id: DefId) -> bool { - if cx.tcx.is_diagnostic_item(sym::option_type, def_id) - && is_ty_param_diagnostic_item(cx, qpath, sym::option_type).is_some() - { + if cx.tcx.is_diagnostic_item(sym::Option, def_id) && is_ty_param_diagnostic_item(cx, qpath, sym::Option).is_some() { span_lint( cx, OPTION_OPTION, diff --git a/src/tools/clippy/clippy_lints/src/types/rc_buffer.rs b/src/tools/clippy/clippy_lints/src/types/rc_buffer.rs index ef629a35d1..31c4abdfc9 100644 --- a/src/tools/clippy/clippy_lints/src/types/rc_buffer.rs +++ b/src/tools/clippy/clippy_lints/src/types/rc_buffer.rs @@ -20,7 +20,7 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_ format!("Rc<{}>", alternate), Applicability::MachineApplicable, ); - } else if let Some(ty) = is_ty_param_diagnostic_item(cx, qpath, sym::vec_type) { + } else if let Some(ty) = is_ty_param_diagnostic_item(cx, qpath, sym::Vec) { let qpath = match &ty.kind { TyKind::Path(qpath) => qpath, _ => return false, @@ -55,7 +55,7 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_ format!("Arc<{}>", alternate), Applicability::MachineApplicable, ); - } else if let Some(ty) = is_ty_param_diagnostic_item(cx, qpath, sym::vec_type) { + } else if let Some(ty) = is_ty_param_diagnostic_item(cx, qpath, sym::Vec) { let qpath = match &ty.kind { TyKind::Path(qpath) => qpath, _ => return false, @@ -85,7 +85,7 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_ } fn match_buffer_type(cx: &LateContext<'_>, qpath: &QPath<'_>) -> Option<&'static str> { - if is_ty_param_diagnostic_item(cx, qpath, sym::string_type).is_some() { + if is_ty_param_diagnostic_item(cx, qpath, sym::String).is_some() { Some("str") } else if is_ty_param_diagnostic_item(cx, qpath, sym::OsString).is_some() { Some("std::ffi::OsStr") diff --git a/src/tools/clippy/clippy_lints/src/types/rc_mutex.rs b/src/tools/clippy/clippy_lints/src/types/rc_mutex.rs index bd7a0ee640..d54608a07b 100644 --- a/src/tools/clippy/clippy_lints/src/types/rc_mutex.rs +++ b/src/tools/clippy/clippy_lints/src/types/rc_mutex.rs @@ -1,4 +1,4 @@ -use clippy_utils::diagnostics::span_lint; +use clippy_utils::diagnostics::span_lint_and_help; use clippy_utils::is_ty_param_diagnostic_item; use if_chain::if_chain; use rustc_hir::{self as hir, def_id::DefId, QPath}; @@ -10,14 +10,15 @@ use super::RC_MUTEX; pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_>, def_id: DefId) -> bool { if_chain! { if cx.tcx.is_diagnostic_item(sym::Rc, def_id) ; - if let Some(_) = is_ty_param_diagnostic_item(cx, qpath, sym!(mutex_type)) ; - - then{ - span_lint( + if let Some(_) = is_ty_param_diagnostic_item(cx, qpath, sym::Mutex) ; + then { + span_lint_and_help( cx, RC_MUTEX, hir_ty.span, - "found `Rc>`. Consider using `Rc>` or `Arc>` instead", + "usage of `Rc>`", + None, + "consider using `Rc>` or `Arc>` instead", ); return true; } diff --git a/src/tools/clippy/clippy_lints/src/types/redundant_allocation.rs b/src/tools/clippy/clippy_lints/src/types/redundant_allocation.rs index 8e83dcbf70..ac7bdd6a1e 100644 --- a/src/tools/clippy/clippy_lints/src/types/redundant_allocation.rs +++ b/src/tools/clippy/clippy_lints/src/types/redundant_allocation.rs @@ -54,7 +54,13 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_ _ => return false, }; let inner_span = match get_qpath_generic_tys(inner_qpath).next() { - Some(ty) => ty.span, + Some(ty) => { + // Box> is smaller than Box because of wide pointers + if matches!(ty.kind, TyKind::TraitObject(..)) { + return false; + } + ty.span + }, None => return false, }; if inner_sym == outer_sym { diff --git a/src/tools/clippy/clippy_lints/src/types/vec_box.rs b/src/tools/clippy/clippy_lints/src/types/vec_box.rs index 7a44417462..c632f82254 100644 --- a/src/tools/clippy/clippy_lints/src/types/vec_box.rs +++ b/src/tools/clippy/clippy_lints/src/types/vec_box.rs @@ -5,9 +5,9 @@ use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::{self as hir, def_id::DefId, GenericArg, QPath, TyKind}; use rustc_lint::LateContext; +use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::TypeFoldable; use rustc_span::symbol::sym; -use rustc_target::abi::LayoutOf; use rustc_typeck::hir_ty_to_ty; use super::VEC_BOX; @@ -19,7 +19,7 @@ pub(super) fn check( def_id: DefId, box_size_threshold: u64, ) -> bool { - if cx.tcx.is_diagnostic_item(sym::vec_type, def_id) { + if cx.tcx.is_diagnostic_item(sym::Vec, def_id) { if_chain! { // Get the _ part of Vec<_> if let Some(last) = last_path_segment(qpath).args; diff --git a/src/tools/clippy/clippy_lints/src/undropped_manually_drops.rs b/src/tools/clippy/clippy_lints/src/undropped_manually_drops.rs index 47571e608c..0957061659 100644 --- a/src/tools/clippy/clippy_lints/src/undropped_manually_drops.rs +++ b/src/tools/clippy/clippy_lints/src/undropped_manually_drops.rs @@ -37,8 +37,8 @@ declare_lint_pass!(UndroppedManuallyDrops => [UNDROPPED_MANUALLY_DROPS]); impl LateLintPass<'tcx> for UndroppedManuallyDrops { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { - if let Some(args) = match_function_call(cx, expr, &paths::DROP) { - let ty = cx.typeck_results().expr_ty(&args[0]); + if let Some([arg_0, ..]) = match_function_call(cx, expr, &paths::DROP) { + let ty = cx.typeck_results().expr_ty(arg_0); if is_type_lang_item(cx, ty, lang_items::LangItem::ManuallyDrop) { span_lint_and_help( cx, 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 97b1b2dae3..dd74bf367f 100644 --- a/src/tools/clippy/clippy_lints/src/unnecessary_sort_by.rs +++ b/src/tools/clippy/clippy_lints/src/unnecessary_sort_by.rs @@ -168,7 +168,7 @@ fn detect_lint(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option { if let name = name_ident.ident.name.to_ident_string(); if name == "sort_by" || name == "sort_unstable_by"; if let [vec, Expr { kind: ExprKind::Closure(_, _, closure_body_id, _, _), .. }] = args; - if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(vec), sym::vec_type); + if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(vec), sym::Vec); if let closure_body = cx.tcx.hir().body(*closure_body_id); if let &[ Param { pat: Pat { kind: PatKind::Binding(_, _, left_ident, _), .. }, ..}, @@ -218,7 +218,10 @@ fn detect_lint(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option { fn expr_borrows(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { let ty = cx.typeck_results().expr_ty(expr); - matches!(ty.kind(), ty::Ref(..)) || ty.walk(cx.tcx).any(|arg| matches!(arg.unpack(), GenericArgKind::Lifetime(_))) + matches!(ty.kind(), ty::Ref(..)) + || ty + .walk(cx.tcx) + .any(|arg| matches!(arg.unpack(), GenericArgKind::Lifetime(_))) } impl LateLintPass<'_> for UnnecessarySortBy { diff --git a/src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs b/src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs index 5ca861a14b..c940cf077d 100644 --- a/src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs +++ b/src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs @@ -101,9 +101,9 @@ impl<'tcx> LateLintPass<'tcx> for UnnecessaryWraps { // Get the wrapper and inner types, if can't, abort. let (return_type_label, lang_item, inner_type) = if let ty::Adt(adt_def, subst) = return_ty(cx, hir_id).kind() { - if cx.tcx.is_diagnostic_item(sym::option_type, adt_def.did) { + if cx.tcx.is_diagnostic_item(sym::Option, adt_def.did) { ("Option", OptionSome, subst.type_at(0)) - } else if cx.tcx.is_diagnostic_item(sym::result_type, adt_def.did) { + } else if cx.tcx.is_diagnostic_item(sym::Result, adt_def.did) { ("Result", ResultOk, subst.type_at(0)) } else { return; diff --git a/src/tools/clippy/clippy_lints/src/unused_async.rs b/src/tools/clippy/clippy_lints/src/unused_async.rs index 3a6a07c522..f4808682b6 100644 --- a/src/tools/clippy/clippy_lints/src/unused_async.rs +++ b/src/tools/clippy/clippy_lints/src/unused_async.rs @@ -1,6 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_help; use rustc_hir::intravisit::{walk_expr, walk_fn, FnKind, NestedVisitorMap, Visitor}; -use rustc_hir::{Body, Expr, ExprKind, FnDecl, FnHeader, HirId, IsAsync, Item, ItemKind, YieldSource}; +use rustc_hir::{Body, Expr, ExprKind, FnDecl, FnHeader, HirId, IsAsync, YieldSource}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::hir::map::Map; use rustc_session::{declare_lint_pass, declare_tool_lint}; @@ -57,11 +57,6 @@ impl<'a, 'tcx> Visitor<'tcx> for AsyncFnVisitor<'a, 'tcx> { } impl<'tcx> LateLintPass<'tcx> for UnusedAsync { - fn check_item(&mut self, _: &LateContext<'tcx>, item: &'tcx Item<'tcx>) { - if let ItemKind::Trait(..) = item.kind { - return; - } - } fn check_fn( &mut self, cx: &LateContext<'tcx>, diff --git a/src/tools/clippy/clippy_lints/src/unused_io_amount.rs b/src/tools/clippy/clippy_lints/src/unused_io_amount.rs index 82bc4a6d15..031b182bd2 100644 --- a/src/tools/clippy/clippy_lints/src/unused_io_amount.rs +++ b/src/tools/clippy/clippy_lints/src/unused_io_amount.rs @@ -45,20 +45,20 @@ impl<'tcx> LateLintPass<'tcx> for UnusedIoAmount { match expr.kind { hir::ExprKind::Match(res, _, _) if is_try(cx, expr).is_some() => { - if let hir::ExprKind::Call(func, args) = res.kind { + if let hir::ExprKind::Call(func, [ref arg_0, ..]) = res.kind { if matches!( func.kind, hir::ExprKind::Path(hir::QPath::LangItem(hir::LangItem::TryTraitBranch, _)) ) { - check_map_error(cx, &args[0], expr); + check_map_error(cx, arg_0, expr); } } else { check_map_error(cx, res, expr); } }, - hir::ExprKind::MethodCall(path, _, args, _) => match &*path.ident.as_str() { + hir::ExprKind::MethodCall(path, _, [ref arg_0, ..], _) => match &*path.ident.as_str() { "expect" | "unwrap" | "unwrap_or" | "unwrap_or_else" => { - check_map_error(cx, &args[0], expr); + check_map_error(cx, arg_0, expr); }, _ => (), }, diff --git a/src/tools/clippy/clippy_lints/src/unused_self.rs b/src/tools/clippy/clippy_lints/src/unused_self.rs index 658ac81f6e..e7e249c79a 100644 --- a/src/tools/clippy/clippy_lints/src/unused_self.rs +++ b/src/tools/clippy/clippy_lints/src/unused_self.rs @@ -1,5 +1,5 @@ use clippy_utils::diagnostics::span_lint_and_help; -use clippy_utils::visitors::LocalUsedVisitor; +use clippy_utils::visitors::is_local_used; use if_chain::if_chain; use rustc_hir::{Impl, ImplItem, ImplItemKind, ItemKind}; use rustc_lint::{LateContext, LateLintPass}; @@ -50,8 +50,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedSelf { if let ImplItemKind::Fn(.., body_id) = &impl_item.kind; let body = cx.tcx.hir().body(*body_id); if let [self_param, ..] = body.params; - let self_hir_id = self_param.pat.hir_id; - if !LocalUsedVisitor::new(cx, self_hir_id).check_body(body); + if !is_local_used(cx, body, self_param.pat.hir_id); then { span_lint_and_help( cx, diff --git a/src/tools/clippy/clippy_lints/src/unwrap.rs b/src/tools/clippy/clippy_lints/src/unwrap.rs index bffd9f3612..ebaa9dcbbf 100644 --- a/src/tools/clippy/clippy_lints/src/unwrap.rs +++ b/src/tools/clippy/clippy_lints/src/unwrap.rs @@ -1,10 +1,11 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::higher; use clippy_utils::ty::is_type_diagnostic_item; -use clippy_utils::{differing_macro_contexts, usage::is_potentially_mutated}; +use clippy_utils::{differing_macro_contexts, path_to_local, usage::is_potentially_mutated}; use if_chain::if_chain; +use rustc_errors::Applicability; use rustc_hir::intravisit::{walk_expr, walk_fn, FnKind, NestedVisitorMap, Visitor}; -use rustc_hir::{BinOpKind, Body, Expr, ExprKind, FnDecl, HirId, Path, QPath, UnOp}; +use rustc_hir::{BinOpKind, Body, Expr, ExprKind, FnDecl, HirId, PathSegment, UnOp}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::hir::map::Map; use rustc_middle::lint::in_external_macro; @@ -74,50 +75,85 @@ struct UnwrappableVariablesVisitor<'a, 'tcx> { unwrappables: Vec>, cx: &'a LateContext<'tcx>, } + +/// What kind of unwrappable this is. +#[derive(Copy, Clone, Debug)] +enum UnwrappableKind { + Option, + Result, +} + +impl UnwrappableKind { + fn success_variant_pattern(self) -> &'static str { + match self { + UnwrappableKind::Option => "Some(..)", + UnwrappableKind::Result => "Ok(..)", + } + } + + fn error_variant_pattern(self) -> &'static str { + match self { + UnwrappableKind::Option => "None", + UnwrappableKind::Result => "Err(..)", + } + } +} + /// Contains information about whether a variable can be unwrapped. #[derive(Copy, Clone, Debug)] struct UnwrapInfo<'tcx> { /// The variable that is checked - ident: &'tcx Path<'tcx>, + local_id: HirId, + /// The if itself + if_expr: &'tcx Expr<'tcx>, /// The check, like `x.is_ok()` check: &'tcx Expr<'tcx>, + /// The check's name, like `is_ok` + check_name: &'tcx PathSegment<'tcx>, /// The branch where the check takes place, like `if x.is_ok() { .. }` branch: &'tcx Expr<'tcx>, /// Whether `is_some()` or `is_ok()` was called (as opposed to `is_err()` or `is_none()`). safe_to_unwrap: bool, + /// What kind of unwrappable this is. + kind: UnwrappableKind, + /// If the check is the entire condition (`if x.is_ok()`) or only a part of it (`foo() && + /// x.is_ok()`) + is_entire_condition: bool, } /// Collects the information about unwrappable variables from an if condition /// The `invert` argument tells us whether the condition is negated. fn collect_unwrap_info<'tcx>( cx: &LateContext<'tcx>, + if_expr: &'tcx Expr<'_>, expr: &'tcx Expr<'_>, branch: &'tcx Expr<'_>, invert: bool, + is_entire_condition: bool, ) -> Vec> { fn is_relevant_option_call(cx: &LateContext<'_>, ty: Ty<'_>, method_name: &str) -> bool { - is_type_diagnostic_item(cx, ty, sym::option_type) && ["is_some", "is_none"].contains(&method_name) + is_type_diagnostic_item(cx, ty, sym::Option) && ["is_some", "is_none"].contains(&method_name) } fn is_relevant_result_call(cx: &LateContext<'_>, ty: Ty<'_>, method_name: &str) -> bool { - is_type_diagnostic_item(cx, ty, sym::result_type) && ["is_ok", "is_err"].contains(&method_name) + is_type_diagnostic_item(cx, ty, sym::Result) && ["is_ok", "is_err"].contains(&method_name) } if let ExprKind::Binary(op, left, right) = &expr.kind { match (invert, op.node) { (false, BinOpKind::And | BinOpKind::BitAnd) | (true, BinOpKind::Or | BinOpKind::BitOr) => { - let mut unwrap_info = collect_unwrap_info(cx, left, branch, invert); - unwrap_info.append(&mut collect_unwrap_info(cx, right, branch, invert)); + let mut unwrap_info = collect_unwrap_info(cx, if_expr, left, branch, invert, false); + unwrap_info.append(&mut collect_unwrap_info(cx, if_expr, right, branch, invert, false)); return unwrap_info; }, _ => (), } } else if let ExprKind::Unary(UnOp::Not, expr) = &expr.kind { - return collect_unwrap_info(cx, expr, branch, !invert); + return collect_unwrap_info(cx, if_expr, expr, branch, !invert, false); } else { if_chain! { if let ExprKind::MethodCall(method_name, _, args, _) = &expr.kind; - if let ExprKind::Path(QPath::Resolved(None, path)) = &args[0].kind; + if let Some(local_id) = path_to_local(&args[0]); let ty = cx.typeck_results().expr_ty(&args[0]); let name = method_name.ident.as_str(); if is_relevant_option_call(cx, ty, &name) || is_relevant_result_call(cx, ty, &name); @@ -129,7 +165,24 @@ fn collect_unwrap_info<'tcx>( _ => unreachable!(), }; let safe_to_unwrap = unwrappable != invert; - return vec![UnwrapInfo { ident: path, check: expr, branch, safe_to_unwrap }]; + let kind = if is_type_diagnostic_item(cx, ty, sym::Option) { + UnwrappableKind::Option + } else { + UnwrappableKind::Result + }; + + return vec![ + UnwrapInfo { + local_id, + if_expr, + check: expr, + check_name: method_name, + branch, + safe_to_unwrap, + kind, + is_entire_condition, + } + ] } } } @@ -137,11 +190,17 @@ fn collect_unwrap_info<'tcx>( } impl<'a, 'tcx> UnwrappableVariablesVisitor<'a, 'tcx> { - fn visit_branch(&mut self, cond: &'tcx Expr<'_>, branch: &'tcx Expr<'_>, else_branch: bool) { + fn visit_branch( + &mut self, + if_expr: &'tcx Expr<'_>, + cond: &'tcx Expr<'_>, + branch: &'tcx Expr<'_>, + else_branch: bool, + ) { let prev_len = self.unwrappables.len(); - for unwrap_info in collect_unwrap_info(self.cx, cond, branch, else_branch) { - if is_potentially_mutated(unwrap_info.ident, cond, self.cx) - || is_potentially_mutated(unwrap_info.ident, branch, self.cx) + for unwrap_info in collect_unwrap_info(self.cx, if_expr, cond, branch, else_branch, true) { + if is_potentially_mutated(unwrap_info.local_id, cond, self.cx) + || is_potentially_mutated(unwrap_info.local_id, branch, self.cx) { // if the variable is mutated, we don't know whether it can be unwrapped: continue; @@ -163,32 +222,62 @@ impl<'a, 'tcx> Visitor<'tcx> for UnwrappableVariablesVisitor<'a, 'tcx> { } if let Some(higher::If { cond, then, r#else }) = higher::If::hir(expr) { walk_expr(self, cond); - self.visit_branch(cond, then, false); + self.visit_branch(expr, cond, then, false); if let Some(else_inner) = r#else { - self.visit_branch(cond, else_inner, true); + self.visit_branch(expr, cond, else_inner, true); } } else { // find `unwrap[_err]()` calls: if_chain! { if let ExprKind::MethodCall(method_name, _, args, _) = expr.kind; - if let ExprKind::Path(QPath::Resolved(None, path)) = args[0].kind; - if [sym::unwrap, sym!(unwrap_err)].contains(&method_name.ident.name); - let call_to_unwrap = method_name.ident.name == sym::unwrap; + if let Some(id) = path_to_local(&args[0]); + if [sym::unwrap, sym::expect, sym!(unwrap_err)].contains(&method_name.ident.name); + let call_to_unwrap = [sym::unwrap, sym::expect].contains(&method_name.ident.name); if let Some(unwrappable) = self.unwrappables.iter() - .find(|u| u.ident.res == path.res); + .find(|u| u.local_id == id); // Span contexts should not differ with the conditional branch if !differing_macro_contexts(unwrappable.branch.span, expr.span); if !differing_macro_contexts(unwrappable.branch.span, unwrappable.check.span); then { if call_to_unwrap == unwrappable.safe_to_unwrap { + let is_entire_condition = unwrappable.is_entire_condition; + let unwrappable_variable_name = self.cx.tcx.hir().name(unwrappable.local_id); + let suggested_pattern = if call_to_unwrap { + unwrappable.kind.success_variant_pattern() + } else { + unwrappable.kind.error_variant_pattern() + }; + span_lint_and_then( self.cx, UNNECESSARY_UNWRAP, expr.span, - &format!("you checked before that `{}()` cannot fail, \ - instead of checking and unwrapping, it's better to use `if let` or `match`", - method_name.ident.name), - |diag| { diag.span_label(unwrappable.check.span, "the check is happening here"); }, + &format!( + "called `{}` on `{}` after checking its variant with `{}`", + method_name.ident.name, + unwrappable_variable_name, + unwrappable.check_name.ident.as_str(), + ), + |diag| { + if is_entire_condition { + diag.span_suggestion( + unwrappable.check.span.with_lo(unwrappable.if_expr.span.lo()), + "try", + format!( + "if let {} = {}", + suggested_pattern, + unwrappable_variable_name, + ), + // We don't track how the unwrapped value is used inside the + // block or suggest deleting the unwrap, so we can't offer a + // fixable solution. + Applicability::Unspecified, + ); + } else { + diag.span_label(unwrappable.check.span, "the check is happening here"); + diag.help("try using `if let` or `match`"); + } + }, ); } else { span_lint_and_then( 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 6eadd1fc1c..a4680ae137 100644 --- a/src/tools/clippy/clippy_lints/src/unwrap_in_result.rs +++ b/src/tools/clippy/clippy_lints/src/unwrap_in_result.rs @@ -64,8 +64,8 @@ impl<'tcx> LateLintPass<'tcx> for UnwrapInResult { // first check if it's a method or function if let hir::ImplItemKind::Fn(ref _signature, _) = impl_item.kind; // checking if its return type is `result` or `option` - if is_type_diagnostic_item(cx, return_ty(cx, impl_item.hir_id()), sym::result_type) - || is_type_diagnostic_item(cx, return_ty(cx, impl_item.hir_id()), sym::option_type); + if is_type_diagnostic_item(cx, return_ty(cx, impl_item.hir_id()), sym::Result) + || is_type_diagnostic_item(cx, return_ty(cx, impl_item.hir_id()), sym::Option); then { lint_impl_body(cx, impl_item.span, impl_item); } @@ -86,8 +86,8 @@ impl<'a, 'tcx> Visitor<'tcx> for FindExpectUnwrap<'a, 'tcx> { // check for `expect` if let Some(arglists) = method_chain_args(expr, &["expect"]) { let reciever_ty = self.typeck_results.expr_ty(&arglists[0][0]).peel_refs(); - if is_type_diagnostic_item(self.lcx, reciever_ty, sym::option_type) - || is_type_diagnostic_item(self.lcx, reciever_ty, sym::result_type) + if is_type_diagnostic_item(self.lcx, reciever_ty, sym::Option) + || is_type_diagnostic_item(self.lcx, reciever_ty, sym::Result) { self.result.push(expr.span); } @@ -96,8 +96,8 @@ impl<'a, 'tcx> Visitor<'tcx> for FindExpectUnwrap<'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.lcx, reciever_ty, sym::option_type) - || is_type_diagnostic_item(self.lcx, reciever_ty, sym::result_type) + if is_type_diagnostic_item(self.lcx, reciever_ty, sym::Option) + || is_type_diagnostic_item(self.lcx, reciever_ty, sym::Result) { self.result.push(expr.span); } diff --git a/src/tools/clippy/clippy_lints/src/useless_conversion.rs b/src/tools/clippy/clippy_lints/src/useless_conversion.rs index 2861b43291..88f1154207 100644 --- a/src/tools/clippy/clippy_lints/src/useless_conversion.rs +++ b/src/tools/clippy/clippy_lints/src/useless_conversion.rs @@ -63,7 +63,7 @@ impl<'tcx> LateLintPass<'tcx> for UselessConversion { }, ExprKind::MethodCall(name, .., args, _) => { - if is_trait_method(cx, e, sym::into_trait) && &*name.ident.as_str() == "into" { + if is_trait_method(cx, e, sym::Into) && &*name.ident.as_str() == "into" { let a = cx.typeck_results().expr_ty(e); let b = cx.typeck_results().expr_ty(&args[0]); if same_type_and_consts(a, b) { @@ -103,10 +103,10 @@ impl<'tcx> LateLintPass<'tcx> for UselessConversion { } } if_chain! { - if is_trait_method(cx, e, sym::try_into_trait) && name.ident.name == sym::try_into; + if is_trait_method(cx, e, sym::TryInto) && name.ident.name == sym::try_into; let a = cx.typeck_results().expr_ty(e); let b = cx.typeck_results().expr_ty(&args[0]); - if is_type_diagnostic_item(cx, a, sym::result_type); + if is_type_diagnostic_item(cx, a, sym::Result); if let ty::Adt(_, substs) = a.kind(); if let Some(a_type) = substs.types().next(); if same_type_and_consts(a_type, b); @@ -134,7 +134,7 @@ impl<'tcx> LateLintPass<'tcx> for UselessConversion { let b = cx.typeck_results().expr_ty(&args[0]); if_chain! { if match_def_path(cx, def_id, &paths::TRY_FROM); - if is_type_diagnostic_item(cx, a, sym::result_type); + if is_type_diagnostic_item(cx, a, sym::Result); if let ty::Adt(_, substs) = a.kind(); if let Some(a_type) = substs.types().next(); if same_type_and_consts(a_type, b); diff --git a/src/tools/clippy/clippy_lints/src/utils/conf.rs b/src/tools/clippy/clippy_lints/src/utils/conf.rs index c192f9094a..6cbada4c15 100644 --- a/src/tools/clippy/clippy_lints/src/utils/conf.rs +++ b/src/tools/clippy/clippy_lints/src/utils/conf.rs @@ -15,6 +15,14 @@ pub struct Rename { pub rename: String, } +/// A single disallowed method, used by the `DISALLOWED_METHOD` lint. +#[derive(Clone, Debug, Deserialize)] +#[serde(untagged)] +pub enum DisallowedMethod { + Simple(String), + WithReason { path: String, reason: Option }, +} + /// Conf with parse errors #[derive(Default)] pub struct TryConf { @@ -31,9 +39,6 @@ impl TryConf { } } -/// Note that the configuration parsing currently doesn't support documentation that will -/// that spans over several lines. This will be possible with the new implementation -/// See (rust-clippy#7172) macro_rules! define_Conf { ($( $(#[doc = $doc:literal])+ @@ -130,13 +135,12 @@ macro_rules! define_Conf { }; } -// N.B., this macro is parsed by util/lintlib.py define_Conf! { - /// Lint: ENUM_VARIANT_NAMES, LARGE_TYPES_PASSED_BY_VALUE, TRIVIALLY_COPY_PASS_BY_REF, UNNECESSARY_WRAPS, UPPER_CASE_ACRONYMS, WRONG_SELF_CONVENTION. + /// Lint: ENUM_VARIANT_NAMES, LARGE_TYPES_PASSED_BY_VALUE, TRIVIALLY_COPY_PASS_BY_REF, UNNECESSARY_WRAPS, UPPER_CASE_ACRONYMS, WRONG_SELF_CONVENTION, BOX_COLLECTION, REDUNDANT_ALLOCATION, RC_BUFFER, VEC_BOX, OPTION_OPTION, LINKEDLIST, RC_MUTEX. /// /// Suppress lints whenever the suggested change would cause breakage for other crates. (avoid_breaking_exported_api: bool = true), - /// Lint: MANUAL_STR_REPEAT, CLONED_INSTEAD_OF_COPIED, REDUNDANT_FIELD_NAMES, REDUNDANT_STATIC_LIFETIMES, FILTER_MAP_NEXT, CHECKED_CONVERSIONS, MANUAL_RANGE_CONTAINS, USE_SELF, MEM_REPLACE_WITH_DEFAULT, MANUAL_NON_EXHAUSTIVE, OPTION_AS_REF_DEREF, MAP_UNWRAP_OR, MATCH_LIKE_MATCHES_MACRO, MANUAL_STRIP, MISSING_CONST_FOR_FN, UNNESTED_OR_PATTERNS, FROM_OVER_INTO, PTR_AS_PTR, IF_THEN_SOME_ELSE_NONE. + /// Lint: MANUAL_SPLIT_ONCE, MANUAL_STR_REPEAT, CLONED_INSTEAD_OF_COPIED, REDUNDANT_FIELD_NAMES, REDUNDANT_STATIC_LIFETIMES, FILTER_MAP_NEXT, CHECKED_CONVERSIONS, MANUAL_RANGE_CONTAINS, USE_SELF, MEM_REPLACE_WITH_DEFAULT, MANUAL_NON_EXHAUSTIVE, OPTION_AS_REF_DEREF, MAP_UNWRAP_OR, MATCH_LIKE_MATCHES_MACRO, MANUAL_STRIP, MISSING_CONST_FOR_FN, UNNESTED_OR_PATTERNS, FROM_OVER_INTO, PTR_AS_PTR, IF_THEN_SOME_ELSE_NONE, APPROX_CONSTANT. /// /// The minimum rust version that the project supports (msrv: Option = None), @@ -247,7 +251,7 @@ define_Conf! { /// Lint: DISALLOWED_METHOD. /// /// The list of disallowed methods, written as fully qualified paths. - (disallowed_methods: Vec = Vec::new()), + (disallowed_methods: Vec = Vec::new()), /// Lint: DISALLOWED_TYPE. /// /// The list of disallowed types, written as fully qualified paths. @@ -280,6 +284,10 @@ define_Conf! { /// /// The list of unicode scripts allowed to be used in the scope. (allowed_scripts: Vec = vec!["Latin".to_string()]), + /// Lint: NON_SEND_FIELDS_IN_SEND_TY. + /// + /// Whether to apply the raw pointer heuristic to determine if a type is `Send`. + (enable_raw_pointer_heuristic_for_send: bool = true), } /// Search for the configuration file. diff --git a/src/tools/clippy/clippy_lints/src/utils/inspector.rs b/src/tools/clippy/clippy_lints/src/utils/inspector.rs index e97983a2e1..43590cc786 100644 --- a/src/tools/clippy/clippy_lints/src/utils/inspector.rs +++ b/src/tools/clippy/clippy_lints/src/utils/inspector.rs @@ -142,7 +142,7 @@ fn print_expr(cx: &LateContext<'_>, expr: &hir::Expr<'_>, indent: usize) { print_expr(cx, arg, indent + 1); } }, - hir::ExprKind::Let(ref pat, ref expr, _) => { + hir::ExprKind::Let(pat, expr, _) => { print_pat(cx, pat, indent + 1); print_expr(cx, expr, indent + 1); }, 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 d660008e7d..9f9edbf258 100644 --- a/src/tools/clippy/clippy_lints/src/utils/internal_lints.rs +++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints.rs @@ -1,5 +1,6 @@ use clippy_utils::consts::{constant_simple, Constant}; use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_and_sugg, span_lint_and_then}; +use clippy_utils::higher; use clippy_utils::source::snippet; use clippy_utils::ty::match_type; use clippy_utils::{ @@ -7,7 +8,7 @@ use clippy_utils::{ paths, SpanlessEq, }; use if_chain::if_chain; -use rustc_ast::ast::{Crate as AstCrate, ItemKind, LitKind, ModKind, NodeId}; +use rustc_ast::ast::{Crate, ItemKind, LitKind, ModKind, NodeId}; use rustc_ast::visit::FnKind; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::Applicability; @@ -17,8 +18,8 @@ use rustc_hir::def_id::DefId; use rustc_hir::hir_id::CRATE_HIR_ID; use rustc_hir::intravisit::{NestedVisitorMap, Visitor}; use rustc_hir::{ - BinOpKind, Block, Crate, Expr, ExprKind, HirId, Item, Local, MatchSource, MutTy, Mutability, Node, Path, Stmt, - StmtKind, Ty, TyKind, UnOp, + BinOpKind, Block, Expr, ExprKind, HirId, Item, Local, MutTy, Mutability, Node, Path, Stmt, StmtKind, Ty, TyKind, + UnOp, }; use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext}; use rustc_middle::hir::map::Map; @@ -241,7 +242,7 @@ declare_clippy_lint! { /// /// Good: /// ```rust,ignore - /// utils::is_type_diagnostic_item(cx, ty, sym::vec_type) + /// utils::is_type_diagnostic_item(cx, ty, sym::Vec) /// ``` pub MATCH_TYPE_ON_DIAGNOSTIC_ITEM, internal, @@ -316,7 +317,7 @@ declare_clippy_lint! { declare_lint_pass!(ClippyLintsInternal => [CLIPPY_LINTS_INTERNAL]); impl EarlyLintPass for ClippyLintsInternal { - fn check_crate(&mut self, cx: &EarlyContext<'_>, krate: &AstCrate) { + fn check_crate(&mut self, cx: &EarlyContext<'_>, krate: &Crate) { if let Some(utils) = krate.items.iter().find(|item| item.ident.name.as_str() == "utils") { if let ItemKind::Mod(_, ModKind::Loaded(ref items, ..)) = utils.kind { if let Some(paths) = items.iter().find(|item| item.ident.name.as_str() == "paths") { @@ -411,7 +412,7 @@ impl<'tcx> LateLintPass<'tcx> for LintWithoutLintPass { } } - fn check_crate_post(&mut self, cx: &LateContext<'tcx>, _: &'tcx Crate<'_>) { + fn check_crate_post(&mut self, cx: &LateContext<'tcx>) { if is_lint_allowed(cx, LINT_WITHOUT_LINT_PASS, CRATE_HIR_ID) { return; } @@ -503,10 +504,10 @@ impl<'tcx> LateLintPass<'tcx> for CompilerLintFunctions { } if_chain! { - if let ExprKind::MethodCall(path, _, args, _) = expr.kind; + if let ExprKind::MethodCall(path, _, [self_arg, ..], _) = &expr.kind; let fn_name = path.ident; if let Some(sugg) = self.map.get(&*fn_name.as_str()); - let ty = cx.typeck_results().expr_ty(&args[0]).peel_refs(); + let ty = cx.typeck_results().expr_ty(self_arg).peel_refs(); if match_type(cx, ty, &paths::EARLY_CONTEXT) || match_type(cx, ty, &paths::LATE_CONTEXT); then { @@ -560,9 +561,7 @@ declare_lint_pass!(ProduceIce => [PRODUCE_ICE]); impl EarlyLintPass for ProduceIce { fn check_fn(&mut self, _: &EarlyContext<'_>, fn_kind: FnKind<'_>, _: Span, _: NodeId) { - if is_trigger_fn(fn_kind) { - panic!("Would you like some help with that?"); - } + assert!(!is_trigger_fn(fn_kind), "Would you like some help with that?"); } } @@ -893,7 +892,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidPaths { }).collect(); if !check_path(cx, &path[..]); then { - span_lint(cx, CLIPPY_LINTS_INTERNAL, item.span, "invalid path"); + span_lint(cx, INVALID_PATHS, item.span, "invalid path"); } } } @@ -908,7 +907,7 @@ pub struct InterningDefinedSymbol { impl_lint_pass!(InterningDefinedSymbol => [INTERNING_DEFINED_SYMBOL, UNNECESSARY_SYMBOL_STR]); impl<'tcx> LateLintPass<'tcx> for InterningDefinedSymbol { - fn check_crate(&mut self, cx: &LateContext<'_>, _: &Crate<'_>) { + fn check_crate(&mut self, cx: &LateContext<'_>) { if !self.symbol_map.is_empty() { return; } @@ -1106,16 +1105,10 @@ impl<'tcx> LateLintPass<'tcx> for IfChainStyle { } fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) { - let (cond, then, els) = match expr.kind { - ExprKind::If(cond, then, els) => (Some(cond), then, els.is_some()), - ExprKind::Match( - _, - [arm, ..], - MatchSource::IfLetDesugar { - contains_else_clause: els, - }, - ) => (None, arm.body, els), - _ => return, + let (cond, then, els) = if let Some(higher::IfOrIfLet { cond, r#else, then }) = higher::IfOrIfLet::hir(expr) { + (cond, then, r#else.is_some()) + } else { + return; }; let then_block = match then.kind { ExprKind::Block(block, _) => block, @@ -1131,7 +1124,6 @@ impl<'tcx> LateLintPass<'tcx> for IfChainStyle { }; // check for `if a && b;` if_chain! { - if let Some(cond) = cond; if let ExprKind::Binary(op, _, _) = cond.kind; if op.node == BinOpKind::And; if cx.sess().source_map().is_multiline(cond.span); @@ -1166,9 +1158,7 @@ fn check_nested_if_chains( _ => return, }; if_chain! { - if matches!(tail.kind, - ExprKind::If(_, _, None) - | ExprKind::Match(.., MatchSource::IfLetDesugar { contains_else_clause: false })); + if let Some(higher::IfOrIfLet { r#else: None, .. }) = higher::IfOrIfLet::hir(tail); let sm = cx.sess().source_map(); if head .iter() @@ -1232,5 +1222,10 @@ fn if_chain_local_span(cx: &LateContext<'_>, local: &Local<'_>, if_chain_span: S let sm = cx.sess().source_map(); let span = sm.span_extend_to_prev_str(span, "let", false); let span = sm.span_extend_to_next_char(span, ';', false); - Span::new(span.lo() - BytePos(3), span.hi() + BytePos(1), span.ctxt()) + Span::new( + span.lo() - BytePos(3), + span.hi() + BytePos(1), + span.ctxt(), + span.parent(), + ) } 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 a48a538508..0d27874b7a 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 @@ -82,7 +82,7 @@ This lint has the following configuration variables: /// `default` macro_rules! CONFIGURATION_VALUE_TEMPLATE { () => { - "* {name}: `{ty}`: {doc} (defaults to `{default}`)\n" + "* `{name}`: `{ty}`: {doc} (defaults to `{default}`)\n" }; } @@ -298,6 +298,7 @@ pub struct ClippyConfiguration { default: String, lints: Vec, doc: String, + #[allow(dead_code)] deprecation_reason: Option<&'static str>, } @@ -786,8 +787,6 @@ impl<'a, 'hir> intravisit::Visitor<'hir> for ApplicabilityResolver<'a, 'hir> { } }; - // TODO xFrednet 2021-03-01: support function arguments? - intravisit::walk_expr(self, expr); } } diff --git a/src/tools/clippy/clippy_lints/src/vec.rs b/src/tools/clippy/clippy_lints/src/vec.rs index 95a45fa937..d124d948b5 100644 --- a/src/tools/clippy/clippy_lints/src/vec.rs +++ b/src/tools/clippy/clippy_lints/src/vec.rs @@ -1,4 +1,3 @@ -use crate::rustc_target::abi::LayoutOf; use clippy_utils::consts::{constant, Constant}; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::higher; @@ -8,6 +7,7 @@ use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::{BorrowKind, Expr, ExprKind, Mutability}; use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::{self, Ty}; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::source_map::Span; @@ -49,7 +49,7 @@ impl<'tcx> LateLintPass<'tcx> for UselessVec { if_chain! { if let ty::Ref(_, ty, _) = cx.typeck_results().expr_ty_adjusted(expr).kind(); if let ty::Slice(..) = ty.kind(); - if let ExprKind::AddrOf(BorrowKind::Ref, mutability, ref addressee) = expr.kind; + if let ExprKind::AddrOf(BorrowKind::Ref, mutability, addressee) = expr.kind; if let Some(vec_args) = higher::VecArgs::hir(cx, addressee); then { self.check_vec_macro(cx, &vec_args, mutability, expr.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 0413c02b23..5b71bb29c1 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 @@ -157,7 +157,7 @@ fn get_vec_init_kind<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> Op 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_type) => + 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); @@ -174,13 +174,13 @@ fn get_vec_init_kind<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> Op } }); } - } + }, 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_type) => + && is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(expr), sym::Vec) => { return Some(VecInitKind::New); - } + }, _ => (), } } diff --git a/src/tools/clippy/clippy_lints/src/wildcard_dependencies.rs b/src/tools/clippy/clippy_lints/src/wildcard_dependencies.rs index fd3872bacb..d0c98b6bd7 100644 --- a/src/tools/clippy/clippy_lints/src/wildcard_dependencies.rs +++ b/src/tools/clippy/clippy_lints/src/wildcard_dependencies.rs @@ -1,5 +1,5 @@ use clippy_utils::{diagnostics::span_lint, is_lint_allowed}; -use rustc_hir::{hir_id::CRATE_HIR_ID, Crate}; +use rustc_hir::hir_id::CRATE_HIR_ID; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::DUMMY_SP; @@ -28,7 +28,7 @@ declare_clippy_lint! { declare_lint_pass!(WildcardDependencies => [WILDCARD_DEPENDENCIES]); impl LateLintPass<'_> for WildcardDependencies { - fn check_crate(&mut self, cx: &LateContext<'_>, _: &Crate<'_>) { + fn check_crate(&mut self, cx: &LateContext<'_>) { if is_lint_allowed(cx, WILDCARD_DEPENDENCIES, CRATE_HIR_ID) { return; } diff --git a/src/tools/clippy/clippy_lints/src/zero_div_zero.rs b/src/tools/clippy/clippy_lints/src/zero_div_zero.rs index b29ced28ac..e0746ce4d8 100644 --- a/src/tools/clippy/clippy_lints/src/zero_div_zero.rs +++ b/src/tools/clippy/clippy_lints/src/zero_div_zero.rs @@ -32,7 +32,7 @@ impl<'tcx> LateLintPass<'tcx> for ZeroDiv { // check for instances of 0.0/0.0 if_chain! { if let ExprKind::Binary(ref op, left, right) = expr.kind; - if let BinOpKind::Div = op.node; + if op.node == BinOpKind::Div; // TODO - constant_simple does not fold many operations involving floats. // That's probably fine for this lint - it's pretty unlikely that someone would // do something like 0.0/(2.0 - 2.0), but it would be nice to warn on that case too. diff --git a/src/tools/clippy/clippy_lints/src/zero_sized_map_values.rs b/src/tools/clippy/clippy_lints/src/zero_sized_map_values.rs index 2fbe27f947..aa6b2614bb 100644 --- a/src/tools/clippy/clippy_lints/src/zero_sized_map_values.rs +++ b/src/tools/clippy/clippy_lints/src/zero_sized_map_values.rs @@ -3,10 +3,10 @@ use clippy_utils::ty::{is_normalizable, is_type_diagnostic_item}; use if_chain::if_chain; use rustc_hir::{self as hir, HirId, ItemKind, Node}; use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::ty::layout::LayoutOf as _; use rustc_middle::ty::{Adt, Ty, TypeFoldable}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::sym; -use rustc_target::abi::LayoutOf as _; use rustc_typeck::hir_ty_to_ty; declare_clippy_lint! { @@ -49,7 +49,7 @@ impl LateLintPass<'_> for ZeroSizedMapValues { if !hir_ty.span.from_expansion(); if !in_trait_impl(cx, hir_ty.hir_id); let ty = ty_from_hir_ty(cx, hir_ty); - if is_type_diagnostic_item(cx, ty, sym::hashmap_type) || is_type_diagnostic_item(cx, ty, sym::BTreeMap); + if is_type_diagnostic_item(cx, ty, sym::HashMap) || is_type_diagnostic_item(cx, ty, sym::BTreeMap); if let Adt(_, substs) = ty.kind(); let ty = substs.type_at(1); // Fixes https://github.com/rust-lang/rust-clippy/issues/7447 because of diff --git a/src/tools/clippy/clippy_utils/Cargo.toml b/src/tools/clippy/clippy_utils/Cargo.toml index c65b2958ec..e7fca3ae5d 100644 --- a/src/tools/clippy/clippy_utils/Cargo.toml +++ b/src/tools/clippy/clippy_utils/Cargo.toml @@ -1,16 +1,12 @@ [package] name = "clippy_utils" -version = "0.1.56" -edition = "2018" +version = "0.1.57" +edition = "2021" publish = false [dependencies] -if_chain = "1.0.0" -itertools = "0.9" -regex-syntax = "0.6" -serde = { version = "1.0", features = ["derive"] } -unicode-normalization = "0.1" -rustc-semver="1.1.0" +if_chain = "1.0" +rustc-semver = "1.1" [features] deny-warnings = [] diff --git a/src/tools/clippy/clippy_utils/src/ast_utils.rs b/src/tools/clippy/clippy_utils/src/ast_utils.rs index 133f6c29f7..2fa98831c7 100644 --- a/src/tools/clippy/clippy_utils/src/ast_utils.rs +++ b/src/tools/clippy/clippy_utils/src/ast_utils.rs @@ -46,15 +46,12 @@ pub fn eq_pat(l: &Pat, r: &Pat) -> bool { | (Ref(l, Mutability::Not), Ref(r, Mutability::Not)) | (Ref(l, Mutability::Mut), Ref(r, Mutability::Mut)) => eq_pat(l, r), (Tuple(l), Tuple(r)) | (Slice(l), Slice(r)) => over(l, r, |l, r| eq_pat(l, r)), - (Path(lq, lp), Path(rq, rp)) => both(lq, rq, |l, r| eq_qself(l, r)) && eq_path(lp, rp), + (Path(lq, lp), Path(rq, rp)) => both(lq, rq, eq_qself) && eq_path(lp, rp), (TupleStruct(lqself, lp, lfs), TupleStruct(rqself, rp, rfs)) => { eq_maybe_qself(lqself, rqself) && eq_path(lp, rp) && over(lfs, rfs, |l, r| eq_pat(l, r)) }, (Struct(lqself, lp, lfs, lr), Struct(rqself, rp, rfs, rr)) => { - lr == rr - && eq_maybe_qself(lqself, rqself) - && eq_path(lp, rp) - && unordered_over(lfs, rfs, |lf, rf| eq_field_pat(lf, rf)) + lr == rr && eq_maybe_qself(lqself, rqself) && eq_path(lp, rp) && unordered_over(lfs, rfs, eq_field_pat) }, (Or(ls), Or(rs)) => unordered_over(ls, rs, |l, r| eq_pat(l, r)), (MacCall(l), MacCall(r)) => eq_mac_call(l, r), @@ -76,7 +73,7 @@ pub fn eq_field_pat(l: &PatField, r: &PatField) -> bool { l.is_placeholder == r.is_placeholder && eq_id(l.ident, r.ident) && eq_pat(&l.pat, &r.pat) - && over(&l.attrs, &r.attrs, |l, r| eq_attr(l, r)) + && over(&l.attrs, &r.attrs, eq_attr) } pub fn eq_qself(l: &QSelf, r: &QSelf) -> bool { @@ -92,7 +89,7 @@ pub fn eq_maybe_qself(l: &Option, r: &Option) -> bool { } pub fn eq_path(l: &Path, r: &Path) -> bool { - over(&l.segments, &r.segments, |l, r| eq_path_seg(l, r)) + over(&l.segments, &r.segments, eq_path_seg) } pub fn eq_path_seg(l: &PathSegment, r: &PathSegment) -> bool { @@ -101,9 +98,7 @@ pub fn eq_path_seg(l: &PathSegment, r: &PathSegment) -> bool { pub fn eq_generic_args(l: &GenericArgs, r: &GenericArgs) -> bool { match (l, r) { - (GenericArgs::AngleBracketed(l), GenericArgs::AngleBracketed(r)) => { - over(&l.args, &r.args, |l, r| eq_angle_arg(l, r)) - }, + (GenericArgs::AngleBracketed(l), GenericArgs::AngleBracketed(r)) => over(&l.args, &r.args, eq_angle_arg), (GenericArgs::Parenthesized(l), GenericArgs::Parenthesized(r)) => { over(&l.inputs, &r.inputs, |l, r| eq_ty(l, r)) && eq_fn_ret_ty(&l.output, &r.output) }, @@ -142,7 +137,7 @@ pub fn eq_struct_rest(l: &StructRest, r: &StructRest) -> bool { pub fn eq_expr(l: &Expr, r: &Expr) -> bool { use ExprKind::*; - if !over(&l.attrs, &r.attrs, |l, r| eq_attr(l, r)) { + if !over(&l.attrs, &r.attrs, eq_attr) { return false; } match (&l.kind, &r.kind) { @@ -173,20 +168,20 @@ pub fn eq_expr(l: &Expr, r: &Expr) -> bool { (Assign(l1, l2, _), Assign(r1, r2, _)) | (Index(l1, l2), Index(r1, r2)) => eq_expr(l1, r1) && eq_expr(l2, r2), (AssignOp(lo, lp, lv), AssignOp(ro, rp, rv)) => lo.node == ro.node && eq_expr(lp, rp) && eq_expr(lv, rv), (Field(lp, lf), Field(rp, rf)) => eq_id(*lf, *rf) && eq_expr(lp, rp), - (Match(ls, la), Match(rs, ra)) => eq_expr(ls, rs) && over(la, ra, |l, r| eq_arm(l, r)), + (Match(ls, la), Match(rs, ra)) => eq_expr(ls, rs) && over(la, ra, eq_arm), (Closure(lc, la, lm, lf, lb, _), Closure(rc, ra, rm, rf, rb, _)) => { lc == rc && la.is_async() == ra.is_async() && lm == rm && eq_fn_decl(lf, rf) && eq_expr(lb, rb) }, (Async(lc, _, lb), Async(rc, _, rb)) => lc == rc && eq_block(lb, rb), (Range(lf, lt, ll), Range(rf, rt, rl)) => ll == rl && eq_expr_opt(lf, rf) && eq_expr_opt(lt, rt), (AddrOf(lbk, lm, le), AddrOf(rbk, rm, re)) => lbk == rbk && lm == rm && eq_expr(le, re), - (Path(lq, lp), Path(rq, rp)) => both(lq, rq, |l, r| eq_qself(l, r)) && eq_path(lp, rp), + (Path(lq, lp), Path(rq, rp)) => both(lq, rq, eq_qself) && eq_path(lp, rp), (MacCall(l), MacCall(r)) => eq_mac_call(l, r), (Struct(lse), Struct(rse)) => { eq_maybe_qself(&lse.qself, &rse.qself) && eq_path(&lse.path, &rse.path) && eq_struct_rest(&lse.rest, &rse.rest) - && unordered_over(&lse.fields, &rse.fields, |l, r| eq_field(l, r)) + && unordered_over(&lse.fields, &rse.fields, eq_field) }, _ => false, } @@ -196,7 +191,7 @@ pub fn eq_field(l: &ExprField, r: &ExprField) -> bool { l.is_placeholder == r.is_placeholder && eq_id(l.ident, r.ident) && eq_expr(&l.expr, &r.expr) - && over(&l.attrs, &r.attrs, |l, r| eq_attr(l, r)) + && over(&l.attrs, &r.attrs, eq_attr) } pub fn eq_arm(l: &Arm, r: &Arm) -> bool { @@ -204,7 +199,7 @@ pub fn eq_arm(l: &Arm, r: &Arm) -> bool { && eq_pat(&l.pat, &r.pat) && eq_expr(&l.body, &r.body) && eq_expr_opt(&l.guard, &r.guard) - && over(&l.attrs, &r.attrs, |l, r| eq_attr(l, r)) + && over(&l.attrs, &r.attrs, eq_attr) } pub fn eq_label(l: &Option